react-mcu 1.0.0 → 1.0.2

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 CHANGED
@@ -1,39 +1,58 @@
1
- # react-mcu
1
+ [![npm version](https://img.shields.io/npm/v/react-mcu.svg)](https://www.npmjs.com/package/react-mcu)
2
+ [![](https://img.shields.io/badge/chromatic-171c23.svg?logo=chromatic)](https://www.chromatic.com/library?appId=695eb517cb602e59b4cc045c&branch=main)
2
3
 
3
- A React component library.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install react-mcu
9
- ```
10
-
11
- ## Usage
4
+ Usage:
12
5
 
13
6
  ```tsx
14
- import { Mcu } from 'react-mcu';
15
-
16
- function App() {
17
- return <Mcu />;
18
- }
7
+ import { Mcu } from "react-mcu";
8
+
9
+ <Mcu
10
+ source="#0e1216"
11
+ scheme="vibrant"
12
+ contrast={0.5}
13
+ customColors=[]
14
+ >
15
+ <div style={{
16
+ backgroundColor: "var(--mcu-surface)",
17
+ color: "var(--mcu-on-surface)",
18
+ }}>
19
+ Hello, MCU colors!
20
+ </div>
21
+ </Mcu>
19
22
  ```
20
23
 
21
- ## Components
22
-
23
- ### Mcu
24
-
25
- A simple component that renders "Hello World".
26
-
27
- ```tsx
28
- <Mcu />
24
+ # Dev
25
+
26
+ ## INSTALL
27
+
28
+ Pre-requisites:
29
+
30
+ - Install [nvm](https://github.com/nvm-sh/nvm), then:
31
+ ```sh
32
+ $ nvm install
33
+ $ nvm use
34
+ $ node -v # make sure your version satisfies package.json#engines.node
35
+ ```
36
+ nb: if you want this node version to be your default nvm's one:
37
+ `nvm alias default node`
38
+ - Install pnpm, with:
39
+ ```sh
40
+ $ corepack enable
41
+ $ corepack prepare --activate # it reads "packageManager"
42
+ $ pnpm -v # make sure your version satisfies package.json#engines.pnpm
43
+ ```
44
+
45
+ ```sh
46
+ $ pnpm i
29
47
  ```
30
48
 
31
- ## Contributing
49
+ ## CONTRIBUTING
32
50
 
33
- When submitting a pull request, please include a changeset to document your changes:
51
+ When submitting a pull request, please include a changeset to document your
52
+ changes:
34
53
 
35
54
  ```bash
36
- npx changeset
55
+ pnpm exec changeset
37
56
  ```
38
57
 
39
58
  This helps us maintain the changelog and version the package appropriately.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,28 @@
1
- interface McuProps {
2
- }
3
- declare const Mcu: React.FC<McuProps>;
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SchemeTonalSpot, SchemeMonochrome, SchemeNeutral, SchemeVibrant, SchemeExpressive, SchemeFidelity, SchemeContent, CustomColor } from '@material/material-color-utilities';
4
3
 
5
- export { Mcu, type McuProps };
4
+ type HexCustomColor = Omit<CustomColor, "value"> & {
5
+ hex: string;
6
+ };
7
+ type McuConfig = {
8
+ source: string;
9
+ scheme: SchemeName;
10
+ contrast: number;
11
+ customColors: HexCustomColor[];
12
+ };
13
+ declare const schemesMap: {
14
+ readonly tonalSpot: typeof SchemeTonalSpot;
15
+ readonly monochrome: typeof SchemeMonochrome;
16
+ readonly neutral: typeof SchemeNeutral;
17
+ readonly vibrant: typeof SchemeVibrant;
18
+ readonly expressive: typeof SchemeExpressive;
19
+ readonly fidelity: typeof SchemeFidelity;
20
+ readonly content: typeof SchemeContent;
21
+ };
22
+ declare const schemeNames: (keyof typeof schemesMap)[];
23
+ type SchemeName = (typeof schemeNames)[number];
24
+ declare function Mcu({ source, scheme, contrast, customColors, children, }: McuConfig & {
25
+ children: React.ReactNode;
26
+ }): react_jsx_runtime.JSX.Element;
27
+
28
+ export { Mcu };
package/dist/index.js CHANGED
@@ -1,8 +1,248 @@
1
1
  // src/Mcu.tsx
2
+ import {
3
+ argbFromHex,
4
+ Hct,
5
+ hexFromArgb as hexFromArgb2,
6
+ MaterialDynamicColors,
7
+ SchemeContent,
8
+ SchemeExpressive,
9
+ SchemeFidelity,
10
+ SchemeMonochrome,
11
+ SchemeNeutral,
12
+ SchemeTonalSpot,
13
+ SchemeVibrant
14
+ } from "@material/material-color-utilities";
15
+ import { kebabCase } from "lodash-es";
16
+ import { useMemo as useMemo2 } from "react";
17
+
18
+ // src/Mcu.context.tsx
19
+ import { hexFromArgb } from "@material/material-color-utilities";
20
+ import {
21
+ useCallback,
22
+ useInsertionEffect,
23
+ useMemo,
24
+ useState
25
+ } from "react";
26
+
27
+ // src/lib/createRequiredContext.ts
28
+ import { createContext, useContext } from "react";
29
+ var createRequiredContext = () => {
30
+ const Ctx = createContext(null);
31
+ const useCtx = () => {
32
+ const contextValue = useContext(Ctx);
33
+ if (contextValue === null) {
34
+ throw new Error("Context value is null");
35
+ }
36
+ return contextValue;
37
+ };
38
+ return [useCtx, Ctx.Provider, Ctx];
39
+ };
40
+
41
+ // src/Mcu.context.tsx
2
42
  import { jsx } from "react/jsx-runtime";
3
- var Mcu = () => {
4
- return /* @__PURE__ */ jsx("div", { children: "Hello World" });
43
+ var [useMcu, Provider, McuContext] = createRequiredContext();
44
+ var McuProvider = ({
45
+ source: initialSource,
46
+ scheme: initialScheme,
47
+ contrast: initialContrast,
48
+ customColors: initialCustomColors,
49
+ styleId,
50
+ children
51
+ }) => {
52
+ const [initials] = useState(() => ({
53
+ source: initialSource,
54
+ scheme: initialScheme,
55
+ contrast: initialContrast,
56
+ customColors: initialCustomColors
57
+ }));
58
+ const [mcuConfig, setMcuConfig] = useState(initials);
59
+ const { css, mergedColorsLight, mergedColorsDark } = useMemo(
60
+ () => generateCss(mcuConfig),
61
+ [mcuConfig]
62
+ );
63
+ useInsertionEffect(() => {
64
+ let tag = document.getElementById(styleId);
65
+ if (!tag) {
66
+ tag = document.createElement("style");
67
+ tag.id = styleId;
68
+ document.head.appendChild(tag);
69
+ }
70
+ tag.textContent = css;
71
+ }, [css, styleId]);
72
+ const getMcuColor = useCallback(
73
+ (colorName, theme) => {
74
+ return hexFromArgb(
75
+ (theme === "light" ? mergedColorsLight : mergedColorsDark)[colorName]
76
+ );
77
+ },
78
+ [mergedColorsDark, mergedColorsLight]
79
+ );
80
+ const value = useMemo(
81
+ () => ({
82
+ initials,
83
+ setMcuConfig,
84
+ getMcuColor
85
+ }),
86
+ [getMcuColor, initials]
87
+ );
88
+ return /* @__PURE__ */ jsx(Provider, { value, children });
89
+ };
90
+
91
+ // src/Mcu.tsx
92
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
93
+ var schemesMap = {
94
+ tonalSpot: SchemeTonalSpot,
95
+ monochrome: SchemeMonochrome,
96
+ neutral: SchemeNeutral,
97
+ vibrant: SchemeVibrant,
98
+ expressive: SchemeExpressive,
99
+ fidelity: SchemeFidelity,
100
+ content: SchemeContent
101
+ };
102
+ var schemeNames = Object.keys(
103
+ schemesMap
104
+ );
105
+ var mcuStyleId = "mcu-styles";
106
+ function Mcu({
107
+ source,
108
+ scheme,
109
+ contrast,
110
+ customColors,
111
+ children
112
+ }) {
113
+ const config = useMemo2(
114
+ () => ({
115
+ source,
116
+ scheme,
117
+ contrast,
118
+ customColors
119
+ }),
120
+ [contrast, customColors, scheme, source]
121
+ );
122
+ const { css } = useMemo2(() => generateCss(config), [config]);
123
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
124
+ /* @__PURE__ */ jsx2("style", { id: mcuStyleId, children: css }),
125
+ /* @__PURE__ */ jsx2(McuProvider, { ...config, styleId: mcuStyleId, children })
126
+ ] });
127
+ }
128
+ var tokenNames = [
129
+ "background",
130
+ "onBackground",
131
+ "surface",
132
+ "surfaceDim",
133
+ "surfaceBright",
134
+ "surfaceContainerLowest",
135
+ "surfaceContainerLow",
136
+ "surfaceContainer",
137
+ "surfaceContainerHigh",
138
+ "surfaceContainerHighest",
139
+ "onSurface",
140
+ "onSurfaceVariant",
141
+ "outline",
142
+ "outlineVariant",
143
+ "inverseSurface",
144
+ "inverseOnSurface",
145
+ "primary",
146
+ // "primaryDim",
147
+ "onPrimary",
148
+ "primaryContainer",
149
+ "onPrimaryContainer",
150
+ "primaryFixed",
151
+ "primaryFixedDim",
152
+ "onPrimaryFixed",
153
+ "onPrimaryFixedVariant",
154
+ "inversePrimary",
155
+ "primaryFixed",
156
+ "primaryFixedDim",
157
+ "onPrimaryFixed",
158
+ "onPrimaryFixedVariant",
159
+ "secondary",
160
+ // "secondaryDim",
161
+ "onSecondary",
162
+ "secondaryContainer",
163
+ "onSecondaryContainer",
164
+ "secondaryFixed",
165
+ "secondaryFixedDim",
166
+ "onSecondaryFixed",
167
+ "onSecondaryFixedVariant",
168
+ "tertiary",
169
+ // "tertiaryDim",
170
+ "onTertiary",
171
+ "tertiaryContainer",
172
+ "onTertiaryContainer",
173
+ "tertiaryFixed",
174
+ "tertiaryFixedDim",
175
+ "onTertiaryFixed",
176
+ "onTertiaryFixedVariant",
177
+ "error",
178
+ // "errorDim",
179
+ "onError",
180
+ "errorContainer",
181
+ "onErrorContainer",
182
+ "scrim",
183
+ // added manually, was missing
184
+ "shadow"
185
+ // added manually, was missing
186
+ ];
187
+ function toRecord(arr, getEntry) {
188
+ return arr.reduce(
189
+ (acc, item) => {
190
+ const [key, value] = getEntry(item);
191
+ acc[key] = value;
192
+ return acc;
193
+ },
194
+ {}
195
+ );
196
+ }
197
+ function mergeBaseAndCustomColors(scheme, customColors) {
198
+ const baseVars = toRecord(tokenNames, (tokenName) => {
199
+ const dynamicColor = MaterialDynamicColors[tokenName];
200
+ const argb = dynamicColor.getArgb(scheme);
201
+ return [tokenName, argb];
202
+ });
203
+ const customVars = toRecord(customColors, (color) => [
204
+ color.name,
205
+ color.value
206
+ ]);
207
+ return { ...baseVars, ...customVars };
208
+ }
209
+ var cssVar = (colorName, colorValue) => {
210
+ const name = `--mcu-${kebabCase(colorName)}`;
211
+ const value = hexFromArgb2(colorValue);
212
+ return `${name}:${value};`;
213
+ };
214
+ var toCssVars = (mergedColors) => {
215
+ return Object.entries(mergedColors).map(([name, value]) => cssVar(name, value)).join(" ");
5
216
  };
217
+ function generateCss({
218
+ source: hexSource,
219
+ customColors: hexCustomColors,
220
+ scheme,
221
+ contrast
222
+ }) {
223
+ console.log("MCU generateCss");
224
+ const sourceArgb = argbFromHex(hexSource);
225
+ const hct = Hct.fromInt(sourceArgb);
226
+ const SchemeClass = schemesMap[scheme];
227
+ const lightScheme = new SchemeClass(hct, false, contrast);
228
+ const darkScheme = new SchemeClass(hct, true, contrast);
229
+ const customColors = hexCustomColors.map(({ hex, ...rest }) => ({
230
+ ...rest,
231
+ value: argbFromHex(hex)
232
+ }));
233
+ const mergedColorsLight = mergeBaseAndCustomColors(lightScheme, customColors);
234
+ const mergedColorsDark = mergeBaseAndCustomColors(darkScheme, customColors);
235
+ const lightVars = toCssVars(mergedColorsLight);
236
+ const darkVars = toCssVars(mergedColorsDark);
237
+ return {
238
+ css: `
239
+ :root { ${lightVars} }
240
+ .dark { ${darkVars} }
241
+ `,
242
+ mergedColorsLight,
243
+ mergedColorsDark
244
+ };
245
+ }
6
246
  export {
7
247
  Mcu
8
248
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-mcu",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A React component library",
5
5
  "keywords": [
6
6
  "react",
@@ -28,34 +28,47 @@
28
28
  ],
29
29
  "type": "module",
30
30
  "devDependencies": {
31
- "@arethetypeswrong/cli": "^0.15.4",
31
+ "@arethetypeswrong/cli": "^0.18.2",
32
32
  "@changesets/cli": "^2.27.7",
33
+ "@storybook/react-vite": "^10.1.11",
33
34
  "@testing-library/dom": "^10.4.1",
34
35
  "@testing-library/react": "^16.3.1",
36
+ "@types/lodash-es": "^4.17.12",
35
37
  "@types/react": "^19.2.7",
36
38
  "@types/react-dom": "^19.2.3",
37
39
  "@vitejs/plugin-react": "^5.1.2",
40
+ "chromatic": "^13.3.5",
41
+ "husky": "^9.1.7",
38
42
  "jsdom": "^27.4.0",
43
+ "lint-staged": "^16.2.7",
39
44
  "prettier": "^3.3.3",
40
45
  "react": "^19.2.3",
41
46
  "react-dom": "^19.2.3",
47
+ "storybook": "^10.1.11",
42
48
  "tsup": "^8.2.4",
43
49
  "typescript": "^5.5.4",
44
- "vitest": "^2.0.5"
50
+ "vitest": "^4.0.16"
51
+ },
52
+ "peerDependencies": {
53
+ "react": "^19.2.3",
54
+ "react-dom": "^19.2.3"
55
+ },
56
+ "dependencies": {
57
+ "@material/material-color-utilities": "^0.3.0",
58
+ "lodash-es": "^4.17.22"
45
59
  },
46
60
  "scripts": {
47
61
  "build": "tsup",
48
- "ci": "npm run build && npm run check-format && npm run check-exports && npm run lint && npm run test",
62
+ "ci": "pnpm run build && pnpm run check-format && pnpm run check-exports && pnpm run lint && pnpm run test",
49
63
  "lint": "tsc",
50
64
  "test": "vitest run",
51
65
  "format": "prettier --write .",
52
66
  "check-format": "prettier --check .",
53
67
  "check-exports": "attw --pack . --ignore-rules cjs-resolves-to-esm no-resolution",
54
- "release": "npm run build && changeset publish",
55
- "local-release": "npm run ci && changeset version && changeset publish"
56
- },
57
- "peerDependencies": {
58
- "react": "^19.2.3",
59
- "react-dom": "^19.2.3"
68
+ "release": "pnpm run build && changeset publish",
69
+ "local-release": "pnpm run ci && changeset version && changeset publish",
70
+ "storybook": "storybook dev -p 6006",
71
+ "build-storybook": "storybook build",
72
+ "chromatic": "chromatic --project-token $CHROMATIC_PROJECT_TOKEN"
60
73
  }
61
- }
74
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) Matt Pocock 2024
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.