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

createPalette - Remix - SyntaxError: Cannot use import statement outside a module #33001

Closed
2 tasks done
JeffBaumgardt opened this issue Jun 2, 2022 · 2 comments
Closed
2 tasks done
Labels
customization: theme Centered around the theming features package: system Specific to @mui/system

Comments

@JeffBaumgardt
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

Building a ssr app in Remix I have a fully custom theme and for the palette I use the createPalette function. In there I do lots of overrides and additions. What I have works as expected in Create React App and I can assume it's webpack doing the magic there with babel.

The error when starting Remix dev

/Users/jeffbaumgardt/Projects/dashboard-remix/node_modules/@mui/material/styles/createPalette.js:1
import _extends from "@babel/runtime/helpers/esm/extends";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:355:18)
    at wrapSafe (node:internal/modules/cjs/loader:1022:15)
    at Module._compile (node:internal/modules/cjs/loader:1056:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:996:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at Object.<anonymous> (/Users/jeffbaumgardt/Projects/dashboard-remix/app/style/theme.ts:2:27)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)

If I do not use createPalette and just pass a generic palette object to the theme it works as expected.

Expected behavior 🤔

I assume the issue is with the babel import, since that's the error it calls out in the stack. But I would assume createPalette to work outside a module or whatever is needed. I am using the @latest of all @mui packages and @emotion. I have not included babel in my project.

The basic example I can provide is:

import {createTheme} from '@mui/material'
import createPalette from '@mui/material/styles/createPalette'

export const theme = createTheme({
    palette: createPalette({
        primary: {
            main: '#3f51b5',
            light: '#7986cb',
            dark: '#303f9f',
        },
    }),
})

Naïve example but I'm doing much more in my use case by adding many more colors and changing existing palette colors to my design theme.

Steps to reproduce 🕹

Steps:

  1. Create a remix app npx create-remix follow prompts
  2. Install all necessary @mui + @emotion packages to add a ThemeProvider and theme.
  3. Add ThemeProvider to entry.client and entry.server as per example Remix-with-typescript Example
  4. Create a new theme as per example above using createPalette.
  5. npm run dev - open browser to provided uri
  6. Notice error
  7. Go back to theme and remove createPalette import and modify createTheme to a generic palette object per official remix example
  8. Refresh browser and notice the error is removed.

Context 🔦

In a broader scope this is my built theme that I'm am using, in production in CRA.

import createPalette from '@mui/material/styles/createPalette'
import type { PaletteColorOptions, Palette, PaletteOptions } from '@mui/material';
import designTokens from './designTokens.json'

type SimpleDesignTokenColor = {value: string; type: string}
type DesignTokenColor = {
    Main: {value: string; type: string}
    Light?: {value: string; type: string}
    Dark?: {value: string; type: string}
}

type Color = keyof typeof designTokens.Color
// Hardcoded colors based in the design tokens, very hard to read in automatically.
type CustomPaletteColors = 'white' | 'midnightPurple' | 'gray' | 'teal' | 'yellow' | 'brightBlue' | 'brightGreen' | 'red'
type CustomPalette = Record<CustomPaletteColors, PaletteColorOptions>

const tokenColors = Object.keys(designTokens.Color) as Color[]

const customPalette = tokenColors.reduce((prev, curr) => {
    const colorName = (curr[0].toLowerCase() + curr.slice(1)) as CustomPaletteColors

    if (!prev[colorName]) {
        let main = ''
        let light = ''
        let dark = ''
        if ((designTokens.Color[curr] as SimpleDesignTokenColor).value) {
            main = (designTokens.Color[curr] as SimpleDesignTokenColor).value
        } else {
            const designTokenColor = designTokens.Color[curr] as DesignTokenColor
            if (designTokenColor.Main) {
                main = designTokenColor.Main.value
            }
            if (designTokenColor.Light) {
                light = designTokenColor.Light.value
            }
            if (designTokenColor.Dark) {
                dark = designTokenColor.Dark.value
            }
        }
        prev[colorName] = {
            main,
            light,
            dark,
        }
    }

    return prev
}, {} as CustomPalette)

const palette = createPalette({
    ...customPalette,

    primary: {
        main: designTokens.Theme.Primary.Main.value,
        light: designTokens.Theme.Primary.Light.value,
    },
    warning: {
        main: designTokens.Theme.Warning.Main.value,
        light: designTokens.Theme.Warning.Light.value,
    },
    info: {
        main: designTokens.Theme.Info.Main.value,
        light: designTokens.Theme.Info.Light.value,
    },
    success: {
        main: designTokens.Theme.Success.Main.value,
    },
    error: {
        main: designTokens.Theme.Error.Main.value,
        light: designTokens.Theme.Error.Light.value,
    },
    text: {
        primary: designTokens.Theme.Text.Primary.value,
        secondary: designTokens.Theme.Text.Secondary.value,
    },
    divider: designTokens.Theme.Divider.value,
    background: {
        paper: designTokens.Theme.Background.Paper.value,
        default: designTokens.Theme.Background.Default.value,
    },
})

export default palette
export interface VisionPalette extends Palette {
    white: Palette['primary']
    midnightPurple: Palette['primary']
    gray: Palette['primary']
    teal: Palette['primary']
    yellow: Palette['primary']
    brightBlue: Palette['primary']
    brightGreen: Palette['primary']
    red: Palette['primary']
}
export interface VisionPaletteOptions extends PaletteOptions {
    white: PaletteOptions['primary']
    midnightPurple: PaletteOptions['primary']
    gray: PaletteOptions['primary']
    teal: PaletteOptions['primary']
    yellow: PaletteOptions['primary']
    brightBlue: PaletteOptions['primary']
    birghtGreen: PaletteOptions['primary']
    red: PaletteOptions['primary']
}

declare module '@mui/material/styles/createPalette' {
    export interface Palette {
        white: Palette['primary']
        midnightPurple: Palette['primary']
        gray: Palette['primary']
        teal: Palette['primary']
        yellow: Palette['primary']
        brightBlue: Palette['primary']
        brightGreen: Palette['primary']
        red: Palette['primary']
    }
    export interface PaletteOptions {
        white: PaletteOptions['primary']
        midnightPurple: PaletteOptions['primary']
        gray: PaletteOptions['primary']
        teal: PaletteOptions['primary']
        yellow: PaletteOptions['primary']
        brightBlue: PaletteOptions['primary']
        brightGreen: PaletteOptions['primary']
        red: PaletteOptions['primary']
    }
}

As you can see I do a fair amount of changes and additions.

Elsewhere I export the ThemeProvider with theme already attached. Build and publish to a package repository. The import into an app is just a new context provider that takes no props since the theme is already attached.

Your environment 🌎

`npx @mui/envinfo`
  System:
    OS: macOS 12.3.1
  Binaries:
    Node: 15.14.0 - ~/.nvm/versions/node/v15.14.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 7.7.6 - ~/.nvm/versions/node/v15.14.0/bin/npm
  Browsers:
    Chrome: 102.0.5005.61
    Edge: Not Found
    Firefox: 88.0.1
    Safari: 15.4
  npmPackages:
    @emotion/react: ^11.9.0 => 11.9.0
    @emotion/styled: ^11.8.1 => 11.8.1
    @mui/base:  5.0.0-alpha.83
    @mui/icons-material: ^5.8.2 => 5.8.2
    @mui/lab: ^5.0.0-alpha.84 => 5.0.0-alpha.84
    @mui/material: ^5.8.2 => 5.8.2
    @mui/private-theming:  5.8.0
    @mui/styled-engine:  5.8.0
    @mui/styles: ^5.8.0 => 5.8.0
    @mui/system:  5.8.2
    @mui/types:  7.1.3
    @mui/utils:  5.8.0
    @mui/x-date-pickers:  5.0.0-alpha.1
    @types/react: ^17.0.45 => 17.0.45
    react: ^17.0.2 => 17.0.2
    react-dom: ^17.0.2 => 17.0.2
    typescript: ^4.6.4 => 4.7.2

   I am currently using Chrome, I have not yet tested in FF or Safari
@JeffBaumgardt JeffBaumgardt added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jun 2, 2022
@JeffBaumgardt
Copy link
Author

I'll leave it as a note here for anyone else. I've done a lot of various research, experimenting with babel configs, rollup/esbuild configs and lots of back and forth.

I did not solve the actual problem, but I did remove createPalette and am just returning an object with my palette config. That config does make it to the createTheme and should make its way there. As far as I can suspect is it might have to do with createPalette not actually being exported in the styles directory like others. I can't be sure but it's really the only difference between createTheme and createPalette code wise. Both have the same babel runtime import, so I have to venture a guess that the imports are in fact being transformed somewhere, how/where I have no idea.

So createPalette as of now in my view is a mui only tool and an end user shouldn't expect to use it straight. But rather send an object through the createTheme and it should pick up.

Actual Change:

const palette = {
    ...customPalette,

    primary: {
        main: designTokens.Theme.Primary.Main.value,
        light: designTokens.Theme.Primary.Light.value,
    },
    warning: {
        main: designTokens.Theme.Warning.Main.value,
        light: designTokens.Theme.Warning.Light.value,
    },
    info: {
        main: designTokens.Theme.Info.Main.value,
        light: designTokens.Theme.Info.Light.value,
    },
    success: {
        main: designTokens.Theme.Success.Main.value,
    },
    error: {
        main: designTokens.Theme.Error.Main.value,
        light: designTokens.Theme.Error.Light.value,
    },
    text: {
        primary: designTokens.Theme.Text.Primary.value,
        secondary: designTokens.Theme.Text.Secondary.value,
    },
    divider: designTokens.Theme.Divider.value,
    background: {
        paper: designTokens.Theme.Background.Paper.value,
        default: designTokens.Theme.Background.Default.value,
    },
}

export default palette

** Note: Only the palette itself changed, no more createPalette wrap.

@michaldudak michaldudak removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 20, 2022
@zannager zannager added package: system Specific to @mui/system customization: theme Centered around the theming features labels Dec 20, 2022
@TryingToImprove
Copy link

I solved this by adding @babel/runtine to `serverDependenciesToBundle´ in remix.config.js.

serverDependenciesToBundle: [/^@mui.*/,/^@babel\/runtime.*/],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
customization: theme Centered around the theming features package: system Specific to @mui/system
Projects
None yet
Development

No branches or pull requests

4 participants