@sublime-ui/library 0.1.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 (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/components/AppBar/AppBar.d.ts +6 -0
  4. package/dist/components/AppBar/AppBar.js +55 -0
  5. package/dist/components/AppBar/AppBar.types.d.ts +11 -0
  6. package/dist/components/AppBar/AppBar.types.js +0 -0
  7. package/dist/components/AppBar/index.d.ts +3 -0
  8. package/dist/components/AppBar/index.js +4 -0
  9. package/dist/components/Avatar/Avatar.d.ts +7 -0
  10. package/dist/components/Avatar/Avatar.js +30 -0
  11. package/dist/components/Avatar/Avatar.types.d.ts +12 -0
  12. package/dist/components/Avatar/Avatar.types.js +0 -0
  13. package/dist/components/Avatar/index.d.ts +4 -0
  14. package/dist/components/Avatar/index.js +4 -0
  15. package/dist/components/Badge/Badge.d.ts +7 -0
  16. package/dist/components/Badge/Badge.js +75 -0
  17. package/dist/components/Badge/Badge.types.d.ts +12 -0
  18. package/dist/components/Badge/Badge.types.js +0 -0
  19. package/dist/components/Badge/index.d.ts +4 -0
  20. package/dist/components/Badge/index.js +4 -0
  21. package/dist/components/Banner/Banner.d.ts +7 -0
  22. package/dist/components/Banner/Banner.js +68 -0
  23. package/dist/components/Banner/Banner.types.d.ts +13 -0
  24. package/dist/components/Banner/Banner.types.js +0 -0
  25. package/dist/components/Banner/index.d.ts +4 -0
  26. package/dist/components/Banner/index.js +4 -0
  27. package/dist/components/BottomNav/BottomNav.d.ts +7 -0
  28. package/dist/components/BottomNav/BottomNav.js +9 -0
  29. package/dist/components/BottomNav/BottomNav.types.d.ts +10 -0
  30. package/dist/components/BottomNav/BottomNav.types.js +0 -0
  31. package/dist/components/BottomNav/index.d.ts +3 -0
  32. package/dist/components/BottomNav/index.js +4 -0
  33. package/dist/components/Button/Button.d.ts +7 -0
  34. package/dist/components/Button/Button.js +42 -0
  35. package/dist/components/Button/Button.types.d.ts +17 -0
  36. package/dist/components/Button/Button.types.js +0 -0
  37. package/dist/components/Button/index.d.ts +4 -0
  38. package/dist/components/Button/index.js +4 -0
  39. package/dist/components/Card/Card.d.ts +6 -0
  40. package/dist/components/Card/Card.js +26 -0
  41. package/dist/components/Card/Card.types.d.ts +10 -0
  42. package/dist/components/Card/Card.types.js +0 -0
  43. package/dist/components/Card/index.d.ts +3 -0
  44. package/dist/components/Card/index.js +4 -0
  45. package/dist/components/Checkbox/Checkbox.d.ts +7 -0
  46. package/dist/components/Checkbox/Checkbox.js +34 -0
  47. package/dist/components/Checkbox/Checkbox.types.d.ts +17 -0
  48. package/dist/components/Checkbox/Checkbox.types.js +0 -0
  49. package/dist/components/Checkbox/index.d.ts +4 -0
  50. package/dist/components/Checkbox/index.js +4 -0
  51. package/dist/components/Dialog/Dialog.d.ts +6 -0
  52. package/dist/components/Dialog/Dialog.js +51 -0
  53. package/dist/components/Dialog/Dialog.types.d.ts +12 -0
  54. package/dist/components/Dialog/Dialog.types.js +0 -0
  55. package/dist/components/Dialog/index.d.ts +3 -0
  56. package/dist/components/Dialog/index.js +4 -0
  57. package/dist/components/Divider/Divider.d.ts +6 -0
  58. package/dist/components/Divider/Divider.js +19 -0
  59. package/dist/components/Divider/Divider.types.d.ts +7 -0
  60. package/dist/components/Divider/Divider.types.js +0 -0
  61. package/dist/components/Divider/index.d.ts +3 -0
  62. package/dist/components/Divider/index.js +4 -0
  63. package/dist/components/Drawer/Drawer.d.ts +8 -0
  64. package/dist/components/Drawer/Drawer.js +9 -0
  65. package/dist/components/Drawer/Drawer.types.d.ts +13 -0
  66. package/dist/components/Drawer/Drawer.types.js +0 -0
  67. package/dist/components/Drawer/index.d.ts +4 -0
  68. package/dist/components/Drawer/index.js +4 -0
  69. package/dist/components/Fab/Fab.d.ts +7 -0
  70. package/dist/components/Fab/Fab.js +33 -0
  71. package/dist/components/Fab/Fab.types.d.ts +11 -0
  72. package/dist/components/Fab/Fab.types.js +0 -0
  73. package/dist/components/Fab/index.d.ts +4 -0
  74. package/dist/components/Fab/index.js +4 -0
  75. package/dist/components/GlassAppBar/GlassAppBar.d.ts +6 -0
  76. package/dist/components/GlassAppBar/GlassAppBar.js +57 -0
  77. package/dist/components/GlassAppBar/GlassAppBar.types.d.ts +12 -0
  78. package/dist/components/GlassAppBar/GlassAppBar.types.js +0 -0
  79. package/dist/components/GlassAppBar/index.d.ts +3 -0
  80. package/dist/components/GlassAppBar/index.js +4 -0
  81. package/dist/components/Icon/Icon.d.ts +8 -0
  82. package/dist/components/Icon/Icon.js +46 -0
  83. package/dist/components/Icon/Icon.types.d.ts +14 -0
  84. package/dist/components/Icon/Icon.types.js +0 -0
  85. package/dist/components/Icon/index.d.ts +5 -0
  86. package/dist/components/Icon/index.js +4 -0
  87. package/dist/components/Input/Input.d.ts +6 -0
  88. package/dist/components/Input/Input.js +43 -0
  89. package/dist/components/Input/Input.types.d.ts +13 -0
  90. package/dist/components/Input/Input.types.js +0 -0
  91. package/dist/components/Input/index.d.ts +3 -0
  92. package/dist/components/Input/index.js +4 -0
  93. package/dist/components/Select/Select.d.ts +6 -0
  94. package/dist/components/Select/Select.js +50 -0
  95. package/dist/components/Select/Select.types.d.ts +15 -0
  96. package/dist/components/Select/Select.types.js +0 -0
  97. package/dist/components/Select/index.d.ts +3 -0
  98. package/dist/components/Select/index.js +4 -0
  99. package/dist/components/Spinner/Spinner.d.ts +7 -0
  100. package/dist/components/Spinner/Spinner.js +35 -0
  101. package/dist/components/Spinner/Spinner.types.d.ts +9 -0
  102. package/dist/components/Spinner/Spinner.types.js +0 -0
  103. package/dist/components/Spinner/index.d.ts +4 -0
  104. package/dist/components/Spinner/index.js +4 -0
  105. package/dist/components/Surface/Surface.d.ts +6 -0
  106. package/dist/components/Surface/Surface.js +29 -0
  107. package/dist/components/Surface/Surface.types.d.ts +11 -0
  108. package/dist/components/Surface/Surface.types.js +0 -0
  109. package/dist/components/Surface/index.d.ts +3 -0
  110. package/dist/components/Surface/index.js +4 -0
  111. package/dist/components/Switch/Switch.d.ts +7 -0
  112. package/dist/components/Switch/Switch.js +34 -0
  113. package/dist/components/Switch/Switch.types.d.ts +17 -0
  114. package/dist/components/Switch/Switch.types.js +0 -0
  115. package/dist/components/Switch/index.d.ts +4 -0
  116. package/dist/components/Switch/index.js +4 -0
  117. package/dist/components/Text/Text.d.ts +7 -0
  118. package/dist/components/Text/Text.js +34 -0
  119. package/dist/components/Text/Text.types.d.ts +13 -0
  120. package/dist/components/Text/Text.types.js +0 -0
  121. package/dist/components/Text/index.d.ts +4 -0
  122. package/dist/components/Text/index.js +4 -0
  123. package/dist/components/Tooltip/Tooltip.d.ts +6 -0
  124. package/dist/components/Tooltip/Tooltip.js +8 -0
  125. package/dist/components/Tooltip/Tooltip.types.d.ts +11 -0
  126. package/dist/components/Tooltip/Tooltip.types.js +0 -0
  127. package/dist/components/Tooltip/index.d.ts +3 -0
  128. package/dist/components/Tooltip/index.js +4 -0
  129. package/dist/components/common.d.ts +11 -0
  130. package/dist/components/common.js +0 -0
  131. package/dist/index.d.ts +53 -0
  132. package/dist/index.js +54 -0
  133. package/dist/notifications/NotificationContext.d.ts +33 -0
  134. package/dist/notifications/NotificationContext.js +34 -0
  135. package/dist/notifications/NotificationHost.d.ts +5 -0
  136. package/dist/notifications/NotificationHost.js +22 -0
  137. package/dist/notifications/useNotify.d.ts +13 -0
  138. package/dist/notifications/useNotify.js +19 -0
  139. package/dist/provider/SublimeProvider.d.ts +12 -0
  140. package/dist/provider/SublimeProvider.js +23 -0
  141. package/dist/provider/TokenContext.d.ts +14 -0
  142. package/dist/provider/TokenContext.js +5 -0
  143. package/dist/provider/resolveTokens.d.ts +7 -0
  144. package/dist/provider/resolveTokens.js +13 -0
  145. package/dist/provider/useTokens.d.ts +7 -0
  146. package/dist/provider/useTokens.js +12 -0
  147. package/dist/tokens/generateThemes.d.ts +10 -0
  148. package/dist/tokens/generateThemes.js +44 -0
  149. package/dist/tokens/tokens.d.ts +74 -0
  150. package/dist/tokens/tokens.js +78 -0
  151. package/package.json +53 -0
  152. package/src/components/AppBar/AppBar.native.tsx +28 -0
  153. package/src/components/AppBar/AppBar.tsx +51 -0
  154. package/src/components/AppBar/AppBar.types.ts +9 -0
  155. package/src/components/AppBar/index.ts +2 -0
  156. package/src/components/Avatar/Avatar.native.tsx +38 -0
  157. package/src/components/Avatar/Avatar.tsx +38 -0
  158. package/src/components/Avatar/Avatar.types.ts +10 -0
  159. package/src/components/Avatar/index.ts +2 -0
  160. package/src/components/Badge/Badge.native.tsx +97 -0
  161. package/src/components/Badge/Badge.tsx +89 -0
  162. package/src/components/Badge/Badge.types.ts +11 -0
  163. package/src/components/Badge/index.ts +2 -0
  164. package/src/components/Banner/Banner.native.tsx +89 -0
  165. package/src/components/Banner/Banner.tsx +78 -0
  166. package/src/components/Banner/Banner.types.ts +11 -0
  167. package/src/components/Banner/index.ts +2 -0
  168. package/src/components/BottomNav/BottomNav.native.tsx +87 -0
  169. package/src/components/BottomNav/BottomNav.tsx +9 -0
  170. package/src/components/BottomNav/BottomNav.types.ts +8 -0
  171. package/src/components/BottomNav/index.ts +2 -0
  172. package/src/components/Button/Button.native.tsx +27 -0
  173. package/src/components/Button/Button.tsx +37 -0
  174. package/src/components/Button/Button.types.ts +17 -0
  175. package/src/components/Button/index.ts +2 -0
  176. package/src/components/Card/Card.native.tsx +24 -0
  177. package/src/components/Card/Card.tsx +30 -0
  178. package/src/components/Card/Card.types.ts +8 -0
  179. package/src/components/Card/index.ts +2 -0
  180. package/src/components/Checkbox/Checkbox.native.tsx +58 -0
  181. package/src/components/Checkbox/Checkbox.tsx +35 -0
  182. package/src/components/Checkbox/Checkbox.types.ts +15 -0
  183. package/src/components/Checkbox/index.ts +2 -0
  184. package/src/components/Dialog/Dialog.native.tsx +28 -0
  185. package/src/components/Dialog/Dialog.tsx +49 -0
  186. package/src/components/Dialog/Dialog.types.ts +10 -0
  187. package/src/components/Dialog/index.ts +2 -0
  188. package/src/components/Divider/Divider.native.tsx +30 -0
  189. package/src/components/Divider/Divider.tsx +16 -0
  190. package/src/components/Divider/Divider.types.ts +5 -0
  191. package/src/components/Divider/index.ts +2 -0
  192. package/src/components/Drawer/Drawer.native.tsx +113 -0
  193. package/src/components/Drawer/Drawer.tsx +9 -0
  194. package/src/components/Drawer/Drawer.types.ts +11 -0
  195. package/src/components/Drawer/index.ts +2 -0
  196. package/src/components/Fab/Fab.native.tsx +41 -0
  197. package/src/components/Fab/Fab.tsx +36 -0
  198. package/src/components/Fab/Fab.types.ts +9 -0
  199. package/src/components/Fab/index.ts +2 -0
  200. package/src/components/GlassAppBar/GlassAppBar.native.tsx +29 -0
  201. package/src/components/GlassAppBar/GlassAppBar.tsx +53 -0
  202. package/src/components/GlassAppBar/GlassAppBar.types.ts +10 -0
  203. package/src/components/GlassAppBar/index.ts +2 -0
  204. package/src/components/Icon/Icon.native.tsx +39 -0
  205. package/src/components/Icon/Icon.tsx +57 -0
  206. package/src/components/Icon/Icon.types.ts +13 -0
  207. package/src/components/Icon/index.ts +2 -0
  208. package/src/components/Input/Input.native.tsx +34 -0
  209. package/src/components/Input/Input.tsx +33 -0
  210. package/src/components/Input/Input.types.ts +11 -0
  211. package/src/components/Input/index.ts +2 -0
  212. package/src/components/Select/Select.native.tsx +63 -0
  213. package/src/components/Select/Select.tsx +48 -0
  214. package/src/components/Select/Select.types.ts +14 -0
  215. package/src/components/Select/index.ts +2 -0
  216. package/src/components/Spinner/Spinner.native.tsx +38 -0
  217. package/src/components/Spinner/Spinner.tsx +37 -0
  218. package/src/components/Spinner/Spinner.types.ts +7 -0
  219. package/src/components/Spinner/index.ts +2 -0
  220. package/src/components/Surface/Surface.native.tsx +32 -0
  221. package/src/components/Surface/Surface.tsx +31 -0
  222. package/src/components/Surface/Surface.types.ts +10 -0
  223. package/src/components/Surface/index.ts +2 -0
  224. package/src/components/Switch/Switch.native.tsx +58 -0
  225. package/src/components/Switch/Switch.tsx +35 -0
  226. package/src/components/Switch/Switch.types.ts +15 -0
  227. package/src/components/Switch/index.ts +2 -0
  228. package/src/components/Text/Text.native.tsx +31 -0
  229. package/src/components/Text/Text.tsx +34 -0
  230. package/src/components/Text/Text.types.ts +12 -0
  231. package/src/components/Text/index.ts +2 -0
  232. package/src/components/Tooltip/Tooltip.native.tsx +6 -0
  233. package/src/components/Tooltip/Tooltip.tsx +10 -0
  234. package/src/components/Tooltip/Tooltip.types.ts +9 -0
  235. package/src/components/Tooltip/index.ts +2 -0
  236. package/src/components/common.ts +10 -0
  237. package/src/index.ts +33 -0
  238. package/src/notifications/NotificationContext.tsx +57 -0
  239. package/src/notifications/NotificationHost.native.tsx +20 -0
  240. package/src/notifications/NotificationHost.tsx +27 -0
  241. package/src/notifications/useNotify.ts +18 -0
  242. package/src/provider/SublimeProvider.native.tsx +29 -0
  243. package/src/provider/SublimeProvider.tsx +30 -0
  244. package/src/provider/TokenContext.ts +13 -0
  245. package/src/provider/resolveTokens.ts +16 -0
  246. package/src/provider/useTokens.ts +10 -0
  247. package/src/test-utils/renderWeb.tsx +8 -0
  248. package/src/tokens/generateThemes.ts +49 -0
  249. package/src/tokens/tokens.ts +71 -0
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+ const TokenContext = createContext(null);
3
+ export {
4
+ TokenContext
5
+ };
@@ -0,0 +1,7 @@
1
+ import { SublimeTokens } from '../tokens/tokens.js';
2
+ import { ResolvedTokens } from './TokenContext.js';
3
+ import 'react';
4
+
5
+ declare function resolveTokens(tokens: SublimeTokens, mode: 'light' | 'dark'): ResolvedTokens;
6
+
7
+ export { resolveTokens };
@@ -0,0 +1,13 @@
1
+ function resolveTokens(tokens, mode) {
2
+ return {
3
+ color: tokens.color[mode],
4
+ radii: tokens.radii,
5
+ shadows: tokens.shadows,
6
+ spacing: tokens.spacing,
7
+ typography: tokens.typography,
8
+ mode
9
+ };
10
+ }
11
+ export {
12
+ resolveTokens
13
+ };
@@ -0,0 +1,7 @@
1
+ import { ResolvedTokens } from './TokenContext.js';
2
+ import 'react';
3
+ import '../tokens/tokens.js';
4
+
5
+ declare function useTokens(): ResolvedTokens;
6
+
7
+ export { useTokens };
@@ -0,0 +1,12 @@
1
+ import { useContext } from "react";
2
+ import { TokenContext } from "./TokenContext.js";
3
+ function useTokens() {
4
+ const tokens = useContext(TokenContext);
5
+ if (tokens === null) {
6
+ throw new Error("useTokens must be used within a <SublimeProvider>.");
7
+ }
8
+ return tokens;
9
+ }
10
+ export {
11
+ useTokens
12
+ };
@@ -0,0 +1,10 @@
1
+ import { MD3Theme } from 'react-native-paper';
2
+ import { Theme } from '@mui/material';
3
+ import { SublimeTokens } from './tokens.js';
4
+
5
+ declare function generateThemes(tokens: SublimeTokens, mode: 'light' | 'dark'): {
6
+ paperTheme: MD3Theme;
7
+ muiTheme: Theme;
8
+ };
9
+
10
+ export { generateThemes };
@@ -0,0 +1,44 @@
1
+ import { MD3LightTheme, MD3DarkTheme } from "react-native-paper";
2
+ import { createTheme } from "@mui/material";
3
+ function generateThemes(tokens, mode) {
4
+ const c = tokens.color[mode];
5
+ const base = mode === "dark" ? MD3DarkTheme : MD3LightTheme;
6
+ const paperTheme = {
7
+ ...base,
8
+ roundness: tokens.radii.md,
9
+ colors: {
10
+ ...base.colors,
11
+ primary: c.primary,
12
+ onPrimary: c.primaryFg,
13
+ secondary: c.secondary,
14
+ onSecondary: c.secondaryFg,
15
+ error: c.danger,
16
+ background: c.background,
17
+ onBackground: c.foreground,
18
+ surface: c.surface,
19
+ onSurface: c.foreground,
20
+ outline: c.surfaceBorder,
21
+ outlineVariant: c.divider
22
+ }
23
+ };
24
+ const muiTheme = createTheme({
25
+ palette: {
26
+ mode,
27
+ primary: { main: c.primary, contrastText: c.primaryFg },
28
+ secondary: { main: c.secondary, contrastText: c.secondaryFg },
29
+ success: { main: c.success },
30
+ warning: { main: c.warning },
31
+ error: { main: c.danger },
32
+ info: { main: c.info },
33
+ background: { default: c.background, paper: c.surface },
34
+ text: { primary: c.foreground, secondary: c.mutedFg },
35
+ divider: c.divider
36
+ },
37
+ shape: { borderRadius: tokens.radii.md },
38
+ typography: { fontFamily: tokens.typography.family }
39
+ });
40
+ return { paperTheme, muiTheme };
41
+ }
42
+ export {
43
+ generateThemes
44
+ };
@@ -0,0 +1,74 @@
1
+ interface ColorTokens {
2
+ primary: string;
3
+ primaryFg: string;
4
+ secondary: string;
5
+ secondaryFg: string;
6
+ success: string;
7
+ warning: string;
8
+ danger: string;
9
+ info: string;
10
+ background: string;
11
+ foreground: string;
12
+ mutedFg: string;
13
+ surface: string;
14
+ surfaceBorder: string;
15
+ surfaceHover: string;
16
+ glassBg: string;
17
+ glassBorder: string;
18
+ divider: string;
19
+ ring: string;
20
+ primarySoftBg: string;
21
+ primarySoftFg: string;
22
+ successSoftBg: string;
23
+ successSoftFg: string;
24
+ warningSoftBg: string;
25
+ warningSoftFg: string;
26
+ dangerSoftBg: string;
27
+ dangerSoftFg: string;
28
+ infoSoftBg: string;
29
+ infoSoftFg: string;
30
+ }
31
+ interface SublimeTokens {
32
+ color: {
33
+ light: ColorTokens;
34
+ dark: ColorTokens;
35
+ };
36
+ radii: {
37
+ sm: number;
38
+ md: number;
39
+ lg: number;
40
+ full: number;
41
+ };
42
+ shadows: {
43
+ sm: string;
44
+ md: string;
45
+ lg: string;
46
+ };
47
+ spacing: {
48
+ xs: number;
49
+ sm: number;
50
+ md: number;
51
+ lg: number;
52
+ xl: number;
53
+ };
54
+ typography: {
55
+ family: string;
56
+ sizes: {
57
+ xs: number;
58
+ sm: number;
59
+ md: number;
60
+ lg: number;
61
+ xl: number;
62
+ '2xl': number;
63
+ };
64
+ weights: {
65
+ regular: number;
66
+ medium: number;
67
+ semibold: number;
68
+ bold: number;
69
+ };
70
+ };
71
+ }
72
+ declare const defaultTokens: SublimeTokens;
73
+
74
+ export { type ColorTokens, type SublimeTokens, defaultTokens };
@@ -0,0 +1,78 @@
1
+ const light = {
2
+ primary: "rgb(37,99,235)",
3
+ primaryFg: "rgb(255,255,255)",
4
+ secondary: "rgb(100,116,139)",
5
+ secondaryFg: "rgb(255,255,255)",
6
+ success: "rgb(22,163,74)",
7
+ warning: "rgb(217,119,6)",
8
+ danger: "rgb(220,38,38)",
9
+ info: "rgb(2,132,199)",
10
+ background: "rgb(247,250,255)",
11
+ foreground: "rgb(15,23,42)",
12
+ mutedFg: "rgba(71,85,105,0.85)",
13
+ surface: "rgba(243,248,255,0.90)",
14
+ surfaceBorder: "rgba(15,23,42,0.08)",
15
+ surfaceHover: "rgba(59,130,246,0.06)",
16
+ glassBg: "rgba(236,244,255,0.60)",
17
+ glassBorder: "rgba(15,23,42,0.08)",
18
+ divider: "rgba(15,23,42,0.06)",
19
+ ring: "rgba(59,130,246,0.45)",
20
+ primarySoftBg: "rgba(59,130,246,0.08)",
21
+ primarySoftFg: "rgb(29,78,216)",
22
+ successSoftBg: "rgba(34,197,94,0.10)",
23
+ successSoftFg: "rgb(21,128,61)",
24
+ warningSoftBg: "rgba(245,158,11,0.12)",
25
+ warningSoftFg: "rgb(180,83,9)",
26
+ dangerSoftBg: "rgba(244,63,94,0.08)",
27
+ dangerSoftFg: "rgb(190,18,60)",
28
+ infoSoftBg: "rgba(14,165,233,0.10)",
29
+ infoSoftFg: "rgb(3,105,161)"
30
+ };
31
+ const dark = {
32
+ primary: "rgb(96,165,250)",
33
+ primaryFg: "rgb(8,12,20)",
34
+ secondary: "rgb(148,163,184)",
35
+ secondaryFg: "rgb(8,12,20)",
36
+ success: "rgb(74,222,128)",
37
+ warning: "rgb(251,191,36)",
38
+ danger: "rgb(251,113,133)",
39
+ info: "rgb(56,189,248)",
40
+ background: "rgb(8,12,20)",
41
+ foreground: "rgb(245,247,251)",
42
+ mutedFg: "rgba(229,231,235,0.65)",
43
+ surface: "rgba(96,165,250,0.06)",
44
+ surfaceBorder: "rgba(255,255,255,0.08)",
45
+ surfaceHover: "rgba(255,255,255,0.06)",
46
+ glassBg: "rgba(96,165,250,0.05)",
47
+ glassBorder: "rgba(255,255,255,0.08)",
48
+ divider: "rgba(255,255,255,0.06)",
49
+ ring: "rgba(96,165,250,0.55)",
50
+ primarySoftBg: "rgba(59,130,246,0.12)",
51
+ primarySoftFg: "rgb(147,197,253)",
52
+ successSoftBg: "rgba(34,197,94,0.16)",
53
+ successSoftFg: "rgb(134,239,172)",
54
+ warningSoftBg: "rgba(245,158,11,0.18)",
55
+ warningSoftFg: "rgb(253,224,71)",
56
+ dangerSoftBg: "rgba(244,63,94,0.18)",
57
+ dangerSoftFg: "rgb(253,164,175)",
58
+ infoSoftBg: "rgba(14,165,233,0.16)",
59
+ infoSoftFg: "rgb(125,211,252)"
60
+ };
61
+ const defaultTokens = {
62
+ color: { light, dark },
63
+ radii: { sm: 8, md: 12, lg: 16, full: 999 },
64
+ shadows: {
65
+ sm: "0 1px 2px rgba(15,23,42,0.06)",
66
+ md: "0 4px 12px rgba(15,23,42,0.10)",
67
+ lg: "0 12px 32px rgba(15,23,42,0.16)"
68
+ },
69
+ spacing: { xs: 4, sm: 8, md: 12, lg: 16, xl: 24 },
70
+ typography: {
71
+ family: "Inter, system-ui, sans-serif",
72
+ sizes: { xs: 12, sm: 14, md: 16, lg: 18, xl: 22, "2xl": 28 },
73
+ weights: { regular: 400, medium: 500, semibold: 600, bold: 700 }
74
+ }
75
+ };
76
+ export {
77
+ defaultTokens
78
+ };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@sublime-ui/library",
3
+ "version": "0.1.0",
4
+ "description": "Tokens-first cross-platform design system — one theme drives MUI (web) and React Native Paper (mobile).",
5
+ "keywords": ["sublime-ui", "design-system", "mui", "react-native-paper", "theme", "tokens", "components", "cross-platform", "typescript"],
6
+ "homepage": "https://sublime-ui.github.io/sublime-ui/",
7
+ "bugs": "https://github.com/sublime-ui/sublime-ui/issues",
8
+ "repository": { "type": "git", "url": "git+https://github.com/sublime-ui/sublime-ui.git", "directory": "library" },
9
+ "license": "MIT",
10
+ "author": "Aaron Mkandawire",
11
+ "publishConfig": { "access": "public" },
12
+ "type": "module",
13
+ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } },
14
+ "react-native": "./src/index.ts",
15
+ "files": ["dist", "src"],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "typecheck": "tsc --noEmit",
19
+ "test": "vitest run --passWithNoTests",
20
+ "lint": "eslint src"
21
+ },
22
+ "peerDependencies": {
23
+ "react": ">=18",
24
+ "react-native": ">=0.74",
25
+ "react-native-paper": ">=5",
26
+ "@mui/material": ">=6",
27
+ "@emotion/react": ">=11",
28
+ "@emotion/styled": ">=11"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "react-native": { "optional": true },
32
+ "react-native-paper": { "optional": true },
33
+ "@mui/material": { "optional": true },
34
+ "@emotion/react": { "optional": true },
35
+ "@emotion/styled": { "optional": true }
36
+ },
37
+ "devDependencies": {
38
+ "@emotion/react": "^11.13.3",
39
+ "@emotion/styled": "^11.13.0",
40
+ "@mui/material": "^6.1.6",
41
+ "@testing-library/dom": "^10.4.0",
42
+ "@testing-library/react": "^16.0.1",
43
+ "@types/node": "^22",
44
+ "@types/react": "^18.3.12",
45
+ "jsdom": "^25.0.1",
46
+ "react": "^18.3.1",
47
+ "react-dom": "^18.3.1",
48
+ "react-native": "^0.76.1",
49
+ "react-native-paper": "^5.12.5",
50
+ "react-native-safe-area-context": "^4.14.0",
51
+ "react-test-renderer": "^18.3.1"
52
+ }
53
+ }
@@ -0,0 +1,28 @@
1
+ import { Appbar } from 'react-native-paper';
2
+ import { useTokens } from '../../provider/useTokens.js';
3
+ import type { AppBarProps } from './AppBar.types.js';
4
+
5
+ export function AppBar({ title, subtitle, onBack, actions, testID }: AppBarProps) {
6
+ const tokens = useTokens();
7
+ return (
8
+ <Appbar.Header
9
+ testID={testID}
10
+ style={{
11
+ backgroundColor: tokens.color.surface,
12
+ borderBottomColor: tokens.color.surfaceBorder,
13
+ borderBottomWidth: 1,
14
+ }}
15
+ >
16
+ {onBack ? <Appbar.BackAction onPress={onBack} accessibilityLabel="back" /> : null}
17
+ <Appbar.Content
18
+ title={title}
19
+ {...(subtitle ? { subtitle } : {})}
20
+ titleStyle={{
21
+ color: tokens.color.foreground,
22
+ fontWeight: String(tokens.typography.weights.semibold) as '600',
23
+ }}
24
+ />
25
+ {actions ?? null}
26
+ </Appbar.Header>
27
+ );
28
+ }
@@ -0,0 +1,51 @@
1
+ import { AppBar as MuiAppBar, Toolbar, Typography, IconButton, Box } from '@mui/material';
2
+ import { useTokens } from '../../provider/useTokens.js';
3
+ import type { AppBarProps } from './AppBar.types.js';
4
+
5
+ export function AppBar({ title, subtitle, onBack, actions, testID }: AppBarProps) {
6
+ const tokens = useTokens();
7
+ return (
8
+ <MuiAppBar
9
+ position="static"
10
+ elevation={0}
11
+ data-testid={testID}
12
+ sx={{
13
+ backgroundColor: tokens.color.surface,
14
+ color: tokens.color.foreground,
15
+ borderBottom: `1px solid ${tokens.color.surfaceBorder}`,
16
+ }}
17
+ >
18
+ <Toolbar sx={{ gap: `${tokens.spacing.sm}px` }}>
19
+ {onBack ? (
20
+ <IconButton
21
+ edge="start"
22
+ aria-label="back"
23
+ onClick={onBack}
24
+ sx={{ color: tokens.color.foreground }}
25
+ >
26
+ <span aria-hidden>{'←'}</span>
27
+ </IconButton>
28
+ ) : null}
29
+ <Box sx={{ flex: 1, minWidth: 0 }}>
30
+ <Typography
31
+ variant="h6"
32
+ noWrap
33
+ sx={{ fontWeight: tokens.typography.weights.semibold }}
34
+ >
35
+ {title}
36
+ </Typography>
37
+ {subtitle ? (
38
+ <Typography
39
+ variant="caption"
40
+ noWrap
41
+ sx={{ display: 'block', color: tokens.color.mutedFg }}
42
+ >
43
+ {subtitle}
44
+ </Typography>
45
+ ) : null}
46
+ </Box>
47
+ {actions ?? null}
48
+ </Toolbar>
49
+ </MuiAppBar>
50
+ );
51
+ }
@@ -0,0 +1,9 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface AppBarProps {
4
+ title: string;
5
+ subtitle?: string;
6
+ onBack?: () => void;
7
+ actions?: ReactNode;
8
+ testID?: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ export { AppBar } from './AppBar.js';
2
+ export type { AppBarProps } from './AppBar.types.js';
@@ -0,0 +1,38 @@
1
+ import { Avatar as PaperAvatar } from 'react-native-paper';
2
+ import { useTokens } from '../../provider/useTokens.js';
3
+ import type { Size } from '../common.js';
4
+ import type { AvatarProps } from './Avatar.types.js';
5
+
6
+ const pxFor = (size: Size): number =>
7
+ size === 'sm' ? 28 : size === 'lg' ? 56 : 40;
8
+
9
+ const initialsOf = (label: string): string =>
10
+ label
11
+ .trim()
12
+ .split(/\s+/)
13
+ .slice(0, 2)
14
+ .map((w) => w.charAt(0).toUpperCase())
15
+ .join('');
16
+
17
+ export function Avatar({ source, label, size = 'md', testID }: AvatarProps) {
18
+ const tokens = useTokens();
19
+ const dim = pxFor(size);
20
+ if (source) {
21
+ return (
22
+ <PaperAvatar.Image
23
+ {...(testID ? { testID } : {})}
24
+ size={dim}
25
+ source={{ uri: source }}
26
+ />
27
+ );
28
+ }
29
+ return (
30
+ <PaperAvatar.Text
31
+ {...(testID ? { testID } : {})}
32
+ size={dim}
33
+ label={label ? initialsOf(label) : ''}
34
+ style={{ backgroundColor: tokens.color.primarySoftBg }}
35
+ labelStyle={{ color: tokens.color.primarySoftFg }}
36
+ />
37
+ );
38
+ }
@@ -0,0 +1,38 @@
1
+ import { Avatar as MuiAvatar } from '@mui/material';
2
+ import { useTokens } from '../../provider/useTokens.js';
3
+ import type { Size } from '../common.js';
4
+ import type { AvatarProps } from './Avatar.types.js';
5
+
6
+ const pxFor = (size: Size): number =>
7
+ size === 'sm' ? 28 : size === 'lg' ? 56 : 40;
8
+
9
+ const initialsOf = (label: string): string =>
10
+ label
11
+ .trim()
12
+ .split(/\s+/)
13
+ .slice(0, 2)
14
+ .map((w) => w.charAt(0).toUpperCase())
15
+ .join('');
16
+
17
+ export function Avatar({ source, label, size = 'md', testID }: AvatarProps) {
18
+ const tokens = useTokens();
19
+ const dim = pxFor(size);
20
+ const initials = label ? initialsOf(label) : '';
21
+ return (
22
+ <MuiAvatar
23
+ data-testid={testID}
24
+ {...(source ? { src: source } : {})}
25
+ {...(label ? { alt: label } : {})}
26
+ sx={{
27
+ width: dim,
28
+ height: dim,
29
+ backgroundColor: tokens.color.primarySoftBg,
30
+ color: tokens.color.primarySoftFg,
31
+ fontWeight: tokens.typography.weights.semibold,
32
+ fontSize: dim * 0.4,
33
+ }}
34
+ >
35
+ {source ? null : initials}
36
+ </MuiAvatar>
37
+ );
38
+ }
@@ -0,0 +1,10 @@
1
+ import type { Size } from '../common.js';
2
+
3
+ export interface AvatarProps {
4
+ /** Image URI; when present the avatar shows the image. */
5
+ source?: string;
6
+ /** Fallback text; initials are derived from it when no source is present. */
7
+ label?: string;
8
+ size?: Size;
9
+ testID?: string;
10
+ }
@@ -0,0 +1,2 @@
1
+ export { Avatar } from './Avatar.js';
2
+ export type { AvatarProps } from './Avatar.types.js';
@@ -0,0 +1,97 @@
1
+ import { View } from 'react-native';
2
+ import { Text, Icon } from 'react-native-paper';
3
+ import { useTokens } from '../../provider/useTokens.js';
4
+ import type { ResolvedTokens } from '../../provider/TokenContext.js';
5
+ import type { Tone } from '../common.js';
6
+ import type { BadgeProps, BadgeVariant } from './Badge.types.js';
7
+
8
+ interface ColorPair {
9
+ bg: string;
10
+ fg: string;
11
+ }
12
+
13
+ const solidPair = (c: ResolvedTokens['color'], tone: Tone): ColorPair => {
14
+ switch (tone) {
15
+ case 'primary':
16
+ return { bg: c.primary, fg: c.primaryFg };
17
+ case 'success':
18
+ return { bg: c.success, fg: c.primaryFg };
19
+ case 'danger':
20
+ return { bg: c.danger, fg: c.primaryFg };
21
+ case 'warning':
22
+ return { bg: c.warning, fg: c.primaryFg };
23
+ case 'info':
24
+ return { bg: c.info, fg: c.primaryFg };
25
+ case 'neutral':
26
+ default:
27
+ return { bg: c.secondary, fg: c.secondaryFg };
28
+ }
29
+ };
30
+
31
+ const softPair = (c: ResolvedTokens['color'], tone: Tone): ColorPair => {
32
+ switch (tone) {
33
+ case 'primary':
34
+ return { bg: c.primarySoftBg, fg: c.primarySoftFg };
35
+ case 'success':
36
+ return { bg: c.successSoftBg, fg: c.successSoftFg };
37
+ case 'danger':
38
+ return { bg: c.dangerSoftBg, fg: c.dangerSoftFg };
39
+ case 'warning':
40
+ return { bg: c.warningSoftBg, fg: c.warningSoftFg };
41
+ case 'info':
42
+ return { bg: c.infoSoftBg, fg: c.infoSoftFg };
43
+ case 'neutral':
44
+ default:
45
+ return { bg: c.surfaceHover, fg: c.mutedFg };
46
+ }
47
+ };
48
+
49
+ const pairFor = (
50
+ c: ResolvedTokens['color'],
51
+ tone: Tone,
52
+ variant: BadgeVariant,
53
+ ): ColorPair => {
54
+ if (variant === 'solid') return solidPair(c, tone);
55
+ if (variant === 'muted') return { bg: c.surfaceHover, fg: c.mutedFg };
56
+ return softPair(c, tone);
57
+ };
58
+
59
+ export function Badge({
60
+ label,
61
+ tone = 'neutral',
62
+ variant = 'soft',
63
+ icon,
64
+ testID,
65
+ }: BadgeProps) {
66
+ const tokens = useTokens();
67
+ const { bg, fg } = pairFor(tokens.color, tone, variant);
68
+ return (
69
+ <View
70
+ {...(testID ? { testID } : {})}
71
+ style={{
72
+ flexDirection: 'row',
73
+ alignItems: 'center',
74
+ alignSelf: 'flex-start',
75
+ backgroundColor: bg,
76
+ borderRadius: tokens.radii.full,
77
+ paddingHorizontal: tokens.spacing.sm,
78
+ paddingVertical: tokens.spacing.xs,
79
+ }}
80
+ >
81
+ {icon ? (
82
+ <View style={{ marginRight: tokens.spacing.xs }}>
83
+ <Icon source={icon} size={tokens.typography.sizes.sm} color={fg} />
84
+ </View>
85
+ ) : null}
86
+ <Text
87
+ style={{
88
+ color: fg,
89
+ fontSize: tokens.typography.sizes.sm,
90
+ fontWeight: String(tokens.typography.weights.medium) as '500',
91
+ }}
92
+ >
93
+ {label}
94
+ </Text>
95
+ </View>
96
+ );
97
+ }