@cmotino/cm-web-components 0.1.0 → 0.2.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/README.md +36 -3
- package/dist/components/Button/index.d.ts +2 -0
- package/dist/components/Button/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/theme/createCmTheme.d.ts +9 -0
- package/dist/theme/createCmTheme.js +18 -1
- package/dist/theme/defaultTheme.js +142 -3
- package/dist/theme/tokens.d.ts +68 -0
- package/dist/theme/tokens.js +70 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,8 +13,7 @@ A React component library built on Material UI.
|
|
|
13
13
|
`CmThemeProvider` applies the default look. Use `createCmTheme` to override it for your project:
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import Button from '@
|
|
17
|
-
import { CmThemeProvider, createCmTheme } from '@cmotino/cm-web-components'
|
|
16
|
+
import { Button, CmThemeProvider, createCmTheme } from '@cmotino/cm-web-components'
|
|
18
17
|
|
|
19
18
|
const theme = createCmTheme({
|
|
20
19
|
palette: { primary: { main: '#0b6e4f' } },
|
|
@@ -45,7 +44,41 @@ createCmTheme({
|
|
|
45
44
|
createCmTheme({ cssVariables: { colorSchemeSelector: 'class' } })
|
|
46
45
|
```
|
|
47
46
|
|
|
48
|
-
`CmThemeProvider` adds no global styles. Pass `baseline` to include MUI's `CssBaseline`.
|
|
47
|
+
`CmThemeProvider` adds no global styles. Pass `baseline` to include MUI's `CssBaseline`. The theme uses `Inter, sans-serif` but doesn't load the font, so load Inter in your project, for example with `@fontsource/inter`.
|
|
48
|
+
|
|
49
|
+
**The default theme turns on MUI's keyboard focus ring for every MUI component.** Change it with `focusVisible`, or turn it off with `false`:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
createCmTheme({ focusVisible: { outlineColor: '#0b6e4f' } })
|
|
53
|
+
createCmTheme({ focusVisible: false })
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Button
|
|
57
|
+
|
|
58
|
+
`Button` is MUI's `Button` with the library's default look: no uppercase text, no elevation and a keyboard focus ring. Every MUI prop works, including `loading`, `startIcon` and `component`:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { Button } from '@cmotino/cm-web-components'
|
|
62
|
+
import { Link as RouterLink } from 'react-router'
|
|
63
|
+
|
|
64
|
+
<Button variant="contained" loading={isSaving} onClick={handleSave}>Save</Button>
|
|
65
|
+
|
|
66
|
+
<Button component={RouterLink} to="/settings">Settings</Button>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Use an object for `styleOverrides.root`.** An object merges with the library defaults. A function replaces them, so the label goes back to uppercase unless the function sets `textTransform` itself:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
createCmTheme({
|
|
73
|
+
components: {
|
|
74
|
+
MuiButton: { styleOverrides: { root: { fontWeight: 700 } } },
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**`ButtonProps` describes the `<button>` form only.** A wrapper of your own around the link form needs to declare link props such as `target` itself.
|
|
80
|
+
|
|
81
|
+
The look comes from the theme, so without `CmThemeProvider` a `Button` renders with the surrounding MUI theme, and MUI's own `Button` used under the library theme gets the library look.
|
|
49
82
|
|
|
50
83
|
## Development
|
|
51
84
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Button } from "@mui/material/Button";
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Button } from "./components/Button/index.js";
|
|
1
2
|
import { createCmTheme } from "./theme/createCmTheme.js";
|
|
2
3
|
import { CmThemeProvider } from "./theme/CmThemeProvider.js";
|
|
3
|
-
export { CmThemeProvider, createCmTheme };
|
|
4
|
+
export { Button, CmThemeProvider, createCmTheme };
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { Theme, ThemeOptions } from '@mui/material/styles';
|
|
2
|
+
declare module '@mui/material/styles' {
|
|
3
|
+
interface Palette {
|
|
4
|
+
/** The shadow of `shadows[1]`, set per color scheme. */
|
|
5
|
+
baseShadow: string;
|
|
6
|
+
}
|
|
7
|
+
interface PaletteOptions {
|
|
8
|
+
baseShadow?: string;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
2
11
|
/**
|
|
3
12
|
* Creates a theme from the library defaults and a project's overrides.
|
|
4
13
|
*
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import { defaultThemeOptions } from "./defaultTheme.js";
|
|
2
|
+
import { baseShadow } from "./tokens.js";
|
|
2
3
|
import { createTheme } from "@mui/material/styles";
|
|
3
4
|
import deepmerge from "@mui/utils/deepmerge";
|
|
4
5
|
// src/theme/createCmTheme.ts
|
|
6
|
+
var muiShadows;
|
|
7
|
+
/**
|
|
8
|
+
* MUI's shadows, with `shadows[1]` replaced by the color scheme's `baseShadow`.
|
|
9
|
+
* Shadows can't differ between color schemes, so the CSS variable does that.
|
|
10
|
+
*/
|
|
11
|
+
function createShadows(options) {
|
|
12
|
+
const { cssVariables } = options;
|
|
13
|
+
const prefix = typeof cssVariables === "object" ? cssVariables.cssVarPrefix ?? "mui" : "mui";
|
|
14
|
+
const name = prefix ? `--${prefix}-palette-baseShadow` : "--palette-baseShadow";
|
|
15
|
+
muiShadows ??= createTheme().shadows;
|
|
16
|
+
const shadows = muiShadows.slice();
|
|
17
|
+
shadows[1] = `var(${name}, ${baseShadow.light})`;
|
|
18
|
+
return shadows;
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* Creates a theme from the library defaults and a project's overrides.
|
|
7
22
|
*
|
|
@@ -12,6 +27,8 @@ import deepmerge from "@mui/utils/deepmerge";
|
|
|
12
27
|
* schemes defined, `createTheme(defaults, overrides)` silently ignores them.
|
|
13
28
|
*/
|
|
14
29
|
function createCmTheme(overrides = {}) {
|
|
15
|
-
|
|
30
|
+
const options = deepmerge(defaultThemeOptions, overrides);
|
|
31
|
+
options.shadows ??= createShadows(options);
|
|
32
|
+
return createTheme(options);
|
|
16
33
|
}
|
|
17
34
|
export { createCmTheme };
|
|
@@ -1,9 +1,148 @@
|
|
|
1
|
+
import { baseShadow, brand, gray, green, orange, red } from "./tokens.js";
|
|
2
|
+
import { alpha } from "@mui/material/styles";
|
|
1
3
|
// src/theme/defaultTheme.ts
|
|
2
4
|
var defaultThemeOptions = {
|
|
3
5
|
cssVariables: true,
|
|
4
6
|
colorSchemes: {
|
|
5
|
-
light:
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
light: { palette: {
|
|
8
|
+
primary: {
|
|
9
|
+
light: brand[200],
|
|
10
|
+
main: brand[400],
|
|
11
|
+
dark: brand[700],
|
|
12
|
+
contrastText: brand[50]
|
|
13
|
+
},
|
|
14
|
+
info: {
|
|
15
|
+
light: brand[100],
|
|
16
|
+
main: brand[300],
|
|
17
|
+
dark: brand[600],
|
|
18
|
+
contrastText: gray[50]
|
|
19
|
+
},
|
|
20
|
+
warning: {
|
|
21
|
+
light: orange[300],
|
|
22
|
+
main: orange[400],
|
|
23
|
+
dark: orange[800]
|
|
24
|
+
},
|
|
25
|
+
error: {
|
|
26
|
+
light: red[300],
|
|
27
|
+
main: red[400],
|
|
28
|
+
dark: red[800]
|
|
29
|
+
},
|
|
30
|
+
success: {
|
|
31
|
+
light: green[300],
|
|
32
|
+
main: green[400],
|
|
33
|
+
dark: green[800]
|
|
34
|
+
},
|
|
35
|
+
grey: { ...gray },
|
|
36
|
+
divider: alpha(gray[300], .4),
|
|
37
|
+
background: {
|
|
38
|
+
default: "hsl(0, 0%, 99%)",
|
|
39
|
+
paper: "hsl(220, 35%, 97%)"
|
|
40
|
+
},
|
|
41
|
+
text: {
|
|
42
|
+
primary: gray[800],
|
|
43
|
+
secondary: gray[600]
|
|
44
|
+
},
|
|
45
|
+
action: {
|
|
46
|
+
hover: alpha(gray[200], .2),
|
|
47
|
+
selected: alpha(gray[200], .3)
|
|
48
|
+
},
|
|
49
|
+
baseShadow: baseShadow.light
|
|
50
|
+
} },
|
|
51
|
+
dark: { palette: {
|
|
52
|
+
primary: {
|
|
53
|
+
light: brand[300],
|
|
54
|
+
main: brand[400],
|
|
55
|
+
dark: brand[700],
|
|
56
|
+
contrastText: brand[50]
|
|
57
|
+
},
|
|
58
|
+
info: {
|
|
59
|
+
light: brand[500],
|
|
60
|
+
main: brand[700],
|
|
61
|
+
dark: brand[900],
|
|
62
|
+
contrastText: brand[300]
|
|
63
|
+
},
|
|
64
|
+
warning: {
|
|
65
|
+
light: orange[400],
|
|
66
|
+
main: orange[500],
|
|
67
|
+
dark: orange[700]
|
|
68
|
+
},
|
|
69
|
+
error: {
|
|
70
|
+
light: red[400],
|
|
71
|
+
main: red[500],
|
|
72
|
+
dark: red[700]
|
|
73
|
+
},
|
|
74
|
+
success: {
|
|
75
|
+
light: green[400],
|
|
76
|
+
main: green[500],
|
|
77
|
+
dark: green[700]
|
|
78
|
+
},
|
|
79
|
+
grey: { ...gray },
|
|
80
|
+
divider: alpha(gray[700], .6),
|
|
81
|
+
background: {
|
|
82
|
+
default: gray[900],
|
|
83
|
+
paper: "hsl(220, 30%, 7%)"
|
|
84
|
+
},
|
|
85
|
+
text: {
|
|
86
|
+
primary: "hsl(0, 0%, 100%)",
|
|
87
|
+
secondary: gray[400]
|
|
88
|
+
},
|
|
89
|
+
action: {
|
|
90
|
+
hover: alpha(gray[600], .2),
|
|
91
|
+
selected: alpha(gray[600], .3)
|
|
92
|
+
},
|
|
93
|
+
baseShadow: baseShadow.dark
|
|
94
|
+
} }
|
|
95
|
+
},
|
|
96
|
+
typography: {
|
|
97
|
+
fontFamily: "Inter, sans-serif",
|
|
98
|
+
h1: {
|
|
99
|
+
fontSize: "3rem",
|
|
100
|
+
fontWeight: 600,
|
|
101
|
+
lineHeight: 1.2,
|
|
102
|
+
letterSpacing: -.5
|
|
103
|
+
},
|
|
104
|
+
h2: {
|
|
105
|
+
fontSize: "2.25rem",
|
|
106
|
+
fontWeight: 600,
|
|
107
|
+
lineHeight: 1.2
|
|
108
|
+
},
|
|
109
|
+
h3: {
|
|
110
|
+
fontSize: "1.875rem",
|
|
111
|
+
lineHeight: 1.2
|
|
112
|
+
},
|
|
113
|
+
h4: {
|
|
114
|
+
fontSize: "1.5rem",
|
|
115
|
+
fontWeight: 600,
|
|
116
|
+
lineHeight: 1.5
|
|
117
|
+
},
|
|
118
|
+
h5: {
|
|
119
|
+
fontSize: "1.25rem",
|
|
120
|
+
fontWeight: 600
|
|
121
|
+
},
|
|
122
|
+
h6: {
|
|
123
|
+
fontSize: "1.125rem",
|
|
124
|
+
fontWeight: 600
|
|
125
|
+
},
|
|
126
|
+
subtitle1: { fontSize: "1.125rem" },
|
|
127
|
+
subtitle2: {
|
|
128
|
+
fontSize: "0.875rem",
|
|
129
|
+
fontWeight: 500
|
|
130
|
+
},
|
|
131
|
+
body1: { fontSize: "0.875rem" },
|
|
132
|
+
body2: {
|
|
133
|
+
fontSize: "0.875rem",
|
|
134
|
+
fontWeight: 400
|
|
135
|
+
},
|
|
136
|
+
caption: {
|
|
137
|
+
fontSize: "0.75rem",
|
|
138
|
+
fontWeight: 400
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
shape: { borderRadius: 8 },
|
|
142
|
+
focusVisible: true,
|
|
143
|
+
components: { MuiButton: {
|
|
144
|
+
defaultProps: { disableElevation: true },
|
|
145
|
+
styleOverrides: { root: { textTransform: "none" } }
|
|
146
|
+
} }
|
|
8
147
|
};
|
|
9
148
|
export { defaultThemeOptions };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color scales for the default theme, taken from `references/theme/themePrimitives.ts`.
|
|
3
|
+
* They're private: components read colors from the theme, never from here.
|
|
4
|
+
*/
|
|
5
|
+
export declare const brand: {
|
|
6
|
+
50: string;
|
|
7
|
+
100: string;
|
|
8
|
+
200: string;
|
|
9
|
+
300: string;
|
|
10
|
+
400: string;
|
|
11
|
+
500: string;
|
|
12
|
+
600: string;
|
|
13
|
+
700: string;
|
|
14
|
+
800: string;
|
|
15
|
+
900: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const gray: {
|
|
18
|
+
50: string;
|
|
19
|
+
100: string;
|
|
20
|
+
200: string;
|
|
21
|
+
300: string;
|
|
22
|
+
400: string;
|
|
23
|
+
500: string;
|
|
24
|
+
600: string;
|
|
25
|
+
700: string;
|
|
26
|
+
800: string;
|
|
27
|
+
900: string;
|
|
28
|
+
};
|
|
29
|
+
export declare const green: {
|
|
30
|
+
50: string;
|
|
31
|
+
100: string;
|
|
32
|
+
200: string;
|
|
33
|
+
300: string;
|
|
34
|
+
400: string;
|
|
35
|
+
500: string;
|
|
36
|
+
600: string;
|
|
37
|
+
700: string;
|
|
38
|
+
800: string;
|
|
39
|
+
900: string;
|
|
40
|
+
};
|
|
41
|
+
export declare const orange: {
|
|
42
|
+
50: string;
|
|
43
|
+
100: string;
|
|
44
|
+
200: string;
|
|
45
|
+
300: string;
|
|
46
|
+
400: string;
|
|
47
|
+
500: string;
|
|
48
|
+
600: string;
|
|
49
|
+
700: string;
|
|
50
|
+
800: string;
|
|
51
|
+
900: string;
|
|
52
|
+
};
|
|
53
|
+
export declare const red: {
|
|
54
|
+
50: string;
|
|
55
|
+
100: string;
|
|
56
|
+
200: string;
|
|
57
|
+
300: string;
|
|
58
|
+
400: string;
|
|
59
|
+
500: string;
|
|
60
|
+
600: string;
|
|
61
|
+
700: string;
|
|
62
|
+
800: string;
|
|
63
|
+
900: string;
|
|
64
|
+
};
|
|
65
|
+
export declare const baseShadow: {
|
|
66
|
+
light: string;
|
|
67
|
+
dark: string;
|
|
68
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/theme/tokens.ts
|
|
2
|
+
/**
|
|
3
|
+
* Color scales for the default theme, taken from `references/theme/themePrimitives.ts`.
|
|
4
|
+
* They're private: components read colors from the theme, never from here.
|
|
5
|
+
*/
|
|
6
|
+
var brand = {
|
|
7
|
+
50: "hsl(210, 100%, 95%)",
|
|
8
|
+
100: "hsl(210, 100%, 92%)",
|
|
9
|
+
200: "hsl(210, 100%, 80%)",
|
|
10
|
+
300: "hsl(210, 100%, 65%)",
|
|
11
|
+
400: "hsl(210, 98%, 48%)",
|
|
12
|
+
500: "hsl(210, 98%, 42%)",
|
|
13
|
+
600: "hsl(210, 98%, 55%)",
|
|
14
|
+
700: "hsl(210, 100%, 35%)",
|
|
15
|
+
800: "hsl(210, 100%, 16%)",
|
|
16
|
+
900: "hsl(210, 100%, 21%)"
|
|
17
|
+
};
|
|
18
|
+
var gray = {
|
|
19
|
+
50: "hsl(220, 35%, 97%)",
|
|
20
|
+
100: "hsl(220, 30%, 94%)",
|
|
21
|
+
200: "hsl(220, 20%, 88%)",
|
|
22
|
+
300: "hsl(220, 20%, 80%)",
|
|
23
|
+
400: "hsl(220, 20%, 65%)",
|
|
24
|
+
500: "hsl(220, 20%, 42%)",
|
|
25
|
+
600: "hsl(220, 20%, 35%)",
|
|
26
|
+
700: "hsl(220, 20%, 25%)",
|
|
27
|
+
800: "hsl(220, 30%, 6%)",
|
|
28
|
+
900: "hsl(220, 35%, 3%)"
|
|
29
|
+
};
|
|
30
|
+
var green = {
|
|
31
|
+
50: "hsl(120, 80%, 98%)",
|
|
32
|
+
100: "hsl(120, 75%, 94%)",
|
|
33
|
+
200: "hsl(120, 75%, 87%)",
|
|
34
|
+
300: "hsl(120, 61%, 77%)",
|
|
35
|
+
400: "hsl(120, 44%, 53%)",
|
|
36
|
+
500: "hsl(120, 59%, 30%)",
|
|
37
|
+
600: "hsl(120, 70%, 25%)",
|
|
38
|
+
700: "hsl(120, 75%, 16%)",
|
|
39
|
+
800: "hsl(120, 84%, 10%)",
|
|
40
|
+
900: "hsl(120, 87%, 6%)"
|
|
41
|
+
};
|
|
42
|
+
var orange = {
|
|
43
|
+
50: "hsl(45, 100%, 97%)",
|
|
44
|
+
100: "hsl(45, 92%, 90%)",
|
|
45
|
+
200: "hsl(45, 94%, 80%)",
|
|
46
|
+
300: "hsl(45, 90%, 65%)",
|
|
47
|
+
400: "hsl(45, 90%, 40%)",
|
|
48
|
+
500: "hsl(45, 90%, 35%)",
|
|
49
|
+
600: "hsl(45, 91%, 25%)",
|
|
50
|
+
700: "hsl(45, 94%, 20%)",
|
|
51
|
+
800: "hsl(45, 95%, 16%)",
|
|
52
|
+
900: "hsl(45, 93%, 12%)"
|
|
53
|
+
};
|
|
54
|
+
var red = {
|
|
55
|
+
50: "hsl(0, 100%, 97%)",
|
|
56
|
+
100: "hsl(0, 92%, 90%)",
|
|
57
|
+
200: "hsl(0, 94%, 80%)",
|
|
58
|
+
300: "hsl(0, 90%, 65%)",
|
|
59
|
+
400: "hsl(0, 90%, 40%)",
|
|
60
|
+
500: "hsl(0, 90%, 30%)",
|
|
61
|
+
600: "hsl(0, 91%, 25%)",
|
|
62
|
+
700: "hsl(0, 94%, 18%)",
|
|
63
|
+
800: "hsl(0, 95%, 12%)",
|
|
64
|
+
900: "hsl(0, 93%, 6%)"
|
|
65
|
+
};
|
|
66
|
+
var baseShadow = {
|
|
67
|
+
light: "hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px",
|
|
68
|
+
dark: "hsla(220, 30%, 5%, 0.7) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.8) 0px 8px 16px -5px"
|
|
69
|
+
};
|
|
70
|
+
export { baseShadow, brand, gray, green, orange, red };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmotino/cm-web-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "storybook dev -p 6006",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@emotion/react": "^11.14.0",
|
|
21
21
|
"@emotion/styled": "^11.14.1",
|
|
22
22
|
"@eslint/js": "^10.0.1",
|
|
23
|
-
"@fontsource/
|
|
23
|
+
"@fontsource/inter": "^5.3.0",
|
|
24
24
|
"@mui/icons-material": "^9.5.0",
|
|
25
25
|
"@mui/material": "^9.5.0",
|
|
26
26
|
"@rolldown/plugin-babel": "^0.3.0",
|