: 'react-native-web',\n \u002F\u002F Tree shaking.\n \u002F\u002F https:\u002F\u002Fgithub.com\u002Fgcanti\u002Ffp-ts\u002Fissues\u002F1044#issue-536939300\n 'fp-ts\u002Flib': 'fp-ts\u002Fes6',\n };\n config.resolve.extensions.push('.web.js', '.web.ts', '.web.tsx');\n return config;\n },\n};\n","directory_shortid":null,"id":"b50a2bb6-c174-4941-ac0d-68bc1c4165ab","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"By04ZBGTgU","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"next.config.js","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"\u002F\u002F\u002F \u003Creference types=\"next\" \u002F\u003E\n\u002F\u002F\u002F \u003Creference types=\"next\u002Ftypes\u002Fglobal\" \u002F\u003E\n","directory_shortid":null,"id":"5cbfdee3-6700-40cc-9872-4910babaf384","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"ryaV-rz6gL","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"next-env.d.ts","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import React, { useContext } from 'react';\nimport { theme } from '..\u002Fthemes\u002Ftheme';\n\nconst Theme = React.createContext(theme);\n\nexport const ThemeProvider = Theme.Provider;\n\nexport const useTheme = () =\u003E useContext(Theme);\n","directory_shortid":"r1x4bSGTg8","id":"117eafc6-6427-490b-a137-bdf16591baff","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"rk3NZSGae8","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"useTheme.ts","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import { useCallback, useMemo, useState } from 'react';\n\nexport const useFocus = () =\u003E {\n const [hasFocus, setHasFocus] = useState(false);\n const handleFocus = useCallback(() =\u003E {\n setHasFocus(true);\n }, []);\n const handleBlur = useCallback(() =\u003E {\n setHasFocus(false);\n }, []);\n const focusProps = useMemo(\n () =\u003E ({\n onFocus: handleFocus,\n onBlur: handleBlur,\n }),\n [handleBlur, handleFocus],\n );\n return [hasFocus, focusProps];\n};\n","directory_shortid":"r1x4bSGTg8","id":"e643aa8c-55af-47c2-86b9-d752f70964be","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"rJi4-Bfpl8","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"useFocus.ts","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import * as O from 'fp-ts\u002Flib\u002FOption';\nimport { pipe } from 'fp-ts\u002Flib\u002Fpipeable';\nimport React, { FC, useCallback } from 'react';\nimport { Text, TextInput, View } from 'react-native';\nimport { FieldMaybeOptional, isOptionalField } from 'typescript-fun';\nimport { useFocus } from '..\u002Fhooks\u002FuseFocus';\nimport { useTheme } from '..\u002Fhooks\u002FuseTheme';\nimport { FieldErrorMessage, FieldErrorType } from '.\u002FFieldErrorMessage';\n\nexport const TextInputField: FC\u003C{\n \u002F\u002F A field can be Field, OptionalField or FieldMaybeOptional.\n \u002F\u002F It's generic type. First arg is \"output\" type, the second is error type.\n field: FieldMaybeOptional\u003Cstring, FieldErrorType\u003E;\n label: string;\n secureTextEntry?: boolean;\n}\u003E = ({ field, label, secureTextEntry }) =\u003E {\n const theme = useTheme();\n const [hasFocus, focusProps] = useFocus();\n\n const value = isOptionalField(field)\n ? pipe(\n field.value,\n O.getOrElse(() =\u003E ''),\n )\n : field.value;\n\n const handleChangeText = useCallback(\n (value: string) =\u003E {\n if (isOptionalField(field)) {\n field.onChange(value.length === 0 ? O.none : O.some(value));\n } else {\n field.onChange(value);\n }\n },\n [field],\n );\n\n const handleSubmitEditing = useCallback(\n () =\u003E {\n field.submit();\n },\n [field],\n );\n\n return (\n \u003CView\u003E\n \u003CView style={theme.row}\u003E\n \u003CText style={theme.textInputLabel}\u003E{label}\u003C\u002FText\u003E\n {!isOptionalField(field) && (\n \u003CText style={theme.textInputIsRequiredAsterisk}\u003E *\u003C\u002FText\u003E\n )}\n \u003C\u002FView\u003E\n \u003CTextInput\n {...focusProps}\n onChangeText={handleChangeText}\n onSubmitEditing={handleSubmitEditing}\n style={[\n theme.textInput,\n hasFocus && theme.textInputFocus,\n field.isInvalid && theme.textInputInvalid,\n ]}\n value={value}\n secureTextEntry={secureTextEntry}\n blurOnSubmit={false}\n ref={field.ref}\n \u002F\u003E\n \u003CFieldErrorMessage error={field.firstError} \u002F\u003E\n \u003C\u002FView\u003E\n );\n};\n","directory_shortid":"H14WHzTxU","id":"4f54deb0-4ad4-4351-a67e-3d009c4cd50e","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"r1qVZHMag8","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"TextInputField.tsx","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import { constNull } from 'fp-ts\u002Flib\u002Ffunction';\nimport * as O from 'fp-ts\u002Flib\u002FOption';\nimport { pipe } from 'fp-ts\u002Flib\u002Fpipeable';\nimport React, { FC } from 'react';\nimport { Text } from 'react-native';\nimport { useTheme } from '..\u002Fhooks\u002FuseTheme';\n\n\u002F\u002F TypeScript compiler ensures all errors are translated.\nconst fieldErrorMessages = {\n EmailString: 'This is not valid email.',\n UniqueEmail: 'This email already exists.',\n Max512String: 'Too long. Max 512 chars.',\n Max64String: 'Too long. Max 64 chars.',\n Min6String: 'Too short. Min 6 chars.',\n NonEmptyString: 'Can not be empty.',\n PhoneString: 'This is not valid phone.',\n TrimmedString: 'Please delete leading and trailing whitespaces.',\n};\n\nexport type FieldErrorType = keyof typeof fieldErrorMessages;\n\nexport const FieldErrorMessage: FC\u003C{\n error: O.Option\u003CFieldErrorType\u003E;\n}\u003E = ({ error }) =\u003E {\n const theme = useTheme();\n return pipe(\n error,\n \u002F\u002F We can use intl.formatMessage here.\n O.map(error =\u003E fieldErrorMessages[error]),\n O.fold(constNull, message =\u003E (\n \u003CText style={theme.formErrorMessage}\u003E{message}\u003C\u002FText\u003E\n )),\n );\n};\n","directory_shortid":"H14WHzTxU","id":"82a5d290-0737-4d42-abd1-f852a1b1409f","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"H1F4-SGaxU","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"FieldErrorMessage.tsx","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import React, { FC, useMemo } from 'react';\nimport { CheckBox, Platform, StyleSheet, Text, View } from 'react-native';\nimport { Field } from 'typescript-fun';\nimport { useFocus } from '..\u002Fhooks\u002FuseFocus';\nimport { useTheme } from '..\u002Fhooks\u002FuseTheme';\nimport { FieldErrorType } from '.\u002FFieldErrorMessage';\n\nexport const CheckBoxField: FC\u003C{\n field: Field\u003Cboolean, FieldErrorType\u003E;\n label: string;\n}\u003E = ({ field, label }) =\u003E {\n const theme = useTheme();\n const [hasFocus, focusProps] = useFocus();\n const { color, ...style } = useMemo(\n () =\u003E StyleSheet.flatten(theme.checkBox),\n [theme.checkBox],\n );\n return (\n \u003CView style={theme.row}\u003E\n \u003CCheckBox\n {...focusProps}\n {...Platform.select({ web: { color } })}\n value={field.value}\n onValueChange={field.onChange}\n style={[style, hasFocus && theme.checkBoxFocus]}\n \u002F\u003E\n \u003CText style={theme.checkBoxLabel}\u003E{label}\u003C\u002FText\u003E\n \u003C\u002FView\u003E\n );\n};\n","directory_shortid":"H14WHzTxU","id":"1284eec8-4b5b-4f9a-8a5e-8912eff63749","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"Syd4bHGalI","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"CheckBoxField.tsx","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"import React, { FC, useCallback } from 'react';\nimport { Text, TouchableOpacity } from 'react-native';\nimport { useFocus } from '..\u002Fhooks\u002FuseFocus';\nimport { useTheme } from '..\u002Fhooks\u002FuseTheme';\n\nexport const Button: FC\u003C{\n label: string;\n disabled?: boolean;\n onPress: () =\u003E void;\n}\u003E = ({ label, disabled, onPress }) =\u003E {\n const theme = useTheme();\n const [hasFocus, focusProps] = useFocus();\n const handlePress = useCallback(() =\u003E {\n \u002F\u002F We do not use disabled prop, because it disables also focus and blur events.\n if (!disabled) onPress();\n }, [disabled, onPress]);\n\n return (\n \u003CTouchableOpacity\n {...focusProps}\n accessibilityRole=\"button\"\n style={[\n theme.button,\n hasFocus && theme.buttonFocus,\n disabled && theme.buttonDisabled,\n ]}\n onPress={handlePress}\n \u003E\n \u003CText style={theme.buttonText}\u003E{label}\u003C\u002FText\u003E\n \u003C\u002FTouchableOpacity\u003E\n );\n};\n","directory_shortid":"H14WHzTxU","id":"8ef93c95-e7e0-43ef-914c-18d2e6ce5639","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"HyDNbrf6xL","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"Button.tsx","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"module.exports = {\n presets: ['next\u002Fbabel'],\n plugins: [['react-native-web', { commonjs: true }]],\n};\n","directory_shortid":null,"id":"9eac37fc-82a9-4aa3-b9e2-b853c3934dd2","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"SyIN-HG6eL","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"babel.config.js","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"{\n \"name\": \"signup-form-react-native-web\",\n \"displayName\": \"signup-form-react-native-web\"\n}\n","directory_shortid":null,"id":"0e04cdb0-169a-49a0-9ab8-c4e4d32ea0aa","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"HJrEbSMpeU","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":"app.json","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":"{\n \"singleQuote\": true,\n \"bracketSpacing\": true,\n \"semi\": true,\n \"trailingComma\": \"all\"\n}\n","directory_shortid":null,"id":"8ad7ea8a-441f-4020-94dc-a3df4fc284e8","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"ryNEWHG6x8","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":".prettierrc","updated_at":"2020-01-15T22:40:59","upload_id":null},{"code":".DS_Store\n.next\ndist\nnode_modules","directory_shortid":null,"id":"debb24fe-9930-40bf-a358-db6dd19902cf","inserted_at":"2020-01-15T22:40:59","is_binary":false,"shortid":"Sk7EZSfTx8","source_id":"d31b660f-a07e-4f0f-a916-63d6b777c2cb","title":".gitignore","updated_at":"2020-01-15T22:40:59","upload_id":null}],"author":null,"preview_secret":null,"git":{"branch":"master","commit_sha":"2d51d3c60783778e1e697318dbce54d0af5a4c3f","path":"examples\u002Fsignup-form-react-native-web","repo":"typescript-fun","username":"typescript-fun"},"original_git_commit_sha":null,"view_count":2799,"description":null,"version":11};