diff --git a/README.md b/README.md index 013bad8..90cd33b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,60 @@ const JustAFlag = () => ``` ### Props +#### from (optional) +#### Type: `{}` +#### Default value: `await import('./flags')` (all available flags). +The flags you want to use. + +By default, [all available flags](https://github.com/frostney/react-native-flags/blob/master/flags/index.js) are bundled/imported. +However, *bundling all flags is discouraged*, because you might not need all of them. +Instead, you could import your flags beforehand and use this prop to pass your flags. + +Below are a few examples: + +Load all flat 32 flags: +```javascript +import Flag from 'react-native-flags'; +import * as allFlatFlags32 from 'react-native-flags/flags/flat/32'; + +const JustAFlag = ({ code }) => + +``` + +Load all shiny 16/24/32/48/64 flags: +```javascript +import Flag from 'react-native-flags'; +import * as allShinyFlags from 'react-native-flags/flags/shiny'; + +const JustAFlag = ({ code, size }) => + +``` + +Load all flat/shiny 16/24/32/48/64 flags. +This is the same as removing the `from` prop: +```javascript +import Flag from 'react-native-flags'; +import * as allFlags from 'react-native-flags/flags'; + +const JustAFlag = ({ code, size, type }) => + +``` + #### code #### Type: `String` The ISO code of a flag, for example "DE", "FR" or "GB" diff --git a/index.js b/index.js index 86940fe..6a5d1df 100644 --- a/index.js +++ b/index.js @@ -1,23 +1,79 @@ // @flow -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Image } from 'react-native'; -import * as flags from './flags'; type Props = { + from?: {}, size: 16 | 24 | 32 | 48 | 64, code: string, type?: 'flat' | 'shiny', style?: any, }; -const Flag = ({ size = 64, code, type = 'shiny', style }: Props) => { - const flag = flags[type][`icons${size}`][code]; - const unknownFlag = flags[type][`icons${size}`]['unknown']; +/** + * Find a flag exported from ./flags' sub-directories + * (or directories that match the same structure) + * and return it. + * + * @example + * import * as flags from './flags'; + * import * as flatFlags from './flags/flat'; + * import * as flatFlags16 from './flags/flat/16'; + * + * const emptyFlags = {}; + * const props = { type: 'flat', size: 16, code: 'ZW' }; + * + * getFlag(flatFlags16, props) === getFlag(flatFlags, props); // > true + * getFlag(flatFlags, props) === getFlag(flags, props); // > true + * getFlag(emptyFlags, props); // > null + */ +const getFlag = (flags: {}, { type, size, code }: { + type: string, + size: number, + code: string +}) => { + const sizeKey = `icons${size}`; + + return (type in flags // ./flags was imported. + ? flags[type][sizeKey][code] + : sizeKey in flags // ./flags/{type} was imported. + ? flags[sizeKey][code] + : code in flags // ./flags/{type}/{size} was imported. + ? flags[code] + : null + ); +}; + +const Flag = ({ from, size = 64, code, type = 'shiny', style }: Props) => { + // @TODO Set an initial value. + const [source, setSource] = useState(); + + // Load flags asynchronously. + useEffect(() => { + let isMounted = true; + + (async () => { + // Use our flags or import all of them. + const flags = from || await import('./flags'); + const flag = getFlag(flags, { type, size, code }); + const unknownFlag = getFlag(flags, { type, size, code: 'unknown' }); + + if (isMounted) { + setSource(flag || unknownFlag); + } + })(); + + return () => { + // Anti-pattern. + // @TODO Abort import instead. + isMounted = false; + }; + }, [from, type, size, code, setSource]); return ( );