Skip to content

Commit 2d4ad56

Browse files
committed
feat: add Switch component.
1 parent ed9c7ad commit 2d4ad56

File tree

10 files changed

+169
-13
lines changed

10 files changed

+169
-13
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@ jobs:
1818
- run: npm run build
1919
- run: npm run doc
2020
- run: npm run coverage
21-
- run: cp -rp ./core/coverage www/build
21+
- run: cp -rp ./coverage www/build
2222

2323
- name: Create Tag
2424
id: create_tag
2525
uses: jaywcjlove/create-tag-action@main
2626
with:
2727
package-path: ./core/package.json
2828

29-
3029
- name: Generate Contributors Images
3130
uses: jaywcjlove/github-action-contributors@main
3231
with:
@@ -37,7 +36,6 @@ jobs:
3736
- name: Create Coverage Badges
3837
uses: jaywcjlove/coverage-badges-cli@main
3938
with:
40-
source: core/coverage/coverage-summary.json
4139
output: www/build/badges.svg
4240

4341
- name: Generate Changelog

core/README.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,25 @@ import Only from '@uiw/react-only-when'
2424
</Only>
2525
```
2626

27-
## \<If>
27+
```jsx
28+
import { If } from '@uiw/react-only-when/if'
29+
30+
<If condition={props.error}>
31+
<h1>{props.error}</h1>
32+
</If>
33+
```
34+
35+
```jsx
36+
import { Switch, Case, Default } from '@uiw/react-only-when/switch'
37+
38+
<Switch>
39+
<Case condition={age < 6}>preschool</Case>
40+
<Case condition={age >= 6}>primary school</Case>
41+
<Default>you graduated</Default>
42+
</Switch>
43+
```
44+
45+
## \<If />
2846

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

@@ -56,7 +74,7 @@ Or you could just use plain JavaScript:
5674
</div>
5775
```
5876

59-
## Example
77+
Only Example
6078

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

96+
## \<Switch />
97+
98+
```jsx
99+
import { Switch, Case, Default } from '@uiw/react-only-when/switch'
100+
101+
<Switch>
102+
<Case condition={age < 6}>preschool</Case>
103+
<Case condition={age >= 6}>primary school</Case>
104+
<Default>you graduated</Default>
105+
</Switch>
106+
```
107+
108+
```jsx mdx:preview&background=#fff&codePen=true
109+
import React, { useState, Fragment } from 'react';
110+
import { Switch, Case, Default } from '@uiw/react-only-when/switch'
111+
112+
export default function App() {
113+
const [age, setAge] = useState(19)
114+
return (
115+
<Fragment>
116+
<input type="range" onChange={(evn) => setAge(Number(evn.target.value))} /> {age}
117+
<Switch>
118+
<Case condition={age < 6}>Preschool</Case>
119+
<Case condition={age >= 6 && age < 18}>Primary school</Case>
120+
<Case condition={age >= 18}>Went to college</Case>
121+
<Default>you graduated</Default>
122+
</Switch>
123+
</Fragment>
124+
);
125+
}
126+
```
127+
78128
## props
79129

80130
| prop name | type | default | isRequired | description |

core/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
"require": "./cjs/If.js",
2121
"types": "./esm/If.d.ts"
2222
},
23-
"./package.json": "./package.json"
23+
"./switch": {
24+
"import": "./esm/switch.js",
25+
"require": "./cjs/switch.js",
26+
"types": "./esm/switch.d.ts"
27+
}
2428
},
2529
"author": "Kenny Wang<[email protected]>",
2630
"license": "MIT",

core/src/switch.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { ReactElement, Children } from 'react';
2+
import { FC, PropsWithChildren } from 'react';
3+
4+
export const Switch: FC<PropsWithChildren<{}>> = ({ children }) => {
5+
let matchChild: ReactElement | null = null;
6+
let defaultCase: ReactElement | null = null;
7+
Children.forEach(Children.toArray(children) as ReactElement<PropsWithChildren<CaseProps>>[], (child) => {
8+
if (!matchChild && child.type === Case) {
9+
const { condition } = child.props;
10+
const conditionIsTrue = Boolean(condition);
11+
if (conditionIsTrue) {
12+
matchChild = child;
13+
}
14+
} else if (!defaultCase && child.type === Default) {
15+
defaultCase = child;
16+
}
17+
});
18+
return matchChild ?? defaultCase ?? null;
19+
};
20+
21+
export interface CaseProps {
22+
readonly condition?: boolean;
23+
}
24+
25+
export const Case: FC<PropsWithChildren<CaseProps>> = ({ children }) => children;
26+
export const Default: FC<PropsWithChildren> = ({ children }) => children;

core/switch.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare module '@uiw/react-only-when/switch' {
2+
import { FC, PropsWithChildren } from 'react';
3+
export const Switch: FC<PropsWithChildren<{}>>;
4+
export interface CaseProps {
5+
readonly condition?: boolean;
6+
}
7+
export const Case: FC<PropsWithChildren<CaseProps>>;
8+
export const Default: FC<PropsWithChildren>;
9+
}

package.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
{
22
"private": true,
33
"scripts": {
4-
"watch": "lerna exec --scope @uiw/react-only-when -- tsbb watch \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
5-
"build": "lerna exec --scope @uiw/react-only-when -- tsbb build \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
64
"start": "lerna exec --scope website -- npm run start",
75
"doc": "lerna exec --scope website -- npm run build",
8-
"test": "lerna exec --scope @uiw/react-only-when -- tsbb test --env=jsdom",
9-
"coverage": "lerna exec --scope @uiw/react-only-when -- tsbb test --env=jsdom --coverage --bail",
6+
"⬇️⬇️⬇️⬇️⬇️ package ⬇️⬇️⬇️⬇️⬇️": "▼▼▼▼▼ package ▼▼▼▼▼",
7+
"watch": "lerna exec --scope @uiw/react-only-when -- tsbb watch \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
8+
"build": "lerna exec --scope @uiw/react-only-when -- tsbb build \"src/*.{ts,tsx}\" --use-babel --cjs cjs",
9+
"⬆️⬆️⬆️⬆️⬆️ package ⬆️⬆️⬆️⬆️⬆️": "▲▲▲▲▲ package ▲▲▲▲▲",
10+
"type-check": "tsc --noEmit",
11+
"test": "tsbb test",
12+
"coverage": "tsbb test --coverage --bail",
1013
"prepare": "husky install",
1114
"publish": "lerna publish from-package --yes --no-verify-access",
1215
"version": "lerna version --exact --force-publish --no-push --no-git-tag-version",
@@ -22,6 +25,15 @@
2225
"engines": {
2326
"node": ">=16.0.0"
2427
},
28+
"jest": {
29+
"collectCoverageFrom": [
30+
"<rootDir>/core/src/*.{tsx,ts}"
31+
],
32+
"coverageReporters": [
33+
"lcov",
34+
"json-summary"
35+
]
36+
},
2537
"overrides": {
2638
"typescript": "^5.1.3"
2739
},

core/src/__test__/If.test.tsx renamed to test/If.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable jest/no-conditional-expect */
22
import TestRenderer from 'react-test-renderer';
3-
import { If } from '../';
3+
import { If } from '../core/src/If';
44

55
describe('<If />', () => {
66
it('Not rendering children', () => {

core/src/__test__/index.test.tsx renamed to test/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable jest/no-conditional-expect */
22
import TestRenderer from 'react-test-renderer';
3-
import Only from '../';
3+
import Only from '../core/src';
44

55
describe('<Only />', () => {
66
it('Not rendering children', () => {

test/switch.test.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* eslint-disable jest/no-conditional-expect */
2+
import renderer from 'react-test-renderer';
3+
import { Switch, Case, Default } from '../core/src/switch';
4+
5+
6+
it('<Switch />', () => {
7+
const component = renderer.create(
8+
<Switch></Switch>
9+
);
10+
const only = component.toJSON();
11+
expect(only).toBeNull();
12+
});
13+
14+
it('<Default />', () => {
15+
const component = renderer.create(
16+
<Switch>
17+
<Default>you graduated</Default>
18+
</Switch>
19+
);
20+
const only = component.toJSON();
21+
expect(only).toEqual('you graduated');
22+
});
23+
24+
it('<Case />', () => {
25+
const component = renderer.create(
26+
<Switch>
27+
<Case condition={true}>preschool</Case>
28+
<Default>you graduated</Default>
29+
</Switch>
30+
);
31+
const only = component.toJSON();
32+
expect(only).toEqual('preschool');
33+
});
34+
35+
it('<Case /> condition=true', () => {
36+
const component = renderer.create(
37+
<Switch>
38+
<Case condition={true}>preschool</Case>
39+
<Case condition={true}>primary school</Case>
40+
<Default>you graduated</Default>
41+
</Switch>
42+
);
43+
const only = component.toJSON();
44+
expect(only).toEqual('preschool');
45+
});
46+
47+
it('<Case /> condition=false', () => {
48+
const component = renderer.create(
49+
<Switch>
50+
<Case condition={false}>preschool</Case>
51+
<Case condition={false}>primary school</Case>
52+
<Default>you graduated</Default>
53+
</Switch>
54+
);
55+
const only = component.toJSON();
56+
expect(only).toEqual('you graduated');
57+
});

www/src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createRoot } from 'react-dom/client';
22
import MarkdownPreviewExample from '@uiw/react-markdown-preview-example';
33
import data from '../../core/README.md';
4-
import pkg from '@uiw/react-only-when/package.json';
4+
import pkg from '../../core/package.json';
55
import OnlyWhenExample from './Example';
66

77
const Github = MarkdownPreviewExample.Github;

0 commit comments

Comments
 (0)