Skip to content

Commit f4a0ef3

Browse files
authored
Merge pull request #226 from flexbox/feat/offline-app
feat: 🎸 init offline app with legend state
2 parents 05880be + ff17223 commit f4a0ef3

File tree

18 files changed

+315
-0
lines changed

18 files changed

+315
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2+
3+
# dependencies
4+
node_modules/
5+
6+
# Expo
7+
.expo/
8+
dist/
9+
web-build/
10+
11+
# Native
12+
*.orig.*
13+
*.jks
14+
*.p8
15+
*.p12
16+
*.key
17+
*.mobileprovision
18+
19+
# Metro
20+
.metro-health-check*
21+
22+
# debug
23+
npm-debug.*
24+
yarn-debug.*
25+
yarn-error.*
26+
27+
# macOS
28+
.DS_Store
29+
*.pem
30+
31+
# local env files
32+
.env*.local
33+
34+
# typescript
35+
*.tsbuildinfo
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import AsyncStorage from '@react-native-async-storage/async-storage';
2+
import { view } from './storybook.requires';
3+
4+
const StorybookUIRoot = view.getStorybookUI({
5+
storage: {
6+
getItem: AsyncStorage.getItem,
7+
setItem: AsyncStorage.setItem,
8+
},
9+
});
10+
11+
export default StorybookUIRoot;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { StorybookConfig } from '@storybook/react-native';
2+
3+
const main: StorybookConfig = {
4+
stories: ['./stories/**/*.stories.?(ts|tsx|js|jsx)'],
5+
addons: ['@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-actions'],
6+
};
7+
8+
export default main;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { Preview } from '@storybook/react';
2+
3+
const preview: Preview = {
4+
parameters: {
5+
controls: {
6+
matchers: {
7+
color: /(background|color)$/i,
8+
date: /Date$/,
9+
},
10+
},
11+
},
12+
};
13+
14+
export default preview;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { View } from 'react-native';
2+
import type { Meta, StoryObj } from '@storybook/react';
3+
import { MyButton } from './Button';
4+
5+
const MyButtonMeta: Meta<typeof MyButton> = {
6+
title: 'MyButton',
7+
component: MyButton,
8+
argTypes: {
9+
onPress: { action: 'pressed the button' },
10+
},
11+
args: {
12+
text: 'Hello world',
13+
},
14+
decorators: [
15+
(Story) => (
16+
<View style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}>
17+
<Story />
18+
</View>
19+
),
20+
],
21+
};
22+
23+
export default MyButtonMeta;
24+
25+
export const Basic: StoryObj<typeof MyButton> = {};
26+
27+
export const AnotherExample: StoryObj<typeof MyButton> = {
28+
args: {
29+
text: 'Another example',
30+
},
31+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
2+
3+
export type MyButtonProps = {
4+
onPress: () => void;
5+
text: string;
6+
};
7+
8+
export const MyButton = ({ onPress, text }: MyButtonProps) => {
9+
return (
10+
<TouchableOpacity style={styles.container} onPress={onPress} activeOpacity={0.8}>
11+
<Text style={styles.text}>{text}</Text>
12+
</TouchableOpacity>
13+
);
14+
};
15+
16+
const styles = StyleSheet.create({
17+
container: {
18+
paddingHorizontal: 16,
19+
paddingVertical: 8,
20+
backgroundColor: 'purple',
21+
borderRadius: 8,
22+
},
23+
text: { color: 'white' },
24+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* do not change this file, it is auto generated by storybook. */
2+
3+
import { start } from '@storybook/react-native';
4+
5+
import '@storybook/addon-ondevice-controls/register';
6+
import '@storybook/addon-ondevice-actions/register';
7+
8+
const normalizedStories = [
9+
{
10+
titlePrefix: '',
11+
directory: './.storybook/stories',
12+
files: '**/*.stories.?(ts|tsx|js|jsx)',
13+
importPathMatcher:
14+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/,
15+
// @ts-ignore
16+
req: require.context(
17+
'./stories',
18+
true,
19+
/^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/
20+
),
21+
},
22+
];
23+
24+
// @ts-ignore
25+
global.STORIES = normalizedStories;
26+
27+
export const view = start({
28+
annotations: [
29+
require('./preview'),
30+
require('@storybook/react-native/dist/preview'),
31+
require('@storybook/addon-actions/preview'),
32+
],
33+
storyEntries: normalizedStories,
34+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Button, FlatList, SafeAreaView, StyleSheet, Text, View } from 'react-native';
2+
import { state$ } from './src/legend-state';
3+
import { observer } from "@legendapp/state/react";
4+
5+
const App = observer(() => {
6+
7+
const addExpense = () => {
8+
const newExpense = {
9+
id: Math.random().toString(),
10+
title: `Expense ${expenses.length + 1}`,
11+
amount: Math.floor(Math.random()),
12+
};
13+
state$.expenses.set((currentExpenses) => [...currentExpenses, newExpense]);
14+
};
15+
const expenses = state$.expenses.get();
16+
17+
return (
18+
<SafeAreaView style={styles.container}>
19+
<FlatList
20+
data={expenses}
21+
keyExtractor={(item) => item.id}
22+
renderItem={({ item }) => (
23+
<View>
24+
<Text>
25+
{item.title}: ${item.amount}
26+
</Text>
27+
</View>
28+
)}
29+
/>
30+
<Button title="Add Expense" onPress={addExpense} />
31+
</SafeAreaView>
32+
);
33+
});
34+
35+
const styles = StyleSheet.create({
36+
container: {
37+
flex: 1,
38+
backgroundColor: '#fff',
39+
alignItems: 'center',
40+
justifyContent: 'center',
41+
},
42+
});
43+
44+
export default App;
45+
// export { default } from "./.storybook";
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"expo": {
3+
"name": "offline-with-legend-state",
4+
"slug": "offline-with-legend-state",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/icon.png",
8+
"userInterfaceStyle": "light",
9+
"splash": {
10+
"image": "./assets/splash.png",
11+
"resizeMode": "contain",
12+
"backgroundColor": "#ffffff"
13+
},
14+
"assetBundlePatterns": [
15+
"**/*"
16+
],
17+
"ios": {
18+
"supportsTablet": true
19+
},
20+
"android": {
21+
"adaptiveIcon": {
22+
"foregroundImage": "./assets/adaptive-icon.png",
23+
"backgroundColor": "#ffffff"
24+
}
25+
},
26+
"web": {
27+
"favicon": "./assets/favicon.png"
28+
}
29+
}
30+
}
17.1 KB
Loading

0 commit comments

Comments
 (0)