├── .eslintrc.json ├── .github ├── renovate.json └── workflows │ ├── deploy.yml │ ├── release.yml │ └── update-alpha.yml ├── .gitignore ├── .prettierrc ├── .storybook ├── main.cjs └── preview-head.html ├── @types └── index.d.ts ├── CHANGELOG.md ├── CNAME ├── LICENSE ├── README.md ├── docs ├── pages │ ├── getting-started.mdx │ └── index.jsx └── src │ ├── Main.tsx │ ├── components │ ├── Code.css │ ├── Code.tsx │ ├── PropTable.module.css │ └── PropTable.tsx │ └── plugins │ ├── jsxExample.cjs │ └── propTable.cjs ├── esbuild.mjs ├── index.html ├── package-lock.json ├── package.json ├── packages ├── _helpers │ ├── affix.tsx │ ├── clickable.tsx │ ├── dead-toggle.tsx │ ├── expand-transition.tsx │ ├── index.ts │ ├── props.ts │ └── unstyled-heading.tsx ├── alert │ ├── docs │ │ └── Alert.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Alert.stories.tsx ├── attention │ ├── docs │ │ └── Attention.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.ts │ └── stories │ │ └── Attention.stories.tsx ├── box │ ├── docs │ │ └── Box.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Box.stories.tsx ├── breadcrumbs │ ├── docs │ │ └── Breadcrumbs.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Breadcrumbs.stories.tsx ├── button │ ├── docs │ │ └── Button.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Button.stories.tsx ├── card │ ├── docs │ │ └── Card.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Card.stories.tsx ├── combobox │ ├── docs │ │ └── Combobox.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ ├── props.ts │ │ └── utils.ts │ └── stories │ │ └── Combobox.stories.tsx ├── expandable │ ├── docs │ │ └── Expandable.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Expandable.stories.tsx ├── index.ts ├── modal │ ├── docs │ │ └── Modal.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.ts │ └── stories │ │ └── Modal.stories.tsx ├── pill │ ├── docs │ │ └── Pill.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Button.stories.tsx ├── select │ ├── __tests__ │ │ └── Select.test.tsx │ ├── docs │ │ └── Select.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Select.stories.tsx ├── slider │ ├── docs │ │ └── Slider.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.ts │ └── stories │ │ └── Slider.stories.tsx ├── steps │ ├── docs │ │ └── Steps.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ ├── props.tsx │ │ └── step.tsx │ └── stories │ │ └── Steps.stories.tsx ├── switch │ ├── docs │ │ └── Switch.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.tsx │ └── stories │ │ └── Switch.stories.tsx ├── tabs │ ├── __tests__ │ │ ├── Tabs.test.tsx │ │ └── __snapshots__ │ │ │ └── Tabs.test.tsx.snap │ ├── docs │ │ └── Tabs.mdx │ ├── src │ │ ├── component-tab-panel.tsx │ │ ├── component-tab.tsx │ │ ├── component-tabs.tsx │ │ ├── index.ts │ │ ├── props.ts │ │ └── utils.ts │ └── stories │ │ └── Tabs.stories.tsx ├── textarea │ ├── __tests__ │ │ └── TextArea.test.tsx │ ├── docs │ │ └── TextArea.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ ├── props.ts │ │ └── useTextAreaHeight.ts │ └── stories │ │ └── TextArea.stories.tsx ├── textfield │ ├── __tests__ │ │ └── Textfield.test.tsx │ ├── docs │ │ └── TextField.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ └── props.ts │ └── stories │ │ └── Textfield.stories.tsx ├── toggle │ ├── docs │ │ └── Toggle.mdx │ ├── src │ │ ├── component.tsx │ │ ├── index.ts │ │ ├── item.tsx │ │ └── props.ts │ └── stories │ │ ├── Checkbox.stories.tsx │ │ ├── Radio.stories.tsx │ │ └── RadioButtons.stories.tsx └── utils │ └── src │ ├── index.ts │ ├── useElementSizeObserver.ts │ ├── useId.ts │ ├── useIsomorphicLayoutEffect.ts │ └── useLogDeprecationWarning.ts ├── release.config.cjs ├── tests ├── eik-react-jsx │ ├── README.md │ ├── index.html │ ├── index.jsx │ └── package.json ├── eik-react │ ├── README.md │ ├── index.html │ ├── index.js │ └── package.json ├── ssr-react-16-cjs │ ├── README.md │ ├── package.json │ └── src │ │ ├── client.jsx │ │ ├── index.jsx │ │ └── server.js ├── ssr-react-16 │ ├── README.md │ ├── client.jsx │ ├── index.jsx │ ├── package.json │ └── server.js ├── ssr-react-ts-16-cjs │ ├── README.md │ ├── package.json │ └── src │ │ ├── client.tsx │ │ ├── index.tsx │ │ └── server.ts └── ssr-react-ts-16 │ ├── README.md │ ├── package.json │ └── src │ ├── client.tsx │ ├── index.tsx │ └── server.ts ├── tsconfig.json └── vite.config.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["react-app"], 3 | "rules": { 4 | // Disabling this rule as we sometimes create empty links for example purposes 5 | "jsx-a11y/anchor-is-valid": 0, 6 | // Disabling this rule as we mostly pass props forward (including children) 7 | "jsx-a11y/heading-has-content": 0 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>podium-lib/renovate-presets:top-level-module"], 4 | "baseBranches": ["next"], 5 | "lockFileMaintenance": { 6 | "automerge": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation to GitHub Pages and publish package 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | - name: Install Dependencies 15 | run: | 16 | npm install 17 | - name: Build Packages 18 | run: | 19 | npm run build 20 | - name: Build Docs 21 | run: | 22 | npm run docs:build 23 | - name: Deploy 24 | if: success() 25 | uses: crazy-max/ghaction-github-pages@v3 26 | with: 27 | target_branch: gh-pages 28 | build_dir: site 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - next 8 | 9 | jobs: 10 | release: 11 | name: Release 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | - name: Setup Node.js 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: '16.x' 22 | - name: Install dependencies 23 | run: npm install 24 | - name: Build 25 | run: npm run build 26 | - name: Release 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 30 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} 31 | run: npx semantic-release 32 | - name: Eik login and publish 33 | run: npm run eik:login -- -k $EIK_TOKEN && npm run eik:publish || true 34 | env: 35 | EIK_TOKEN: ${{ secrets.EIK_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/update-alpha.yml: -------------------------------------------------------------------------------- 1 | name: Update next 2 | on: 3 | workflow_run: 4 | workflows: 5 | - Release 6 | branches: 7 | - main 8 | types: completed 9 | jobs: 10 | rebase: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | - name: Rebase next to main 16 | run: | 17 | git fetch --unshallow 18 | git checkout next 19 | git rebase origin/main 20 | git push 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock 4 | yarn-error.log 5 | 6 | # doc site build 7 | site/ 8 | 9 | dist/ 10 | .eik 11 | 12 | *.log 13 | *.swp 14 | 15 | # editors 16 | .idea/ 17 | .vscode/ 18 | 19 | # os 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "proseWrap": "always", 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "tabWidth": 2, 6 | "overrides": [ 7 | { 8 | "files": "*.css", 9 | "options": { 10 | "singleQuote": false 11 | } 12 | }, 13 | { 14 | "files": "*.json", 15 | "options": { 16 | "tabWidth": 2 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.storybook/main.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | core: { 3 | builder: 'webpack5', 4 | }, 5 | stories: ['../packages/**/*.stories.[tj]sx'], 6 | addons: ['@storybook/addon-actions/register', '@storybook/addon-postcss'], 7 | framework: '@storybook/react', 8 | webpackFinal: async (config) => { 9 | config.resolve.alias['@fabric-ds/core/attention'] = require.resolve( 10 | '../node_modules/@fabric-ds/core/dist/attention/index.js', 11 | ); 12 | config.module.rules.push({ 13 | test: /\.js$/, 14 | include: /node_modules/, 15 | use: [ 16 | { 17 | loader: require.resolve('babel-loader'), 18 | options: { 19 | presets: [require('@babel/preset-env').default], 20 | }, 21 | }, 22 | ], 23 | }); 24 | config.resolve.extensions.push('.js'); 25 | return config; 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /@types/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.mdx' { 2 | const content: React.FunctionComponent<{}>; 3 | export default content; 4 | } 5 | 6 | declare module '*.module.css' { 7 | const classes: { [key: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '@fabric-ds/css'; 12 | declare module '@fabric-ds/css/component-classes'; 13 | declare module '@fabric-ds/css/tailwind-css'; 14 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | react.fabric-ds.io -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 FINN.no 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fabric React 2 | 3 | Reacts components exported under `@fabric-ds/react`. 4 | 5 | ## Development 6 | 7 | The project uses [Storybook](https://storybook.js.org/) for component 8 | development. Start the storybook instance by running the following command: 9 | 10 | ```sh 11 | yarn dev 12 | ``` 13 | 14 | ## Documentation 15 | 16 | To start a local dev server for the documentation site, run the following 17 | command: 18 | 19 | ```sh 20 | yarn docs:dev 21 | ``` 22 | 23 | ## Releases 24 | 25 | This project uses 26 | [Semantic Release](https://github.com/semantic-release/semantic-release) to 27 | automate package publishing when making changes to the `main` or `next` branch. 28 | 29 | It is recommended to branch off the `next` branch and follow 30 | [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) 31 | when making changes. When your changes are ready for pull request, this should 32 | be opened against the `next` branch. 33 | 34 | [Read more in-depth about Fabric Releases here](https://github.com/fabric-ds/issues/blob/779d59723993c13d62374516259602d967da56ca/rfcs/0004-releases.md). 35 | 36 | Please note that the version published will depend on your commit message 37 | structure. We use [commitizen](https://github.com/commitizen/cz-cli) to help 38 | follow this structure: 39 | 40 | ``` 41 | npm install -g commitizen 42 | ``` 43 | 44 | When installed, you should be able to type `cz` or `git cz` in your terminal to 45 | commit your changes (replacing `git commit`). 46 | 47 | [![Add and commit with Commitizen](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png)](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png) 48 | -------------------------------------------------------------------------------- /docs/pages/getting-started.mdx: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | This page describes how to get started building an application with Fabric 4 | React. 5 | 6 | ## Setting up your app 7 | 8 | Ensure the [Fabric CSS](https://css.fabric-ds.io) stylesheet is loaded in the 9 | page you are working on. 10 | 11 | See the 12 | [Fabric CSS getting started guide](https://css.fabric-ds.io/pages/getting-started.html) 13 | for more information. 14 | 15 | ## Installation 16 | 17 | All the Fabric React code is provided as a single package and each component can 18 | be imported from this package. 19 | 20 | ### Install from NPM 21 | 22 | The Fabric React package can be installed from NPM. 23 | 24 | ```shell 25 | npm install @fabric-ds/react 26 | ``` 27 | 28 | ### Install from Eik 29 | 30 | The same package is also available via our Eik CDN server 31 | 32 | ```html 33 | https://assets.finn.no/pkg/@fabric-ds/react/v0/index.js 34 | ``` 35 | 36 | ### Importing Components 37 | 38 | Once installed, components can be imported into your app by name. Below are 39 | examples of how thats done 40 | 41 |
42 | 43 | #### Importing from the NPM package 44 | 45 | 👉 _**This is the most common method and should be used in most cases**_ 46 | 47 | When importing from NPM you will need to ensure you have build tooling in place. 48 | If you are working with Podium podlets or layouts which is the most common use 49 | case at Finn, you likely already have Eik in place with Rollup or Esbuild in 50 | which case no further action should be needed. 51 | 52 | If not, take a look at the React 53 | [getting started](https://reactjs.org/docs/getting-started.html) docs. 54 | 55 | _Example_ 56 | 57 | ```js 58 | import { Button } from '@fabric-ds/react'; 59 | ``` 60 | 61 |
62 | 63 | #### Importing directly from Eik 64 | 65 | 👉 _**This is great for prototyping (can also be used in production)**_ 66 | 67 | It is also possible to import components directly from the URL on our Eik 68 | server. While not common, it should be possible to write React code without the 69 | need for a build setup. You might find this useful for rapid prototyping 70 | something on a hack day for example! 71 | 72 | _Example_ 73 | 74 | ```js 75 | import { Button } from 'https://assets.finn.no/pkg/@fabric-ds/react/v0/index.js'; 76 | ``` 77 | 78 | If you go down this route, other dependencies such as React and React Dom will 79 | also need to be imported via URLs. These can also be found on the Eik server. 80 | 81 | _Example_ 82 | 83 | ```js 84 | import React from 'https://assets.finn.no/npm/@pika/react/v16/index.js'; 85 | import ReactDom from 'https://assets.finn.no/npm/@pika/react-dom/v16/index.js'; 86 | ``` 87 | 88 |
89 | 90 | #### Individual component imports 91 | 92 | You can find the specific import statement to import each component on that 93 | component's documentation page. For example, here's the [button page](/button) 94 | 95 | ## TypeScript support 96 | 97 | The components are written in TypeScript. To take advantage of this, make sure 98 | your project is up to date on the latest `@types/react` definitions. 99 | 100 | ```shell 101 | # YARN 102 | yarn add @types/react -D 103 | 104 | # NPM 105 | npm i @types/react -D 106 | ``` 107 | -------------------------------------------------------------------------------- /docs/pages/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import GettingStarted from './getting-started.mdx'; 3 | 4 | export default function Index() { 5 | return ( 6 | <> 7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /docs/src/Main.tsx: -------------------------------------------------------------------------------- 1 | import { MDXProvider } from '@mdx-js/react'; 2 | import React from 'react'; 3 | import { render } from 'react-dom'; 4 | import { 5 | BrowserRouter as Router, 6 | Route, 7 | Switch as ReactSwitch, 8 | } from 'react-router-dom'; 9 | import Alert from '../../packages/alert/docs/Alert.mdx'; 10 | import Box from '../../packages/box/docs/Box.mdx'; 11 | import Breadcrumbs from '../../packages/breadcrumbs/docs/Breadcrumbs.mdx'; 12 | import Button from '../../packages/button/docs/Button.mdx'; 13 | import Pill from '../../packages/pill/docs/Pill.mdx'; 14 | import Card from '../../packages/card/docs/Card.mdx'; 15 | import Combobox from '../../packages/combobox/docs/Combobox.mdx'; 16 | import Expandable from '../../packages/expandable/docs/Expandable.mdx'; 17 | import Modal from '../../packages/modal/docs/Modal.mdx'; 18 | import Select from '../../packages/select/docs/Select.mdx'; 19 | import Slider from '../../packages/slider/docs/Slider.mdx'; 20 | import Steps from '../../packages/steps/docs/Steps.mdx'; 21 | import Switch from '../../packages/switch/docs/Switch.mdx'; 22 | import Tabs from '../../packages/tabs/docs/Tabs.mdx'; 23 | import TextArea from '../../packages/textarea/docs/TextArea.mdx'; 24 | import TextField from '../../packages/textfield/docs/TextField.mdx'; 25 | import Toggle from '../../packages/toggle/docs/Toggle.mdx'; 26 | import Attention from '../../packages/attention/docs/Attention.mdx'; 27 | import Home from '../pages/index.jsx'; 28 | import Code from './components/Code'; 29 | import PropTable from './components/PropTable'; 30 | 31 | const components = { 32 | code: Code, 33 | PropTable, 34 | pre: (props) =>
, 35 | img: ({ style, ...props }) => ( 36 | // eslint-disable-next-line jsx-a11y/alt-text 37 | 38 | ), 39 | }; 40 | 41 | const App = () => { 42 | return ( 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /tests/ssr-react-16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssr-react-16", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "npx nodemon server.js", 10 | "build:client": "npx esbuild ./client.jsx --outdir=dist --target=es2017 --bundle --sourcemap --format=esm", 11 | "build:server": "npx esbuild ./index.jsx --outdir=dist --target=es2017 --bundle --sourcemap --format=esm --external:react", 12 | "build": "npm run build:server && npm run build:client" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "@fabric-ds/react": "*", 19 | "fastify": "^3.22.0", 20 | "react-dom": "16.14.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/ssr-react-16/server.js: -------------------------------------------------------------------------------- 1 | import fastify from 'fastify'; 2 | import React from 'react'; 3 | import fs from 'fs'; 4 | import { dirname, join } from 'path'; 5 | import { fileURLToPath } from 'url'; 6 | import ReactDomServer from 'react-dom/server.js'; 7 | import app from './dist/index.js'; 8 | 9 | const __dirname = dirname(fileURLToPath(import.meta.url)); 10 | 11 | const server = fastify(); 12 | 13 | server.get('/client.js', (request, reply) => { 14 | reply.type('application/javascript'); 15 | return fs.createReadStream(join(__dirname, './dist/client.js')); 16 | }); 17 | 18 | server.get('/', (request, reply) => { 19 | const markup = ReactDomServer.renderToString(React.createElement(app)); 20 | console.log(markup); 21 | reply.type('html').send(` 22 | 23 | 24 | 25 | 26 | Fabric React 27 | 28 | 29 | 30 | 31 |
${markup}
32 | 33 | 34 | 35 | `); 36 | }); 37 | 38 | server.listen(3000); 39 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16-cjs/README.md: -------------------------------------------------------------------------------- 1 | # SSR React 16 with Typescript and Common JS 2 | 3 | To run: 4 | 5 | ```sh 6 | npm install 7 | npm run build 8 | npm start 9 | ``` 10 | 11 | Visit `localhost:3000` 12 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssr-react-16", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "npx nodemon ./dist/server.js", 9 | "build:client": "npx esbuild ./src/client.tsx --outdir=dist --target=es2017 --bundle --sourcemap --format=esm", 10 | "build:ssr": "npx esbuild ./src/index.tsx --outdir=dist --target=es2017 --bundle --sourcemap --format=cjs --external:react --platform=node", 11 | "build:server": "npx esbuild ./src/server.ts --outdir=dist --target=es2020 --sourcemap --format=cjs --platform=node", 12 | "build": "rm -rf dist && npm run build:server && npm run build:ssr && npm run build:client" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "@fabric-ds/react": "*", 19 | "fastify": "^3.22.0", 20 | "react-dom": "16.14.0" 21 | }, 22 | "devDependencies": { 23 | "@types/node": "^16.10.3", 24 | "typescript": "^4.4.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16-cjs/src/client.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDom from 'react-dom'; 3 | import App from './index'; 4 | 5 | ReactDom.hydrate(, document.getElementById('app')); 6 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16-cjs/src/server.ts: -------------------------------------------------------------------------------- 1 | import fastify from 'fastify'; 2 | import fs from 'fs'; 3 | import { join } from 'path'; 4 | import React from 'react'; 5 | import ReactDomServer from 'react-dom/server.js'; 6 | import app from './index.js'; 7 | 8 | const server = fastify(); 9 | 10 | // @ts-ignore 11 | server.get('/client.js', (_, reply) => { 12 | reply.type('application/javascript'); 13 | return fs.createReadStream(join(__dirname, './client.js')); 14 | }); 15 | 16 | server.get('/', (request, reply) => { 17 | const markup = ReactDomServer.renderToString(React.createElement(app)); 18 | console.log(markup); 19 | reply.type('html').send(` 20 | 21 | 22 | 23 | 24 | Fabric React 25 | 26 | 27 | 28 | 29 |
${markup}
30 | 31 | 32 | 33 | `); 34 | }); 35 | 36 | server.listen(3000); 37 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16/README.md: -------------------------------------------------------------------------------- 1 | # SSR React 16 with Typescript 2 | 3 | To run: 4 | 5 | ```sh 6 | npm install 7 | npm run build 8 | npm start 9 | ``` 10 | 11 | Visit `localhost:3000` 12 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssr-react-16", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "npx nodemon ./dist/server.js", 10 | "build:client": "npx esbuild ./src/client.tsx --outdir=dist --target=es2017 --bundle --sourcemap --format=esm", 11 | "build:ssr": "npx esbuild ./src/index.tsx --outdir=dist --target=es2017 --bundle --sourcemap --format=esm --external:react --platform=node", 12 | "build:server": "npx esbuild ./src/server.ts --outdir=dist --target=es2020 --sourcemap --format=esm --platform=node", 13 | "build": "rm -rf dist && npm run build:server && npm run build:ssr && npm run build:client" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "dependencies": { 19 | "@fabric-ds/react": "*", 20 | "fastify": "^3.22.0", 21 | "react-dom": "16.14.0" 22 | }, 23 | "devDependencies": { 24 | "@types/node": "^16.10.3", 25 | "typescript": "^4.4.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16/src/client.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDom from 'react-dom'; 3 | import App from './index'; 4 | 5 | ReactDom.hydrate(, document.getElementById('app')); 6 | -------------------------------------------------------------------------------- /tests/ssr-react-ts-16/src/server.ts: -------------------------------------------------------------------------------- 1 | import fastify from 'fastify'; 2 | import React from 'react'; 3 | import fs from 'fs'; 4 | import { dirname, join } from 'path'; 5 | import { fileURLToPath } from 'url'; 6 | import ReactDomServer from 'react-dom/server.js'; 7 | import app from './index.js'; 8 | 9 | const __dirname = dirname(fileURLToPath(import.meta.url)); 10 | 11 | const server = fastify(); 12 | 13 | // @ts-ignore 14 | server.get('/client.js', (_, reply) => { 15 | reply.type('application/javascript'); 16 | return fs.createReadStream(join(__dirname, './client.js')); 17 | }); 18 | 19 | server.get('/', (request, reply) => { 20 | const markup = ReactDomServer.renderToString(React.createElement(app)); 21 | console.log(markup); 22 | reply.type('html').send(` 23 | 24 | 25 | 26 | 27 | Fabric React 28 | 29 | 30 | 31 | 32 |
${markup}
33 | 34 | 35 | 36 | `); 37 | }); 38 | 39 | server.listen(3000); 40 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["packages", "@types/index.d.ts"], 3 | "compilerOptions": { 4 | "emitDeclarationOnly": true, 5 | "module": "ES2020", 6 | "lib": ["DOM", "ES2020"], 7 | "outFile": "./dist/npm/index.d.ts", 8 | "target": "ES2020", 9 | "declaration": true, 10 | "sourceMap": true, 11 | "rootDir": "packages", 12 | "outDir": "dist/npm", 13 | "strict": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "moduleResolution": "node", 19 | "jsx": "react", 20 | "esModuleInterop": true, 21 | "skipLibCheck": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "noEmit": false, 24 | "resolveJsonModule": true, 25 | "noImplicitAny": false, 26 | "allowSyntheticDefaultImports": true, 27 | "noEmitOnError": true, 28 | "strictNullChecks": true 29 | }, 30 | "typeRoots": ["node_modules/@types", "@types"], 31 | "exclude": ["**/__tests__", "**/*.stories.tsx", "docs"] 32 | } 33 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import mdx from 'vite-plugin-mdx'; 2 | import reactRefresh from '@vitejs/plugin-react-refresh'; 3 | import slug from 'remark-slug'; 4 | import autoLinkHeadings from 'remark-autolink-headings'; 5 | import jsxExample from './docs/src/plugins/jsxExample.cjs'; 6 | import propTable from './docs/src/plugins/propTable.cjs'; 7 | 8 | export default function config({ mode }) { 9 | return { 10 | // base: '/', 11 | plugins: [ 12 | reactRefresh(), 13 | mdx.default({ 14 | remarkPlugins: [slug, autoLinkHeadings, jsxExample, propTable], 15 | }), 16 | ], 17 | build: { 18 | outDir: 'site', 19 | }, 20 | }; 21 | } 22 | --------------------------------------------------------------------------------