@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.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/components/AppBar/AppBar.d.ts +6 -0
- package/dist/components/AppBar/AppBar.js +55 -0
- package/dist/components/AppBar/AppBar.types.d.ts +11 -0
- package/dist/components/AppBar/AppBar.types.js +0 -0
- package/dist/components/AppBar/index.d.ts +3 -0
- package/dist/components/AppBar/index.js +4 -0
- package/dist/components/Avatar/Avatar.d.ts +7 -0
- package/dist/components/Avatar/Avatar.js +30 -0
- package/dist/components/Avatar/Avatar.types.d.ts +12 -0
- package/dist/components/Avatar/Avatar.types.js +0 -0
- package/dist/components/Avatar/index.d.ts +4 -0
- package/dist/components/Avatar/index.js +4 -0
- package/dist/components/Badge/Badge.d.ts +7 -0
- package/dist/components/Badge/Badge.js +75 -0
- package/dist/components/Badge/Badge.types.d.ts +12 -0
- package/dist/components/Badge/Badge.types.js +0 -0
- package/dist/components/Badge/index.d.ts +4 -0
- package/dist/components/Badge/index.js +4 -0
- package/dist/components/Banner/Banner.d.ts +7 -0
- package/dist/components/Banner/Banner.js +68 -0
- package/dist/components/Banner/Banner.types.d.ts +13 -0
- package/dist/components/Banner/Banner.types.js +0 -0
- package/dist/components/Banner/index.d.ts +4 -0
- package/dist/components/Banner/index.js +4 -0
- package/dist/components/BottomNav/BottomNav.d.ts +7 -0
- package/dist/components/BottomNav/BottomNav.js +9 -0
- package/dist/components/BottomNav/BottomNav.types.d.ts +10 -0
- package/dist/components/BottomNav/BottomNav.types.js +0 -0
- package/dist/components/BottomNav/index.d.ts +3 -0
- package/dist/components/BottomNav/index.js +4 -0
- package/dist/components/Button/Button.d.ts +7 -0
- package/dist/components/Button/Button.js +42 -0
- package/dist/components/Button/Button.types.d.ts +17 -0
- package/dist/components/Button/Button.types.js +0 -0
- package/dist/components/Button/index.d.ts +4 -0
- package/dist/components/Button/index.js +4 -0
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +26 -0
- package/dist/components/Card/Card.types.d.ts +10 -0
- package/dist/components/Card/Card.types.js +0 -0
- package/dist/components/Card/index.d.ts +3 -0
- package/dist/components/Card/index.js +4 -0
- package/dist/components/Checkbox/Checkbox.d.ts +7 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.types.d.ts +17 -0
- package/dist/components/Checkbox/Checkbox.types.js +0 -0
- package/dist/components/Checkbox/index.d.ts +4 -0
- package/dist/components/Checkbox/index.js +4 -0
- package/dist/components/Dialog/Dialog.d.ts +6 -0
- package/dist/components/Dialog/Dialog.js +51 -0
- package/dist/components/Dialog/Dialog.types.d.ts +12 -0
- package/dist/components/Dialog/Dialog.types.js +0 -0
- package/dist/components/Dialog/index.d.ts +3 -0
- package/dist/components/Dialog/index.js +4 -0
- package/dist/components/Divider/Divider.d.ts +6 -0
- package/dist/components/Divider/Divider.js +19 -0
- package/dist/components/Divider/Divider.types.d.ts +7 -0
- package/dist/components/Divider/Divider.types.js +0 -0
- package/dist/components/Divider/index.d.ts +3 -0
- package/dist/components/Divider/index.js +4 -0
- package/dist/components/Drawer/Drawer.d.ts +8 -0
- package/dist/components/Drawer/Drawer.js +9 -0
- package/dist/components/Drawer/Drawer.types.d.ts +13 -0
- package/dist/components/Drawer/Drawer.types.js +0 -0
- package/dist/components/Drawer/index.d.ts +4 -0
- package/dist/components/Drawer/index.js +4 -0
- package/dist/components/Fab/Fab.d.ts +7 -0
- package/dist/components/Fab/Fab.js +33 -0
- package/dist/components/Fab/Fab.types.d.ts +11 -0
- package/dist/components/Fab/Fab.types.js +0 -0
- package/dist/components/Fab/index.d.ts +4 -0
- package/dist/components/Fab/index.js +4 -0
- package/dist/components/GlassAppBar/GlassAppBar.d.ts +6 -0
- package/dist/components/GlassAppBar/GlassAppBar.js +57 -0
- package/dist/components/GlassAppBar/GlassAppBar.types.d.ts +12 -0
- package/dist/components/GlassAppBar/GlassAppBar.types.js +0 -0
- package/dist/components/GlassAppBar/index.d.ts +3 -0
- package/dist/components/GlassAppBar/index.js +4 -0
- package/dist/components/Icon/Icon.d.ts +8 -0
- package/dist/components/Icon/Icon.js +46 -0
- package/dist/components/Icon/Icon.types.d.ts +14 -0
- package/dist/components/Icon/Icon.types.js +0 -0
- package/dist/components/Icon/index.d.ts +5 -0
- package/dist/components/Icon/index.js +4 -0
- package/dist/components/Input/Input.d.ts +6 -0
- package/dist/components/Input/Input.js +43 -0
- package/dist/components/Input/Input.types.d.ts +13 -0
- package/dist/components/Input/Input.types.js +0 -0
- package/dist/components/Input/index.d.ts +3 -0
- package/dist/components/Input/index.js +4 -0
- package/dist/components/Select/Select.d.ts +6 -0
- package/dist/components/Select/Select.js +50 -0
- package/dist/components/Select/Select.types.d.ts +15 -0
- package/dist/components/Select/Select.types.js +0 -0
- package/dist/components/Select/index.d.ts +3 -0
- package/dist/components/Select/index.js +4 -0
- package/dist/components/Spinner/Spinner.d.ts +7 -0
- package/dist/components/Spinner/Spinner.js +35 -0
- package/dist/components/Spinner/Spinner.types.d.ts +9 -0
- package/dist/components/Spinner/Spinner.types.js +0 -0
- package/dist/components/Spinner/index.d.ts +4 -0
- package/dist/components/Spinner/index.js +4 -0
- package/dist/components/Surface/Surface.d.ts +6 -0
- package/dist/components/Surface/Surface.js +29 -0
- package/dist/components/Surface/Surface.types.d.ts +11 -0
- package/dist/components/Surface/Surface.types.js +0 -0
- package/dist/components/Surface/index.d.ts +3 -0
- package/dist/components/Surface/index.js +4 -0
- package/dist/components/Switch/Switch.d.ts +7 -0
- package/dist/components/Switch/Switch.js +34 -0
- package/dist/components/Switch/Switch.types.d.ts +17 -0
- package/dist/components/Switch/Switch.types.js +0 -0
- package/dist/components/Switch/index.d.ts +4 -0
- package/dist/components/Switch/index.js +4 -0
- package/dist/components/Text/Text.d.ts +7 -0
- package/dist/components/Text/Text.js +34 -0
- package/dist/components/Text/Text.types.d.ts +13 -0
- package/dist/components/Text/Text.types.js +0 -0
- package/dist/components/Text/index.d.ts +4 -0
- package/dist/components/Text/index.js +4 -0
- package/dist/components/Tooltip/Tooltip.d.ts +6 -0
- package/dist/components/Tooltip/Tooltip.js +8 -0
- package/dist/components/Tooltip/Tooltip.types.d.ts +11 -0
- package/dist/components/Tooltip/Tooltip.types.js +0 -0
- package/dist/components/Tooltip/index.d.ts +3 -0
- package/dist/components/Tooltip/index.js +4 -0
- package/dist/components/common.d.ts +11 -0
- package/dist/components/common.js +0 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +54 -0
- package/dist/notifications/NotificationContext.d.ts +33 -0
- package/dist/notifications/NotificationContext.js +34 -0
- package/dist/notifications/NotificationHost.d.ts +5 -0
- package/dist/notifications/NotificationHost.js +22 -0
- package/dist/notifications/useNotify.d.ts +13 -0
- package/dist/notifications/useNotify.js +19 -0
- package/dist/provider/SublimeProvider.d.ts +12 -0
- package/dist/provider/SublimeProvider.js +23 -0
- package/dist/provider/TokenContext.d.ts +14 -0
- package/dist/provider/TokenContext.js +5 -0
- package/dist/provider/resolveTokens.d.ts +7 -0
- package/dist/provider/resolveTokens.js +13 -0
- package/dist/provider/useTokens.d.ts +7 -0
- package/dist/provider/useTokens.js +12 -0
- package/dist/tokens/generateThemes.d.ts +10 -0
- package/dist/tokens/generateThemes.js +44 -0
- package/dist/tokens/tokens.d.ts +74 -0
- package/dist/tokens/tokens.js +78 -0
- package/package.json +53 -0
- package/src/components/AppBar/AppBar.native.tsx +28 -0
- package/src/components/AppBar/AppBar.tsx +51 -0
- package/src/components/AppBar/AppBar.types.ts +9 -0
- package/src/components/AppBar/index.ts +2 -0
- package/src/components/Avatar/Avatar.native.tsx +38 -0
- package/src/components/Avatar/Avatar.tsx +38 -0
- package/src/components/Avatar/Avatar.types.ts +10 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/Badge/Badge.native.tsx +97 -0
- package/src/components/Badge/Badge.tsx +89 -0
- package/src/components/Badge/Badge.types.ts +11 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Banner/Banner.native.tsx +89 -0
- package/src/components/Banner/Banner.tsx +78 -0
- package/src/components/Banner/Banner.types.ts +11 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/BottomNav/BottomNav.native.tsx +87 -0
- package/src/components/BottomNav/BottomNav.tsx +9 -0
- package/src/components/BottomNav/BottomNav.types.ts +8 -0
- package/src/components/BottomNav/index.ts +2 -0
- package/src/components/Button/Button.native.tsx +27 -0
- package/src/components/Button/Button.tsx +37 -0
- package/src/components/Button/Button.types.ts +17 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Card/Card.native.tsx +24 -0
- package/src/components/Card/Card.tsx +30 -0
- package/src/components/Card/Card.types.ts +8 -0
- package/src/components/Card/index.ts +2 -0
- package/src/components/Checkbox/Checkbox.native.tsx +58 -0
- package/src/components/Checkbox/Checkbox.tsx +35 -0
- package/src/components/Checkbox/Checkbox.types.ts +15 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/Dialog/Dialog.native.tsx +28 -0
- package/src/components/Dialog/Dialog.tsx +49 -0
- package/src/components/Dialog/Dialog.types.ts +10 -0
- package/src/components/Dialog/index.ts +2 -0
- package/src/components/Divider/Divider.native.tsx +30 -0
- package/src/components/Divider/Divider.tsx +16 -0
- package/src/components/Divider/Divider.types.ts +5 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Drawer/Drawer.native.tsx +113 -0
- package/src/components/Drawer/Drawer.tsx +9 -0
- package/src/components/Drawer/Drawer.types.ts +11 -0
- package/src/components/Drawer/index.ts +2 -0
- package/src/components/Fab/Fab.native.tsx +41 -0
- package/src/components/Fab/Fab.tsx +36 -0
- package/src/components/Fab/Fab.types.ts +9 -0
- package/src/components/Fab/index.ts +2 -0
- package/src/components/GlassAppBar/GlassAppBar.native.tsx +29 -0
- package/src/components/GlassAppBar/GlassAppBar.tsx +53 -0
- package/src/components/GlassAppBar/GlassAppBar.types.ts +10 -0
- package/src/components/GlassAppBar/index.ts +2 -0
- package/src/components/Icon/Icon.native.tsx +39 -0
- package/src/components/Icon/Icon.tsx +57 -0
- package/src/components/Icon/Icon.types.ts +13 -0
- package/src/components/Icon/index.ts +2 -0
- package/src/components/Input/Input.native.tsx +34 -0
- package/src/components/Input/Input.tsx +33 -0
- package/src/components/Input/Input.types.ts +11 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Select/Select.native.tsx +63 -0
- package/src/components/Select/Select.tsx +48 -0
- package/src/components/Select/Select.types.ts +14 -0
- package/src/components/Select/index.ts +2 -0
- package/src/components/Spinner/Spinner.native.tsx +38 -0
- package/src/components/Spinner/Spinner.tsx +37 -0
- package/src/components/Spinner/Spinner.types.ts +7 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Surface/Surface.native.tsx +32 -0
- package/src/components/Surface/Surface.tsx +31 -0
- package/src/components/Surface/Surface.types.ts +10 -0
- package/src/components/Surface/index.ts +2 -0
- package/src/components/Switch/Switch.native.tsx +58 -0
- package/src/components/Switch/Switch.tsx +35 -0
- package/src/components/Switch/Switch.types.ts +15 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Text/Text.native.tsx +31 -0
- package/src/components/Text/Text.tsx +34 -0
- package/src/components/Text/Text.types.ts +12 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Tooltip/Tooltip.native.tsx +6 -0
- package/src/components/Tooltip/Tooltip.tsx +10 -0
- package/src/components/Tooltip/Tooltip.types.ts +9 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/common.ts +10 -0
- package/src/index.ts +33 -0
- package/src/notifications/NotificationContext.tsx +57 -0
- package/src/notifications/NotificationHost.native.tsx +20 -0
- package/src/notifications/NotificationHost.tsx +27 -0
- package/src/notifications/useNotify.ts +18 -0
- package/src/provider/SublimeProvider.native.tsx +29 -0
- package/src/provider/SublimeProvider.tsx +30 -0
- package/src/provider/TokenContext.ts +13 -0
- package/src/provider/resolveTokens.ts +16 -0
- package/src/provider/useTokens.ts +10 -0
- package/src/test-utils/renderWeb.tsx +8 -0
- package/src/tokens/generateThemes.ts +49 -0
- package/src/tokens/tokens.ts +71 -0
|
@@ -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,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,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
|
+
}
|