Skip to content

Commit c6c4fac

Browse files
committed
feat(api-improvement): separated components and wrote readme
1 parent fc8c7c9 commit c6c4fac

File tree

5 files changed

+189
-25
lines changed

5 files changed

+189
-25
lines changed

README.md

+71-4
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,88 @@
11
# react-native-skia-ui
22

3-
Cross platform UI primitives implemented with `@shopify/react-native-skia`
3+
Cross platform UI primitives implemented with `@shopify/react-native-skia`.
4+
This library provides functionality of system UI components like `ActivityIndicator` for Android, IOS and Web.
5+
Components are ported from flutter and are implemented using `@shopify/react-native-skia` and `react-native-reanimated`.
46

57
## Installation
68

79
```sh
810
npm install react-native-skia-ui
911
```
1012

13+
### Peer Dependencies
14+
15+
This library has the following peer dependencies:
16+
17+
- `@shopify/react-native-skia`
18+
- `react-native-reanimated`
19+
20+
If you don't have them installed, you can install them with:
21+
22+
```sh
23+
npm install @shopify/react-native-skia react-native-reanimated
24+
```
25+
1126
## Usage
1227

28+
For now, the library only provides a few components:
29+
30+
- `DeterminateMaterialCircularProgressIndicator`
31+
- `IndeterminateMaterialCircularProgressIndicator`
32+
- `MaterialCircularProgressIndicator` (blend of the two above)
33+
1334
```js
14-
import { multiply } from 'react-native-skia-ui';
35+
import * as React from 'react';
36+
37+
import { StyleSheet, Text, View } from 'react-native';
38+
import {
39+
DeterminateMaterialCircularProgressIndicator,
40+
IndeterminateMaterialCircularProgressIndicator,
41+
} from 'react-native-skia-ui/material-circular-progress-indicator';
42+
import { useSharedValue, withTiming } from 'react-native-reanimated';
43+
44+
export default function App() {
45+
const progress = useSharedValue(0);
46+
React.useEffect(() => {
47+
const id = setInterval(() => {
48+
progress.value = withTiming(Math.random(), { duration: 1000 });
49+
}, 1000);
1550

16-
// ...
51+
return () => clearInterval(id);
52+
});
53+
return (
54+
<View style={styles.container}>
55+
<Text>DeterminateMaterialCircularProgressIndicator</Text>
56+
<DeterminateMaterialCircularProgressIndicator
57+
size={56}
58+
valueColor="green"
59+
strokeWidth={5}
60+
strokeCap="round"
61+
value={progress}
62+
/>
63+
<DeterminateMaterialCircularProgressIndicator
64+
size={100}
65+
valueColor="blue"
66+
strokeWidth={4}
67+
strokeCap="round"
68+
value={progress}
69+
/>
70+
<Text>IndeterminateMaterialCircularProgressIndicator</Text>
71+
<IndeterminateMaterialCircularProgressIndicator
72+
size={40}
73+
valueColor="black"
74+
/>
1775

18-
const result = await multiply(3, 7);
76+
<IndeterminateMaterialCircularProgressIndicator
77+
size={100}
78+
valueColor="red"
79+
backgroundColor={'#f0f0f0'}
80+
strokeWidth={8}
81+
strokeCap="round"
82+
/>
83+
</View>
84+
);
85+
}
1986
```
2087

2188
## Contributing

example/babel.config.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,29 @@ const pak = require('../package.json');
44
module.exports = function (api) {
55
api.cache(true);
66

7+
const exports = pak.exports;
8+
if (!exports) {
9+
throw new Error('The package.json must have a "exports" field');
10+
}
11+
12+
const aliases = Object.entries(exports).reduce((acc, [_key, value]) => {
13+
const key = _key.startsWith('.') ? _key.slice(1) : _key;
14+
// We only care about the "source" field
15+
if (value.source) {
16+
const aliasName = pak.name + key;
17+
acc[`^${aliasName}$`] = path.join(__dirname, '..', value.source);
18+
}
19+
return acc;
20+
}, {});
21+
722
return {
823
presets: ['babel-preset-expo'],
924
plugins: [
1025
[
1126
'module-resolver',
1227
{
1328
extensions: ['.tsx', '.ts', '.js', '.json'],
14-
alias: {
15-
// For development, we want to alias the library to the source
16-
[pak.name]: path.join(__dirname, '..', pak.source),
17-
},
29+
alias: aliases,
1830
},
1931
],
2032
'react-native-reanimated/plugin',

example/src/App.tsx

+27-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import * as React from 'react';
22

3-
import { StyleSheet, View } from 'react-native';
4-
import { MaterialCircularProgressIndicator } from '../../src/material-circular-progress-indicator';
3+
import { StyleSheet, Text, View } from 'react-native';
4+
import {
5+
DeterminateMaterialCircularProgressIndicator,
6+
IndeterminateMaterialCircularProgressIndicator,
7+
} from 'react-native-skia-ui/material-circular-progress-indicator';
58
import { useSharedValue, withTiming } from 'react-native-reanimated';
69

710
export default function App() {
@@ -15,14 +18,34 @@ export default function App() {
1518
});
1619
return (
1720
<View style={styles.container}>
18-
<MaterialCircularProgressIndicator
21+
<Text>DeterminateMaterialCircularProgressIndicator</Text>
22+
<DeterminateMaterialCircularProgressIndicator
1923
size={56}
2024
valueColor="green"
2125
strokeWidth={5}
2226
strokeCap="round"
2327
value={progress}
2428
/>
25-
<MaterialCircularProgressIndicator size={40} valueColor="black" />
29+
<DeterminateMaterialCircularProgressIndicator
30+
size={100}
31+
valueColor="blue"
32+
strokeWidth={4}
33+
strokeCap="round"
34+
value={progress}
35+
/>
36+
<Text>IndeterminateMaterialCircularProgressIndicator</Text>
37+
<IndeterminateMaterialCircularProgressIndicator
38+
size={40}
39+
valueColor="black"
40+
/>
41+
42+
<IndeterminateMaterialCircularProgressIndicator
43+
size={100}
44+
valueColor="red"
45+
backgroundColor={'#f0f0f0'}
46+
strokeWidth={8}
47+
strokeCap="round"
48+
/>
2649
</View>
2750
);
2851
}

src/material-circular-progress-indicator/MaterialCircularProgressIndicator.tsx

+65-12
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import Animated, {
2727
withSequence,
2828
withTiming,
2929
} from 'react-native-reanimated';
30-
import type { SetOptional } from 'type-fest';
30+
import type { SetNonNullable, SetOptional } from 'type-fest';
3131
import {
3232
K_INTERMEDIATE_CIRCULAR_DURATION,
3333
offsetTween,
@@ -152,7 +152,7 @@ const Content_ = ({
152152
}));
153153

154154
useAnimatedReaction(
155-
() => stopped.value,
155+
() => stopped.value || value.value !== undefined,
156156
(shouldStop) => {
157157
if (shouldStop) {
158158
// stopping the animation
@@ -238,17 +238,35 @@ const Content_ = ({
238238
);
239239
};
240240

241+
export type InternalOrSharedProps = OrPlainValueProp<
242+
InternalProps,
243+
| 'size'
244+
| 'value'
245+
| 'strokeWidth'
246+
| 'backgroundColor'
247+
| 'valueColor'
248+
| 'stopped'
249+
>;
250+
251+
export type DefaultedKeys = 'strokeWidth' | 'backgroundColor';
241252
export type MaterialCircularProgressIndicatorProps = SetOptional<
242-
OrPlainValueProp<
243-
InternalProps,
244-
| 'size'
245-
| 'value'
246-
| 'strokeWidth'
247-
| 'backgroundColor'
248-
| 'valueColor'
249-
| 'stopped'
250-
>,
251-
'strokeWidth' | 'stopped' | 'value' | 'backgroundColor'
253+
InternalOrSharedProps,
254+
DefaultedKeys | 'stopped' | 'value'
255+
>;
256+
/*
257+
type SetRequiredAndNonNullable<T, K extends keyof T> = SetRequired<
258+
SetNonNullable<T, K>,
259+
K
260+
>; */
261+
262+
export type DeterminateMaterialCircularProgressIndicatorProps = SetOptional<
263+
SetNonNullable<Omit<InternalOrSharedProps, 'stopped'>, 'value'>,
264+
DefaultedKeys
265+
>;
266+
267+
export type IndeterminateMaterialCircularProgressIndicatorProps = SetOptional<
268+
Omit<InternalOrSharedProps, 'value'>,
269+
DefaultedKeys | 'stopped'
252270
>;
253271

254272
const useToSharedValueOptional = <T,>(
@@ -270,6 +288,13 @@ const useToSharedValue = <T,>(value: T | SharedValue<T>) =>
270288
return value;
271289
}, [value]);
272290

291+
/**
292+
*
293+
* @description Component has two modes: determinate and indeterminate. Which are controlled by the `value` prop.
294+
* If `value` is undefined, the progress indicator will be indeterminate.
295+
* If `value` is a number between 0 and 1, the progress indicator will be determinate.
296+
* Not all props applies to both modes. For more type safety, use `DeterminateMaterialCircularProgressIndicator` and `IndeterminateMaterialCircularProgressIndicator` instead.
297+
*/
273298
export const MaterialCircularProgressIndicator = (
274299
props: MaterialCircularProgressIndicatorProps
275300
) => (
@@ -283,3 +308,31 @@ export const MaterialCircularProgressIndicator = (
283308
valueColor={useToSharedValue(props.valueColor)}
284309
/>
285310
);
311+
312+
export const IndeterminateMaterialCircularProgressIndicator = (
313+
props: IndeterminateMaterialCircularProgressIndicatorProps
314+
) => (
315+
<Content_
316+
{...props}
317+
size={useToSharedValue(props.size)}
318+
value={useSharedValue(undefined)}
319+
stopped={useToSharedValueOptional(props.stopped, false)}
320+
strokeWidth={useToSharedValueOptional(props.strokeWidth, 4)}
321+
backgroundColor={useToSharedValue(props.backgroundColor)}
322+
valueColor={useToSharedValue(props.valueColor)}
323+
/>
324+
);
325+
326+
export const DeterminateMaterialCircularProgressIndicator = (
327+
props: DeterminateMaterialCircularProgressIndicatorProps
328+
) => (
329+
<Content_
330+
{...props}
331+
size={useToSharedValue(props.size)}
332+
value={useToSharedValue(props.value)}
333+
stopped={useSharedValue(false)}
334+
strokeWidth={useToSharedValueOptional(props.strokeWidth, 4)}
335+
backgroundColor={useToSharedValue(props.backgroundColor)}
336+
valueColor={useToSharedValue(props.valueColor)}
337+
/>
338+
);
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
export {
22
MaterialCircularProgressIndicator,
3-
type MaterialCircularProgressIndicatorProps,
3+
DeterminateMaterialCircularProgressIndicator,
4+
IndeterminateMaterialCircularProgressIndicator,
5+
} from './MaterialCircularProgressIndicator';
6+
7+
export type {
8+
DefaultedKeys,
9+
MaterialCircularProgressIndicatorProps,
10+
DeterminateMaterialCircularProgressIndicatorProps,
11+
IndeterminateMaterialCircularProgressIndicatorProps,
12+
InternalOrSharedProps,
413
} from './MaterialCircularProgressIndicator';

0 commit comments

Comments
 (0)