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

Filter scale tuples in Theme type inside .sx prop #2457

Merged
merged 9 commits into from
Jan 24, 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
19 changes: 10 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v2
with:
version: 7
version: 8

- uses: actions/setup-node@v3
with:
node-version: 18.x
node-version: 20.x
cache: 'pnpm'

- name: Install
Expand Down Expand Up @@ -74,18 +74,18 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- uses: actions/checkout@v3

- name: Prepare repository
run: git fetch --unshallow --tags
- uses: actions/checkout@v4
with:
fetch-depth: 100
fetch-tags: true

- uses: pnpm/action-setup@v2
with:
version: 7
version: 8

- uses: actions/setup-node@v3
with:
node-version: 18.x
node-version: 20.x
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'

Expand All @@ -105,6 +105,7 @@ jobs:
# continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.AUTO_RELEASE_GH_TOKEN }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
run: pnpm release

- name: Check published prerelease
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@theme-ui/monorepo",
"version": "0.16.1",
"version": "0.16.2-scale-tuples.0",
"private": true,
"scripts": {
"build": "preconstruct build",
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/Box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
ArrayInterpolation,
CSSObject,
Interpolation,
jsx,
useTheme,
} from '@emotion/react'
import React, { forwardRef } from 'react'
Expand All @@ -12,6 +11,7 @@ import {
ThemeUICSSProperties,
ThemeUIStyleObject,
} from '@theme-ui/css'
import { Theme } from '@theme-ui/core'
import type { Assign, ForwardRef } from './types'
import type { __ThemeUIComponentsInternalProps } from './util'

Expand Down Expand Up @@ -59,7 +59,7 @@ export interface BoxOwnProps extends BoxSystemProps {
as?: React.ElementType
variant?: string
css?: Interpolation<any>
sx?: ThemeUIStyleObject
sx?: ThemeUIStyleObject<Theme>
}

export interface BoxProps
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export type {
Scale,
StylePropertyValue,
TLengthStyledSystem,
Theme,
ThemeDerivedStyles,
ThemeStyles,
ThemeUICSSObject,
Expand Down
28 changes: 26 additions & 2 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
import { Interpolation } from '@emotion/react'
import { ThemeUIStyleObject, Theme as ThemeUITheme } from '@theme-ui/css'
import {
Scale,
ScaleDict,
ThemeUIStyleObject,
Theme as ThemeUITheme,
} from '@theme-ui/css'

export interface UserThemes {}

/** @internal */
export type _UserTheme = UserThemes[keyof UserThemes]

/** Theme without array scales, so it's easier to read from inside of .sx prop */
export type WidenedTheme = {
[P in keyof ThemeUITheme]: ThemeUITheme[P] extends Scale<infer R> | undefined
? ScaleDict<R>
: ThemeUITheme[P]
} & ThemeUITheme

export type Theme<TTheme = {}> = _UserTheme extends never
? ThemeUITheme<TTheme>
: _UserTheme

/** @internal */
export type _JSXTheme = _UserTheme extends never ? WidenedTheme : _UserTheme

export interface SxProp {
/**
Expand All @@ -8,7 +32,7 @@ export interface SxProp {
*
* @see https://theme-ui.com/sx-prop/
*/
sx?: ThemeUIStyleObject
sx?: ThemeUIStyleObject<_JSXTheme>
/**
* Theme UI uses Emotion's JSX function. You can pass styles to it directly
* using `css` prop.
Expand Down
23 changes: 22 additions & 1 deletion packages/core/test/react-jsx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
*/
/* eslint-disable no-lone-blocks */
import { renderJSON, NotHas, Assert, expecter } from '@theme-ui/test-utils'
import { matchers } from '@emotion/jest'

import { SxProp, ThemeUIJSX } from '../src'
import { SxProp, ThemeProvider, ThemeUIJSX } from '../src'

expect.extend(matchers)

describe('JSX', () => {
test('accepts sx prop', () => {
Expand All @@ -30,6 +33,24 @@ describe('JSX', () => {
).toMatchSnapshot()
})

test('sx prop gives a theme that can be read as array or object', () => {
const json = renderJSON(
<ThemeProvider
theme={{ shadows: { small: '0 0 4px rgba(0, 0, 0, .125)' } }}
>
<div
sx={(t) => ({
boxShadow: t.shadows?.small,
'&:hover': {
boxShadow: t.shadows?.[2],
},
})}
/>
</ThemeProvider>
)
expect(json).toHaveStyleRule('box-shadow', '0 0 4px rgba(0, 0, 0, .125)')
})

test('accepts css prop', () => {
const expectSnippet = expecter(
`/** @jsxImportSource ./packages/core */
Expand Down
13 changes: 8 additions & 5 deletions packages/css/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,12 @@ const transforms = [
)

const responsive =
(styles: Exclude<ThemeUIStyleObject, ThemeDerivedStyles>) =>
(styles: Exclude<ThemeUIStyleObject<Theme>, ThemeDerivedStyles<Theme>>) =>
(theme?: Theme) => {
const next: Exclude<ThemeUIStyleObject, ThemeDerivedStyles> = {}
const next: Exclude<
ThemeUIStyleObject<Theme>,
ThemeDerivedStyles<Theme>
> = {}
const breakpoints =
(theme && (theme.breakpoints as string[])) || defaultBreakpoints
const mediaQueries = [
Expand Down Expand Up @@ -348,12 +351,12 @@ const responsive =
type CssPropsArgument = { theme: Theme } | Theme

export const css =
(args: ThemeUIStyleObject = {}) =>
<TTheme extends Theme<{}>>(args: ThemeUIStyleObject<TTheme> = {}) =>
(props: CssPropsArgument = {}): CSSObject => {
const theme: Theme = {
const theme = {
...defaultTheme,
...('theme' in props ? props.theme : props),
}
} as TTheme
// insert variant props before responsive styles, so they can be merged
// we need to maintain order of the style props, so if a variant is place in the middle
// of other props, it will extends its props at that same location order.
Expand Down
Loading
Loading