diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8db2ffb..7fa1c51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,6 @@ on: branches: - main pull_request: - branches: - - main merge_group: types: - checks_requested diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8cd94a..abc594b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,17 +49,17 @@ To run the example app on Web: pnpm example web ``` -Make sure your code passes TypeScript and ESLint. Run the following to verify: +Make sure your code passes TypeScript and Biome. Run the following to verify: ```sh pnpm typecheck pnpm lint ``` -To fix formatting errors, run the following: +To fix lint and formatting errors, run the following: ```sh -pnpm lint --fix +pnpm lint:fix ``` Remember to add tests for your change if possible. Run the unit tests by: @@ -83,9 +83,9 @@ Our pre-commit hooks verify that your commit message matches this format when co ### Linting and tests -[ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/) +[Biome](https://biomejs.dev/), [TypeScript](https://www.typescriptlang.org/) -We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. +We use [TypeScript](https://www.typescriptlang.org/) for type checking, [Biome](https://biomejs.dev/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. Our pre-commit hooks verify that the linter and tests pass when committing. @@ -105,7 +105,7 @@ The `package.json` file contains various scripts for common tasks: - `pnpm install`: setup project by installing dependencies. - `pnpm typecheck`: type-check files with TypeScript. -- `pnpm lint`: lint files with ESLint. +- `pnpm lint`: lint and check formatting with Biome. - `pnpm test`: run unit tests with Jest. - `pnpm example start`: start the Metro server for the example app. - `pnpm example android`: run the example app on Android. diff --git a/babel.config.js b/babel.config.js index 5d51f25..893d243 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: ['module:react-native-builder-bob/babel-preset'], + presets: ["module:react-native-builder-bob/babel-preset"], }; diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..a6bbf79 --- /dev/null +++ b/biome.json @@ -0,0 +1,9 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "vcs": { + "clientKind": "git", + "defaultBranch": "main", + "enabled": true, + "useIgnoreFile": true + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 922dd52..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,39 +0,0 @@ -import { fixupConfigRules } from '@eslint/compat'; -import { FlatCompat } from '@eslint/eslintrc'; -import js from '@eslint/js'; -import prettier from 'eslint-plugin-prettier'; -import { defineConfig } from 'eslint/config'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -export default defineConfig([ - { - extends: fixupConfigRules(compat.extends('@react-native', 'prettier')), - plugins: { prettier }, - rules: { - 'react/react-in-jsx-scope': 'off', - 'prettier/prettier': [ - 'error', - { - quoteProps: 'consistent', - singleQuote: true, - tabWidth: 2, - trailingComma: 'es5', - useTabs: false, - }, - ], - 'no-console': 'error', - }, - }, - { - ignores: ['node_modules/', 'lib/'], - }, -]); diff --git a/example/app.json b/example/app.json index 8e5634c..001ebd6 100644 --- a/example/app.json +++ b/example/app.json @@ -1,30 +1,30 @@ { - "expo": { - "name": "example", - "slug": "example", - "version": "1.0.0", - "orientation": "portrait", - "icon": "./assets/icon.png", - "userInterfaceStyle": "light", - "newArchEnabled": true, - "splash": { - "image": "./assets/splash-icon.png", - "resizeMode": "contain", - "backgroundColor": "#ffffff" - }, - "ios": { - "supportsTablet": true, - "bundleIdentifier": "alertqueue.example" - }, - "android": { - "adaptiveIcon": { - "foregroundImage": "./assets/adaptive-icon.png", - "backgroundColor": "#ffffff" - }, - "package": "alertqueue.example" - }, - "web": { - "favicon": "./assets/favicon.png" - } - } + "expo": { + "name": "React Native Alert Queue", + "slug": "rn.alert.queue.example", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "userInterfaceStyle": "light", + "newArchEnabled": true, + "splash": { + "image": "./assets/splash-icon.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "ios": { + "supportsTablet": true, + "bundleIdentifier": "rn.alert.queue.example" + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#ffffff" + }, + "package": "rn.alert.queue.example" + }, + "web": { + "favicon": "./assets/favicon.png" + } + } } diff --git a/example/babel.config.js b/example/babel.config.js index 7a437af..6901d94 100644 --- a/example/babel.config.js +++ b/example/babel.config.js @@ -1,16 +1,16 @@ -const path = require('path'); -const { getConfig } = require('react-native-builder-bob/babel-config'); -const pkg = require('../package.json'); +const path = require("node:path"); +const { getConfig } = require("react-native-builder-bob/babel-config"); +const pkg = require("../package.json"); -const root = path.resolve(__dirname, '..'); +const root = path.resolve(__dirname, ".."); -module.exports = function (api) { - api.cache(true); +module.exports = (api) => { + api.cache(true); - return getConfig( - { - presets: ['babel-preset-expo'], - }, - { root, pkg } - ); + return getConfig( + { + presets: ["babel-preset-expo"], + }, + { root, pkg }, + ); }; diff --git a/example/index.js b/example/index.js index 018d06f..fc82eb1 100644 --- a/example/index.js +++ b/example/index.js @@ -1,6 +1,6 @@ -import { registerRootComponent } from 'expo'; +import { registerRootComponent } from "expo"; -import App from './src/App'; +import App from "./src/App"; // registerRootComponent calls AppRegistry.registerComponent('main', () => App); // It also ensures that whether you load the app in Expo Go or in a native build, diff --git a/example/metro.config.js b/example/metro.config.js index 403c771..df077e4 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -1,11 +1,11 @@ -const path = require('path'); -const { getDefaultConfig } = require('@expo/metro-config'); -const { mergeConfig } = require('@react-native/metro-config'); +const path = require("node:path"); +const { getDefaultConfig } = require("@expo/metro-config"); +const { mergeConfig } = require("@react-native/metro-config"); const defaultConfig = getDefaultConfig(__dirname); const projectRoot = __dirname; -const monorepoRoot = path.resolve(projectRoot, '..'); +const monorepoRoot = path.resolve(projectRoot, ".."); /** * Metro configuration @@ -14,14 +14,14 @@ const monorepoRoot = path.resolve(projectRoot, '..'); * @type {import('@react-native/metro-config').MetroConfig} */ const config = { - watchFolders: [monorepoRoot], - resolver: { - nodeModulesPaths: [ - path.resolve(projectRoot, 'node_modules'), - path.resolve(monorepoRoot, 'node_modules'), - ], - unstable_enablePackageExports: true, - }, + watchFolders: [monorepoRoot], + resolver: { + nodeModulesPaths: [ + path.resolve(projectRoot, "node_modules"), + path.resolve(monorepoRoot, "node_modules"), + ], + unstable_enablePackageExports: true, + }, }; module.exports = mergeConfig(defaultConfig, config); diff --git a/example/package.json b/example/package.json index f50a666..818317b 100644 --- a/example/package.json +++ b/example/package.json @@ -1,30 +1,30 @@ { - "name": "react-native-alert-queue-example", - "version": "1.0.0", - "main": "index.js", - "scripts": { - "start": "expo start", - "android": "expo start --android", - "ios": "expo start --ios", - "web": "expo start --web" - }, - "dependencies": { - "react-native-alert-queue": "workspace:*", - "@expo/metro-runtime": "~6.1.2", - "expo": "~54.0.32", - "expo-status-bar": "~3.0.9", - "react": "19.1.0", - "react-dom": "19.1.0", - "react-native": "0.81.5", - "react-native-reanimated": "~4.1.1", - "react-native-safe-area-context": "~5.6.0", - "react-native-web": "^0.21.0", - "react-native-worklets": "0.5.1" - }, - "devDependencies": { - "@babel/core": "^7.20.0", - "@react-native/metro-config": "0.81.5", - "react-native-builder-bob": "^0.40.17" - }, - "private": true + "name": "react-native-alert-queue-example", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "start": "expo start", + "android": "expo start --android", + "ios": "expo start --ios", + "web": "expo start --web" + }, + "dependencies": { + "react-native-alert-queue": "workspace:*", + "@expo/metro-runtime": "~6.1.2", + "expo": "~54.0.33", + "expo-status-bar": "~3.0.9", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-native": "0.81.5", + "react-native-reanimated": "~4.1.1", + "react-native-safe-area-context": "~5.6.2", + "react-native-web": "^0.21.2", + "react-native-worklets": "0.5.1" + }, + "devDependencies": { + "@babel/core": "^7.29.0", + "@react-native/metro-config": "0.81.5", + "react-native-builder-bob": "^0.40.18" + }, + "private": true } diff --git a/example/src/App.tsx b/example/src/App.tsx index 2dc4637..692b505 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,49 +1,49 @@ -import { Text, View, StyleSheet, ScrollView } from 'react-native'; +import { ScrollView, StyleSheet, Text, View } from "react-native"; -import { AlertContainer } from 'react-native-alert-queue'; +import { AlertContainer } from "react-native-alert-queue"; -import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; -import { Basics } from './containers/Basics'; -import { Customizations } from './containers/Customizations'; -import { Updating } from './containers/Updating'; -import { KeyboardAvoiding } from './containers/Keyboard'; -import { Confetti } from './containers/Confetti'; +import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; +import { Basics } from "./containers/Basics"; +import { Confetti } from "./containers/Confetti"; +import { Customizations } from "./containers/Customizations"; +import { KeyboardAvoiding } from "./containers/Keyboard"; +import { Updating } from "./containers/Updating"; export default function App() { - return ( - - - - React Native Alert Queue - - - - - - - - - - - - ); + return ( + + + + React Native Alert Queue + + + + + + + + + + + + ); } const styles = StyleSheet.create({ - container: { - flex: 1, - }, - wrapper: { - flex: 1, - }, - scrollViewContent: { - paddingHorizontal: 20, - paddingBottom: 20, - }, - title: { - fontSize: 26, - fontWeight: 'bold', - marginVertical: 20, - textAlign: 'center', - }, + container: { + flex: 1, + }, + wrapper: { + flex: 1, + }, + scrollViewContent: { + paddingHorizontal: 20, + paddingBottom: 20, + }, + title: { + fontSize: 26, + fontWeight: "bold", + marginVertical: 20, + textAlign: "center", + }, }); diff --git a/example/src/components/Button/index.tsx b/example/src/components/Button/index.tsx index 68b8570..995196c 100644 --- a/example/src/components/Button/index.tsx +++ b/example/src/components/Button/index.tsx @@ -1,29 +1,29 @@ -import { Pressable, StyleSheet, Text } from 'react-native'; +import { Pressable, StyleSheet, Text } from "react-native"; export const Button = ({ - onPress, - text, + onPress, + text, }: { - onPress: () => void; - text: string; + onPress: () => void; + text: string; }) => { - return ( - - {text} - - ); + return ( + + {text} + + ); }; const styles = StyleSheet.create({ - button: { - backgroundColor: '#f0f0f0', - borderRadius: 10, - paddingVertical: 10, - paddingHorizontal: 20, - }, - text: { - color: 'black', - fontSize: 16, - textAlign: 'center', - }, + button: { + backgroundColor: "#f0f0f0", + borderRadius: 10, + paddingVertical: 10, + paddingHorizontal: 20, + }, + text: { + color: "black", + fontSize: 16, + textAlign: "center", + }, }); diff --git a/example/src/components/Section/index.tsx b/example/src/components/Section/index.tsx index bf05388..7deb004 100644 --- a/example/src/components/Section/index.tsx +++ b/example/src/components/Section/index.tsx @@ -1,26 +1,26 @@ -import type { FC, PropsWithChildren } from 'react'; -import { StyleSheet, Text, View } from 'react-native'; +import type { FC, PropsWithChildren } from "react"; +import { StyleSheet, Text, View } from "react-native"; type Props = PropsWithChildren<{ - title: string; + title: string; }>; export const Section: FC = ({ children, title }) => { - return ( - - {title} - {children} - - ); + return ( + + {title} + {children} + + ); }; const styles = StyleSheet.create({ - title: { - fontSize: 20, - fontWeight: 'bold', - marginVertical: 20, - }, - container: { - gap: 10, - }, + title: { + fontSize: 20, + fontWeight: "bold", + marginVertical: 20, + }, + container: { + gap: 10, + }, }); diff --git a/example/src/components/icons/Danger.tsx b/example/src/components/icons/Danger.tsx index 7444a19..664b414 100644 --- a/example/src/components/icons/Danger.tsx +++ b/example/src/components/icons/Danger.tsx @@ -1,15 +1,15 @@ -import Svg, { type SvgProps, Path } from 'react-native-svg'; +import Svg, { Path, type SvgProps } from "react-native-svg"; export const DangerIcon = (props: SvgProps) => ( - - - - + + + + ); diff --git a/example/src/containers/Basics.tsx b/example/src/containers/Basics.tsx index bb38e94..3bf998f 100644 --- a/example/src/containers/Basics.tsx +++ b/example/src/containers/Basics.tsx @@ -1,115 +1,115 @@ -import { alert } from 'react-native-alert-queue'; -import { Button } from '../components/Button'; -import { Section } from '../components/Section'; +import { alert } from "react-native-alert-queue"; +import { Button } from "../components/Button"; +import { Section } from "../components/Section"; export const Basics = () => { - return ( -
-
- ); + if (result) { + alert.success({ + message: "You pressed yes", + }); + } else { + alert.error(new Error("You pressed no")); + } + }} + text="Confirm" + /> +