Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Mantine #210

Merged
merged 5 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/create-next-stack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The table below provides an overview of the technologies currently supported by
| Sass | [Website](https://sass-lang.com/) - [Docs](https://sass-lang.com/documentation) - [Next.js-specific docs](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support) |
| CSS Modules | [Website](https://github.com/css-modules/css-modules) - [Docs](https://github.com/css-modules/css-modules) - [Next.js-specific docs](https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css) |
| CSS Modules | [Website](https://github.com/css-modules/css-modules) - [Docs](https://github.com/css-modules/css-modules) - [Next.js-specific docs](https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css) |
| Mantine | [Website](https://mantine.dev/) - [Docs](https://mantine.dev/pages/getting-started/) - [GitHub](https://github.com/mantinedev/mantine) |
| Chakra UI | [Website](https://chakra-ui.com/) - [Docs](https://chakra-ui.com/docs/getting-started) - [GitHub](https://github.com/chakra-ui/chakra-ui) |
| Material UI | [Website](https://material-ui.com/) - [Docs](https://material-ui.com/getting-started/installation/) - [GitHub](https://github.com/mui-org/material-ui) |
| Framer Motion | [Website](https://www.framer.com/motion/) - [Docs](https://www.framer.com/docs/) - [GitHub](https://github.com/framer/motion) |
Expand Down Expand Up @@ -89,7 +90,10 @@ FLAGS
--framer-motion Adds Framer Motion. (Animation library)
--github-actions Adds a GitHub Actions continuous integration
workflow.
--material-ui Adds Material UI. (Component library)
--mantine Adds Mantine. (Component library) (Requires
Emotion)
--material-ui Adds Material UI. (Component library) (Requires
Emotion)
--package-manager=<option> (required) Sets the preferred package manager.
(Required)
<options: pnpm|yarn|npm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ export default class CreateNextStack extends Command {
description:
"Adds Chakra UI. (Component library) (Requires Emotion and Framer Motion)",
}),

"material-ui": Flags.boolean({
description: "Adds Material UI. (Component library)",
description: "Adds Material UI. (Component library) (Requires Emotion)",
}),
mantine: Flags.boolean({
description: "Adds Mantine. (Component library) (Requires Emotion)",
}),

// Form libraries:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ export const validateFlags = (
"Chakra UI (category: Component library, flag: --chakra) requires Emotion (category: Styling, flag: --styling=emotion)."
)
}
if (flags.mantine && flags.styling !== "emotion") {
throw new Error(
"Mantine (category: Component library, flag: --mantine) requires Emotion (category: Styling, flag: --styling=emotion)."
)
}
if (flags["material-ui"] && flags.styling !== "emotion") {
throw new Error(
"Material UI (category: Component library, flag: --material-ui) requires Emotion (category: Styling, flag: --styling=emotion)."
Expand Down
6 changes: 6 additions & 0 deletions packages/create-next-stack/src/main/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ type PluginConfig = DeeplyReadonly<{
document?: {
/** Code to add to the imports section of the _document.tsx file. */
imports?: string
/** Code to add after the imports section of the _document.tsx file. */
afterImports?: string
/** Code to add to the class members of the Document class in _document.tsx file. */
classMembers?: string
/** Code to add before the return statement of the Document render function in _document.tsx file. */
renderLogic?: string
/** Code to add to the attributes of the <Html> tag of the _document.tsx file. */
htmlAttributes?: string
/** Code to add to the <Head> tag of the _document.tsx file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ export const generateDocument = (inputs: ValidCNSInputs): string => {
.map((plugin) => plugin.slots?.document?.imports)
.filter(nonNull)
.join("\n")
const afterImports = filterPlugins(inputs)
.map((plugin) => plugin.slots?.document?.afterImports)
.filter(nonNull)
.join("\n")
const classMembers = filterPlugins(inputs)
.map((plugin) => plugin.slots?.document?.classMembers)
.filter(nonNull)
.join("\n")
const renderLogic = filterPlugins(inputs)
.map((plugin) => plugin.slots?.document?.renderLogic)
.filter(nonNull)
.join("\n")
const htmlAttributes = filterPlugins(inputs)
.map((plugin) => plugin.slots?.document?.htmlAttributes)
.filter(nonNull)
Expand All @@ -25,8 +37,13 @@ export const generateDocument = (inputs: ValidCNSInputs): string => {
import NextDocument, { Html, Head, Main, NextScript } from "next/document";
${imports}

${afterImports}

export default class Document extends NextDocument {
${classMembers}

render() {
${renderLogic}
return (
<Html lang="en" ${htmlAttributes}>
<Head>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"tailwindCSS",
"sass",
"cssModules",
"mantine",
"chakraUI",
"materialUI",
"framerMotion",
Expand All @@ -36,7 +37,7 @@
return filterPlugins(inputs)
.flatMap((plugin) => plugin.technologies ?? [])
.sort((a, b) => compareByOrder(a.id, b.id, technologiesSortOrder))
.map(({ id, ...rest }) => ({

Check warning on line 40 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - ubuntu-latest

'id' is defined but never used

Check warning on line 40 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - windows-latest

'id' is defined but never used

Check warning on line 40 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - macOS-latest

'id' is defined but never used
...rest,
}))
}
Expand All @@ -47,7 +48,7 @@
return plugins
.flatMap((plugin) => plugin.technologies ?? [])
.sort((a, b) => compareByOrder(a.id, b.id, technologiesSortOrder))
.map(({ id, ...rest }) => ({

Check warning on line 51 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - ubuntu-latest

'id' is defined but never used

Check warning on line 51 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - windows-latest

'id' is defined but never used

Check warning on line 51 in packages/create-next-stack/src/main/plugins/create-next-stack/sort-orders/technologies.ts

View workflow job for this annotation

GitHub Actions / Build, lint, test - macOS-latest

'id' is defined but never used
...rest,
}))
}
80 changes: 80 additions & 0 deletions packages/create-next-stack/src/main/plugins/mantine/mantine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import endent from "endent"
import { writeFile } from "../../helpers/io"
import { createPlugin } from "../../plugin"
import { mantineTheme } from "./setup/mantine-theme"

export const mantinePlugin = createPlugin({
id: "mantine",
name: "Mantine",
description: "Adds support for Mantine",
active: ({ flags }) => Boolean(flags.mantine),
dependencies: {
"@mantine/core": {
name: "@mantine/core",
version: "^6.0.0",
},
"@mantine/hooks": {
name: "@mantine/hooks",
version: "^6.0.0",
},
"@mantine/next": {
name: "@mantine/next",
version: "^6.0.0",
},
"@emotion/server": {
name: "@emotion/server",
version: "^11.0.0",
},
},
technologies: [
{
id: "mantine",
name: "Mantine",
description:
"Mantine is a fully featured React component library. Aside from the core package, Mantine also provides additional packages for utility hooks, form state management, date inputs and calendars, notifications, code highlighting, right text editor, and the list goes on.",
links: [
{ title: "Website", url: "https://mantine.dev/" },
{ title: "Docs", url: "https://mantine.dev/pages/getting-started/" },
{ title: "GitHub", url: "https://github.com/mantinedev/mantine" },
],
},
],
steps: {
setUpMantine: {
id: "setUpMantine",
description: "setting up Mantine",
run: async () => {
await writeFile("mantine-theme.ts", mantineTheme)
},
},
},
slots: {
app: {
imports: endent`
import { MantineProvider } from '@mantine/core';
import { mantineTheme } from "../mantine-theme";
`,
componentsStart: endent`
<MantineProvider
withGlobalStyles
withNormalizeCSS
theme={mantineTheme}
>
`,
componentsEnd: endent`
</MantineProvider>
`,
},
document: {
imports: endent`
import { createGetInitialProps } from '@mantine/next';
`,
afterImports: endent`
const getInitialProps = createGetInitialProps();
`,
classMembers: endent`
static getInitialProps = getInitialProps;
`,
},
},
} as const)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import endent from "endent"

export const mantineTheme = endent`
import { MantineThemeOverride } from "@mantine/core";

export const mantineTheme: MantineThemeOverride = {
colorScheme: "light",
};
`
2 changes: 1 addition & 1 deletion packages/create-next-stack/src/main/plugins/react-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const reactQueryPlugin = createPlugin({
id: "reactQuery",
name: "React Query",
description:
"React Query is a data fetching library for React. It provides hooks for fetching, caching, and updating asynchronous data in React. It is designed to be flexible and composable, and can be used with any data source.",
"React Query, aka. TanStack Query, is a data fetching library that provides hooks for fetching, caching, and updating, remote data. It has a declarative API that makes working with asynchronous data much easier than with previous solutions.",
links: [
{ title: "Website", url: "https://tanstack.com/query/latest" },
{
Expand Down
9 changes: 4 additions & 5 deletions packages/create-next-stack/src/main/setup/plugins.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import { plugins } from "./setup"
test("`plugins` contains no duplicates", () => {
const seenPluginIDs = new Set<string>()
for (const plugin of plugins) {
if (seenPluginIDs.has(plugin.id)) {
throw new Error(
`Duplicate plugin with ID "${plugin.id}" found in setup.ts`
)
const { id } = plugin
if (seenPluginIDs.has(id)) {
throw new Error(`Duplicate plugin with ID "${id}" found in setup.ts`)
}
seenPluginIDs.add(plugin.id)
seenPluginIDs.add(id)
}
})
2 changes: 2 additions & 0 deletions packages/create-next-stack/src/main/setup/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { formattingPreCommitHookPlugin } from "../plugins/formatting-pre-commit-
import { formikPlugin } from "../plugins/formik"
import { framerMotionPlugin } from "../plugins/framer-motion"
import { githubActionsPlugin } from "../plugins/github-actions"
import { mantinePlugin } from "../plugins/mantine/mantine"
import { materialUIPlugin } from "../plugins/material-ui/material-ui"
import { nextPlugin } from "../plugins/next"
import { npmPlugin } from "../plugins/npm"
Expand Down Expand Up @@ -42,6 +43,7 @@ export const plugins: Plugin[] = [
tailwindCSSPlugin,
cssModulesPlugin,
sassPlugin,
mantinePlugin,
chakraUIPlugin,
materialUIPlugin,
reactHookFormPlugin,
Expand Down
28 changes: 28 additions & 0 deletions packages/create-next-stack/src/main/steps.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { test } from "@jest/globals"
import { plugins } from "./setup/setup"
import { steps } from "./steps"

test("`steps` contains no duplicates", () => {
const seenSteps = new Set<string>()
for (const step of steps) {
const { id } = step
if (seenSteps.has(id)) {
throw new Error(`Duplicate step with ID "${id}" found in steps.ts`)
}
seenSteps.add(id)
}
})

test("`steps` includes all plugins' steps", () => {
const requiredStepIDs = plugins.flatMap((plugin) =>
plugin.steps //
? Object.values(plugin.steps).map((step) => step.id)
: []
)
const actualStepIDs = new Set(steps.map((step) => step.id))
for (const requiredStepID of requiredStepIDs) {
if (!actualStepIDs.has(requiredStepID)) {
throw new Error(`Missing step with ID "${requiredStepID}" in steps.ts`)
}
}
})
2 changes: 2 additions & 0 deletions packages/create-next-stack/src/main/steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cssModulesPlugin } from "./plugins/css-modules/css-modules"
import { emotionPlugin } from "./plugins/emotion"
import { formattingPreCommitHookPlugin } from "./plugins/formatting-pre-commit-hook"
import { githubActionsPlugin } from "./plugins/github-actions"
import { mantinePlugin } from "./plugins/mantine/mantine"
import { materialUIPlugin } from "./plugins/material-ui/material-ui"
import { nextPlugin } from "./plugins/next"
import { pnpmPlugin } from "./plugins/pnpm"
Expand Down Expand Up @@ -49,6 +50,7 @@ export const steps: Step[] = [
createNextStackPlugin.steps.addReadme,

// Component libraries
mantinePlugin.steps.setUpMantine,
chakraUIPlugin.steps.setUpChakraUI,
materialUIPlugin.steps.setUpMaterialUI,

Expand Down
3 changes: 2 additions & 1 deletion packages/create-next-stack/src/tests/e2e/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { testInvalidInputs } from "./tests/test-invalid-inputs"
import { testNoAppName } from "./tests/test-no-app-name"
import { testNoFlags } from "./tests/test-no-flags"
import { testNpm } from "./tests/test-npm"
import { testPnpm } from "./tests/test-pnpm"
import { testVersionFlag } from "./tests/test-version-flag"
import { testYarn } from "./tests/test-yarn"
;(async () => {
Expand All @@ -42,7 +43,7 @@ import { testYarn } from "./tests/test-yarn"
await testNoAppName(createNextStackDir)

// Package manager tests
// pnpm is used in all other tests, so not tested here.
await testPnpm(createNextStackDir)
await testNpm(createNextStackDir)
await testYarn(createNextStackDir)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const testCssModulesWithSassAllFlags = async (
"--framer-motion",
"--formatting-pre-commit-hook",
"--react-icons",
"--react-query",
".",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const testCssModulesAllFlags = async (
"--framer-motion",
"--formatting-pre-commit-hook",
"--react-icons",
"--react-query",
".",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export const testEmotionAllFlags = async (
const args = [
"--debug",
"--package-manager=pnpm",
"--prettier",
"--styling=emotion",
"--mantine",
"--chakra",
"--material-ui",
"--react-hook-form",
"--formik",
"--framer-motion",
"--prettier",
"--formatting-pre-commit-hook",
"--chakra",
"--react-icons",
"--react-query",
".",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const testStyledComponentsAllFlags = async (
"--framer-motion",
"--formatting-pre-commit-hook",
"--react-icons",
"--react-query",
".",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const testTailwindCssAllFlags = async (
"--framer-motion",
"--formatting-pre-commit-hook",
"--react-icons",
"--react-query",
".",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ export const testInvalidInputs = async (
],
noStyling: ["--package-manager=npm"],
noPackageManager: ["--styling=css-modules"],
preCommitHookRequiresPrettier: [
preCommitHookWithoutPrettier: [
"--package-manager=pnpm",
"--styling=css-modules",
"--formatting-pre-commit-hook",
],
mantineWithoutEmotion: [
"--package-manager=pnpm",
"--styling=css-modules",
"--mantine",
],
chakraWithoutEmotion: [
"--package-manager=pnpm",
"--styling=css-modules",
Expand Down
7 changes: 5 additions & 2 deletions packages/create-next-stack/src/tests/e2e/tests/test-npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ export const testNpm = async (createNextStackDir: string): Promise<void> => {
const args = [
"--debug",
"--package-manager=npm",
"--prettier",
"--styling=emotion",
"--mantine",
"--chakra",
"--material-ui",
"--react-hook-form",
"--formik",
"--framer-motion",
"--prettier",
"--formatting-pre-commit-hook",
"--chakra",
"--react-icons",
"--react-query",
".",
]

Expand Down
Loading