diff --git a/.eslintrc.js b/.eslintrc.js index 5c23c7be0839..54d035ab3850 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -171,6 +171,21 @@ module.exports = { '@typescript-eslint/switch-exhaustiveness-check': 'error', '@typescript-eslint/consistent-type-definitions': ['error', 'type'], '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + prefer: 'type-imports', + fixStyle: 'separate-type-imports', + }, + ], + '@typescript-eslint/no-import-type-side-effects': 'error', + '@typescript-eslint/consistent-type-exports': [ + 'error', + { + fixMixedExportsWithInlineTypeSpecifier: false, + }, + ], + 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], 'es/no-nullish-coalescing-operators': 'off', 'es/no-optional-chaining': 'off', 'valid-jsdoc': 'off', diff --git a/.github/actions/javascript/authorChecklist/categories/index.ts b/.github/actions/javascript/authorChecklist/categories/index.ts index 53e0ed2ab838..5ed63c647e74 100644 --- a/.github/actions/javascript/authorChecklist/categories/index.ts +++ b/.github/actions/javascript/authorChecklist/categories/index.ts @@ -1,4 +1,4 @@ -import Category from './Category'; +import type Category from './Category'; import newComponent from './newComponentCategory'; const categories: Category[] = [newComponent]; diff --git a/.github/actions/javascript/authorChecklist/categories/newComponentCategory.ts b/.github/actions/javascript/authorChecklist/categories/newComponentCategory.ts index 63e26c015a5a..405a687b5d3e 100644 --- a/.github/actions/javascript/authorChecklist/categories/newComponentCategory.ts +++ b/.github/actions/javascript/authorChecklist/categories/newComponentCategory.ts @@ -4,7 +4,7 @@ import traverse from '@babel/traverse'; import CONST from '../../../../libs/CONST'; import GithubUtils from '../../../../libs/GithubUtils'; import promiseSome from '../../../../libs/promiseSome'; -import Category from './Category'; +import type Category from './Category'; type SuperClassType = {superClass: {name?: string; object: {name: string}; property: {name: string}} | null; name: string}; diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml index 6aeecb3b4e05..813c341caaf6 100644 --- a/.github/workflows/platformDeploy.yml +++ b/.github/workflows/platformDeploy.yml @@ -10,7 +10,6 @@ on: env: SHOULD_DEPLOY_PRODUCTION: ${{ github.event_name == 'release' }} - DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer concurrency: group: ${{ github.workflow }}-${{ github.event_name }} @@ -174,6 +173,8 @@ jobs: name: Build and deploy iOS needs: validateActor if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} + env: + DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer runs-on: macos-13-xlarge steps: - name: Checkout diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 8b18b8aa5d53..25a14fb27e1b 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -10,9 +10,6 @@ on: types: [opened, synchronize, labeled] branches: ['*ci-test/**'] -env: - DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer - jobs: validateActor: runs-on: ubuntu-latest @@ -139,6 +136,7 @@ jobs: if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} + DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer runs-on: macos-13-xlarge steps: - name: Checkout diff --git a/.github/workflows/testGithubActionsWorkflows.yml b/.github/workflows/testGithubActionsWorkflows.yml index 58de3ba2d9f3..d052b343cf0c 100644 --- a/.github/workflows/testGithubActionsWorkflows.yml +++ b/.github/workflows/testGithubActionsWorkflows.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: workflow_call: pull_request: - types: [opened, reopened, edited, synchronize] + types: [opened, reopened, synchronize] branches-ignore: [staging, production] paths: ['.github/**'] diff --git a/android/app/build.gradle b/android/app/build.gradle index 4dd8d1766953..4c6289456041 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -96,8 +96,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001042002 - versionName "1.4.20-2" + versionCode 1001042104 + versionName "1.4.21-4" } flavorDimensions "default" diff --git a/assets/emojis/common.ts b/assets/emojis/common.ts index cbefb21cf2d6..b23383590c51 100644 --- a/assets/emojis/common.ts +++ b/assets/emojis/common.ts @@ -7,7 +7,7 @@ import TravelAndPlaces from '@assets/images/emojiCategoryIcons/plane.svg'; import AnimalsAndNature from '@assets/images/emojiCategoryIcons/plant.svg'; import Activities from '@assets/images/emojiCategoryIcons/soccer-ball.svg'; import FrequentlyUsed from '@assets/images/history.svg'; -import {HeaderEmoji, PickerEmojis} from './types'; +import type {HeaderEmoji, PickerEmojis} from './types'; const skinTones = [ { diff --git a/assets/emojis/en.ts b/assets/emojis/en.ts index 0a1ca7611117..28051e5ecd99 100644 --- a/assets/emojis/en.ts +++ b/assets/emojis/en.ts @@ -1,4 +1,4 @@ -import {EmojisList} from './types'; +import type {EmojisList} from './types'; /* eslint-disable @typescript-eslint/naming-convention */ const enEmojis: EmojisList = { diff --git a/assets/emojis/es.ts b/assets/emojis/es.ts index 46f825643859..0d23f887f556 100644 --- a/assets/emojis/es.ts +++ b/assets/emojis/es.ts @@ -1,4 +1,4 @@ -import {EmojisList} from './types'; +import type {EmojisList} from './types'; /* eslint-disable @typescript-eslint/naming-convention */ const esEmojis: EmojisList = { diff --git a/assets/emojis/index.ts b/assets/emojis/index.ts index bc62adc4b252..5e5565da1499 100644 --- a/assets/emojis/index.ts +++ b/assets/emojis/index.ts @@ -1,7 +1,7 @@ import emojis from './common'; import enEmojis from './en'; import esEmojis from './es'; -import {Emoji} from './types'; +import type {Emoji} from './types'; type EmojiTable = Record; diff --git a/assets/emojis/types.ts b/assets/emojis/types.ts index c3a3b692f202..e8c222fde948 100644 --- a/assets/emojis/types.ts +++ b/assets/emojis/types.ts @@ -1,4 +1,4 @@ -import IconAsset from '@src/types/utils/IconAsset'; +import type IconAsset from '@src/types/utils/IconAsset'; type Emoji = { code: string; diff --git a/contributingGuides/TS_STYLE.md b/contributingGuides/TS_STYLE.md index a583941bf71d..b60c28147a45 100644 --- a/contributingGuides/TS_STYLE.md +++ b/contributingGuides/TS_STYLE.md @@ -26,6 +26,7 @@ - [1.19 Satisfies operator](#satisfies-operator) - [1.20 Hooks instead of HOCs](#hooks-instead-of-hocs) - [1.21 `compose` usage](#compose-usage) + - [1.22 Type imports](#type-imports) - [Exception to Rules](#exception-to-rules) - [Communication Items](#communication-items) - [Migration Guidelines](#migration-guidelines) @@ -383,7 +384,7 @@ type Foo = { -- [1.15](#file-organization) **File organization**: In modules with platform-specific implementations, create `types.ts` to define shared types. Import and use shared types in each platform specific files. Do not use [`satisfies` operator](#satisfies-operator) for platform-specific implementations, always define shared types that complies with all variants. +- [1.15](#file-organization) **File organization**: In modules with platform-specific implementations, create `types.ts` to define shared types. Import and use shared types in each platform specific files. Do not use [`satisfies` operator](#satisfies-operator) for platform-specific implementations, always define shared types that complies with all variants. > Why? To encourage consistent API across platform-specific implementations. If you're migrating module that doesn't have a default implement (i.e. `index.ts`, e.g. `getPlatform`), refer to [Migration Guidelines](#migration-guidelines) for further information. @@ -514,7 +515,7 @@ type Foo = { - [1.20](#hooks-instead-of-hocs) **Hooks instead of HOCs**: Replace HOCs usage with Hooks whenever possible. - + > Why? Hooks are easier to use (can be used inside the function component), and don't need nesting or `compose` when exporting the component. It also allows us to remove `compose` completely in some components since it has been bringing up some issues with TypeScript. Read the [`compose` usage](#compose-usage) section for further information about the TypeScript issues with `compose`. > Note: Because Onyx doesn't provide a hook yet, in a component that accesses Onyx data with `withOnyx` HOC, please make sure that you don't use other HOCs (if applicable) to avoid HOC nesting. @@ -571,7 +572,7 @@ type Foo = { - [1.21](#compose-usage) **`compose` usage**: Avoid the usage of `compose` function to compose HOCs in TypeScript files. Use nesting instead. - + > Why? `compose` function doesn't work well with TypeScript when dealing with several HOCs being used in a component, many times resulting in wrong types and errors. Instead, nesting can be used to allow a seamless use of multiple HOCs and result in a correct return type of the compoment. Also, you can use [hooks instead of HOCs](#hooks-instead-of-hocs) whenever possible to minimize or even remove the need of HOCs in the component. ```ts @@ -607,6 +608,38 @@ type Foo = { export default withCurrentUserPersonalDetails(ComponentWithReportOrNotFound); ``` + + +- [1.22](#type-imports) **Type imports/exports**: Always use the `type` keyword when importing/exporting types + + > Why? In order to improve code clarity and consistency and reduce bundle size after typescript transpilation, we enforce the all type imports/exports to contain the `type` keyword. This way, TypeScript can automatically remove those imports from the transpiled JavaScript bundle + + Imports: + ```ts + // BAD + import {SomeType} from './a' + import someVariable from './a' + + import {someVariable, SomeOtherType} from './b' + + // GOOD + import type {SomeType} from './a' + import someVariable from './a' + ``` + + Exports: + ```ts + // BAD + export {SomeType} + export someVariable + // or + export {someVariable, SomeOtherType} + + // GOOD + export type {SomeType} + export someVariable + ``` + ## Exception to Rules Most of the rules are enforced in ESLint or checked by TypeScript. If you think your particular situation warrants an exception, post the context in the `#expensify-open-source` Slack channel with your message prefixed with `TS EXCEPTION:`. The internal engineer assigned to the PR should be the one that approves each exception, however all discussion regarding granting exceptions should happen in the public channel instead of the GitHub PR page so that the TS migration team can access them easily. diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md b/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md index 65361ba1af9a..0856e2694340 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md +++ b/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md @@ -3,7 +3,7 @@ title: Certinia description: Guide to connecting Expensify and Certinia FFA and PSA/SRP (formerly known as FinancialForce) --- # Overview -[Cetinia](https://use.expensify.com/financialforce) (Formerly known as FinancialForce)is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both. +[Cetinia](https://use.expensify.com/financialforce) (formerly known as FinancialForce) is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both. # Before connecting to Certinia Install the Expensify bundle in Certinia using the relevant installer: diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 8d60003e1355..ac41382486a5 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.20 + 1.4.21 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.20.2 + 1.4.21.4 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 740a07ea24ac..ab58f3c293bd 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.4.20 + 1.4.21 CFBundleSignature ???? CFBundleVersion - 1.4.20.2 + 1.4.21.4 diff --git a/package-lock.json b/package-lock.json index e00ae28b8113..15964d8c5f3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.20-2", + "version": "1.4.21-4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.20-2", + "version": "1.4.21-4", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -99,7 +99,7 @@ "react-native-pdf": "^6.7.3", "react-native-performance": "^5.1.0", "react-native-permissions": "^3.9.3", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5", "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", @@ -201,6 +201,7 @@ "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-expensify": "^2.0.43", "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.1.0", "eslint-plugin-jsdoc": "^46.2.6", "eslint-plugin-jsx-a11y": "^6.6.1", @@ -21202,8 +21203,7 @@ "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/keyv": { "version": "3.1.4", @@ -23403,15 +23403,15 @@ "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -23448,15 +23448,34 @@ "node": ">=0.10.0" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -23467,14 +23486,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -30582,12 +30601,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -30595,15 +30616,15 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { - "version": "2.7.4", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -30621,7 +30642,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -30719,23 +30739,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.26.0", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, - "license": "MIT", "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -30745,11 +30770,12 @@ } }, "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import/node_modules/doctrine": { @@ -30765,12 +30791,14 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT" + "bin": { + "semver": "bin/semver.js" + } }, "node_modules/eslint-plugin-jest": { "version": "24.7.0", @@ -33493,10 +33521,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "license": "MIT" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -34214,6 +34244,17 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hast-to-hyperscript": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", @@ -35900,11 +35941,11 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -44759,14 +44800,14 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -44792,6 +44833,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "node_modules/object.hasown": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", @@ -44819,14 +44872,14 @@ } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -47631,8 +47684,8 @@ }, "node_modules/react-native-picker-select": { "version": "8.1.0", - "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", - "integrity": "sha512-ly0ZCt3K4RX7t9lfSb2OSGAw0cv8UqdMoxNfh5j+KujYYq+N8VsI9O/lmqquNeX/AMp5hM3fjetEWue4nZw/hA==", + "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5", + "integrity": "sha512-NpXXyK+UuANYOysjUb9pCoq9SookRYPfpOcM4shxOD4+2Fkh7TYt2LBUpAdBicMHmtaR43RWXVQk9pMimOhg2w==", "license": "MIT", "dependencies": { "lodash.isequal": "^4.5.0" @@ -53277,12 +53330,13 @@ "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { - "version": "3.14.1", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, - "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -53304,7 +53358,6 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -73074,15 +73127,15 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" } }, @@ -73101,27 +73154,40 @@ "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", "devOptional": true }, + "array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, @@ -78429,11 +78495,14 @@ "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.6", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "requires": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" }, "dependencies": { "debug": { @@ -78448,7 +78517,9 @@ } }, "eslint-module-utils": { - "version": "2.7.4", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -78520,29 +78591,37 @@ } }, "eslint-plugin-import": { - "version": "2.26.0", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "debug": { - "version": "2.6.9", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "doctrine": { @@ -78554,10 +78633,10 @@ "esutils": "^2.0.2" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -80424,9 +80503,9 @@ "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "function.prototype.name": { "version": "1.1.5", @@ -80914,6 +80993,14 @@ "minimalistic-assert": "^1.0.1" } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, "hast-to-hyperscript": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", @@ -82096,11 +82183,11 @@ } }, "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "is-data-descriptor": { @@ -88377,14 +88464,14 @@ } }, "object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "object.getownpropertydescriptors": { @@ -88397,6 +88484,18 @@ "es-abstract": "^1.20.1" } }, + "object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "object.hasown": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", @@ -88417,14 +88516,14 @@ } }, "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "objectorarray": { @@ -90460,9 +90559,9 @@ "requires": {} }, "react-native-picker-select": { - "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", - "integrity": "sha512-ly0ZCt3K4RX7t9lfSb2OSGAw0cv8UqdMoxNfh5j+KujYYq+N8VsI9O/lmqquNeX/AMp5hM3fjetEWue4nZw/hA==", - "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", + "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5", + "integrity": "sha512-NpXXyK+UuANYOysjUb9pCoq9SookRYPfpOcM4shxOD4+2Fkh7TYt2LBUpAdBicMHmtaR43RWXVQk9pMimOhg2w==", + "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5", "requires": { "lodash.isequal": "^4.5.0" } @@ -94475,11 +94574,13 @@ "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" }, "tsconfig-paths": { - "version": "3.14.1", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" }, diff --git a/package.json b/package.json index 28dc12938d60..29ade80b518d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.20-2", + "version": "1.4.21-4", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -147,7 +147,7 @@ "react-native-pdf": "^6.7.3", "react-native-performance": "^5.1.0", "react-native-permissions": "^3.9.3", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5", "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", @@ -249,6 +249,7 @@ "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-expensify": "^2.0.43", "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^24.1.0", "eslint-plugin-jsdoc": "^46.2.6", "eslint-plugin-jsx-a11y": "^6.6.1", diff --git a/src/CONFIG.ts b/src/CONFIG.ts index 61e347671269..37da65f0c305 100644 --- a/src/CONFIG.ts +++ b/src/CONFIG.ts @@ -1,5 +1,6 @@ import {Platform} from 'react-native'; -import Config, {NativeConfig} from 'react-native-config'; +import type {NativeConfig} from 'react-native-config'; +import Config from 'react-native-config'; import CONST from './CONST'; import getPlatform from './libs/getPlatform'; import * as Url from './libs/Url'; diff --git a/src/CONST.ts b/src/CONST.ts index abba27b0c33b..b5563825e016 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -512,6 +512,7 @@ const CONST = { CLOSED: 'CLOSED', CREATED: 'CREATED', IOU: 'IOU', + MARKEDREIMBURSED: 'MARKEDREIMBURSED', MODIFIEDEXPENSE: 'MODIFIEDEXPENSE', MOVED: 'MOVED', REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', @@ -719,6 +720,7 @@ const CONST = { TRIE_INITIALIZATION: 'trie_initialization', COMMENT_LENGTH_DEBOUNCE_TIME: 500, SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, + RESIZE_DEBOUNCE_TIME: 100, }, PRIORITY_MODE: { GSD: 'gsd', @@ -853,7 +855,7 @@ const CONST = { // It's copied here so that the same regex pattern can be used in form validations to be consistent with the server. VALIDATE_FOR_HTML_TAG_REGEX: /<([^>\s]+)(?:[^>]*?)>/g, - VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+[\s\w~!@#$%^&*(){}[\];':"`|?.,/\\+\-=<]+.*[\s]*)>/g, + VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+.+[\s]*)>/g, WHITELISTED_TAGS: [/<>/, /< >/, /<->/, /<-->/, /
/, //], @@ -979,6 +981,7 @@ const CONST = { CHAT_FOOTER_SECONDARY_ROW_HEIGHT: 15, CHAT_FOOTER_SECONDARY_ROW_PADDING: 5, CHAT_FOOTER_MIN_HEIGHT: 65, + CHAT_FOOTER_HORIZONTAL_PADDING: 40, CHAT_SKELETON_VIEW: { AVERAGE_ROW_HEIGHT: 80, HEIGHT_FOR_ROW_COUNT: { @@ -2942,6 +2945,7 @@ const CONST = { PARENT_CHILD_SEPARATOR: ': ', CATEGORY_LIST_THRESHOLD: 8, TAG_LIST_THRESHOLD: 8, + TAX_RATES_LIST_THRESHOLD: 8, COLON: ':', MAPBOX: { PADDING: 50, diff --git a/src/NAVIGATORS.ts b/src/NAVIGATORS.ts index a3a041e65684..c68a950d3501 100644 --- a/src/NAVIGATORS.ts +++ b/src/NAVIGATORS.ts @@ -4,6 +4,7 @@ * */ export default { CENTRAL_PANE_NAVIGATOR: 'CentralPaneNavigator', + LEFT_MODAL_NAVIGATOR: 'LeftModalNavigator', RIGHT_MODAL_NAVIGATOR: 'RightModalNavigator', FULL_SCREEN_NAVIGATOR: 'FullScreenNavigator', } as const; diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 53cd37e71f67..89ddbdc06883 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -1,8 +1,8 @@ -import {OnyxEntry} from 'react-native-onyx/lib/types'; -import {ValueOf} from 'type-fest'; -import CONST from './CONST'; -import * as OnyxTypes from './types/onyx'; -import DeepValueOf from './types/utils/DeepValueOf'; +import type {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {ValueOf} from 'type-fest'; +import type CONST from './CONST'; +import type * as OnyxTypes from './types/onyx'; +import type DeepValueOf from './types/utils/DeepValueOf'; /** * This is a file containing constants for all the top level keys in our store @@ -250,6 +250,7 @@ const ONYXKEYS = { POLICY_CATEGORIES: 'policyCategories_', POLICY_RECENTLY_USED_CATEGORIES: 'policyRecentlyUsedCategories_', POLICY_TAGS: 'policyTags_', + POLICY_TAX_RATE: 'policyTaxRates_', POLICY_RECENTLY_USED_TAGS: 'policyRecentlyUsedTags_', POLICY_REPORT_FIELDS: 'policyReportFields_', POLICY_RECENTLY_USED_REPORT_FIELDS: 'policyRecentlyUsedReportFields_', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index db17378684d6..35fa4bbf0837 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1,5 +1,5 @@ -import {IsEqual, ValueOf} from 'type-fest'; -import CONST from './CONST'; +import type {IsEqual, ValueOf} from 'type-fest'; +import type CONST from './CONST'; // This is a file containing constants for all the routes we want to be able to go to @@ -322,6 +322,16 @@ const ROUTES = { getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => getUrlWithBackToParam(`create/${iouType}/amount/${transactionID}/${reportID}/`, backTo), }, + MONEY_REQUEST_STEP_TAX_RATE: { + route: 'create/:iouType/taxRate/:transactionID/:reportID?', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo: string) => + getUrlWithBackToParam(`create/${iouType}/taxRate/${transactionID}/${reportID}`, backTo), + }, + MONEY_REQUEST_STEP_TAX_AMOUNT: { + route: 'create/:iouType/taxAmount/:transactionID/:reportID?', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo: string) => + getUrlWithBackToParam(`create/${iouType}/taxAmount/${transactionID}/${reportID}`, backTo), + }, MONEY_REQUEST_STEP_CATEGORY: { route: 'create/:iouType/category/:transactionID/:reportID/', getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => diff --git a/src/SCREENS.ts b/src/SCREENS.ts index c1d2059cd3b0..91c4153bacd2 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -2,7 +2,7 @@ * This is a file containing constants for all of the screen names. In most cases, we should use the routes for * navigation. But there are situations where we may need to access screen names directly. */ -import DeepValueOf from './types/utils/DeepValueOf'; +import type DeepValueOf from './types/utils/DeepValueOf'; const PROTECTED_SCREENS = { HOME: 'Home', @@ -81,10 +81,12 @@ const SCREENS = { SAVE_THE_WORLD: { ROOT: 'SaveTheWorld_Root', }, + LEFT_MODAL: { + SEARCH: 'Search', + }, RIGHT_MODAL: { SETTINGS: 'Settings', NEW_CHAT: 'NewChat', - SEARCH: 'Search', DETAILS: 'Details', PROFILE: 'Profile', REPORT_DETAILS: 'Report_Details', @@ -130,6 +132,8 @@ const SCREENS = { STEP_SCAN: 'Money_Request_Step_Scan', STEP_TAG: 'Money_Request_Step_Tag', STEP_WAYPOINT: 'Money_Request_Step_Waypoint', + STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount', + STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate', ROOT: 'Money_Request', AMOUNT: 'Money_Request_Amount', PARTICIPANTS: 'Money_Request_Participants', diff --git a/src/components/AddressSearch/index.js b/src/components/AddressSearch/index.js index d9e4ef2c0f6e..31b04a3d954f 100644 --- a/src/components/AddressSearch/index.js +++ b/src/components/AddressSearch/index.js @@ -111,6 +111,9 @@ const propTypes = { /** Information about the network */ network: networkPropTypes.isRequired, + /** Location bias for querying search results. */ + locationBias: PropTypes.string, + ...withLocalizePropTypes, }; @@ -138,6 +141,7 @@ const defaultProps = { maxInputLength: undefined, predefinedPlaces: [], resultTypes: 'address', + locationBias: undefined, }; function AddressSearch({ @@ -162,6 +166,7 @@ function AddressSearch({ shouldSaveDraft, translate, value, + locationBias, }) { const theme = useTheme(); const styles = useThemeStyles(); @@ -179,11 +184,11 @@ function AddressSearch({ language: preferredLocale, types: resultTypes, components: isLimitedToUSA ? 'country:us' : undefined, + ...(locationBias && {locationbias: locationBias}), }), - [preferredLocale, resultTypes, isLimitedToUSA], + [preferredLocale, resultTypes, isLimitedToUSA, locationBias], ); const shouldShowCurrentLocationButton = canUseCurrentLocation && searchValue.trim().length === 0 && isFocused; - const saveLocationDetails = (autocompleteData, details) => { const addressComponents = details.address_components; if (!addressComponents) { @@ -192,7 +197,7 @@ function AddressSearch({ // amount of data massaging needs to happen for what the parent expects to get from this function. if (_.size(details)) { onPress({ - address: lodashGet(details, 'description'), + address: autocompleteData.description || lodashGet(details, 'description', ''), lat: lodashGet(details, 'geometry.location.lat', 0), lng: lodashGet(details, 'geometry.location.lng', 0), name: lodashGet(details, 'name'), @@ -261,7 +266,7 @@ function AddressSearch({ lat: lodashGet(details, 'geometry.location.lat', 0), lng: lodashGet(details, 'geometry.location.lng', 0), - address: lodashGet(details, 'formatted_address', ''), + address: autocompleteData.description || lodashGet(details, 'formatted_address', ''), }; // If the address is not in the US, use the full length state name since we're displaying the address's diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.tsx b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.tsx index 1bcdbb383f7a..bb3792f59d9f 100644 --- a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.tsx +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.tsx @@ -1,6 +1,7 @@ import Str from 'expensify-common/lib/str'; import React, {useEffect, useRef} from 'react'; -import {Text as RNText, StyleSheet} from 'react-native'; +import type {Text as RNText} from 'react-native'; +import {StyleSheet} from 'react-native'; import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; diff --git a/src/components/AnchorForCommentsOnly/types.ts b/src/components/AnchorForCommentsOnly/types.ts index 005364c2077f..eea8571f5277 100644 --- a/src/components/AnchorForCommentsOnly/types.ts +++ b/src/components/AnchorForCommentsOnly/types.ts @@ -1,5 +1,5 @@ -import {StyleProp, TextStyle} from 'react-native'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type {StyleProp, TextStyle} from 'react-native'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; type AnchorForCommentsOnlyProps = ChildrenProps & { /** The URL to open */ diff --git a/src/components/AnimatedStep/AnimatedStepContext.ts b/src/components/AnimatedStep/AnimatedStepContext.ts index 3b4c5f79a34f..14dba4b27cc2 100644 --- a/src/components/AnimatedStep/AnimatedStepContext.ts +++ b/src/components/AnimatedStep/AnimatedStepContext.ts @@ -1,6 +1,7 @@ -import React, {createContext} from 'react'; -import {ValueOf} from 'type-fest'; -import CONST from '@src/CONST'; +import type React from 'react'; +import {createContext} from 'react'; +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; type AnimationDirection = ValueOf; diff --git a/src/components/AnimatedStep/AnimatedStepProvider.tsx b/src/components/AnimatedStep/AnimatedStepProvider.tsx index 53b3a0e0a53d..ea268e1d52cb 100644 --- a/src/components/AnimatedStep/AnimatedStepProvider.tsx +++ b/src/components/AnimatedStep/AnimatedStepProvider.tsx @@ -1,7 +1,8 @@ import React, {useMemo, useState} from 'react'; import CONST from '@src/CONST'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; -import AnimatedStepContext, {AnimationDirection} from './AnimatedStepContext'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import type {AnimationDirection} from './AnimatedStepContext'; +import AnimatedStepContext from './AnimatedStepContext'; function AnimatedStepProvider({children}: ChildrenProps): React.ReactNode { const [animationDirection, setAnimationDirection] = useState(CONST.ANIMATION_DIRECTION.IN); diff --git a/src/components/AnimatedStep/index.tsx b/src/components/AnimatedStep/index.tsx index e2b9952c0617..66d2108ca5d8 100644 --- a/src/components/AnimatedStep/index.tsx +++ b/src/components/AnimatedStep/index.tsx @@ -1,11 +1,11 @@ import React, {useMemo} from 'react'; -import {StyleProp, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; import * as Animatable from 'react-native-animatable'; import useThemeStyles from '@hooks/useThemeStyles'; import useNativeDriver from '@libs/useNativeDriver'; import CONST from '@src/CONST'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; -import {AnimationDirection} from './AnimatedStepContext'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import type {AnimationDirection} from './AnimatedStepContext'; type AnimatedStepProps = ChildrenProps & { /** Styles to be assigned to Container */ diff --git a/src/components/AnimatedStep/useAnimatedStepContext.ts b/src/components/AnimatedStep/useAnimatedStepContext.ts index 3edc71e5289e..2adde8fd576e 100644 --- a/src/components/AnimatedStep/useAnimatedStepContext.ts +++ b/src/components/AnimatedStep/useAnimatedStepContext.ts @@ -1,5 +1,6 @@ import {useContext} from 'react'; -import AnimatedStepContext, {StepContext} from './AnimatedStepContext'; +import type {StepContext} from './AnimatedStepContext'; +import AnimatedStepContext from './AnimatedStepContext'; function useAnimatedStepContext(): StepContext { const context = useContext(AnimatedStepContext); diff --git a/src/components/AnonymousReportFooter.tsx b/src/components/AnonymousReportFooter.tsx index 877ca9444661..ad79e316baf3 100644 --- a/src/components/AnonymousReportFooter.tsx +++ b/src/components/AnonymousReportFooter.tsx @@ -1,11 +1,11 @@ import React from 'react'; import {Text, View} from 'react-native'; -import {OnyxCollection} from 'react-native-onyx'; -import {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx/lib/types'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Session from '@userActions/Session'; -import {PersonalDetails, Report} from '@src/types/onyx'; +import type {PersonalDetails, Report} from '@src/types/onyx'; import AvatarWithDisplayName from './AvatarWithDisplayName'; import Button from './Button'; import ExpensifyWordmark from './ExpensifyWordmark'; diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 8604d20130c7..083c8340baa6 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -1,6 +1,7 @@ import lodashEscape from 'lodash/escape'; import React from 'react'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; @@ -30,14 +31,14 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}} const originalMessage = reportClosedAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED ? reportClosedAction.originalMessage : null; const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT; - let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]?.displayName); + let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]); let oldDisplayName: string | undefined; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { const newAccountID = originalMessage?.newAccountID; const oldAccountID = originalMessage?.oldAccountID; - displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]?.displayName); - oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]?.displayName); + displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]); + oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]); } const shouldRenderHTML = archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT; diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index 863e59aa4474..d24d1e18907f 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -358,7 +358,15 @@ function AttachmentModal(props) { setIsModalOpen(true); }, []); - const sourceForAttachmentView = props.source || source; + useEffect(() => { + setSource(props.source); + }, [props.source]); + + useEffect(() => { + setIsAuthTokenRequired(props.isAuthTokenRequired); + }, [props.isAuthTokenRequired]); + + const sourceForAttachmentView = source || props.source; const threeDotsMenuItems = useMemo(() => { if (!props.isReceiptAttachment || !props.parentReport || !props.parentReportActions) { @@ -368,7 +376,7 @@ function AttachmentModal(props) { const parentReportAction = props.parentReportActions[props.report.parentReportActionID]; const canEdit = - ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT) && + ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT, props.transaction) && !TransactionUtils.isDistanceRequest(props.transaction); if (canEdit) { menuItems.push({ @@ -396,7 +404,7 @@ function AttachmentModal(props) { } return menuItems; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file]); + }, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file, source]); // There are a few things that shouldn't be set until we absolutely know if the file is a receipt or an attachment. // props.isReceiptAttachment will be null until its certain what the file is, in which case it will then be true|false. diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index c2320f7c0202..fc3bf4659bd7 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -1,6 +1,7 @@ import {FlashList} from '@shopify/flash-list'; -import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useRef} from 'react'; -import {View} from 'react-native'; +import type {ForwardedRef, ReactElement} from 'react'; +import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react'; +import type {View} from 'react-native'; // We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another import {ScrollView} from 'react-native-gesture-handler'; import Animated, {Easing, FadeOutDown, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; @@ -8,6 +9,8 @@ import ColorSchemeWrapper from '@components/ColorSchemeWrapper'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import viewForwardedRef from '@src/types/utils/viewForwardedRef'; import type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps} from './types'; @@ -39,6 +42,7 @@ function BaseAutoCompleteSuggestions( }: AutoCompleteSuggestionsProps, ref: ForwardedRef, ) { + const {windowWidth, isLargeScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const rowHeight = useSharedValue(0); @@ -64,7 +68,13 @@ function BaseAutoCompleteSuggestions( const innerHeight = CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length; const animatedStyles = useAnimatedStyle(() => StyleUtils.getAutoCompleteSuggestionContainerStyle(rowHeight.value)); - + const estimatedListSize = useMemo( + () => ({ + height: CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length, + width: (isLargeScreenWidth ? windowWidth - variables.sideBarWidth : windowWidth) - CONST.CHAT_FOOTER_HORIZONTAL_PADDING, + }), + [isLargeScreenWidth, suggestions.length, windowWidth], + ); useEffect(() => { rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length, isSuggestionPickerLarge), { duration: 100, @@ -88,6 +98,7 @@ function BaseAutoCompleteSuggestions( void; diff --git a/src/components/AutoUpdateTime.tsx b/src/components/AutoUpdateTime.tsx index 258bdb281eb2..f6be32fd3970 100644 --- a/src/components/AutoUpdateTime.tsx +++ b/src/components/AutoUpdateTime.tsx @@ -6,9 +6,10 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; -import {Timezone} from '@src/types/onyx/PersonalDetails'; +import type {Timezone} from '@src/types/onyx/PersonalDetails'; import Text from './Text'; -import withLocalize, {WithLocalizeProps} from './withLocalize'; +import type {WithLocalizeProps} from './withLocalize'; +import withLocalize from './withLocalize'; type AutoUpdateTimeProps = WithLocalizeProps & { /** Timezone of the user from their personal details */ diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index 65b0b6c36061..4da91c2e7d19 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -1,14 +1,15 @@ import React, {useEffect, useState} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ReportUtils from '@libs/ReportUtils'; -import {AvatarSource} from '@libs/UserUtils'; +import type {AvatarSource} from '@libs/UserUtils'; import type {AvatarSizeName} from '@styles/utils'; import CONST from '@src/CONST'; -import {AvatarType} from '@src/types/onyx/OnyxCommon'; +import type {AvatarType} from '@src/types/onyx/OnyxCommon'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import Image from './Image'; diff --git a/src/components/AvatarWithDisplayName.tsx b/src/components/AvatarWithDisplayName.tsx index b9bae33d7e23..4580f3b7e4d4 100644 --- a/src/components/AvatarWithDisplayName.tsx +++ b/src/components/AvatarWithDisplayName.tsx @@ -1,7 +1,8 @@ import React, {useCallback, useEffect, useRef} from 'react'; import {View} from 'react-native'; -import {OnyxCollection, OnyxEntry, withOnyx} from 'react-native-onyx'; -import {ValueOf} from 'type-fest'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -11,7 +12,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {PersonalDetails, Policy, Report, ReportActions} from '@src/types/onyx'; +import type {PersonalDetails, Policy, Report, ReportActions} from '@src/types/onyx'; import DisplayNames from './DisplayNames'; import MultipleAvatars from './MultipleAvatars'; import ParentNavigationSubtitle from './ParentNavigationSubtitle'; diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index d766d4cb6f22..71193147c292 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -322,7 +322,7 @@ function AvatarWithImagePicker({ src={Expensicons.Camera} width={variables.iconSizeSmall} height={variables.iconSizeSmall} - fill={theme.textLight} + fill={theme.icon} /> diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 70aebc30ee83..5be33e6ff2ec 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -1,5 +1,6 @@ import React, {useCallback} from 'react'; -import {GestureResponderEvent, PressableStateCallbackType, StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {GestureResponderEvent, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; diff --git a/src/components/Banner.tsx b/src/components/Banner.tsx index d57257efab49..56fe7c4d0b42 100644 --- a/src/components/Banner.tsx +++ b/src/components/Banner.tsx @@ -1,5 +1,6 @@ import React, {memo} from 'react'; -import {StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; diff --git a/src/components/BaseMiniContextMenuItem.tsx b/src/components/BaseMiniContextMenuItem.tsx index 8d115a37cba7..1f9a14cdfdee 100644 --- a/src/components/BaseMiniContextMenuItem.tsx +++ b/src/components/BaseMiniContextMenuItem.tsx @@ -1,5 +1,7 @@ -import React, {ForwardedRef} from 'react'; -import {PressableStateCallbackType, View} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React from 'react'; +import type {PressableStateCallbackType} from 'react-native'; +import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import DomUtils from '@libs/DomUtils'; diff --git a/src/components/BlockingViews/BlockingView.tsx b/src/components/BlockingViews/BlockingView.tsx index 3a038c58d886..edec30604b88 100644 --- a/src/components/BlockingViews/BlockingView.tsx +++ b/src/components/BlockingViews/BlockingView.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import {ImageSourcePropType, View} from 'react-native'; -import {SvgProps} from 'react-native-svg'; +import type {ImageSourcePropType} from 'react-native'; +import {View} from 'react-native'; +import type {SvgProps} from 'react-native-svg'; import AutoEmailLink from '@components/AutoEmailLink'; import Icon from '@components/Icon'; import Text from '@components/Text'; @@ -9,7 +10,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import variables from '@styles/variables'; -import {TranslationPaths} from '@src/languages/types'; +import type {TranslationPaths} from '@src/languages/types'; type BlockingViewProps = { /** Expensicon for the page */ diff --git a/src/components/BlockingViews/FullPageNotFoundView.tsx b/src/components/BlockingViews/FullPageNotFoundView.tsx index 6d7f838bf6c2..5993e60861f5 100644 --- a/src/components/BlockingViews/FullPageNotFoundView.tsx +++ b/src/components/BlockingViews/FullPageNotFoundView.tsx @@ -6,7 +6,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import variables from '@styles/variables'; -import {TranslationPaths} from '@src/languages/types'; +import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import BlockingView from './BlockingView'; diff --git a/src/components/BlockingViews/FullPageOfflineBlockingView.tsx b/src/components/BlockingViews/FullPageOfflineBlockingView.tsx index a9ebcf969ae5..787752dd4e72 100644 --- a/src/components/BlockingViews/FullPageOfflineBlockingView.tsx +++ b/src/components/BlockingViews/FullPageOfflineBlockingView.tsx @@ -3,7 +3,7 @@ import * as Expensicons from '@components/Icon/Expensicons'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useTheme from '@hooks/useTheme'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; import BlockingView from './BlockingView'; function FullPageOfflineBlockingView({children}: ChildrenProps) { diff --git a/src/components/Breadcrumbs.tsx b/src/components/Breadcrumbs.tsx index fa761218b4a0..6af3a4c6d477 100644 --- a/src/components/Breadcrumbs.tsx +++ b/src/components/Breadcrumbs.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import LogoComponent from '@assets/images/expensify-wordmark.svg'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index cdafd0b0b93b..dd0499d4d243 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -1,6 +1,8 @@ import {useIsFocused} from '@react-navigation/native'; -import React, {ForwardedRef, useCallback} from 'react'; -import {ActivityIndicator, GestureResponderEvent, StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {useCallback} from 'react'; +import type {GestureResponderEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {ActivityIndicator, View} from 'react-native'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; @@ -12,8 +14,8 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import HapticFeedback from '@libs/HapticFeedback'; import CONST from '@src/CONST'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; -import IconAsset from '@src/types/utils/IconAsset'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import type IconAsset from '@src/types/utils/IconAsset'; import validateSubmitShortcut from './validateSubmitShortcut'; type ButtonWithText = { @@ -221,7 +223,7 @@ function Button( @@ -232,7 +234,7 @@ function Button( diff --git a/src/components/Button/validateSubmitShortcut/index.native.ts b/src/components/Button/validateSubmitShortcut/index.native.ts index 7687855f109b..3f277ed208a1 100644 --- a/src/components/Button/validateSubmitShortcut/index.native.ts +++ b/src/components/Button/validateSubmitShortcut/index.native.ts @@ -1,4 +1,4 @@ -import ValidateSubmitShortcut from './types'; +import type ValidateSubmitShortcut from './types'; /** * Validate if the submit shortcut should be triggered depending on the button state diff --git a/src/components/Button/validateSubmitShortcut/index.ts b/src/components/Button/validateSubmitShortcut/index.ts index 55b3e44192e4..695c56af7bb7 100644 --- a/src/components/Button/validateSubmitShortcut/index.ts +++ b/src/components/Button/validateSubmitShortcut/index.ts @@ -1,4 +1,4 @@ -import ValidateSubmitShortcut from './types'; +import type ValidateSubmitShortcut from './types'; /** * Validate if the submit shortcut should be triggered depending on the button state diff --git a/src/components/Button/validateSubmitShortcut/types.ts b/src/components/Button/validateSubmitShortcut/types.ts index 9970e1478a4c..088718d0334e 100644 --- a/src/components/Button/validateSubmitShortcut/types.ts +++ b/src/components/Button/validateSubmitShortcut/types.ts @@ -1,4 +1,4 @@ -import {GestureResponderEvent} from 'react-native'; +import type {GestureResponderEvent} from 'react-native'; type ValidateSubmitShortcut = (isFocused: boolean, isDisabled: boolean, isLoading: boolean, event?: GestureResponderEvent | KeyboardEvent) => boolean; diff --git a/src/components/CardPreview.tsx b/src/components/CardPreview.tsx index 2196e6f441bb..3ac56d6b26a8 100644 --- a/src/components/CardPreview.tsx +++ b/src/components/CardPreview.tsx @@ -1,12 +1,13 @@ import React from 'react'; import {View} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import ExpensifyCardImage from '@assets/images/expensify-card.svg'; import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; import ONYXKEYS from '@src/ONYXKEYS'; -import {PrivatePersonalDetails, Session} from '@src/types/onyx'; +import type {PrivatePersonalDetails, Session} from '@src/types/onyx'; import ImageSVG from './ImageSVG'; import Text from './Text'; diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index ac18b550501d..7e7720b57a6e 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,10 +1,12 @@ -import React, {type ForwardedRef, forwardRef, type MouseEventHandler, type KeyboardEvent as ReactKeyboardEvent} from 'react'; -import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'; +import React, {forwardRef} from 'react'; +import type {ForwardedRef, MouseEventHandler, KeyboardEvent as ReactKeyboardEvent} from 'react'; +import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; diff --git a/src/components/CheckboxWithLabel.tsx b/src/components/CheckboxWithLabel.tsx index 9660c9e1a2e5..a25ccf184f52 100644 --- a/src/components/CheckboxWithLabel.tsx +++ b/src/components/CheckboxWithLabel.tsx @@ -1,5 +1,7 @@ -import React, {ComponentType, ForwardedRef, useState} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {ComponentType, ForwardedRef} from 'react'; +import React, {useState} from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; import Checkbox from './Checkbox'; diff --git a/src/components/CollapsibleSection/Collapsible/index.native.tsx b/src/components/CollapsibleSection/Collapsible/index.native.tsx index e8d3dc9439d0..63cb427f845f 100644 --- a/src/components/CollapsibleSection/Collapsible/index.native.tsx +++ b/src/components/CollapsibleSection/Collapsible/index.native.tsx @@ -1,6 +1,6 @@ import React from 'react'; import CollapsibleRN from 'react-native-collapsible'; -import CollapsibleProps from './types'; +import type CollapsibleProps from './types'; function Collapsible({isOpened = false, children}: CollapsibleProps) { return {children}; diff --git a/src/components/CollapsibleSection/Collapsible/index.tsx b/src/components/CollapsibleSection/Collapsible/index.tsx index 2585fd92f42b..5bf31c10ee68 100644 --- a/src/components/CollapsibleSection/Collapsible/index.tsx +++ b/src/components/CollapsibleSection/Collapsible/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {Collapse} from 'react-collapse'; -import CollapsibleProps from './types'; +import type CollapsibleProps from './types'; function Collapsible({isOpened = false, children}: CollapsibleProps) { return {children}; diff --git a/src/components/CollapsibleSection/Collapsible/types.ts b/src/components/CollapsibleSection/Collapsible/types.ts index 8b8e8aba6860..a60b8d79f935 100644 --- a/src/components/CollapsibleSection/Collapsible/types.ts +++ b/src/components/CollapsibleSection/Collapsible/types.ts @@ -1,4 +1,4 @@ -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; type CollapsibleProps = ChildrenProps & { /** Whether the section should start expanded. False by default */ diff --git a/src/components/CollapsibleSection/index.tsx b/src/components/CollapsibleSection/index.tsx index 18b24269b773..393a48e85616 100644 --- a/src/components/CollapsibleSection/index.tsx +++ b/src/components/CollapsibleSection/index.tsx @@ -7,7 +7,7 @@ import Text from '@components/Text'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; import Collapsible from './Collapsible'; type CollapsibleSectionProps = ChildrenProps & { diff --git a/src/components/ComposeProviders.tsx b/src/components/ComposeProviders.tsx index 2c73719358d8..8fc487c78251 100644 --- a/src/components/ComposeProviders.tsx +++ b/src/components/ComposeProviders.tsx @@ -1,5 +1,6 @@ -import React, {ComponentType, ReactNode} from 'react'; -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type {ComponentType, ReactNode} from 'react'; +import React from 'react'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; type ComposeProvidersProps = ChildrenProps & { /** Provider components go here */ diff --git a/src/components/Composer/index.android.tsx b/src/components/Composer/index.android.tsx index 46c2a5f06ded..d60a41e0f263 100644 --- a/src/components/Composer/index.android.tsx +++ b/src/components/Composer/index.android.tsx @@ -1,10 +1,12 @@ -import React, {ForwardedRef, useCallback, useEffect, useMemo, useRef} from 'react'; -import {StyleSheet, TextInput} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import type {TextInput} from 'react-native'; +import {StyleSheet} from 'react-native'; import RNTextInput from '@components/RNTextInput'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ComposerUtils from '@libs/ComposerUtils'; -import {ComposerProps} from './types'; +import type {ComposerProps} from './types'; function Composer( { diff --git a/src/components/Composer/index.ios.tsx b/src/components/Composer/index.ios.tsx index 240dfabded0b..b1357fef9a46 100644 --- a/src/components/Composer/index.ios.tsx +++ b/src/components/Composer/index.ios.tsx @@ -1,10 +1,12 @@ -import React, {ForwardedRef, useCallback, useEffect, useMemo, useRef} from 'react'; -import {StyleSheet, TextInput} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import type {TextInput} from 'react-native'; +import {StyleSheet} from 'react-native'; import RNTextInput from '@components/RNTextInput'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ComposerUtils from '@libs/ComposerUtils'; -import {ComposerProps} from './types'; +import type {ComposerProps} from './types'; function Composer( { diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 4ff5c6dbd75f..19b7bb6bb30a 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -1,9 +1,11 @@ import {useNavigation} from '@react-navigation/native'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; -import React, {BaseSyntheticEvent, ForwardedRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import type {BaseSyntheticEvent, ForwardedRef} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {flushSync} from 'react-dom'; -import {DimensionValue, NativeSyntheticEvent, Text as RNText, StyleSheet, TextInput, TextInputKeyPressEventData, TextInputProps, TextInputSelectionChangeEventData, View} from 'react-native'; -import {AnimatedProps} from 'react-native-reanimated'; +import type {DimensionValue, NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputProps, TextInputSelectionChangeEventData} from 'react-native'; +import {StyleSheet, View} from 'react-native'; +import type {AnimatedProps} from 'react-native-reanimated'; import RNTextInput from '@components/RNTextInput'; import Text from '@components/Text'; import useIsScrollBarVisible from '@hooks/useIsScrollBarVisible'; @@ -17,7 +19,7 @@ import updateIsFullComposerAvailable from '@libs/ComposerUtils/updateIsFullCompo import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import CONST from '@src/CONST'; -import {ComposerProps} from './types'; +import type {ComposerProps} from './types'; /** * Retrieves the characters from the specified cursor position up to the next space or new line. diff --git a/src/components/Composer/types.ts b/src/components/Composer/types.ts index cc0654b68019..bfdcb6715d40 100644 --- a/src/components/Composer/types.ts +++ b/src/components/Composer/types.ts @@ -1,4 +1,4 @@ -import {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, TextInputKeyPressEventData, TextInputSelectionChangeEventData, TextStyle} from 'react-native'; +import type {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, TextInputKeyPressEventData, TextInputSelectionChangeEventData, TextStyle} from 'react-native'; type TextSelection = { start: number; diff --git a/src/components/ConfirmContent.tsx b/src/components/ConfirmContent.tsx index 9e4ffa8720da..94146a2c2957 100644 --- a/src/components/ConfirmContent.tsx +++ b/src/components/ConfirmContent.tsx @@ -1,11 +1,13 @@ -import React, {ReactNode} from 'react'; -import {StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {ReactNode} from 'react'; +import React from 'react'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; -import IconAsset from '@src/types/utils/IconAsset'; +import type IconAsset from '@src/types/utils/IconAsset'; import Button from './Button'; import Header from './Header'; import Icon from './Icon'; diff --git a/src/components/ConfirmationPage.tsx b/src/components/ConfirmationPage.tsx index 21813edd693d..fe4036a4435f 100644 --- a/src/components/ConfirmationPage.tsx +++ b/src/components/ConfirmationPage.tsx @@ -5,7 +5,7 @@ import Button from './Button'; import FixedFooter from './FixedFooter'; import Lottie from './Lottie'; import LottieAnimations from './LottieAnimations'; -import DotLottieAnimation from './LottieAnimations/types'; +import type DotLottieAnimation from './LottieAnimations/types'; import Text from './Text'; type ConfirmationPageProps = { diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index 6f3b42e88fee..3c99a85fd0e7 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -1,5 +1,5 @@ import React, {useCallback} from 'react'; -import {AccessibilityRole, StyleProp, TextStyle} from 'react-native'; +import type {AccessibilityRole, StyleProp, TextStyle} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import Clipboard from '@libs/Clipboard'; import * as Expensicons from './Icon/Expensicons'; diff --git a/src/components/CurrencySymbolButton.js b/src/components/CurrencySymbolButton.tsx similarity index 83% rename from src/components/CurrencySymbolButton.js rename to src/components/CurrencySymbolButton.tsx index d03834fc1fd6..18955bb0b391 100644 --- a/src/components/CurrencySymbolButton.js +++ b/src/components/CurrencySymbolButton.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -7,15 +6,15 @@ import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import Text from './Text'; import Tooltip from './Tooltip'; -const propTypes = { +type CurrencySymbolButtonProps = { /** Currency symbol of selected currency */ - currencySymbol: PropTypes.string.isRequired, + currencySymbol: string; /** Function to call when currency button is pressed */ - onCurrencyButtonPress: PropTypes.func.isRequired, + onCurrencyButtonPress: () => void; }; -function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol}) { +function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol}: CurrencySymbolButtonProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); return ( @@ -31,7 +30,6 @@ function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol}) { ); } -CurrencySymbolButton.propTypes = propTypes; CurrencySymbolButton.displayName = 'CurrencySymbolButton'; export default CurrencySymbolButton; diff --git a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx index 02c308705994..367e54e8be64 100644 --- a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx +++ b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {Circle, Rect} from 'react-native-svg'; -import {ValueOf} from 'type-fest'; +import type {ValueOf} from 'type-fest'; import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; diff --git a/src/components/CurrentWalletBalance.tsx b/src/components/CurrentWalletBalance.tsx index 28a83fb1ae50..8761b50465f3 100644 --- a/src/components/CurrentWalletBalance.tsx +++ b/src/components/CurrentWalletBalance.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import {StyleProp, TextStyle} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {StyleProp, TextStyle} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import UserWallet from '@src/types/onyx/UserWallet'; +import type UserWallet from '@src/types/onyx/UserWallet'; import Text from './Text'; type CurrentWalletBalanceOnyxProps = { diff --git a/src/components/CustomDevMenu/index.native.tsx b/src/components/CustomDevMenu/index.native.tsx index d8a0ea987171..54f1336b4fef 100644 --- a/src/components/CustomDevMenu/index.native.tsx +++ b/src/components/CustomDevMenu/index.native.tsx @@ -1,7 +1,7 @@ import {useEffect} from 'react'; import DevMenu from 'react-native-dev-menu'; import toggleTestToolsModal from '@userActions/TestTool'; -import CustomDevMenuElement from './types'; +import type CustomDevMenuElement from './types'; const CustomDevMenu: CustomDevMenuElement = Object.assign( () => { diff --git a/src/components/CustomDevMenu/index.tsx b/src/components/CustomDevMenu/index.tsx index c8eae861b676..4306d0cae090 100644 --- a/src/components/CustomDevMenu/index.tsx +++ b/src/components/CustomDevMenu/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import CustomDevMenuElement from './types'; +import type CustomDevMenuElement from './types'; const CustomDevMenu: CustomDevMenuElement = Object.assign(() => <>, {displayName: 'CustomDevMenu'}); diff --git a/src/components/CustomDevMenu/types.ts b/src/components/CustomDevMenu/types.ts index bdfc800a17f0..17e2b30ef4f6 100644 --- a/src/components/CustomDevMenu/types.ts +++ b/src/components/CustomDevMenu/types.ts @@ -1,4 +1,4 @@ -import {ReactElement} from 'react'; +import type {ReactElement} from 'react'; type CustomDevMenuElement = { (): ReactElement; diff --git a/src/components/CustomStatusBarAndBackground/index.tsx b/src/components/CustomStatusBarAndBackground/index.tsx index b84f9c6a6630..f66a0204ac5e 100644 --- a/src/components/CustomStatusBarAndBackground/index.tsx +++ b/src/components/CustomStatusBarAndBackground/index.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useContext, useEffect, useRef, useState} from 'react'; +import {interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withDelay, withTiming} from 'react-native-reanimated'; import useTheme from '@hooks/useTheme'; import {navigationRef} from '@libs/Navigation/Navigation'; import StatusBar from '@libs/StatusBar'; @@ -33,7 +34,27 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack }; }, [disableRootStatusBar, isNested]); + const prevStatusBarBackgroundColor = useRef(theme.appBG); + const statusBarBackgroundColor = useRef(theme.appBG); + const statusBarAnimation = useSharedValue(0); + + useAnimatedReaction( + () => statusBarAnimation.value, + (current, previous) => { + // Do not run if either of the animated value is null + // or previous animated value is greater than or equal to the current one + if (previous === null || current === null || current <= previous) { + return; + } + const backgroundColor = interpolateColor(statusBarAnimation.value, [0, 1], [prevStatusBarBackgroundColor.current, statusBarBackgroundColor.current]); + runOnJS(updateStatusBarAppearance)({backgroundColor}); + }, + ); + const listenerCount = useRef(0); + + // Updates the status bar style and background color depending on the current route and theme + // This callback is triggered everytime the route changes or the theme changes const updateStatusBarStyle = useCallback( (listenerId?: number) => { // Check if this function is either called through the current navigation listener or the general useEffect which listens for theme changes. @@ -49,27 +70,40 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack currentRoute = navigationRef.getCurrentRoute(); } - let currentScreenBackgroundColor = theme.appBG; let newStatusBarStyle = theme.statusBarStyle; + let currentScreenBackgroundColor = theme.appBG; if (currentRoute && 'name' in currentRoute && currentRoute.name in theme.PAGE_THEMES) { - const screenTheme = theme.PAGE_THEMES[currentRoute.name]; - currentScreenBackgroundColor = screenTheme.backgroundColor; - newStatusBarStyle = screenTheme.statusBarStyle; + const pageTheme = theme.PAGE_THEMES[currentRoute.name]; + + newStatusBarStyle = pageTheme.statusBarStyle; + + const backgroundColorFromRoute = + currentRoute?.params && 'backgroundColor' in currentRoute.params && typeof currentRoute.params.backgroundColor === 'string' && currentRoute.params.backgroundColor; + + // It's possible for backgroundColorFromRoute to be empty string, so we must use "||" to fallback to backgroundColorFallback. + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + currentScreenBackgroundColor = backgroundColorFromRoute || pageTheme.backgroundColor; + } + + prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current; + statusBarBackgroundColor.current = currentScreenBackgroundColor; + + if (currentScreenBackgroundColor !== theme.appBG || prevStatusBarBackgroundColor.current !== theme.appBG) { + statusBarAnimation.value = 0; + statusBarAnimation.value = withDelay(300, withTiming(1)); } // Don't update the status bar style if it's the same as the current one, to prevent flashing. - if (newStatusBarStyle === statusBarStyle) { - updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor}); - } else { - updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor, statusBarStyle: newStatusBarStyle}); + if (newStatusBarStyle !== statusBarStyle) { + updateStatusBarAppearance({statusBarStyle: newStatusBarStyle}); setStatusBarStyle(newStatusBarStyle); } }, - [statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle], + [statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle], ); // Add navigation state listeners to update the status bar every time the route changes - // We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properyl + // We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properly useEffect(() => { if (isDisabled) { return; @@ -82,15 +116,6 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack return () => navigationRef.removeListener('state', listener); }, [isDisabled, theme.appBG, updateStatusBarStyle]); - // Update the status bar style everytime the theme changes - useEffect(() => { - if (isDisabled) { - return; - } - - updateStatusBarStyle(); - }, [isDisabled, theme, updateStatusBarStyle]); - // Update the global background (on web) everytime the theme changes. // The background of the html element needs to be updated, otherwise you will see a big contrast when resizing the window or when the keyboard is open on iOS web. useEffect(() => { diff --git a/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/index.website.ts b/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/index.website.ts index 481d866dbe4f..f92016048bde 100644 --- a/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/index.website.ts +++ b/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/index.website.ts @@ -1,4 +1,4 @@ -import UpdateGlobalBackgroundColor from './types'; +import type UpdateGlobalBackgroundColor from './types'; const updateGlobalBackgroundColor: UpdateGlobalBackgroundColor = (theme) => { const htmlElement = document.getElementsByTagName('html')[0]; diff --git a/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/types.ts b/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/types.ts index 83bd36a9428a..078703e3846d 100644 --- a/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/types.ts +++ b/src/components/CustomStatusBarAndBackground/updateGlobalBackgroundColor/types.ts @@ -1,4 +1,4 @@ -import {ThemeColors} from '@styles/theme/types'; +import type {ThemeColors} from '@styles/theme/types'; type UpdateGlobalBackgroundColor = (theme: ThemeColors) => void; diff --git a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.android.ts b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.android.ts index b7651d4549de..c25f45bfb050 100644 --- a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.android.ts +++ b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.android.ts @@ -1,5 +1,5 @@ import StatusBar from '@libs/StatusBar'; -import UpdateStatusBarAppearanceProps from './types'; +import type UpdateStatusBarAppearanceProps from './types'; // eslint-disable-next-line @typescript-eslint/naming-convention export default function updateStatusBarAppearance({statusBarStyle}: UpdateStatusBarAppearanceProps) { diff --git a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ios.ts b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ios.ts index 61fcb056bba5..e887b5f0a98b 100644 --- a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ios.ts +++ b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ios.ts @@ -1,5 +1,5 @@ import StatusBar from '@libs/StatusBar'; -import UpdateStatusBarAppearanceProps from './types'; +import type UpdateStatusBarAppearanceProps from './types'; // eslint-disable-next-line @typescript-eslint/naming-convention export default function updateStatusBarAppearance({statusBarStyle}: UpdateStatusBarAppearanceProps) { diff --git a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ts b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ts index 574efd90f0b5..a11b3619f8d9 100644 --- a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ts +++ b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/index.ts @@ -1,5 +1,5 @@ import StatusBar from '@libs/StatusBar'; -import UpdateStatusBarAppearanceProps from './types'; +import type UpdateStatusBarAppearanceProps from './types'; export default function updateStatusBarAppearance({backgroundColor, statusBarStyle}: UpdateStatusBarAppearanceProps) { if (backgroundColor) { diff --git a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/types.ts b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/types.ts index 823f0059eccf..775082187395 100644 --- a/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/types.ts +++ b/src/components/CustomStatusBarAndBackground/updateStatusBarAppearance/types.ts @@ -1,4 +1,4 @@ -import {StatusBarStyle} from '@styles/index'; +import type {StatusBarStyle} from '@styles/index'; type UpdateStatusBarAppearanceProps = { backgroundColor?: string; diff --git a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx index 0e8996bf5022..27d8027bbcff 100644 --- a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx +++ b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -12,7 +13,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import * as OnyxTypes from '@src/types/onyx'; +import type * as OnyxTypes from '@src/types/onyx'; type DeeplinkRedirectLoadingIndicatorOnyxProps = { /** Current user session */ diff --git a/src/components/DeeplinkWrapper/index.tsx b/src/components/DeeplinkWrapper/index.tsx index 4b0382bd6b14..076e6b91460d 100644 --- a/src/components/DeeplinkWrapper/index.tsx +++ b/src/components/DeeplinkWrapper/index.tsx @@ -1,4 +1,4 @@ -import DeeplinkWrapperProps from './types'; +import type DeeplinkWrapperProps from './types'; function DeeplinkWrapper({children}: DeeplinkWrapperProps) { return children; diff --git a/src/components/DeeplinkWrapper/index.website.tsx b/src/components/DeeplinkWrapper/index.website.tsx index 2cae91e2f2a0..1d509666ec98 100644 --- a/src/components/DeeplinkWrapper/index.website.tsx +++ b/src/components/DeeplinkWrapper/index.website.tsx @@ -8,7 +8,7 @@ import * as App from '@userActions/App'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -import DeeplinkWrapperProps from './types'; +import type DeeplinkWrapperProps from './types'; function isMacOSWeb(): boolean { return !Browser.isMobile() && typeof navigator === 'object' && typeof navigator.userAgent === 'string' && /Mac/i.test(navigator.userAgent) && !/Electron/i.test(navigator.userAgent); diff --git a/src/components/DeeplinkWrapper/types.ts b/src/components/DeeplinkWrapper/types.ts index dfd56b62573d..db61e5b01c24 100644 --- a/src/components/DeeplinkWrapper/types.ts +++ b/src/components/DeeplinkWrapper/types.ts @@ -1,4 +1,4 @@ -import ChildrenProps from '@src/types/utils/ChildrenProps'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; type DeeplinkWrapperProps = ChildrenProps & { /** User authentication status */ diff --git a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx index 440457d22965..9b3eaeb4e447 100644 --- a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx +++ b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx @@ -1,15 +1,16 @@ -import React, {RefObject, useCallback} from 'react'; -import {Text as RNText, StyleProp, TextStyle} from 'react-native'; +import type {RefObject} from 'react'; +import React, {useCallback} from 'react'; +import type {Text as RNText, StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; import UserDetailsTooltip from '@components/UserDetailsTooltip'; import useThemeStyles from '@hooks/useThemeStyles'; -import {AvatarSource} from '@libs/UserUtils'; +import type {AvatarSource} from '@libs/UserUtils'; type DisplayNamesTooltipItemProps = { index?: number; /** The function to get a distance to shift the tooltip horizontally */ - getTooltipShiftX?: (index: number) => number | undefined; + getTooltipShiftX?: (index: number) => number; /** The Account ID for the tooltip */ accountID?: number; @@ -32,7 +33,7 @@ type DisplayNamesTooltipItemProps = { function DisplayNamesTooltipItem({ index = 0, - getTooltipShiftX = () => undefined, + getTooltipShiftX = () => 0, accountID = 0, avatar = '', login = '', diff --git a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx index 43061ada9a94..f22b1f0c2209 100644 --- a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx @@ -1,10 +1,11 @@ import React, {Fragment, useCallback, useRef} from 'react'; -import {Text as RNText, View} from 'react-native'; +import type {Text as RNText} from 'react-native'; +import {View} from 'react-native'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; import useThemeStyles from '@hooks/useThemeStyles'; import DisplayNamesTooltipItem from './DisplayNamesTooltipItem'; -import DisplayNamesProps from './types'; +import type DisplayNamesProps from './types'; type HTMLElementWithText = HTMLElement & RNText; @@ -23,13 +24,13 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit * 2. Now we get the tooltip original position. * 3. If inline node's right edge is overflowing the container's right edge, we set the tooltip to the center * of the distance between the left edge of the inline node and right edge of the container. - * @param {Number} index Used to get the Ref to the node at the current index - * @returns {Number} Distance to shift the tooltip horizontally + * @param index Used to get the Ref to the node at the current index + * @returns Distance to shift the tooltip horizontally */ const getTooltipShiftX = useCallback((index: number) => { // Only shift the tooltip in case the containerLayout or Refs to the text node are available if (!containerRef.current || !childRefs.current[index]) { - return; + return 0; } const {width: containerWidth, left: containerLeft} = containerRef.current.getBoundingClientRect(); diff --git a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx index 761b0b66ee2c..177bdb6a9fc4 100644 --- a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {StyleProp, TextStyle} from 'react-native'; +import type {StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/DisplayNames/index.native.tsx b/src/components/DisplayNames/index.native.tsx index 8f1fef37a6ba..b3eceb794bcb 100644 --- a/src/components/DisplayNames/index.native.tsx +++ b/src/components/DisplayNames/index.native.tsx @@ -1,7 +1,7 @@ import React from 'react'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; -import DisplayNamesProps from './types'; +import type DisplayNamesProps from './types'; // As we don't have to show tooltips of the Native platform so we simply render the full display names list. function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1}: DisplayNamesProps) { diff --git a/src/components/DisplayNames/index.tsx b/src/components/DisplayNames/index.tsx index 7ff1081937d5..155193368cc5 100644 --- a/src/components/DisplayNames/index.tsx +++ b/src/components/DisplayNames/index.tsx @@ -2,7 +2,7 @@ import React from 'react'; import useLocalize from '@hooks/useLocalize'; import DisplayNamesWithoutTooltip from './DisplayNamesWithoutTooltip'; import DisplayNamesWithToolTip from './DisplayNamesWithTooltip'; -import DisplayNamesProps from './types'; +import type DisplayNamesProps from './types'; function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldUseFullTitle, displayNamesWithTooltips}: DisplayNamesProps) { const {translate} = useLocalize(); diff --git a/src/components/DisplayNames/types.ts b/src/components/DisplayNames/types.ts index 5137d6f54108..b0959d43aa96 100644 --- a/src/components/DisplayNames/types.ts +++ b/src/components/DisplayNames/types.ts @@ -1,4 +1,4 @@ -import {StyleProp, TextStyle} from 'react-native'; +import type {StyleProp, TextStyle} from 'react-native'; import type {AvatarSource} from '@libs/UserUtils'; type DisplayNameWithTooltip = { diff --git a/src/components/DistanceMapView/distanceMapViewPropTypes.js b/src/components/DistanceMapView/distanceMapViewPropTypes.js deleted file mode 100644 index f7a3bab1879e..000000000000 --- a/src/components/DistanceMapView/distanceMapViewPropTypes.js +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import sourcePropTypes from '@components/Image/sourcePropTypes'; - -const propTypes = { - // Public access token to be used to fetch map data from Mapbox. - accessToken: PropTypes.string.isRequired, - - // Style applied to MapView component. Note some of the View Style props are not available on ViewMap - style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), - - // Link to the style JSON document. - styleURL: PropTypes.string, - - // Whether map can tilt in the vertical direction. - pitchEnabled: PropTypes.bool, - - // Padding to apply when the map is adjusted to fit waypoints and directions - mapPadding: PropTypes.number, - - // Initial coordinate and zoom level - initialState: PropTypes.shape({ - location: PropTypes.arrayOf(PropTypes.number).isRequired, - zoom: PropTypes.number.isRequired, - }), - - // Locations on which to put markers - waypoints: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - coordinate: PropTypes.arrayOf(PropTypes.number), - markerComponent: sourcePropTypes, - }), - ), - - // List of coordinates which together forms a direction. - directionCoordinates: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)), - - // Callback to call when the map is idle / ready - onMapReady: PropTypes.func, - - // Optional additional styles to be applied to the overlay - overlayStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), -}; - -const defaultProps = { - styleURL: undefined, - pitchEnabled: false, - mapPadding: 0, - initialState: undefined, - waypoints: undefined, - directionCoordinates: undefined, - onMapReady: () => {}, - overlayStyle: undefined, -}; - -export {propTypes, defaultProps}; diff --git a/src/components/DistanceMapView/index.android.js b/src/components/DistanceMapView/index.android.tsx similarity index 73% rename from src/components/DistanceMapView/index.android.js rename to src/components/DistanceMapView/index.android.tsx index fa40bd50673e..168a480c6100 100644 --- a/src/components/DistanceMapView/index.android.js +++ b/src/components/DistanceMapView/index.android.tsx @@ -1,18 +1,15 @@ import React, {useState} from 'react'; import {View} from 'react-native'; -import _ from 'underscore'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Expensicons from '@components/Icon/Expensicons'; import MapView from '@components/MapView'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as distanceMapViewPropTypes from './distanceMapViewPropTypes'; +import type DistanceMapViewProps from './types'; -function DistanceMapView(props) { +function DistanceMapView({overlayStyle, ...rest}: DistanceMapViewProps) { const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); const [isMapReady, setIsMapReady] = useState(false); const {isOffline} = useNetwork(); const {translate} = useLocalize(); @@ -21,7 +18,7 @@ function DistanceMapView(props) { <> { if (isMapReady) { return; @@ -30,7 +27,7 @@ function DistanceMapView(props) { }} /> {!isMapReady && ( - + ; -} - -DistanceMapView.propTypes = distanceMapViewPropTypes.propTypes; -DistanceMapView.defaultProps = distanceMapViewPropTypes.defaultProps; -DistanceMapView.displayName = 'DistanceMapView'; - -export default DistanceMapView; diff --git a/src/components/DistanceMapView/index.tsx b/src/components/DistanceMapView/index.tsx new file mode 100644 index 000000000000..3f1b3b8439ed --- /dev/null +++ b/src/components/DistanceMapView/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import MapView from '@components/MapView'; +import type DistanceMapViewProps from './types'; + +function DistanceMapView({overlayStyle, ...rest}: DistanceMapViewProps) { + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +} + +DistanceMapView.displayName = 'DistanceMapView'; + +export default DistanceMapView; diff --git a/src/components/DistanceMapView/types.ts b/src/components/DistanceMapView/types.ts new file mode 100644 index 000000000000..18213235445f --- /dev/null +++ b/src/components/DistanceMapView/types.ts @@ -0,0 +1,8 @@ +import type {StyleProp, ViewStyle} from 'react-native'; +import type {MapViewProps} from '@components/MapView/MapViewTypes'; + +type DistanceMapViewProps = MapViewProps & { + overlayStyle?: StyleProp; +}; + +export default DistanceMapViewProps; diff --git a/src/components/DotIndicatorMessage.tsx b/src/components/DotIndicatorMessage.tsx index 65afe8c7e4eb..d18704fdfb05 100644 --- a/src/components/DotIndicatorMessage.tsx +++ b/src/components/DotIndicatorMessage.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/no-array-index-key */ import React from 'react'; -import {StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -84,9 +85,9 @@ function DotIndicatorMessage({messages = {}, style, type, textStyles}: DotIndica key={i} style={styles.offlineFeedback.text} > - {Localize.translateLocal('iou.error.receiptFailureMessage')} - {Localize.translateLocal('iou.error.saveFileMessage')} - {Localize.translateLocal('iou.error.loseFileMessage')} + {Localize.translateLocal('iou.error.receiptFailureMessage')} + {Localize.translateLocal('iou.error.saveFileMessage')} + {Localize.translateLocal('iou.error.loseFileMessage')} ) : ( diff --git a/src/components/DragAndDrop/Consumer/types.ts b/src/components/DragAndDrop/Consumer/types.ts index 1f85f32a0153..03bdee3f23d8 100644 --- a/src/components/DragAndDrop/Consumer/types.ts +++ b/src/components/DragAndDrop/Consumer/types.ts @@ -1,4 +1,4 @@ -import {ReactNode} from 'react'; +import type {ReactNode} from 'react'; type DragAndDropConsumerProps = { /** Children to render inside this component. */ diff --git a/src/components/DragAndDrop/NoDropZone/types.ts b/src/components/DragAndDrop/NoDropZone/types.ts index 09715ecd942f..0735f4936ada 100644 --- a/src/components/DragAndDrop/NoDropZone/types.ts +++ b/src/components/DragAndDrop/NoDropZone/types.ts @@ -1,4 +1,4 @@ -import {ReactNode} from 'react'; +import type {ReactNode} from 'react'; type NoDropZoneProps = { /** Content */ diff --git a/src/components/DragAndDrop/Provider/types.ts b/src/components/DragAndDrop/Provider/types.ts index eae83d10682a..b4394056cac5 100644 --- a/src/components/DragAndDrop/Provider/types.ts +++ b/src/components/DragAndDrop/Provider/types.ts @@ -1,4 +1,4 @@ -import {ReactNode} from 'react'; +import type {ReactNode} from 'react'; type DragAndDropProviderProps = { /** Children to render inside this component. */ diff --git a/src/components/DraggableList/index.native.tsx b/src/components/DraggableList/index.native.tsx index f532b21720da..7cf33112bece 100644 --- a/src/components/DraggableList/index.native.tsx +++ b/src/components/DraggableList/index.native.tsx @@ -1,6 +1,6 @@ import React from 'react'; import DraggableFlatList from 'react-native-draggable-flatlist'; -import {FlatList} from 'react-native-gesture-handler'; +import type {FlatList} from 'react-native-gesture-handler'; import useThemeStyles from '@hooks/useThemeStyles'; import type {DraggableListProps} from './types'; diff --git a/src/components/DraggableList/index.tsx b/src/components/DraggableList/index.tsx index b92691075424..dc78a3ce6222 100644 --- a/src/components/DraggableList/index.tsx +++ b/src/components/DraggableList/index.tsx @@ -1,5 +1,6 @@ import React, {useCallback} from 'react'; -import {DragDropContext, Draggable, Droppable, type OnDragEndResponder} from 'react-beautiful-dnd'; +import {DragDropContext, Draggable, Droppable} from 'react-beautiful-dnd'; +import type {OnDragEndResponder} from 'react-beautiful-dnd'; import {ScrollView} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import type {DraggableListProps} from './types'; diff --git a/src/components/EmojiSuggestions.tsx b/src/components/EmojiSuggestions.tsx index 2fcf8e827b4e..5904b1521f98 100644 --- a/src/components/EmojiSuggestions.tsx +++ b/src/components/EmojiSuggestions.tsx @@ -1,4 +1,5 @@ -import React, {ReactElement, useCallback} from 'react'; +import type {ReactElement} from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/ErrorBoundary/BaseErrorBoundary.tsx b/src/components/ErrorBoundary/BaseErrorBoundary.tsx index 2a6524d5a993..6a0f1a0ae55e 100644 --- a/src/components/ErrorBoundary/BaseErrorBoundary.tsx +++ b/src/components/ErrorBoundary/BaseErrorBoundary.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {ErrorBoundary} from 'react-error-boundary'; import BootSplash from '@libs/BootSplash'; import GenericErrorPage from '@pages/ErrorPage/GenericErrorPage'; -import {BaseErrorBoundaryProps, LogError} from './types'; +import type {BaseErrorBoundaryProps, LogError} from './types'; /** * This component captures an error in the child component tree and logs it to the server diff --git a/src/components/ErrorBoundary/index.native.tsx b/src/components/ErrorBoundary/index.native.tsx index b8e56ee528c2..5e0c9ca9af38 100644 --- a/src/components/ErrorBoundary/index.native.tsx +++ b/src/components/ErrorBoundary/index.native.tsx @@ -2,7 +2,7 @@ import crashlytics from '@react-native-firebase/crashlytics'; import React from 'react'; import Log from '@libs/Log'; import BaseErrorBoundary from './BaseErrorBoundary'; -import {BaseErrorBoundaryProps, LogError} from './types'; +import type {BaseErrorBoundaryProps, LogError} from './types'; const logError: LogError = (errorMessage, error, errorInfo) => { // Log the error to the server diff --git a/src/components/ErrorBoundary/index.tsx b/src/components/ErrorBoundary/index.tsx index fce70674dd97..890cf5f4e587 100644 --- a/src/components/ErrorBoundary/index.tsx +++ b/src/components/ErrorBoundary/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import Log from '@libs//Log'; import BaseErrorBoundary from './BaseErrorBoundary'; -import {BaseErrorBoundaryProps, LogError} from './types'; +import type {BaseErrorBoundaryProps, LogError} from './types'; const logError: LogError = (errorMessage, error, errorInfo) => { // Log the error to the server diff --git a/src/components/ExpensifyWordmark.tsx b/src/components/ExpensifyWordmark.tsx index 798907c7eeb6..0e8f78686b07 100644 --- a/src/components/ExpensifyWordmark.tsx +++ b/src/components/ExpensifyWordmark.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import AdHocLogo from '@assets/images/expensify-logo--adhoc.svg'; import DevLogo from '@assets/images/expensify-logo--dev.svg'; import StagingLogo from '@assets/images/expensify-logo--staging.svg'; diff --git a/src/components/FixedFooter.tsx b/src/components/FixedFooter.tsx index 7fd6811c1df6..35fa4d02f5e0 100644 --- a/src/components/FixedFooter.tsx +++ b/src/components/FixedFooter.tsx @@ -1,5 +1,7 @@ -import React, {ReactNode} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {ReactNode} from 'react'; +import React from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; type FixedFooterProps = { diff --git a/src/components/FlatList/index.android.tsx b/src/components/FlatList/index.android.tsx index 84345f6e0ed4..863930203863 100644 --- a/src/components/FlatList/index.android.tsx +++ b/src/components/FlatList/index.android.tsx @@ -1,6 +1,8 @@ import {useFocusEffect} from '@react-navigation/native'; -import React, {ForwardedRef, forwardRef, useCallback, useContext} from 'react'; -import {FlatList, FlatListProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useCallback, useContext} from 'react'; +import type {FlatListProps} from 'react-native'; +import {FlatList} from 'react-native'; import {ActionListContext} from '@pages/home/ReportScreenContext'; // FlatList wrapped with the freeze component will lose its scroll state when frozen (only for Android). diff --git a/src/components/FormAlertWithSubmitButton.tsx b/src/components/FormAlertWithSubmitButton.tsx index d8e30b27371d..512d2063dc0f 100644 --- a/src/components/FormAlertWithSubmitButton.tsx +++ b/src/components/FormAlertWithSubmitButton.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import Button from './Button'; import FormAlertWrapper from './FormAlertWrapper'; diff --git a/src/components/FormAlertWrapper.tsx b/src/components/FormAlertWrapper.tsx index a144bf069502..65fa2311620d 100644 --- a/src/components/FormAlertWrapper.tsx +++ b/src/components/FormAlertWrapper.tsx @@ -1,8 +1,10 @@ -import React, {ReactNode} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {ReactNode} from 'react'; +import React from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import Network from '@src/types/onyx/Network'; +import type Network from '@src/types/onyx/Network'; import FormHelpMessage from './FormHelpMessage'; import {withNetwork} from './OnyxProvider'; import RenderHTML from './RenderHTML'; diff --git a/src/components/FormElement.tsx b/src/components/FormElement.tsx index c61a09b9d1ec..da98d4dc565a 100644 --- a/src/components/FormElement.tsx +++ b/src/components/FormElement.tsx @@ -1,5 +1,7 @@ -import React, {ForwardedRef, forwardRef} from 'react'; -import {View, ViewProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; +import type {ViewProps} from 'react-native'; +import {View} from 'react-native'; import * as ComponentUtils from '@libs/ComponentUtils'; function FormElement(props: ViewProps, ref: ForwardedRef) { diff --git a/src/components/FormHelpMessage.tsx b/src/components/FormHelpMessage.tsx index 43709b51db44..4f1d784788bf 100644 --- a/src/components/FormHelpMessage.tsx +++ b/src/components/FormHelpMessage.tsx @@ -1,6 +1,7 @@ import isEmpty from 'lodash/isEmpty'; import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Localize from '@libs/Localize'; diff --git a/src/components/FormScrollView.tsx b/src/components/FormScrollView.tsx index 4646a534e750..ade167e9e628 100644 --- a/src/components/FormScrollView.tsx +++ b/src/components/FormScrollView.tsx @@ -1,5 +1,7 @@ -import React, {ForwardedRef} from 'react'; -import {ScrollView, ScrollViewProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React from 'react'; +import type {ScrollViewProps} from 'react-native'; +import {ScrollView} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; type FormScrollViewProps = ScrollViewProps & { diff --git a/src/components/FormSubmit/index.native.tsx b/src/components/FormSubmit/index.native.tsx index 22bf5353949d..5eae7b51d988 100644 --- a/src/components/FormSubmit/index.native.tsx +++ b/src/components/FormSubmit/index.native.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import {FormSubmitProps, FormSubmitRef} from './types'; +import type {FormSubmitProps, FormSubmitRef} from './types'; function FormSubmit({style, children}: FormSubmitProps, ref: FormSubmitRef) { return ( diff --git a/src/components/FormSubmit/index.tsx b/src/components/FormSubmit/index.tsx index ef3f3c39bbaa..2ccd006bf322 100644 --- a/src/components/FormSubmit/index.tsx +++ b/src/components/FormSubmit/index.tsx @@ -1,9 +1,10 @@ -import React, {KeyboardEvent, useEffect} from 'react'; +import type {KeyboardEvent} from 'react'; +import React, {useEffect} from 'react'; import {View} from 'react-native'; import * as ComponentUtils from '@libs/ComponentUtils'; import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition'; import CONST from '@src/CONST'; -import {FormSubmitProps, FormSubmitRef} from './types'; +import type {FormSubmitProps, FormSubmitRef} from './types'; function FormSubmit({children, onSubmit, style}: FormSubmitProps, ref: FormSubmitRef) { /** diff --git a/src/components/FormSubmit/types.ts b/src/components/FormSubmit/types.ts index 20910647ecb8..722a3fbf746e 100644 --- a/src/components/FormSubmit/types.ts +++ b/src/components/FormSubmit/types.ts @@ -1,5 +1,6 @@ -import React, {ForwardedRef} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {ForwardedRef} from 'react'; +import type React from 'react'; +import type {StyleProp, View, ViewStyle} from 'react-native'; type FormSubmitProps = { children: React.ReactNode; diff --git a/src/components/FullscreenLoadingIndicator.tsx b/src/components/FullscreenLoadingIndicator.tsx index 2b5f7b3ada72..bd3082db5fa4 100644 --- a/src/components/FullscreenLoadingIndicator.tsx +++ b/src/components/FullscreenLoadingIndicator.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ActivityIndicator, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {ActivityIndicator, StyleSheet, View} from 'react-native'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.js similarity index 76% rename from src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js rename to src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.js index 07954cc97a00..27eff02d63ea 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.js @@ -1,14 +1,14 @@ import PropTypes from 'prop-types'; -import React, {forwardRef} from 'react'; -import {ScrollView, View} from 'react-native'; +import React from 'react'; +import {View} from 'react-native'; import _ from 'underscore'; -import htmlRendererPropTypes from '@components/HTMLEngineProvider/HTMLRenderers/htmlRendererPropTypes'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import {ShowContextMenuContext, showContextMenuForReport} from '@components/ShowContextMenuContext'; import withLocalize from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; +import htmlRendererPropTypes from './htmlRendererPropTypes'; const propTypes = { /** Press in handler for the code block */ @@ -31,20 +31,14 @@ const defaultProps = { onPressOut: undefined, }; -const BasePreRenderer = forwardRef((props, ref) => { +function PreRenderer(props) { const styles = useThemeStyles(); const TDefaultRenderer = props.TDefaultRenderer; const defaultRendererProps = _.omit(props, ['TDefaultRenderer', 'onPressIn', 'onPressOut', 'onLongPress']); const isLast = props.renderIndex === props.renderLength - 1; return ( - + {({anchor, report, action, checkIfContextMenuActive}) => ( { )} - + ); -}); +} -BasePreRenderer.displayName = 'BasePreRenderer'; -BasePreRenderer.propTypes = propTypes; -BasePreRenderer.defaultProps = defaultProps; +PreRenderer.displayName = 'PreRenderer'; +PreRenderer.propTypes = propTypes; +PreRenderer.defaultProps = defaultProps; -export default withLocalize(BasePreRenderer); +export default withLocalize(PreRenderer); diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js deleted file mode 100644 index 3beb52e6ee81..000000000000 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js +++ /dev/null @@ -1,68 +0,0 @@ -import React, {useCallback, useEffect, useRef} from 'react'; -import _ from 'underscore'; -import htmlRendererPropTypes from '@components/HTMLEngineProvider/HTMLRenderers/htmlRendererPropTypes'; -import ControlSelection from '@libs/ControlSelection'; -import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import BasePreRenderer from './BasePreRenderer'; - -const supportsPassive = DeviceCapabilities.hasPassiveEventListenerSupport(); - -const isScrollingVertically = (event) => - // Mark as vertical scrolling only when absolute value of deltaY is more than the double of absolute - // value of deltaX, so user can use trackpad scroll on the code block horizontally at a wide angle. - Math.abs(event.deltaY) > Math.abs(event.deltaX) * 2; - -const debouncedIsScrollingVertically = _.debounce(isScrollingVertically, 100, true); - -function PreRenderer(props) { - const scrollViewRef = useRef(); - - /** - * Checks if user is scrolling vertically based on deltaX and deltaY. We debounce this - * method in order to make sure it's called only for the first event. - * @param {WheelEvent} event Wheel event - * @returns {Boolean} true if user is scrolling vertically - */ - - /** - * Manually scrolls the code block if code block horizontal scrollable, then prevents the event from being passed up to the parent. - * @param {Object} event native event - */ - const scrollNode = useCallback((event) => { - const node = scrollViewRef.current.getScrollableNode(); - const horizontalOverflow = node.scrollWidth > node.offsetWidth; - if (event.currentTarget === node && horizontalOverflow && !debouncedIsScrollingVertically(event)) { - node.scrollLeft += event.deltaX; - } - }, []); - - useEffect(() => { - const eventListenerRefValue = scrollViewRef.current; - if (!eventListenerRefValue) { - return; - } - eventListenerRefValue.getScrollableNode().addEventListener('wheel', scrollNode, supportsPassive ? {passive: true} : false); - - return () => { - if (!eventListenerRefValue.getScrollableNode()) { - return; - } - eventListenerRefValue.getScrollableNode().removeEventListener('wheel', scrollNode); - }; - }, [scrollNode]); - - return ( - DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} - onPressOut={ControlSelection.unblock} - /> - ); -} - -PreRenderer.propTypes = htmlRendererPropTypes; -PreRenderer.displayName = 'PreRenderer'; - -export default PreRenderer; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.native.js b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.native.js deleted file mode 100644 index b84dd43dd82f..000000000000 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.native.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import htmlRendererPropTypes from '@components/HTMLEngineProvider/HTMLRenderers/htmlRendererPropTypes'; -import withLocalize from '@components/withLocalize'; -import BasePreRenderer from './BasePreRenderer'; - -function PreRenderer(props) { - // eslint-disable-next-line react/jsx-props-no-spreading - return ; -} - -PreRenderer.propTypes = htmlRendererPropTypes; -PreRenderer.displayName = 'PreRenderer'; - -export default withLocalize(PreRenderer); diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 4eac2c7a6994..25532107016f 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,5 +1,7 @@ -import React, {ReactNode} from 'react'; -import {StyleProp, TextStyle, View} from 'react-native'; +import type {ReactNode} from 'react'; +import React from 'react'; +import type {StyleProp, TextStyle} from 'react-native'; +import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import EnvironmentBadge from './EnvironmentBadge'; import Text from './Text'; diff --git a/src/components/HeaderGap/types.ts b/src/components/HeaderGap/types.ts index 55a202c2e48c..1333ceac6198 100644 --- a/src/components/HeaderGap/types.ts +++ b/src/components/HeaderGap/types.ts @@ -1,5 +1,5 @@ -import {ReactNode} from 'react'; -import {StyleProp, ViewStyle} from 'react-native'; +import type {ReactNode} from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; type HeaderGapProps = { styles?: StyleProp; diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index 9ec8bca55a95..209803f2a5d1 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -19,7 +19,7 @@ import getButtonState from '@libs/getButtonState'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -import HeaderWithBackButtonProps from './types'; +import type HeaderWithBackButtonProps from './types'; function HeaderWithBackButton({ iconFill, diff --git a/src/components/HeaderWithBackButton/types.ts b/src/components/HeaderWithBackButton/types.ts index 939b2530fa3d..9ffb0b5ef2f3 100644 --- a/src/components/HeaderWithBackButton/types.ts +++ b/src/components/HeaderWithBackButton/types.ts @@ -1,5 +1,5 @@ -import {ReactNode} from 'react'; -import {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {ReactNode} from 'react'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {Action} from '@hooks/useSingleExecution'; import type {StepCounterParams} from '@src/languages/types'; import type {AnchorPosition} from '@src/styles'; @@ -18,7 +18,7 @@ type ThreeDotsMenuItems = { onSelected: () => void; }; -type HeaderWithBackButtonProps = ChildrenProps & { +type HeaderWithBackButtonProps = Partial & { /** Title of the Header */ title?: string; diff --git a/src/components/Hoverable/index.native.tsx b/src/components/Hoverable/index.native.tsx index b3d49db9d96e..47268e0f440a 100644 --- a/src/components/Hoverable/index.native.tsx +++ b/src/components/Hoverable/index.native.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import HoverableProps from './types'; +import type HoverableProps from './types'; /** * On mobile, there is no concept of hovering, so we return a plain wrapper around the component's children, diff --git a/src/components/Hoverable/index.tsx b/src/components/Hoverable/index.tsx index 9c641cfc19be..c82ba659593a 100644 --- a/src/components/Hoverable/index.tsx +++ b/src/components/Hoverable/index.tsx @@ -1,8 +1,9 @@ -import React, {ForwardedRef, forwardRef, MutableRefObject, ReactElement, RefAttributes, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; +import type {ForwardedRef, MutableRefObject, ReactElement, RefAttributes} from 'react'; +import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import {DeviceEventEmitter} from 'react-native'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import CONST from '@src/CONST'; -import HoverableProps from './types'; +import type HoverableProps from './types'; /** * Maps the children of a Hoverable component to @@ -145,7 +146,7 @@ function Hoverable( // Expose inner ref to parent through outerRef. This enable us to use ref both in parent and child. useImperativeHandle(outerRef, () => ref.current, []); - const child = useMemo(() => React.Children.only(mapChildren(children, isHovered)), [children, isHovered]); + const child = useMemo(() => React.Children.only(mapChildren(children as ReactElement, isHovered)), [children, isHovered]); const enableHoveredOnMouseEnter = useCallback( (event: MouseEvent) => { diff --git a/src/components/Hoverable/types.ts b/src/components/Hoverable/types.ts index 430b865f50c5..921772743ab4 100644 --- a/src/components/Hoverable/types.ts +++ b/src/components/Hoverable/types.ts @@ -1,8 +1,8 @@ -import {ReactElement} from 'react'; +import type {ReactNode} from 'react'; type HoverableProps = { /** Children to wrap with Hoverable. */ - children: ((isHovered: boolean) => ReactElement) | ReactElement; + children: ((isHovered: boolean) => ReactNode) | ReactNode; /** Whether to disable the hover action */ disabled?: boolean; diff --git a/src/components/IFrame.tsx b/src/components/IFrame.tsx index 7520ad869507..ab27597aeebd 100644 --- a/src/components/IFrame.tsx +++ b/src/components/IFrame.tsx @@ -1,7 +1,8 @@ import React, {useEffect, useState} from 'react'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import {Session} from '@src/types/onyx'; +import type {Session} from '@src/types/onyx'; type OldDotIFrameOnyxProps = { session: OnyxEntry; diff --git a/src/components/Icon/BankIcons/index.native.ts b/src/components/Icon/BankIcons/index.native.ts index 2011b71588af..61721512ec04 100644 --- a/src/components/Icon/BankIcons/index.native.ts +++ b/src/components/Icon/BankIcons/index.native.ts @@ -1,9 +1,10 @@ import GenericBank from '@assets/images/bankicons/generic-bank-account.svg'; import GenericBankCard from '@assets/images/cardicons/generic-bank-card.svg'; -import {BankIconParams, getBankIconAsset, getBankNameKey} from '@components/Icon/BankIconsUtils'; +import type {BankIconParams} from '@components/Icon/BankIconsUtils'; +import {getBankIconAsset, getBankNameKey} from '@components/Icon/BankIconsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; -import {BankIcon} from '@src/types/onyx/Bank'; +import type {BankIcon} from '@src/types/onyx/Bank'; /** * Returns Bank Icon Object that matches to existing bank icons or default icons diff --git a/src/components/Icon/BankIcons/index.ts b/src/components/Icon/BankIcons/index.ts index 0e0935b103e4..378a7107aa03 100644 --- a/src/components/Icon/BankIcons/index.ts +++ b/src/components/Icon/BankIcons/index.ts @@ -1,10 +1,11 @@ import GenericBank from '@assets/images/bankicons/generic-bank-account.svg'; import GenericBankCard from '@assets/images/cardicons/generic-bank-card.svg'; -import {BankIconParams, getBankIconAsset, getBankNameKey} from '@components/Icon/BankIconsUtils'; +import type {BankIconParams} from '@components/Icon/BankIconsUtils'; +import {getBankIconAsset, getBankNameKey} from '@components/Icon/BankIconsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; -import {BankIcon} from '@src/types/onyx/Bank'; -import IconAsset from '@src/types/utils/IconAsset'; +import type {BankIcon} from '@src/types/onyx/Bank'; +import type IconAsset from '@src/types/utils/IconAsset'; /** * It's a wrapper type for a bank icon asset. Bank icons are imported using require(), on the web platform after importing in this way it's necessary to use the property "default" diff --git a/src/components/Icon/BankIconsUtils.ts b/src/components/Icon/BankIconsUtils.ts index cc877ef9ef6f..c91ec030c9ba 100644 --- a/src/components/Icon/BankIconsUtils.ts +++ b/src/components/Icon/BankIconsUtils.ts @@ -1,7 +1,7 @@ -import {type ThemeStyles} from '@styles/index'; +import type {ThemeStyles} from '@styles/index'; import CONST from '@src/CONST'; -import {BankName, BankNameKey} from '@src/types/onyx/Bank'; -import IconAsset from '@src/types/utils/IconAsset'; +import type {BankName, BankNameKey} from '@src/types/onyx/Bank'; +import type IconAsset from '@src/types/utils/IconAsset'; type BankIconParams = { styles: ThemeStyles; diff --git a/src/components/Icon/IconWrapperStyles/index.ios.ts b/src/components/Icon/IconWrapperStyles/index.ios.ts index 9507502d9d26..b039cff95f58 100644 --- a/src/components/Icon/IconWrapperStyles/index.ios.ts +++ b/src/components/Icon/IconWrapperStyles/index.ios.ts @@ -1,4 +1,4 @@ -import IconWrapperStyle from './types'; +import type IconWrapperStyle from './types'; const style: IconWrapperStyle = { top: 1, diff --git a/src/components/Icon/IconWrapperStyles/index.ts b/src/components/Icon/IconWrapperStyles/index.ts index 541a2c296c17..2c4be7b706e8 100644 --- a/src/components/Icon/IconWrapperStyles/index.ts +++ b/src/components/Icon/IconWrapperStyles/index.ts @@ -1,4 +1,4 @@ -import IconWrapperStyle from './types'; +import type IconWrapperStyle from './types'; const style: IconWrapperStyle = { top: 2, diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx index 732fe90deae2..20f3fd4a8acb 100644 --- a/src/components/Icon/index.tsx +++ b/src/components/Icon/index.tsx @@ -1,11 +1,12 @@ -import {ImageContentFit} from 'expo-image'; +import type {ImageContentFit} from 'expo-image'; import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import ImageSVG from '@components/ImageSVG'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; -import IconAsset from '@src/types/utils/IconAsset'; +import type IconAsset from '@src/types/utils/IconAsset'; import IconWrapperStyles from './IconWrapperStyles'; type IconProps = { diff --git a/src/components/ImageSVG/index.native.tsx b/src/components/ImageSVG/index.native.tsx index c397e047b7e0..bdd0b3830a22 100644 --- a/src/components/ImageSVG/index.native.tsx +++ b/src/components/ImageSVG/index.native.tsx @@ -1,7 +1,7 @@ import {Image} from 'expo-image'; import React from 'react'; -import {ImageSourcePropType} from 'react-native'; -import ImageSVGProps from './types'; +import type {ImageSourcePropType} from 'react-native'; +import type ImageSVGProps from './types'; function ImageSVG({src, width = '100%', height = '100%', fill, contentFit = 'cover', style}: ImageSVGProps) { const tintColorProp = fill ? {tintColor: fill} : {}; diff --git a/src/components/ImageSVG/index.tsx b/src/components/ImageSVG/index.tsx index 32d83fdcadd3..3ce04a1a190a 100644 --- a/src/components/ImageSVG/index.tsx +++ b/src/components/ImageSVG/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {SvgProps} from 'react-native-svg'; -import ImageSVGProps from './types'; +import type {SvgProps} from 'react-native-svg'; +import type ImageSVGProps from './types'; function ImageSVG({src, width = '100%', height = '100%', fill, hovered = false, pressed = false, style, pointerEvents, preserveAspectRatio}: ImageSVGProps) { const ImageSvgComponent = src as React.FC; diff --git a/src/components/ImageSVG/types.ts b/src/components/ImageSVG/types.ts index cc580651c30c..341934852303 100644 --- a/src/components/ImageSVG/types.ts +++ b/src/components/ImageSVG/types.ts @@ -1,6 +1,6 @@ -import {ImageContentFit, ImageStyle} from 'expo-image'; -import {StyleProp, ViewStyle} from 'react-native'; -import IconAsset from '@src/types/utils/IconAsset'; +import type {ImageContentFit, ImageStyle} from 'expo-image'; +import type {StyleProp, ViewStyle} from 'react-native'; +import type IconAsset from '@src/types/utils/IconAsset'; type ImageSVGProps = { /** The asset to render. */ diff --git a/src/components/ImageWithSizeCalculation.tsx b/src/components/ImageWithSizeCalculation.tsx index af803bb360ee..b13d863d97e1 100644 --- a/src/components/ImageWithSizeCalculation.tsx +++ b/src/components/ImageWithSizeCalculation.tsx @@ -1,6 +1,7 @@ import delay from 'lodash/delay'; import React, {useEffect, useRef, useState} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import Log from '@libs/Log'; import FullscreenLoadingIndicator from './FullscreenLoadingIndicator'; diff --git a/src/components/Indicator.tsx b/src/components/Indicator.tsx index 7b7eae97fd86..5bf93eb8a6b3 100644 --- a/src/components/Indicator.tsx +++ b/src/components/Indicator.tsx @@ -1,7 +1,8 @@ import React from 'react'; import {StyleSheet, View} from 'react-native'; -import {OnyxCollection, withOnyx} from 'react-native-onyx'; -import {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxCollection} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx/lib/types'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as PolicyUtils from '@libs/PolicyUtils'; diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx index 1c66cef234ed..3c196f2a7492 100644 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ b/src/components/InlineCodeBlock/WrappedText.tsx @@ -1,5 +1,6 @@ import React, {Fragment} from 'react'; -import {StyleProp, TextStyle, View, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; diff --git a/src/components/InlineCodeBlock/types.ts b/src/components/InlineCodeBlock/types.ts index a100177e41a7..ae847b293a60 100644 --- a/src/components/InlineCodeBlock/types.ts +++ b/src/components/InlineCodeBlock/types.ts @@ -1,4 +1,4 @@ -import {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import type {TDefaultRenderer, TDefaultRendererProps, TText} from 'react-native-render-html'; type InlineCodeBlockProps = { diff --git a/src/components/InvertedFlatList/BaseInvertedFlatList.tsx b/src/components/InvertedFlatList/BaseInvertedFlatList.tsx index 08d990583572..9e3991828625 100644 --- a/src/components/InvertedFlatList/BaseInvertedFlatList.tsx +++ b/src/components/InvertedFlatList/BaseInvertedFlatList.tsx @@ -1,5 +1,6 @@ -import React, {ForwardedRef, forwardRef} from 'react'; -import {FlatListProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; +import type {FlatListProps} from 'react-native'; import FlatList from '@components/FlatList'; const AUTOSCROLL_TO_TOP_THRESHOLD = 128; diff --git a/src/components/InvertedFlatList/CellRendererComponent.tsx b/src/components/InvertedFlatList/CellRendererComponent.tsx index 252d47989064..b95fbf42cbb4 100644 --- a/src/components/InvertedFlatList/CellRendererComponent.tsx +++ b/src/components/InvertedFlatList/CellRendererComponent.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {StyleProp, View, ViewProps} from 'react-native'; +import type {StyleProp, ViewProps} from 'react-native'; +import {View} from 'react-native'; type CellRendererComponentProps = ViewProps & { index: number; diff --git a/src/components/InvertedFlatList/index.native.tsx b/src/components/InvertedFlatList/index.native.tsx index f2768251cc29..70cabf5a536a 100644 --- a/src/components/InvertedFlatList/index.native.tsx +++ b/src/components/InvertedFlatList/index.native.tsx @@ -1,5 +1,6 @@ -import React, {ForwardedRef, forwardRef} from 'react'; -import {FlatList, FlatListProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; +import type {FlatList, FlatListProps} from 'react-native'; import BaseInvertedFlatList from './BaseInvertedFlatList'; import CellRendererComponent from './CellRendererComponent'; diff --git a/src/components/InvertedFlatList/index.tsx b/src/components/InvertedFlatList/index.tsx index c8d58299ddff..a96058a3046f 100644 --- a/src/components/InvertedFlatList/index.tsx +++ b/src/components/InvertedFlatList/index.tsx @@ -1,5 +1,7 @@ -import React, {ForwardedRef, forwardRef, useEffect, useRef} from 'react'; -import {DeviceEventEmitter, FlatList, FlatListProps, NativeScrollEvent, NativeSyntheticEvent} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useEffect, useRef} from 'react'; +import type {FlatList, FlatListProps, NativeScrollEvent, NativeSyntheticEvent} from 'react-native'; +import {DeviceEventEmitter} from 'react-native'; import CONST from '@src/CONST'; import BaseInvertedFlatList from './BaseInvertedFlatList'; diff --git a/src/components/KeyboardAvoidingView/index.ios.tsx b/src/components/KeyboardAvoidingView/index.ios.tsx index fde4df6fc05b..a7cd767377ef 100644 --- a/src/components/KeyboardAvoidingView/index.ios.tsx +++ b/src/components/KeyboardAvoidingView/index.ios.tsx @@ -3,7 +3,7 @@ */ import React from 'react'; import {KeyboardAvoidingView as KeyboardAvoidingViewComponent} from 'react-native'; -import KeyboardAvoidingViewProps from './types'; +import type KeyboardAvoidingViewProps from './types'; function KeyboardAvoidingView(props: KeyboardAvoidingViewProps) { // eslint-disable-next-line react/jsx-props-no-spreading diff --git a/src/components/KeyboardAvoidingView/index.tsx b/src/components/KeyboardAvoidingView/index.tsx index cf3a5c5ebef7..09ec21e5b219 100644 --- a/src/components/KeyboardAvoidingView/index.tsx +++ b/src/components/KeyboardAvoidingView/index.tsx @@ -3,7 +3,7 @@ */ import React from 'react'; import {View} from 'react-native'; -import KeyboardAvoidingViewProps from './types'; +import type KeyboardAvoidingViewProps from './types'; function KeyboardAvoidingView(props: KeyboardAvoidingViewProps) { const {behavior, contentContainerStyle, enabled, keyboardVerticalOffset, ...rest} = props; diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index f75e3390136a..fc4f05eefd22 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -135,7 +135,7 @@ function OptionRowLHN(props) { props.reportID, '0', props.reportID, - '', + undefined, () => {}, () => setIsContextMenuActive(false), false, diff --git a/src/components/LinearGradient/index.native.ts b/src/components/LinearGradient/index.native.ts index 46bed24ebc10..29af26b96b64 100644 --- a/src/components/LinearGradient/index.native.ts +++ b/src/components/LinearGradient/index.native.ts @@ -1,5 +1,5 @@ import LinearGradientNative from 'react-native-linear-gradient'; -import LinearGradient from './types'; +import type LinearGradient from './types'; const LinearGradientImplementation: LinearGradient = LinearGradientNative; diff --git a/src/components/LinearGradient/index.ts b/src/components/LinearGradient/index.ts index 7246ccf2fb69..84d0fc2ce5c8 100644 --- a/src/components/LinearGradient/index.ts +++ b/src/components/LinearGradient/index.ts @@ -1,5 +1,5 @@ import LinearGradientWeb from 'react-native-web-linear-gradient'; -import LinearGradient from './types'; +import type LinearGradient from './types'; const LinearGradientImplementation: LinearGradient = LinearGradientWeb; diff --git a/src/components/LinearGradient/types.ts b/src/components/LinearGradient/types.ts index cf6661eaecaa..9e238ef71f12 100644 --- a/src/components/LinearGradient/types.ts +++ b/src/components/LinearGradient/types.ts @@ -1,4 +1,4 @@ -import LinearGradientNative from 'react-native-linear-gradient'; +import type LinearGradientNative from 'react-native-linear-gradient'; type LinearGradient = typeof LinearGradientNative; diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 3c649a8cb546..7313bb4aa7bb 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -1,6 +1,7 @@ import React, {createContext, useMemo} from 'react'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; -import {ValueOf} from 'type-fest'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import compose from '@libs/compose'; import DateUtils from '@libs/DateUtils'; import * as LocaleDigitUtils from '@libs/LocaleDigitUtils'; @@ -8,9 +9,10 @@ import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import * as Localize from '@libs/Localize'; import * as NumberFormatUtils from '@libs/NumberFormatUtils'; import CONST from '@src/CONST'; -import {TranslationPaths} from '@src/languages/types'; +import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import withCurrentUserPersonalDetails, {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; +import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; +import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; type Locale = ValueOf; diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 46adb1a4895e..3a2d9a0fd7b9 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js b/src/components/LocationErrorMessage/BaseLocationErrorMessage.tsx similarity index 81% rename from src/components/LocationErrorMessage/BaseLocationErrorMessage.js rename to src/components/LocationErrorMessage/BaseLocationErrorMessage.tsx index d90783d94ad5..33a0bba7481c 100644 --- a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js +++ b/src/components/LocationErrorMessage/BaseLocationErrorMessage.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; @@ -7,29 +6,25 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed import Text from '@components/Text'; import TextLink from '@components/TextLink'; import Tooltip from '@components/Tooltip'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import colors from '@styles/theme/colors'; import CONST from '@src/CONST'; -import * as locationErrorMessagePropTypes from './locationErrorMessagePropTypes'; +import type LocationErrorMessageProps from './types'; -const propTypes = { +type BaseLocationErrorMessageProps = LocationErrorMessageProps & { /** A callback that runs when 'allow location permission' link is pressed */ - onAllowLocationLinkPress: PropTypes.func.isRequired, - - // eslint-disable-next-line react/forbid-foreign-prop-types - ...locationErrorMessagePropTypes.propTypes, - - /* Onyx Props */ - ...withLocalizePropTypes, + onAllowLocationLinkPress: () => void; }; -function BaseLocationErrorMessage({onClose, onAllowLocationLinkPress, locationErrorCode, translate}) { +function BaseLocationErrorMessage({onClose, onAllowLocationLinkPress, locationErrorCode}: BaseLocationErrorMessageProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); + const {translate} = useLocalize(); + if (!locationErrorCode) { return null; } @@ -81,6 +76,5 @@ function BaseLocationErrorMessage({onClose, onAllowLocationLinkPress, locationEr } BaseLocationErrorMessage.displayName = 'BaseLocationErrorMessage'; -BaseLocationErrorMessage.propTypes = propTypes; -BaseLocationErrorMessage.defaultProps = locationErrorMessagePropTypes.defaultProps; -export default withLocalize(BaseLocationErrorMessage); + +export default BaseLocationErrorMessage; diff --git a/src/components/LocationErrorMessage/index.native.js b/src/components/LocationErrorMessage/index.native.tsx similarity index 67% rename from src/components/LocationErrorMessage/index.native.js rename to src/components/LocationErrorMessage/index.native.tsx index 467018538b6e..7936fff73c06 100644 --- a/src/components/LocationErrorMessage/index.native.js +++ b/src/components/LocationErrorMessage/index.native.tsx @@ -1,14 +1,14 @@ import React from 'react'; import {Linking} from 'react-native'; import BaseLocationErrorMessage from './BaseLocationErrorMessage'; -import * as locationErrorMessagePropTypes from './locationErrorMessagePropTypes'; +import type LocationErrorMessageProps from './types'; /** Opens app level settings from the native system settings */ const openAppSettings = () => { Linking.openSettings(); }; -function LocationErrorMessage(props) { +function LocationErrorMessage(props: LocationErrorMessageProps) { return ( { Linking.openURL(CONST.NEWHELP_URL); }; -function LocationErrorMessage(props) { +function LocationErrorMessage(props: LocationErrorMessageProps) { return ( void; /** * The location error code from onyx @@ -11,11 +9,7 @@ const propTypes = { * - code 2 = location is unavailable or there is some connection issue * - code 3 = location fetch timeout */ - locationErrorCode: PropTypes.oneOf([-1, 1, 2, 3]), -}; - -const defaultProps = { - locationErrorCode: null, + locationErrorCode?: -1 | 1 | 2 | 3; }; -export {propTypes, defaultProps}; +export default LocationErrorMessageProps; diff --git a/src/components/Lottie/index.tsx b/src/components/Lottie/index.tsx index 2bf7df056c4d..5c672cf7cab6 100644 --- a/src/components/Lottie/index.tsx +++ b/src/components/Lottie/index.tsx @@ -1,7 +1,9 @@ -import LottieView, {LottieViewProps} from 'lottie-react-native'; -import React, {ForwardedRef, forwardRef} from 'react'; +import type {LottieViewProps} from 'lottie-react-native'; +import LottieView from 'lottie-react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; import {View} from 'react-native'; -import DotLottieAnimation from '@components/LottieAnimations/types'; +import type DotLottieAnimation from '@components/LottieAnimations/types'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; diff --git a/src/components/LottieAnimations/index.tsx b/src/components/LottieAnimations/index.tsx index 078cdc0c6987..0d2cac253135 100644 --- a/src/components/LottieAnimations/index.tsx +++ b/src/components/LottieAnimations/index.tsx @@ -1,4 +1,4 @@ -import DotLottieAnimation from './types'; +import type DotLottieAnimation from './types'; const DotLottieAnimations: Record = { ExpensifyLounge: { diff --git a/src/components/LottieAnimations/types.ts b/src/components/LottieAnimations/types.ts index fcd793c6dfed..6000b9f853f0 100644 --- a/src/components/LottieAnimations/types.ts +++ b/src/components/LottieAnimations/types.ts @@ -1,4 +1,4 @@ -import {LottieViewProps} from 'lottie-react-native'; +import type {LottieViewProps} from 'lottie-react-native'; type DotLottieAnimation = { file: LottieViewProps['source']; diff --git a/src/components/MapView/Direction.tsx b/src/components/MapView/Direction.tsx index b3162149a48d..729d3c71e91f 100644 --- a/src/components/MapView/Direction.tsx +++ b/src/components/MapView/Direction.tsx @@ -1,6 +1,6 @@ import Mapbox from '@rnmapbox/maps'; import useThemeStyles from '@hooks/useThemeStyles'; -import {DirectionProps} from './MapViewTypes'; +import type {DirectionProps} from './MapViewTypes'; function Direction({coordinates}: DirectionProps) { const styles = useThemeStyles(); diff --git a/src/components/MapView/Direction.website.tsx b/src/components/MapView/Direction.website.tsx index f85bda125473..02fee83042a2 100644 --- a/src/components/MapView/Direction.website.tsx +++ b/src/components/MapView/Direction.website.tsx @@ -6,7 +6,7 @@ import React from 'react'; import {Layer, Source} from 'react-map-gl'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import {DirectionProps} from './MapViewTypes'; +import type {DirectionProps} from './MapViewTypes'; function Direction({coordinates}: DirectionProps) { const styles = useThemeStyles(); diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index f7a15ba10d2c..6321b461f21e 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -1,5 +1,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'; -import Mapbox, {MapState, MarkerView, setAccessToken} from '@rnmapbox/maps'; +import type {MapState} from '@rnmapbox/maps'; +import Mapbox, {MarkerView, setAccessToken} from '@rnmapbox/maps'; import {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; @@ -12,10 +13,10 @@ import useLocalize from '@src/hooks/useLocalize'; import useNetwork from '@src/hooks/useNetwork'; import ONYXKEYS from '@src/ONYXKEYS'; import Direction from './Direction'; -import {MapViewHandle} from './MapViewTypes'; +import type {MapViewHandle} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import {ComponentProps, MapViewOnyxProps} from './types'; +import type {ComponentProps, MapViewOnyxProps} from './types'; import utils from './utils'; const MapView = forwardRef( diff --git a/src/components/MapView/MapView.website.tsx b/src/components/MapView/MapView.website.tsx index 82909001fefd..05d86e8ec999 100644 --- a/src/components/MapView/MapView.website.tsx +++ b/src/components/MapView/MapView.website.tsx @@ -6,7 +6,8 @@ import {useFocusEffect} from '@react-navigation/native'; import mapboxgl from 'mapbox-gl'; import 'mapbox-gl/dist/mapbox-gl.css'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; -import Map, {MapRef, Marker} from 'react-map-gl'; +import type {MapRef} from 'react-map-gl'; +import Map, {Marker} from 'react-map-gl'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -20,10 +21,10 @@ import getCurrentPosition from '@src/libs/getCurrentPosition'; import ONYXKEYS from '@src/ONYXKEYS'; import Direction from './Direction'; import './mapbox.css'; -import {MapViewHandle} from './MapViewTypes'; +import type {MapViewHandle} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import {ComponentProps, MapViewOnyxProps} from './types'; +import type {ComponentProps, MapViewOnyxProps} from './types'; import utils from './utils'; const MapView = forwardRef( diff --git a/src/components/MapView/MapViewTypes.ts b/src/components/MapView/MapViewTypes.ts index 6cc52ac91d18..4b9ab6af233b 100644 --- a/src/components/MapView/MapViewTypes.ts +++ b/src/components/MapView/MapViewTypes.ts @@ -1,4 +1,4 @@ -import {ComponentType} from 'react'; +import type {ComponentType} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; type MapViewProps = { diff --git a/src/components/MapView/PendingMapView.tsx b/src/components/MapView/PendingMapView.tsx index 0af816785e9a..32bf42a14b10 100644 --- a/src/components/MapView/PendingMapView.tsx +++ b/src/components/MapView/PendingMapView.tsx @@ -6,7 +6,7 @@ import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; -import {PendingMapViewProps} from './MapViewTypes'; +import type {PendingMapViewProps} from './MapViewTypes'; function PendingMapView({title = '', subtitle = '', style}: PendingMapViewProps) { const hasTextContent = !_.isEmpty(title) || !_.isEmpty(subtitle); diff --git a/src/components/MapView/index.tsx b/src/components/MapView/index.tsx index f273845fe4c0..d9da7f1dfea3 100644 --- a/src/components/MapView/index.tsx +++ b/src/components/MapView/index.tsx @@ -1,8 +1,8 @@ import React from 'react'; import MapView from './MapView'; -import {ComponentProps} from './types'; +import type {MapViewProps} from './MapViewTypes'; -function MapViewComponent(props: ComponentProps) { +function MapViewComponent(props: MapViewProps) { // eslint-disable-next-line react/jsx-props-no-spreading return ; } diff --git a/src/components/MapView/types.ts b/src/components/MapView/types.ts index 2c8b9240c445..a0494a9ac499 100644 --- a/src/components/MapView/types.ts +++ b/src/components/MapView/types.ts @@ -1,6 +1,6 @@ -import {OnyxEntry} from 'react-native-onyx'; -import * as OnyxTypes from '@src/types/onyx'; -import {MapViewProps} from './MapViewTypes'; +import type {OnyxEntry} from 'react-native-onyx'; +import type * as OnyxTypes from '@src/types/onyx'; +import type {MapViewProps} from './MapViewTypes'; type MapViewOnyxProps = { userLocation: OnyxEntry; diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx index 3e235a2fc88a..459131ecc434 100644 --- a/src/components/MentionSuggestions.tsx +++ b/src/components/MentionSuggestions.tsx @@ -5,7 +5,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import getStyledTextArray from '@libs/GetStyledTextArray'; import CONST from '@src/CONST'; -import {Icon} from '@src/types/onyx/OnyxCommon'; +import type {Icon} from '@src/types/onyx/OnyxCommon'; import AutoCompleteSuggestions from './AutoCompleteSuggestions'; import Avatar from './Avatar'; import Text from './Text'; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index db150d55f0d2..14dfd0e8dbc4 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -1,9 +1,11 @@ import ExpensiMark from 'expensify-common/lib/ExpensiMark'; -import {ImageContentFit} from 'expo-image'; -import React, {ForwardedRef, forwardRef, ReactNode, useEffect, useMemo, useRef, useState} from 'react'; -import {GestureResponderEvent, StyleProp, TextStyle, View, ViewStyle} from 'react-native'; -import {AnimatedStyle} from 'react-native-reanimated'; -import {ValueOf} from 'type-fest'; +import type {ImageContentFit} from 'expo-image'; +import type {ForwardedRef, ReactNode} from 'react'; +import React, {forwardRef, useEffect, useMemo, useRef, useState} from 'react'; +import type {GestureResponderEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {View} from 'react-native'; +import type {AnimatedStyle} from 'react-native-reanimated'; +import type {ValueOf} from 'type-fest'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -12,16 +14,16 @@ import ControlSelection from '@libs/ControlSelection'; import convertToLTR from '@libs/convertToLTR'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import getButtonState from '@libs/getButtonState'; -import {AvatarSource} from '@libs/UserUtils'; +import type {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import * as Session from '@userActions/Session'; import CONST from '@src/CONST'; -import {Icon as IconType} from '@src/types/onyx/OnyxCommon'; -import IconAsset from '@src/types/utils/IconAsset'; +import type {Icon as IconType} from '@src/types/onyx/OnyxCommon'; +import type IconAsset from '@src/types/utils/IconAsset'; import Avatar from './Avatar'; import Badge from './Badge'; import DisplayNames from './DisplayNames'; -import {DisplayNameWithTooltip} from './DisplayNames/types'; +import type {DisplayNameWithTooltip} from './DisplayNames/types'; import FormHelpMessage from './FormHelpMessage'; import Hoverable from './Hoverable'; import Icon from './Icon'; @@ -49,14 +51,14 @@ type UnresponsiveProps = { type IconProps = { /** Flag to choose between avatar image or an icon */ - iconType: typeof CONST.ICON_TYPE_ICON; + iconType?: typeof CONST.ICON_TYPE_ICON; /** Icon to display on the left side of component */ icon: IconAsset; }; type AvatarProps = { - iconType: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; + iconType?: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; icon: AvatarSource; }; @@ -85,7 +87,7 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & titleStyle?: ViewStyle; /** Any adjustments to style when menu item is hovered or pressed */ - hoverAndPressStyle: StyleProp>; + hoverAndPressStyle?: StyleProp>; /** Additional styles to style the description text below the title */ descriptionTextStyle?: StyleProp; @@ -175,7 +177,7 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & isSelected?: boolean; /** Prop to identify if we should load avatars vertically instead of diagonally */ - shouldStackHorizontally: boolean; + shouldStackHorizontally?: boolean; /** Prop to represent the size of the avatar images to be shown */ avatarSize?: (typeof CONST.AVATAR_SIZE)[keyof typeof CONST.AVATAR_SIZE]; @@ -220,10 +222,10 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & furtherDetails?: string; /** The function that should be called when this component is LongPressed or right-clicked. */ - onSecondaryInteraction: () => void; + onSecondaryInteraction?: () => void; /** Array of objects that map display names to their corresponding tooltip */ - titleWithTooltips: DisplayNameWithTooltip[]; + titleWithTooltips?: DisplayNameWithTooltip[]; /** Icon should be displayed in its own color */ displayInDefaultIconColor?: boolean; diff --git a/src/components/MenuItemWithTopDescription.tsx b/src/components/MenuItemWithTopDescription.tsx index 48fa95ecf637..0a48740de62e 100644 --- a/src/components/MenuItemWithTopDescription.tsx +++ b/src/components/MenuItemWithTopDescription.tsx @@ -1,5 +1,6 @@ -import React, {ForwardedRef, forwardRef} from 'react'; -import {View} from 'react-native'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; +import type {View} from 'react-native'; import MenuItem from './MenuItem'; import type {MenuItemProps} from './MenuItem'; diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx index f49a0927de06..cfec6fd292e9 100644 --- a/src/components/MessagesRow.tsx +++ b/src/components/MessagesRow.tsx @@ -1,9 +1,10 @@ import React from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Localize from '@libs/Localize'; +import type * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DotIndicatorMessage from './DotIndicatorMessage'; diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx index e03c32f6bfcc..6e5b4eddae9e 100644 --- a/src/components/Modal/BaseModal.tsx +++ b/src/components/Modal/BaseModal.tsx @@ -13,7 +13,7 @@ import useNativeDriver from '@libs/useNativeDriver'; import variables from '@styles/variables'; import * as Modal from '@userActions/Modal'; import CONST from '@src/CONST'; -import BaseModalProps from './types'; +import type BaseModalProps from './types'; function BaseModal( { diff --git a/src/components/Modal/index.android.tsx b/src/components/Modal/index.android.tsx index 2343cb4c70a9..4d7ae128a114 100644 --- a/src/components/Modal/index.android.tsx +++ b/src/components/Modal/index.android.tsx @@ -3,7 +3,7 @@ import {AppState} from 'react-native'; import withWindowDimensions from '@components/withWindowDimensions'; import ComposerFocusManager from '@libs/ComposerFocusManager'; import BaseModal from './BaseModal'; -import BaseModalProps from './types'; +import type BaseModalProps from './types'; AppState.addEventListener('focus', () => { ComposerFocusManager.setReadyToFocus(); diff --git a/src/components/Modal/index.ios.tsx b/src/components/Modal/index.ios.tsx index f780775ec216..cbe58a071d7d 100644 --- a/src/components/Modal/index.ios.tsx +++ b/src/components/Modal/index.ios.tsx @@ -1,7 +1,7 @@ import React from 'react'; import withWindowDimensions from '@components/withWindowDimensions'; import BaseModal from './BaseModal'; -import BaseModalProps from './types'; +import type BaseModalProps from './types'; function Modal({children, ...rest}: BaseModalProps) { return ( diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 4269420dcd7f..56f3c76a8879 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -5,7 +5,7 @@ import useTheme from '@hooks/useTheme'; import StatusBar from '@libs/StatusBar'; import CONST from '@src/CONST'; import BaseModal from './BaseModal'; -import BaseModalProps from './types'; +import type BaseModalProps from './types'; function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = () => {}, children, ...rest}: BaseModalProps) { const theme = useTheme(); diff --git a/src/components/Modal/types.ts b/src/components/Modal/types.ts index 461a5935eda9..0fed37ffea8b 100644 --- a/src/components/Modal/types.ts +++ b/src/components/Modal/types.ts @@ -1,8 +1,8 @@ -import {ViewStyle} from 'react-native'; -import {ModalProps} from 'react-native-modal'; -import {ValueOf} from 'type-fest'; -import {WindowDimensionsProps} from '@components/withWindowDimensions/types'; -import CONST from '@src/CONST'; +import type {ViewStyle} from 'react-native'; +import type {ModalProps} from 'react-native-modal'; +import type {ValueOf} from 'type-fest'; +import type {WindowDimensionsProps} from '@components/withWindowDimensions/types'; +import type CONST from '@src/CONST'; type PopoverAnchorPosition = { top?: number; diff --git a/src/components/MoneyReportHeader.js b/src/components/MoneyReportHeader.js index a559e876af18..8ed6d0746438 100644 --- a/src/components/MoneyReportHeader.js +++ b/src/components/MoneyReportHeader.js @@ -44,6 +44,9 @@ const propTypes = { /** The role of the current user in the policy */ role: PropTypes.string, + + /** Whether Scheduled Submit is turned on for this policy */ + isHarvestingEnabled: PropTypes.bool, }), /** The chat report this report is linked to */ @@ -70,7 +73,9 @@ const defaultProps = { session: { email: null, }, - policy: {}, + policy: { + isHarvestingEnabled: false, + }, }; function MoneyReportHeader({session, personalDetails, policy, chatReport, nextStep, report: moneyRequestReport, isSmallScreenWidth}) { @@ -108,6 +113,12 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableTotal, moneyRequestReport.currency); const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && isSmallScreenWidth); + // The submit button should be success green colour only if the user is submitter and the policy does not have Scheduled Submit turned on + const isWaitingForSubmissionFromCurrentUser = useMemo( + () => chatReport.isOwnPolicyExpenseChat && !policy.isHarvestingEnabled, + [chatReport.isOwnPolicyExpenseChat, policy.isHarvestingEnabled], + ); + const threeDotsMenuItems = [HeaderUtils.getPinMenuItem(moneyRequestReport)]; if (!ReportUtils.isArchivedRoom(chatReport)) { threeDotsMenuItems.push({ @@ -164,7 +175,7 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt