Skip to content

Commit

Permalink
feat: add functions
Browse files Browse the repository at this point in the history
  • Loading branch information
maxgfr committed Dec 4, 2022
1 parent 9658b41 commit 4c4c111
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 147 deletions.
1 change: 1 addition & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
Expand Down
33 changes: 7 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
# typescript-react-lib-swc
# react-essentials-functions

A simple react boilerplate for creating a library of components made in typescript using `swc`.
A collection of useful `hooks` and `components` for React that I use in my projects.

It also uses:
- `storybook` for viewing a components
- `testing-library` for testing components
- `semantic-release` for publishing a package for this library components
## Installation

## Clone repository and install dependencies

```sh
git clone https://github.com/maxgfr/typescript-react-lib-swc # For cloning the repository
cd typescript-react-lib-swc # To navigate to the repository root
yarn # Install dependencies
```

## Building the code

```sh
yarn build # For building the code with typechecking
yarn build:swc # For building without typechecking
```bash
yarn add react-essentials-functions
```

> **:warning: No typechecking made in dev mode**
## Testing the code
## Usage

```sh
yarn test # For running unit test
yarn test:watch # For watching unit test
```
Documentation is in progress...
27 changes: 13 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
{
"name": "typescript-react-lib-swc",
"version": "1.0.1",
"name": "react-essentials-functions",
"version": "1.0.0",
"author": "maxgfr",
"license": "MIT",
"description": "A minimalist typescript swc starter for react",
"description": "A collection of zero-dependencies useful hooks and components for React",
"main": "./build/index.js",
"repository": {
"type": "git",
"url": "https://github.com/maxgfr/typescript-react-lib-swc.git"
"url": "https://github.com/maxgfr/react-essentials-functions.git"
},
"bugs": {
"url": "https://github.com/maxgfr/typescript-react-lib-swc/issues"
"url": "https://github.com/maxgfr/react-essentials-functions/issues"
},
"homepage": "https://github.com/maxgfr/typescript-react-lib-swc#readme",
"homepage": "https://github.com/maxgfr/react-essentials-functions#readme",
"files": [
"build"
],
"keywords": [
"boilerplate",
"typescript",
"swc",
"hooks",
"react",
"storybook",
"@testing-library"
"components",
"useful"
],
"scripts": {
"dev": "nodemon",
Expand All @@ -42,12 +40,13 @@
"storybook:deploy:action": "npm run storybook:build && gh-pages -d storybook-static -u \"github-actions-bot <[email protected]>\"",
"release": "semantic-release"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"peerDependencies": {
"react": "*",
"react-dom": "*"
},
"devDependencies": {
"@babel/core": "^7.20.2",
"@semantic-release/changelog": "^6.0.2",
"@semantic-release/commit-analyzer": "^9.0.2",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^8.0.6",
Expand Down
7 changes: 0 additions & 7 deletions src/HelloWorld.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions src/Input.tsx

This file was deleted.

13 changes: 0 additions & 13 deletions src/__tests__/HelloWorld.test.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions src/__tests__/Input.test.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions src/components/ConditionnalWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';

export type ConditionnalWrapperProps = {
condition: boolean;
wrapper: (children: React.ReactNode) => React.ReactNode;
children: React.ReactNode;
};

export const ConditionalWrapper = ({
condition,
wrapper,
children,
}: ConditionnalWrapperProps) => (condition ? wrapper(children) : children);

// <ConditionalWrapper
// condition={link}
// wrapper={children => <a href={link}>{children}</a>}
// >
// .....
// </ConditionalWrapper>
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ConditionnalWrapper';
6 changes: 6 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './useDimensions';
export * from './useSafeFetch';
export * from './useSafeState';
export * from './useScript';
export * from './useTheme';
export * from './useWindowDimensions';
37 changes: 37 additions & 0 deletions src/hooks/useDimensions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useEffect, useLayoutEffect, useState } from 'react';

export function useDimensions(targetRef: React.RefObject<HTMLElement>) {
const getDimensions = () => {
return {
width: targetRef.current ? targetRef.current.offsetWidth : 0,
height: targetRef.current ? targetRef.current.offsetHeight : 0,
};
};

const [dimensions, setDimensions] = useState(getDimensions);

const handleResize = () => {
setDimensions(getDimensions());
};

useEffect(() => {
window.addEventListener('resize', handleResize);
window.addEventListener('scroll', handleResize);
window.addEventListener('load', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.removeEventListener('scroll', handleResize);
window.addEventListener('load', handleResize);
};
}, []);

useLayoutEffect(() => {
handleResize();
}, []);
return dimensions;
}

// const targetRef = useRef() // then set a ref to your component
// const size = useDimensions(targetRef)
// ....
// return (div ref={targetRef}> .... <p>{size.width} - {size.height} </p> .... </div>);
12 changes: 12 additions & 0 deletions src/hooks/useSafeFetch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useCallback, useEffect, useRef } from 'react';

export function useSafeFetch() {
const abortController = useRef(new AbortController());
useEffect(() => () => abortController.current.abort(), []);

return useCallback(
(url: string, options: Record<any, any>) =>
fetch(url, { signal: abortController.current.signal, ...options }),
[],
);
}
19 changes: 19 additions & 0 deletions src/hooks/useSafeState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRef, useState, useEffect, useCallback } from 'react';

export function useSafeState(initialValue = null) {
const isMounted = useRef(true);
const [state, setState] = useState(initialValue);

useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);

const setStateSafe = useCallback((value: any) => {
if (isMounted.current) {
setState(value);
}
}, []);
return [state, setStateSafe];
}
16 changes: 16 additions & 0 deletions src/hooks/useScript.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect } from 'react';

export const useScript = (url: string) => {
useEffect(() => {
const script = document.createElement('script');

script.src = url;
script.async = true;

document.body.appendChild(script);

return () => {
document.body.removeChild(script);
};
}, [url]);
};
19 changes: 19 additions & 0 deletions src/hooks/useTheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MouseEventHandler, useEffect, useState } from 'react';

export const useTheme = (): [string, MouseEventHandler, boolean] => {
const [theme, setTheme] = useState('light');
const [mountedComponent, setMountedComponent] = useState(false);
const setMode = (mode: 'light' | 'dark') => {
window.localStorage.setItem('theme', mode);
setTheme(mode);
};
const themeToggler = () => {
theme === 'light' ? setMode('dark') : setMode('light');
};
useEffect(() => {
const localTheme = window.localStorage.getItem('theme');
localTheme ? setTheme(localTheme) : setMode('light');
setMountedComponent(true);
}, []);
return [theme, themeToggler, mountedComponent];
};
32 changes: 32 additions & 0 deletions src/hooks/useWindowDimensions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useState, useEffect } from 'react';

export default function useWindowDimensions() {
const hasWindow = typeof window !== 'undefined';

function getWindowDimensions() {
const width = hasWindow ? window.innerWidth : null;
const height = hasWindow ? window.innerHeight : null;
return {
width,
height,
};
}

const [windowDimensions, setWindowDimensions] = useState(
getWindowDimensions(),
);

useEffect(() => {
if (hasWindow) {
// eslint-disable-next-line no-inner-declarations
function handleResize() {
setWindowDimensions(getWindowDimensions());
}

window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}
}, [hasWindow]);

return windowDimensions;
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './HelloWorld';
export * from './Input';
export * from './components';
export * from './hooks';
16 changes: 0 additions & 16 deletions src/stories/HelloWorld.stories.tsx

This file was deleted.

12 changes: 0 additions & 12 deletions src/stories/Input.stories.tsx

This file was deleted.

Loading

0 comments on commit 4c4c111

Please sign in to comment.