chore: change prettier config (#19)
This commit is contained in:
parent
c4a8ed36fc
commit
f68fcf720f
|
@ -1,3 +1,3 @@
|
|||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const path = require('path');
|
||||
const pak = require('../package.json');
|
||||
const path = require('path')
|
||||
const pak = require('../package.json')
|
||||
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
|
@ -14,4 +14,4 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AppRegistry } from 'react-native';
|
||||
import App from './src/App';
|
||||
import { name as appName } from './app.json';
|
||||
import { AppRegistry } from 'react-native'
|
||||
import App from './src/App'
|
||||
import { name as appName } from './app.json'
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App);
|
||||
AppRegistry.registerComponent(appName, () => App)
|
||||
|
|
|
@ -494,8 +494,8 @@ SPEC CHECKSUMS:
|
|||
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
|
||||
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
|
||||
FlipperKit: 57764956d2f0f972c1af5075a9c8f05ca5b12349
|
||||
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
||||
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
|
||||
Folly: aeb27d02cdff07ca01f8a8a5a6dd5bcaf6be6f70
|
||||
glog: 2ad46e202fbaa5641fceb4b2af37dcd88fd8762d
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b
|
||||
RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
const path = require('path');
|
||||
const blacklist = require('metro-config/src/defaults/blacklist');
|
||||
const escape = require('escape-string-regexp');
|
||||
const pak = require('../package.json');
|
||||
const path = require('path')
|
||||
const blacklist = require('metro-config/src/defaults/blacklist')
|
||||
const escape = require('escape-string-regexp')
|
||||
const pak = require('../package.json')
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const root = path.resolve(__dirname, '..')
|
||||
|
||||
const modules = Object.keys({
|
||||
...pak.peerDependencies,
|
||||
});
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
projectRoot: __dirname,
|
||||
|
@ -17,15 +17,12 @@ module.exports = {
|
|||
// So we blacklist them at the root, and alias them to the versions in example's node_modules
|
||||
resolver: {
|
||||
blacklistRE: blacklist(
|
||||
modules.map(
|
||||
(m) =>
|
||||
new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
|
||||
)
|
||||
modules.map((m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`))
|
||||
),
|
||||
|
||||
extraNodeModules: modules.reduce((acc, name) => {
|
||||
acc[name] = path.join(__dirname, 'node_modules', name);
|
||||
return acc;
|
||||
acc[name] = path.join(__dirname, 'node_modules', name)
|
||||
return acc
|
||||
}, {}),
|
||||
},
|
||||
|
||||
|
@ -37,4 +34,4 @@ module.exports = {
|
|||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import 'react-native-gesture-handler';
|
||||
import * as React from 'react';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import Examples from './Examples/Examples';
|
||||
import Basic from './Basic/Basic';
|
||||
import Dark from './Dark/Dark';
|
||||
import Translated from './Translated/Translated';
|
||||
import DisabledCategories from './DisabledCategories/DisabledCategories';
|
||||
import StaticModal from './StaticModal/StaticModal';
|
||||
import Static from './Static/Static';
|
||||
import EnableRecently from './EnableRecently/EnableRecently';
|
||||
import TopCategory from './TopCategory/TopCategory';
|
||||
import BottomCategory from './BottomCategory/BottomCategory';
|
||||
import SearchBar from './SearchBar/SearchBar';
|
||||
import 'react-native-gesture-handler'
|
||||
import * as React from 'react'
|
||||
import { NavigationContainer } from '@react-navigation/native'
|
||||
import { createStackNavigator } from '@react-navigation/stack'
|
||||
import Examples from './Examples/Examples'
|
||||
import Basic from './Basic/Basic'
|
||||
import Dark from './Dark/Dark'
|
||||
import Translated from './Translated/Translated'
|
||||
import DisabledCategories from './DisabledCategories/DisabledCategories'
|
||||
import StaticModal from './StaticModal/StaticModal'
|
||||
import Static from './Static/Static'
|
||||
import EnableRecently from './EnableRecently/EnableRecently'
|
||||
import TopCategory from './TopCategory/TopCategory'
|
||||
import BottomCategory from './BottomCategory/BottomCategory'
|
||||
import SearchBar from './SearchBar/SearchBar'
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
const Stack = createStackNavigator()
|
||||
export default () => {
|
||||
return (
|
||||
<NavigationContainer>
|
||||
|
@ -27,13 +27,10 @@ export default () => {
|
|||
<Stack.Screen name="TopCategory" component={TopCategory} />
|
||||
<Stack.Screen name="BottomCategory" component={BottomCategory} />
|
||||
<Stack.Screen name="Translated" component={Translated} />
|
||||
<Stack.Screen
|
||||
name="DisabledCategories"
|
||||
component={DisabledCategories}
|
||||
/>
|
||||
<Stack.Screen name="DisabledCategories" component={DisabledCategories} />
|
||||
<Stack.Screen name="StaticModal" component={StaticModal} />
|
||||
<Stack.Screen name="Static" component={Static} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const Basic = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -26,8 +26,8 @@ const Basic = () => {
|
|||
onClose={() => setIsModalOpen(false)}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -38,6 +38,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default Basic;
|
||||
export default Basic
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const BottomCategory = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -26,8 +26,8 @@ const BottomCategory = () => {
|
|||
categoryPosition="bottom"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -38,6 +38,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default BottomCategory;
|
||||
export default BottomCategory
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const Dark = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -34,8 +34,8 @@ const Dark = () => {
|
|||
headerStyles={styles.headerStyles}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -58,6 +58,6 @@ const styles = StyleSheet.create({
|
|||
color: '#fff',
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default Dark;
|
||||
export default Dark
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const DisabledCategories = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -27,8 +27,8 @@ const DisabledCategories = () => {
|
|||
disabledCategory={['activities', 'flags', 'objects', 'symbols']}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -39,6 +39,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default DisabledCategories;
|
||||
export default DisabledCategories
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const EnableRecently = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -27,8 +27,8 @@ const EnableRecently = () => {
|
|||
enableRecentlyUsed
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -39,6 +39,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default EnableRecently;
|
||||
export default EnableRecently
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import * as React from 'react';
|
||||
import { View, Button } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import type { StackScreenProps } from '@react-navigation/stack';
|
||||
import * as React from 'react'
|
||||
import { View, Button } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import type { StackScreenProps } from '@react-navigation/stack'
|
||||
|
||||
type RootStackParamList = {
|
||||
Examples: undefined;
|
||||
Basic: undefined;
|
||||
Dark: undefined;
|
||||
Translated: undefined;
|
||||
DisabledCategories: undefined;
|
||||
StaticModal: undefined;
|
||||
Static: undefined;
|
||||
EnableRecently: undefined;
|
||||
TopCategory: undefined;
|
||||
BottomCategory: undefined;
|
||||
SearchBar: undefined;
|
||||
};
|
||||
Examples: undefined
|
||||
Basic: undefined
|
||||
Dark: undefined
|
||||
Translated: undefined
|
||||
DisabledCategories: undefined
|
||||
StaticModal: undefined
|
||||
Static: undefined
|
||||
EnableRecently: undefined
|
||||
TopCategory: undefined
|
||||
BottomCategory: undefined
|
||||
SearchBar: undefined
|
||||
}
|
||||
|
||||
type Props = StackScreenProps<RootStackParamList, 'Examples'>;
|
||||
type Props = StackScreenProps<RootStackParamList, 'Examples'>
|
||||
|
||||
const Examples = ({ navigation }: Props) => {
|
||||
return (
|
||||
|
@ -25,10 +25,7 @@ const Examples = ({ navigation }: Props) => {
|
|||
<View>
|
||||
<Button title="Basic" onPress={() => navigation.navigate('Basic')} />
|
||||
<Button title="Dark" onPress={() => navigation.navigate('Dark')} />
|
||||
<Button
|
||||
title="Translated"
|
||||
onPress={() => navigation.navigate('Translated')}
|
||||
/>
|
||||
<Button title="Translated" onPress={() => navigation.navigate('Translated')} />
|
||||
<Button
|
||||
title="Disabled Categories"
|
||||
onPress={() => navigation.navigate('DisabledCategories')}
|
||||
|
@ -37,28 +34,16 @@ const Examples = ({ navigation }: Props) => {
|
|||
title="Static Modal (wihtout knob)"
|
||||
onPress={() => navigation.navigate('StaticModal')}
|
||||
/>
|
||||
<Button
|
||||
title="Static Component"
|
||||
onPress={() => navigation.navigate('Static')}
|
||||
/>
|
||||
<Button title="Static Component" onPress={() => navigation.navigate('Static')} />
|
||||
<Button
|
||||
title="Enable recently used"
|
||||
onPress={() => navigation.navigate('EnableRecently')}
|
||||
/>
|
||||
<Button
|
||||
title="Category Top"
|
||||
onPress={() => navigation.navigate('TopCategory')}
|
||||
/>
|
||||
<Button
|
||||
title="Category Bottom"
|
||||
onPress={() => navigation.navigate('BottomCategory')}
|
||||
/>
|
||||
<Button
|
||||
title="Search Bar"
|
||||
onPress={() => navigation.navigate('SearchBar')}
|
||||
/>
|
||||
<Button title="Category Top" onPress={() => navigation.navigate('TopCategory')} />
|
||||
<Button title="Category Bottom" onPress={() => navigation.navigate('BottomCategory')} />
|
||||
<Button title="Search Bar" onPress={() => navigation.navigate('SearchBar')} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
export default Examples;
|
||||
)
|
||||
}
|
||||
export default Examples
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const SearchBar = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -27,8 +27,8 @@ const SearchBar = () => {
|
|||
enableSearchBar
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -39,6 +39,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default SearchBar;
|
||||
export default SearchBar
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { EmojiKeyboard } from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import { EmojiKeyboard } from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const Static = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [result, setResult] = React.useState<string>()
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
setResult(emoji.emoji);
|
||||
};
|
||||
setResult(emoji.emoji)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
</View>
|
||||
<View style={styles.container}>
|
||||
<EmojiKeyboard
|
||||
onEmojiSelected={handlePick}
|
||||
containerStyles={styles.keyboardContainer}
|
||||
/>
|
||||
<EmojiKeyboard onEmojiSelected={handlePick} containerStyles={styles.keyboardContainer} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -37,6 +34,6 @@ const styles = StyleSheet.create({
|
|||
keyboardContainer: {
|
||||
borderRadius: 0,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default Static;
|
||||
export default Static
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const StaticModal = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -28,8 +28,8 @@ const StaticModal = () => {
|
|||
defaultHeight="65%"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -40,6 +40,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default StaticModal;
|
||||
export default StaticModal
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const TopCategory = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Result: {result}</Text>
|
||||
|
@ -26,8 +26,8 @@ const TopCategory = () => {
|
|||
categoryPosition="top"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -38,6 +38,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default TopCategory;
|
||||
export default TopCategory
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import EmojiPicker, { pl } from 'rn-emoji-keyboard';
|
||||
import type { EmojiType } from 'src/types';
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import EmojiPicker, { pl } from 'rn-emoji-keyboard'
|
||||
import type { EmojiType } from 'src/types'
|
||||
|
||||
const Translated = () => {
|
||||
const [result, setResult] = React.useState<string>();
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||
const [result, setResult] = React.useState<string>()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false)
|
||||
|
||||
const handlePick = (emoji: EmojiType) => {
|
||||
console.log(emoji);
|
||||
setResult(emoji.emoji);
|
||||
setIsModalOpen((prev) => !prev);
|
||||
};
|
||||
console.log(emoji)
|
||||
setResult(emoji.emoji)
|
||||
setIsModalOpen((prev) => !prev)
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.text}>Emotka: {result}</Text>
|
||||
|
@ -27,8 +27,8 @@ const Translated = () => {
|
|||
translation={pl}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -39,6 +39,6 @@ const styles = StyleSheet.create({
|
|||
margin: 64,
|
||||
fontSize: 18,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default Translated;
|
||||
export default Translated
|
||||
|
|
23
package.json
23
package.json
|
@ -52,6 +52,7 @@
|
|||
"@commitlint/config-conventional": "^11.0.0",
|
||||
"@react-native-community/eslint-config": "^2.0.0",
|
||||
"@release-it/conventional-changelog": "^2.0.0",
|
||||
"@twgdev/prettier-config": "^1.0.2",
|
||||
"@types/jest": "^26.0.0",
|
||||
"@types/react": "^16.9.19",
|
||||
"@types/react-native": "0.62.13",
|
||||
|
@ -116,31 +117,13 @@
|
|||
"extends": [
|
||||
"@react-native-community",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"quoteProps": "consistent",
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"useTabs": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eslintIgnore": [
|
||||
"node_modules/",
|
||||
"lib/"
|
||||
],
|
||||
"prettier": {
|
||||
"quoteProps": "consistent",
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"useTabs": false
|
||||
},
|
||||
"prettier": "@twgdev/prettier-config",
|
||||
"react-native-builder-bob": {
|
||||
"source": "src",
|
||||
"output": "lib",
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
const path = require('path')
|
||||
const child_process = require('child_process')
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const args = process.argv.slice(2);
|
||||
const root = path.resolve(__dirname, '..')
|
||||
const args = process.argv.slice(2)
|
||||
const options = {
|
||||
cwd: process.cwd(),
|
||||
env: process.env,
|
||||
stdio: 'inherit',
|
||||
encoding: 'utf-8',
|
||||
};
|
||||
}
|
||||
|
||||
let result;
|
||||
let result
|
||||
|
||||
if (process.cwd() !== root || args.length) {
|
||||
// We're not in the root of the project, or additional arguments were passed
|
||||
// In this case, forward the command to `yarn`
|
||||
result = child_process.spawnSync('yarn', args, options);
|
||||
result = child_process.spawnSync('yarn', args, options)
|
||||
} else {
|
||||
// If `yarn` is run without arguments, perform bootstrap
|
||||
result = child_process.spawnSync('yarn', ['bootstrap'], options);
|
||||
result = child_process.spawnSync('yarn', ['bootstrap'], options)
|
||||
}
|
||||
|
||||
process.exitCode = result.status;
|
||||
process.exitCode = result.status
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
const json = require('unicode-emoji-json/data-by-group.json');
|
||||
const fs = require('fs');
|
||||
const json = require('unicode-emoji-json/data-by-group.json')
|
||||
const fs = require('fs')
|
||||
|
||||
const newArray = [];
|
||||
const newArray = []
|
||||
for (const [key, value] of Object.entries(json)) {
|
||||
const newData = value.map((emoji) => ({
|
||||
emoji: emoji.emoji,
|
||||
name: emoji.name,
|
||||
v: emoji.unicode_version,
|
||||
}));
|
||||
}))
|
||||
newArray.push({
|
||||
title: key.replace(' & ', '_').replace(' ', '_').toLocaleLowerCase(),
|
||||
data: newData,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fs.writeFile(
|
||||
'./src/assets/emojis.json',
|
||||
JSON.stringify(newArray),
|
||||
function (err) {
|
||||
if (err) return console.log(err);
|
||||
console.log('emojis.json successfully saved to assets folder');
|
||||
}
|
||||
);
|
||||
fs.writeFile('./src/assets/emojis.json', JSON.stringify(newArray), function (err) {
|
||||
if (err) return console.log(err)
|
||||
console.log('emojis.json successfully saved to assets folder')
|
||||
})
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import * as React from 'react';
|
||||
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
|
||||
import { KeyboardProvider } from './contexts/KeyboardProvider';
|
||||
import type {
|
||||
KeyboardProps,
|
||||
OnEmojiSelected,
|
||||
} from './contexts/KeyboardContext';
|
||||
import * as React from 'react'
|
||||
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard'
|
||||
import { KeyboardProvider } from './contexts/KeyboardProvider'
|
||||
import type { KeyboardProps, OnEmojiSelected } from './contexts/KeyboardContext'
|
||||
|
||||
type EmojiKeyboardProps = {
|
||||
onEmojiSelected: OnEmojiSelected;
|
||||
} & Partial<KeyboardProps>;
|
||||
onEmojiSelected: OnEmojiSelected
|
||||
} & Partial<KeyboardProps>
|
||||
|
||||
export const EmojiKeyboard = (props: EmojiKeyboardProps) => {
|
||||
return (
|
||||
<KeyboardProvider {...props}>
|
||||
<EmojiStaticKeyboard />
|
||||
</KeyboardProvider>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import * as React from 'react';
|
||||
import { Animated, useWindowDimensions } from 'react-native';
|
||||
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
|
||||
import { Knob } from './components/Knob';
|
||||
import {
|
||||
defaultKeyboardContext,
|
||||
KeyboardProvider,
|
||||
} from './contexts/KeyboardProvider';
|
||||
import type { KeyboardProps } from './contexts/KeyboardContext';
|
||||
import type { EmojiType } from './types';
|
||||
import { ModalWithBackdrop } from './components/ModalWithBackdrop';
|
||||
import { getHeight } from './utils';
|
||||
import * as React from 'react'
|
||||
import { Animated, useWindowDimensions } from 'react-native'
|
||||
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard'
|
||||
import { Knob } from './components/Knob'
|
||||
import { defaultKeyboardContext, KeyboardProvider } from './contexts/KeyboardProvider'
|
||||
import type { KeyboardProps } from './contexts/KeyboardContext'
|
||||
import type { EmojiType } from './types'
|
||||
import { ModalWithBackdrop } from './components/ModalWithBackdrop'
|
||||
import { getHeight } from './utils'
|
||||
|
||||
export const EmojiPicker = ({
|
||||
onEmojiSelected,
|
||||
|
@ -19,55 +16,49 @@ export const EmojiPicker = ({
|
|||
defaultHeight = defaultKeyboardContext.defaultHeight,
|
||||
...props
|
||||
}: KeyboardProps) => {
|
||||
const { height: screenHeight } = useWindowDimensions();
|
||||
const offsetY = React.useRef(new Animated.Value(0)).current;
|
||||
const height = React.useRef(
|
||||
new Animated.Value(getHeight(defaultHeight, screenHeight))
|
||||
).current;
|
||||
const translateY = React.useRef(new Animated.Value(0)).current;
|
||||
const { height: screenHeight } = useWindowDimensions()
|
||||
const offsetY = React.useRef(new Animated.Value(0)).current
|
||||
const height = React.useRef(new Animated.Value(getHeight(defaultHeight, screenHeight))).current
|
||||
const translateY = React.useRef(new Animated.Value(0)).current
|
||||
|
||||
React.useEffect(() => {
|
||||
Animated.timing(translateY, {
|
||||
toValue: open ? 0 : screenHeight,
|
||||
useNativeDriver: true,
|
||||
duration: 500,
|
||||
}).start();
|
||||
}, [open, screenHeight, translateY]);
|
||||
}).start()
|
||||
}, [open, screenHeight, translateY])
|
||||
|
||||
const close = () => {
|
||||
height.setValue(getHeight(defaultHeight, screenHeight));
|
||||
offsetY.setValue(0);
|
||||
onClose();
|
||||
};
|
||||
height.setValue(getHeight(defaultHeight, screenHeight))
|
||||
offsetY.setValue(0)
|
||||
onClose()
|
||||
}
|
||||
|
||||
return (
|
||||
<KeyboardProvider
|
||||
onEmojiSelected={(emoji: EmojiType) => {
|
||||
onEmojiSelected(emoji);
|
||||
close();
|
||||
onEmojiSelected(emoji)
|
||||
close()
|
||||
}}
|
||||
open={open}
|
||||
onClose={close}
|
||||
expandable={expandable}
|
||||
defaultHeight={defaultHeight}
|
||||
{...props}
|
||||
>
|
||||
{...props}>
|
||||
<ModalWithBackdrop isOpen={open} backdropPress={close}>
|
||||
<>
|
||||
{expandable && (
|
||||
<Knob height={height} offsetY={offsetY} onClose={onClose} />
|
||||
)}
|
||||
{expandable && <Knob height={height} offsetY={offsetY} onClose={onClose} />}
|
||||
<Animated.View
|
||||
style={[
|
||||
{
|
||||
height: Animated.subtract(height, offsetY),
|
||||
},
|
||||
]}
|
||||
>
|
||||
]}>
|
||||
<EmojiStaticKeyboard />
|
||||
</Animated.View>
|
||||
</>
|
||||
</ModalWithBackdrop>
|
||||
</KeyboardProvider>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="23" height="23" viewBox="0 0 24 24" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -10,4 +10,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="23" height="23" viewBox="0 0 24 24" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
import * as React from 'react'
|
||||
import Svg, { FillProps, Path } from 'react-native-svg'
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||||
|
@ -8,4 +8,4 @@ export default ({ fill }: FillProps) => (
|
|||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
)
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import * as React from 'react';
|
||||
import { Animated, FlatList, StyleSheet, View, ViewStyle } from 'react-native';
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore';
|
||||
import { defaultKeyboardContext } from '../contexts/KeyboardProvider';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import {
|
||||
CATEGORIES_NAVIGATION,
|
||||
CategoryNavigationItem,
|
||||
CategoryTypes,
|
||||
} from '../types';
|
||||
import { CategoryItem } from './CategoryItem';
|
||||
import { exhaustiveTypeCheck, getCategoryIndex } from '../utils';
|
||||
import * as React from 'react'
|
||||
import { Animated, FlatList, StyleSheet, View, ViewStyle } from 'react-native'
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore'
|
||||
import { defaultKeyboardContext } from '../contexts/KeyboardProvider'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import { CATEGORIES_NAVIGATION, CategoryNavigationItem, CategoryTypes } from '../types'
|
||||
import { CategoryItem } from './CategoryItem'
|
||||
import { exhaustiveTypeCheck, getCategoryIndex } from '../utils'
|
||||
|
||||
type CategoriesProps = {
|
||||
flatListRef: React.RefObject<FlatList>;
|
||||
scrollNav: Animated.Value;
|
||||
};
|
||||
flatListRef: React.RefObject<FlatList>
|
||||
scrollNav: Animated.Value
|
||||
}
|
||||
|
||||
export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
||||
const {
|
||||
|
@ -26,27 +22,21 @@ export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
|||
enableRecentlyUsed,
|
||||
categoryPosition,
|
||||
searchPhrase,
|
||||
} = React.useContext(KeyboardContext);
|
||||
const { keyboardState } = useKeyboardStore();
|
||||
} = React.useContext(KeyboardContext)
|
||||
const { keyboardState } = useKeyboardStore()
|
||||
const handleScrollToCategory = React.useCallback(
|
||||
(category: CategoryTypes) => {
|
||||
flatListRef?.current?.scrollToIndex(
|
||||
getCategoryIndex(disabledCategory, category)
|
||||
);
|
||||
flatListRef?.current?.scrollToIndex(getCategoryIndex(disabledCategory, category))
|
||||
},
|
||||
[disabledCategory, flatListRef]
|
||||
);
|
||||
)
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
({ item, index }: { item: CategoryNavigationItem; index: number }) => (
|
||||
<CategoryItem
|
||||
item={item}
|
||||
index={index}
|
||||
handleScrollToCategory={handleScrollToCategory}
|
||||
/>
|
||||
<CategoryItem item={item} index={index} handleScrollToCategory={handleScrollToCategory} />
|
||||
),
|
||||
[handleScrollToCategory]
|
||||
);
|
||||
)
|
||||
|
||||
const activeIndicator = React.useCallback(
|
||||
() => (
|
||||
|
@ -63,51 +53,45 @@ export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
|||
/>
|
||||
),
|
||||
[activeCategoryContainerColor, scrollNav]
|
||||
);
|
||||
)
|
||||
|
||||
const getStylesBasedOnPosition = () => {
|
||||
const style: ViewStyle[] = [styles.navigation];
|
||||
const style: ViewStyle[] = [styles.navigation]
|
||||
switch (categoryPosition) {
|
||||
case 'floating':
|
||||
style.push(styles.navigationFloating);
|
||||
break;
|
||||
style.push(styles.navigationFloating)
|
||||
break
|
||||
case 'top':
|
||||
style.push(styles.navigationTop);
|
||||
break;
|
||||
style.push(styles.navigationTop)
|
||||
break
|
||||
case 'bottom':
|
||||
style.push(styles.navigationBottom);
|
||||
break;
|
||||
style.push(styles.navigationBottom)
|
||||
break
|
||||
default:
|
||||
exhaustiveTypeCheck(categoryPosition);
|
||||
break;
|
||||
exhaustiveTypeCheck(categoryPosition)
|
||||
break
|
||||
}
|
||||
|
||||
if (
|
||||
categoryContainerColor !==
|
||||
defaultKeyboardContext.categoryContainerColor ||
|
||||
categoryContainerColor !== defaultKeyboardContext.categoryContainerColor ||
|
||||
categoryPosition === 'floating'
|
||||
)
|
||||
style.push({
|
||||
backgroundColor: categoryContainerColor,
|
||||
});
|
||||
return style;
|
||||
};
|
||||
})
|
||||
return style
|
||||
}
|
||||
|
||||
const renderData = React.useMemo(() => {
|
||||
const isRecentlyUsedHidden = (category: CategoryTypes) =>
|
||||
category === 'recently_used' &&
|
||||
(keyboardState.recentlyUsed.length === 0 || !enableRecentlyUsed);
|
||||
(keyboardState.recentlyUsed.length === 0 || !enableRecentlyUsed)
|
||||
return CATEGORIES_NAVIGATION.filter(({ category }) => {
|
||||
if (searchPhrase === '' && category === 'search') return false;
|
||||
if (isRecentlyUsedHidden(category)) return false;
|
||||
return !disabledCategory.includes(category);
|
||||
});
|
||||
}, [
|
||||
disabledCategory,
|
||||
enableRecentlyUsed,
|
||||
keyboardState.recentlyUsed.length,
|
||||
searchPhrase,
|
||||
]);
|
||||
if (searchPhrase === '' && category === 'search') return false
|
||||
if (isRecentlyUsedHidden(category)) return false
|
||||
return !disabledCategory.includes(category)
|
||||
})
|
||||
}, [disabledCategory, enableRecentlyUsed, keyboardState.recentlyUsed.length, searchPhrase])
|
||||
|
||||
return (
|
||||
<View style={[categoryPosition === 'floating' && styles.floating]}>
|
||||
|
@ -126,8 +110,8 @@ export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
|||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
floating: {
|
||||
|
@ -175,4 +159,4 @@ const styles = StyleSheet.create({
|
|||
width: 28,
|
||||
height: 28,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,31 +1,23 @@
|
|||
import * as React from 'react';
|
||||
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import type { CategoryNavigationItem, CategoryTypes } from '../types';
|
||||
import { Icon } from './Icon';
|
||||
import * as React from 'react'
|
||||
import { View, StyleSheet, TouchableOpacity } from 'react-native'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import type { CategoryNavigationItem, CategoryTypes } from '../types'
|
||||
import { Icon } from './Icon'
|
||||
|
||||
type CategoryItemProps = {
|
||||
item: CategoryNavigationItem;
|
||||
index: number;
|
||||
handleScrollToCategory: (category: CategoryTypes) => void;
|
||||
};
|
||||
item: CategoryNavigationItem
|
||||
index: number
|
||||
handleScrollToCategory: (category: CategoryTypes) => void
|
||||
}
|
||||
|
||||
export const CategoryItem = ({
|
||||
item,
|
||||
index,
|
||||
handleScrollToCategory,
|
||||
}: CategoryItemProps) => {
|
||||
const {
|
||||
activeCategoryIndex,
|
||||
categoryColor,
|
||||
activeCategoryColor,
|
||||
setActiveCategoryIndex,
|
||||
} = React.useContext(KeyboardContext);
|
||||
export const CategoryItem = ({ item, index, handleScrollToCategory }: CategoryItemProps) => {
|
||||
const { activeCategoryIndex, categoryColor, activeCategoryColor, setActiveCategoryIndex } =
|
||||
React.useContext(KeyboardContext)
|
||||
|
||||
const handleSelect = () => {
|
||||
handleScrollToCategory(item.category);
|
||||
setActiveCategoryIndex(index);
|
||||
};
|
||||
handleScrollToCategory(item.category)
|
||||
setActiveCategoryIndex(index)
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={handleSelect}>
|
||||
|
@ -38,8 +30,8 @@ export const CategoryItem = ({
|
|||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -51,4 +43,4 @@ const styles = StyleSheet.create({
|
|||
borderRadius: 6,
|
||||
},
|
||||
icon: { textAlign: 'center' },
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
import * as React from 'react';
|
||||
import * as React from 'react'
|
||||
|
||||
import { StyleSheet, View, Text, FlatList } from 'react-native';
|
||||
import type { EmojisByCategory, EmojiType, JsonEmoji } from '../types';
|
||||
import { SingleEmoji } from './SingleEmoji';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore';
|
||||
import { parseEmoji } from '../utils';
|
||||
import { StyleSheet, View, Text, FlatList } from 'react-native'
|
||||
import type { EmojisByCategory, EmojiType, JsonEmoji } from '../types'
|
||||
import { SingleEmoji } from './SingleEmoji'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore'
|
||||
import { parseEmoji } from '../utils'
|
||||
|
||||
const emptyEmoji = {
|
||||
emoji: '',
|
||||
name: 'blank emoji',
|
||||
slug: 'blank_emoji',
|
||||
unicode_version: '0',
|
||||
};
|
||||
}
|
||||
|
||||
export const EmojiCategory = ({
|
||||
item: { title, data },
|
||||
}: {
|
||||
item: EmojisByCategory;
|
||||
}) => {
|
||||
export const EmojiCategory = ({ item: { title, data } }: { item: EmojisByCategory }) => {
|
||||
const {
|
||||
onEmojiSelected,
|
||||
emojiSize,
|
||||
|
@ -28,55 +24,47 @@ export const EmojiCategory = ({
|
|||
headerStyles,
|
||||
translation,
|
||||
categoryPosition,
|
||||
} = React.useContext(KeyboardContext);
|
||||
} = React.useContext(KeyboardContext)
|
||||
|
||||
const { setKeyboardState } = useKeyboardStore();
|
||||
const { setKeyboardState } = useKeyboardStore()
|
||||
|
||||
const [empty, setEmpty] = React.useState<EmojiType[]>([]);
|
||||
const [empty, setEmpty] = React.useState<EmojiType[]>([])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (data.length % numberOfColumns) {
|
||||
const fillWithEmpty = new Array(
|
||||
numberOfColumns - (data.length % numberOfColumns)
|
||||
).fill(emptyEmoji);
|
||||
setEmpty(fillWithEmpty);
|
||||
const fillWithEmpty = new Array(numberOfColumns - (data.length % numberOfColumns)).fill(
|
||||
emptyEmoji
|
||||
)
|
||||
setEmpty(fillWithEmpty)
|
||||
}
|
||||
}, [numberOfColumns, data]);
|
||||
}, [numberOfColumns, data])
|
||||
|
||||
const getItemLayout = (_: EmojiType[] | null | undefined, index: number) => ({
|
||||
length: emojiSize ? emojiSize : 0,
|
||||
offset: emojiSize * Math.ceil(index / numberOfColumns),
|
||||
index,
|
||||
});
|
||||
})
|
||||
|
||||
const handleEmojiPress = React.useCallback(
|
||||
(emoji: JsonEmoji) => {
|
||||
if (emoji.name === 'blank emoji') return;
|
||||
const parsedEmoji = parseEmoji(emoji);
|
||||
onEmojiSelected(parsedEmoji);
|
||||
setKeyboardState({ type: 'RECENT_EMOJI_ADD', payload: emoji });
|
||||
if (emoji.name === 'blank emoji') return
|
||||
const parsedEmoji = parseEmoji(emoji)
|
||||
onEmojiSelected(parsedEmoji)
|
||||
setKeyboardState({ type: 'RECENT_EMOJI_ADD', payload: emoji })
|
||||
},
|
||||
[onEmojiSelected, setKeyboardState]
|
||||
);
|
||||
)
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
(props) => (
|
||||
<SingleEmoji
|
||||
{...props}
|
||||
onPress={() => handleEmojiPress(props.item)}
|
||||
emojiSize={emojiSize}
|
||||
/>
|
||||
<SingleEmoji {...props} onPress={() => handleEmojiPress(props.item)} emojiSize={emojiSize} />
|
||||
),
|
||||
[emojiSize, handleEmojiPress]
|
||||
);
|
||||
)
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { width: width }]}>
|
||||
{!hideHeader && (
|
||||
<Text style={[styles.sectionTitle, headerStyles]}>
|
||||
{translation[title]}
|
||||
</Text>
|
||||
)}
|
||||
{!hideHeader && <Text style={[styles.sectionTitle, headerStyles]}>{translation[title]}</Text>}
|
||||
<FlatList
|
||||
data={[...data, ...empty]}
|
||||
keyExtractor={(emoji) => emoji.name}
|
||||
|
@ -85,19 +73,13 @@ export const EmojiCategory = ({
|
|||
removeClippedSubviews={true}
|
||||
getItemLayout={getItemLayout}
|
||||
ListFooterComponent={() => (
|
||||
<View
|
||||
style={
|
||||
categoryPosition === 'floating'
|
||||
? styles.footerFloating
|
||||
: styles.footer
|
||||
}
|
||||
/>
|
||||
<View style={categoryPosition === 'floating' ? styles.footerFloating : styles.footer} />
|
||||
)}
|
||||
windowSize={20}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -113,4 +95,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
footer: { height: 8 },
|
||||
footerFloating: { height: 70 },
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import * as React from 'react'
|
||||
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
FlatList,
|
||||
useWindowDimensions,
|
||||
Animated,
|
||||
} from 'react-native';
|
||||
import type { CategoryTypes, EmojisByCategory } from '../types';
|
||||
import { EmojiCategory } from './EmojiCategory';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import { Categories } from './Categories';
|
||||
import emojisByGroup from '../assets/emojis.json';
|
||||
import { SearchBar } from './SearchBar';
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore';
|
||||
import { StyleSheet, View, FlatList, useWindowDimensions, Animated } from 'react-native'
|
||||
import type { CategoryTypes, EmojisByCategory } from '../types'
|
||||
import { EmojiCategory } from './EmojiCategory'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import { Categories } from './Categories'
|
||||
import emojisByGroup from '../assets/emojis.json'
|
||||
import { SearchBar } from './SearchBar'
|
||||
import { useKeyboardStore } from '../store/useKeyboardStore'
|
||||
|
||||
const CATEGORY_ELEMENT_WIDTH = 37;
|
||||
const CATEGORY_ELEMENT_WIDTH = 37
|
||||
|
||||
export const EmojiStaticKeyboard = () => {
|
||||
const { width } = useWindowDimensions();
|
||||
const { width } = useWindowDimensions()
|
||||
const {
|
||||
activeCategoryIndex,
|
||||
containerStyles,
|
||||
|
@ -29,41 +23,35 @@ export const EmojiStaticKeyboard = () => {
|
|||
searchPhrase,
|
||||
setActiveCategoryIndex,
|
||||
enableRecentlyUsed,
|
||||
} = React.useContext(KeyboardContext);
|
||||
const { keyboardState } = useKeyboardStore();
|
||||
const flatListRef = React.useRef<FlatList>(null);
|
||||
const scrollNav = React.useRef(new Animated.Value(0)).current;
|
||||
} = React.useContext(KeyboardContext)
|
||||
const { keyboardState } = useKeyboardStore()
|
||||
const flatListRef = React.useRef<FlatList>(null)
|
||||
const scrollNav = React.useRef(new Animated.Value(0)).current
|
||||
|
||||
const getItemLayout = (
|
||||
_: CategoryTypes[] | null | undefined,
|
||||
index: number
|
||||
) => ({
|
||||
const getItemLayout = (_: CategoryTypes[] | null | undefined, index: number) => ({
|
||||
length: width,
|
||||
offset: width * index,
|
||||
index,
|
||||
});
|
||||
})
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
(props) => <EmojiCategory {...props} />,
|
||||
[]
|
||||
);
|
||||
const renderItem = React.useCallback((props) => <EmojiCategory {...props} />, [])
|
||||
React.useEffect(() => {
|
||||
Animated.spring(scrollNav, {
|
||||
toValue: activeCategoryIndex * CATEGORY_ELEMENT_WIDTH,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}, [activeCategoryIndex, scrollNav]);
|
||||
}).start()
|
||||
}, [activeCategoryIndex, scrollNav])
|
||||
|
||||
const renderList = React.useMemo(() => {
|
||||
const data = emojisByGroup.filter((category) => {
|
||||
const title = category.title as CategoryTypes;
|
||||
return !disabledCategory.includes(title);
|
||||
});
|
||||
const title = category.title as CategoryTypes
|
||||
return !disabledCategory.includes(title)
|
||||
})
|
||||
if (keyboardState.recentlyUsed.length && enableRecentlyUsed) {
|
||||
data.push({
|
||||
title: 'recently_used',
|
||||
data: keyboardState.recentlyUsed,
|
||||
});
|
||||
})
|
||||
}
|
||||
data.push({
|
||||
title: 'search',
|
||||
|
@ -71,24 +59,19 @@ export const EmojiStaticKeyboard = () => {
|
|||
.map((group) => group.data)
|
||||
.flat()
|
||||
.filter((emoji) => {
|
||||
if (searchPhrase && searchPhrase.length < 2) return false;
|
||||
return emoji.name.toLowerCase().includes(searchPhrase.toLowerCase());
|
||||
if (searchPhrase && searchPhrase.length < 2) return false
|
||||
return emoji.name.toLowerCase().includes(searchPhrase.toLowerCase())
|
||||
}),
|
||||
});
|
||||
return data;
|
||||
}, [
|
||||
disabledCategory,
|
||||
enableRecentlyUsed,
|
||||
keyboardState.recentlyUsed,
|
||||
searchPhrase,
|
||||
]);
|
||||
})
|
||||
return data
|
||||
}, [disabledCategory, enableRecentlyUsed, keyboardState.recentlyUsed, searchPhrase])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (searchPhrase !== '') {
|
||||
flatListRef.current?.scrollToEnd();
|
||||
setActiveCategoryIndex(renderList.length - 1);
|
||||
flatListRef.current?.scrollToEnd()
|
||||
setActiveCategoryIndex(renderList.length - 1)
|
||||
}
|
||||
}, [renderList, searchPhrase, setActiveCategoryIndex]);
|
||||
}, [renderList, searchPhrase, setActiveCategoryIndex])
|
||||
|
||||
return (
|
||||
<View
|
||||
|
@ -97,8 +80,7 @@ export const EmojiStaticKeyboard = () => {
|
|||
styles.containerShadow,
|
||||
categoryPosition === 'top' && styles.containerReverse,
|
||||
containerStyles,
|
||||
]}
|
||||
>
|
||||
]}>
|
||||
{enableSearchBar && <SearchBar flatListRef={flatListRef} />}
|
||||
<Animated.FlatList
|
||||
extraData={[keyboardState.recentlyUsed.length, searchPhrase]}
|
||||
|
@ -120,8 +102,8 @@ export const EmojiStaticKeyboard = () => {
|
|||
/>
|
||||
<Categories flatListRef={flatListRef} scrollNav={scrollNav} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -137,4 +119,4 @@ const styles = StyleSheet.create({
|
|||
shadowRadius: 5,
|
||||
elevation: 10,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import Flag from '../assets/Flag';
|
||||
import Football from '../assets/Football';
|
||||
import Lightbulb from '../assets/Lightbulb';
|
||||
import Pizza from '../assets/Pizza';
|
||||
import Plane from '../assets/Plane';
|
||||
import Smile from '../assets/Smile';
|
||||
import Trees from '../assets/Trees';
|
||||
import Ban from '../assets/Ban';
|
||||
import Users from '../assets/Users';
|
||||
import Search from '../assets/Search';
|
||||
import Close from '../assets/Close';
|
||||
import Clock from '../assets/Clock';
|
||||
import type { IconNames } from '../types';
|
||||
import { exhaustiveTypeCheck } from '../utils';
|
||||
import * as React from 'react'
|
||||
import Flag from '../assets/Flag'
|
||||
import Football from '../assets/Football'
|
||||
import Lightbulb from '../assets/Lightbulb'
|
||||
import Pizza from '../assets/Pizza'
|
||||
import Plane from '../assets/Plane'
|
||||
import Smile from '../assets/Smile'
|
||||
import Trees from '../assets/Trees'
|
||||
import Ban from '../assets/Ban'
|
||||
import Users from '../assets/Users'
|
||||
import Search from '../assets/Search'
|
||||
import Close from '../assets/Close'
|
||||
import Clock from '../assets/Clock'
|
||||
import type { IconNames } from '../types'
|
||||
import { exhaustiveTypeCheck } from '../utils'
|
||||
|
||||
export const Icon = ({
|
||||
iconName,
|
||||
|
@ -20,39 +20,39 @@ export const Icon = ({
|
|||
normalColor,
|
||||
activeColor,
|
||||
}: {
|
||||
iconName: IconNames | 'Close';
|
||||
isActive: boolean;
|
||||
normalColor: string;
|
||||
activeColor: string;
|
||||
iconName: IconNames | 'Close'
|
||||
isActive: boolean
|
||||
normalColor: string
|
||||
activeColor: string
|
||||
}) => {
|
||||
const color = isActive ? activeColor : normalColor;
|
||||
const color = isActive ? activeColor : normalColor
|
||||
switch (iconName) {
|
||||
case 'Smile':
|
||||
return <Smile fill={color} />;
|
||||
return <Smile fill={color} />
|
||||
case 'Trees':
|
||||
return <Trees fill={color} />;
|
||||
return <Trees fill={color} />
|
||||
case 'Pizza':
|
||||
return <Pizza fill={color} />;
|
||||
return <Pizza fill={color} />
|
||||
case 'Plane':
|
||||
return <Plane fill={color} />;
|
||||
return <Plane fill={color} />
|
||||
case 'Football':
|
||||
return <Football fill={color} />;
|
||||
return <Football fill={color} />
|
||||
case 'Lightbulb':
|
||||
return <Lightbulb fill={color} />;
|
||||
return <Lightbulb fill={color} />
|
||||
case 'Flag':
|
||||
return <Flag fill={color} />;
|
||||
return <Flag fill={color} />
|
||||
case 'Ban':
|
||||
return <Ban fill={color} />;
|
||||
return <Ban fill={color} />
|
||||
case 'Users':
|
||||
return <Users fill={color} />;
|
||||
return <Users fill={color} />
|
||||
case 'Search':
|
||||
return <Search fill={color} />;
|
||||
return <Search fill={color} />
|
||||
case 'Close':
|
||||
return <Close fill={color} />;
|
||||
return <Close fill={color} />
|
||||
case 'Clock':
|
||||
return <Clock fill={color} />;
|
||||
return <Clock fill={color} />
|
||||
default:
|
||||
exhaustiveTypeCheck(iconName);
|
||||
return null;
|
||||
exhaustiveTypeCheck(iconName)
|
||||
return null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
import * as React from 'react';
|
||||
import {
|
||||
Animated,
|
||||
useWindowDimensions,
|
||||
StyleSheet,
|
||||
View,
|
||||
PanResponder,
|
||||
} from 'react-native';
|
||||
import { getHeight } from '../utils';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import * as React from 'react'
|
||||
import { Animated, useWindowDimensions, StyleSheet, View, PanResponder } from 'react-native'
|
||||
import { getHeight } from '../utils'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
|
||||
type KnobProps = {
|
||||
offsetY: Animated.Value;
|
||||
height: Animated.Value;
|
||||
onClose: () => void;
|
||||
};
|
||||
offsetY: Animated.Value
|
||||
height: Animated.Value
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export const Knob = ({ offsetY, height, onClose }: KnobProps) => {
|
||||
const { height: screenHeight } = useWindowDimensions();
|
||||
const { expandedHeight, defaultHeight, knobStyles } =
|
||||
React.useContext(KeyboardContext);
|
||||
const { height: screenHeight } = useWindowDimensions()
|
||||
const { expandedHeight, defaultHeight, knobStyles } = React.useContext(KeyboardContext)
|
||||
|
||||
const panResponder = React.useRef(
|
||||
PanResponder.create({
|
||||
|
@ -34,28 +27,28 @@ export const Knob = ({ offsetY, height, onClose }: KnobProps) => {
|
|||
Animated.spring(offsetY, {
|
||||
useNativeDriver: false,
|
||||
toValue: 0,
|
||||
}).start();
|
||||
}).start()
|
||||
if (gestureState.dy < -50) {
|
||||
Animated.spring(height, {
|
||||
useNativeDriver: false,
|
||||
toValue: getHeight(expandedHeight, screenHeight),
|
||||
}).start();
|
||||
}).start()
|
||||
} else if (gestureState.dy > 150) {
|
||||
height.setValue(getHeight(defaultHeight, screenHeight));
|
||||
offsetY.setValue(0);
|
||||
onClose();
|
||||
height.setValue(getHeight(defaultHeight, screenHeight))
|
||||
offsetY.setValue(0)
|
||||
onClose()
|
||||
} else {
|
||||
Animated.spring(height, {
|
||||
useNativeDriver: false,
|
||||
toValue: getHeight(defaultHeight, screenHeight),
|
||||
}).start();
|
||||
}).start()
|
||||
}
|
||||
},
|
||||
onShouldBlockNativeResponder: () => {
|
||||
return true;
|
||||
return true
|
||||
},
|
||||
})
|
||||
).current;
|
||||
).current
|
||||
|
||||
return (
|
||||
<View {...panResponder.panHandlers}>
|
||||
|
@ -63,8 +56,8 @@ export const Knob = ({ offsetY, height, onClose }: KnobProps) => {
|
|||
<Animated.View style={[styles.knob, knobStyles]} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
panContainer: {
|
||||
|
@ -86,4 +79,4 @@ const styles = StyleSheet.create({
|
|||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowRadius: 5,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as React from 'react';
|
||||
import * as React from 'react'
|
||||
import {
|
||||
SafeAreaView,
|
||||
Modal,
|
||||
|
@ -7,58 +7,47 @@ import {
|
|||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import { useTimeout } from '../hooks/useTimeout';
|
||||
} from 'react-native'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import { useTimeout } from '../hooks/useTimeout'
|
||||
|
||||
type ModalWithBackdropProps = {
|
||||
isOpen: boolean;
|
||||
backdropPress: () => void;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
isOpen: boolean
|
||||
backdropPress: () => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const ModalWithBackdrop = ({
|
||||
isOpen,
|
||||
backdropPress,
|
||||
children,
|
||||
}: ModalWithBackdropProps) => {
|
||||
const { height: screenHeight } = useWindowDimensions();
|
||||
const translateY = React.useRef(new Animated.Value(screenHeight)).current;
|
||||
const { backdropColor } = React.useContext(KeyboardContext);
|
||||
const handleTimeout = useTimeout();
|
||||
export const ModalWithBackdrop = ({ isOpen, backdropPress, children }: ModalWithBackdropProps) => {
|
||||
const { height: screenHeight } = useWindowDimensions()
|
||||
const translateY = React.useRef(new Animated.Value(screenHeight)).current
|
||||
const { backdropColor } = React.useContext(KeyboardContext)
|
||||
const handleTimeout = useTimeout()
|
||||
|
||||
React.useEffect(() => {
|
||||
Animated.spring(translateY, {
|
||||
toValue: isOpen ? 0 : screenHeight,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}, [isOpen, screenHeight, translateY]);
|
||||
}).start()
|
||||
}, [isOpen, screenHeight, translateY])
|
||||
|
||||
const handleClose = () => {
|
||||
Animated.spring(translateY, {
|
||||
toValue: screenHeight,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
handleTimeout(() => backdropPress(), 200);
|
||||
};
|
||||
}).start()
|
||||
handleTimeout(() => backdropPress(), 200)
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal visible={isOpen} animationType="fade" transparent={true}>
|
||||
<TouchableOpacity
|
||||
style={styles.modalContainer}
|
||||
activeOpacity={1}
|
||||
onPress={handleClose}
|
||||
>
|
||||
<View
|
||||
style={[styles.modalContainer, { backgroundColor: backdropColor }]}
|
||||
>
|
||||
<TouchableOpacity style={styles.modalContainer} activeOpacity={1} onPress={handleClose}>
|
||||
<View style={[styles.modalContainer, { backgroundColor: backdropColor }]}>
|
||||
<SafeAreaView style={styles.modalContainer}>
|
||||
<TouchableOpacity activeOpacity={1}>
|
||||
<Animated.View
|
||||
style={{
|
||||
transform: [{ translateY }],
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
{children}
|
||||
</Animated.View>
|
||||
</TouchableOpacity>
|
||||
|
@ -66,8 +55,8 @@ export const ModalWithBackdrop = ({
|
|||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContainer: { flex: 1, justifyContent: 'flex-end' },
|
||||
|
@ -80,4 +69,4 @@ const styles = StyleSheet.create({
|
|||
shadowRadius: 5,
|
||||
elevation: 10,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
import * as React from 'react';
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
FlatList,
|
||||
} from 'react-native';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import { Icon } from './Icon';
|
||||
import * as React from 'react'
|
||||
import { View, StyleSheet, TextInput, TouchableOpacity, FlatList } from 'react-native'
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext'
|
||||
import { Icon } from './Icon'
|
||||
|
||||
type SearchBarProps = {
|
||||
flatListRef: React.RefObject<FlatList>;
|
||||
};
|
||||
flatListRef: React.RefObject<FlatList>
|
||||
}
|
||||
|
||||
export const SearchBar = ({ flatListRef }: SearchBarProps) => {
|
||||
const {
|
||||
|
@ -23,18 +17,18 @@ export const SearchBar = ({ flatListRef }: SearchBarProps) => {
|
|||
searchBarStyles,
|
||||
searchBarTextStyles,
|
||||
searchBarPlaceholderColor,
|
||||
} = React.useContext(KeyboardContext);
|
||||
const inputRef = React.useRef<TextInput>(null);
|
||||
} = React.useContext(KeyboardContext)
|
||||
const inputRef = React.useRef<TextInput>(null)
|
||||
|
||||
const handleSearch = (text: string) => {
|
||||
setSearchPhrase(text);
|
||||
};
|
||||
setSearchPhrase(text)
|
||||
}
|
||||
const clearPhrase = () => {
|
||||
setSearchPhrase('');
|
||||
inputRef.current?.blur();
|
||||
setActiveCategoryIndex(0);
|
||||
flatListRef?.current?.scrollToIndex({ index: 0, animated: true });
|
||||
};
|
||||
setSearchPhrase('')
|
||||
inputRef.current?.blur()
|
||||
setActiveCategoryIndex(0)
|
||||
flatListRef?.current?.scrollToIndex({ index: 0, animated: true })
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, searchBarStyles]}>
|
||||
|
@ -57,8 +51,8 @@ export const SearchBar = ({ flatListRef }: SearchBarProps) => {
|
|||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -78,4 +72,4 @@ const styles = StyleSheet.create({
|
|||
button: {
|
||||
marginRight: 8,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
import * as React from 'react';
|
||||
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
||||
import type { JsonEmoji } from '../types';
|
||||
import * as React from 'react'
|
||||
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'
|
||||
import type { JsonEmoji } from '../types'
|
||||
|
||||
export class SingleEmoji extends React.Component<{
|
||||
item: JsonEmoji;
|
||||
onPress: () => void;
|
||||
emojiSize: number;
|
||||
item: JsonEmoji
|
||||
onPress: () => void
|
||||
emojiSize: number
|
||||
}> {
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
render() {
|
||||
const { item, emojiSize, onPress } = this.props;
|
||||
const { item, emojiSize, onPress } = this.props
|
||||
return (
|
||||
<TouchableOpacity onPress={onPress} style={styles.container}>
|
||||
<View style={styles.iconContainer}>
|
||||
<Text style={{ fontSize: emojiSize }}>{item.emoji}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, padding: 8 },
|
||||
iconContainer: { justifyContent: 'center', alignItems: 'center' },
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,62 +1,52 @@
|
|||
import * as React from 'react';
|
||||
import type { TextStyle, ViewStyle } from 'react-native';
|
||||
import {
|
||||
defaultKeyboardContext,
|
||||
defaultKeyboardValues,
|
||||
} from './KeyboardProvider';
|
||||
import type {
|
||||
CategoryTranslation,
|
||||
EmojiType,
|
||||
CategoryTypes,
|
||||
CategoryPosition,
|
||||
} from '../types';
|
||||
import * as React from 'react'
|
||||
import type { TextStyle, ViewStyle } from 'react-native'
|
||||
import { defaultKeyboardContext, defaultKeyboardValues } from './KeyboardProvider'
|
||||
import type { CategoryTranslation, EmojiType, CategoryTypes, CategoryPosition } from '../types'
|
||||
|
||||
export type OnEmojiSelected = (emoji: EmojiType) => void;
|
||||
export type OnEmojiSelected = (emoji: EmojiType) => void
|
||||
|
||||
export type KeyboardProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onEmojiSelected: OnEmojiSelected;
|
||||
emojiSize?: number;
|
||||
containerStyles?: ViewStyle;
|
||||
knobStyles?: ViewStyle;
|
||||
headerStyles?: TextStyle;
|
||||
expandable?: boolean;
|
||||
hideHeader?: boolean;
|
||||
defaultHeight?: number | string;
|
||||
expandedHeight?: number | string;
|
||||
backdropColor?: string;
|
||||
categoryColor?: string;
|
||||
activeCategoryColor?: string;
|
||||
categoryContainerColor?: string;
|
||||
activeCategoryContainerColor?: string;
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
onEmojiSelected: OnEmojiSelected
|
||||
emojiSize?: number
|
||||
containerStyles?: ViewStyle
|
||||
knobStyles?: ViewStyle
|
||||
headerStyles?: TextStyle
|
||||
expandable?: boolean
|
||||
hideHeader?: boolean
|
||||
defaultHeight?: number | string
|
||||
expandedHeight?: number | string
|
||||
backdropColor?: string
|
||||
categoryColor?: string
|
||||
activeCategoryColor?: string
|
||||
categoryContainerColor?: string
|
||||
activeCategoryContainerColor?: string
|
||||
onCategoryChangeFailed?: (info: {
|
||||
index: number;
|
||||
highestMeasuredFrameIndex: number;
|
||||
averageItemLength: number;
|
||||
}) => void;
|
||||
translation?: CategoryTranslation;
|
||||
disabledCategory?: CategoryTypes[];
|
||||
enableRecentlyUsed?: boolean;
|
||||
categoryPosition?: CategoryPosition;
|
||||
enableSearchBar?: boolean;
|
||||
closeSearchColor?: string;
|
||||
searchBarStyles?: ViewStyle;
|
||||
searchBarTextStyles?: TextStyle;
|
||||
searchBarPlaceholderColor?: string;
|
||||
};
|
||||
index: number
|
||||
highestMeasuredFrameIndex: number
|
||||
averageItemLength: number
|
||||
}) => void
|
||||
translation?: CategoryTranslation
|
||||
disabledCategory?: CategoryTypes[]
|
||||
enableRecentlyUsed?: boolean
|
||||
categoryPosition?: CategoryPosition
|
||||
enableSearchBar?: boolean
|
||||
closeSearchColor?: string
|
||||
searchBarStyles?: ViewStyle
|
||||
searchBarTextStyles?: TextStyle
|
||||
searchBarPlaceholderColor?: string
|
||||
}
|
||||
export type ContextValues = {
|
||||
activeCategoryIndex: number;
|
||||
setActiveCategoryIndex: (index: number) => void;
|
||||
numberOfColumns: number;
|
||||
width: number;
|
||||
searchPhrase: string;
|
||||
setSearchPhrase: (phrase: string) => void;
|
||||
};
|
||||
activeCategoryIndex: number
|
||||
setActiveCategoryIndex: (index: number) => void
|
||||
numberOfColumns: number
|
||||
width: number
|
||||
searchPhrase: string
|
||||
setSearchPhrase: (phrase: string) => void
|
||||
}
|
||||
|
||||
export const KeyboardContext = React.createContext<
|
||||
Required<KeyboardProps> & ContextValues
|
||||
>({
|
||||
export const KeyboardContext = React.createContext<Required<KeyboardProps> & ContextValues>({
|
||||
...defaultKeyboardContext,
|
||||
...defaultKeyboardValues,
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
import * as React from 'react';
|
||||
import { useWindowDimensions } from 'react-native';
|
||||
import {
|
||||
KeyboardProps,
|
||||
ContextValues,
|
||||
KeyboardContext,
|
||||
OnEmojiSelected,
|
||||
} from './KeyboardContext';
|
||||
import en from '../translation/en';
|
||||
import type { EmojiType } from '../types';
|
||||
import * as React from 'react'
|
||||
import { useWindowDimensions } from 'react-native'
|
||||
import { KeyboardProps, ContextValues, KeyboardContext, OnEmojiSelected } from './KeyboardContext'
|
||||
import en from '../translation/en'
|
||||
import type { EmojiType } from '../types'
|
||||
|
||||
type ProviderProps = Partial<KeyboardProps> & {
|
||||
children: React.ReactNode;
|
||||
onEmojiSelected: OnEmojiSelected;
|
||||
};
|
||||
children: React.ReactNode
|
||||
onEmojiSelected: OnEmojiSelected
|
||||
}
|
||||
|
||||
export const defaultKeyboardContext: Required<KeyboardProps> = {
|
||||
open: false,
|
||||
|
@ -32,7 +27,7 @@ export const defaultKeyboardContext: Required<KeyboardProps> = {
|
|||
categoryContainerColor: '#e3dbcd',
|
||||
activeCategoryContainerColor: '#ffffff',
|
||||
onCategoryChangeFailed: (info) => {
|
||||
console.warn(info);
|
||||
console.warn(info)
|
||||
},
|
||||
translation: en,
|
||||
disabledCategory: [],
|
||||
|
@ -43,7 +38,7 @@ export const defaultKeyboardContext: Required<KeyboardProps> = {
|
|||
searchBarStyles: {},
|
||||
searchBarTextStyles: {},
|
||||
searchBarPlaceholderColor: '#00000055',
|
||||
};
|
||||
}
|
||||
|
||||
export const defaultKeyboardValues: ContextValues = {
|
||||
activeCategoryIndex: 0,
|
||||
|
@ -52,25 +47,19 @@ export const defaultKeyboardValues: ContextValues = {
|
|||
width: 0,
|
||||
searchPhrase: '',
|
||||
setSearchPhrase: (_phrase: string) => {},
|
||||
};
|
||||
}
|
||||
|
||||
export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
|
||||
const { width } = useWindowDimensions();
|
||||
const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0);
|
||||
const [searchPhrase, setSearchPhrase] = React.useState('');
|
||||
const { width } = useWindowDimensions()
|
||||
const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0)
|
||||
const [searchPhrase, setSearchPhrase] = React.useState('')
|
||||
const numberOfColumns = React.useRef<number>(
|
||||
Math.floor(
|
||||
width /
|
||||
((props.emojiSize
|
||||
? props.emojiSize
|
||||
: defaultKeyboardContext.emojiSize) *
|
||||
2)
|
||||
)
|
||||
);
|
||||
Math.floor(width / ((props.emojiSize ? props.emojiSize : defaultKeyboardContext.emojiSize) * 2))
|
||||
)
|
||||
React.useEffect(() => {
|
||||
if (props.open) setActiveCategoryIndex(0);
|
||||
setSearchPhrase('');
|
||||
}, [props.open]);
|
||||
if (props.open) setActiveCategoryIndex(0)
|
||||
setSearchPhrase('')
|
||||
}, [props.open])
|
||||
|
||||
const value: Required<KeyboardProps> & ContextValues = {
|
||||
...defaultKeyboardContext,
|
||||
|
@ -82,12 +71,8 @@ export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
|
|||
width,
|
||||
searchPhrase,
|
||||
setSearchPhrase,
|
||||
};
|
||||
return (
|
||||
<KeyboardContext.Provider value={value}>
|
||||
{props.children}
|
||||
</KeyboardContext.Provider>
|
||||
);
|
||||
});
|
||||
}
|
||||
return <KeyboardContext.Provider value={value}>{props.children}</KeyboardContext.Provider>
|
||||
})
|
||||
|
||||
KeyboardProvider.displayName = 'KeyboardProvider';
|
||||
KeyboardProvider.displayName = 'KeyboardProvider'
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import { MutableRefObject, useCallback, useEffect, useRef } from 'react';
|
||||
import { MutableRefObject, useCallback, useEffect, useRef } from 'react'
|
||||
|
||||
export const useTimeout = () => {
|
||||
const timeoutRef = useRef(null) as MutableRefObject<ReturnType<
|
||||
typeof setTimeout
|
||||
> | null>;
|
||||
const timeoutRef = useRef(null) as MutableRefObject<ReturnType<typeof setTimeout> | null>
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
clearTimeout(timeoutRef.current)
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
}, [])
|
||||
|
||||
return useCallback((callback: () => void, time: number) => {
|
||||
timeoutRef.current = setTimeout(callback, time);
|
||||
}, []);
|
||||
};
|
||||
timeoutRef.current = setTimeout(callback, time)
|
||||
}, [])
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { EmojiPicker } from './EmojiPicker';
|
||||
import { EmojiKeyboard } from './EmojiKeyboard';
|
||||
import en from './translation/en';
|
||||
import pl from './translation/pl';
|
||||
import { EmojiPicker } from './EmojiPicker'
|
||||
import { EmojiKeyboard } from './EmojiKeyboard'
|
||||
import en from './translation/en'
|
||||
import pl from './translation/pl'
|
||||
|
||||
export { EmojiKeyboard };
|
||||
export { en, pl };
|
||||
export { EmojiKeyboard }
|
||||
export { en, pl }
|
||||
|
||||
export default EmojiPicker;
|
||||
export default EmojiPicker
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import type { JsonEmoji } from 'src/types';
|
||||
import type { JsonEmoji } from 'src/types'
|
||||
|
||||
export type RecentEmojiState = {
|
||||
recentlyUsed: JsonEmoji[];
|
||||
};
|
||||
recentlyUsed: JsonEmoji[]
|
||||
}
|
||||
|
||||
export type RecentEmojiAction =
|
||||
| { type: 'RECENT_EMOJI_ADD'; payload: JsonEmoji }
|
||||
| { type: 'RECENT_EMOJI_REMOVE'; payload: JsonEmoji }
|
||||
| { type: 'RECENT_EMOJI_CLEAR' };
|
||||
| { type: 'RECENT_EMOJI_CLEAR' }
|
||||
|
||||
export default function recentEmojiReducer(
|
||||
state: RecentEmojiState,
|
||||
|
@ -18,18 +18,18 @@ export default function recentEmojiReducer(
|
|||
return {
|
||||
...state,
|
||||
recentlyUsed: [action.payload, ...filterEmoji(state, action.payload)],
|
||||
};
|
||||
}
|
||||
case 'RECENT_EMOJI_REMOVE':
|
||||
return {
|
||||
...state,
|
||||
recentlyUsed: filterEmoji(state, action.payload),
|
||||
};
|
||||
}
|
||||
case 'RECENT_EMOJI_CLEAR':
|
||||
return { ...state, recentlyUsed: [] };
|
||||
return { ...state, recentlyUsed: [] }
|
||||
default:
|
||||
return state;
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const filterEmoji = (state: RecentEmojiState, emoji: JsonEmoji) =>
|
||||
state.recentlyUsed.filter((usedEmoji) => usedEmoji.emoji !== emoji.emoji);
|
||||
state.recentlyUsed.filter((usedEmoji) => usedEmoji.emoji !== emoji.emoji)
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import recentEmojiReducer, {
|
||||
RecentEmojiAction,
|
||||
RecentEmojiState,
|
||||
} from './RecentEmojiReducer';
|
||||
import recentEmojiReducer, { RecentEmojiAction, RecentEmojiState } from './RecentEmojiReducer'
|
||||
|
||||
// TODO:
|
||||
// - combine Keyboard reducers in future
|
||||
|
||||
export type KeyboardState = RecentEmojiState;
|
||||
export type KeyboardAction = RecentEmojiAction;
|
||||
export default recentEmojiReducer;
|
||||
export type KeyboardState = RecentEmojiState
|
||||
export type KeyboardAction = RecentEmojiAction
|
||||
export default recentEmojiReducer
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import type { KeyboardAction, KeyboardState } from './reducers';
|
||||
import keyboardReducer from './reducers';
|
||||
import { useEffect, useState } from 'react'
|
||||
import type { KeyboardAction, KeyboardState } from './reducers'
|
||||
import keyboardReducer from './reducers'
|
||||
|
||||
let globalKeyboardState: KeyboardState = {
|
||||
recentlyUsed: [],
|
||||
};
|
||||
}
|
||||
|
||||
type KeyboardStateSetter = () => any;
|
||||
const keyboardStateListeners = new Set<KeyboardStateSetter>();
|
||||
type KeyboardStateSetter = () => any
|
||||
const keyboardStateListeners = new Set<KeyboardStateSetter>()
|
||||
|
||||
const setKeyboardState = (action: KeyboardAction) => {
|
||||
globalKeyboardState = keyboardReducer(globalKeyboardState, action);
|
||||
keyboardStateListeners.forEach((listener) => listener());
|
||||
};
|
||||
globalKeyboardState = keyboardReducer(globalKeyboardState, action)
|
||||
keyboardStateListeners.forEach((listener) => listener())
|
||||
}
|
||||
|
||||
export const useKeyboardStore = () => {
|
||||
const [keyboardState, setState] = useState(globalKeyboardState);
|
||||
const [keyboardState, setState] = useState(globalKeyboardState)
|
||||
|
||||
useEffect(() => {
|
||||
const listener = () => setState(globalKeyboardState);
|
||||
keyboardStateListeners.add(listener);
|
||||
const listener = () => setState(globalKeyboardState)
|
||||
keyboardStateListeners.add(listener)
|
||||
return () => {
|
||||
keyboardStateListeners.delete(listener);
|
||||
};
|
||||
}, [keyboardState]);
|
||||
keyboardStateListeners.delete(listener)
|
||||
}
|
||||
}, [keyboardState])
|
||||
|
||||
return { keyboardState, setKeyboardState };
|
||||
};
|
||||
return { keyboardState, setKeyboardState }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { CategoryTranslation } from '../types';
|
||||
import type { CategoryTranslation } from '../types'
|
||||
|
||||
export const en: CategoryTranslation = {
|
||||
recently_used: 'Recently used',
|
||||
|
@ -12,5 +12,5 @@ export const en: CategoryTranslation = {
|
|||
symbols: 'Symbols',
|
||||
flags: 'Flags',
|
||||
search: 'Search',
|
||||
};
|
||||
export default en;
|
||||
}
|
||||
export default en
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { CategoryTranslation } from '../types';
|
||||
import type { CategoryTranslation } from '../types'
|
||||
|
||||
const pl: CategoryTranslation = {
|
||||
recently_used: 'Ostatnio używane',
|
||||
|
@ -12,5 +12,5 @@ const pl: CategoryTranslation = {
|
|||
symbols: 'Symbole',
|
||||
flags: 'Flagi',
|
||||
search: 'Szukaj',
|
||||
};
|
||||
export default pl;
|
||||
}
|
||||
export default pl
|
||||
|
|
44
src/types.ts
44
src/types.ts
|
@ -10,39 +10,39 @@ export const CATEGORIES_NAVIGATION = [
|
|||
{ icon: 'Flag', category: 'flags' },
|
||||
{ icon: 'Clock', category: 'recently_used' },
|
||||
{ icon: 'Search', category: 'search' },
|
||||
] as const;
|
||||
] as const
|
||||
|
||||
export type IconNames = typeof CATEGORIES_NAVIGATION[number]['icon'];
|
||||
export type CategoryTypes = typeof CATEGORIES_NAVIGATION[number]['category'];
|
||||
export type IconNames = typeof CATEGORIES_NAVIGATION[number]['icon']
|
||||
export type CategoryTypes = typeof CATEGORIES_NAVIGATION[number]['category']
|
||||
|
||||
export const CATEGORIES: readonly CategoryTypes[] = CATEGORIES_NAVIGATION.map(
|
||||
({ category }) => category
|
||||
);
|
||||
)
|
||||
|
||||
export type JsonEmoji = {
|
||||
emoji: string;
|
||||
name: string;
|
||||
v: string;
|
||||
};
|
||||
emoji: string
|
||||
name: string
|
||||
v: string
|
||||
}
|
||||
export type EmojiType = {
|
||||
emoji: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
unicode_version: string;
|
||||
};
|
||||
emoji: string
|
||||
name: string
|
||||
slug: string
|
||||
unicode_version: string
|
||||
}
|
||||
|
||||
export type CategoryPosition = 'floating' | 'top' | 'bottom';
|
||||
export type CategoryPosition = 'floating' | 'top' | 'bottom'
|
||||
|
||||
export type CategoryNavigationItem = {
|
||||
icon: IconNames;
|
||||
category: CategoryTypes;
|
||||
};
|
||||
icon: IconNames
|
||||
category: CategoryTypes
|
||||
}
|
||||
|
||||
export type CategoryTranslation = {
|
||||
[key in CategoryTypes]: string;
|
||||
};
|
||||
[key in CategoryTypes]: string
|
||||
}
|
||||
|
||||
export type EmojisByCategory = {
|
||||
title: CategoryTypes;
|
||||
data: EmojiType[];
|
||||
};
|
||||
title: CategoryTypes
|
||||
data: EmojiType[]
|
||||
}
|
||||
|
|
25
src/utils.ts
25
src/utils.ts
|
@ -1,29 +1,22 @@
|
|||
import { CATEGORIES, CategoryTypes, JsonEmoji } from './types';
|
||||
import { CATEGORIES, CategoryTypes, JsonEmoji } from './types'
|
||||
|
||||
export const getHeight = (value: string | number, screenHeight: number) =>
|
||||
typeof value === 'number'
|
||||
? value
|
||||
: (screenHeight / 100) * parseInt(value.replace('%', ''), 10);
|
||||
typeof value === 'number' ? value : (screenHeight / 100) * parseInt(value.replace('%', ''), 10)
|
||||
|
||||
export const exhaustiveTypeCheck = (arg: never, strict = true) => {
|
||||
console.log(`unhandled union case for : ${arg}`);
|
||||
console.log(`unhandled union case for : ${arg}`)
|
||||
if (strict) {
|
||||
throw new Error(`unhandled union case for : ${arg}`);
|
||||
throw new Error(`unhandled union case for : ${arg}`)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const parseEmoji = (emoji: JsonEmoji) => ({
|
||||
name: emoji.name,
|
||||
emoji: emoji.emoji,
|
||||
unicode_version: emoji.v,
|
||||
slug: emoji.name.replace(' ', '_'),
|
||||
});
|
||||
})
|
||||
|
||||
export const getCategoryIndex = (
|
||||
disabledCategory: CategoryTypes[],
|
||||
category: CategoryTypes
|
||||
) => ({
|
||||
index: CATEGORIES.filter((name) => !disabledCategory.includes(name)).indexOf(
|
||||
category
|
||||
),
|
||||
});
|
||||
export const getCategoryIndex = (disabledCategory: CategoryTypes[], category: CategoryTypes) => ({
|
||||
index: CATEGORIES.filter((name) => !disabledCategory.includes(name)).indexOf(category),
|
||||
})
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
{
|
||||
"extends": "./tsconfig",
|
||||
"exclude": ["example"]
|
||||
}
|
||||
}
|
|
@ -1837,6 +1837,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||
|
||||
"@twgdev/prettier-config@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@twgdev/prettier-config/-/prettier-config-1.0.2.tgz#5a313df4341efb2221b5e7b4c52153e86861b1dc"
|
||||
integrity sha512-79UJ8Cp+dIoE8V5g8y2SDvshhGQsGaDkTdY3YVbbMzTUW/Bdv/0AOFASNNGKXy7pfkcukeUD27cgRECAU4Swyg==
|
||||
|
||||
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7":
|
||||
version "7.1.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.14.tgz#faaeefc4185ec71c389f4501ee5ec84b170cc402"
|
||||
|
|
Loading…
Reference in New Issue