diff --git a/README.md b/README.md index 3bea019..e38ec36 100644 --- a/README.md +++ b/README.md @@ -2,39 +2,6 @@ [![NPM](https://nodei.co/npm/react-native-parallax-scroll-view.png)](https://www.npmjs.com/package/react-native-parallax-scroll-view) -# Rodrigocs - Animated Driver - -This component now uses Native Driver by default. -Remember to pass a Animated component to `renderScrollComponent`, by default it has `Animated.ScrollView` - -# Example -```js -import ParallaxScrollView from 'react-native-parallax-scroll-view'; -import CustomScrollView from 'custom-scroll-view' - -const AnimatedCustomScrollView = Animated.createAnimatedComponent(CustomScrollView) - -render() { - return ( - } - renderScrollComponent={() => } - renderForeground={() => ( - - Hello World! - - )}> - - Scroll me - - - ); -} -``` - # react-native-parallax-scroll-view A `ScrollView`-like component that: @@ -101,28 +68,30 @@ All of the properties of `ScrollView` are supported. Please refer to the The `ParallaxScrollView` component adds a few additional properties, as described below. -| Property | Type | Required | Description | -| -------- | ---- | -------- | ----------- | -| `backgroundColor` | `string` | No | The color of the header background. Defaults to `#000`) | -| `backgroundScrollSpeed` | `number` | No | The speed factor that the background moves at relative to the foreground. Defaults to 5. | -| `contentBackgroundColor` | `string` | No | This is the background color of the content. (Defaults to `'#fff'`) | -| `fadeOutForeground` | `bool` | No | If `true`, the foreground will fade out as the user scrolls up. (Defaults to `true`) | -| `onChangeHeaderVisibility` | `func` | No | A callback function that is invoked when the parallax header is hidden or shown (as the user is scrolling). Function is called with a `boolean` value to indicate whether header is visible or not. | -| **`parallaxHeaderHeight`** | `number` | **Yes** |This is the height of parallax header. | -| `renderBackground` | `func` | No | This renders the background of the parallax header. Can be used to display cover images for example. (Defaults to an opaque background using `backgroundColor`) | -| `renderContentBackground` | `func` | No | This renders the background of the content. Can be used to display cover images for example. (Defaults to a non-visible `View`) | -| `renderFixedHeader` | `func` | No | This renders an optional fixed header that will always be visible and fixed to the top of the view (and sticky header). You should set its height and width appropriately. | -| `renderForeground` | `func` | No |This renders the foreground header that moves at same speed as scroll content. | -| `renderScrollComponent` | `func` | No | A function with input `props` and outputs an `Animated.ScrollView`-like component in which the content is rendered. This is useful if you want to provide your own scrollable component, remember however to make it an Animated component. (See: [https://github.com/exponentjs/react-native-scrollable-mixin](https://github.com/exponentjs/react-native-scrollable-mixin)) (By default, returns a `Animated.ScrollView` with the given props) | -| `renderStickyHeader` | `func` | No | This renders an optional sticky header that will stick to the top of view when parallax header scrolls up. | -| `stickyHeaderHeight` | `number` | If `renderStickyHeader` is used | If `renderStickyHeader` is set, then its height must be specified. | -| `contentContainerStyle` | `object` | No | These styles will be applied to the scroll view content container which wraps all of the child views. (same as for [ScrollView](https://facebook.github.io/react-native/docs/scrollview.html#contentcontainerstyle)) | -| `outputScaleValue` | `number` | No | The value for the scale interpolation output value, default `5` | -| `parallaxHeaderContainerStyle` | `object` | No | These styles will be applied to the parallax header view content container | -| `parallaxHeaderStyle` | `object` | No | These styles will be applied to the parallax header view content | -| `backgroundImageStyle` | `object` | No | These styles will be applied to the background image header view content | -| `stickyHeaderStyle` | `object` | No | These styles will be applied to the sticky headerStyle view content | -| `scrollEvent` | `func` | No | Callback to recieve the animated scroll event values | +| Property | Type | Required | Description | +|--------------------------------|----------| -------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `backgroundColor` | `string` | No | The color of the header background. Defaults to `#000`) | +| `backgroundScrollSpeed` | `number` | No | The speed factor that the background moves at relative to the foreground. Defaults to `5`. | +| `contentBackgroundColor` | `string` | No | This is the background color of the content. (Defaults to `'#fff'`) | +| `fadeOutForeground` | `bool` | No | If `true`, the foreground will fade out as the user scrolls up. (Defaults to `true`) | +| `fadeOutBackground` | `bool` | No | If `true`, the background will fade out as the user scrolls up. (Defaults to `false`) | +| `onChangeHeaderVisibility` | `func` | No | A callback function that is invoked when the parallax header is hidden or shown (as the user is scrolling). Function is called with a `boolean` value to indicate whether header is visible or not. | +| **`parallaxHeaderHeight`** | `number` | **Yes** | This is the height of parallax header. | +| `renderBackground` | `func` | No | This renders the background of the parallax header. Can be used to display cover images for example. (Defaults to an opaque background using `backgroundColor`) | +| `renderContentBackground` | `func` | No | This renders the background of the content. Can be used to display cover images for example. (Defaults to a non-visible `View`) | +| `renderFixedHeader` | `func` | No | This renders an optional fixed header that will always be visible and fixed to the top of the view (and sticky header). You should set its height and width appropriately. | +| **`renderForeground`** | `func` | **Yes** | This renders the foreground header that moves at same speed as scroll content. | +| `renderScrollComponent` | `func` | No | A function with input `props` and outputs an `Animated.ScrollView`-like component in which the content is rendered. This is useful if you want to provide your own scrollable component, remember however to make it an Animated component. (See: [https://github.com/exponentjs/react-native-scrollable-mixin](https://github.com/exponentjs/react-native-scrollable-mixin)) (By default, returns a `Animated.ScrollView` with the given props) | +| `renderStickyHeader` | `func` | No | This renders an optional sticky header that will stick to the top of view when parallax header scrolls up. | +| `stickyHeaderHeight` | `number` | If `renderStickyHeader` is used | If `renderStickyHeader` is set, then its height must be specified. | +| `contentContainerStyle` | `object` | No | These styles will be applied to the scroll view content container which wraps all of the child views. (same as for [ScrollView](https://facebook.github.io/react-native/docs/scrollview.html#contentcontainerstyle)) | +| `outputScaleValue` | `number` | No | The value for the scale interpolation output value, default `5` | +| `parallaxHeaderContainerStyle` | `object` | No | These styles will be applied to the parallax header view content container | +| `parallaxHeaderStyle` | `object` | No | These styles will be applied to the parallax header view content | +| `backgroundImageStyle` | `object` | No | These styles will be applied to the background image header view content | +| `stickyHeaderStyle` | `object` | No | These styles will be applied to the sticky headerStyle view content | +| `style` | `object` | No | These styles will be applied to the ParallaxScrollView container | +| `scrollEvent` | `func` | No | Callback to recieve the animated scroll event values | ## Latest changes diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..0295751 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,327 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const react_1 = __importStar(require("react")); +const react_native_1 = require("react-native"); +const styles_1 = __importDefault(require("./styles")); +const window = react_native_1.Dimensions.get('window'); +const pivotPoint = (a, b) => a - b; +const renderScroll = (props) => react_1.default.createElement(react_native_1.Animated.ScrollView, Object.assign({}, props)); +const renderEmpty = () => react_1.default.createElement(react_native_1.View, null); +const noRender = () => react_1.default.createElement(react_native_1.View, { style: { display: 'none' } }); +// Override `toJSON` of interpolated value because of +// an error when serializing style on view inside inspector. +// See: https://github.com/jaysoo/react-native-parallax-scroll-view/issues/23 +const interpolate = (value, opts) => { + const x = value.interpolate(opts); + // We have to play to make TypeScript happy + const xAny = x; + xAny.toJSON = () => xAny.__getValue(); + // We want the return type to still make sense from the value.interpolate function + return xAny; +}; +class ParallaxScrollView extends react_1.Component { + constructor(props) { + super(props); + this.scrollY = new react_native_1.Animated.Value(0); + this._footerComponent = { setNativeProps(props) { } }; // Initial stub + this._footerHeight = 0; + this.scrollViewRef = react_1.default.createRef(); + this.animatedEvent = react_native_1.Animated.event([{ nativeEvent: { contentOffset: { y: this.scrollY } } }], { useNativeDriver: true }); + if (props.renderStickyHeader && props.stickyHeaderHeightEx === undefined) { + console.warn('Property `stickyHeaderHeight` must be set if `renderStickyHeader` is used.'); + } + this.state = { + viewHeight: window.height, + viewWidth: window.width + }; + } + render() { + const _a = this.props, { backgroundColor, backgroundScrollSpeed, children, contentBackgroundColor, fadeOutForeground, fadeOutBackground, parallaxHeaderHeight, renderBackground, renderContentBackground, renderFixedHeader, renderForeground, renderScrollComponent, renderStickyHeader, stickyHeaderHeight, style, contentContainerStyle, outputScaleValue } = _a, scrollViewProps = __rest(_a, ["backgroundColor", "backgroundScrollSpeed", "children", "contentBackgroundColor", "fadeOutForeground", "fadeOutBackground", "parallaxHeaderHeight", "renderBackground", "renderContentBackground", "renderFixedHeader", "renderForeground", "renderScrollComponent", "renderStickyHeader", "stickyHeaderHeight", "style", "contentContainerStyle", "outputScaleValue"]); + const background = this._renderBackground({ + fadeOutBackground, + backgroundScrollSpeed, + backgroundColor, + parallaxHeaderHeight, + stickyHeaderHeight, + renderBackground, + outputScaleValue + }); + const foreground = this._renderForeground({ + fadeOutForeground, + parallaxHeaderHeight, + stickyHeaderHeight, + renderForeground + }); + const bodyComponent = this._wrapChildren(children, { + contentBackgroundColor, + stickyHeaderHeight, + renderContentBackground, + contentContainerStyle + }); + const footerSpacer = this._renderFooterSpacer({ contentBackgroundColor }); + const maybeStickyHeader = this._maybeRenderStickyHeader({ + parallaxHeaderHeight, + stickyHeaderHeight, + backgroundColor, + renderFixedHeader, + renderStickyHeader + }); + const scrollElement = renderScrollComponent(scrollViewProps); + return (react_1.default.createElement(react_native_1.View, { style: [style, styles_1.default.container], onLayout: e => this._maybeUpdateViewDimensions(e) }, + background, + react_1.default.cloneElement(scrollElement, { + ref: this.scrollViewRef, + style: [styles_1.default.scrollView, scrollElement.props.style], + scrollEventThrottle: 1, + // Using Native Driver greatly optimizes performance + onScroll: react_native_1.Animated.event([{ nativeEvent: { contentOffset: { y: this.scrollY } } }], { useNativeDriver: true, listener: this._onScroll.bind(this) }) + // onScroll: this._onScroll.bind(this) + }, foreground, bodyComponent, footerSpacer), + maybeStickyHeader)); + } + /* + * Expose `ScrollView` API so this component is composable with any component that expects a `ScrollView`. + */ + getScrollResponder() { + var _a; + return (_a = this.scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.getScrollResponder(); + } + getScrollableNode() { + var _a; + return (_a = this.scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.getScrollableNode(); + } + getInnerViewNode() { + var _a; + return (_a = this.scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.getInnerViewNode(); + } + scrollTo(...args) { + var _a; + (_a = this.scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo(...args); + } + setNativeProps(props) { + var _a; + (_a = this.scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.setNativeProps(props); + } + /* + * Private helpers + */ + _onScroll(e) { + const { parallaxHeaderHeight, stickyHeaderHeight, onChangeHeaderVisibility, onScroll: prevOnScroll = () => { } } = this.props; + this.props.scrollEvent && this.props.scrollEvent(e); + const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight); + // This optimization wont run, since we update the animation value directly in onScroll event + // this._maybeUpdateScrollPosition(e) + if (e.nativeEvent.contentOffset.y >= p) { + onChangeHeaderVisibility(false); + } + else { + onChangeHeaderVisibility(true); + } + prevOnScroll(e); + } + // This optimizes the state update of current scrollY since we don't need to + // perform any updates when user has scrolled past the pivot point. + _maybeUpdateScrollPosition(e) { + const { parallaxHeaderHeight, stickyHeaderHeight } = this.props; + const { scrollY } = this; + const { nativeEvent: { contentOffset: { y: offsetY } } } = e; + const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight); + // @ts-ignore getting the internal value of scrollY + const syv = scrollY._value; + if (offsetY <= p || syv <= p) { + scrollY.setValue(offsetY); + } + } + _maybeUpdateViewDimensions(e) { + const { nativeEvent: { layout: { width, height } } } = e; + if (width !== this.state.viewWidth || height !== this.state.viewHeight) { + this.setState({ + viewWidth: width, + viewHeight: height + }); + } + } + _renderBackground({ fadeOutBackground, backgroundScrollSpeed, backgroundColor, parallaxHeaderHeight, stickyHeaderHeight, renderBackground, outputScaleValue }) { + const { viewWidth, viewHeight } = this.state; + const { scrollY } = this; + const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight); + return (react_1.default.createElement(react_native_1.Animated.View, { style: [ + styles_1.default.backgroundImage, + ((this.props.backgroundImageStyle) ? this.props.backgroundImageStyle : null), + { + backgroundColor: backgroundColor, + height: parallaxHeaderHeight, + width: viewWidth, + opacity: fadeOutBackground + ? interpolate(scrollY, { + inputRange: [0, p * (1 / 2), p * (3 / 4), p], + outputRange: [1, 0.3, 0.1, 0], + extrapolate: 'clamp' + }) + : 1, + transform: [ + { + translateY: interpolate(scrollY, { + inputRange: [0, p], + outputRange: [0, -(p / backgroundScrollSpeed)], + extrapolateRight: 'extend', + extrapolateLeft: 'clamp' + }) + }, + { + scale: interpolate(scrollY, { + inputRange: [-viewHeight, 0], + outputRange: [outputScaleValue * 1.5, 1], + extrapolate: 'clamp' + }) + } + ] + } + ] }, + react_1.default.createElement(react_native_1.View, null, renderBackground()))); + } + _renderForeground({ fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, renderForeground }) { + const { scrollY } = this; + const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight); + return (react_1.default.createElement(react_native_1.View, { style: [ + styles_1.default.parallaxHeaderContainer, + (this.props.parallaxHeaderContainerStyle) ? this.props.parallaxHeaderContainerStyle : null + ] }, + react_1.default.createElement(react_native_1.Animated.View, { style: [ + styles_1.default.parallaxHeader, + ((this.props.parallaxHeaderStyle) ? this.props.parallaxHeaderStyle : null), + { + height: parallaxHeaderHeight, + opacity: fadeOutForeground + ? interpolate(scrollY, { + inputRange: [0, p * (1 / 2), p * (3 / 4), p], + outputRange: [1, 0.3, 0.1, 0], + extrapolate: 'clamp' + }) + : 1 + } + ] }, + react_1.default.createElement(react_native_1.View, { style: { height: parallaxHeaderHeight } }, renderForeground())))); + } + _wrapChildren(children, { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle, renderContentBackground }) { + const { viewHeight } = this.state; + const containerStyles = [{ backgroundColor: contentBackgroundColor }]; + if (contentContainerStyle) + containerStyles.push(contentContainerStyle); + let containerHeight = this.state.viewHeight; + react_1.default.Children.forEach(children, (item) => { + if (item && Object.keys(item).length != 0) { + containerHeight = 0; + } + }); + return (react_1.default.createElement(react_native_1.View, { style: [containerStyles, { minHeight: containerHeight }], onLayout: e => { + // Adjust the bottom height so we can scroll the parallax header all the way up. + const { nativeEvent: { layout: { height } } } = e; + const footerHeight = Math.max(0, viewHeight - height - stickyHeaderHeight); + if (this._footerHeight !== footerHeight) { + this._footerComponent.setNativeProps({ + style: { height: footerHeight } + }); + this._footerHeight = footerHeight; + } + } }, + renderContentBackground(), + children)); + } + _renderFooterSpacer({ contentBackgroundColor }) { + return (react_1.default.createElement(react_native_1.View, { ref: ref => { + if (ref) { + this._footerComponent = ref; + } + }, style: { backgroundColor: contentBackgroundColor } })); + } + _maybeRenderStickyHeader({ parallaxHeaderHeight, stickyHeaderHeight, backgroundColor, renderFixedHeader, renderStickyHeader }) { + const { viewWidth } = this.state; + const { scrollY } = this; + if (renderStickyHeader || renderFixedHeader) { + const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight); + return (react_1.default.createElement(react_native_1.View, { style: [ + styles_1.default.stickyHeader, + ((this.props.stickyHeaderStyle) ? this.props.stickyHeaderStyle : null), + Object.assign({ width: viewWidth }, (stickyHeaderHeight ? { height: stickyHeaderHeight } : null)) + ] }, + renderStickyHeader + ? react_1.default.createElement(react_native_1.Animated.View, { style: { + backgroundColor: backgroundColor, + height: stickyHeaderHeight, + opacity: interpolate(scrollY, { + inputRange: [0, p], + outputRange: [0, 1], + extrapolate: 'clamp' + }) + } }, + react_1.default.createElement(react_native_1.Animated.View, { style: { + transform: [ + { + translateY: interpolate(scrollY, { + inputRange: [0, p], + outputRange: [stickyHeaderHeight, 0], + extrapolate: 'clamp' + }) + } + ] + } }, renderStickyHeader())) + : null, + renderFixedHeader && renderFixedHeader())); + } + else { + return null; + } + } +} +ParallaxScrollView.defaultProps = { + backgroundColor: '#000', + backgroundScrollSpeed: 5, + contentBackgroundColor: '#fff', + fadeOutForeground: true, + fadeOutBackground: false, + onChangeHeaderVisibility: () => { }, + renderBackground: renderEmpty, + renderContentBackground: noRender, + renderFixedHeader: () => react_1.default.createElement(react_native_1.View, null), + renderScrollComponent: renderScroll, + outputScaleValue: 5, +}; +exports.default = ParallaxScrollView; diff --git a/dist/styles.js b/dist/styles.js new file mode 100644 index 0000000..f592daa --- /dev/null +++ b/dist/styles.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const react_native_1 = require("react-native"); +const styles = react_native_1.StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'transparent' + }, + parallaxHeaderContainer: { + backgroundColor: 'transparent', + overflow: 'hidden' + }, + parallaxHeader: { + backgroundColor: 'transparent', + overflow: 'hidden' + }, + backgroundImage: { + position: 'absolute', + backgroundColor: 'transparent', + overflow: 'hidden', + top: 0 + }, + stickyHeader: { + backgroundColor: 'transparent', + position: 'absolute', + overflow: 'hidden', + top: 0, + left: 0 + }, + scrollView: { + backgroundColor: 'transparent' + } +}); +exports.default = styles; diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/package-lock.json b/package-lock.json index 510c428..8566a68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,35 +1,101 @@ { "name": "react-native-parallax-scroll-view", - "version": "0.21.3", - "lockfileVersion": 1, + "version": "1.0.0", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "react-native-parallax-scroll-view", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@types/react": "^18.2.73", + "@types/react-native": "^0.70.19", + "typescript": "^5.4.3" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.2.73", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.73.tgz", + "integrity": "sha512-XcGdod0Jjv84HOC7N5ziY3x+qL0AfmubvKOZ9hJjJ2yd5EE+KYjWhdOjt387e9HPheHkdggF9atTifMRtyAaRA==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-native": { + "version": "0.70.19", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.19.tgz", + "integrity": "sha512-c6WbyCgWTBgKKMESj/8b4w+zWcZSsCforson7UdXtXMecG3MxCinYi6ihhrHVPyUrVzORsvEzK8zg32z4pK6Sg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + }, "dependencies": { - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "@types/react": { + "version": "18.2.73", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.73.tgz", + "integrity": "sha512-XcGdod0Jjv84HOC7N5ziY3x+qL0AfmubvKOZ9hJjJ2yd5EE+KYjWhdOjt387e9HPheHkdggF9atTifMRtyAaRA==", + "dev": true, "requires": { - "js-tokens": "^3.0.0" + "@types/prop-types": "*", + "csstype": "^3.0.2" } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "@types/react-native": { + "version": "0.70.19", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.19.tgz", + "integrity": "sha512-c6WbyCgWTBgKKMESj/8b4w+zWcZSsCforson7UdXtXMecG3MxCinYi6ihhrHVPyUrVzORsvEzK8zg32z4pK6Sg==", + "dev": true, "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" + "@types/react": "*" } + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true } } } diff --git a/package.json b/package.json index a34729c..09490a3 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,38 @@ { - "name": "react-native-parallax-scroll-view", - "version": "0.21.3", - "description": "A ScrollView-like component with parallax and sticky header support", - "main": "src/index.js", - "repository": { - "type": "git", - "url": "https://github.com/jaysoo/react-native-parallax-scroll-view" - }, - "files": [ - "src", - "demo.ios.gif", - "demo.android.20160117.gif", - "README.md", - "LICENSE" - ], - "keywords": [ - "react-native", - "react", - "parallax", - "scrollable", - "scrollview", - "sticky", - "react-component", - "ios", - "android" - ], - "author": "Jack Hsu", - "license": "ISC", - "dependencies": { - "deprecated-react-native-prop-types": "^2.3.0", - "prop-types": "^15.6.0" - } + "name": "react-native-parallax-scroll-view", + "version": "1.0.0", + "description": "A ScrollView-like component with parallax and sticky header support", + "main": "dist/index.js", + "repository": { + "type": "git", + "url": "https://github.com/i6mi6/react-native-parallax-scroll-view" + }, + "scripts": { + "build": "tsc" + }, + "files": [ + "src", + "demo.ios.gif", + "demo.android.20160117.gif", + "README.md", + "LICENSE" + ], + "keywords": [ + "react-native", + "react", + "parallax", + "scrollable", + "scrollview", + "sticky", + "react-component", + "ios", + "android" + ], + "author": "Jack Hsu", + "license": "ISC", + "devDependencies": { + "@types/react": "^18.2.73", + "@types/react-native": "^0.70.19", + "typescript": "^5.4.3" + } } diff --git a/src/index.js b/src/index.tsx similarity index 63% rename from src/index.js rename to src/index.tsx index 30d0596..9fc7abc 100644 --- a/src/index.js +++ b/src/index.tsx @@ -1,16 +1,23 @@ -import React, { Component } from 'react' -import { Animated, Dimensions, View } from 'react-native' -import { ViewPropTypes } from 'deprecated-react-native-prop-types' - -const styles = require('./styles') - -import { bool, func, number, string } from 'prop-types' +import React, {Component} from 'react' +import { + Animated, + ColorValue, + Dimensions, + ScrollView, + StyleProp, + ViewStyle, + View, + NativeScrollEvent, + NativeSyntheticEvent, +} from 'react-native' + +import styles from './styles' const window = Dimensions.get('window') -const SCROLLVIEW_REF = 'ScrollView' +const pivotPoint = (a: number, b: number) => a - b -const pivotPoint = (a, b) => a - b +const renderScroll = (props: Animated.AnimatedProps) => const renderEmpty = () => @@ -19,57 +26,93 @@ const noRender = () => // Override `toJSON` of interpolated value because of // an error when serializing style on view inside inspector. // See: https://github.com/jaysoo/react-native-parallax-scroll-view/issues/23 -const interpolate = (value, opts) => { +const interpolate = (value: Animated.Value, opts: {inputRange: number[]; + outputRange: number[] | string[]; + easing?: ((input: number) => number) | undefined; + extrapolate?: Animated.ExtrapolateType | undefined; + extrapolateLeft?: Animated.ExtrapolateType | undefined; + extrapolateRight?: Animated.ExtrapolateType | undefined;}) => { const x = value.interpolate(opts) - x.toJSON = () => x.__getValue() - return x + + // We have to play to make TypeScript happy + const xAny = x as any + xAny.toJSON = () => xAny.__getValue() as number + + // We want the return type to still make sense from the value.interpolate function + return xAny as typeof x +} + +// Properties that we set the defaults on +type ParallaxScrollViewDefaultProps = { + backgroundColor: string | ColorValue + backgroundScrollSpeed: number + contentBackgroundColor: string | ColorValue + fadeOutForeground: boolean + fadeOutBackground: boolean + onChangeHeaderVisibility: (isVisible: boolean) => void + renderBackground: () => React.ReactElement + renderContentBackground: () => React.ReactElement + renderFixedHeader: () => React.ReactElement + renderScrollComponent: (props: Animated.AnimatedProps>) => React.ReactElement + outputScaleValue: number } // Properties accepted by `ParallaxScrollView`. -const IPropTypes = { - backgroundColor: string, - backgroundScrollSpeed: number, - fadeOutForeground: bool, - fadeOutBackground: bool, - contentBackgroundColor: string, - onChangeHeaderVisibility: func, - parallaxHeaderHeight: number.isRequired, - renderBackground: func, - renderContentBackground: func, - renderFixedHeader: func, - renderForeground: func, - renderScrollComponent: func, - renderStickyHeader: func, - stickyHeaderHeight: number, - contentContainerStyle: ViewPropTypes.style, - outputScaleValue: number, - parallaxHeaderContainerStyle: ViewPropTypes.style, - parallaxHeaderStyle: ViewPropTypes.style, - backgroundImageStyle: ViewPropTypes.style, - stickyHeaderStyle: ViewPropTypes.style +export type ParallaxScrollViewProps = { + parallaxHeaderHeight: number + renderForeground: () => React.ReactElement + renderStickyHeader?: () => React.ReactElement + stickyHeaderHeightEx?: number + contentContainerStyle?: StyleProp + parallaxHeaderContainerStyle?: StyleProp + parallaxHeaderStyle?: StyleProp + backgroundImageStyle?: StyleProp + stickyHeaderStyle?: StyleProp + style?: StyleProp + scrollEvent?: (e: NativeSyntheticEvent) => void +} & Partial + +type InternalParallaxScrollViewProps = ParallaxScrollViewProps & ParallaxScrollViewDefaultProps & { + stickyHeaderHeight: number + onScroll: (e: any) => void +} + +type ParallaxScrollViewState = { + viewHeight: number + viewWidth: number } -class ParallaxScrollView extends Component { - constructor(props) { +class ParallaxScrollView extends Component, ParallaxScrollViewState> { + private scrollY = new Animated.Value(0) + private _footerComponent = { setNativeProps(props: any) { } } // Initial stub + private _footerHeight = 0 + private scrollViewRef = React.createRef() + + static defaultProps: ParallaxScrollViewDefaultProps = { + backgroundColor: '#000', + backgroundScrollSpeed: 5, + contentBackgroundColor: '#fff', + fadeOutForeground: true, + fadeOutBackground: false, + onChangeHeaderVisibility: () => { }, + renderBackground: renderEmpty, + renderContentBackground: noRender, + renderFixedHeader: () => , + renderScrollComponent: renderScroll, + outputScaleValue: 5, + } + + constructor(props: React.PropsWithChildren) { super(props) - if (props.renderStickyHeader && !props.stickyHeaderHeight) { + if (props.renderStickyHeader && props.stickyHeaderHeightEx === undefined) { console.warn( 'Property `stickyHeaderHeight` must be set if `renderStickyHeader` is used.' ) } - if (props.renderParallaxHeader !== renderEmpty && !props.renderForeground) { - console.warn( - 'Property `renderParallaxHeader` is deprecated. Use `renderForeground` instead.' - ) - } this.state = { - scrollY: new Animated.Value(0), viewHeight: window.height, viewWidth: window.width } - this.scrollY = new Animated.Value(0) - this._footerComponent = { setNativeProps() { } } // Initial stub - this._footerHeight = 0 } animatedEvent = Animated.event( @@ -90,7 +133,6 @@ class ParallaxScrollView extends Component { renderContentBackground, renderFixedHeader, renderForeground, - renderParallaxHeader, renderScrollComponent, renderStickyHeader, stickyHeaderHeight, @@ -113,7 +155,7 @@ class ParallaxScrollView extends Component { fadeOutForeground, parallaxHeaderHeight, stickyHeaderHeight, - renderForeground: renderForeground || renderParallaxHeader + renderForeground }) const bodyComponent = this._wrapChildren(children, { contentBackgroundColor, @@ -139,7 +181,7 @@ class ParallaxScrollView extends Component { {React.cloneElement( scrollElement, { - ref: SCROLLVIEW_REF, + ref: this.scrollViewRef, style: [styles.scrollView, scrollElement.props.style], scrollEventThrottle: 1, // Using Native Driver greatly optimizes performance @@ -162,26 +204,26 @@ class ParallaxScrollView extends Component { * Expose `ScrollView` API so this component is composable with any component that expects a `ScrollView`. */ getScrollResponder() { - return this.refs[SCROLLVIEW_REF]._component.getScrollResponder() + return this.scrollViewRef.current?.getScrollResponder() } getScrollableNode() { - return this.getScrollResponder().getScrollableNode() + return this.scrollViewRef.current?.getScrollableNode() } getInnerViewNode() { - return this.getScrollResponder().getInnerViewNode() + return this.scrollViewRef.current?.getInnerViewNode() } - scrollTo(...args) { - this.getScrollResponder().scrollTo(...args) + scrollTo(...args: any) { + this.scrollViewRef.current?.scrollTo(...args) } - setNativeProps(props) { - this.refs[SCROLLVIEW_REF].setNativeProps(props) + setNativeProps(props: object) { + this.scrollViewRef.current?.setNativeProps(props) } /* * Private helpers */ - _onScroll(e) { + _onScroll(e: NativeSyntheticEvent) { const { parallaxHeaderHeight, stickyHeaderHeight, @@ -205,17 +247,19 @@ class ParallaxScrollView extends Component { // This optimizes the state update of current scrollY since we don't need to // perform any updates when user has scrolled past the pivot point. - _maybeUpdateScrollPosition(e) { + _maybeUpdateScrollPosition(e: NativeSyntheticEvent) { const { parallaxHeaderHeight, stickyHeaderHeight } = this.props const { scrollY } = this const { nativeEvent: { contentOffset: { y: offsetY } } } = e const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight) - if (offsetY <= p || scrollY._value <= p) { + // @ts-ignore getting the internal value of scrollY + const syv: number = scrollY._value + if (offsetY <= p || syv <= p) { scrollY.setValue(offsetY) } } - _maybeUpdateViewDimensions(e) { + _maybeUpdateViewDimensions(e: any) { const { nativeEvent: { layout: { width, height } } } = e if (width !== this.state.viewWidth || height !== this.state.viewHeight) { @@ -234,6 +278,14 @@ class ParallaxScrollView extends Component { stickyHeaderHeight, renderBackground, outputScaleValue + }: { + fadeOutBackground: boolean; + backgroundScrollSpeed: number; + backgroundColor: string | ColorValue; + parallaxHeaderHeight: number; + stickyHeaderHeight: number; + renderBackground: () => React.ReactElement; + outputScaleValue: number }) { const { viewWidth, viewHeight } = this.state const { scrollY } = this @@ -286,6 +338,11 @@ class ParallaxScrollView extends Component { parallaxHeaderHeight, stickyHeaderHeight, renderForeground + }: { + fadeOutForeground: boolean; + parallaxHeaderHeight: number; + stickyHeaderHeight: number; + renderForeground: () => React.ReactElement }) { const { scrollY } = this const p = pivotPoint(parallaxHeaderHeight, stickyHeaderHeight) @@ -319,25 +376,25 @@ class ParallaxScrollView extends Component { } _wrapChildren( - children, - { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle, renderContentBackground } + children: React.ReactNode, + { contentBackgroundColor, stickyHeaderHeight, contentContainerStyle, renderContentBackground }: {contentBackgroundColor: string | ColorValue, stickyHeaderHeight: number, contentContainerStyle?: StyleProp, renderContentBackground: () => React.ReactElement} ) { const { viewHeight } = this.state - const containerStyles = [{ backgroundColor: contentBackgroundColor }] + const containerStyles: StyleProp[] = [{ backgroundColor: contentBackgroundColor }] if (contentContainerStyle) containerStyles.push(contentContainerStyle) - this.containerHeight = this.state.viewHeight; + let containerHeight = this.state.viewHeight; React.Children.forEach(children, (item) => { if (item && Object.keys(item).length != 0) { - this.containerHeight = 0; + containerHeight = 0; } }); return ( { // Adjust the bottom height so we can scroll the parallax header all the way up. const { nativeEvent: { layout: { height } } } = e @@ -359,7 +416,7 @@ class ParallaxScrollView extends Component { ) } - _renderFooterSpacer({ contentBackgroundColor }) { + _renderFooterSpacer({ contentBackgroundColor }: { contentBackgroundColor: string | ColorValue }) { return ( { @@ -378,6 +435,12 @@ class ParallaxScrollView extends Component { backgroundColor, renderFixedHeader, renderStickyHeader + } :{ + parallaxHeaderHeight: number; + stickyHeaderHeight: number; + backgroundColor: string | ColorValue; + renderFixedHeader?: () => React.ReactElement; + renderStickyHeader?: () => React.ReactElement; }) { const { viewWidth } = this.state const { scrollY } = this @@ -432,26 +495,4 @@ class ParallaxScrollView extends Component { } } -ParallaxScrollView.propTypes = IPropTypes - -ParallaxScrollView.defaultProps = { - backgroundScrollSpeed: 5, - backgroundColor: '#000', - contentBackgroundColor: '#fff', - fadeOutForeground: true, - onChangeHeaderVisibility: () => { }, - renderScrollComponent: props => , - renderBackground: renderEmpty, - renderContentBackground: noRender, - renderParallaxHeader: renderEmpty, // Deprecated (will be removed in 0.18.0) - renderForeground: null, - stickyHeaderHeight: 0, - contentContainerStyle: null, - outputScaleValue: 5, - parallaxHeaderContainerStyle: null, - parallaxHeaderStyle: null, - backgroundImageStyle: null, - stickyHeaderStyle: null -} - -module.exports = ParallaxScrollView +export default ParallaxScrollView diff --git a/src/styles.js b/src/styles.ts similarity index 88% rename from src/styles.js rename to src/styles.ts index 4562277..626e8ef 100644 --- a/src/styles.js +++ b/src/styles.ts @@ -1,4 +1,4 @@ -const StyleSheet = require('react-native').StyleSheet; +import {StyleSheet} from 'react-native' const styles = StyleSheet.create({ container: { @@ -31,4 +31,4 @@ const styles = StyleSheet.create({ } }); -module.exports = styles; +export default styles; diff --git a/index.d.ts b/src/types.ts similarity index 81% rename from index.d.ts rename to src/types.ts index b71dcf1..4345ee1 100644 --- a/index.d.ts +++ b/src/types.ts @@ -1,8 +1,4 @@ -import * as React from 'react'; - -declare class ParallaxScrollView extends React.Component { - -} +import {JSX} from 'react'; export interface ParallaxScrollViewProps { backgroundScrollSpeed?: number; @@ -22,7 +18,7 @@ export interface ParallaxScrollViewProps { parallaxHeaderHeight?: number; } -export class RenderBackgroundParams { +export interface RenderBackgroundParams { fadeOutForeground: any; backgroundScrollSpeed: number; backgroundColor: string; @@ -31,5 +27,3 @@ export class RenderBackgroundParams { renderBackground: () => void; outputScaleValue: number; } - -export default ParallaxScrollView; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9c90b66 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, + /* Skip type checking all .d.ts files. */ + "jsx": "react" + } +}