Skip to content

Commit

Permalink
First package version
Browse files Browse the repository at this point in the history
  • Loading branch information
Hubert Stemplewski authored and Hubert Stemplewski committed Nov 3, 2021
0 parents commit cca3e2f
Show file tree
Hide file tree
Showing 13 changed files with 3,982 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react",
"@typescript-eslint"
],
"rules": {
}
}
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/lib

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src
tsconfig.json
eslint.json
.prettierrc
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore artifacts:
build
coverage
9 changes: 9 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"arrowParens": "always",
"bracketSpacing": true,
"printWidth": 120
}
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./src";
8 changes: 8 additions & 0 deletions jestconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"transform": {
"^.+\\.(t|j)sx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
"testEnvironment": "jsdom"
}
37 changes: 37 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "react-dialog-hook",
"version": "0.0.1",
"description": "React hook for manage dialogs state",
"main": "lib/index.js",
"author": "Hubert Stemplewski",
"license": "MIT",
"scripts": {
"test": "jest --config jestconfig.json",
"build": "rm -rf ./lib && tsc --module CommonJS --outDir ./lib",
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
"lint": "eslint --ext js,ts src",
"prepare": "yarn run build",
"prepublishOnly": "yarn test && yarn run lint",
"preversion": "yarn run lint",
"version": "yarn run format && git add -A src",
"postversion": "git push && git push --tags"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.15.0",
"@testing-library/react": "^12.1.2",
"@testing-library/react-hooks": "^7.0.2",
"@types/jest": "^27.0.2",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"eslint": "^7.26.0",
"eslint-plugin-react": "^7.26.1",
"jest": "^27.3.1",
"prettier": "^2.4.1",
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
64 changes: 64 additions & 0 deletions src/__tests__/use-dialog.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { renderHook, act } from "@testing-library/react-hooks";
import { useDialog } from "../use-dialog";

describe("use-dialog", () => {
test("open/close dialog with params and results", async () => {
const dialogInstance = renderHook(() => useDialog());
const MOCKED_PARAMS = { key: "param" };
const MOCKED_RESULT = { key: "result" };
// OPEN
act(() => {
dialogInstance.result.current.open(MOCKED_PARAMS);
});
expect(dialogInstance.result.current.isOpen).toBe(true);
expect(dialogInstance.result.current.params).toEqual(MOCKED_PARAMS);
expect(dialogInstance.result.current.results).toBe(null);
// CLOSE
act(() => {
dialogInstance.result.current.close(MOCKED_RESULT);
});
expect(dialogInstance.result.current.isOpen).toBe(false);
expect(dialogInstance.result.current.results).toEqual(MOCKED_RESULT);
expect(dialogInstance.result.current.params).toBe(null);
});

test("open/close dialog without params and results", async () => {
const dialogInstance = renderHook(() => useDialog());

// OPEN
act(() => {
dialogInstance.result.current.open();
});
expect(dialogInstance.result.current.isOpen).toBe(true);
expect(dialogInstance.result.current.params).toBe(null);
expect(dialogInstance.result.current.results).toBe(null);
// CLOSE
act(() => {
dialogInstance.result.current.close();
});
expect(dialogInstance.result.current.isOpen).toBe(false);
expect(dialogInstance.result.current.results).toBe(null);
expect(dialogInstance.result.current.params).toBe(null);
});
});

test("default open dialog", () => {
const dialogInstance = renderHook(() => useDialog({ isDefaultOpen: true }));

expect(dialogInstance.result.current.isOpen).toBe(true);
});

test("open method return results after close", async () => {
const dialogInstance = renderHook(() => useDialog());

await act(async () => {
setTimeout(() => {
// close dialog after 1000 to get results without breaking await
dialogInstance.result.current.close("RESULTS");
}, 1000);

const result = await dialogInstance.result.current.open();

expect(result).toEqual("RESULTS");
});
});
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useDialog } from "./use-dialog";
47 changes: 47 additions & 0 deletions src/use-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useCallback, useRef, useState } from "react";

interface UseDialogConfig {
isDefaultOpen?: boolean;
}

interface UseDialogInterface<Params = unknown, Results = unknown> {
isOpen: boolean;
params: Params | null;
results: Results | null;
open(params?: Params | null): Promise<UseDialogInterface["results"]>;
close(results?: UseDialogInterface["results"]): void;
}

export function useDialog<Params = unknown, Results = unknown>(
config?: UseDialogConfig
): UseDialogInterface<Params, Results> {
const [isOpen, setIsOpen] = useState<boolean>(!!config?.isDefaultOpen);
const [params, setParams] = useState<Params | null>(null);
const [results, setResults] = useState<Results | null>(null);

const close = useRef<UseDialogInterface<Params, Results>["close"]>(() => {
throw new Error("Trying to close dialog without opening it");
});

const open = useCallback((params: Params | null = null) => {
setIsOpen(true);
setParams(params);

return new Promise((resolve) => {
close.current = (results: UseDialogInterface<Params, Results>["results"] = null) => {
setIsOpen(false);
setResults(results);
setParams(null);
resolve(results);
};
});
}, []);

return {
isOpen,
params,
results,
open,
close: close.current,
};
}
22 changes: 22 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react",
"noFallthroughCasesInSwitch": true,
"declaration": true,
"outDir": "./lib"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/__tests__/*"]
}
Loading

0 comments on commit cca3e2f

Please sign in to comment.