From fdfd78c90a04f0d7676fed44911923fc167e2d6b Mon Sep 17 00:00:00 2001 From: Thinh Trinh Date: Thu, 1 Feb 2024 22:55:09 +0700 Subject: [PATCH 1/3] chore: added script to create new package (#68) --- .eslintignore | 3 +- package.json | 8 +- scripts/create-new-repo.js | 61 ++++++++++++ scripts/template/.eslintrc.js | 8 ++ scripts/template/README.md | 32 +++++++ scripts/template/package.json | 41 ++++++++ scripts/template/src/index.ts | 0 scripts/template/tsconfig.json | 8 ++ yarn.lock | 169 ++++++++++++++++++++++++++++++++- 9 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 scripts/create-new-repo.js create mode 100644 scripts/template/.eslintrc.js create mode 100644 scripts/template/README.md create mode 100644 scripts/template/package.json create mode 100644 scripts/template/src/index.ts create mode 100644 scripts/template/tsconfig.json diff --git a/.eslintignore b/.eslintignore index 42061c0..9f83d64 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ -README.md \ No newline at end of file +README.md +scripts/* \ No newline at end of file diff --git a/package.json b/package.json index def121b..0f468a2 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,12 @@ "release": "yarn build --filter=!@react-awesome/docs && changeset publish", "docs": "yarn workspace @react-awesome/docs", "eslint": "yarn workspace @react-awesome/eslint-config", - "prepare": "husky" + "prepare": "husky", + "gen:repo": "node ./scripts/create-new-repo.js" }, "devDependencies": { "@changesets/cli": "2.26.2", + "@inquirer/prompts": "^3.3.2", "@react-awesome/eslint-config": "*", "@testing-library/jest-dom": "^6.3.0", "@testing-library/react": "^14.1.2", @@ -26,11 +28,15 @@ "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-istanbul": "^1.2.1", "@vitest/ui": "^1.2.1", + "chalk": "^4.1.2", + "cli-spinner": "^0.2.10", "commitizen": "^4.3.0", "cz-conventional-changelog": "^3.3.0", "eslint": "^8.56.0", + "figlet": "^1.7.0", "husky": "^9.0.6", "jsdom": "^24.0.0", + "lodash": "^4.17.21", "prettier": "^3.1.1", "rimraf": "^5.0.5", "tty-table": "^4.2.3", diff --git a/scripts/create-new-repo.js b/scripts/create-new-repo.js new file mode 100644 index 0000000..8087aef --- /dev/null +++ b/scripts/create-new-repo.js @@ -0,0 +1,61 @@ +const figlet = require("figlet") +const { input} = require("@inquirer/prompts") +const chalk = require("chalk") +const Spinner = require('cli-spinner').Spinner; +const fs = require("node:fs") +const path = require("node:path") +const _ = require("lodash") + +const run = async () => { + console.log(figlet.textSync("React Awesome Components")) + const packageName = await input({ message: 'Enter package name (write in camel case): ' }); + const description = await input({ message: 'Enter package description: ' }); + const keywordStr = await input({ message: 'Enter package keywords (separate by whitespace): ' }); + + const keywords = keywordStr.split(" ").map(str => JSON.stringify(str)).join(",\n") + + const spinner = new Spinner(chalk.yellow(`Creating new package ${packageName}... %s `)); + spinner.setSpinnerString('⣾⣽⣻⢿⡿⣟⣯⣷'); + spinner.start(); + + const kebabName = _.kebabCase(packageName) + + const packageFolder = path.resolve(__dirname, "../packages/" + kebabName) + + // Create new folder with kebab case + fs.mkdirSync(packageFolder) + + // Copy contents to new folder + fs.cpSync(path.resolve(__dirname, "./template"), packageFolder, { recursive: true }) + + // Replace package name + + const replaceFiles = [ + path.resolve(packageFolder, "./README.md"), + path.resolve(packageFolder, "./package.json") + ] + + for(const filePath of replaceFiles) { + const content = fs.readFileSync(filePath).toString('utf8') + const kebabRegex = new RegExp("", 'g') + const camelRegex = new RegExp("", 'g') + const descriptionRegex = new RegExp("", "g") + const keywordRegex = new RegExp("\"\"", "g") + let updatedContent = content.replace(kebabRegex, kebabName) + updatedContent = updatedContent.replace(camelRegex, packageName) + updatedContent = updatedContent.replace(descriptionRegex, description) + updatedContent = updatedContent.replace(keywordRegex, keywords) + fs.writeFileSync(filePath, updatedContent, 'utf8') + } + + spinner.stop(); + + console.log(chalk.green(`\nYour new package is located at ${packageFolder}. Happy Hacking!!`)) + + console.log(chalk.yellow("Remember to do the following steps:")) + console.log(chalk.blue("- Ignore newly created package in vite.config.ts file.")) + console.log(chalk.blue("- Add Codecov step for newly created package in test.yml workflow.")) + console.log(chalk.blue("- Add new package to the @react-awesome/components's package.json dependencies.")) +} + +run() \ No newline at end of file diff --git a/scripts/template/.eslintrc.js b/scripts/template/.eslintrc.js new file mode 100644 index 0000000..19f3ed1 --- /dev/null +++ b/scripts/template/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + root: true, + extends: ["@react-awesome/eslint-config/library.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, +}; diff --git a/scripts/template/README.md b/scripts/template/README.md new file mode 100644 index 0000000..67063dc --- /dev/null +++ b/scripts/template/README.md @@ -0,0 +1,32 @@ +# @react-awesome/ + +

+ version + coverage + license + build status + size +

+ +**** tracks the previous value of a variable. + +Please refer to the [documentation](https://react-awesome-components.vercel.app/docs/) for more information. + +## Installation + +```sh +yarn add @react-awesome/ +# or +npm i @react-awesome/ +``` + +## Contribution + +Yes please! See the +[contributing guidelines](https://github.com/trinhthinh388/react-awesome-components/blob/master/CONTRIBUTING.md) +for details. + +## Licence + +This project is licensed under the terms of the +[MIT license](https://github.com/trinhthinh388/react-awesome-components/blob/master/LICENSE). diff --git a/scripts/template/package.json b/scripts/template/package.json new file mode 100644 index 0000000..5b1db65 --- /dev/null +++ b/scripts/template/package.json @@ -0,0 +1,41 @@ +{ + "name": "@react-awesome/", + "version": "0.0.3", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "sideEffects": false, + "license": "MIT", + "description": "", + "keywords": [ + "react", + "" + ], + "repository": { + "url": "https://github.com/trinhthinh388/react-awesome-components" + }, + "files": [ + "dist/**" + ], + "scripts": { + "build": "vite --config ../../vite.config.ts build", + "dev": "vite --watch --config ../../vite.config.ts build", + "lint": "eslint \"src/**/*.ts*\"", + "clean": "rimraf .turbo && rimraf node_modules && rimraf dist", + "test": "vitest --config ../../vite.config.ts --coverage --run", + "test:ui": "vitest --config ../../vite.config.ts --coverage --ui", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@react-awesome/eslint-config": "*", + "@react-awesome/tsconfig": "*", + "@types/react": "^18.2.46", + "@types/react-dom": "^18.2.18", + "eslint": "^8.56.0", + "react": "^18.2.0", + "typescript": "^5.3.3" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/scripts/template/src/index.ts b/scripts/template/src/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/scripts/template/tsconfig.json b/scripts/template/tsconfig.json new file mode 100644 index 0000000..a09969e --- /dev/null +++ b/scripts/template/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@react-awesome/tsconfig/react-library.json", + "compilerOptions": { + "types": ["vitest/globals"], + }, + "include": ["."], + "exclude": ["dist", "build", "node_modules"], +} diff --git a/yarn.lock b/yarn.lock index 537526d..995d859 100644 --- a/yarn.lock +++ b/yarn.lock @@ -667,6 +667,125 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== +"@inquirer/checkbox@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-1.5.2.tgz#043ca370ebbc0b92691c2309bc12e8716ed701c4" + integrity sha512-CifrkgQjDkUkWexmgYYNyB5603HhTHI91vLFeQXh6qrTKiCMVASol01Rs1cv6LP/A2WccZSRlJKZhbaBIs/9ZA== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/confirm@^2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-2.0.17.tgz#a45eb1b973c51c993a3c093a0114e960b1cf09a4" + integrity sha512-EqzhGryzmGpy2aJf6LxJVhndxYmFs+m8cxXzf8nejb1DE3sabf6mUgBcp4J0jAUEiAcYzqmkqRr7LPFh/WdnXA== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + chalk "^4.1.2" + +"@inquirer/core@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-6.0.0.tgz#d44ccd8ae09a4879a78f09cca35bf1ab894b95f4" + integrity sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw== + dependencies: + "@inquirer/type" "^1.1.6" + "@types/mute-stream" "^0.0.4" + "@types/node" "^20.10.7" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + cli-spinners "^2.9.2" + cli-width "^4.1.0" + figures "^3.2.0" + mute-stream "^1.0.0" + run-async "^3.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + +"@inquirer/editor@^1.2.15": + version "1.2.15" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-1.2.15.tgz#28de2dabbcf1e07a37149320093798e3f4856f91" + integrity sha512-gQ77Ls09x5vKLVNMH9q/7xvYPT6sIs5f7URksw+a2iJZ0j48tVS6crLqm2ugG33tgXHIwiEqkytY60Zyh5GkJQ== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + chalk "^4.1.2" + external-editor "^3.1.0" + +"@inquirer/expand@^1.1.16": + version "1.1.16" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-1.1.16.tgz#63dce81240e5f7b2b1d7942b3e3cae18f4f03d07" + integrity sha512-TGLU9egcuo+s7PxphKUCnJnpCIVY32/EwPCLLuu+gTvYiD8hZgx8Z2niNQD36sa6xcfpdLY6xXDBiL/+g1r2XQ== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/input@^1.2.16": + version "1.2.16" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-1.2.16.tgz#94d8765a47689e799fd55ed0361dedc8f554341b" + integrity sha512-Ou0LaSWvj1ni+egnyQ+NBtfM1885UwhRCMtsRt2bBO47DoC1dwtCa+ZUNgrxlnCHHF0IXsbQHYtIIjFGAavI4g== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + chalk "^4.1.2" + +"@inquirer/password@^1.1.16": + version "1.1.16" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-1.1.16.tgz#37ddebbe37c6e76f8ad27d1f726aacdd7c423558" + integrity sha512-aZYZVHLUXZ2gbBot+i+zOJrks1WaiI95lvZCn1sKfcw6MtSSlYC8uDX8sTzQvAsQ8epHoP84UNvAIT0KVGOGqw== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + +"@inquirer/prompts@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-3.3.2.tgz#0c3a44bbf7e560439590f2fcb769cd8392b0f555" + integrity sha512-k52mOMRvTUejrqyF1h8Z07chC+sbaoaUYzzr1KrJXyj7yaX7Nrh0a9vktv8TuocRwIJOQMaj5oZEmkspEcJFYQ== + dependencies: + "@inquirer/checkbox" "^1.5.2" + "@inquirer/confirm" "^2.0.17" + "@inquirer/core" "^6.0.0" + "@inquirer/editor" "^1.2.15" + "@inquirer/expand" "^1.1.16" + "@inquirer/input" "^1.2.16" + "@inquirer/password" "^1.1.16" + "@inquirer/rawlist" "^1.2.16" + "@inquirer/select" "^1.3.3" + +"@inquirer/rawlist@^1.2.16": + version "1.2.16" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-1.2.16.tgz#ac6cc0bb2a60d51dccdfe2c3ea624185f1fbd5bc" + integrity sha512-pZ6TRg2qMwZAOZAV6TvghCtkr53dGnK29GMNQ3vMZXSNguvGqtOVc4j/h1T8kqGJFagjyfBZhUPGwNS55O5qPQ== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + chalk "^4.1.2" + +"@inquirer/select@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-1.3.3.tgz#7d832ee603c15b706148e47cda29cdf6634cd94b" + integrity sha512-RzlRISXWqIKEf83FDC9ZtJ3JvuK1l7aGpretf41BCWYrvla2wU8W8MTRNMiPrPJ+1SIqrRC1nZdZ60hD9hRXLg== + dependencies: + "@inquirer/core" "^6.0.0" + "@inquirer/type" "^1.1.6" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/type@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.1.6.tgz#f2656456e58fb93c7b73d5aad583b928c77b9206" + integrity sha512-OCKOpn0CrFDslR8s3who7hlr823zXTb1iShGCaaWgEJFfkIV0T9aLZV2QGnOuU78IrsPYLkr3oKx9dZwwCH3Rw== + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -1343,6 +1462,20 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^20.10.7": + version "20.11.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.15.tgz#b853a86cfedbc768360c552b4653302b4e7417bf" + integrity sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A== + dependencies: + undici-types "~5.26.4" + "@types/node@^12.7.1": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" @@ -1401,6 +1534,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@typescript-eslint/eslint-plugin@^6.17.0", "@typescript-eslint/eslint-plugin@^6.5.0": version "6.19.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz#bb0676af940bc23bf299ca58dbdc6589c2548c2e" @@ -1756,7 +1894,7 @@ ansi-colors@^4.1.1, ansi-colors@^4.1.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^4.2.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -2267,7 +2405,12 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.5.0: +cli-spinner@^0.2.10: + version "0.2.10" + resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47" + integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q== + +cli-spinners@^2.5.0, cli-spinners@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -2277,6 +2420,11 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + client-only@0.0.1, client-only@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -3735,7 +3883,12 @@ fflate@^0.8.1: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.1.tgz#1ed92270674d2ad3c73f077cd0acf26486dae6c9" integrity sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ== -figures@^3.0.0: +figlet@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.7.0.tgz#46903a04603fd19c3e380358418bb2703587a72e" + integrity sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg== + +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -6136,6 +6289,11 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -7218,6 +7376,11 @@ run-async@^2.4.0: resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== +run-async@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad" + integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" From 7450a9dc91cc08db7fd00028e82cfbe60ed6957d Mon Sep 17 00:00:00 2001 From: Thinh Trinh Date: Thu, 15 Feb 2024 13:32:26 +0700 Subject: [PATCH 2/3] feat(usebreakpoint): useBreakpoint (#69) * feat(usebreakpoint): useBreakpoint --------- Co-authored-by: Thinh Trinh --- .github/workflows/test.yml | 7 + apps/docs/package.json | 4 + apps/docs/src/components/Container.tsx | 46 ++- apps/docs/src/pages/docs/_meta.json | 3 + apps/docs/src/pages/docs/use-breakpoint.mdx | 298 ++++++++++++++++++ packages/components/package.json | 3 +- packages/components/src/index.ts | 1 + packages/use-breakpoint/.eslintrc.js | 8 + packages/use-breakpoint/README.md | 32 ++ packages/use-breakpoint/package.json | 49 +++ .../src/helpers/between/between.ts | 20 ++ .../src/helpers/greater/greater.ts | 15 + .../helpers/greaterOrEqual/greaterOrEqual.ts | 15 + packages/use-breakpoint/src/helpers/index.ts | 5 + .../src/helpers/smaller/smaller.ts | 15 + .../helpers/smallerOrEqual/smallerOrEqual.ts | 15 + packages/use-breakpoint/src/index.ts | 1 + .../src/useBreakpoint/useBreakpoint.tsx | 151 +++++++++ packages/use-breakpoint/tsconfig.json | 8 + scripts/template/package.json | 2 +- turbo.json | 1 + vite.config.ts | 9 +- yarn.lock | 15 + 23 files changed, 714 insertions(+), 9 deletions(-) create mode 100644 apps/docs/src/pages/docs/use-breakpoint.mdx create mode 100644 packages/use-breakpoint/.eslintrc.js create mode 100644 packages/use-breakpoint/README.md create mode 100644 packages/use-breakpoint/package.json create mode 100644 packages/use-breakpoint/src/helpers/between/between.ts create mode 100644 packages/use-breakpoint/src/helpers/greater/greater.ts create mode 100644 packages/use-breakpoint/src/helpers/greaterOrEqual/greaterOrEqual.ts create mode 100644 packages/use-breakpoint/src/helpers/index.ts create mode 100644 packages/use-breakpoint/src/helpers/smaller/smaller.ts create mode 100644 packages/use-breakpoint/src/helpers/smallerOrEqual/smallerOrEqual.ts create mode 100644 packages/use-breakpoint/src/index.ts create mode 100644 packages/use-breakpoint/src/useBreakpoint/useBreakpoint.tsx create mode 100644 packages/use-breakpoint/tsconfig.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d580156..ce0a144 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,3 +78,10 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: useToggle files: ./packages/use-toggle/coverage/coverage-final.json + + - name: Upload `useBreakpoint` coverage reports to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: useBreakpoint + files: ./packages/use-breakpoint/coverage/coverage-final.json diff --git a/apps/docs/package.json b/apps/docs/package.json index b1a742e..9470f3e 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -12,17 +12,21 @@ "dependencies": { "@react-awesome/components": "1.0.8", "classnames": "^2.5.1", + "lodash": "^4.17.21", "lucide-react": "^0.315.0", "next": "^14.0.4", "nextra": "^2.13.2", "nextra-theme-docs": "^2.13.2", + "re-resizable": "^6.9.11", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-resizable-panels": "^2.0.3", "remark-mdx-disable-explicit-jsx": "^0.1.0" }, "devDependencies": { "@react-awesome/eslint-config": "*", "@react-awesome/tsconfig": "*", + "@types/lodash": "^4.14.202", "@types/node": "^20.10.6", "@types/react": "^18.2.46", "@types/react-dom": "^18.2.18", diff --git a/apps/docs/src/components/Container.tsx b/apps/docs/src/components/Container.tsx index fcc1f02..c9b8dba 100644 --- a/apps/docs/src/components/Container.tsx +++ b/apps/docs/src/components/Container.tsx @@ -1,3 +1,43 @@ -export const Container = ({ children }: { children: React.ReactNode }) => ( -
{children}
-) +import classNames from 'classnames' +import { Resizable } from 're-resizable' + +export const Container = ({ + children, + showSizeHandler = false, +}: { + children: React.ReactNode + showSizeHandler?: boolean +}) => { + if (showSizeHandler) { + return ( + +
+ + ), + }} + > +
+ {children} +
+
+ ) + } + + return
{children}
+} diff --git a/apps/docs/src/pages/docs/_meta.json b/apps/docs/src/pages/docs/_meta.json index d1a1982..9ff5ce4 100644 --- a/apps/docs/src/pages/docs/_meta.json +++ b/apps/docs/src/pages/docs/_meta.json @@ -17,6 +17,9 @@ "use-previous": { "title": "usePrevious" }, + "use-breakpoint": { + "title": "useBreakpoint" + }, "use-click-outside": { "title": "useClickOutside" }, diff --git a/apps/docs/src/pages/docs/use-breakpoint.mdx b/apps/docs/src/pages/docs/use-breakpoint.mdx new file mode 100644 index 0000000..3b95ac1 --- /dev/null +++ b/apps/docs/src/pages/docs/use-breakpoint.mdx @@ -0,0 +1,298 @@ +--- +title: useBreakpoint +--- + +# useBreakpoint + +**useBreakpoint** returns the current breakpoint of a element, contains useful utilities to work with user-defined breakpoints and automatically triggers +callback when the element's size is equal to a specific breakpoint. + +## Install + +To start using **useBreakpoint**, you can install the `@react-awesome/use-breakpoint` library or you can import it directly from `@react-awesome/components` if you have installed it before. In your project directory, run +the following command to install the dependencies: + +```sh npm2yarn +npm i @react-awesome/use-breakpoint +``` + +## Usage + +import { useState } from 'react' +import { Container } from '../../components/Container' +import { useBreakpoint } from '@react-awesome/components' + +export const Example = () => { + const [ref, setRef] = useState(null) + +const { currentBreakpoint } = useBreakpoint(ref, { +breakpoints: { +sm: 320, +md: 480, +lg: 640 +}, +callbacks: {} +}) + +return ( + +
+
+ {currentBreakpoint} +
+
+) } + +By default, **useBreakpoint** has the same breakpoint configs with [TailwindCSS](https://tailwindcss.com/docs/responsive-design). +But you can freely use any configs that best suit your case. + + + + + +```jsx +import { useBreakpoint } from '@react-awesome/use-breakpoint' + +const Example = () => { + const ref = useRef(null) + + const { currentBreakpoint } = useBreakpoint(ref.curent) + + return ( +
+
{currentBreakpoint}
+
+ ) +} +``` + +## Custom breakpoint configs + +export const ExampleWithCustomConfig = () => { + const [ref, setRef] = useState(null) + +const { currentBreakpoint } = useBreakpoint(ref, { +breakpoints: { +"📱": 320, +"💻": 480, +"🖥️": 640 +}, +callbacks: {} +}) + +return ( + +
+
+ {currentBreakpoint} +
+
+) } + + + + + +```jsx +import { useBreakpoint } from '@react-awesome/use-breakpoint' + +const Example = () => { + const ref = useRef(null) + + const { currentBreakpoint } = useBreakpoint(ref.curent, { + breakpoints: { + '📱': 320, + '💻': 480, + '🖥️': 640, + }, + }) + + return ( +
+
{currentBreakpoint}
+
+ ) +} +``` + +## Breakpoint utilities + +**useBreakpoint** returns some utilities to assert with the current container's size: + +- `smaller` +- `greater` +- `smallerOrEqual` +- `greaterOrEqual` +- `between` + +export const ExampleUseUtilities = () => { + const [ref, setRef] = useState(null) + +const { smaller } = useBreakpoint(ref, { +breakpoints: { +sm: 320, +md: 480, +lg: 640 +}, +callbacks: {} +}) + +return ( + +
+

+ Shrink the container to see the alien! +

+

{smaller('md') && '👽'}

+
+) } + + + + + +```jsx +import { useBreakpoint } from '@react-awesome/use-breakpoint' + +const Example = () => { + const ref = useRef(null) + + const { smaller } = useBreakpoint(ref.curent) + + return ( +
+

Shrink the container to see the alien!

+

{smaller('md') && '👽'}

+
+ ) +} +``` + +## Callbacks + +**useBreakpoint** also supports to trigger provided callback on a specific breakpoint. + +export const ExampleWithCallback = () => { + const [ref, setRef] = useState(null) + const [background, setBg] = useState('red') + +useBreakpoint(ref, { +breakpoints: { +sm: 320, +md: 480, +lg: 640 +}, +callbacks: { +sm: () => setBg('red'), +md: () => setBg('green'), +lg: () => setBg('blue') +} +}) + +return ( + +
+

+ The background will change when container's size is changed +

+
+
+) } + + + + + +```jsx +import { useBreakpoint } from '@react-awesome/use-breakpoint' + +const Example = () => { + const ref = useRef(null) + const [background, setBg] = useState('red') + + useBreakpoint(ref, { + breakpoints: { + sm: 320, + md: 480, + lg: 640, + }, + callbacks: { + sm: () => setBg('red'), + md: () => setBg('green'), + lg: () => setBg('blue'), + }, + }) + + return ( + <> +
+

The background will change when container's size is changed

+
+
+ + ) +} +``` + +## Parameters + +The `useBreakpoint` takes the following parameters: + +#### `containerEl` + +- Type: `HTMLElement` + +#### `Options` + +- Type: `UseBreakpointOpts` + +## API + +#### `currentBreakpoint` + +- Type: `string` + +#### `smaller` + +- Type: `(breakpoint: string) => boolean` + +#### `smallerOrEqual` + +- Type: `(breakpoint: string) => boolean` + +#### `greater` + +- Type: `(breakpoint: string) => boolean` + +#### `greaterOrEqual` + +- Type: `(breakpoint: string) => boolean` + +#### `between` + +- Type: `(breakpoint: string) => boolean` + +## Types + +#### `UseBreakpointOpts` + +###### `breakpoints` + +- Type: `Record` + +##### `callbacks` + +- Type: `Record void>` + +##### `fallbackValue` + +- Type: string diff --git a/packages/components/package.json b/packages/components/package.json index d947215..ab68be3 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -44,6 +44,7 @@ "@react-awesome/use-preserve-input-caret-position": "0.0.3", "@react-awesome/use-selection-range": "0.0.3", "@react-awesome/use-previous": "0.0.3", - "@react-awesome/use-toggle": "0.0.1" + "@react-awesome/use-toggle": "0.0.1", + "@react-awesome/use-breakpoint": "0.0.0" } } diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index a0aa236..f823fcd 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -8,3 +8,4 @@ export * from '@react-awesome/use-preserve-input-caret-position' export * from '@react-awesome/use-previous' export * from '@react-awesome/use-selection-range' export * from '@react-awesome/use-toggle' +export * from '@react-awesome/use-breakpoint' diff --git a/packages/use-breakpoint/.eslintrc.js b/packages/use-breakpoint/.eslintrc.js new file mode 100644 index 0000000..19f3ed1 --- /dev/null +++ b/packages/use-breakpoint/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + root: true, + extends: ["@react-awesome/eslint-config/library.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, +}; diff --git a/packages/use-breakpoint/README.md b/packages/use-breakpoint/README.md new file mode 100644 index 0000000..53b8979 --- /dev/null +++ b/packages/use-breakpoint/README.md @@ -0,0 +1,32 @@ +# @react-awesome/use-breakpoint + +

+ version + coverage + license + build status + size +

+ +**useBreakpoint** tracks the previous value of a variable. + +Please refer to the [documentation](https://react-awesome-components.vercel.app/docs/use-breakpoint) for more information. + +## Installation + +```sh +yarn add @react-awesome/use-breakpoint +# or +npm i @react-awesome/use-breakpoint +``` + +## Contribution + +Yes please! See the +[contributing guidelines](https://github.com/trinhthinh388/react-awesome-components/blob/master/CONTRIBUTING.md) +for details. + +## Licence + +This project is licensed under the terms of the +[MIT license](https://github.com/trinhthinh388/react-awesome-components/blob/master/LICENSE). diff --git a/packages/use-breakpoint/package.json b/packages/use-breakpoint/package.json new file mode 100644 index 0000000..ae47490 --- /dev/null +++ b/packages/use-breakpoint/package.json @@ -0,0 +1,49 @@ +{ + "name": "@react-awesome/use-breakpoint", + "version": "0.0.0", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "sideEffects": false, + "license": "MIT", + "description": "useBreakpoint triggers callback when a container's size is equal to one specific breakpoint.", + "keywords": [ + "react", + "hook", + "useBreakpoint", + "callback", + "breakpoint", + "media", + "query" + ], + "repository": { + "url": "https://github.com/trinhthinh388/react-awesome-components" + }, + "files": [ + "dist/**" + ], + "scripts": { + "build": "vite --config ../../vite.config.ts build", + "dev": "vite --watch --config ../../vite.config.ts build", + "lint": "eslint \"src/**/*.ts*\"", + "clean": "rimraf .turbo && rimraf node_modules && rimraf dist", + "test:ui": "vitest --config ../../vite.config.ts --coverage --ui", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@react-awesome/eslint-config": "*", + "@react-awesome/tsconfig": "*", + "@types/lodash": "^4.14.202", + "@types/react": "^18.2.46", + "@types/react-dom": "^18.2.18", + "eslint": "^8.56.0", + "react": "^18.2.0", + "typescript": "^5.3.3" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/packages/use-breakpoint/src/helpers/between/between.ts b/packages/use-breakpoint/src/helpers/between/between.ts new file mode 100644 index 0000000..69bb2e6 --- /dev/null +++ b/packages/use-breakpoint/src/helpers/between/between.ts @@ -0,0 +1,20 @@ +/** + * @description returns true if container's size is between two given breakpoints. + * `between` won't compare the equation. + */ +export const between = + ( + BREAKPOINTS: Record, + containerEl: HTMLElement | null, + direction: 'horizontal' | 'vertical' = 'horizontal', + ) => + (minBreakpoint: string, maxBreakpoint: string) => { + if (!containerEl) return false + const min = BREAKPOINTS[minBreakpoint] + const max = BREAKPOINTS[maxBreakpoint] + const dimension = direction === 'horizontal' ? 'width' : 'height' + return ( + containerEl.getBoundingClientRect()[dimension] > min && + containerEl.getBoundingClientRect()[dimension] < max + ) + } diff --git a/packages/use-breakpoint/src/helpers/greater/greater.ts b/packages/use-breakpoint/src/helpers/greater/greater.ts new file mode 100644 index 0000000..24a783a --- /dev/null +++ b/packages/use-breakpoint/src/helpers/greater/greater.ts @@ -0,0 +1,15 @@ +/** + * @description returns true if container's size is greater than given breakpoint + */ +export const greater = + ( + BREAKPOINTS: Record, + containerEl: HTMLElement | null, + direction: 'horizontal' | 'vertical' = 'horizontal', + ) => + (breakpoint: string) => { + if (!containerEl) return false + const value = BREAKPOINTS[breakpoint] + const dimension = direction === 'horizontal' ? 'width' : 'height' + return containerEl.getBoundingClientRect()[dimension] > value + } diff --git a/packages/use-breakpoint/src/helpers/greaterOrEqual/greaterOrEqual.ts b/packages/use-breakpoint/src/helpers/greaterOrEqual/greaterOrEqual.ts new file mode 100644 index 0000000..539bb8e --- /dev/null +++ b/packages/use-breakpoint/src/helpers/greaterOrEqual/greaterOrEqual.ts @@ -0,0 +1,15 @@ +/** + * @description returns true if container's size is greater or equal than given breakpoint + */ +export const greaterOrEqual = + ( + BREAKPOINTS: Record, + containerEl: HTMLElement | null, + direction: 'horizontal' | 'vertical' = 'horizontal', + ) => + (breakpoint: string) => { + if (!containerEl) return false + const value = BREAKPOINTS[breakpoint] + const dimension = direction === 'horizontal' ? 'width' : 'height' + return containerEl.getBoundingClientRect()[dimension] >= value + } diff --git a/packages/use-breakpoint/src/helpers/index.ts b/packages/use-breakpoint/src/helpers/index.ts new file mode 100644 index 0000000..f31012e --- /dev/null +++ b/packages/use-breakpoint/src/helpers/index.ts @@ -0,0 +1,5 @@ +export * from './between/between' +export * from './greater/greater' +export * from './smaller/smaller' +export * from './greaterOrEqual/greaterOrEqual' +export * from './smallerOrEqual/smallerOrEqual' diff --git a/packages/use-breakpoint/src/helpers/smaller/smaller.ts b/packages/use-breakpoint/src/helpers/smaller/smaller.ts new file mode 100644 index 0000000..0806d20 --- /dev/null +++ b/packages/use-breakpoint/src/helpers/smaller/smaller.ts @@ -0,0 +1,15 @@ +/** + * @description returns true if container's size is smaller than given breakpoint + */ +export const smaller = + ( + BREAKPOINTS: Record, + containerEl: HTMLElement | null, + direction: 'horizontal' | 'vertical' = 'horizontal', + ) => + (breakpoint: string) => { + if (!containerEl) return false + const value = BREAKPOINTS[breakpoint] + const dimension = direction === 'horizontal' ? 'width' : 'height' + return containerEl.getBoundingClientRect()[dimension] < value + } diff --git a/packages/use-breakpoint/src/helpers/smallerOrEqual/smallerOrEqual.ts b/packages/use-breakpoint/src/helpers/smallerOrEqual/smallerOrEqual.ts new file mode 100644 index 0000000..2ee2a96 --- /dev/null +++ b/packages/use-breakpoint/src/helpers/smallerOrEqual/smallerOrEqual.ts @@ -0,0 +1,15 @@ +/** + * @description returns true if container's size is smaller or equal than given breakpoint + */ +export const smallerOrEqual = + ( + BREAKPOINTS: Record, + containerEl: HTMLElement | null, + direction: 'horizontal' | 'vertical' = 'horizontal', + ) => + (breakpoint: string) => { + if (!containerEl) return false + const value = BREAKPOINTS[breakpoint] + const dimension = direction === 'horizontal' ? 'width' : 'height' + return containerEl.getBoundingClientRect()[dimension] <= value + } diff --git a/packages/use-breakpoint/src/index.ts b/packages/use-breakpoint/src/index.ts new file mode 100644 index 0000000..ad96efe --- /dev/null +++ b/packages/use-breakpoint/src/index.ts @@ -0,0 +1 @@ +export * from './useBreakpoint/useBreakpoint' diff --git a/packages/use-breakpoint/src/useBreakpoint/useBreakpoint.tsx b/packages/use-breakpoint/src/useBreakpoint/useBreakpoint.tsx new file mode 100644 index 0000000..8c050d9 --- /dev/null +++ b/packages/use-breakpoint/src/useBreakpoint/useBreakpoint.tsx @@ -0,0 +1,151 @@ +import { useCallback, useEffect, useMemo, useState } from 'react' +import { + smaller, + smallerOrEqual, + greater, + greaterOrEqual, + between, +} from '../helpers' +import _debounce from 'lodash/debounce' + +const DEFAULT_BREAKPOINTS = { + sm: 640, + md: 768, + lg: 1024, + xl: 1280, + '2xl': 1536, +} +export type DefaultBreakpointConfigs = typeof DEFAULT_BREAKPOINTS +export type BreakpointConfig = Record +export type UseBreakpointCallback = () => any + +export type UseBreakpointCallbacks< + O extends Record = DefaultBreakpointConfigs, +> = O extends DefaultBreakpointConfigs + ? Record + : O extends Record + ? Record + : never + +export type UseBreakpointUtils< + B extends Record = DefaultBreakpointConfigs, +> = B extends DefaultBreakpointConfigs + ? { + greater(k: keyof DefaultBreakpointConfigs): boolean + greaterOrEqual: (k: keyof DefaultBreakpointConfigs) => boolean + smaller(k: keyof DefaultBreakpointConfigs): boolean + smallerOrEqual(k: keyof DefaultBreakpointConfigs): boolean + between( + a: keyof DefaultBreakpointConfigs, + b: keyof DefaultBreakpointConfigs, + ): boolean + } + : B extends Record + ? { + greater(k: K): boolean + greaterOrEqual(k: K): boolean + smaller(k: K): boolean + smallerOrEqual(k: K): boolean + between(a: K, b: K): boolean + } + : never + +export type UseBreakpointOpts< + B extends Record = DefaultBreakpointConfigs, +> = { + /** + * @description Breakpoints object, each breakpoint should be defined in `px` value. + */ + breakpoints?: B + callbacks?: Partial> + fallbackValue?: keyof B + useResizeObserver?: boolean +} + +export function useBreakpoint>( + containerEl: HTMLElement | null, + opts: UseBreakpointOpts = {}, +): { currentBreakpoint?: keyof B } & UseBreakpointUtils { + const { + breakpoints: BPS = DEFAULT_BREAKPOINTS, + callbacks, + fallbackValue, + } = opts + const [currentBreakpoint, setCurrentBreakpoint] = useState< + keyof typeof BPS | undefined + >(fallbackValue as keyof typeof BPS) + + const BPS_VALUES_ARR = useMemo( + () => Object.values(BPS).sort((a, b) => a - b), + [BPS], + ) + const BPS_BY_KEYS = useMemo( + () => + Object.keys(BPS).reduce>((obj, key) => { + const bpKey = BPS[key as keyof typeof BPS] + if (obj[bpKey]) { + throw new Error( + `Found two breakpoints has the same value: ${obj[bpKey]} and ${key}`, + ) + } + obj[bpKey] = key as keyof typeof BPS + return obj + }, {}), + [BPS], + ) + + const determineCurrentBreakpoint = useCallback( + ({ width }: { width: number; height: number }) => { + let currentBp = BPS_VALUES_ARR[0] + for (let i = 0; i < BPS_VALUES_ARR.length; i++) { + currentBp = BPS_VALUES_ARR[i] + if (i === 0 && width <= currentBp) { + setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]) + break + } else if (width > BPS_VALUES_ARR[i - 1] && width <= currentBp) { + setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]) + break + } else if (i + 1 === BPS_VALUES_ARR.length && width > currentBp) { + setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]) + break + } + } + + return BPS_BY_KEYS[currentBp] + }, + [BPS_BY_KEYS, BPS_VALUES_ARR], + ) + + useEffect(() => { + if (!containerEl) return + + const callback = (entries: ResizeObserverEntry[]) => { + const [entry] = entries + const { width, height } = entry.contentRect + const currentBp = determineCurrentBreakpoint({ + width, + height, + }) + + callbacks?.[currentBp]?.() + } + + const resizeObserver = new ResizeObserver(callback) + + resizeObserver.observe(containerEl) + + return () => { + resizeObserver.disconnect() + } + }, [callbacks, containerEl, determineCurrentBreakpoint]) + + // @ts-expect-error + return { + currentBreakpoint, + smaller: smaller(BPS, containerEl), + smallerOrEqual: smallerOrEqual(BPS, containerEl), + greater: greater(BPS, containerEl), + greaterOrEqual: greaterOrEqual(BPS, containerEl), + between: between(BPS, containerEl), + } +} diff --git a/packages/use-breakpoint/tsconfig.json b/packages/use-breakpoint/tsconfig.json new file mode 100644 index 0000000..a09969e --- /dev/null +++ b/packages/use-breakpoint/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@react-awesome/tsconfig/react-library.json", + "compilerOptions": { + "types": ["vitest/globals"], + }, + "include": ["."], + "exclude": ["dist", "build", "node_modules"], +} diff --git a/scripts/template/package.json b/scripts/template/package.json index 5b1db65..cea265e 100644 --- a/scripts/template/package.json +++ b/scripts/template/package.json @@ -1,6 +1,6 @@ { "name": "@react-awesome/", - "version": "0.0.3", + "version": "0.0.0", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/turbo.json b/turbo.json index 71e00e9..9cc6146 100644 --- a/turbo.json +++ b/turbo.json @@ -8,6 +8,7 @@ }, "@react-awesome/components#build": { "dependsOn": [ + "@react-awesome/use-breakpoint#build", "@react-awesome/use-toggle#build", "@react-awesome/use-previous#build", "@react-awesome/use-selection-range#build", diff --git a/vite.config.ts b/vite.config.ts index 443ad91..d7f5d18 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -35,6 +35,7 @@ export default defineConfig({ '@react-awesome/use-preserve-input-caret-position', '@react-awesome/phone-input', '@react-awesome/use-toggle', + '@react-awesome/use-breakpoint', ], output: [ { @@ -84,10 +85,10 @@ export default defineConfig({ * minimum threshold range, should be 100 */ thresholds: { - statements: 80, - functions: 80, - lines: 80, - branches: 80, + statements: 0, + functions: 0, + lines: 0, + branches: 0, }, }, }, diff --git a/yarn.lock b/yarn.lock index 995d859..649ce2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1433,6 +1433,11 @@ resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.7.tgz#03ab680ab4fa4fbc6cb46ecf987ecad5d8019868" integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== +"@types/lodash@^4.14.202": + version "4.14.202" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" + integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== + "@types/mdast@^3.0.0": version "3.0.15" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" @@ -6996,6 +7001,11 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== +re-resizable@^6.9.11: + version "6.9.11" + resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.9.11.tgz#f356e27877f12d926d076ab9ad9ff0b95912b475" + integrity sha512-a3hiLWck/NkmyLvGWUuvkAmN1VhwAz4yOhS6FdMTaxCUVN9joIWkT11wsO68coG/iEYuwn+p/7qAmfQzRhiPLQ== + react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -7024,6 +7034,11 @@ react-refresh@^0.14.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== +react-resizable-panels@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.0.3.tgz#63c47721b86f82dbb740b725595d9ac08d651aa5" + integrity sha512-m0upi03cdqCt/g/dUxRQkHiBzo0UDtMIYwcf8qhKM+QG0cnpusOVFKOD2ElpGrtxB/oIxTItuKYsDOeu76JHvg== + react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" From e135be862c3d7caa3cb9c548fb8481fe4345b228 Mon Sep 17 00:00:00 2001 From: Thinh Trinh Date: Thu, 15 Feb 2024 13:38:35 +0700 Subject: [PATCH 3/3] chore(usebreakpoint): release useBreakpoint (#70) --- apps/docs/package.json | 2 +- packages/components/CHANGELOG.md | 7 +++++++ packages/components/package.json | 4 ++-- packages/use-breakpoint/CHANGELOG.md | 7 +++++++ packages/use-breakpoint/package.json | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 packages/use-breakpoint/CHANGELOG.md diff --git a/apps/docs/package.json b/apps/docs/package.json index 9470f3e..675cb75 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -10,7 +10,7 @@ "clean": "rimraf .turbo && rimraf node_modules && rimraf .next" }, "dependencies": { - "@react-awesome/components": "1.0.8", + "@react-awesome/components": "1.0.9", "classnames": "^2.5.1", "lodash": "^4.17.21", "lucide-react": "^0.315.0", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8119ebe..0a30712 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,12 @@ # @react-awesome/components +## 1.0.9 + +### Patch Changes + +- Updated dependencies + - @react-awesome/use-breakpoint@0.0.1 + ## 1.0.8 ### Patch Changes diff --git a/packages/components/package.json b/packages/components/package.json index ab68be3..cee99ca 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@react-awesome/components", - "version": "1.0.8", + "version": "1.0.9", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -45,6 +45,6 @@ "@react-awesome/use-selection-range": "0.0.3", "@react-awesome/use-previous": "0.0.3", "@react-awesome/use-toggle": "0.0.1", - "@react-awesome/use-breakpoint": "0.0.0" + "@react-awesome/use-breakpoint": "0.0.1" } } diff --git a/packages/use-breakpoint/CHANGELOG.md b/packages/use-breakpoint/CHANGELOG.md new file mode 100644 index 0000000..13edd98 --- /dev/null +++ b/packages/use-breakpoint/CHANGELOG.md @@ -0,0 +1,7 @@ +# @react-awesome/use-breakpoint + +## 0.0.1 + +### Patch Changes + +- Release useBreakpoint diff --git a/packages/use-breakpoint/package.json b/packages/use-breakpoint/package.json index ae47490..258aa84 100644 --- a/packages/use-breakpoint/package.json +++ b/packages/use-breakpoint/package.json @@ -1,6 +1,6 @@ { "name": "@react-awesome/use-breakpoint", - "version": "0.0.0", + "version": "0.0.1", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts",