diff --git a/.changeset/old-crabs-applaud.md b/.changeset/old-crabs-applaud.md
new file mode 100644
index 0000000..94e3840
--- /dev/null
+++ b/.changeset/old-crabs-applaud.md
@@ -0,0 +1,6 @@
+---
+'classic-react-components': minor
+---
+
+- [docs]: update examples and add more descrition of the components
+- [refactor]: use normal for loop to iterate over array in Switch component instead of Children.map function
diff --git a/README.md b/README.md
index 231ea4d..aace6d9 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,12 @@
# 🚀 classic-react-components
-- A Simple React Library of `Utility Components`.
-- Write jsx in `maintainable` and `readable` way, and fun too.
+## Intro
+
+- Simplifying the way you write conditional and loops in JSX.
+
+- Adding `If-Else` like syntax for conditional jsx.
+- Adding `For` component to map over the data within jsx.
+- Adding `Switch-Case` to your jsx.
@@ -20,10 +25,11 @@
## Features
-- Comes with treeshaking
-- Typescript support
+- Built in Typescript
+- Supports Treeshaking
- Small bundle size
- Minimal and Easy to use
+- Open Source
## Installation
@@ -38,6 +44,11 @@ For pnpm users
```bash
$ pnpm install classic-react-components
```
+For bun users
+
+```bash
+$ bun install classic-react-components
+```
For yarn users
@@ -53,30 +64,27 @@ $ yarn add classic-react-components
- [For](#for)
- [Switch](#switch)
-### If
+## If
| Prop | Type | Required | Default Value | Description |
| --------- | :-------: | :------: | :-----------: | -------------------------------------------------------------------------------------------- |
-| condition | any | ❌ | false | Based on evaluation of the condition flag the component will return null or children |
-| children | ReactNode | ❌ | null | To render the children |
-| suspense | boolean | ❌ | false | Needed to show fallback until its children have finished loading |
-| fallback | ReactNode | ❌ | null | Fallback needed to show until the component is loaded fully. Needed for suspensed components |
+| condition | any | ❌ | false | Based on the evaluation of `condition` prop, either children or null will be rendered |
+| children | ReactNode | ❌ | null | Renders the passed children |
+| suspense | boolean | ❌ | false | Used for rendering lazily loaded components |
+| fallback | ReactNode | ❌ | null | Used for showing the fallback until the suspensed children have been loaded. |
### Working
-- Based on the condition the children are rendered.
-- If the condition is true then the childeren will render otherwise it will return null.
-
-- For one children
-
- - If condition is true then children will be rendered.
- - If condition is false then null gets returned.
+- Based on evaulation of the condition flag the children are rendered.
+- If the condition is true then it will render the children otherwise null.
+- Working with one child
+ - If condition is true then child will be rendered.
+ - If condition is false then null gets rendered.
+- Working with children(more than one child)
+ - If condition is true then the first child will be rendered.
+ - Otherwise the all of the children will be rendered excluding the first child.
-- For multiple children
- - If conndition is true then the first children will rendered.
- - Otherwise the all of the children will be rendered excluding the first children.
-
-### Example
+### Examples
```tsx
import { If } from 'classic-react-components'
@@ -106,7 +114,7 @@ export default function YourComponent() {
}
```
-### Usage with Suspense
+#### Usage with Suspense
```tsx
import { If, Then, Else } from 'classic-react-components'
@@ -133,7 +141,35 @@ export default function YourComponent() {
}
```
-### Then
+
+### Replacing ternary and short-circuit
+
+```tsx
+ const show = true // some state, which will be toggled to true|false
+
+ // ❌ ternary operator
+ { show ?
{(item, i) => (
@@ -40,6 +76,7 @@ describe('For.tsx', () => {
)
expect(screen.queryByTestId('react')).toBeInTheDocument()
expect(screen.queryByTestId('nextjs')).toBeInTheDocument()
+ expect(screen.queryByTestId('vuejs')).toBeInTheDocument()
expect(screen.queryByTestId('typescript')).toBeInTheDocument()
})
})
diff --git a/src/lib/components/For/For.tsx b/src/lib/components/For/For.tsx
index 0824f7c..1febc31 100644
--- a/src/lib/components/For/For.tsx
+++ b/src/lib/components/For/For.tsx
@@ -26,7 +26,7 @@ import React from 'react'
)
}
*/
-export default function For({
+export default function For({
data,
children = null,
}: {
@@ -35,14 +35,17 @@ export default function For({
}) {
if (!data || children === null) return <>>
+ if (!Array.isArray(data)) {
+ throw new Error(`Type of data prop must be an array, but got ${typeof data} type.`)
+ }
+
if (typeof children != 'function') {
- throw new Error('Children type must be a function.')
+ throw new Error(`Type of children prop must be a function but got ${typeof children} type.`)
}
- let arr: JSX.Element[] = []
- for (let i = 0; i < Number(data.length); i++) {
- const element = children(data[i], i)
- arr.push(element)
+ const arr: JSX.Element[] = new Array(data.length)
+ for (let i = 0; i < data.length; i++) {
+ arr.push(children(data[i], i))
}
return <>{arr}>
diff --git a/src/lib/components/Switch/Switch.test.tsx b/src/lib/components/Switch/Switch.test.tsx
index 1bf3c54..4d0d593 100644
--- a/src/lib/components/Switch/Switch.test.tsx
+++ b/src/lib/components/Switch/Switch.test.tsx
@@ -148,12 +148,9 @@ describe('Switch', () => {
expect(screen.queryByTestId('default')).toBeInTheDocument()
})
- it('should console warning for multiple Default case', () => {
+ it('should only render first number of Default case, if there are multiple Default cases are passed', () => {
let item = 'awesome' as 'coding' | 'sleep' | 'awesome'
- const consoleFn = vi.fn(() => {})
- const consoleLogMock = vi.spyOn(console, 'warn').mockImplementation(consoleFn)
-
render(
{({ Case, Default }) => {
@@ -180,12 +177,6 @@ describe('Switch', () => {
expect(screen.queryByTestId('sleep')).not.toBeInTheDocument()
expect(screen.queryByTestId('default')).toBeInTheDocument()
expect(screen.queryByTestId('default-2')).not.toBeInTheDocument()
-
- expect(consoleFn).toBeCalledTimes(1)
- expect(consoleFn).toBeCalledWith('You can not use multiple Default-Case inside Switch')
-
- expect(consoleLogMock).toBeCalledTimes(1)
- expect(consoleLogMock).toBeCalledWith('You can not use multiple Default-Case inside Switch')
})
it('should console warning if used HtmlElement or any Component inside Switch', () => {
diff --git a/src/lib/components/Switch/Switch.tsx b/src/lib/components/Switch/Switch.tsx
index 16d4ffb..dcef0c8 100644
--- a/src/lib/components/Switch/Switch.tsx
+++ b/src/lib/components/Switch/Switch.tsx
@@ -1,5 +1,7 @@
+'use client'
+
import type { ReactNode } from 'react'
-import React, { Children, useRef } from 'react'
+import React, { useRef } from 'react'
type SwitchProps = {
children: ({
@@ -65,10 +67,7 @@ export default function Switch({ children, item }: SwitchProps) {
const { props } = children({ Case: functionsRefObj.current.Case, Default: functionsRefObj.current.Default })
let new_child: JSX.Element | null = null
- const defaultCase = {
- present: false,
- index: 0,
- }
+ let defaultCase: JSX.Element | null = null
// handling case for when only one children is passed
if (
@@ -89,31 +88,31 @@ export default function Switch({ children, item }: SwitchProps) {
}
if ('children' in props && Array.isArray(props.children) && props.children.length > 0) {
- Children.forEach(props.children, (child: JSX.Element, i) => {
+ for (let i = 0; i < props.children.length; i++) {
+ const child: JSX.Element = props.children[i]
+
if (!child || (child?.type?.name != 'Default' && child?.type?.name != 'Case')) {
console.warn('You must use Default or Case component inside Switch')
+ continue
}
// check if it is case
if (child?.type?.name == 'Case') {
// if passed - prop is equal to the component's prop, then assign it to state
if (child?.props?.value === item) {
new_child = child
- return
+ break
}
}
// check if case is present or not
if (child?.type?.name == 'Default') {
- if (defaultCase.present) {
- console.warn('You can not use multiple Default-Case inside Switch')
- return
+ if (!defaultCase) {
+ defaultCase = child
}
- defaultCase.present = true
- defaultCase.index = i
}
- })
+ }
// if no-other cases match and case is present, then assign the to the state
- if (!new_child && defaultCase.present) {
- new_child = props?.children[defaultCase.index]
+ if (!new_child && defaultCase) {
+ new_child = defaultCase
}
}
diff --git a/vitest.config.ts b/vitest.config.ts
index 2f50039..8dc8978 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -13,7 +13,7 @@ export default defineConfig({
clean: true,
all: false,
},
- include: ['./src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+ include: ['./src/**/*.{test,spec}.{ts,tsx}'],
exclude: [
'**/node_modules/**',
'**/dist/**',