From 8af0d6dd9bdb586531bf03abc0048c63c1c5382c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Wed, 18 Nov 2020 10:22:50 +0100 Subject: [PATCH] feat(utils): export a theme prop type (#17) --- README.md | 19 ++ package.json | 4 + src/index.ts | 2 + src/themes/shared.ts | 2 +- src/types/index.ts | 1 + .../{index.spec.ts => media-queries.spec.ts} | 2 +- src/utils/{index.ts => media-queries.ts} | 0 src/utils/prop-types.ts | 219 ++++++++++++++++++ yarn.lock | 13 +- 9 files changed, 252 insertions(+), 10 deletions(-) rename src/utils/{index.spec.ts => media-queries.spec.ts} (96%) rename src/utils/{index.ts => media-queries.ts} (100%) create mode 100644 src/utils/prop-types.ts diff --git a/README.md b/README.md index 35f0f63..cb7e691 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,25 @@ const Bold = styled.strong` The theme is a plain JavaScript object, so you can use it in other ways, too. +### With prop types + +The package exports a `themePropType` which can be used to check the `theme` prop: + +```js +import PropTypes from 'prop-types'; +import { withTheme } from 'emotion-theming'; +import { themePropType } from '@sumup/design-tokens'; + +export function ComponentWithInlineStyles({ theme, label }) { + return
{label}
; +} + +ComponentWithInlineStyles.propTypes = { + theme: themePropType.isRequired, + label: PropTypes.string, +}; +``` + ### With TypeScript The package exports a `Theme` interface which can be used to type Emotion's `styled` function. Create a custom `styled` instance as described in the [Emotion docs](https://emotion.sh/docs/typescript): diff --git a/package.json b/package.json index abb0954..3b9bd71 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,13 @@ "prerelease": "yarn build", "release": "foundry run semantic-release" }, + "dependencies": { + "prop-types": "^15.7.2" + }, "devDependencies": { "@sumup/foundry": "^3.0.0", "@types/jest": "^26.0.15", + "@types/prop-types": "^15.7.3", "jest": "^25.4.0", "jest-extended": "^0.11.5", "ts-jest": "^25.4.0", diff --git a/src/index.ts b/src/index.ts index 0803635..5cedbca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,8 @@ import * as Types from './types'; import * as lightBase from './themes/light'; +export { themePropType } from './utils/prop-types'; + // HACK: Copy the theme, otherwise, it gets exported as 'module'. const light: Types.Theme = { ...lightBase }; diff --git a/src/themes/shared.ts b/src/themes/shared.ts index 3f83d17..75b282e 100644 --- a/src/themes/shared.ts +++ b/src/themes/shared.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { createMediaQueries } from '../utils'; +import { createMediaQueries } from '../utils/media-queries'; import { Spacings, IconSizes, diff --git a/src/types/index.ts b/src/types/index.ts index 6ccbe9a..679c471 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -102,6 +102,7 @@ export type IconSizes = { mega: string; giga: string; }; + export type BorderRadius = { kilo: string; mega: string; diff --git a/src/utils/index.spec.ts b/src/utils/media-queries.spec.ts similarity index 96% rename from src/utils/index.spec.ts rename to src/utils/media-queries.spec.ts index 574d93c..5928abf 100644 --- a/src/utils/index.spec.ts +++ b/src/utils/media-queries.spec.ts @@ -15,7 +15,7 @@ import { Breakpoints } from '../types'; -import { createMediaQueries } from '.'; +import { createMediaQueries } from './media-queries'; describe('Utils', () => { describe('createMediaQueries', () => { diff --git a/src/utils/index.ts b/src/utils/media-queries.ts similarity index 100% rename from src/utils/index.ts rename to src/utils/media-queries.ts diff --git a/src/utils/prop-types.ts b/src/utils/prop-types.ts new file mode 100644 index 0000000..e50c173 --- /dev/null +++ b/src/utils/prop-types.ts @@ -0,0 +1,219 @@ +/** + * Copyright 2020, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import PropTypes from 'prop-types'; + +const typePropType = PropTypes.shape({ + fontSize: PropTypes.string, + lineHeight: PropTypes.string, +}).isRequired; + +const breakpointPropType = PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, +]).isRequired; + +const gridPropType = PropTypes.shape({ + priority: PropTypes.number.isRequired, + breakpoint: PropTypes.oneOf([ + 'untilKilo', + 'kilo', + 'kiloToMega', + 'mega', + 'untilMega', + 'megaToGiga', + 'giga', + 'gigaToTera', + 'tera', + 'default', + ]).isRequired, + cols: PropTypes.number.isRequired, + maxWidth: PropTypes.string.isRequired, + gutter: PropTypes.string.isRequired, +}).isRequired; + +export const themePropType = PropTypes.shape({ + colors: PropTypes.shape({ + white: PropTypes.string.isRequired, + black: PropTypes.string.isRequired, + // Neutrals + n100: PropTypes.string.isRequired, + n200: PropTypes.string.isRequired, + n300: PropTypes.string.isRequired, + n500: PropTypes.string.isRequired, + n700: PropTypes.string.isRequired, + n800: PropTypes.string.isRequired, + n900: PropTypes.string.isRequired, + // Blues + b100: PropTypes.string.isRequired, + b200: PropTypes.string.isRequired, + b300: PropTypes.string.isRequired, + b400: PropTypes.string.isRequired, + b500: PropTypes.string.isRequired, + b700: PropTypes.string.isRequired, + b900: PropTypes.string.isRequired, + // Greens + g100: PropTypes.string.isRequired, + g200: PropTypes.string.isRequired, + g300: PropTypes.string.isRequired, + g500: PropTypes.string.isRequired, + g700: PropTypes.string.isRequired, + g900: PropTypes.string.isRequired, + // Violets + v100: PropTypes.string.isRequired, + v200: PropTypes.string.isRequired, + v300: PropTypes.string.isRequired, + v500: PropTypes.string.isRequired, + v700: PropTypes.string.isRequired, + v900: PropTypes.string.isRequired, + // Oranges + o100: PropTypes.string.isRequired, + o200: PropTypes.string.isRequired, + o300: PropTypes.string.isRequired, + o500: PropTypes.string.isRequired, + o700: PropTypes.string.isRequired, + o900: PropTypes.string.isRequired, + // Yellows + y100: PropTypes.string.isRequired, + y200: PropTypes.string.isRequired, + y300: PropTypes.string.isRequired, + y500: PropTypes.string.isRequired, + y700: PropTypes.string.isRequired, + y900: PropTypes.string.isRequired, + // Reds + r100: PropTypes.string.isRequired, + r200: PropTypes.string.isRequired, + r300: PropTypes.string.isRequired, + r500: PropTypes.string.isRequired, + r700: PropTypes.string.isRequired, + r900: PropTypes.string.isRequired, + // Primary + p100: PropTypes.string.isRequired, + p200: PropTypes.string.isRequired, + p300: PropTypes.string.isRequired, + p400: PropTypes.string.isRequired, + p500: PropTypes.string.isRequired, + p700: PropTypes.string.isRequired, + p900: PropTypes.string.isRequired, + // Misc + shadow: PropTypes.string.isRequired, + bodyBg: PropTypes.string.isRequired, + bodyColor: PropTypes.string.isRequired, + }).isRequired, + spacings: PropTypes.shape({ + bit: PropTypes.string.isRequired, + byte: PropTypes.string.isRequired, + kilo: PropTypes.string.isRequired, + mega: PropTypes.string.isRequired, + giga: PropTypes.string.isRequired, + tera: PropTypes.string.isRequired, + peta: PropTypes.string.isRequired, + exa: PropTypes.string.isRequired, + zetta: PropTypes.string.isRequired, + }).isRequired, + iconSizes: PropTypes.shape({ + kilo: PropTypes.string.isRequired, + mega: PropTypes.string.isRequired, + giga: PropTypes.string.isRequired, + }).isRequired, + borderRadius: PropTypes.shape({ + kilo: PropTypes.string.isRequired, + mega: PropTypes.string.isRequired, + giga: PropTypes.string.isRequired, + tera: PropTypes.string.isRequired, + circle: PropTypes.string.isRequired, + pill: PropTypes.string.isRequired, + }).isRequired, + borderWidth: PropTypes.shape({ + kilo: PropTypes.string.isRequired, + mega: PropTypes.string.isRequired, + }).isRequired, + typography: PropTypes.shape({ + headings: PropTypes.shape({ + kilo: typePropType, + mega: typePropType, + giga: typePropType, + tera: typePropType, + peta: typePropType, + exa: typePropType, + zetta: typePropType, + }).isRequired, + subHeadings: PropTypes.shape({ + kilo: typePropType, + mega: typePropType, + }).isRequired, + text: PropTypes.shape({ + kilo: typePropType, + mega: typePropType, + giga: typePropType, + }).isRequired, + }).isRequired, + fontStack: PropTypes.shape({ + default: PropTypes.string, + mono: PropTypes.string, + }).isRequired, + fontWeight: PropTypes.shape({ + regular: PropTypes.string.isRequired, + bold: PropTypes.string.isRequired, + }).isRequired, + breakpoint: PropTypes.shape({ + untilKilo: breakpointPropType, + kilo: breakpointPropType, + kiloToMega: breakpointPropType, + mega: breakpointPropType, + untilMega: breakpointPropType, + megaToGiga: breakpointPropType, + giga: breakpointPropType, + gigaToTera: breakpointPropType, + tera: breakpointPropType, + }).isRequired, + mx: PropTypes.shape({ + untilKilo: PropTypes.string.isRequired, + kilo: PropTypes.string.isRequired, + kiloToMega: PropTypes.string.isRequired, + mega: PropTypes.string.isRequired, + untilMega: PropTypes.string.isRequired, + megaToGiga: PropTypes.string.isRequired, + giga: PropTypes.string.isRequired, + gigaToTera: PropTypes.string.isRequired, + tera: PropTypes.string.isRequired, + }).isRequired, + grid: PropTypes.shape({ + default: gridPropType, + untilKilo: gridPropType, + kilo: gridPropType, + mega: gridPropType, + giga: gridPropType, + tera: gridPropType, + }).isRequired, + transitions: PropTypes.shape({ + default: PropTypes.string.isRequired, + slow: PropTypes.string.isRequired, + }).isRequired, + zIndex: PropTypes.shape({ + default: PropTypes.number.isRequired, + absolute: PropTypes.number.isRequired, + drawer: PropTypes.number.isRequired, + // @deprecated use input value instead + select: PropTypes.number.isRequired, + input: PropTypes.number.isRequired, + popover: PropTypes.number.isRequired, + tooltip: PropTypes.number.isRequired, + header: PropTypes.number.isRequired, + backdrop: PropTypes.number.isRequired, + sidebar: PropTypes.number.isRequired, + modal: PropTypes.number.isRequired, + }).isRequired, +}); diff --git a/yarn.lock b/yarn.lock index 40cfbb1..3e4edea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,6 +976,11 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== +"@types/prop-types@^15.7.3": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -6290,7 +6295,6 @@ npm@^6.10.3: cmd-shim "^3.0.3" columnify "~1.5.4" config-chain "^1.1.12" - debuglog "*" detect-indent "~5.0.0" detect-newline "^2.1.0" dezalgo "~1.0.3" @@ -6305,7 +6309,6 @@ npm@^6.10.3: has-unicode "~2.0.1" hosted-git-info "^2.8.8" iferr "^1.0.2" - imurmurhash "*" infer-owner "^1.0.4" inflight "~1.0.6" inherits "^2.0.4" @@ -6324,14 +6327,8 @@ npm@^6.10.3: libnpx "^10.2.2" lock-verify "^2.1.0" lockfile "^1.0.4" - lodash._baseindexof "*" lodash._baseuniq "~4.6.0" - lodash._bindcallback "*" - lodash._cacheindexof "*" - lodash._createcache "*" - lodash._getnative "*" lodash.clonedeep "~4.5.0" - lodash.restparam "*" lodash.union "~4.6.0" lodash.uniq "~4.5.0" lodash.without "~4.4.0"