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

breaking feat: adopt styled-components v6 #419

Merged
merged 4 commits into from
May 9, 2024
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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 3 additions & 3 deletions benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
"@emotion/core": "^11.0.0",
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@xstyled/emotion": "^3.8.1",
"@xstyled/styled-components": "^3.8.1",
"@xstyled/emotion": "workspace:*",
"@xstyled/styled-components": "workspace:*",
"emotion-theming": "^11.0.0",
"styled-components": "^5.3.6",
"styled-components": "^6.1.9",
"styled-system": "^5.1.5"
}
}
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lerna": "3.3.0",
"packages": ["packages/*"],
"version": "3.8.1",
"version": "independent",
"useWorkspaces": true
}
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@types/react": "^18.0.21",
"@types/styled-components": "^5.1.26",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"babel-jest": "^29.1.2",
"browser-resolve": "^2.0.0",
"bundlewatch": "^0.3.3",
"codecov": "^3.8.2",
"conventional-github-releaser": "^3.1.5",
"csstype": "^3.1.3",
"esbuild": "^0.15.10",
"eslint": "^8.24.0",
"eslint-plugin-react": "^7.31.8",
Expand All @@ -49,7 +49,7 @@
"rollup": "^2.79.1",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-esbuild": "^4.10.1",
"styled-components": "^5.3.6",
"styled-components": "^6.1.11",
"typescript": "^4.8.4"
},
"resolutions": {
Expand Down Expand Up @@ -80,8 +80,5 @@
}
]
},
"overrides": {
"babel-plugin-styled-components": "2.0.2"
},
"packageManager": "[email protected]"
}
4 changes: 4 additions & 0 deletions packages/styled-components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [4.0.0](https://github.com/gregberge/xstyled/compare/v3.8.1...v4.0.0) (2024-05-09)

The minimum version of styled-components is now v6.1.11. See the [migration guide](https://styled-components.com/docs/faqs#what-do-i-need-to-do-to-migrate-to-v6) for more information.

## [3.8.1](https://github.com/gregberge/xstyled/compare/v3.8.0...v3.8.1) (2024-05-08)

**Note:** Version bump only for package @xstyled/styled-components
Expand Down
5 changes: 3 additions & 2 deletions packages/styled-components/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@xstyled/styled-components",
"description": "A utility-first CSS-in-JS framework built for React (styled-components bindings).",
"version": "3.8.1",
"version": "4.0.0",
"keywords": [
"styled-components",
"css",
Expand Down Expand Up @@ -38,9 +38,10 @@
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"styled-components": "^4.0.0 || ^5.0.0"
"styled-components": "^6.1.11"
},
"dependencies": {
"@emotion/is-prop-valid": "^1.2.2",
"@xstyled/core": "^3.8.1",
"@xstyled/system": "^3.8.1",
"@xstyled/util": "^3.7.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/styled-components/src/breakpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useThemeDown,
} from '@xstyled/core'
import { Screens } from '@xstyled/system'
import { useTheme } from './theme'
import { useTheme } from 'styled-components'

export { useViewportWidth } from '@xstyled/core'

Expand Down
16 changes: 8 additions & 8 deletions packages/styled-components/src/create.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { StyleGenerator } from '@xstyled/system'
import { createCssFunction, XCSSFunction } from './createCssFunction'
import { createX, X } from './createX'
import { createStyled, XStyled } from './createStyled'
import {
createCreateGlobalStyle,
XCreateGlobalStyle,
createCreateGlobalStyle,
} from './createCreateGlobalStyle'
import { XCSSFunction, createCssFunction } from './createCssFunction'
import { XStyled, createStyled } from './createStyled'
import { X, createX } from './createX'

export interface XStyledSet<TGen extends StyleGenerator> {
css: XCSSFunction
Expand All @@ -18,9 +18,9 @@ export const createCss = <TGen extends StyleGenerator>(
generator: TGen,
): XStyledSet<TGen> => {
return {
css: createCssFunction(generator),
x: createX(generator),
styled: createStyled(generator),
createGlobalStyle: createCreateGlobalStyle(generator),
css: createCssFunction<TGen>(generator),
x: createX<TGen>(generator),
styled: createStyled<TGen>(generator),
createGlobalStyle: createCreateGlobalStyle<TGen>(generator),
}
}
14 changes: 6 additions & 8 deletions packages/styled-components/src/createCreateGlobalStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ export type XCreateGlobalStyle = typeof scCreateGlobalStyle
export const createCreateGlobalStyle = <TGen extends StyleGenerator>(
generator: TGen,
): XCreateGlobalStyle => {
const css = createCssFunction(generator)
return ((
...args: Parameters<XCreateGlobalStyle>
): ReturnType<XCreateGlobalStyle> =>
scCreateGlobalStyle([
// @ts-ignore
css(...args),
])) as XCreateGlobalStyle
const css = createCssFunction<TGen>(generator)
return <Props extends object>(
...args: Parameters<typeof scCreateGlobalStyle<Props>>
) =>
// @ts-expect-error
scCreateGlobalStyle<Props>([css<Props>(...args)])
}
21 changes: 9 additions & 12 deletions packages/styled-components/src/createCssFunction.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
/* eslint-disable no-continue, no-loop-func, no-cond-assign */
import {
css as scCss,
FlattenSimpleInterpolation,
ThemedCssFunction,
} from 'styled-components'
import { StyleGenerator, Theme } from '@xstyled/system'
import { flattenStrings } from '@xstyled/util'
import { createTransform } from '@xstyled/core'
import { StyleGenerator } from '@xstyled/system'
import { flattenStrings } from '@xstyled/util'
import { css as scCss } from 'styled-components'

export type XCSSFunction = ThemedCssFunction<Theme>
export type XCSSFunction = typeof scCss

export const createCssFunction = <TGen extends StyleGenerator>(
generator: TGen,
): XCSSFunction => {
const transform = createTransform(generator)
return ((...args: Parameters<XCSSFunction>) => {
const scCssArgs = scCss(...args)

return <Props extends object>(...args: Parameters<XCSSFunction>) => {
const scCssArgs = scCss<Props>(...args)
const flattenedArgs = flattenStrings(scCssArgs as any[])
return flattenedArgs.map(transform) as FlattenSimpleInterpolation
}) as XCSSFunction
return flattenedArgs.map(transform) as ReturnType<typeof scCss<Props>>
}
}
2 changes: 1 addition & 1 deletion packages/styled-components/src/createGlobalStyle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('#createGlobalStyle', () => {
const GlobalStyle = createGlobalStyle`
.margin {
margin: 2;
}
}
`
const { container } = render(
<>
Expand Down
75 changes: 37 additions & 38 deletions packages/styled-components/src/createStyled.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,52 @@
/* eslint-disable no-continue, no-loop-func, no-cond-assign */
import type { ElementType } from 'react'
import isPropValid from '@emotion/is-prop-valid'
import { BoxElements } from '@xstyled/core'
import { StyleGenerator, StyleGeneratorProps } from '@xstyled/system'
import { string } from '@xstyled/util'
import { StyleGenerator, StyleGeneratorProps, Theme } from '@xstyled/system'
import {
StyledConfig,
ThemedBaseStyledInterface,
ThemedStyledFunction,
FastOmit,
LibraryStyled,
ShouldForwardProp,
Styled,
StyledInstance,
StyledOptions,
WebTarget,
} from 'styled-components'
import { XCSSFunction, createCssFunction } from './createCssFunction'
import { scStyled } from './scStyled'
import { createCssFunction, XCSSFunction } from './createCssFunction'

const getCreateStyle = (
baseCreateStyle: ThemedStyledFunction<any, any>,
const getCreateStyle = <TGen extends StyleGenerator>(
baseCreateStyle: StyledInstance<'web', any, any>,
css: XCSSFunction,
generator?: StyleGenerator,
) => {
generator?: TGen,
): ReturnType<LibraryStyled<StyleGeneratorProps<TGen>>> => {
const createStyle = (...args: Parameters<typeof css>) =>
// @ts-ignore
baseCreateStyle`${css(...args)}${generator}`
createStyle.attrs = (attrs: Parameters<typeof baseCreateStyle.attrs>[0]) =>
getCreateStyle(baseCreateStyle.attrs(attrs), css, generator)
createStyle.withConfig = (config: StyledConfig<any>) =>
getCreateStyle(baseCreateStyle.withConfig(config), css, generator)
getCreateStyle<TGen>(baseCreateStyle.attrs(attrs), css, generator)
createStyle.withConfig = (config: StyledOptions<'web', any>) =>
getCreateStyle<TGen>(baseCreateStyle.withConfig(config), css, generator)
// @ts-expect-error
return createStyle
}

type BoxStyledTags<TProps extends object> = {
[Key in keyof BoxElements]: ThemedStyledFunction<
[Key in keyof BoxElements]: StyledInstance<
'web',
BoxElements[Key],
Theme,
TProps
FastOmit<JSX.IntrinsicElements[BoxElements[Key]], keyof TProps> & TProps
>
}

export interface XStyled<TGen extends StyleGenerator>
extends ThemedBaseStyledInterface<Theme>,
extends Styled,
BoxStyledTags<StyleGeneratorProps<TGen>> {}

const createShouldForwardProp = (
generator: StyleGenerator,
): ((
prop: string | number | symbol,
defaultValidatorFn: (prop: string | number | symbol) => boolean,
elementToBeCreated?: ElementType,
) => boolean) => {
): ShouldForwardProp<'web'> => {
const propSet = new Set<string>(generator.meta.props)
return (
prop: string | number | symbol,
defaultValidatorFn: (prop: string | number | symbol) => boolean,
elementToBeCreated?: ElementType,
) => {
return (prop: string, elementToBeCreated?: WebTarget) => {
if (string(prop) && propSet.has(prop)) {
return false
}
Expand All @@ -61,7 +57,7 @@ const createShouldForwardProp = (
// This means that HTML elements could get unwanted props, but ultimately
// this is a bug in the caller, because why are they passing unwanted
// props?
return defaultValidatorFn(prop)
return isPropValid(prop)
}
return true
}
Expand All @@ -71,33 +67,36 @@ export const createBaseStyled = <TGen extends StyleGenerator>(
css: XCSSFunction,
generator?: TGen,
): XStyled<TGen> => {
const config = generator
const config: StyledOptions<'web', any> = generator
? {
shouldForwardProp: createShouldForwardProp(generator),
}
: {}
return ((component: Parameters<typeof scStyled>[0]) => {
return (<Target extends WebTarget>(component: Target) => {
const baseStyled = scStyled(component)
return getCreateStyle(
return getCreateStyle<TGen>(
config ? baseStyled.withConfig(config) : baseStyled,
css,
generator,
)
}) as XStyled<TGen>
}

type JSXElementKeys = BoxElements[keyof BoxElements]

export const createStyled = <TGen extends StyleGenerator>(
generator: TGen,
): XStyled<TGen> => {
const css = createCssFunction(generator)
const styled = createBaseStyled(css)
const xstyled = createBaseStyled(css, generator)
const css = createCssFunction<TGen>(generator)
const styled = createBaseStyled<TGen>(css)
const xstyled = createBaseStyled<TGen>(css, generator)
styled.box = xstyled('div')
Object.keys(scStyled).forEach((key) => {
// @ts-ignore
;(Object.keys(scStyled) as JSXElementKeys[]).forEach((key) => {
// @ts-expect-error
styled[key] = styled(key)
// @ts-ignore
// @ts-expect-error
styled[`${key}Box`] = xstyled(key)
})

return styled
}
34 changes: 17 additions & 17 deletions packages/styled-components/src/createX.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
/* eslint-disable no-continue, no-loop-func, no-cond-assign */
import { StyledComponent, DefaultTheme } from 'styled-components'
import { scStyled } from './scStyled'
import { StyleGenerator, StyleGeneratorProps } from '@xstyled/system'
import { createBaseStyled } from './createStyled'
import {
FastOmit,
SupportedHTMLElements,
IStyledComponent,
} from 'styled-components'
import { createCssFunction } from './createCssFunction'

type JSXElementKeys = keyof JSX.IntrinsicElements

type SafeIntrinsicElement<T extends keyof JSX.IntrinsicElements> = (
props: Omit<JSX.IntrinsicElements[T], 'color'>,
) => React.ReactElement<any, T>
import { createBaseStyled } from './createStyled'
import { scStyled } from './scStyled'

export type X<TGen extends StyleGenerator> = {
[Key in JSXElementKeys]: StyledComponent<
SafeIntrinsicElement<Key>,
DefaultTheme,
StyleGeneratorProps<TGen>,
'color'
[Key in SupportedHTMLElements]: IStyledComponent<
'web',
FastOmit<JSX.IntrinsicElements[Key], keyof StyleGeneratorProps<TGen>> &
StyleGeneratorProps<TGen>
>
}

export const createX = <TGen extends StyleGenerator>(
generator: TGen,
): X<TGen> => {
const xstyled = createBaseStyled(createCssFunction(generator), generator)
const xstyled = createBaseStyled<TGen>(
createCssFunction<TGen>(generator),
generator,
)
const x = {} as X<TGen>
Object.keys(scStyled).forEach((tag) => {
// @ts-ignore
x[tag] = xstyled(tag)``
// @ts-expect-error
x[tag] = xstyled(tag)({})
})
return x
}
6 changes: 3 additions & 3 deletions packages/styled-components/src/scStyled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from 'styled-components'
import styled, { Styled } from 'styled-components'

// Provide interop since `styled-components` does not work out of the box with ESM
export const scStyled =
// @ts-ignore
typeof styled === 'function' ? styled : styled.default
// @ts-expect-error
(typeof styled === 'function' ? styled : styled.default) as Styled
6 changes: 2 additions & 4 deletions packages/styled-components/src/styled.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ describe('#styled', () => {
})

it('works with render props', () => {
const Foo = ({
children,
}: {
const Foo: React.FC<{
children: ({ content }: { content: string }) => React.ReactNode
}) => <div>{children({ content: 'Hello World' })}</div>
}> = ({ children }) => <div>{children({ content: 'Hello World' })}</div>

const StyledFoo = styled(Foo)``

Expand Down
Loading
Loading