An open API service indexing awesome lists of open source software.

https://github.com/rcrdk/utils

Day by day helpers including code snippets, scripts and anything else that could be useful 😅
https://github.com/rcrdk/utils

functions helpers lint nextjs packages react shell tailwindcss typescript utils vscode

Last synced: 3 months ago
JSON representation

Day by day helpers including code snippets, scripts and anything else that could be useful 😅

Awesome Lists containing this project

README

          

# 🛟 Utils
I created this repository to put together all utils and helpers that I need from time to time:

---
### 1️⃣ Functions
---

GroupBy

---
[`group-by.ts`](https://github.com/rcrdk/utils/blob/main/functions/group-by.ts)

Groups an array of objects by a specific key. From time to time I need to use the newly or not so `Object.groupBy(items, callbackFn)`, and the problem was that this method is only supported in [newly versions of Node (21.x)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy#browser_compatibility). I faced this issue after deploying an app at Vercel where the Node version at the time was the 20.x as the newest available or when I was coding a React Native App.

**Usage:**
```typescript
const data = [
{ id: 1, category: 'A' },
{ id: 2, category: 'B' },
{ id: 3, category: 'A' },
];

groupBy(data, 'category')

// Result:
// {
// A: [
// { id: 1, category: 'A' },
// { id: 3, category: 'A' },
// ],
// B: [
// { id: 2, category: 'B' },
// ],
// }
```

Tailwind ClassName Merge

---
[`tw-cn-merge.ts`](https://github.com/rcrdk/utils/blob/main/functions/tw-cn-merge.ts)

Combines class names into a single string, handling Tailwind CSS class conflicts.

**Dependencies:**
```JSX
npm i clsx tailwind-merge
```

**Usage:**
```JSX


```

Price Formatted to PT-BR

---
[`price-formatted-ptbr.ts`](https://github.com/rcrdk/price-formatted-ptbr.ts/copy-to-clipboard.ts)

Formats a numeric amount as a currency string in Brazilian Real (BRL).

**Usage:**
```js
priceFormatted(10000); // '100,00'
priceFormatted(123456, 100); // '1.234,56'
priceFormatted(5000, 1); // '5.000,00'
```

Generate Slug

---
[`generate-slug.ts`](https://github.com/rcrdk/utils/blob/main/functions/generate-slug.ts)

Generates a URL-friendly slug from a given string.

**Usage:**
```js
generateSlug('Hello World!'); // 'hello-world'
generateSlug('Café au lait!'); // 'cafe-au-lait'
generateSlug(' Multiple Spaces '); // 'multiple-spaces'
```

Is Query Included?

---
[`is-query-included.ts`](https://github.com/rcrdk/utils/blob/main/is-query-included.ts.ts)

Checks if the query string is included in the stringToCompare after normalization.

**Example:**
```js
const query1 = 'café';
const stringToCompare1 = 'O café está ótimo';

const result1 = isQueryIncluded(query1, stringToCompare1);
console.log(result1); // true
```

**Example:**
```js
const query2 = 'hello';
const stringToCompare2 = ' HeLLo World!';

const result2 = isQueryIncluded(query2, stringToCompare2);
console.log(result2); // true
```

**Example:**
```js
const query3 = 'ça';
const stringToCompare3 = 'O café está aqui';

const result3 = isQueryIncluded(query3, stringToCompare3);
console.log(result3); // true
```

**Example:**
```js
const query4 = 'world';
const stringToCompare4 = 'Goodbye, everyone!';

const result4 = isQueryIncluded(query4, stringToCompare4);
console.log(result4); // false
```

---
### 2️⃣ React
---

Component with 'as' prop

---
[`component-as-prop.tsx`](https://github.com/rcrdk/utils/blob/main/react/component-as-prop.tsx)

Create custom components with `as` prop with TypeScript.

useFormState hook

---
[`use-form-state.ts`](https://github.com/rcrdk/utils/blob/main/react/use-form-state/use-form-state.ts)

A custom React hook for managing form state, inspired by React DOM’s useFormState.

- Handles form submissions with async actions
- Manages success, error, and loading states
- Supports automatic form resets
- Supports clearing form state message after a delay, useful for toasts.
- Allows custom success callbacks

**foo-form.tsx**
```js
'use client'

export function FooForm() {
const [{ success, error, message }, handleSubmit, isSubmitting] = useFormState(
createPageAction,
{
onSuccess() {},
resetFormOnSuccess: false,
resetStateMessage: true,
},
)

useEffect(() => {
if (!success && message) {
toast.error(message, { id: 'foo-action' })
}
if (success && message) {
toast.success(message, { id: 'foo-action' })
}
}, [success, message, isSubmitting])

return (



)
}
```

**foo-action.ts:**
```js
'use server'

import { z } from 'zod'

const createFooSchema = z.object({
name: z.string().min(1, 'Enter a name.'),
})

export async function createFooAction(data: FormData) {
const result = createFooSchema.safeParse(Object.fromEntries(data))

if (!result.success) {
const errors = result.error.flatten().fieldErrors

return {
success: false,
message: null,
errors,
}
}

const { name } = result.data

try {
// action
} catch (error) {
return {
success: false,
message: 'An unexpected error occured.',
errors: null,
}
}

return {
success: true,
message: 'Action successfully executed.',
errors: null,
}
}
```

Validated actions

---
[`validated-actions.tsx`](https://github.com/rcrdk/utils/blob/main/react/validated-actionstsx)

Validate actions with user session.

---
### 3️⃣ Shell
---

Convert an entire folder of images to WEBP format

---
[`convert-image-directory-to-webp.sh`](https://github.com/rcrdk/utils/blob/main/shell/convert-image-directory-to-webp.sh)

I was having trouble and wasting my time by converting file by file in command line. This script could help you too:

**Requirements:**
- This script works on Unix based systems such as MacOS and Linux.
- You'll need `cwebp` command available.

**Steps:**
1. Download `webp-convert-directory.sh`;
2. Open terminal;
3. Access folder containing images;
4. Run `sh [file_path]`. You can drag and drop file to terminal to get full path:
- Example: `sh /Users/ricardo/Desktop/webp-convert-directory.sh`
5. And voilà! All files converted!

---
### 4️⃣ TypeScript
---

Optional properties on types utility

---
[`optional.ts`](https://github.com/rcrdk/utils/blob/main/typescript/optional.ts)

Make some properties optional on type

```typescript
type Post {
id: string;
name: string;
category: string;
}

Optional
```

---
### 5️⃣ Linting
---

React Native + Expo

---
[`react-native-expo/*`](https://github.com/rcrdk/utils/tree/main/linting/react-native-expo)

Read the [Expo Docs](https://docs.expo.dev/guides/using-eslint/) on using ESlint and Prettier.

**Extra Dependencies:**
```shell
npm i -D eslint-plugin-simple-import-sort
```

React 19 + Next.js 15 + ESlint 9

---
[`react19-nextjs15-eslint9`](https://github.com/rcrdk/utils/tree/main/linting/react19-nextjs15-eslint9)

Here is a basic setup with the latest versions of React, Next.js and ESlint.

Prettier Sort imports and exports

---
That's a great plugin for who always keep reordering and formatting imports and exports. Check it out the [plugin repository](https://github.com/IanVS/prettier-plugin-sort-imports).

**Depependencies:**
```shell
pnpm add -D @ianvs/prettier-plugin-sort-imports
```
**Setup:**
```json
{
"plugins": ["@ianvs/prettier-plugin-sort-imports", "prettier-plugin-sort-json"],
"importOrder": [
"^(react/(.*)$)|^(react$)",
"^(next/(.*)$)|^(next$)",
"",
"",
"^@/(.*)$",
"^[./]"
],
"importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"]
}
```

> [!NOTE]
> The below plugin was the first wan that I've been using, but recently I discovered a better one.

---
That's a great plugin for who always keep reordering and formatting imports and exports. Check it out the [plugin repository](https://github.com/lydell/eslint-plugin-simple-import-sort).

**Depependencies:**
```shell
npm i -D eslint-plugin-simple-import-sort
```

**Setup:**
```json
{
"plugins": ["simple-import-sort"],
"rules": {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
}
}
```

Tailwind Prettier Plugin

---
Checkout the [Plugin Docs](https://github.com/tailwindlabs/prettier-plugin-tailwindcss).

**Dependencies:**
```shell
npm i -D prettier-plugin-tailwindcss
```

**Setup:**
```json
// .prettierrc
{
"plugins": ["prettier-plugin-tailwindcss"]
}
```

Rocketseat Eslint Initial Configs

---
**Dependencies:**
```shell
npm i -D @rocketseat/eslint-config
```

**Usage:**
```json
// [environment]: node, react, next
{
"extends": ["@rocketseat/eslint-config/[environment]"]
}
```

Add type imports

---
**Configuration:**
```json
// .eslintrc.js
{
"rules": {
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports"
}
]
}
}
```

Knip

---
Copy [`knip.config.ts`](https://github.com/rcrdk/utils/tree/main/linting/knip/knip.config.ts) to the base of the project, customize it.

**Dependencies:**
```shell
npm i -D knip
```

**Usage:**
```shell
npx run knip # And it's time for a cleanup!
```

Commit linting

---
Copy [`commit-lint`](https://github.com/rcrdk/utils/tree/main/linting/commit-lint) to the base of the project, install dependencies and start commiting.

---
### 6️⃣ VScode
---

Settings

---
`.vscode/settings.json`: settings for specific projects.

**Force to use import aliases:**
```json
{
"typescript.preferences.importModuleSpecifier": "non-relative"
}
```

**Setup Tailwind IntelliSense for custom props:**
```json
{
"tailwindCSS.classAttributes": ["class", "className", "classNameCenter", ".*Styles"]
}
```

EditorConfig IDE Plugin

---
EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. Check it out the [tool page](https://editorconfig.org). Just need to install a plugin on code editor and set a `.editorconfig` file:

**Configuration file example:**
```bash
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true

[*]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

[*.md]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
```

---
### 7️⃣ Packages
---

- [**React Haiku**](https://www.reacthaiku.dev/): a collection of react hooks and utilities
- [**Day.js**](https://day.js.org/): Day.js is a minimalist JavaScript library that parses, validates, manipulates, and displays dates and times
- [**Sonner**](https://sonner.emilkowal.ski/): An opinionated toast component for React. Emil and I share the same last name 🤠.
- [**Swiper**](https://swiperjs.com/): This is the best slider for websites, web apps, and mobile apps.
- [**T3 Env**](https://env.t3.gg/): Framework agnostic validation for type-safe environment variables.
- [**Radix Primitives**](https://www.radix-ui.com/primitives): Unstyled, accessible, open source React primitives for high-quality web apps and design systems.
- [**Sharp**](https://sharp.pixelplumbing.com/): High performance Node.js image processing.
- [**Auth.js**](https://authjs.dev/): Authentication for the Web.
- [**TailwindCSS**](https://tailwindcss.com/): A utility-first CSS framework.
- [**Tablr Icons**](https://tabler.io/icons): A package of thousands icons.
- [**Tanstack React Query**](https://tanstack.com/query/latest): This is a JavaScript library that helps developers fetch, cache, and update data in React applications
- [**Fancyapps / Fancybox**](https://fancyapps.com/fancybox/): Fancybox is the ultimate JavaScript lightbox alternative that sets the standard for premium user experience in multimedia display. Supports images, videos, maps, inline content, iframes and any other HTML content.
- [**KY**](https://github.com/sindresorhus/ky): Tiny & elegant JavaScript HTTP client based on the Fetch API. Supports experimental next.js cache.
- [**useDraggableHook**](https://github.com/rfmiotto/react-use-draggable-scroll): scroll content using mouse events.