feat: converts to TypeScript (#642)

This converts the codebase to TypeScript. Compilation and bundling is done with tsdx. This will
hopefully ensure our types are more accurate in the future.
This commit is contained in:
Dylan Vann 2020-03-08 20:44:22 -04:00 committed by GitHub
parent e24c931826
commit ac117060eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1669 additions and 420 deletions

View File

@ -1,3 +0,0 @@
{
"presets": ["module:metro-react-native-babel-preset"]
}

1
.gitignore vendored
View File

@ -38,6 +38,7 @@ example/android/app/src/main/gen
# build
react-native-fast-image-*.tgz
dist/
# coverage reports
coverage

View File

@ -1,28 +0,0 @@
# Docs
docs
# Build
android/build
ios/build
react-native-fast-image-*.tgz
# Examples
ReactNativeFastImageExample
ReactNativeFastImageExampleServer
# Tests
.circleci
__snapshots__
*.test.js
# Configs
.babelrc
.gitignore
.npmignore
prettier.config.js
yarn.lock
babel.config.js
jest.config.js
# IDE
.idea/

View File

@ -16,7 +16,7 @@
"@react-navigation/stack": "^5.1.0",
"react": "16.9.0",
"react-native": "0.61.5",
"react-native-fast-image": "^7.0.2",
"react-native-fast-image": "../react-native-fast-image-8.0.0.tgz",
"react-native-gesture-handler": "^1.6.0",
"react-native-image-picker": "^2.3.1",
"react-native-image-progress": "^1.1.1",

View File

@ -5368,10 +5368,9 @@ react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==
react-native-fast-image@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-7.0.2.tgz#e06b21f42f4a9786eaa86f3db35d919070fb8403"
integrity sha512-MfuzJbC0RjYobR2gFCdqe1I7jvNOCfDkjQ7VGOHXniqjohhULMkcWNBE9Umovi9Dx93lJ6t5utcE2wf/09zvlg==
react-native-fast-image@../react-native-fast-image-8.0.0.tgz:
version "8.0.0"
resolved "../react-native-fast-image-8.0.0.tgz#9c62a27bbc643ce1cdae634b8a9a7252ced7ed00"
react-native-gesture-handler@^1.6.0:
version "1.6.0"

View File

@ -19,30 +19,35 @@
},
"license": "(MIT AND Apache-2.0)",
"author": "Dylan Vann <dylan@dylanvann.com> (https://dylanvann.com)",
"main": "src/index.js",
"types": "src/index.d.ts",
"main": "dist/index.js",
"module": "dist/react-native-fast-image.esm.js",
"typings": "dist/index.d.ts",
"files": [
"android",
"!android/build",
"ios",
"!ios/build",
"src",
"dist",
"RNFastImage.podspec"
],
"scripts": {
"build": "exit 0",
"build": "tsdx build && cp src/index.js.flow dist/index.js.flow",
"commit": "git-cz",
"format": "yarn prettier --write",
"lint": "eslint src/**/*.js",
"prettier": "prettier './**/*.{js,d.ts,js.flow,yml}'",
"lint": "tsdx lint src",
"semantic-release": "semantic-release",
"test": "jest ./src/*.js"
"test": "jest ./src/*.tsx"
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
},
"prettier": {
"semi": false,
"singleQuote": true,
"tabWidth": 4,
"trailingComma": "all"
},
"jest": {
"modulePathIgnorePatterns": [
"ReactNativeFastImageExample*",
@ -59,6 +64,8 @@
"@semantic-release/git": "^9.0.0",
"@semantic-release/npm": "^7.0.3",
"@semantic-release/release-notes-generator": "^9.0.1",
"@types/react": "^16.9.23",
"@types/react-native": "^0.61.17",
"babel-jest": "^24.9.0",
"commitizen": "^4.0.3",
"cz-conventional-changelog": "^3.1.0",
@ -75,6 +82,7 @@
"react-native": "0.61.5",
"react-test-renderer": "16.9.0",
"semantic-release": "^17.0.4",
"tsdx": "^0.12.3",
"typescript": "^3.8.3"
},
"peerDependencies": {

View File

@ -1,6 +0,0 @@
module.exports = {
semi: false,
singleQuote: true,
trailingComma: 'all',
tabWidth: 4,
}

154
src/index.d.ts vendored
View File

@ -1,154 +0,0 @@
import * as React from 'react'
import {
FlexStyle,
LayoutChangeEvent,
ShadowStyleIOS,
StyleProp,
TransformsStyle,
} from 'react-native'
declare namespace FastImage {
namespace priority {
type low = 'low'
type normal = 'normal'
type high = 'high'
}
namespace resizeMode {
type contain = 'contain'
type cover = 'cover'
type stretch = 'stretch'
type center = 'center'
}
namespace cacheControl {
type cacheOnly = 'cacheOnly'
type immutable = 'immutable'
type web = 'web'
}
export type Priority =
| FastImage.priority.low
| FastImage.priority.normal
| FastImage.priority.high
export type ResizeMode =
| FastImage.resizeMode.contain
| FastImage.resizeMode.cover
| FastImage.resizeMode.stretch
| FastImage.resizeMode.center
export type Cache =
| FastImage.cacheControl.cacheOnly
| FastImage.cacheControl.immutable
| FastImage.cacheControl.web
}
export type FastImageSource = {
uri?: string
headers?: { [key: string]: string }
priority?: FastImage.Priority
cache?: FastImage.Cache
}
export interface ImageStyle extends FlexStyle, TransformsStyle, ShadowStyleIOS {
backfaceVisibility?: 'visible' | 'hidden'
borderBottomLeftRadius?: number
borderBottomRightRadius?: number
backgroundColor?: string
borderColor?: string
borderWidth?: number
borderRadius?: number
borderTopLeftRadius?: number
borderTopRightRadius?: number
overlayColor?: string
tintColor?: string
opacity?: number
}
export interface OnLoadEvent {
nativeEvent: {
width: number
height: number
}
}
export interface OnProgressEvent {
nativeEvent: {
loaded: number
total: number
}
}
export interface FastImageProperties {
source: FastImageSource | number
resizeMode?: FastImage.ResizeMode
fallback?: boolean
onLoadStart?(): void
onProgress?(event: OnProgressEvent): void
onLoad?(event: OnLoadEvent): void
onError?(): void
onLoadEnd?(): void
/**
* onLayout function
*
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout?: (event: LayoutChangeEvent) => void
/**
*
* Style
*/
style?: StyleProp<ImageStyle>
/**
* TintColor
*
* If supplied, changes the color of all the non-transparent pixels to the given color.
*/
tintColor?: number | string
/**
* A unique identifier for this element to be used in UI Automation testing scripts.
*/
testID?: string
}
interface FastImageStatic extends React.ComponentClass<FastImageProperties> {
resizeMode: {
contain: FastImage.resizeMode.contain
cover: FastImage.resizeMode.cover
stretch: FastImage.resizeMode.stretch
center: FastImage.resizeMode.center
}
priority: {
low: FastImage.priority.low
normal: FastImage.priority.normal
high: FastImage.priority.high
}
cacheControl: {
cacheOnly: FastImage.cacheControl.cacheOnly
immutable: FastImage.cacheControl.immutable
web: FastImage.cacheControl.web
}
preload(sources: FastImageSource[]): void
}
declare var FastImage: FastImageStatic
type FastImage = FastImageStatic
export default FastImage

View File

@ -1,122 +0,0 @@
import React, { forwardRef, memo } from 'react'
import {
View,
Image,
NativeModules,
requireNativeComponent,
StyleSheet,
} from 'react-native'
const FastImageViewNativeModule = NativeModules.FastImageView
function FastImageBase({
source,
tintColor,
onLoadStart,
onProgress,
onLoad,
onError,
onLoadEnd,
style,
children,
fallback,
forwardedRef,
...props
}) {
const resolvedSource = Image.resolveAssetSource(source)
if (fallback) {
return (
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<Image
{...props}
tintColor={tintColor}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onLoadStart={onLoadStart}
onProgress={onProgress}
onLoad={onLoad}
onError={onError}
onLoadEnd={onLoadEnd}
/>
{children}
</View>
)
}
return (
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<FastImageView
{...props}
tintColor={tintColor}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
{children}
</View>
)
}
const FastImageMemo = memo(FastImageBase)
const FastImage = forwardRef((props, ref) => (
<FastImageMemo forwardedRef={ref} {...props} />
))
FastImage.displayName = 'FastImage'
const styles = StyleSheet.create({
imageContainer: {
overflow: 'hidden',
},
})
FastImage.resizeMode = {
contain: 'contain',
cover: 'cover',
stretch: 'stretch',
center: 'center',
}
FastImage.priority = {
// lower than usual.
low: 'low',
// normal, the default.
normal: 'normal',
// higher than usual.
high: 'high',
}
FastImage.cacheControl = {
// Ignore headers, use uri as cache key, fetch only if not in cache.
immutable: 'immutable',
// Respect http headers, no aggressive caching.
web: 'web',
// Only load from cache.
cacheOnly: 'cacheOnly',
}
FastImage.preload = sources => {
FastImageViewNativeModule.preload(sources)
}
FastImage.defaultProps = {
resizeMode: FastImage.resizeMode.cover,
}
const FastImageView = requireNativeComponent('FastImageView', FastImage, {
nativeOnly: {
onFastImageLoadStart: true,
onFastImageProgress: true,
onFastImageLoad: true,
onFastImageError: true,
onFastImageLoadEnd: true,
},
})
export default FastImage

View File

@ -1,7 +1,7 @@
import { StyleSheet } from 'react-native'
import React from 'react'
import renderer from 'react-test-renderer'
import FastImage from './index.js'
import FastImage from './index'
const style = StyleSheet.create({ image: { width: 44, height: 44 } })

235
src/index.tsx Normal file
View File

@ -0,0 +1,235 @@
import React, { forwardRef, memo } from 'react'
import {
View,
Image,
NativeModules,
requireNativeComponent,
StyleSheet,
FlexStyle,
LayoutChangeEvent,
ShadowStyleIOS,
StyleProp,
TransformsStyle,
} from 'react-native'
const FastImageViewNativeModule = NativeModules.FastImageView
type ResizeMode = 'contain' | 'cover' | 'stretch' | 'center'
const resizeMode = {
contain: 'contain',
cover: 'cover',
stretch: 'stretch',
center: 'center',
} as const
type Priority = 'low' | 'normal' | 'high'
const priority = {
low: 'low',
normal: 'normal',
high: 'high',
} as const
type Cache = 'low' | 'normal' | 'high'
const cacheControl = {
// Ignore headers, use uri as cache key, fetch only if not in cache.
immutable: 'immutable',
// Respect http headers, no aggressive caching.
web: 'web',
// Only load from cache.
cacheOnly: 'cacheOnly',
} as const
export type Source = {
uri?: string
headers?: { [key: string]: string }
priority?: Priority
cache?: Cache
}
export interface OnLoadEvent {
nativeEvent: {
width: number
height: number
}
}
export interface OnProgressEvent {
nativeEvent: {
loaded: number
total: number
}
}
export interface ImageStyle extends FlexStyle, TransformsStyle, ShadowStyleIOS {
backfaceVisibility?: 'visible' | 'hidden'
borderBottomLeftRadius?: number
borderBottomRightRadius?: number
backgroundColor?: string
borderColor?: string
borderWidth?: number
borderRadius?: number
borderTopLeftRadius?: number
borderTopRightRadius?: number
overlayColor?: string
tintColor?: string
opacity?: number
}
export interface FastImageProps {
source: Source | number
resizeMode?: ResizeMode
fallback?: boolean
onLoadStart?(): void
onProgress?(event: OnProgressEvent): void
onLoad?(event: OnLoadEvent): void
onError?(): void
onLoadEnd?(): void
/**
* onLayout function
*
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout?: (event: LayoutChangeEvent) => void
/**
*
* Style
*/
style?: StyleProp<ImageStyle>
/**
* TintColor
*
* If supplied, changes the color of all the non-transparent pixels to the given color.
*/
tintColor?: number | string
/**
* A unique identifier for this element to be used in UI Automation testing scripts.
*/
testID?: string
/**
* Render children within the image.
*/
children?: React.ReactNode
}
function FastImageBase({
source,
tintColor,
onLoadStart,
onProgress,
onLoad,
onError,
onLoadEnd,
style,
fallback,
children,
resizeMode = 'cover',
forwardedRef,
...props
}: FastImageProps & { forwardedRef: React.Ref<any> }) {
const resolvedSource = Image.resolveAssetSource(source as any)
if (fallback) {
return (
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<Image
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onLoadStart={onLoadStart}
onProgress={onProgress}
onLoad={onLoad as any}
onError={onError}
onLoadEnd={onLoadEnd}
resizeMode={resizeMode}
/>
{children}
</View>
)
}
return (
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<FastImageView
{...props}
tintColor={tintColor}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
resizeMode={resizeMode}
/>
{children}
</View>
)
}
const FastImageMemo = memo(FastImageBase)
const FastImageComponent: React.ComponentType<FastImageProps> = forwardRef(
(props: FastImageProps, ref: React.Ref<any>) => (
<FastImageMemo forwardedRef={ref} {...props} />
),
)
FastImageComponent.displayName = 'FastImage'
interface FastImageStaticProperties {
resizeMode: typeof resizeMode
priority: typeof priority
cacheControl: typeof cacheControl
preload: (sources: Source[]) => void
}
const FastImage: React.Component<FastImageProps> &
FastImageStaticProperties = FastImageComponent as any
FastImage.resizeMode = resizeMode
FastImage.cacheControl = cacheControl
FastImage.priority = priority
FastImage.preload = (sources: Source[]) =>
FastImageViewNativeModule.preload(sources)
const styles = StyleSheet.create({
imageContainer: {
overflow: 'hidden',
},
})
// Types of requireNativeComponent are not correct.
const FastImageView = (requireNativeComponent as any)(
'FastImageView',
FastImage,
{
nativeOnly: {
onFastImageLoadStart: true,
onFastImageProgress: true,
onFastImageLoad: true,
onFastImageError: true,
onFastImageLoadEnd: true,
},
},
)
export default FastImage

30
tsconfig.json Normal file
View File

@ -0,0 +1,30 @@
{
"include": ["src", "types", "test"],
"compilerOptions": {
"target": "es5",
"module": "esnext",
"lib": ["dom", "esnext"],
"importHelpers": true,
"declaration": true,
"sourceMap": true,
"rootDir": "./",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"*": ["src/*", "node_modules/*"]
},
"jsx": "react",
"esModuleInterop": true
}
}

1475
yarn.lock

File diff suppressed because it is too large Load Diff