├── .all-contributorsrc ├── .babelrc ├── .gitignore ├── .nvmrc ├── .travis.yml ├── CONTRIBUTING.md ├── HOW-CREATE-A-HOOK.md ├── LICENSE ├── README.md ├── config ├── jest.js └── webpack.js ├── docs ├── getting-started.md ├── useSlider.md └── useTabs.md ├── package-lock.json ├── package.json ├── scripts ├── boilerplates │ ├── useHook.js.boilerplate │ ├── useHook.md.boilerplate │ └── useHook.test.js.boilerplate ├── generate-docs.js ├── generate-hook.js ├── generate-test.js └── lib │ ├── docs.js │ ├── helpers.js │ ├── hook.js │ └── test.js ├── src ├── hooks │ ├── useSlider.js │ └── useTabs.js └── index.js ├── tests └── hooks │ ├── useSlider.test.js │ └── useTabs.test.js └── website ├── .gitignore ├── README.md ├── blog ├── 2016-03-11-blog-post.md ├── 2017-04-10-blog-post-two.md ├── 2017-09-25-testing-rss.md ├── 2017-09-26-adding-rss.md └── 2017-10-24-new-version-1.0.0.md ├── core └── Footer.js ├── i18n └── en.json ├── package.json ├── pages └── en │ ├── help.js │ ├── index.js │ └── users.js ├── sidebars.json ├── siteConfig.js ├── static ├── css │ └── custom.css └── img │ ├── docusaurus.svg │ ├── favicon.png │ ├── favicon │ └── favicon.ico │ └── oss_logo.png └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "react-ui-hooks", 3 | "projectOwner": "devthiago", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": false, 11 | "contributors": [ 12 | { 13 | "login": "devthiago", 14 | "name": "Thiago Alves Luiz", 15 | "avatar_url": "https://avatars0.githubusercontent.com/u/5190217?v=4", 16 | "profile": "http://thiagoalv.es", 17 | "contributions": [ 18 | "infra", 19 | "code" 20 | ] 21 | }, 22 | { 23 | "login": "jprask", 24 | "name": "João Pedro Raskopf", 25 | "avatar_url": "https://avatars3.githubusercontent.com/u/28638133?v=4", 26 | "profile": "http://lattes.cnpq.br/4287615973321905", 27 | "contributions": [ 28 | "infra", 29 | "code" 30 | ] 31 | }, 32 | { 33 | "login": "Lukyhenson", 34 | "name": "Tauan Tathiell", 35 | "avatar_url": "https://avatars0.githubusercontent.com/u/16005211?v=4", 36 | "profile": "https://www.linkedin.com/in/tauan-tathiell/", 37 | "contributions": [ 38 | "doc" 39 | ] 40 | }, 41 | { 42 | "login": "elainemattos", 43 | "name": "Elaine Mattos", 44 | "avatar_url": "https://avatars1.githubusercontent.com/u/10763483?v=4", 45 | "profile": "https://github.com/elainemattos", 46 | "contributions": [ 47 | "doc" 48 | ] 49 | }, 50 | { 51 | "login": "faogustavo", 52 | "name": "Gustavo Fão Valvassori", 53 | "avatar_url": "https://avatars3.githubusercontent.com/u/7588480?v=4", 54 | "profile": "http://gustavofao.com/", 55 | "contributions": [ 56 | "infra" 57 | ] 58 | }, 59 | { 60 | "login": "gutofoletto", 61 | "name": "Guto Foletto", 62 | "avatar_url": "https://avatars2.githubusercontent.com/u/1004681?v=4", 63 | "profile": "http://about.me/gutofoletto", 64 | "contributions": [ 65 | "review" 66 | ] 67 | }, 68 | { 69 | "login": "felipelovato", 70 | "name": "Felipe Lovato Flores", 71 | "avatar_url": "https://avatars3.githubusercontent.com/u/2296173?v=4", 72 | "profile": "https://github.com/felipelovato", 73 | "contributions": [ 74 | "review" 75 | ] 76 | } 77 | ], 78 | "contributorsPerLine": 7 79 | } 80 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ] 6 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | /demo/dist 14 | 15 | # misc 16 | .vscode 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | /umd 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v10.15.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | 4 | cache: 5 | directories: 6 | - node_modules/ 7 | 8 | install: 9 | - npm 10 | 11 | script: 12 | - npm test 13 | 14 | after_script: 15 | - cat coverage/lcov.info | coveralls 16 | 17 | branches: 18 | only: 19 | - master 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | Contributions are always welcome and we appreciate. 4 | 5 | ### Prerequisites 6 | 7 | - Git. 8 | - Node: any 10.x version. 9 | - `npm`: See [Npm web site for installation instructions](https://www.npmjs.com/get-npm). 10 | - Fork [react-ui-hooks repo](https://github.com/devthiago/react-ui-hooks) (for any contributions). 11 | - Get the project on your local machine, following the example: `git clone https://github.com/YOUR-GITHUB-USERNAME/react-ui-hooks.git`. 12 | 13 | #### Create a branch 14 | 15 | - `cd react-ui-hooks` 16 | - `git checkout master` from any folder in your local `react-ui-hooks` repository. 17 | - `git pull origin master` to ensure you have the latest main code. 18 | - `git checkout -b name-of-my-branch` to create a branch. 19 | 20 | ### Create new approaches or make changes 21 | 22 | - Make the changes or create a new Hook (Detailed explanation can be found at [How to Create a Hook](HOW-CREATE-A-HOOK.md)). 23 | - Save the files and check in the browser. 24 | - Make the tests. 25 | - Check if the tests are all passing `npm test`. 26 | 27 | ### Push it 28 | 29 | - `git add .` 30 | - `git commit -m "My message"` (replacing `My message` with a commit message like `It creates a new amazing React ui hook`) to stage and commit your changes 31 | - `git push my-fork-name name-of-my-branch` 32 | - Go to the [react-ui-hooks repo](https://github.com/devthiago/react-ui-hooks) and you should see recently pushed branches. 33 | - Follow GitHub's instructions. 34 | - If possible, include screenshots of visual changes. 35 | 36 | After you have submitted your pull request, we'll try to get back to you as soon as possible. We may suggest some changes or improvements. 37 | 38 | Thank you for contributing! 39 | -------------------------------------------------------------------------------- /HOW-CREATE-A-HOOK.md: -------------------------------------------------------------------------------- 1 | # How to Create a Hook 2 | 3 | The purpose of this guide is to help you to create your own UI Hooks. 4 | 5 | ------------ 6 | 7 | ### Prerequisites 8 | 9 | - Node: any 10.x version. 10 | - `npm` installed. 11 | - Fork [react-ui-hooks repo](https://github.com/devthiago/react-ui-hooks) (for any contributions). 12 | - Get the project on your local machine, following the example: `git clone https://github.com/YOUR-GITHUB-USERNAME/react-ui-hooks.git`. 13 | 14 | ------------ 15 | 16 | #### Creating a Hook 17 | 18 | - First things first, if you want to create a new hook, you have to give it a name that starts with `use` and then the name of the hook, such as useModal, useSlider, etc. 19 | - If you try to create a hook without this pattern, you'll get an error. 20 | 21 | ------------ 22 | 23 | #### Create a Hook file 24 | 25 | The `npm run generate:hook` command create 3 files: 26 | 27 | - A hook file ***useExample.js*** 28 | - The tests file ***useExample.test.js*** 29 | - The documentation file ***useExample.md*** 30 | 31 | The hook and its tests files must be updated manually, the documentation file can be updated all at once by using the `npm run generate:docs` command. 32 | 33 | ------------ 34 | 35 | ### How to create a .js Hook file: 36 | 37 | - Open your shell and run the command: 38 | 39 | ```bash 40 | npm run generate:hook useExample 41 | ``` 42 | 43 | - ##### **After you run the command, you'll get:** 44 | 45 | ***useExample.js*** on `src/hooks/` 46 | 47 | ***useExample.test.js*** on `src/tests/hooks` 48 | 49 | ***useExample.md*** on `docs/` 50 | 51 | ------------ 52 | 53 | ### Create a new react hook unit test 54 | 55 | If you've created your hook manually you can generate its unit test file with the command: 56 | 57 | ```bash 58 | npm run generate:test useExample.js 59 | ``` 60 | 61 | ------------ 62 | 63 | ### Create a new react hook doc: 64 | 65 | You can get the doc file of your hook created automaticaly as well! 66 | 67 | ```bash 68 | npm run generate:docs useExample.js 69 | ``` 70 | 71 | ------------ 72 | 73 | ### Generate docs for all react hooks: 74 | 75 | As you update the hooks and tests frequently there's a need to update the documentation, so you can do it for all of the hooks with: 76 | 77 | ```bash 78 | npm run generate:docs 79 | ``` 80 | 81 | This command scans your hooks and its tests to generate the documentation. 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thiago Alves Luiz 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 |
2 |

React UI Hooks

3 |
4 | 5 | [![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors) 6 | [![Build Status](https://travis-ci.org/devthiago/react-ui-hooks.svg?branch=master)](https://travis-ci.org/devthiago/react-ui-hooks) 7 | [![Coverage Status](https://coveralls.io/repos/github/devthiago/react-ui-hooks/badge.svg?branch=master)](https://coveralls.io/github/devthiago/react-ui-hooks?branch=master) 8 | 9 | Simple repository of React hooks for building UI components 10 | 11 | ## The Problem 12 | 13 | Before we have React Hooks we had to separate components into logic and view ones, if we would like to share IU logic like a component for tabs. Another way to do that is using components built over CSS frameworks like Bootstrap or Materialize, but we have to change a bunch of style if we want to create our own style. What it means is that style should be unique, your product/application should have an unique design. However, the logic for creating UI components is basically the same. 14 | 15 | ## This Solution 16 | 17 | The `react-ui-hooks` is a repository of React Hooks for UI logic. The main idea on this approach is to share and collaborate hooks to became building UI components easier and to try not "reinventing the wheel" one more time (although be doing this 🧐). As well as writing less of the same logic as always, this project also aims to help teams write less CSS, since we can avoid too much use of unnecessary CSS that comes with components/UI third part libraries. 18 | 19 | ## Example 20 | 21 | ```javascript 22 | import React from 'react' 23 | import { useSlider } from 'react-ui-hooks' 24 | import './style.scss' 25 | 26 | const setSlideClassname = (isActive, type = 'slide') => { 27 | const className = `carousel__${type}` 28 | if (isActive) { 29 | return `${className} ${className}--active` 30 | } 31 | return className 32 | } 33 | 34 | const createSlides = activeSlide => (slide, index) => ( 35 |
  • 40 | ) 41 | 42 | const createSlideIndicators = (activeSlide, goToSlide = () => null) => ( 43 | (slide, index) => ( 44 |
  • 45 | goToSlide(index)} 49 | /> 50 |
  • 51 | ) 52 | ) 53 | 54 | const Carousel = ({ children, ...config }) => { 55 | const { 56 | activeSlide, 57 | nextSlide, 58 | prevSlide, 59 | goToSlide, 60 | goToNextSlide, 61 | goToPrevSlide 62 | } = useSlider(children.length, config) 63 | 64 | return ( 65 |
    66 |
    67 | 73 | 74 |
    90 |
    91 | ) 92 | } 93 | 94 | export default Carousel 95 | ``` 96 | 97 | ## Contributing 98 | 99 | - [How to Start Contributing](CONTRIBUTING.md) 100 | - [How to Create a New Hook](HOW-CREATE-A-HOOK.md) 101 | 102 | ## Contributors 103 | 104 | Thanks goes to these wonderful people ([emoji key](https://github.com/all-contributors/all-contributors#emoji-key)): 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 |
    Thiago Alves Luiz
    Thiago Alves Luiz

    🚇 💻
    João Pedro Raskopf
    João Pedro Raskopf

    🚇 💻
    Tauan Tathiell
    Tauan Tathiell

    📖
    Elaine Mattos
    Elaine Mattos

    📖
    Gustavo Fão Valvassori
    Gustavo Fão Valvassori

    🚇
    Guto Foletto
    Guto Foletto

    👀
    Felipe Lovato Flores
    Felipe Lovato Flores

    👀
    119 | 120 | 121 | 122 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 123 | -------------------------------------------------------------------------------- /config/jest.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | rootDir: path.join(__dirname, '..'), 5 | collectCoverage: true, 6 | collectCoverageFrom: [ 7 | "./src/**/*.{js,jsx}", 8 | "!./src/index.js" 9 | ], 10 | moduleNameMapper: { 11 | "^@hooks(.*)$": "/src/hooks$1" 12 | }, 13 | coverageDirectory: 'coverage', 14 | verbose: true, 15 | testRegex: '(/tests/.*\\.(test|spec))\\.jsx?$', 16 | moduleFileExtensions: ['js', 'json', 'jsx', 'node'], 17 | coverageThreshold: { 18 | global: { 19 | branches: 30, 20 | functions: 90, 21 | lines: 90, 22 | statements: 90 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /config/webpack.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const config = { 4 | resolve: { 5 | alias: { 6 | ['@hooks']: path.resolve(__dirname, '../src/hooks') 7 | } 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.(js|jsx)$/, 13 | exclude: /node_modules/, 14 | use: { 15 | loader: "babel-loader" 16 | } 17 | } 18 | ] 19 | } 20 | }; 21 | 22 | module.exports = (env, argv) => config; 23 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting Started 4 | sidebar_label: Getting Started 5 | --- 6 | 7 | Check the [documentation](https://docusaurus.io) for how to use Docusaurus. 8 | 9 | ## Lorem 10 | 11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 12 | 13 | ## Mauris In Code 14 | 15 | ``` 16 | Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut. 17 | ``` 18 | 19 | ## Nulla 20 | 21 | Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra. 22 | 23 | ## Orci 24 | 25 | Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum. 26 | 27 | ## Phasellus 28 | 29 | Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis. 30 | -------------------------------------------------------------------------------- /docs/useSlider.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: use-slider 3 | title: useSlider 4 | sidebar_label: useSlider 5 | --- 6 | 7 | ## Lorem 8 | 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 10 | 11 | 12 | 13 | ## HookResponse 14 | 15 | Type: [object][1] 16 | 17 | ### Properties 18 | 19 | - `activeSlide` **[number][2]** Array index referred to the current active slide. 20 | - `nextSlide` **([number][2] | null)** Array index referred to the next slide. If it's null, the active slide is the last. If it's smaller than the active slide, the Slider component is an infinite one. 21 | - `prevSlide` **([number][2] | null)** Array index referred to the previous slide. If it's null, the active slide is the first. If it's bigger than the active slide, the Slider component is an infinite one. 22 | - `goToSlide` **function ([number][2])** Function responsible for changing the slider state, moving to the desired slide. This function waits for the slide index number as argument. 23 | - `goToNextSlide` **function ()** Function to change the slider state, moving to the next slide. 24 | - `goToPrevSlide` **function ()** Function to change the slider state, moving to the previous slide. 25 | 26 | ## useSlider 27 | 28 | React hook to help on creation of slider/carousel components. 29 | 30 | ### Parameters 31 | 32 | - `length` **[number][2]** Slides/slider items amount. 33 | - `config` **[object][1]** Slider configuration object. 34 | - `config.initialSlide` **[number][2]** Which slide will be the first one. (optional, default `0`) 35 | - `config.infinite` **[boolean][3]** If it's true the slider will reach the first slide when try move forward after has been arrived to the last one. Same will happen if it's on the first slide and try move backward, it will reach the last one. (optional, default `true`) 36 | - `config.autoplay` **[boolean][3]** If it's true the slider will start swapping slides automatically. (optional, default `false`) 37 | - `config.autoplaySpeed` **[number][2]** Defines how fast (ms) the slides will be swapped when the autoplay is true. (optional, default `200`) 38 | - `config.slidesToShow` **[number][2]** How many slides will be shown at the same moment. (optional, default `1`) 39 | - `config.slidesToScroll` **[number][2]** How many slides will be swapped when the change action (go forward or backward) is triggered. (optional, default `1`) 40 | 41 | Returns **[HookResponse][4]** Hook response to be used within your component like props 42 | 43 | **Meta** 44 | 45 | - **author**: Thiago Alves <me@thiagoalv.es> 46 | - **license**: https://tldrlegal.com/license/mit-license MIT 47 | 48 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object 49 | 50 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number 51 | 52 | [3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean 53 | 54 | [4]: #hookresponse 55 | -------------------------------------------------------------------------------- /docs/useTabs.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: use-tabs 3 | title: useTabs 4 | sidebar_label: useTabs 5 | --- 6 | 7 | ## Lorem 8 | 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 10 | 11 | 12 | 13 | ## useTabs 14 | 15 | React hook to help create a tabs component. The hook will 16 | keep track of tab indexes that can be enabled or disabled. 17 | 18 | Type: [object][1] 19 | 20 | ### Parameters 21 | 22 | - `config` **[object][1]** A configuration object 23 | - `config.initialTab` **[number][2]** The initially selected tab index. (optional, default `0`) 24 | - `config.initialDisabledTabs` **[array][3]** An array with initially disabled tab indexes. (optional, default `[]`) 25 | 26 | ### Properties 27 | 28 | - `activeTab` **[number][2]** The index of the current active tab. 29 | - `selectTab` **function ()** Change the current active tab index. 30 | - `disabledTabs` **[array][3]** Includes indexes of all disabled tabs. 31 | - `isEnabled` **function ([number][2])** Returns true for enabled indexes. 32 | - `isDisabled` **function ([number][2])** Returns true for disabled indexes. 33 | - `enableTab` **function ([number][2])** For enabling a tab. 34 | - `disableTab` **function ([number][2])** For disabling a tab./\*\* 35 | 36 | Returns **HookResponse** Hook response to be used within your component like props. 37 | 38 | **Meta** 39 | 40 | - **author**: João Pedro R. D. Saldanha <jprasys@gmail.com> 41 | - **license**: https://tldrlegal.com/license/mit-license MIT 42 | 43 | [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object 44 | 45 | [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number 46 | 47 | [3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-ui-hooks", 3 | "version": "0.1.0", 4 | "description": "React hooks for UI components building", 5 | "main": "build/index.js", 6 | "module": "build/index.js", 7 | "engines" : { 8 | "node" : ">=10.15.0" 9 | }, 10 | "scripts": { 11 | "start": "", 12 | "test": "jest --config=./config/jest.js", 13 | "build": "webpack --mode=production --config=./config/webpack.js", 14 | "generate:hook": "node ./scripts/generate-hook.js", 15 | "generate:docs": "node ./scripts/generate-docs.js", 16 | "generate:test": "node ./scripts/generate-test.js" 17 | }, 18 | "peerDependencies": { 19 | "react": "16.8.x" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.2.2", 23 | "@babel/preset-env": "^7.3.1", 24 | "@babel/preset-react": "^7.0.0", 25 | "babel-jest": "^24.1.0", 26 | "babel-loader": "^8.0.5", 27 | "coveralls": "^3.0.3", 28 | "documentation": "^9.1.1", 29 | "jest": "^24.1.0", 30 | "jest-dom": "^3.1.2", 31 | "react": "^16.8.0", 32 | "react-dom": "^16.8.0", 33 | "react-hooks-testing-library": "^0.3.6", 34 | "webpack": "^4.29.0", 35 | "webpack-cli": "^3.2.1" 36 | }, 37 | "author": "Thiago Alves ", 38 | "license": "MIT", 39 | "homepage": "https://github.com/devthiago/react-ui-hooks", 40 | "repository": "https://github.com/devthiago/react-ui-hooks", 41 | "keywords": [ 42 | "ui", 43 | "user", 44 | "interface", 45 | "react", 46 | "hook", 47 | "hooks", 48 | "react-hook", 49 | "react-hooks" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /scripts/boilerplates/useHook.js.boilerplate: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | 3 | /** 4 | * @typedef {object} HookResponse 5 | * @property {number} propNumber - [description] 6 | * @property {string} propString - [description] 7 | * @property {function(number)} propFunction - [Function with a number arg] 8 | */ 9 | 10 | /** 11 | * @function 12 | * @name <%=HOOK_NAME%> 13 | * @description React hook description. 14 | * @author <%=HOOK_AUTHOR_NAME%> <<%=HOOK_AUTHOR_EMAIL%>> 15 | * @license https://tldrlegal.com/license/mit-license MIT 16 | * 17 | * @param {number} numberVar - [description] 18 | * @param {object} config - [description] 19 | * @param {number} [config.numberProp] - [description] 20 | * @param {boolean} [config.booleanProp] - [description] 21 | * 22 | * @return {HookResponse} Hook response to be used within your component like props 23 | */ 24 | export default function <%=HOOK_NAME%>() { 25 | // state 26 | const [state, setState] = useState(null) 27 | 28 | useEffect(() => { 29 | // didMout and didUpdate 30 | return () => { 31 | //willUnmount 32 | } 33 | }) 34 | 35 | return { 36 | foo: 'bar' 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scripts/boilerplates/useHook.md.boilerplate: -------------------------------------------------------------------------------- 1 | --- 2 | id: <%=HOOK_ID%> 3 | title: <%=HOOK_NAME%> 4 | sidebar_label: <%=HOOK_NAME%> 5 | --- 6 | 7 | ## Lorem 8 | 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 10 | 11 | -------------------------------------------------------------------------------- /scripts/boilerplates/useHook.test.js.boilerplate: -------------------------------------------------------------------------------- 1 | import { renderHook } from 'react-hooks-testing-library' 2 | import <%=HOOK_NAME%> from '@hooks/<%=HOOK_NAME%>' 3 | 4 | describe('<%=HOOK_NAME%>()', () => { 5 | test('Describe what you are testing', () => { 6 | const { result } = renderHook(() => <%=HOOK_NAME%>()) 7 | const { prop } = result.current 8 | expect(prop).toBeTruthy() 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /scripts/generate-docs.js: -------------------------------------------------------------------------------- 1 | require('./lib/docs.js')(process.argv[2]); 2 | -------------------------------------------------------------------------------- /scripts/generate-hook.js: -------------------------------------------------------------------------------- 1 | require('./lib/hook.js')(process.argv[2]); 2 | -------------------------------------------------------------------------------- /scripts/generate-test.js: -------------------------------------------------------------------------------- 1 | require('./lib/test.js')(process.argv[2]); 2 | -------------------------------------------------------------------------------- /scripts/lib/docs.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const documentation = require('documentation'); 3 | const { 4 | hookDir, 5 | docContentBreakPoint, 6 | boilerplateFile, 7 | createHookRefs, 8 | getHookInfo, 9 | isValidFile, 10 | replaceBoilerplateVariables 11 | } = require('./helpers.js'); 12 | 13 | const editMarkdownFile = (file, content = '') => { 14 | let output = ''; 15 | if (!fs.existsSync(file.md)) { 16 | console.log('\x1b[35m%s\x1b[0m', `✏️ Creating doc file for ${file.name} hook...`); 17 | const boilerplate = fs.readFileSync(boilerplateFile('useHook.md'), 'utf8'); 18 | output = replaceBoilerplateVariables(boilerplate, getHookInfo(file)); 19 | } else { 20 | console.log('\x1b[35m%s\x1b[0m', `✏️ Editing ${file.name} hook doc file...`); 21 | const current = fs.readFileSync(file.md, 'utf8'); 22 | output = current.split(docContentBreakPoint)[0]; 23 | } 24 | const newContent = `${output}${content}`; 25 | fs.writeFileSync(file.md, newContent); 26 | console.log('\x1b[32m%s\x1b[0m', `✅ DONE! ${file.md}`); 27 | return newContent; 28 | }; 29 | 30 | const generateDoc = file => documentation.build([file.js], { shallow: false }) 31 | .then(documentation.formats.md) 32 | .then(output => editMarkdownFile(file, output)); 33 | 34 | const exec = (filename = null) => { 35 | if (filename) { 36 | const file = createHookRefs(filename); 37 | if (isValidFile(filename) && fs.existsSync(file.js)) { 38 | generateDoc(file); 39 | } else { 40 | console.error('\x1b[31m%s\x1b[0m', `🚫 ${filename} doesn't exist in ${hookDir}`); 41 | } 42 | } else { 43 | console.log('\x1b[33m%s\x1b[0m', `🔍 Looking for React hooks in ${hookDir}...`); 44 | fs.readdir(hookDir, (err, files) => { 45 | const hooks = files.reduce((acc, cur) => { 46 | if (isValidFile(cur)) { 47 | acc.push(createHookRefs(cur)); 48 | } 49 | return acc; 50 | }, []); 51 | 52 | if (hooks.length > 0) { 53 | hooks.forEach(generateDoc); 54 | } 55 | }); 56 | } 57 | }; 58 | 59 | module.exports = exec; 60 | -------------------------------------------------------------------------------- /scripts/lib/helpers.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const hookDir = path.join(__dirname, '../../src/hooks'); 4 | const docsDir = path.join(__dirname, '../../docs'); 5 | const testsDir = path.join(__dirname, '../../tests/hooks'); 6 | const boilerplatesDir = path.join(__dirname, '../boilerplates'); 7 | 8 | const docContentBreakPoint = ''; 9 | 10 | const hookFile = file => `${hookDir}/${file}`; 11 | const docFile = file => `${docsDir}/${file}.md`; 12 | const testFile = file => `${testsDir}/${file}.test.js`; 13 | const boilerplateFile = file => `${boilerplatesDir}/${file}.boilerplate`; 14 | 15 | const removeExt = file => file.slice(0,-3); 16 | const createHookNameID = name => `use-${name.split('use')[1].toLowerCase()}`; 17 | 18 | const createHookRefs = file => ({ 19 | name: removeExt(file), 20 | id: createHookNameID(removeExt(file)), 21 | js: hookFile(file), 22 | md: docFile(removeExt(file)), 23 | test: testFile(removeExt(file)) 24 | }); 25 | 26 | const getHookInfo = fileRef => ({ 27 | ...fileRef, 28 | author: 'Thiago Alves', 29 | email: 'taltk9@gmail.com' 30 | }); 31 | 32 | const isValidFile = file => file.indexOf('use') !== -1 && file.indexOf('.js') !== -1; 33 | 34 | const replaceBoilerplateVariables = (string = '', obj = {}) => { 35 | return string 36 | .replace(new RegExp('<%=HOOK_NAME%>', 'gi'), obj.name) 37 | .replace(new RegExp('<%=HOOK_ID%>', 'gi'), obj.id) 38 | .replace(new RegExp('<%=HOOK_AUTHOR_NAME%>', 'gi'), obj.author) 39 | .replace(new RegExp('<%=HOOK_AUTHOR_EMAIL%>', 'gi'), obj.email); 40 | }; 41 | 42 | module.exports = { 43 | hookDir, 44 | docsDir, 45 | boilerplatesDir, 46 | docContentBreakPoint, 47 | hookFile, 48 | docFile, 49 | boilerplateFile, 50 | removeExt, 51 | createHookNameID, 52 | createHookRefs, 53 | getHookInfo, 54 | isValidFile, 55 | replaceBoilerplateVariables 56 | }; 57 | -------------------------------------------------------------------------------- /scripts/lib/hook.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const generateDoc = require('./docs.js'); 3 | const generateTest = require('./test.js'); 4 | const { 5 | boilerplateFile, 6 | createHookRefs, 7 | getHookInfo, 8 | isValidFile, 9 | replaceBoilerplateVariables 10 | } = require('./helpers.js'); 11 | 12 | const generateHook = file => { 13 | if (fs.existsSync(file.js)) { 14 | console.error('\x1b[33m%s\x1b[0m', `⚠️ ${file.name}.js already exists`); 15 | return null; 16 | } else { 17 | console.log('\x1b[35m%s\x1b[0m', `✏️ Creating JavaScript file for ${file.name} hook...`); 18 | const boilerplate = fs.readFileSync(boilerplateFile('useHook.js'), 'utf8'); 19 | const content = replaceBoilerplateVariables(boilerplate, getHookInfo(file)); 20 | fs.writeFileSync(file.js, content); 21 | console.log('\x1b[32m%s\x1b[0m', `✅ DONE! ${file.js}`); 22 | return content; 23 | } 24 | }; 25 | 26 | const exec = (filename = null) => { 27 | if (filename) { 28 | const jsFile = `${filename}.js`; 29 | if (isValidFile(jsFile)) { 30 | const file = createHookRefs(jsFile); 31 | if (generateHook(file)) { 32 | generateTest(jsFile); 33 | generateDoc(jsFile); 34 | } 35 | } else { 36 | console.error('\x1b[31m%s\x1b[0m', `🚫 ${filename} isn't a valid hook name`); 37 | } 38 | } else { 39 | console.log('\x1b[33m%s\x1b[0m', `⚠️ You have to say the desired hook name.`); 40 | } 41 | }; 42 | 43 | module.exports = exec; 44 | -------------------------------------------------------------------------------- /scripts/lib/test.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { 3 | boilerplateFile, 4 | createHookRefs, 5 | getHookInfo, 6 | isValidFile, 7 | replaceBoilerplateVariables 8 | } = require('./helpers.js'); 9 | 10 | const generateTest = file => { 11 | if (fs.existsSync(file.test)) { 12 | console.error('\x1b[33m%s\x1b[0m', `⚠️ ${file.test} already exists`); 13 | return null; 14 | } else { 15 | console.log('\x1b[35m%s\x1b[0m', `✏️ Creating JavaScript test file for ${file.name} hook...`); 16 | const boilerplate = fs.readFileSync(boilerplateFile('useHook.test.js'), 'utf8'); 17 | const content = replaceBoilerplateVariables(boilerplate, getHookInfo(file)); 18 | fs.writeFileSync(file.test, content); 19 | console.log('\x1b[32m%s\x1b[0m', `✅ DONE! ${file.test}`); 20 | return content; 21 | } 22 | }; 23 | 24 | const exec = (filename = null) => { 25 | if (filename) { 26 | const file = createHookRefs(filename); 27 | if (isValidFile(filename) && fs.existsSync(file.js)) { 28 | generateTest(file); 29 | } else { 30 | console.error('\x1b[31m%s\x1b[0m', `🚫 ${filename} doesn't exist in ${hookDir}`); 31 | } 32 | } else { 33 | console.log('\x1b[33m%s\x1b[0m', `⚠️ You have to say the desired hook name.`); 34 | } 35 | }; 36 | 37 | module.exports = exec; 38 | -------------------------------------------------------------------------------- /src/hooks/useSlider.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | 3 | const defaultConfig = { 4 | initialSlide: 0, 5 | infinite: true, 6 | autoplay: false, 7 | autoplaySpeed: 2000, 8 | slidesToShow: 1, 9 | slidesToScroll: 1 10 | } 11 | 12 | /** 13 | * @typedef {object} HookResponse 14 | * @property {number} activeSlide - Array index referred to the current active slide. 15 | * @property {(number|null)} nextSlide - Array index referred to the next slide. If it's null, the active slide is the last. If it's smaller than the active slide, the Slider component is an infinite one. 16 | * @property {(number|null)} prevSlide - Array index referred to the previous slide. If it's null, the active slide is the first. If it's bigger than the active slide, the Slider component is an infinite one. 17 | * @property {function(number)} goToSlide - Function responsible for changing the slider state, moving to the desired slide. This function waits for the slide index number as argument. 18 | * @property {function()} goToNextSlide - Function to change the slider state, moving to the next slide. 19 | * @property {function()} goToPrevSlide - Function to change the slider state, moving to the previous slide. 20 | */ 21 | 22 | /** 23 | * @function 24 | * @name useSlider 25 | * @description React hook to help on creation of slider/carousel components. 26 | * @author Thiago Alves 27 | * @license https://tldrlegal.com/license/mit-license MIT 28 | * 29 | * @param {number} length - Slides/slider items amount. 30 | * @param {object} config - Slider configuration object. 31 | * @param {number} [config.initialSlide=0] - Which slide will be the first one. 32 | * @param {boolean} [config.infinite=true] - If it's true the slider will reach the first slide when try move forward after has been arrived to the last one. Same will happen if it's on the first slide and try move backward, it will reach the last one. 33 | * @param {boolean} [config.autoplay=false] - If it's true the slider will start swapping slides automatically. 34 | * @param {number} [config.autoplaySpeed=200] - Defines how fast (ms) the slides will be swapped when the autoplay is true. 35 | * @param {number} [config.slidesToShow=1] - How many slides will be shown at the same moment. 36 | * @param {number} [config.slidesToScroll=1] - How many slides will be swapped when the change action (go forward or backward) is triggered. 37 | * 38 | * @return {HookResponse} Hook response to be used within your component like props 39 | */ 40 | export default function useSlider(length = 0, config = {}) { 41 | const settings = { ...defaultConfig, ...config } 42 | const { 43 | initialSlide, 44 | infinite, 45 | slidesToScroll, 46 | autoplay, 47 | autoplaySpeed 48 | } = settings 49 | 50 | const [activeSlide, setActiveSlide] = useState(initialSlide) 51 | 52 | const lastSlide = length - 1 53 | const isRightLimit = activeSlide === lastSlide 54 | const isLeftLimit = activeSlide === 0 55 | 56 | let nextSlide = isRightLimit ? activeSlide : activeSlide + slidesToScroll 57 | let prevSlide = isLeftLimit ? activeSlide : activeSlide - slidesToScroll 58 | 59 | if (infinite && isRightLimit) { 60 | nextSlide = 0 61 | } else if (infinite && isLeftLimit) { 62 | prevSlide = lastSlide 63 | } 64 | 65 | const goToSlide = index => setActiveSlide(index) 66 | const goToNextSlide = () => setActiveSlide(nextSlide) 67 | const goToPrevSlide = () => setActiveSlide(prevSlide) 68 | 69 | let timeoutID = null 70 | 71 | useEffect(() => { 72 | if (autoplay && (infinite || !isRightLimit)) { 73 | timeoutID = setTimeout(goToNextSlide, autoplaySpeed) 74 | } 75 | return () => { 76 | if (timeoutID) { 77 | clearTimeout(timeoutID) 78 | } 79 | } 80 | }) 81 | 82 | return { 83 | activeSlide, 84 | nextSlide, 85 | prevSlide, 86 | goToSlide, 87 | goToNextSlide, 88 | goToPrevSlide 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/hooks/useTabs.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | 3 | const defaultConfig = { 4 | initialTab: 0, 5 | initialDisabledTabs: [] 6 | } 7 | 8 | /** 9 | * @typedef {object} HookResponse 10 | * @property {number} activeTab - The index of the current active tab. 11 | * @property {function()} selectTab - Change the current active tab index. 12 | * @property {array} disabledTabs - Includes indexes of all disabled tabs. 13 | * @property {function(number)} isEnabled - Returns true for enabled indexes. 14 | * @property {function(number)} isDisabled - Returns true for disabled indexes. 15 | * @property {function(number)} enableTab - For enabling a tab. 16 | * @property {function(number)} disableTab - For disabling a tab. 17 | 18 | /** 19 | * @function 20 | * @name useTabs 21 | * @description React hook to help create a tabs component. The hook will 22 | * keep track of tab indexes that can be enabled or disabled. 23 | * @author João Pedro R. D. Saldanha 24 | * @license https://tldrlegal.com/license/mit-license MIT 25 | * 26 | * @param {object} config - A configuration object 27 | * @param {number} [config.initialTab=0] - The initially selected tab index. 28 | * @param {array} [config.initialDisabledTabs=[]] - An array with initially disabled tab indexes. 29 | * 30 | * @return {HookResponse} Hook response to be used within your component like props. 31 | */ 32 | export default function useTabs(config = {}) { 33 | const settings = { ...defaultConfig, ...config } 34 | const { initialTab, initialDisabledTabs } = settings 35 | 36 | const [activeTab, setActiveTab] = useState(initialTab) 37 | const [disabledTabs, setDisabledTabs] = useState(initialDisabledTabs) 38 | 39 | const isEnabled = index => !disabledTabs.includes(index) 40 | const isDisabled = index => !isEnabled(index) 41 | 42 | const selectTab = index => { 43 | if (index !== activeTab && isEnabled(index)) { 44 | setActiveTab(index) 45 | } 46 | } 47 | 48 | const disableTab = index => { 49 | if (index !== activeTab && isEnabled(index)) { 50 | setDisabledTabs(previousDisabledTabs => { 51 | return [...previousDisabledTabs, index] 52 | }) 53 | } 54 | } 55 | 56 | const enableTab = index => { 57 | if (isDisabled(index)) { 58 | setDisabledTabs(previousDisabledTabs => ( 59 | previousDisabledTabs.filter(tab => tab !== index) 60 | )) 61 | } 62 | } 63 | 64 | return { 65 | activeTab, 66 | selectTab, 67 | disabledTabs, 68 | isEnabled, 69 | isDisabled, 70 | enableTab, 71 | disableTab 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devthiago/react-ui-hooks/a6f7323a27c145adaadcd9f0227fb2f1159f68b6/src/index.js -------------------------------------------------------------------------------- /tests/hooks/useSlider.test.js: -------------------------------------------------------------------------------- 1 | import { renderHook } from 'react-hooks-testing-library' 2 | import useSlider from '@hooks/useSlider' 3 | 4 | describe('useSlider()', () => { 5 | test('Describe what you are testing', () => { 6 | const { result } = renderHook(() => useSlider()) 7 | const { activeSlide } = result.current 8 | expect(activeSlide).toBe(50) 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /tests/hooks/useTabs.test.js: -------------------------------------------------------------------------------- 1 | import { renderHook, cleanup, act } from 'react-hooks-testing-library' 2 | import useTabs from '@hooks/useTabs' 3 | 4 | describe('useTabs()', () => { 5 | beforeEach(cleanup) 6 | 7 | describe('activeTab integer response', () => { 8 | test('returns 0 when theres no default value', () => { 9 | const { result } = renderHook(() => useTabs()) 10 | const { activeTab } = result.current 11 | expect(activeTab).toBe(0) 12 | }) 13 | 14 | test('uses the initialTab config value if provided', () => { 15 | const config = { initialTab: 5 } 16 | const { result } = renderHook(() => useTabs(config)) 17 | const { activeTab } = result.current 18 | expect(activeTab).toBe(5) 19 | }) 20 | }) 21 | 22 | describe('when selectTab function response is called', () => { 23 | test('activeTab is equal to the selectTab passed parameter', () => { 24 | const { result } = renderHook(() => useTabs()) 25 | const { selectTab } = result.current 26 | act(() => selectTab(1)) 27 | const { activeTab } = result.current 28 | expect(activeTab).toBe(1) 29 | }) 30 | 31 | test('does not change activeTab if called with a disabled index', () => { 32 | const config = {initialDisabledTabs: [1]} 33 | const { result } = renderHook(() => useTabs(config)) 34 | const { selectTab } = result.current 35 | act(() => selectTab(1)) 36 | const { activeTab } = result.current 37 | expect(activeTab).toBe(0) 38 | }) 39 | }) 40 | 41 | describe('disabledTabs array', () => { 42 | test('starts at [] by default', () => { 43 | const { result } = renderHook(() => useTabs()) 44 | const { disabledTabs } = result.current 45 | expect(disabledTabs).toEqual([]) 46 | }) 47 | 48 | test('uses the initialDisabledTabs config value if provided', () => { 49 | const config = { initialDisabledTabs: [3, 4, 5] } 50 | const { result } = renderHook(() => useTabs(config)) 51 | const { disabledTabs } = result.current 52 | expect(disabledTabs).toEqual([3, 4, 5]) 53 | }) 54 | }) 55 | 56 | describe('disableTab function', () => { 57 | test('disables a tab if it is enabled', () => { 58 | const { result } = renderHook(() => useTabs()) 59 | const { disableTab } = result.current 60 | act(() => disableTab(1)) 61 | const { disabledTabs } = result.current 62 | expect(disabledTabs).toEqual([1]) 63 | }) 64 | 65 | test('does not disable the current activeTab', () => { 66 | const { result } = renderHook(() => useTabs()) 67 | const { disableTab } = result.current 68 | act(() => disableTab(0)) 69 | const { disabledTabs } = result.current 70 | expect(disabledTabs).toEqual([]) 71 | }) 72 | }) 73 | 74 | describe('enableTab function', () => { 75 | test('enables a tab if its disabled', () => { 76 | const config = {initialDisabledTabs: [1]} 77 | const { result } = renderHook(() => useTabs(config)) 78 | const { enableTab } = result.current 79 | act(() => enableTab(1)) 80 | const { disabledTabs } = result.current 81 | expect(disabledTabs).toEqual([]) 82 | }) 83 | 84 | test('does nothing when called with an already enabled tab as parameter', () => { 85 | const config = {initialDisabledTabs: [2]} 86 | const { result } = renderHook(() => useTabs(config)) 87 | const { enableTab } = result.current 88 | act(() => enableTab(1)) 89 | const { disabledTabs } = result.current 90 | expect(disabledTabs).toEqual([2]) 91 | }) 92 | }) 93 | 94 | describe('isEnabled function response', () => { 95 | let current = null 96 | 97 | beforeAll(() => { 98 | const config = {initialDisabledTabs: [1]} 99 | const { result } = renderHook(() => useTabs(config)) 100 | current = result.current 101 | }) 102 | 103 | test('returns true if tab index is enabled', () => { 104 | const { isEnabled } = current 105 | expect(isEnabled(0)).toBe(true) 106 | }) 107 | 108 | test('returns false if tab index is not enabled', () => { 109 | const { isEnabled } = current 110 | expect(isEnabled(1)).toBe(false) 111 | }) 112 | }) 113 | }) 114 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | /demo/dist 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | /umd 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | This website was created with [Docusaurus](https://docusaurus.io/). 2 | 3 | # What's In This Document 4 | 5 | * [Get Started in 5 Minutes](#get-started-in-5-minutes) 6 | * [Directory Structure](#directory-structure) 7 | * [Editing Content](#editing-content) 8 | * [Adding Content](#adding-content) 9 | * [Full Documentation](#full-documentation) 10 | 11 | # Get Started in 5 Minutes 12 | 13 | 1. Make sure all the dependencies for the website are installed: 14 | 15 | ```sh 16 | # Install dependencies 17 | $ yarn 18 | ``` 19 | 2. Run your dev server: 20 | 21 | ```sh 22 | # Start the site 23 | $ yarn start 24 | ``` 25 | 26 | ## Directory Structure 27 | 28 | Your project file structure should look something like this 29 | 30 | ``` 31 | my-docusaurus/ 32 | docs/ 33 | doc-1.md 34 | doc-2.md 35 | doc-3.md 36 | website/ 37 | blog/ 38 | 2016-3-11-oldest-post.md 39 | 2017-10-24-newest-post.md 40 | core/ 41 | node_modules/ 42 | pages/ 43 | static/ 44 | css/ 45 | img/ 46 | package.json 47 | sidebar.json 48 | siteConfig.js 49 | ``` 50 | 51 | # Editing Content 52 | 53 | ## Editing an existing docs page 54 | 55 | Edit docs by navigating to `docs/` and editing the corresponding document: 56 | 57 | `docs/doc-to-be-edited.md` 58 | 59 | ```markdown 60 | --- 61 | id: page-needs-edit 62 | title: This Doc Needs To Be Edited 63 | --- 64 | 65 | Edit me... 66 | ``` 67 | 68 | For more information about docs, click [here](https://docusaurus.io/docs/en/navigation) 69 | 70 | ## Editing an existing blog post 71 | 72 | Edit blog posts by navigating to `website/blog` and editing the corresponding post: 73 | 74 | `website/blog/post-to-be-edited.md` 75 | ```markdown 76 | --- 77 | id: post-needs-edit 78 | title: This Blog Post Needs To Be Edited 79 | --- 80 | 81 | Edit me... 82 | ``` 83 | 84 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) 85 | 86 | # Adding Content 87 | 88 | ## Adding a new docs page to an existing sidebar 89 | 90 | 1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`: 91 | 92 | ```md 93 | --- 94 | id: newly-created-doc 95 | title: This Doc Needs To Be Edited 96 | --- 97 | 98 | My new content here.. 99 | ``` 100 | 101 | 1. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`: 102 | 103 | ```javascript 104 | // Add newly-created-doc to the Getting Started category of docs 105 | { 106 | "docs": { 107 | "Getting Started": [ 108 | "quick-start", 109 | "newly-created-doc" // new doc here 110 | ], 111 | ... 112 | }, 113 | ... 114 | } 115 | ``` 116 | 117 | For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation) 118 | 119 | ## Adding a new blog post 120 | 121 | 1. Make sure there is a header link to your blog in `website/siteConfig.js`: 122 | 123 | `website/siteConfig.js` 124 | ```javascript 125 | headerLinks: [ 126 | ... 127 | { blog: true, label: 'Blog' }, 128 | ... 129 | ] 130 | ``` 131 | 132 | 2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`: 133 | 134 | `website/blog/2018-05-21-New-Blog-Post.md` 135 | 136 | ```markdown 137 | --- 138 | author: Frank Li 139 | authorURL: https://twitter.com/foobarbaz 140 | authorFBID: 503283835 141 | title: New Blog Post 142 | --- 143 | 144 | Lorem Ipsum... 145 | ``` 146 | 147 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) 148 | 149 | ## Adding items to your site's top navigation bar 150 | 151 | 1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`: 152 | 153 | `website/siteConfig.js` 154 | ```javascript 155 | { 156 | headerLinks: [ 157 | ... 158 | /* you can add docs */ 159 | { doc: 'my-examples', label: 'Examples' }, 160 | /* you can add custom pages */ 161 | { page: 'help', label: 'Help' }, 162 | /* you can add external links */ 163 | { href: 'https://github.com/facebook/Docusaurus', label: 'GitHub' }, 164 | ... 165 | ], 166 | ... 167 | } 168 | ``` 169 | 170 | For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation) 171 | 172 | ## Adding custom pages 173 | 174 | 1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`: 175 | 1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element: 176 | 177 | `website/siteConfig.js` 178 | ```javascript 179 | { 180 | headerLinks: [ 181 | ... 182 | { page: 'my-new-custom-page', label: 'My New Custom Page' }, 183 | ... 184 | ], 185 | ... 186 | } 187 | ``` 188 | 189 | For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages). 190 | 191 | # Full Documentation 192 | 193 | Full documentation can be found on the [website](https://docusaurus.io/). 194 | -------------------------------------------------------------------------------- /website/blog/2016-03-11-blog-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Blog Title 3 | author: Blog Author 4 | authorURL: http://twitter.com/ 5 | authorFBID: 100002976521003 6 | --- 7 | 8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 9 | 10 | 11 | 12 | Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut. 13 | 14 | Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra. 15 | 16 | Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum. 17 | 18 | Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis. 19 | -------------------------------------------------------------------------------- /website/blog/2017-04-10-blog-post-two.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: New Blog Post 3 | author: Blog Author 4 | authorURL: http://twitter.com/ 5 | authorFBID: 100002976521003 6 | --- 7 | 8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien. 9 | 10 | 11 | 12 | Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut. 13 | 14 | Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra. 15 | 16 | Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum. 17 | 18 | Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis. 19 | -------------------------------------------------------------------------------- /website/blog/2017-09-25-testing-rss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding RSS Support - RSS Truncation Test 3 | author: Eric Nakagawa 4 | authorURL: http://twitter.com/ericnakagawa 5 | authorFBID: 661277173 6 | --- 7 | 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 8 | 9 | This should be truncated. 10 | 11 | This line should never render in XML. 12 | -------------------------------------------------------------------------------- /website/blog/2017-09-26-adding-rss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding RSS Support 3 | author: Eric Nakagawa 4 | authorURL: http://twitter.com/ericnakagawa 5 | authorFBID: 661277173 6 | --- 7 | 8 | This is a test post. 9 | 10 | A whole bunch of other information. 11 | -------------------------------------------------------------------------------- /website/blog/2017-10-24-new-version-1.0.0.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: New Version 1.0.0 3 | author: Eric Nakagawa 4 | authorURL: http://twitter.com/ericnakagawa 5 | authorFBID: 661277173 6 | --- 7 | 8 | This blog post will test file name parsing issues when periods are present. 9 | -------------------------------------------------------------------------------- /website/core/Footer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | class Footer extends React.Component { 11 | docUrl(doc, language) { 12 | const baseUrl = this.props.config.baseUrl; 13 | const docsUrl = this.props.config.docsUrl; 14 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; 15 | const langPart = `${language ? `${language}/` : ''}`; 16 | return `${baseUrl}${docsPart}${langPart}${doc}`; 17 | } 18 | 19 | pageUrl(doc, language) { 20 | const baseUrl = this.props.config.baseUrl; 21 | return baseUrl + (language ? `${language}/` : '') + doc; 22 | } 23 | 24 | render() { 25 | return ( 26 |
    100 | ); 101 | } 102 | } 103 | 104 | module.exports = Footer; 105 | -------------------------------------------------------------------------------- /website/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "This file is auto-generated by write-translations.js", 3 | "localized-strings": { 4 | "next": "Next", 5 | "previous": "Previous", 6 | "tagline": "Logic for React UI components", 7 | "docs": { 8 | "getting-started": { 9 | "title": "Getting Started", 10 | "sidebar_label": "Getting Started" 11 | }, 12 | "use-slider": { 13 | "title": "useSlider", 14 | "sidebar_label": "useSlider" 15 | } 16 | }, 17 | "links": { 18 | "Docs": "Docs", 19 | "API": "API" 20 | }, 21 | "categories": { 22 | "Introduction": "Introduction", 23 | "API Reference": "API Reference" 24 | } 25 | }, 26 | "pages-strings": { 27 | "Help Translate|recruit community translators for your project": "Help Translate", 28 | "Edit this Doc|recruitment message asking to edit the doc source": "Edit", 29 | "Translate this Doc|recruitment message asking to translate the docs": "Translate" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "examples": "docusaurus-examples", 4 | "start": "docusaurus-start", 5 | "build": "docusaurus-build", 6 | "publish-gh-pages": "docusaurus-publish", 7 | "write-translations": "docusaurus-write-translations", 8 | "version": "docusaurus-version", 9 | "rename-version": "docusaurus-rename-version" 10 | }, 11 | "devDependencies": { 12 | "docusaurus": "^1.7.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /website/pages/en/help.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js'); 11 | 12 | const Container = CompLibrary.Container; 13 | const GridBlock = CompLibrary.GridBlock; 14 | 15 | function Help(props) { 16 | const {config: siteConfig, language = ''} = props; 17 | const {baseUrl, docsUrl} = siteConfig; 18 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; 19 | const langPart = `${language ? `${language}/` : ''}`; 20 | const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; 21 | 22 | const supportLinks = [ 23 | { 24 | content: `Learn more using the [documentation on this site.](${docUrl( 25 | 'doc1.html', 26 | )})`, 27 | title: 'Browse Docs', 28 | }, 29 | { 30 | content: 'Ask questions about the documentation and project', 31 | title: 'Join the community', 32 | }, 33 | { 34 | content: "Find out what's new with this project", 35 | title: 'Stay up to date', 36 | }, 37 | ]; 38 | 39 | return ( 40 |
    41 | 42 |
    43 |
    44 |

    Need help?

    45 |
    46 |

    This project is maintained by a dedicated group of people.

    47 | 48 |
    49 |
    50 |
    51 | ); 52 | } 53 | 54 | module.exports = Help; 55 | -------------------------------------------------------------------------------- /website/pages/en/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js'); 11 | 12 | const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ 13 | const Container = CompLibrary.Container; 14 | const GridBlock = CompLibrary.GridBlock; 15 | 16 | class HomeSplash extends React.Component { 17 | render() { 18 | const {siteConfig, language = ''} = this.props; 19 | const {baseUrl, docsUrl} = siteConfig; 20 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; 21 | const langPart = `${language ? `${language}/` : ''}`; 22 | const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; 23 | 24 | const SplashContainer = props => ( 25 |
    26 |
    27 |
    {props.children}
    28 |
    29 |
    30 | ); 31 | 32 | const Logo = props => ( 33 |
    34 | Project Logo 35 |
    36 | ); 37 | 38 | const ProjectTitle = () => ( 39 |

    40 | {siteConfig.title} 41 | {siteConfig.tagline} 42 |

    43 | ); 44 | 45 | const PromoSection = props => ( 46 |
    47 |
    48 |
    {props.children}
    49 |
    50 |
    51 | ); 52 | 53 | const Button = props => ( 54 |
    55 | 56 | {props.children} 57 | 58 |
    59 | ); 60 | 61 | return ( 62 | 63 | 64 |
    65 | 66 | 67 | 68 | 69 | 70 | 71 |
    72 |
    73 | ); 74 | } 75 | } 76 | 77 | class Index extends React.Component { 78 | render() { 79 | const {config: siteConfig, language = ''} = this.props; 80 | const {baseUrl} = siteConfig; 81 | 82 | const Block = props => ( 83 | 87 | 92 | 93 | ); 94 | 95 | const FeatureCallout = () => ( 96 |
    99 |

    Feature Callout

    100 | These are features of this project 101 |
    102 | ); 103 | 104 | const TryOut = () => ( 105 | 106 | {[ 107 | { 108 | content: 'Talk about trying this out', 109 | image: `${baseUrl}img/docusaurus.svg`, 110 | imageAlign: 'left', 111 | title: 'Try it Out', 112 | }, 113 | ]} 114 | 115 | ); 116 | 117 | const Description = () => ( 118 | 119 | {[ 120 | { 121 | content: 122 | 'This is another description of how this project is useful', 123 | image: `${baseUrl}img/docusaurus.svg`, 124 | imageAlign: 'right', 125 | title: 'Description', 126 | }, 127 | ]} 128 | 129 | ); 130 | 131 | const LearnHow = () => ( 132 | 133 | {[ 134 | { 135 | content: 'Talk about learning how to use this', 136 | image: `${baseUrl}img/docusaurus.svg`, 137 | imageAlign: 'right', 138 | title: 'Learn How', 139 | }, 140 | ]} 141 | 142 | ); 143 | 144 | const Features = () => ( 145 | 146 | {[ 147 | { 148 | content: 'This is the content of my feature', 149 | image: `${baseUrl}img/docusaurus.svg`, 150 | imageAlign: 'top', 151 | title: 'Feature One', 152 | }, 153 | { 154 | content: 'The content of my second feature', 155 | image: `${baseUrl}img/docusaurus.svg`, 156 | imageAlign: 'top', 157 | title: 'Feature Two', 158 | }, 159 | ]} 160 | 161 | ); 162 | 163 | const Showcase = () => { 164 | if ((siteConfig.users || []).length === 0) { 165 | return null; 166 | } 167 | 168 | const showcase = siteConfig.users 169 | .filter(user => user.pinned) 170 | .map(user => ( 171 | 172 | {user.caption} 173 | 174 | )); 175 | 176 | const pageUrl = page => baseUrl + (language ? `${language}/` : '') + page; 177 | 178 | return ( 179 |
    180 |

    Who is Using This?

    181 |

    This project is used by all these people

    182 |
    {showcase}
    183 |
    184 | 185 | More {siteConfig.title} Users 186 | 187 |
    188 |
    189 | ); 190 | }; 191 | 192 | return ( 193 |
    194 | 195 |
    196 | 197 | 198 | 199 | 200 | 201 | 202 |
    203 |
    204 | ); 205 | } 206 | } 207 | 208 | module.exports = Index; 209 | -------------------------------------------------------------------------------- /website/pages/en/users.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js'); 11 | 12 | const Container = CompLibrary.Container; 13 | 14 | class Users extends React.Component { 15 | render() { 16 | const {config: siteConfig} = this.props; 17 | if ((siteConfig.users || []).length === 0) { 18 | return null; 19 | } 20 | 21 | const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js`; 22 | const showcase = siteConfig.users.map(user => ( 23 | 24 | {user.caption} 25 | 26 | )); 27 | 28 | return ( 29 |
    30 | 31 |
    32 |
    33 |

    Who is Using This?

    34 |

    This project is used by many folks

    35 |
    36 |
    {showcase}
    37 |

    Are you using this project?

    38 | 39 | Add your company 40 | 41 |
    42 |
    43 |
    44 | ); 45 | } 46 | } 47 | 48 | module.exports = Users; 49 | -------------------------------------------------------------------------------- /website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Introduction": ["getting-started"], 4 | "API Reference": ["use-slider"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /website/siteConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // See https://docusaurus.io/docs/site-config for all the possible 9 | // site configuration options. 10 | 11 | // List of projects/orgs using your project for the users page. 12 | const users = [ 13 | { 14 | caption: 'User1', 15 | // You will need to prepend the image path with your baseUrl 16 | // if it is not '/', like: '/test-site/img/docusaurus.svg'. 17 | image: '/img/docusaurus.svg', 18 | infoLink: 'https://www.facebook.com', 19 | pinned: true, 20 | }, 21 | ]; 22 | 23 | const siteConfig = { 24 | title: 'React UI Hooks', // Title for your website. 25 | tagline: 'Logic for React UI components', 26 | url: 'https://your-docusaurus-test-site.com', // Your website URL 27 | baseUrl: '/', // Base URL for your project */ 28 | // For github.io type URLs, you would set the url and baseUrl like: 29 | // url: 'https://facebook.github.io', 30 | // baseUrl: '/test-site/', 31 | 32 | // Used for publishing and more 33 | projectName: 'react-ui-hooks', 34 | organizationName: 'CodeMiner42', 35 | // For top-level user or org sites, the organization is still the same. 36 | // e.g., for the https://JoelMarcey.github.io site, it would be set like... 37 | // organizationName: 'JoelMarcey' 38 | 39 | // For no header links in the top nav bar -> headerLinks: [], 40 | headerLinks: [ 41 | {doc: 'getting-started', label: 'Docs'}, 42 | {doc: 'use-slider', label: 'API'}, 43 | // {page: 'help', label: 'Help'}, 44 | // {blog: true, label: 'Blog'}, 45 | ], 46 | 47 | // If you have users set above, you add it here: 48 | users, 49 | 50 | /* path to images for header/footer */ 51 | headerIcon: 'img/docusaurus.svg', 52 | footerIcon: 'img/docusaurus.svg', 53 | favicon: 'img/favicon.png', 54 | 55 | /* Colors for website */ 56 | colors: { 57 | primaryColor: '#2E8555', 58 | secondaryColor: '#205C3B', 59 | }, 60 | 61 | /* Custom fonts for website */ 62 | /* 63 | fonts: { 64 | myFont: [ 65 | "Times New Roman", 66 | "Serif" 67 | ], 68 | myOtherFont: [ 69 | "-apple-system", 70 | "system-ui" 71 | ] 72 | }, 73 | */ 74 | 75 | // This copyright info is used in /core/Footer.js and blog RSS/Atom feeds. 76 | copyright: `Copyright © ${new Date().getFullYear()} CodeMiner42`, 77 | 78 | highlight: { 79 | // Highlight.js theme to use for syntax highlighting in code blocks. 80 | theme: 'default', 81 | }, 82 | 83 | // Add custom scripts here that would be placed in