diff --git a/.gitignore b/.gitignore index d5e3b11..2659df7 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,4 @@ typings/ .env .next dist/ -.gitignore -.docz/ -/docz.config.js +.next/ diff --git a/README.md b/README.md deleted file mode 100644 index c173293..0000000 --- a/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# Tesseract Web - React Common - -Common front-end components for Web using the [Tesseract design system](https://make.modal.sh/tesseract/design), written for [React](https://reactjs.org). - -Package: - -[![@tesseract-design/react-common](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=package&color=C78AB3&kind=name)](https://js.pack.modal.sh/-/web/detail/@tesseract-design/react-common) -[![@tesseract-design/react-common](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=package&color=C78AB3&kind=version)](https://js.pack.modal.sh/-/web/detail/@tesseract-design/react-common#versions) - -Dependencies: - -[![React](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=dependency&dependency=react&kind=peerDependencies)](https://github.com/facebook/react) -[![Styled Components](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=dependency&dependency=styled-components&kind=peerDependencies)](https://github.com/styled-components/styled-components) -[![TypeScript](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=dependency&dependency=typescript&kind=devDependencies)](https://github.com/microsoft/typescript) -[![Jest](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=dependency&dependency=jest&kind=devDependencies)](https://github.com/facebook/jest) -[![Rollup](https://code.modal.sh/badge?repo=tesseract-design/react-common&type=dependency&dependency=rollup&kind=devDependencies)](https://github.com/rollup/rollup) - -## Installation - -Since this package resides in the [Modal.sh JavaScript Package Registry](https://js.pack.modal.sh/), you may need to -adjust configuration in your chosen package manager. - -With [Yarn](https://yarnpkg.com), add this to your `.yarnrc` file: - -``` -"@tesseract-design:registry" "https://js.pack.modal.sh/" -``` - -Then, install the package by running the following command: - -```shell script -yarn add @tesseract-design/react-common -``` - -## Usage - -The package includes components as named exports. Simply import the components you need individually or use a namespace -import, like so: - -```jsx harmony -import * as React from 'react' -import ReactDOM from 'react-dom' -import * as T from '@tesseract-design/react-common' - -const LoginForm = etcProps => ( -
-
- - Log In - -
- -
-
- -
-
- - Log In - -
-
-
-) - -const mountNode = window.document.createElement('div') - -ReactDOM.render( - , - mountNode, -) - -window.document.body.appendChild(mountNode) -``` - -Detailed usage guides can be found in the [Tesseract Design - React Common documentation](https://make.modal.sh/tesseract/web/react/common). - -## TypeScript - -The package is written and tested using TypeScript. Thus, typings for consumption in TypeScript are bundled with the -compiled source. - diff --git a/README.md b/README.md new file mode 120000 index 0000000..f0e93b5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +packages/react-common-docs/src/pages/index.md \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 5e77eb6..4df51b0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,8 +5,8 @@ module.exports = { './jest.setup.ts', ], collectCoverageFrom: [ - './lib/**/*.{ts,tsx}', - '!./lib/**/*.stories.{ts,tsx}' + './packages/**/*.{ts,tsx}', + '!./packages/**/*.stories.{ts,tsx}' ], preset: 'ts-jest', testTimeout: 30000, diff --git a/lib/components/Checkbox/Checkbox.mdx b/lib/components/Checkbox/Checkbox.mdx deleted file mode 100644 index 81d5bd9..0000000 --- a/lib/components/Checkbox/Checkbox.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Checkbox -route: /components/checkbox -menu: Components ---- - -import { Playground, Props, Link } from 'docz' -import Checkbox from './Checkbox' - -# Checkbox - -Component for values that have an on/off state. - - - - - -## Props - - - -## See Also - -- Select for a similar component suitable for selecting more values. -- RadioButton for a similar component on selecting a single value among very few choices. diff --git a/lib/components/Icon/Icon.mdx b/lib/components/Icon/Icon.mdx deleted file mode 100644 index 261ea08..0000000 --- a/lib/components/Icon/Icon.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Icon -route: /components/icon -menu: Components ---- - -import { Playground, Props } from 'docz' -import Icon from './Icon' - -# Icon - -Component for displaying graphics. - - - - - -## Props - - diff --git a/lib/components/RadioButton/RadioButton.mdx b/lib/components/RadioButton/RadioButton.mdx deleted file mode 100644 index 6b5f662..0000000 --- a/lib/components/RadioButton/RadioButton.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: RadioButton -route: /components/radiobutton -menu: Components ---- - -import { Playground, Props, Link } from 'docz' -import RadioButton from './RadioButton' - -# RadioButton - -Component for values which are to be selected from a few list of options. - - -
-
- -
-
- -
-
-
- -## Props - - - -## See Also - -- Checkbox for a similar component on selecting values among very few choices. -- Select for a similar component suitable for selecting more values. diff --git a/lib/components/Select/Select.mdx b/lib/components/Select/Select.mdx deleted file mode 100644 index 35a1a80..0000000 --- a/lib/components/Select/Select.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: Select -route: /components/select -menu: Components ---- - -import { Playground, Props, Link } from 'docz' -import Select from './Select' - -# Select - -Component for selecting values from a larger number of options. - - - - - -## Props - - - -## Usage Notes - -The component will behave as `block`, i.e. it takes the remaining of the horizontal space. -To use the component together with layouts, see [TextInput](./textinput) for examples. Both `Select` and -`TextInput` have similar strategies on usage with layouts. - -## See Also - -- Checkbox for a similar component on selecting values among very few choices. -- RadioButton for a similar component on selecting a single value among very few choices. diff --git a/lib/components/Slider/Slider.mdx b/lib/components/Slider/Slider.mdx deleted file mode 100644 index 3668c29..0000000 --- a/lib/components/Slider/Slider.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Slider -route: /components/slider -menu: Components ---- - -import { Playground, Props } from 'docz' -import Slider from './Slider' - -# Slider - -Component for inputting numeric values in a graphical manner. - -The component is styled using client-side scripts. When the component is rendered server-side, -the component falls back into the original `` element. - - - - - -## Props - - - -## See Also - -- [Reach UI Slider](//reacttraining.com/reach-ui/slider/#sliderinput) for the client-side implementation. diff --git a/lib/components/TextInput/TextInput.mdx b/lib/components/TextInput/TextInput.mdx deleted file mode 100644 index a7178bd..0000000 --- a/lib/components/TextInput/TextInput.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -name: TextInput -route: /components/textinput -menu: Components ---- - -import { Playground, Props, Link } from 'docz' -import TextInput from './TextInput' - -# TextInput - -Component for inputting textual values. - - - - - -## Props - - - -## Usage Notes - -The component will behave as `block`, i.e. it takes the remaining of the horizontal space. -To use the component together with layouts, see the following examples. - -### Inline - -The components are surrounded by `inline-block` elements. These surrounding elements have specified widths, which could -act as guide to the user on how long the expected input values are. - - -
- I am and I live in . -
-
- -### Grid - -It is advisable to put surrounding elements instead of the `TextInput` components themselves as children of the -element specified as `grid`. This is to be able to add complementing content to the components, if for example there are -some content that is best displayed outside the component instead of putting in the `hint` prop. - - -
-
- -
-
- -
-
- -
-
- -
-
- - - Consult the fees table for shipping fee details. - -
-
-
- -## See Also - -- Select for a graphically-similar component suitable for selecting more values. diff --git a/lib/services/isEmpty.test.ts b/lib/services/isEmpty.test.ts deleted file mode 100644 index 4837494..0000000 --- a/lib/services/isEmpty.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as fc from 'fast-check' -import isEmpty from './isEmpty' - -describe('lib/services/isEmpty', () => { - it('should exist', () => { - expect(isEmpty).toBeDefined() - }) - - it('should be a function', () => { - expect(isEmpty).toBeFunction() - }) - - it('should accept 1 argument', () => { - expect(isEmpty).toHaveLength(1) - }) - - it('should return a boolean value', () => { - fc.assert( - fc.property(fc.anything(), (v) => { - expect(typeof isEmpty(v)).toBe('boolean') - }), - ) - }) - - describe('on arguments', () => { - it('should return `true` on an argument with value of `undefined`', () => { - expect(isEmpty(undefined)).toBe(true) - }) - - it('should return `true` on an argument with value of `null`', () => { - expect(isEmpty(null)).toBe(true) - }) - - it('should return `false` on an argument with value that is neither `undefined` nor `null`', () => { - fc.assert( - fc.property(fc.anything().filter((v) => typeof v !== 'undefined' && v !== null), (v) => { - expect(isEmpty(v)).toBe(false) - }), - ) - }) - }) -}) diff --git a/package.json b/package.json index f69519f..0bbaac0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "license": "MIT", "private": false, "devDependencies": { + "@babel/runtime": "^7.12.5", + "@reach/slider": "^0.10.5", "@rollup/plugin-typescript": "^5.0.2", "@types/enzyme": "^3.10.5", "@types/enzyme-adapter-react-16": "^1.0.6", @@ -29,23 +31,20 @@ "jest-axe": "3.4.0", "jest-enzyme": "7.1.2", "jest-extended": "0.11.5", + "pascal-case": "3.1.1", "plop": "2.6.0", "prettier": "1.19.1", - "react-is": "^16.13.1", + "prop-types": "15.7.2", + "react": "16.13.1", + "react-dom": "16.13.1", + "react-feather": "2.0.3", "rollup": "^2.23.0", "rollup-plugin-peer-deps-external": "2.2.2", "rollup-plugin-terser": "5.3.0", + "styled-components": "5.1.0", "ts-jest": "^26.1.3", "tslib": "^2.0.0", - "typescript": "^3.9.7", - "@reach/slider": "^0.10.5", - "docz": "^2.3.1", - "pascal-case": "3.1.1", - "prop-types": "15.7.2", - "react": "16.13.1", - "react-dom": "16.13.1", - "react-feather": "2.0.3", - "styled-components": "5.1.0" + "typescript": "^3.9.7" }, "scripts": { "prepublishOnly": "NODE_ENV=production rm -rf dist/ && rollup -c", @@ -64,5 +63,6 @@ "react-feather": "2.0.3", "styled-components": "5.1.0" }, - "homepage": "https://make.modal.sh/tesseract/web/react/common" + "homepage": "https://make.modal.sh/tesseract/web/react/common", + "dependencies": {} } diff --git a/packages/react-common-docs/brand.tsx b/packages/react-common-docs/brand.tsx new file mode 100644 index 0000000..a5ef71b --- /dev/null +++ b/packages/react-common-docs/brand.tsx @@ -0,0 +1,40 @@ +import * as React from 'react' +import styled from 'styled-components' +import pkg from '../../package.json' + +const Base = styled('div')({ + position: 'relative', +}) + +const Title = styled('strong')({ + fontSize: '2rem', + fontFamily: 'var(--font-family-headings), sans-serif', + fontWeight: 'var(--font-weight-headings, 400)', + lineHeight: 'var(--line-height-headings, 1.5)', + fontStretch: 'var(--font-stretch-headings, normal)', + textTransform: 'lowercase', + whiteSpace: 'nowrap', +}) + +const Subtitle = styled('small')({ + position: 'absolute', + bottom: '-1em', + right: 0, + fontWeight: 'bolder', +}) + +const Brand = () => { + const name = pkg.name.includes('@') ? pkg.name.split('/')[1] : pkg.name + return ( + + + {name} + + + v.{pkg.version} + + + ) +} + +export default Brand diff --git a/packages/react-common-docs/next-env.d.ts b/packages/react-common-docs/next-env.d.ts new file mode 100644 index 0000000..6f84a8d --- /dev/null +++ b/packages/react-common-docs/next-env.d.ts @@ -0,0 +1,3 @@ +/// +/// +declare module 'remark-react' diff --git a/packages/react-common-docs/next.config.js b/packages/react-common-docs/next.config.js new file mode 100644 index 0000000..d24602c --- /dev/null +++ b/packages/react-common-docs/next.config.js @@ -0,0 +1,25 @@ +const path = require('path') + +const withMDX = require('next-mdx-frontmatter')({ + extension: /\.mdx?$/ +}) + +const e = withMDX({ + pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'] +}) + +module.exports = { + ...e, + webpack(...args) { + const oldWebpack = e.webpack(...args) + const [config, { defaultLoaders, }] = args + + config.module.rules.push({ + test: /\.(ts|tsx)$/, + include: [path.resolve(__dirname, '../react-common/')], + use: [defaultLoaders.babel], + }) + + return oldWebpack + } +} diff --git a/packages/react-common-docs/package.json b/packages/react-common-docs/package.json new file mode 100644 index 0000000..e6e2c4b --- /dev/null +++ b/packages/react-common-docs/package.json @@ -0,0 +1,26 @@ +{ + "name": "react-common-docs", + "version": "0.1.0", + "private": true, + "scripts": { + "predev": "./scripts/docgen", + "dev": "next dev", + "prebuild": "./scripts/docgen", + "build": "next build", + "prestart": "./scripts/docgen", + "start": "next start", + "docgen": "./scripts/docgen" + }, + "dependencies": { + "@mdx-js/loader": "^1.6.19", + "next": "10.0.1", + "next-mdx-frontmatter": "^0.0.3", + "pascal-case": "^3.1.1", + "react-docgen-typescript": "^1.20.5", + "react-live": "^2.2.3", + "remark-parse": "^9.0.0", + "remark-react": "^8.0.0", + "styled-components": "^5.2.1", + "unified": "^9.2.0" + } +} diff --git a/packages/react-common-docs/public/favicon.ico b/packages/react-common-docs/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4965832f2c9b0605eaa189b7c7fb11124d24e48a GIT binary patch literal 15086 zcmeHOOH5Q(7(R0cc?bh2AT>N@1PWL!LLfZKyG5c!MTHoP7_p!sBz0k$?pjS;^lmgJ zU6^i~bWuZYHL)9$wuvEKm~qo~(5=Lvx5&Hv;?X#m}i|`yaGY4gX+&b>tew;gcnRQA1kp zBbm04SRuuE{Hn+&1wk%&g;?wja_Is#1gKoFlI7f`Gt}X*-nsMO30b_J@)EFNhzd1QM zdH&qFb9PVqQOx@clvc#KAu}^GrN`q5oP(8>m4UOcp`k&xwzkTio*p?kI4BPtIwX%B zJN69cGsm=x90<;Wmh-bs>43F}ro$}Of@8)4KHndLiR$nW?*{Rl72JPUqRr3ta6e#A z%DTEbi9N}+xPtd1juj8;(CJt3r9NOgb>KTuK|z7!JB_KsFW3(pBN4oh&M&}Nb$Ee2 z$-arA6a)CdsPj`M#1DS>fqj#KF%0q?w50GN4YbmMZIoF{e1yTR=4ablqXHBB2!`wM z1M1ke9+<);|AI;f=2^F1;G6Wfpql?1d5D4rMr?#f(=hkoH)U`6Gb)#xDLjoKjp)1;Js@2Iy5yk zMXUqj+gyk1i0yLjWS|3sM2-1ECc;MAz<4t0P53%7se$$+5Ex`L5TQO_MMXXi04UDIU+3*7Ez&X|mj9cFYBXqM{M;mw_ zpw>azP*qjMyNSD4hh)XZt$gqf8f?eRSFX8VQ4Y+H3jAtvyTrXr`qHAD6`m;aYmH2zOhJC~_*AuT} zvUxC38|JYN94i(05R)dVKgUQF$}#cxV7xZ4FULqFCNX*Forhgp*yr6;DsIk=ub0Hv zpk2L{9Q&|uI^b<6@i(Y+iSxeO_n**4nRLc`P!3ld5jL=nZRw6;DEJ*1z6Pvg+eW|$lnnjO zjd|8>6l{i~UxI244CGn2kK@cJ|#ecwgSyt&HKA2)z zrOO{op^o*- + + \ No newline at end of file diff --git a/packages/react-common-docs/scripts/docgen b/packages/react-common-docs/scripts/docgen new file mode 100755 index 0000000..78ebe5e --- /dev/null +++ b/packages/react-common-docs/scripts/docgen @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const docgen = require('react-docgen-typescript') +const path = require('path') +const fs = require('fs') + +const componentsPath = path.resolve(__dirname, '..', '..', 'react-common', 'src', 'components') + +fs.readdir(componentsPath, (err, dir) => { + const trueFilePaths = dir.map(d => path.resolve(__dirname, '..', '..', 'react-common', 'src', 'components', d, `${d}.tsx`)) + const docs = docgen.parse( + trueFilePaths, + { + shouldExtractLiteralValuesFromEnum: true, + shouldRemoveUndefinedFromOptional: true, + propFilter: { + skipPropsWithName: ['key', 'ref'], + }, + } + ) + fs.writeFile(path.resolve(__dirname, '..', 'src', 'docgen.json'), JSON.stringify(docs, null, 2), (err) => { + + }) +}) diff --git a/packages/react-common-docs/src/components/Header/Header.tsx b/packages/react-common-docs/src/components/Header/Header.tsx new file mode 100644 index 0000000..a0672f4 --- /dev/null +++ b/packages/react-common-docs/src/components/Header/Header.tsx @@ -0,0 +1,35 @@ +import * as React from 'react' +import Head from 'next/head' +import unified from 'unified' +import parse from 'remark-parse' +import remark2react from 'remark-react' +import docgen from '../../docgen.json' + +const Header = ({ of: ofAttr }) => { + const docs = docgen.find(d => d.displayName === ofAttr) + + if (!docs) { + return null + } + + return ( + + + + {docs.displayName} | React Common + + +

{docs.displayName}

+

+ { + unified() + .use(parse) + .use(remark2react) + .processSync(docs.description).result + } +

+
+ ) +} + +export default Header diff --git a/packages/react-common-docs/src/components/MenuGraphics/MenuGraphics.tsx b/packages/react-common-docs/src/components/MenuGraphics/MenuGraphics.tsx new file mode 100644 index 0000000..c7ea6f7 --- /dev/null +++ b/packages/react-common-docs/src/components/MenuGraphics/MenuGraphics.tsx @@ -0,0 +1,50 @@ +import * as React from 'react' +import * as PropTypes from 'prop-types' +import styled from 'styled-components' +import { Icon } from '../../../../react-common/src' + +const Image = styled('img')({ + display: 'block', + maxWidth: '100%', + maxHeight: '100%', +}) + +export type MenuGraphicsKind = 'icon' | 'image' + +export const propTypes = { + kind: PropTypes.oneOf(['icon', 'image']).isRequired, + alt: PropTypes.string, + id: PropTypes.string.isRequired, +} + +type Props = PropTypes.InferProps + +const MenuGraphics: React.FC = ({ + kind, + alt, + id, +}) => { + switch (kind) { + case 'icon': + return ( + + ) + case 'image': + return ( + {alt} + ) + default: + break + } + + return null +} + +MenuGraphics.propTypes = propTypes + +export default MenuGraphics diff --git a/packages/react-common-docs/src/components/Nav/Nav.tsx b/packages/react-common-docs/src/components/Nav/Nav.tsx new file mode 100644 index 0000000..1415a35 --- /dev/null +++ b/packages/react-common-docs/src/components/Nav/Nav.tsx @@ -0,0 +1,91 @@ +import * as React from 'react' +import Link from 'next/link' +import styled from 'styled-components' +import NavLink from '../NavLink/NavLink' + +const StyledLink = styled('a')({ + display: 'block', + textDecoration: 'none', +}) + +const Container = styled('span')({ + display: 'flex', + alignItems: 'center', + padding: '0 1rem', + height: '100%', + margin: '0 0 0 auto', + boxSizing: 'border-box', + '@media (min-width: 720px)': { + maxWidth: 'var(--max-width)', + }, +}) + +const HeaderContainer = styled(Container)({ + marginTop: '2rem', +}) + +const NavContainer = styled('div')({ + +}) + +const Nav = ({ + data, +}) => { + if (Array.isArray(data)) { + return ( + + { + data.map(d => ( +