Skip to content

Commit

Permalink
feat: add Switch component.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Aug 17, 2023
1 parent ed9c7ad commit 2d4ad56
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 13 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ jobs:
- run: npm run build
- run: npm run doc
- run: npm run coverage
- run: cp -rp ./core/coverage www/build
- run: cp -rp ./coverage www/build

- name: Create Tag
id: create_tag
uses: jaywcjlove/create-tag-action@main
with:
package-path: ./core/package.json


- name: Generate Contributors Images
uses: jaywcjlove/github-action-contributors@main
with:
Expand All @@ -37,7 +36,6 @@ jobs:
- name: Create Coverage Badges
uses: jaywcjlove/coverage-badges-cli@main
with:
source: core/coverage/coverage-summary.json
output: www/build/badges.svg

- name: Generate Changelog
Expand Down
54 changes: 52 additions & 2 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,25 @@ import Only from '@uiw/react-only-when'
</Only>
```

## \<If>
```jsx
import { If } from '@uiw/react-only-when/if'

<If condition={props.error}>
<h1>{props.error}</h1>
</If>
```

```jsx
import { Switch, Case, Default } from '@uiw/react-only-when/switch'

<Switch>
<Case condition={age < 6}>preschool</Case>
<Case condition={age >= 6}>primary school</Case>
<Default>you graduated</Default>
</Switch>
```

## \<If />

React component that renders the children if the `condition` prop is `true`.

Expand Down Expand Up @@ -56,7 +74,7 @@ Or you could just use plain JavaScript:
</div>
```

## Example
Only Example

```jsx mdx:preview&background=#fff&codePen=true
import React, { useState } from 'react';
Expand All @@ -75,6 +93,38 @@ export default function App() {
}
```

## \<Switch />

```jsx
import { Switch, Case, Default } from '@uiw/react-only-when/switch'

<Switch>
<Case condition={age < 6}>preschool</Case>
<Case condition={age >= 6}>primary school</Case>
<Default>you graduated</Default>
</Switch>
```

```jsx mdx:preview&background=#fff&codePen=true
import React, { useState, Fragment } from 'react';
import { Switch, Case, Default } from '@uiw/react-only-when/switch'

export default function App() {
const [age, setAge] = useState(19)
return (
<Fragment>
<input type="range" onChange={(evn) => setAge(Number(evn.target.value))} /> {age}
<Switch>
<Case condition={age < 6}>Preschool</Case>
<Case condition={age >= 6 && age < 18}>Primary school</Case>
<Case condition={age >= 18}>Went to college</Case>
<Default>you graduated</Default>
</Switch>
</Fragment>
);
}
```

## props

| prop name | type | default | isRequired | description |
Expand Down
6 changes: 5 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
"require": "./cjs/If.js",
"types": "./esm/If.d.ts"
},
"./package.json": "./package.json"
"./switch": {
"import": "./esm/switch.js",
"require": "./cjs/switch.js",
"types": "./esm/switch.d.ts"
}
},
"author": "Kenny Wang<wowohoo@qq.com>",
"license": "MIT",
Expand Down
26 changes: 26 additions & 0 deletions core/src/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ReactElement, Children } from 'react';
import { FC, PropsWithChildren } from 'react';

export const Switch: FC<PropsWithChildren<{}>> = ({ children }) => {
let matchChild: ReactElement | null = null;
let defaultCase: ReactElement | null = null;
Children.forEach(Children.toArray(children) as ReactElement<PropsWithChildren<CaseProps>>[], (child) => {
if (!matchChild && child.type === Case) {
const { condition } = child.props;
const conditionIsTrue = Boolean(condition);
if (conditionIsTrue) {
matchChild = child;
}
} else if (!defaultCase && child.type === Default) {
defaultCase = child;
}
});
return matchChild ?? defaultCase ?? null;
};

export interface CaseProps {
readonly condition?: boolean;
}

export const Case: FC<PropsWithChildren<CaseProps>> = ({ children }) => children;
export const Default: FC<PropsWithChildren> = ({ children }) => children;
9 changes: 9 additions & 0 deletions core/switch.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare module '@uiw/react-only-when/switch' {
import { FC, PropsWithChildren } from 'react';
export const Switch: FC<PropsWithChildren<{}>>;
export interface CaseProps {
readonly condition?: boolean;
}
export const Case: FC<PropsWithChildren<CaseProps>>;
export const Default: FC<PropsWithChildren>;
}
20 changes: 16 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
{
"private": true,
"scripts": {
"watch": "lerna exec --scope @uiw/react-only-when -- tsbb watch \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
"build": "lerna exec --scope @uiw/react-only-when -- tsbb build \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
"start": "lerna exec --scope website -- npm run start",
"doc": "lerna exec --scope website -- npm run build",
"test": "lerna exec --scope @uiw/react-only-when -- tsbb test --env=jsdom",
"coverage": "lerna exec --scope @uiw/react-only-when -- tsbb test --env=jsdom --coverage --bail",
"⬇️⬇️⬇️⬇️⬇️ package ⬇️⬇️⬇️⬇️⬇️": "▼▼▼▼▼ package ▼▼▼▼▼",
"watch": "lerna exec --scope @uiw/react-only-when -- tsbb watch \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
"build": "lerna exec --scope @uiw/react-only-when -- tsbb build \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
"⬆️⬆️⬆️⬆️⬆️ package ⬆️⬆️⬆️⬆️⬆️": "▲▲▲▲▲ package ▲▲▲▲▲",
"type-check": "tsc --noEmit",
"test": "tsbb test",
"coverage": "tsbb test --coverage --bail",
"prepare": "husky install",
"publish": "lerna publish from-package --yes --no-verify-access",
"version": "lerna version --exact --force-publish --no-push --no-git-tag-version",
Expand All @@ -22,6 +25,15 @@
"engines": {
"node": ">=16.0.0"
},
"jest": {
"collectCoverageFrom": [
"<rootDir>/core/src/*.{tsx,ts}"
],
"coverageReporters": [
"lcov",
"json-summary"
]
},
"overrides": {
"typescript": "^5.1.3"
},
Expand Down
2 changes: 1 addition & 1 deletion core/src/__test__/If.test.tsx → test/If.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable jest/no-conditional-expect */
import TestRenderer from 'react-test-renderer';
import { If } from '../';
import { If } from '../core/src/If';

describe('<If />', () => {
it('Not rendering children', () => {
Expand Down
2 changes: 1 addition & 1 deletion core/src/__test__/index.test.tsx → test/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable jest/no-conditional-expect */
import TestRenderer from 'react-test-renderer';
import Only from '../';
import Only from '../core/src';

describe('<Only />', () => {
it('Not rendering children', () => {
Expand Down
57 changes: 57 additions & 0 deletions test/switch.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* eslint-disable jest/no-conditional-expect */
import renderer from 'react-test-renderer';
import { Switch, Case, Default } from '../core/src/switch';


it('<Switch />', () => {
const component = renderer.create(
<Switch></Switch>
);
const only = component.toJSON();
expect(only).toBeNull();
});

it('<Default />', () => {
const component = renderer.create(
<Switch>
<Default>you graduated</Default>
</Switch>
);
const only = component.toJSON();
expect(only).toEqual('you graduated');
});

it('<Case />', () => {
const component = renderer.create(
<Switch>
<Case condition={true}>preschool</Case>
<Default>you graduated</Default>
</Switch>
);
const only = component.toJSON();
expect(only).toEqual('preschool');
});

it('<Case /> condition=true', () => {
const component = renderer.create(
<Switch>
<Case condition={true}>preschool</Case>
<Case condition={true}>primary school</Case>
<Default>you graduated</Default>
</Switch>
);
const only = component.toJSON();
expect(only).toEqual('preschool');
});

it('<Case /> condition=false', () => {
const component = renderer.create(
<Switch>
<Case condition={false}>preschool</Case>
<Case condition={false}>primary school</Case>
<Default>you graduated</Default>
</Switch>
);
const only = component.toJSON();
expect(only).toEqual('you graduated');
});
2 changes: 1 addition & 1 deletion www/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createRoot } from 'react-dom/client';
import MarkdownPreviewExample from '@uiw/react-markdown-preview-example';
import data from '../../core/README.md';
import pkg from '@uiw/react-only-when/package.json';
import pkg from '../../core/package.json';
import OnlyWhenExample from './Example';

const Github = MarkdownPreviewExample.Github;
Expand Down

0 comments on commit 2d4ad56

Please sign in to comment.