diff --git a/.eslintrc.js b/.eslintrc.js index 128ffc8a85..56d2575d1f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -78,6 +78,7 @@ module.exports = { 'no-unused-expressions': ['error', { allowTaggedTemplates: true }], 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], 'react-native/no-inline-styles': 0, + '@typescript-eslint/no-explicit-any': ['error', { ignoreRestArgs: true }], // NOTE: @typescript-eslint rules are configured under the TS override below 'jest/expect-expect': [ 'warn', @@ -121,6 +122,8 @@ module.exports = { 'no-shadow': 'off', 'import/named': 'off', 'react-native/no-inline-styles': 0, + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }], '@typescript-eslint/no-explicit-any': [ 'warn', { ignoreRestArgs: true }, diff --git a/.prettierrc.js b/.prettierrc.js index de2f53cdf9..a1566e4879 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,4 +1,8 @@ +/** @type {import('prettier').Config} */ module.exports = { - singleQuote: true, - trailingComma: 'all', -}; + arrowParens: 'avoid', // (x) => x ⟶ x => x + singleQuote: true, // prefer 'test' over "test" + trailingComma: 'all', // multi-line trailing commas + semi: true, // for compatibility and clarity with ESLint default + tabWidth: 2, +}; \ No newline at end of file diff --git a/__tests__/__mocks__/react-native.mock.js b/__tests__/__mocks__/react-native.mock.js index 3abb794f39..9c4e1d34a0 100644 --- a/__tests__/__mocks__/react-native.mock.js +++ b/__tests__/__mocks__/react-native.mock.js @@ -4,7 +4,6 @@ jest.mock('react-native/Libraries/Image/resolveAssetSource', () => { jest.mock('../../src/assets/heading.png', () => 'heading.png'); - jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter', () => { function MockEventEmitter() {} MockEventEmitter.prototype.addListener = jest.fn(() => ({ @@ -16,12 +15,11 @@ jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter', () => { }; }); - jest.mock('react-native/Libraries/Utilities/Platform', () => ({ __esModule: true, default: { OS: 'ios', // or 'android' - select: (x) => { + select: x => { if (x.android) { return x.android; } else if (x.native) { @@ -30,7 +28,7 @@ jest.mock('react-native/Libraries/Utilities/Platform', () => ({ return x.default; } }, - } + }, })); jest.mock('react-native/src/private/animated/NativeAnimatedHelper', () => ({ @@ -40,4 +38,3 @@ jest.mock('react-native/src/private/animated/NativeAnimatedHelper', () => ({ }, shouldUseNativeDriver: jest.fn(), })); - diff --git a/__tests__/components/Callout.test.js b/__tests__/components/Callout.test.js index 148a978088..124dcb4eac 100644 --- a/__tests__/components/Callout.test.js +++ b/__tests__/components/Callout.test.js @@ -1,6 +1,5 @@ import React from 'react'; import { render } from '@testing-library/react-native'; -import type { ReactTestInstance } from 'react-test-renderer'; import { Text, View } from 'react-native'; import Callout from '../../src/components/Callout'; @@ -31,15 +30,13 @@ describe('Callout', () => { tipStyle: { height: 4 }, textStyle: { height: 5 }, }; - const result = render( - , - ); - const { UNSAFE_getByType, UNSAFE_getAllByType } = result + const result = render(); + const { UNSAFE_getByType, UNSAFE_getAllByType } = result; const callout = UNSAFE_getByType('RNMBXCallout'); const views = UNSAFE_getAllByType(View); const text = UNSAFE_getByType(Text); - - function getStyleHeightForViewWithProps(props: { [propName: string]: any }): ReactTestInstance { + + function getStyleHeightForViewWithProps(props) { if (Array.isArray(props.style)) { return props.style[1].height; } @@ -47,13 +44,21 @@ describe('Callout', () => { return props.style.height; } - const calloutWrapperTestStyle = getStyleHeightForViewWithProps(callout.props); - const animatedViewTestStyle = getStyleHeightForViewWithProps(views[0].props); - const wrapperViewTestStyle = getStyleHeightForViewWithProps(views[1].props); + const calloutWrapperTestStyle = getStyleHeightForViewWithProps( + callout.props, + ); + const animatedViewTestStyle = getStyleHeightForViewWithProps( + views[0].props, + ); + const wrapperViewTestStyle = getStyleHeightForViewWithProps( + views[1].props, + ); const tipViewTestStyle = getStyleHeightForViewWithProps(views[2].props); const textTestStyle = getStyleHeightForViewWithProps(text.props); - expect(calloutWrapperTestStyle).toStrictEqual(testProps.containerStyle.height); + expect(calloutWrapperTestStyle).toStrictEqual( + testProps.containerStyle.height, + ); expect(animatedViewTestStyle).toStrictEqual(testProps.style.height); expect(wrapperViewTestStyle).toStrictEqual(testProps.contentStyle.height); expect(tipViewTestStyle).toStrictEqual(testProps.tipStyle.height); diff --git a/__tests__/components/Camera.test.js b/__tests__/components/Camera.test.js index 5a9460a30f..9f1a60751d 100644 --- a/__tests__/components/Camera.test.js +++ b/__tests__/components/Camera.test.js @@ -10,14 +10,7 @@ const bounds1 = { sw: [-74.143727, 40.772177], }; -const paddingZero = { - paddingTop: 0, - paddingRight: 0, - paddingBottom: 0, - paddingLeft: 0, -}; - -const toFeature = (position) => { +const toFeature = position => { return { type: 'Feature', geometry: { @@ -28,7 +21,7 @@ const toFeature = (position) => { }; }; -const toFeatureCollection = (bounds) => { +const toFeatureCollection = bounds => { return { type: 'FeatureCollection', features: [toFeature(bounds.ne), toFeature(bounds.sw)], diff --git a/__tests__/components/UserLocation.test.js b/__tests__/components/UserLocation.test.js index 1fba98d950..98e4a6e40f 100644 --- a/__tests__/components/UserLocation.test.js +++ b/__tests__/components/UserLocation.test.js @@ -39,7 +39,9 @@ describe('UserLocation', () => { }); test('renders with CircleLayers by default', async () => { - const { UNSAFE_getAllByType, UNSAFE_queryByType } = render(); + const { UNSAFE_getAllByType, UNSAFE_queryByType } = render( + , + ); await waitFor(() => { expect(() => UNSAFE_queryByType(UserLocation)).not.toThrow(); }); @@ -79,9 +81,9 @@ describe('UserLocation', () => { const { UNSAFE_queryByType, UNSAFE_queryAllByType } = render( - - - ) + + , + ); await waitFor(() => { expect(() => UNSAFE_queryByType(UserLocation)).not.toThrow(); }); @@ -99,7 +101,9 @@ describe('UserLocation', () => { test('calls onUpdate callback when new location is received', async () => { const onUpdateCallback = jest.fn(); - const { UNSAFE_getByType } = render(); + const { UNSAFE_getByType } = render( + , + ); await waitFor(() => { expect(() => UNSAFE_getByType(UserLocation)).not.toThrow(); @@ -118,7 +122,7 @@ describe('UserLocation', () => { }, timestamp: 1573730357879, }); - }) + }); expect(onUpdateCallback).toHaveBeenCalled(); }); @@ -152,7 +156,7 @@ describe('UserLocation', () => { const ul = UNSAFE_queryByType(UserLocation); const lastKnownLocation = [4.1036916, 51.5462244]; - locationManager._lastKnownLocation = lastKnownLocation + locationManager._lastKnownLocation = lastKnownLocation; expect(locationManager.start).toHaveBeenCalledTimes(0); expect(locationManager._isListening).toStrictEqual(false); @@ -219,13 +223,13 @@ describe('UserLocation', () => { test('called with "running" true', async () => { const lastKnownLocation = [4.1036916, 51.5462244]; const heading = 251.5358428955078; - locationManager._lastKnownLocation = lastKnownLocation + locationManager._lastKnownLocation = lastKnownLocation; expect(ul.locationManagerRunning).toStrictEqual(false); await act(async () => { await ul.setLocationManager({ running: true }); - }) + }); expect(ul.locationManagerRunning).toStrictEqual(true); expect(locationManager.start).toHaveBeenCalledTimes(1); @@ -243,14 +247,14 @@ describe('UserLocation', () => { expect(ul.locationManagerRunning).toStrictEqual(false); await act(async () => { await ul.setLocationManager({ running: true }); - }) + }); expect(ul.locationManagerRunning).toStrictEqual(true); // stop await act(async () => { await ul.setLocationManager({ running: false }); - }) + }); expect(ul.locationManagerRunning).toStrictEqual(false); // only once from start diff --git a/__tests__/interface.test.js b/__tests__/interface.test.js index 141defc77f..14820e012e 100644 --- a/__tests__/interface.test.js +++ b/__tests__/interface.test.js @@ -115,6 +115,6 @@ describe('Public Interface', () => { '__experimental', ]; - actualKeys.forEach((key) => expect(expectedKeys).toContain(key)); + actualKeys.forEach(key => expect(expectedKeys).toContain(key)); }); }); diff --git a/__tests__/modules/location/locationManager.test.js b/__tests__/modules/location/locationManager.test.js index 02285320e0..05f76379a0 100644 --- a/__tests__/modules/location/locationManager.test.js +++ b/__tests__/modules/location/locationManager.test.js @@ -261,13 +261,13 @@ describe('LocationManager', () => { test('calls listeners with location', () => { const listeners = [jest.fn(), jest.fn(), jest.fn()]; - listeners.forEach((listener) => { + listeners.forEach(listener => { locationManager.addListener(listener); }); locationManager._onUpdate(location); - listeners.forEach((listener) => { + listeners.forEach(listener => { expect(listener).toHaveBeenCalledTimes(1); expect(listener).toHaveBeenCalledWith(location); }); diff --git a/__tests__/modules/snapshot/SnapshotOptions.test.js b/__tests__/modules/snapshot/SnapshotOptions.test.js index f19eeb9030..9c4f4260a3 100644 --- a/__tests__/modules/snapshot/SnapshotOptions.test.js +++ b/__tests__/modules/snapshot/SnapshotOptions.test.js @@ -62,7 +62,7 @@ describe('SnapshotOptions', () => { }; const geoJSONBounds = JSON.stringify( - makeFeatureCollection(expectedOptions.bounds.map((c) => makePoint(c))), + makeFeatureCollection(expectedOptions.bounds.map(c => makePoint(c))), ); const options = new SnapshotOptions(expectedOptions); diff --git a/__tests__/utils/animated/AnimatedCoordinatesArray.test.js b/__tests__/utils/animated/AnimatedCoordinatesArray.test.js index 375706276f..877e7215bb 100644 --- a/__tests__/utils/animated/AnimatedCoordinatesArray.test.js +++ b/__tests__/utils/animated/AnimatedCoordinatesArray.test.js @@ -13,13 +13,13 @@ let oldNodeEnv = null; beforeAll(() => { clock = FakeTimers.install(); clock._requestedAnimationFrames = []; - clock.requestAnimationFrame = (callback) => { + clock.requestAnimationFrame = callback => { clock._requestedAnimationFrames.push(callback); }; clock.fireRequestAnimationFrames = () => { const oldRAF = clock._requestedAnimationFrames; clock._requestedAnimationFrames = []; - oldRAF.forEach((cb) => cb(Date.now())); + oldRAF.forEach(cb => cb(Date.now())); }; // animated will not call nativeProps in test mode @@ -53,7 +53,7 @@ describe('AnimatedShapeSource', () => { const testRenderer = TestRenderer.create( (shapeSourceRef = ref)} + ref={ref => (shapeSourceRef = ref)} />, ); }); @@ -104,10 +104,10 @@ describe('AnimatedShapeSource', () => { const testRenderer = TestRenderer.create( (shapeSourceRef = ref)} + ref={ref => (shapeSourceRef = ref)} />, ); - }) + }); const setNativeProps = jest.fn(); _nativeRef(shapeSourceRef).setNativeProps = setNativeProps; @@ -158,10 +158,10 @@ describe('AnimatedShapeSource', () => { const testRenderer = TestRenderer.create( (shapeSourceRef = ref)} + ref={ref => (shapeSourceRef = ref)} />, ); - }) + }); const setNativeProps = jest.fn(); _nativeRef(shapeSourceRef).setNativeProps = setNativeProps; diff --git a/example/__tests__/dumpExamplesJson.ts b/example/__tests__/dumpExamplesJson.ts index aa56149163..93567c6e23 100644 --- a/example/__tests__/dumpExamplesJson.ts +++ b/example/__tests__/dumpExamplesJson.ts @@ -1,5 +1,5 @@ /** - * Dumps examples.json to docs/examples.json from metadata in the examples in the example direcrory + * Dumps examples.json to docs/examples.json from metadata in the examples in the example directory */ import path from 'path'; import fs from 'fs'; diff --git a/example/e2e/docScreenshots.e2e.js b/example/e2e/docScreenshots.e2e.js index 9e5d7c37c4..aeea0acbcb 100644 --- a/example/e2e/docScreenshots.e2e.js +++ b/example/e2e/docScreenshots.e2e.js @@ -140,35 +140,43 @@ if (['true', 1, '1'].includes(process.env.SKIP_TESTS_NO_METAL)) { /** @type Screenshots */ const screenshots = {}; - examples.forEach(({ groupName, metadata: groupMetadata, examples }) => { - describe(`${groupName}`, () => { - examples.forEach(({ metadata, fullPath, name }) => { - if (metadata) { - it(`${name}`, async () => { - await setSampleLocation(); - - await expect(element(by.text(groupMetadata.title))).toBeVisible(); - await element(by.text(groupMetadata.title)).tap(); - - await waitFor(element(by.text(metadata.title))) - .toBeVisible() - .whileElement(by.id('example-list')) - .scroll(50, 'down'); - await element(by.text(metadata.title)).tap(); - - let shots = new ExampleScreenshots( - { testName: name, groupName }, - screenshots, - ); - - await wait(1000); - - await shots.screenshot(); - }); - } + examples.forEach( + ({ + groupName, + metadata: groupMetadata, + examples: exampleGroupExamples, + }) => { + describe(`${groupName}`, () => { + exampleGroupExamples.forEach(({ metadata, fullPath, name }) => { + if (metadata) { + it(`${name}`, async () => { + await setSampleLocation(); + + await expect( + element(by.text(groupMetadata.title)), + ).toBeVisible(); + await element(by.text(groupMetadata.title)).tap(); + + await waitFor(element(by.text(metadata.title))) + .toBeVisible() + .whileElement(by.id('example-list')) + .scroll(50, 'down'); + await element(by.text(metadata.title)).tap(); + + let shots = new ExampleScreenshots( + { testName: name, groupName }, + screenshots, + ); + + await wait(1000); + + await shots.screenshot(); + }); + } + }); }); - }); - }); + }, + ); afterAll(async () => { console.log('Writing screenshots.json', screenshotsJSONPath); diff --git a/example/metro.config.js b/example/metro.config.js index b08902ca4d..ade9aac724 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -39,8 +39,7 @@ const config = { blockList: exclusionList( modules.map( - (m) => - new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`), + m => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`), ), ), diff --git a/example/package.json b/example/package.json index 05a01784d4..1a55936a0c 100644 --- a/example/package.json +++ b/example/package.json @@ -1,5 +1,5 @@ { - "name": "RNMapboxGLExample", + "name": "rnmapboxglexample", "main": "expo/AppEntry.js", "version": "1.0.0", "private": true, @@ -72,7 +72,7 @@ "jest": "^30.0.5", "patch-package": "^8.0.0", "pod-install": "^1.0.1", - "prettier": "^2.8.8", + "prettier": "^3.6.2", "react-test-renderer": "19.1.0", "typescript": "^5.8.3" }, diff --git a/example/src/examples/Animations/AnimatedLine.js b/example/src/examples/Animations/AnimatedLine.js index 3141d56faf..3ed8189e8c 100755 --- a/example/src/examples/Animations/AnimatedLine.js +++ b/example/src/examples/Animations/AnimatedLine.js @@ -216,7 +216,7 @@ class AnimatedLine extends React.Component { return ( <> (this._map = c)} + ref={c => (this._map = c)} onPress={this.onPress} onDidFinishLoadingMap={this.onDidFinishLoadingMap} style={sheet.matchParent} diff --git a/example/src/examples/Animations/AnimatedLineOffsets.tsx b/example/src/examples/Animations/AnimatedLineOffsets.tsx index 78e56dcb3f..7f992070ba 100644 --- a/example/src/examples/Animations/AnimatedLineOffsets.tsx +++ b/example/src/examples/Animations/AnimatedLineOffsets.tsx @@ -74,7 +74,7 @@ const AnimatedLineOffsets = memo(() => { }, []); const buildRandomizedLine = useCallback(() => { - return baseCoordinates.map((c) => { + return baseCoordinates.map(c => { return [c[0] + randNorm() * 0.001, c[1] + randNorm() * 0.001]; }); }, []); @@ -139,7 +139,7 @@ const AnimatedLineOffsets = memo(() => { { + onSlidingComplete={v => { startOffset.current = v * lineLength; animator.setStartOffset({ offset: startOffset.current, @@ -160,7 +160,7 @@ const AnimatedLineOffsets = memo(() => { { + onSlidingComplete={v => { endOffset.current = v * lineLength; animator.setEndOffset({ offset: endOffset.current, @@ -181,7 +181,7 @@ const AnimatedLineOffsets = memo(() => { { + onSlidingComplete={v => { duration.current = v * maxDuration; animator.setStartOffset({ offset: startOffset.current, diff --git a/example/src/examples/Animations/AnimatedPoint.tsx b/example/src/examples/Animations/AnimatedPoint.tsx index fd8fd595bf..effce77165 100644 --- a/example/src/examples/Animations/AnimatedPoint.tsx +++ b/example/src/examples/Animations/AnimatedPoint.tsx @@ -28,7 +28,6 @@ const AnimatedPoint = memo(() => { const animator = useMemo(() => { return new __experimental.MovePointShapeAnimator(basePosition); - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const contents = useMemo(() => { @@ -81,7 +80,7 @@ const AnimatedPoint = memo(() => { { + onSlidingComplete={v => { duration.current = v * maxDuration; animator.moveTo({ coordinate: currentPosition.current, diff --git a/example/src/examples/Animations/DriveTheLine.js b/example/src/examples/Animations/DriveTheLine.js index bd47ea4072..f71f4382ec 100755 --- a/example/src/examples/Animations/DriveTheLine.js +++ b/example/src/examples/Animations/DriveTheLine.js @@ -70,9 +70,7 @@ class DriveTheLine extends React.Component { onStart() { const routeSimulator = new RouteSimulator(this.state.route); - routeSimulator.addListener((currentPoint) => - this.setState({ currentPoint }), - ); + routeSimulator.addListener(currentPoint => this.setState({ currentPoint })); routeSimulator.start(); this.setState({ routeSimulator }); } @@ -192,7 +190,7 @@ class DriveTheLine extends React.Component { return ( <> (this._map = c)} + ref={c => (this._map = c)} style={sheet.matchParent} styleURL={MapboxGL.StyleURL.Dark} > diff --git a/example/src/examples/Annotations/MarkerView.tsx b/example/src/examples/Annotations/MarkerView.tsx index 5e8afa95e6..70b7af25e1 100644 --- a/example/src/examples/Annotations/MarkerView.tsx +++ b/example/src/examples/Annotations/MarkerView.tsx @@ -42,7 +42,7 @@ const ShowMarkerView = () => { const onPressMap = (e: GeoJSON.Feature) => { const geometry = e.geometry as GeoJSON.Point; - setPointList((pl) => [...pl, geometry.coordinates]); + setPointList(pl => [...pl, geometry.coordinates]); }; return ( @@ -53,7 +53,7 @@ const ShowMarkerView = () => { ? 'allowOverlapWithPuck true' : 'allowOverlapWithPuck false' } - onPress={() => setAllowOverlapWithPuck((prev) => !prev)} + onPress={() => setAllowOverlapWithPuck(prev => !prev)} /> { +const PointAnnotationAnchors = props => { return ( diff --git a/example/src/examples/Annotations/ShowPointAnnotation.tsx b/example/src/examples/Annotations/ShowPointAnnotation.tsx index fa1d6a4eb8..1cc96961b5 100755 --- a/example/src/examples/Annotations/ShowPointAnnotation.tsx +++ b/example/src/examples/Annotations/ShowPointAnnotation.tsx @@ -53,16 +53,16 @@ const AnnotationWithRemoteImage = ({ coordinate={coordinate} title={title} draggable - onSelected={(feature) => + onSelected={feature => console.log('onSelected:', feature.id, feature.geometry.coordinates) } - onDrag={(feature) => + onDrag={feature => console.log('onDrag:', feature.id, feature.geometry.coordinates) } - onDragStart={(feature) => + onDragStart={feature => console.log('onDragStart:', feature.id, feature.geometry.coordinates) } - onDragEnd={(feature) => + onDragEnd={feature => console.log('onDragEnd:', feature.id, feature.geometry.coordinates) } ref={pointAnnotation} @@ -131,8 +131,8 @@ const ShowPointAnnotation = () => { return ( <> { - setCoordinates((prevState) => [ + onPress={feature => { + setCoordinates(prevState => [ ...prevState, (feature.geometry as Point).coordinates, ]); @@ -182,8 +182,8 @@ const ShowPointAnnotation = () => {