Skip to content

Commit

Permalink
chore: Combine sources and tests directories (#94)
Browse files Browse the repository at this point in the history
* tests: move tests under the src directory for comfort reasons

* build: fix typescript configs

During recent directories change it could suck tests directory, now it only consists of stuff exported in `src/index.ts`

* test: bring back misc tests

* ci: test linting issues

* docs: move docs near the sources

fix: #89

* docs: update CONTRIBUTING.md

* feat: add script that help[s to create hook files

Said file creates valid files and directories structure, handy when
creating new hooks.

* docs: annotation about hook create script
  • Loading branch information
xobotyi authored Jun 1, 2021
1 parent 49e31c5 commit 509ec73
Show file tree
Hide file tree
Showing 128 changed files with 648 additions and 686 deletions.
5 changes: 2 additions & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = {
],
plugins: ['import'],
parserOptions: {
project: './tsconfig.json',
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
},
rules: {
Expand Down Expand Up @@ -98,7 +98,7 @@ module.exports = {
},
},
{
files: ['stories/**/*', '.storybook/**/*'],
files: ['src/**/__docs__/*.tsx', '.storybook/*.js'],
rules: {
'import/no-extraneous-dependencies': 'off',
'import/no-default-export': 'off',
Expand All @@ -114,7 +114,6 @@ module.exports = {
'prettier/prettier': [
2,
{
// unnecessary if you're not using `eslint-plugin-prettier`, but required if you are
parser: 'markdown',
},
],
Expand Down
4 changes: 2 additions & 2 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module.exports = {
stories: ['../stories/**/*.story.mdx', '../stories/**/*.story.@(js|jsx|ts|tsx)'],
stories: ['../src/**/__docs__/*.mdx'],
addons: [
'@storybook/addon-links',
{
name: '@storybook/addon-essentials',
options: {
backgrounds: false,
},
},
'@storybook/addon-docs',
],
reactOptions: {
fastRefresh: true,
Expand Down
4 changes: 2 additions & 2 deletions .storybook/manager-head.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<link rel='shortcut icon' href='/favicon.ico'>
<link rel='icon' type='image/png' href='/storybook.png' sizes='60x60'>
<link rel='shortcut icon' href='./favicon.ico'>
<link rel='icon' type='image/png' href='./storybook.png' sizes='60x60'>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;700;800&display=swap" rel="stylesheet">
2 changes: 1 addition & 1 deletion .storybook/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ addons.setConfig({
theme: {
...themes.light,
brandTitle: '@react-hookz/web',
brandImage: '/logo.png',
brandImage: './logo.png',
fontBase: '"Manrope", sans-serif',
},
});
24 changes: 13 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,40 @@ first.
## Development
1. Implement the hook in `src` folder.
- File should be named after the hook.
- File should be named after the hook and placed in subdirectory also named after the hook.
- Hook should have return types explicitly defined.
- Hook should have JSDoc containing hook description and an overview of its arguments.
- Hook should be exported by name, not default exported.
- In case hook has some custom types as arguments or return values - it should also be exported.
- All types and interfaces should be `I` prefixed.
- Hook should be developed with SSR in mind.
- In case hook is stateful and exposes `setState` method, or is has async callbacks (that can
resolve after component unmount), it should use `useSafeState` instead of `useState`.
theoretically be resolved after component unmount), it should use `useSafeState` instead
of `useState`.
2. Reexport hook implementation and all custom types in `src/index.ts`.
3. Write complete tests for your hook, tests should consist of both DOM and SSR parts.
- Hook's test should be placed in `tests` folder and named after the hook.
4ex: `test/dom/useFirstMountState.test.ts` and `test/ssr/useFirstMountState.test.ts`.
- Hook's test should be placed in `__tests__` sub-folder, near the source file, `dom.ts` for DOM
environment, `ssr.ts` for SSR environment.
4ex: `src/useFirstMountState/__tests__/dom.ts` and `src/useFirstMountState/__tests__/ssr.ts`.
- Ideally your hook should have 100% test coverage. For cases where that is impossible, you
should comment above the code exactly why it is impossible to have 100% coverage.
- Each hook should have at least 'should be defined' and 'should render' tests in `SSR`
environment.
- All utility functions should also be tested.
4. Write docs for your hook.
- Docs should be placed in `stories` folder and named after the hook.
4ex: `stories/useUpdateEffect.story.mdx`.
- Docs should be placed in `__docs__` sub-folder, near the source file.
4ex: `src/useFirstMountState/__docs__/story.mdx`.
- Docs are built with storybook, to help you during writing docs - start webserver
with `yarn storybook:watch`.
- Components representing hook functionality should be placed in file named after the hook
with `.stories` suffix.
4ex: `useFirstMountState.stories.tsx`.
- Components representing hook functionality should be placed next to story file, within
`__docs__` folder.
4ex: `src/useFirstMountState/__docs__/example.tsx`.
- Preferred format to write the docs is
MDX. [Read more about storybook docs](https://storybook.js.org/docs/react/writing-docs/introduction)
.
MDX. [Read more about storybook docs](https://storybook.js.org/docs/react/writing-docs/introduction).
5. Add docs link and hook summary to the `README.md`.
6. After all above steps are done - run `yarn lint:fix` and ensure that everything is styled by our
standards.
7. Command `yarn new-hook myAwesomeHook` will help you create proper file structure for new hook.
## Committing
Expand Down
5 changes: 2 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ module.exports = {
displayName: 'dom',
preset: 'ts-jest',
testEnvironment: 'jsdom',
testMatch: ['<rootDir>/tests/dom/**/*.test.[jt]s?(x)'],
testMatch: ['<rootDir>/src/**/__tests__/dom.[jt]s?(x)'],
},
{
displayName: 'ssr',
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['<rootDir>/tests/ssr/**/*.test.[jt]s?(x)'],
testMatch: ['<rootDir>/src/**/__tests__/ssr.[jt]s?(x)'],
},
],
coverageDirectory: './coverage',
collectCoverage: false,
collectCoverageFrom: ['src/**/*.ts'],
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"build:cjs": "ttsc -p ./tsconfig.build.json --module CommonJS --target ES5 --outDir ./cjs",
"build:esm": "ttsc -p ./tsconfig.build.json --module ES6 --target ES5 --outDir ./esm",
"build:esnext": "ttsc -p ./tsconfig.build.json --module ESNext --target ESNext --outDir ./esnext",
"new-hook": "node ./utility/add-new-hook.js",
"test": "jest",
"test:coverage": "yarn test --coverage",
"lint": "eslint ./ ./.storybook --ext ts,js,tsx,jsx,md,mdx",
Expand Down Expand Up @@ -109,6 +110,7 @@
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"globby": "^11.0.3",
"husky": "^4.3.8",
"jest": "^26.6.3",
"jest-github-actions-reporter": "^1.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Home" />

# ![@react-hookz/web](/logo.png)
<div style={{textAlign: 'center'}}>

React hooks done right, for browser and SSR.
# ![@react-hookz/web](./logo.png)

[![NPM Version](https://flat.badgen.net/npm/v/@react-hookz/web)](https://www.npmjs.com/package/@react-hookz/web)
[![NPM Downloads](https://flat.badgen.net/npm/dm/@react-hookz/web)](https://www.npmjs.com/package/@react-hookz/web)
Expand All @@ -14,6 +14,14 @@ React hooks done right, for browser and SSR.
[![Types](https://flat.badgen.net/npm/types/@react-hookz/web)](https://www.npmjs.com/package/@react-hookz/web)
[![Tree Shaking](https://flat.badgen.net/bundlephobia/tree-shaking/@react-hookz/web)](https://bundlephobia.com/result?p=@react-hookz/web)

× **[DOCS](https://react-hookz.github.io/web/)**
× **[DISCORD](https://discord.gg/Fjwphtu65f)**
× **[CHANGELOG](https://github.com/react-hookz/web/blob/master/CHANGELOG.md)** ×

</div>

---

`@react-hookz/web` is a library of general-purpose React hooks built with care and SSR compatibility
in mind.

Expand All @@ -27,8 +35,8 @@ npm i @react-hookz/web
yarn add @react-hookz/web
```

As hooks was introduced to the world in React 16.8, `@react-hookz/web` requires - you guessed
it - `react` and `react-dom` 16.8+.
As hooks was introduced to the world in React 16.8, `@react-hookz/web` requires - you guessed it -
`react` and `react-dom` 16.8+.
Also, as React does not support IE, `@react-hookz/web` does not do so either. You'll have to
transpile your `node-modules` in order to run in IE.

Expand Down
51 changes: 29 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
// Callback
export { useDebounceCallback } from './useDebounceCallback';
export { useRafCallback } from './useRafCallback';
export { useDebounceCallback } from './useDebounceCallback/useDebounceCallback';
export { useRafCallback } from './useRafCallback/useRafCallback';

// Livecycle
export { useConditionalEffect, IUseConditionalEffectPredicate } from './useConditionalEffect';
export {
useConditionalEffect,
IUseConditionalEffectPredicate,
} from './useConditionalEffect/useConditionalEffect';
export {
useConditionalUpdateEffect,
IUseConditionalUpdateEffectPredicate,
} from './useConditionalUpdateEffect';
export { useFirstMountState } from './useFirstMountState';
export { useIsMounted } from './useIsMounted';
export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export { useMountEffect } from './useMountEffect';
export { useRerender } from './useRerender';
export { useUnmountEffect } from './useUnmountEffect';
export { useUpdateEffect } from './useUpdateEffect';
} from './useConditionalUpdateEffect/useConditionalUpdateEffect';
export { useFirstMountState } from './useFirstMountState/useFirstMountState';
export { useIsMounted } from './useIsMounted/useIsMounted';
export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect/useIsomorphicLayoutEffect';
export { useMountEffect } from './useMountEffect/useMountEffect';
export { useRerender } from './useRerender/useRerender';
export { useUnmountEffect } from './useUnmountEffect/useUnmountEffect';
export { useUpdateEffect } from './useUpdateEffect/useUpdateEffect';

// State
export { useMediatedState } from './useMediatedState';
export { usePrevious } from './usePrevious';
export { useSafeState } from './useSafeState';
export { useToggle } from './useToggle';
export { useMediatedState } from './useMediatedState/useMediatedState';
export { usePrevious } from './usePrevious/usePrevious';
export { useSafeState } from './useSafeState/useSafeState';
export { useToggle } from './useToggle/useToggle';

// Navogator
export { useNetworkState } from './useNetworkState';
// Navigator
export { useNetworkState } from './useNetworkState/useNetworkState';

// Miscellaneous
export { useSyncedRef } from './useSyncedRef';
export { useSyncedRef } from './useSyncedRef/useSyncedRef';

// SideEffect
export { useLocalStorageValue } from './useLocalStorageValue';
export { useSessionStorageValue } from './useSessionStorageValue';
export { useLocalStorageValue } from './useLocalStorageValue/useLocalStorageValue';
export { useSessionStorageValue } from './useSessionStorageValue/useSessionStorageValue';

// Sensor
export { useResizeObserver, IUseResizeObserverCallback } from './useResizeObserver';
export {
useResizeObserver,
IUseResizeObserverCallback,
} from './useResizeObserver/useResizeObserver';
export { useMeasure } from './useMeasure/useMeasure';

// Dom
export { useDocumentTitle, IUseDocumentTitleOptions } from './useDocumentTitle';
export { useDocumentTitle, IUseDocumentTitleOptions } from './useDocumentTitle/useDocumentTitle';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useState } from 'react';
import { useConditionalEffect, useToggle } from '../../src';
import { useConditionalEffect, useToggle } from '../..';

export const Example: React.FC = () => {
const [isToggled, toggle] = useToggle(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
import { Example } from './useConditionalEffect.stories';
import { Example } from './example';

<Meta title="Lifecycle/useConditionalEffect" component={Example} />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useConditionalEffect } from '../../src';
import { useConditionalEffect } from '../..';

describe('useConditionalEffect', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/server';
import { useConditionalEffect } from '../../src';
import { useConditionalEffect } from '../..';

describe('useConditionalEffect', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EffectCallback, useEffect, useRef } from 'react';
import { noop, truthyArrayItemsPredicate } from './util/const';
import { noop, truthyArrayItemsPredicate } from '../util/const';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type IUseConditionalEffectPredicate<Cond extends ReadonlyArray<any>> = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useState } from 'react';
import { useConditionalUpdateEffect } from '../../src';
import { useConditionalUpdateEffect } from '../..';

export const Example: React.FC = () => {
const [state1, setState1] = useState(2);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
import { Example } from './useConditionalUpdateEffect.stories';
import { Example } from './example';

<Meta title="Lifecycle/useConditionalUpdateEffect" component={Example} />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useConditionalUpdateEffect } from '../../src';
import { useConditionalUpdateEffect } from '../..';

describe('useConditionalUpdateEffect', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/server';
import { useConditionalUpdateEffect } from '../../src';
import { useConditionalUpdateEffect } from '../..';

describe('useConditionalUpdateEffect', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EffectCallback, useEffect, useRef } from 'react';
import { noop, truthyArrayItemsPredicate } from './util/const';
import { useFirstMountState } from './useFirstMountState';
import { noop, truthyArrayItemsPredicate } from '../util/const';
import { useFirstMountState } from '../useFirstMountState/useFirstMountState';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type IUseConditionalUpdateEffectPredicate<Cond extends ReadonlyArray<any>> = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useDebounceCallback } from '../../src';
import { useDebounceCallback } from '../..';

export const Example: React.FC = () => {
const [state, setState] = useState('');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
import { Example } from './useDebounceCallback.stories';
import { Example } from './example';

<Meta title="Callback/useDebounceCallback" component={Example} />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useDebounceCallback } from '../../src';
import { useDebounceCallback } from '../..';

describe('useDebounceCallback', () => {
beforeAll(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/server';
import { useDebounceCallback } from '../../src';
import { useDebounceCallback } from '../..';

describe('useDebounceCallback', () => {
beforeAll(() => {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useDocumentTitle, useToggle } from '../../src';
import { useDocumentTitle, useToggle } from '../..';

export const Example: React.FC = () => {
const [mounted, toggleMounted] = useToggle(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
import { Example } from './useDocumentTitle.stories';
import { Example } from './example';

<Meta title="Dom/useDocumentTitle" component={Example} />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useDocumentTitle } from '../../src';
import { useDocumentTitle } from '../..';

describe('useDocumentTitle', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react-hooks/server';
import { useDocumentTitle } from '../../src';
import { useDocumentTitle } from '../..';

describe('useDocumentTitle', () => {
it('should be defined', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef } from 'react';
import { isBrowser } from './util/const';
import { useUnmountEffect } from './useUnmountEffect';
import { useSyncedRef } from './useSyncedRef';
import { isBrowser } from '../util/const';
import { useUnmountEffect } from '../useUnmountEffect/useUnmountEffect';
import { useSyncedRef } from '../useSyncedRef/useSyncedRef';

export interface IUseDocumentTitleOptions {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { useFirstMountState, useRerender } from '../../src';
import { useFirstMountState, useRerender } from '../..';

export const Example: React.FC = () => {
const isFirstMount = useFirstMountState();
Expand Down
Loading

0 comments on commit 509ec73

Please sign in to comment.