Bläddra i källkod

Add Next.js + MDX support

Implement Next.js MDX

Separate the docs from the code and tests.
tags/0.3.0
TheoryOfNekomata 4 år sedan
förälder
incheckning
36954ed21c
59 ändrade filer med 7524 tillägg och 265 borttagningar
  1. +2
    -2
      jest.config.js
  2. +0
    -25
      lib/components/Checkbox/Checkbox.mdx
  3. +0
    -20
      lib/components/Icon/Icon.mdx
  4. +0
    -32
      lib/components/RadioButton/RadioButton.mdx
  5. +0
    -45
      lib/components/Select/Select.mdx
  6. +0
    -71
      lib/components/TextInput/TextInput.mdx
  7. +0
    -42
      lib/services/isEmpty.test.ts
  8. +30
    -0
      packages/react-common-docs/README.md
  9. +9
    -0
      packages/react-common-docs/brand.tsx
  10. +2
    -0
      packages/react-common-docs/next-env.d.ts
  11. +6
    -0
      packages/react-common-docs/next.config.js
  12. +19
    -0
      packages/react-common-docs/package.json
  13. Binär
      packages/react-common-docs/public/favicon.ico
  14. +52
    -0
      packages/react-common-docs/public/global.css
  15. +127
    -0
      packages/react-common-docs/public/theme/dark.css
  16. +138
    -0
      packages/react-common-docs/public/theme/light.css
  17. +4
    -0
      packages/react-common-docs/public/vercel.svg
  18. +91
    -0
      packages/react-common-docs/src/components/Nav.tsx
  19. +47
    -0
      packages/react-common-docs/src/components/Playground.tsx
  20. +96
    -0
      packages/react-common-docs/src/components/Sidebar.tsx
  21. +35
    -0
      packages/react-common-docs/src/pages/_app.tsx
  22. +45
    -0
      packages/react-common-docs/src/pages/_document.tsx
  23. +12
    -9
      packages/react-common-docs/src/pages/components/Button.mdx
  24. +26
    -0
      packages/react-common-docs/src/pages/components/Checkbox.mdx
  25. +21
    -0
      packages/react-common-docs/src/pages/components/Icon.mdx
  26. +33
    -0
      packages/react-common-docs/src/pages/components/RadioButton.mdx
  27. +46
    -0
      packages/react-common-docs/src/pages/components/Select.mdx
  28. +9
    -8
      packages/react-common-docs/src/pages/components/Slider.mdx
  29. +78
    -0
      packages/react-common-docs/src/pages/components/TextInput.mdx
  30. +1
    -0
      packages/react-common-docs/src/pages/index.md
  31. +0
    -0
      packages/react-common-docs/src/pages/theming.md
  32. +18
    -0
      packages/react-common-docs/src/sidebar.json
  33. +37
    -0
      packages/react-common-docs/tsconfig.json
  34. +6489
    -0
      packages/react-common-docs/yarn.lock
  35. +1
    -1
      packages/react-common/components/Button/Button.test.tsx
  36. +0
    -0
      packages/react-common/components/Button/Button.tsx
  37. +1
    -1
      packages/react-common/components/Checkbox/Checkbox.test.tsx
  38. +0
    -0
      packages/react-common/components/Checkbox/Checkbox.tsx
  39. +1
    -1
      packages/react-common/components/Icon/Icon.test.tsx
  40. +0
    -0
      packages/react-common/components/Icon/Icon.tsx
  41. +1
    -1
      packages/react-common/components/RadioButton/RadioButton.test.tsx
  42. +0
    -0
      packages/react-common/components/RadioButton/RadioButton.tsx
  43. +1
    -1
      packages/react-common/components/Select/Select.test.tsx
  44. +0
    -0
      packages/react-common/components/Select/Select.tsx
  45. +1
    -1
      packages/react-common/components/Slider/Slider.test.tsx
  46. +0
    -0
      packages/react-common/components/Slider/Slider.tsx
  47. +1
    -1
      packages/react-common/components/TextInput/TextInput.test.tsx
  48. +0
    -0
      packages/react-common/components/TextInput/TextInput.tsx
  49. +1
    -1
      packages/react-common/index.test.ts
  50. +0
    -0
      packages/react-common/index.ts
  51. +40
    -0
      packages/react-common/services/isEmpty.test.ts
  52. +0
    -0
      packages/react-common/services/isEmpty.ts
  53. +0
    -0
      packages/react-common/services/splitValueAndUnit.test.ts
  54. +0
    -0
      packages/react-common/services/splitValueAndUnit.ts
  55. +1
    -1
      packages/react-common/services/stringify.test.ts
  56. +0
    -0
      packages/react-common/services/stringify.ts
  57. +0
    -0
      packages/react-common/services/utilities.ts
  58. +1
    -1
      plopfile.js
  59. +1
    -1
      rollup.config.js

+ 2
- 2
jest.config.js Visa fil

@@ -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,


+ 0
- 25
lib/components/Checkbox/Checkbox.mdx Visa fil

@@ -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.

<Playground>
<Checkbox label="Accept Terms" />
</Playground>

## Props

<Props of={Checkbox} />

## See Also

- <Link to="../select">Select</Link> for a similar component suitable for selecting more values.
- <Link to="../radiobutton">RadioButton</Link> for a similar component on selecting a single value among very few choices.

+ 0
- 20
lib/components/Icon/Icon.mdx Visa fil

@@ -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.

<Playground>
<Icon name="check" label="OK" size="1.5rem" weight={0.125} />
</Playground>

## Props

<Props of={Icon} />

+ 0
- 32
lib/components/RadioButton/RadioButton.mdx Visa fil

@@ -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.

<Playground>
<div style={{ display: 'grid', gap: '1rem', }}>
<div>
<RadioButton name="flavor" label="Chocolate" />
</div>
<div>
<RadioButton name="flavor" label="Vanilla" />
</div>
</div>
</Playground>

## Props

<Props of={RadioButton} />

## See Also

- <Link to="../checkbox">Checkbox</Link> for a similar component on selecting values among very few choices.
- <Link to="../select">Select</Link> for a similar component suitable for selecting more values.

+ 0
- 45
lib/components/Select/Select.mdx Visa fil

@@ -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.

<Playground>
<Select>
<optgroup
label="Fruits"
>
<option value="mango">Mango</option>
<option value="strawberry">Strawberry</option>
<option value="blueberry">Blueberry</option>
</optgroup>
<optgroup
label="Classic"
>
<option value="chocolate">Chocolate</option>
<option value="vanilla">Vanilla</option>
</optgroup>
</Select>
</Playground>

## Props

<Props of={Select} />

## 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

- <Link to="../checkbox">Checkbox</Link> for a similar component on selecting values among very few choices.
- <Link to="../radiobutton">RadioButton</Link> for a similar component on selecting a single value among very few choices.

+ 0
- 71
lib/components/TextInput/TextInput.mdx Visa fil

@@ -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.

<Playground>
<TextInput label="Username" placeholder="johndoe" hint="the name you use to log in" />
</Playground>

## Props

<Props of={TextInput} />

## 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.

<Playground>
<form>
I am <span style={{ display: 'inline-block', width: '16rem', }}><TextInput label="Full name" hint="given and family name" /></span> and I live in <span style={{ display: 'inline-block', width: '24rem', }}><TextInput label="Address" hint="city, state and country" /></span>.
</form>
</Playground>

### 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.

<Playground>
<form
style={{ display: 'grid', gridTemplateColumns: '4fr 4fr 5fr', gap: '1rem', }}
>
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}>
<TextInput label="Address line 1" hint="unit/house number, building" />
</div>
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}>
<TextInput label="Address line 2" hint="street, area" />
</div>
<div>
<TextInput size="large" label="City/Town" />
</div>
<div>
<TextInput size="large" label="State/Province" />
</div>
<div>
<TextInput size="large" label="Country" hint="abbreviations are accepted" />
<small>
Consult the <a href="#">fees table</a> for shipping fee details.
</small>
</div>
</form>
</Playground>

## See Also

- <Link to="../select">Select</Link> for a graphically-similar component suitable for selecting more values.

+ 0
- 42
lib/services/isEmpty.test.ts Visa fil

@@ -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)
}),
)
})
})
})

+ 30
- 0
packages/react-common-docs/README.md Visa fil

@@ -0,0 +1,30 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

+ 9
- 0
packages/react-common-docs/brand.tsx Visa fil

@@ -0,0 +1,9 @@
const Brand = () => (
<div>
<strong>
Tesseract
</strong>
</div>
)

export default Brand

+ 2
- 0
packages/react-common-docs/next-env.d.ts Visa fil

@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

+ 6
- 0
packages/react-common-docs/next.config.js Visa fil

@@ -0,0 +1,6 @@
const withMDX = require('next-mdx-frontmatter')({
extension: /\.mdx?$/
})
module.exports = withMDX({
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx']
})

+ 19
- 0
packages/react-common-docs/package.json Visa fil

@@ -0,0 +1,19 @@
{
"name": "react-common-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@mdx-js/loader": "^1.6.19",
"@tesseract-design/react-common": "^0.2.1",
"next": "10.0.1",
"next-mdx-frontmatter": "^0.0.3",
"pascalcase": "^1.0.0",
"react-live": "^2.2.3",
"styled-components": "^5.2.1"
}
}

Binär
packages/react-common-docs/public/favicon.ico Visa fil

Före Efter

+ 52
- 0
packages/react-common-docs/public/global.css Visa fil

@@ -0,0 +1,52 @@
body {
margin: 0;
}

h1 {
font-size: 3em;
text-transform: lowercase;
}

h2 {
font-size: 2em;
text-transform: lowercase;
}

h3 {
font-size: 1.75em;
text-transform: lowercase;
}

h4 {
text-transform: lowercase;
}

h5 {
text-transform: lowercase;
}

h6 {
text-transform: lowercase;
}

p {
margin: 2em 0;
}

small {
font-size: 0.75em;
}

a:focus {
color: var(--color-active);
outline: 0;
}

::selection {
background-color: var(--color-active);
color: var(--color-fg);
}

:root {
caret-color: var(--color-active);
}

+ 127
- 0
packages/react-common-docs/public/theme/dark.css Visa fil

@@ -0,0 +1,127 @@
@font-face {
font-family: 'Encode Sans';
font-stretch: semi-expanded;
font-weight: 400;
src:
local('Encode Sans Semi Expanded'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: semi-expanded;
font-weight: 700;
src:
local('Encode Sans Semi Expanded Bold'),
local('Encode Sans Semi Expanded'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 100;
src:
local('Encode Sans Condensed Thin'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 200;
src:
local('Encode Sans Condensed ExtraLight'),
local('Encode Sans Condensed Extra Light'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 300;
src:
local('Encode Sans Condensed Light'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

:root {
--color-active: #f90;
--font-family-base: 'Encode Sans Semi Expanded', 'Encode Sans', system-ui;
--font-stretch-base: semi-expanded;
--font-weight-base: 400;
--line-height-base: 2;
--font-family-headings:'Encode Sans Condensed', 'Encode Sans', system-ui;
--font-stretch-headings: condensed;
--font-weight-headings: 100;
--line-height-headings: 1.5;
--font-family-monospace: 'mononoki';
--font-size-root: 16px;
--color-negative: #222;
--color-positive: #eee;
--color-accent: #C78AB3;
--opacity-light: 0.25;
--opacity-lighter: 0.5;
--opacity-lightest: 0.75;
}

:root {
--color-bg: var(--color-negative, white);
--color-fg: var(--color-positive, black);
background-color: var(--color-bg);
color: var(--color-fg);
font-size: var(--font-size-root);
font-family: var(--font-family-base), sans-serif;
font-stretch: var(--font-stretch-base, normal);
font-weight: var(--font-weight-base, 400);
line-height: var(--line-height-base, 2);
}

h1 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h2 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h3 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h4 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h5 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h6 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

a {
color: var(--color-accent);
}

+ 138
- 0
packages/react-common-docs/public/theme/light.css Visa fil

@@ -0,0 +1,138 @@
@font-face {
font-family: 'Encode Sans';
font-stretch: semi-expanded;
font-weight: 400;
src:
local('Encode Sans Semi Expanded'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: semi-expanded;
font-weight: 700;
src:
local('Encode Sans Semi Expanded Bold'),
local('Encode Sans Semi Expanded'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 100;
src:
local('Encode Sans Condensed Thin'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 200;
src:
local('Encode Sans Condensed ExtraLight'),
local('Encode Sans Condensed Extra Light'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

@font-face {
font-family: 'Encode Sans';
font-stretch: condensed;
font-weight: 300;
src:
local('Encode Sans Condensed Light'),
local('Encode Sans Condensed'),
local('Encode Sans');
}

:root {
--color-negative: #eee;
--color-positive: #222;
--color-accent: #ba6a9c;
--color-active: #f90;
--font-family-base: 'Encode Sans Semi Expanded', 'Encode Sans', system-ui;
--font-stretch-base: semi-expanded;
--font-weight-base: 400;
--line-height-base: 2;
--font-family-headings:'Encode Sans Condensed', 'Encode Sans', system-ui;
--font-stretch-headings: condensed;
--font-weight-headings: 100;
--line-height-headings: 1.5;
--font-family-monospace: 'mononoki';
--font-size-root: 16px;
--opacity-light: 0.5;
--opacity-lighter: 0.75;
--opacity-lightest: 0.875;
}

/*@media (prefers-color-scheme: dark) {*/
/* :root {*/
/* --color-negative: #222;*/
/* --color-positive: #eee;*/
/* --color-accent: #C78AB3;*/
/* --opacity-light: 0.25;*/
/* --opacity-lighter: 0.5;*/
/* --opacity-lightest: 0.75;*/
/* }*/
/*}*/

:root {
--color-bg: var(--color-negative, white);
--color-fg: var(--color-positive, black);
background-color: var(--color-bg);
color: var(--color-fg);
font-size: var(--font-size-root);
font-family: var(--font-family-base), sans-serif;
font-stretch: var(--font-stretch-base, normal);
font-weight: var(--font-weight-base, 400);
line-height: var(--line-height-base, 2);
}

h1 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h2 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h3 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h4 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h5 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h6 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

a {
color: var(--color-accent);
}

+ 4
- 0
packages/react-common-docs/public/vercel.svg Visa fil

@@ -0,0 +1,4 @@
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>

+ 91
- 0
packages/react-common-docs/src/components/Nav.tsx Visa fil

@@ -0,0 +1,91 @@
import * as React from 'react'
import Link from 'next/link'
import styled from 'styled-components'

const StyledLink = styled('a')({
display: 'block',
textDecoration: 'none',
})

const Container = styled('span')({
display: 'flex',
alignItems: 'center',
padding: '0 1rem',
height: '2rem',
margin: '0 0 0 auto',
'@media (min-width: 720px)': {
maxWidth: 360,
},
})

const HeaderContainer = styled(Container)({
marginTop: '2rem',
})

const NavContainer = styled('div')({

})

const Nav = ({
data,
}) => {
if (Array.isArray(data)) {
return (
<NavContainer>
{
data.map(d => (
<Nav
data={d}
/>
))
}
</NavContainer>
)
}
if (typeof data === 'object') {
const [entry] = Object.entries(data)
const [key, value] = entry
if (Array.isArray(value)) {
return (
<NavContainer>
<HeaderContainer>
{key}
</HeaderContainer>
{
value.map(v => (
<Nav
data={v}
/>
))
}
</NavContainer>
)
}
return (
<Link
href={value}
passHref
>
<StyledLink>
<Container>
{key}
</Container>
</StyledLink>
</Link>
)
}
return (
<Link
href={data}
passHref
>
<StyledLink>
<Container>
{data}
</Container>
</StyledLink>
</Link>
)
}

export default Nav

+ 47
- 0
packages/react-common-docs/src/components/Playground.tsx Visa fil

@@ -0,0 +1,47 @@
import * as React from 'react'
import {
LiveProvider,
LiveEditor,
LivePreview
} from 'react-live'
import styled from 'styled-components'

const Figure = styled('figure')({
margin: 0,
})

const Playground = ({
components,
code,
label,
}) => {
const indentLevel = code.indexOf('<') - 1
const normalizedCode = code
.split('\n')
.map((s: string) => s.slice(indentLevel))
.filter((s: string) => s.trim().length > 0)
.join('\n')

return (
<div>
<Figure>
{
label
&& (
<figcaption>
{label}
</figcaption>
)
}
<div>
<LiveProvider code={normalizedCode} scope={components}>
<LivePreview />
<LiveEditor />
</LiveProvider>
</div>
</Figure>
</div>
)
}

export default Playground

+ 96
- 0
packages/react-common-docs/src/components/Sidebar.tsx Visa fil

@@ -0,0 +1,96 @@
import styled from 'styled-components'
import Nav from './Nav'
import Link from 'next/link'
import * as React from 'react'
import { Checkbox } from '@tesseract-design/react-common'

const StyledLink = styled('a')({
display: 'block',
textDecoration: 'none',
marginBottom: '2rem',
})

const Container = styled('span')({
display: 'flex',
alignItems: 'center',
padding: '0 1rem',
height: '2rem',
margin: '0 0 0 auto',
'@media (min-width: 720px)': {
maxWidth: 360,
},
})

const Base = styled('aside')({
position: 'fixed',
top: 0,
left: '-100%',
width: '100%',
height: '100%',
backgroundColor: 'var(--color-bg)',
zIndex: 4,
'@media (min-width: 720px)': {
left: 0,
width: `${100 / 3}%`,
maxWidth: 'none',
height: '100%',
'+ *': {
paddingLeft: `${100 / 3}%`,
boxSizing: 'border-box',
},
},
})

const Sidebar = ({
data,
brand: Brand,
}) => {
const [dark, setDark] = React.useState(false)

const toggleDarkMode = b => () => {
setDark(b)
}

React.useEffect(() => {
const stylesheets = Array.from(window.document.querySelectorAll('link[title]'))

stylesheets.forEach(s => {
if (s.getAttribute('rel').includes('alternate')) {
s.setAttribute('rel', 'stylesheet')
s.removeAttribute('disabled')
} else {
s.setAttribute('rel', 'alternate stylesheet')
s.setAttribute('disabled', 'disabled')
}
})
}, [dark])

return (
<Base>
<Container>
<input
type="checkbox"
defaultChecked={dark}
onChange={toggleDarkMode(!dark)}
/>
</Container>
<nav>
<Link
href="/"
passHref
>
<StyledLink>
<Container>
<Brand />
</Container>
</StyledLink>
</Link>
<Nav
data={data.nav}
/>
</nav>
</Base>
)
}

export default Sidebar

+ 35
- 0
packages/react-common-docs/src/pages/_app.tsx Visa fil

@@ -0,0 +1,35 @@
import '../../public/global.css'
import '../../public/theme/dark.css'
import sidebar from '../sidebar.json'
import brand from '../../brand'
import Sidebar from '../components/Sidebar'
import styled from 'styled-components'

const Container = styled('div')({
maxWidth: 720,
margin: '0 auto',
padding: '0 1rem',
boxSizing: 'border-box',
})

const App = ({
Component,
pageProps,
...etc
}) => (
<div>
<Sidebar
brand={brand}
data={sidebar}
/>
<main>
<Container>
<Component
{...pageProps}
/>
</Container>
</main>
</div>
)

export default App

+ 45
- 0
packages/react-common-docs/src/pages/_document.tsx Visa fil

@@ -0,0 +1,45 @@
import Document, { Html, Head, Main, NextScript, DocumentContext } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage

try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})

const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<link rel="stylesheet" href="/global.css" />
<link rel="stylesheet" title="Dark" href="/theme/dark.css" />
<link rel="alternate stylesheet" title="Light" href="/theme/light.css" />
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}

render() {
return (
<Html lang="en-PH">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}

lib/components/Button/Button.mdx → packages/react-common-docs/src/pages/components/Button.mdx Visa fil

@@ -1,23 +1,26 @@
---
name: Button
route: /components/button
menu: Components
title: Button
---

import { Playground, Props } from 'docz'
import Button from './Button'
import { Button } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# Button

Component for performing an action upon activation (e.g. when clicked).

<Playground>
<Button>Perform Action</Button>
</Playground>
<Playground
code={`
<Button>
Perform Action
</Button>
`}
components={{ Button }}
/>

## Props

<Props of={Button} />
Props

## Usage Notes


+ 26
- 0
packages/react-common-docs/src/pages/components/Checkbox.mdx Visa fil

@@ -0,0 +1,26 @@
---
name: Checkbox
---

import { Checkbox } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# Checkbox

Component for values that have an on/off state.

<Playground
components={{ Checkbox }}
code={`
<Checkbox label="Accept Terms" />
`}
/>

## Props

Props

## See Also

- [Select](./Select) for a similar component suitable for selecting more values.
- [RadioButton](./RadioButton) for a similar component on selecting a single value among very few choices.

+ 21
- 0
packages/react-common-docs/src/pages/components/Icon.mdx Visa fil

@@ -0,0 +1,21 @@
---
name: Icon
---

import { Icon } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# Icon

Component for displaying graphics.

<Playground
components={{ Icon }}
code={`
<Icon name="check" label="OK" size="1.5rem" weight={0.125} />
`}
/>

## Props

Props

+ 33
- 0
packages/react-common-docs/src/pages/components/RadioButton.mdx Visa fil

@@ -0,0 +1,33 @@
---
name: RadioButton
---

import { RadioButton } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# RadioButton

Component for values which are to be selected from a few list of options.

<Playground
components={{ RadioButton }}
code={`
<div style={{ display: 'grid', gap: '1rem', }}>
<div>
<RadioButton name="flavor" label="Chocolate" />
</div>
<div>
<RadioButton name="flavor" label="Vanilla" />
</div>
</div>
`}
/>

## Props

Props

## See Also

- [Checkbox](./Checkbox) for a similar component on selecting values among very few choices.
- [Select](./Select) for a similar component suitable for selecting more values.

+ 46
- 0
packages/react-common-docs/src/pages/components/Select.mdx Visa fil

@@ -0,0 +1,46 @@
---
name: Select
---

import { Select } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# Select

Component for selecting values from a larger number of options.

<Playground
components={{ Select }}
code={`
<Select>
<optgroup
label="Fruits"
>
<option value="mango">Mango</option>
<option value="strawberry">Strawberry</option>
<option value="blueberry">Blueberry</option>
</optgroup>
<optgroup
label="Classic"
>
<option value="chocolate">Chocolate</option>
<option value="vanilla">Vanilla</option>
</optgroup>
</Select>
`}
/>

## Props

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](./Checkbox) for a similar component on selecting values among very few choices.
- [RadioButton](./RadioButton) for a similar component on selecting a single value among very few choices.

lib/components/Slider/Slider.mdx → packages/react-common-docs/src/pages/components/Slider.mdx Visa fil

@@ -1,11 +1,9 @@
---
name: Slider
route: /components/slider
menu: Components
---

import { Playground, Props } from 'docz'
import Slider from './Slider'
import { Slider } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# Slider

@@ -14,13 +12,16 @@ 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 `<input type="range">` element.

<Playground>
<Slider />
</Playground>
<Playground
components={{ Slider }}
code={`
<Slider />
`}
/>

## Props

<Props of={Slider} />
Props

## See Also


+ 78
- 0
packages/react-common-docs/src/pages/components/TextInput.mdx Visa fil

@@ -0,0 +1,78 @@
---
name: TextInput
---

import { TextInput } from '@tesseract-design/react-common'
import Playground from '../../components/Playground'

# TextInput

Component for inputting textual values.

<Playground
components={{ TextInput }}
code={`
<TextInput label="Username" placeholder="johndoe" hint="the name you use to log in" />
`}
/>

## Props

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.

<Playground
components={{ TextInput }}
code={`
<form>
I am <span style={{ display: 'inline-block', width: '16rem', }}><TextInput label="Full name" hint="given and family name" /></span> and I live in <span style={{ display: 'inline-block', width: '24rem', }}><TextInput label="Address" hint="city, state and country" /></span>.
</form>
`}
/>

### 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.

<Playground
components={{ TextInput }}
code={`
<form
style={{ display: 'grid', gridTemplateColumns: '4fr 4fr 5fr', gap: '1rem', }}
>
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}>
<TextInput label="Address line 1" hint="unit/house number, building" />
</div>
<div style={{ gridColumnStart: 1, gridColumnEnd: 4, }}>
<TextInput label="Address line 2" hint="street, area" />
</div>
<div>
<TextInput size="large" label="City/Town" />
</div>
<div>
<TextInput size="large" label="State/Province" />
</div>
<div>
<TextInput size="large" label="Country" hint="abbreviations are accepted" />
<small>
Consult the <a href="#">fees table</a> for shipping fee details.
</small>
</div>
</form>
`}
/>

## See Also

- [Select](./Select) for a graphically-similar component suitable for selecting more values.

+ 1
- 0
packages/react-common-docs/src/pages/index.md Visa fil

@@ -0,0 +1 @@
../../../../README.md

docs/theming.md → packages/react-common-docs/src/pages/theming.md Visa fil


+ 18
- 0
packages/react-common-docs/src/sidebar.json Visa fil

@@ -0,0 +1,18 @@
{
"nav": [
{
"Theming": "/theming"
},
{
"Components": [
{ "Button": "/components/Button" },
{ "Checkbox": "/components/Checkbox" },
{ "Icon": "/components/Icon" },
{ "RadioButton": "/components/RadioButton" },
{ "Select": "/components/Select" },
{ "Slider": "/components/Slider" },
{ "TextInput": "/components/TextInput" }
]
}
]
}

+ 37
- 0
packages/react-common-docs/tsconfig.json Visa fil

@@ -0,0 +1,37 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"declaration": true,
"declarationDir": "./dist",
"sourceMap": true
},
"exclude": [
"node_modules",
"**/*.test.ts",
"**/*.test.tsx",
"utilities/**/*",
"jest.setup.ts"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}

+ 6489
- 0
packages/react-common-docs/yarn.lock
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


lib/components/Button/Button.test.tsx → packages/react-common/components/Button/Button.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/Button/Button.tsx → packages/react-common/components/Button/Button.tsx Visa fil


lib/components/Checkbox/Checkbox.test.tsx → packages/react-common/components/Checkbox/Checkbox.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/Checkbox/Checkbox.tsx → packages/react-common/components/Checkbox/Checkbox.tsx Visa fil


lib/components/Icon/Icon.test.tsx → packages/react-common/components/Icon/Icon.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/Icon/Icon.tsx → packages/react-common/components/Icon/Icon.tsx Visa fil


lib/components/RadioButton/RadioButton.test.tsx → packages/react-common/components/RadioButton/RadioButton.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/RadioButton/RadioButton.tsx → packages/react-common/components/RadioButton/RadioButton.tsx Visa fil


lib/components/Select/Select.test.tsx → packages/react-common/components/Select/Select.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/Select/Select.tsx → packages/react-common/components/Select/Select.tsx Visa fil


lib/components/Slider/Slider.test.tsx → packages/react-common/components/Slider/Slider.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/Slider/Slider.tsx → packages/react-common/components/Slider/Slider.tsx Visa fil


lib/components/TextInput/TextInput.test.tsx → packages/react-common/components/TextInput/TextInput.test.tsx Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../../../utilities/jest/extensions.ts" />
/// <reference path="../../../../utilities/jest/extensions.ts" />

import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'

lib/components/TextInput/TextInput.tsx → packages/react-common/components/TextInput/TextInput.tsx Visa fil


lib/index.test.ts → packages/react-common/index.test.ts Visa fil

@@ -1,5 +1,5 @@
/// <reference types="jest-enzyme" />
/// <reference path="../utilities/jest/extensions.ts" />
/// <reference path="../../utilities/jest/extensions.ts" />

import * as T from './index'


lib/index.ts → packages/react-common/index.ts Visa fil


+ 40
- 0
packages/react-common/services/isEmpty.test.ts Visa fil

@@ -0,0 +1,40 @@
import * as fc from 'fast-check'
import isEmpty from './isEmpty'

it('should exist', () => {
expect(isEmpty).toBeDefined()
})

it('should be a function', () => {
expect(typeof isEmpty).toBe('function')
})

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)
}),
)
})
})

lib/services/isEmpty.ts → packages/react-common/services/isEmpty.ts Visa fil


lib/services/splitValueAndUnit.test.ts → packages/react-common/services/splitValueAndUnit.test.ts Visa fil


lib/services/splitValueAndUnit.ts → packages/react-common/services/splitValueAndUnit.ts Visa fil


lib/services/stringify.test.ts → packages/react-common/services/stringify.test.ts Visa fil

@@ -1,5 +1,5 @@
import * as fc from 'fast-check'
import * as fcArb from '../../utilities/fast-check/arbitraries'
import * as fcArb from '../../../utilities/fast-check/arbitraries'
import stringify from './stringify'

it('should exist', () => {

lib/services/stringify.ts → packages/react-common/services/stringify.ts Visa fil


lib/services/utilities.ts → packages/react-common/services/utilities.ts Visa fil


+ 1
- 1
plopfile.js Visa fil

@@ -23,7 +23,7 @@ module.exports = plop => {
type: 'addMany',
templateFiles: 'plop/templates/component/*',
base: 'plop/templates/component',
destination: 'lib/components/{{pascalCase name}}',
destination: 'packages/react-common/components/{{pascalCase name}}',
},
],
})


+ 1
- 1
rollup.config.js Visa fil

@@ -4,7 +4,7 @@ import typescript from '@rollup/plugin-typescript'

import pkg from './package.json'

const ENTRY_POINT = './lib/index.ts'
const ENTRY_POINT = './packages/react-common/index.ts'

export default {
input: ENTRY_POINT,


Laddar…
Avbryt
Spara