diff --git a/.eslintrc.js b/.eslintrc.js index b5b4add538f6..75a74ed371c4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,6 +38,7 @@ module.exports = { { files: ['*.js', '*.jsx', '*.ts', '*.tsx'], rules: { + 'rulesdir/no-multiple-onyx-in-file': 'off', 'rulesdir/onyx-props-must-have-default': 'off', 'react-native-a11y/has-accessibility-hint': ['off'], 'react-native-a11y/has-valid-accessibility-descriptors': [ @@ -163,6 +164,7 @@ module.exports = { }, ], curly: 'error', + 'you-dont-need-lodash-underscore/throttle': 'off', }, }, { diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index f7f1e5fc7ac7..3666e8c7d343 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -192,7 +192,6 @@ jobs: run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log" - name: Check if test failed, if so post the results and add the DeployBlocker label - if: ${{ github.event_name == 'workflow_call' }} run: | if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash diff --git a/README.md b/README.md index fce7cee8dcdd..9aad797ebb51 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ For an M1 Mac, read this [SO](https://stackoverflow.com/questions/64901180/how-t * If you get the error `Could not find 'bundler'`, install the bundler gem first: `gem install bundler` and try again. * If you are using MacOS and get the error `Gem::FilePermissionError` when trying to install the bundler gem, you're likely using system Ruby, which requires administrator permission to modify. To get around this, install another version of Ruby with a version manager like [rbenv](https://github.com/rbenv/rbenv#installation). * Before installing iOS dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run `npm run configure-mapbox` and follow the instructions. + * For help with MapBox token, you can see [this Slack thread](https://expensify.slack.com/archives/C01GTK53T8Q/p1692740856745279?thread_ts=1692322511.804599&cid=C01GTK53T8Q) * To install the iOS dependencies, run: `npm install && npm run pod-install` * If you are an Expensify employee and want to point the emulator to your local VM, follow [this](https://stackoverflow.com/c/expensify/questions/7699) * To run a on a **Development Simulator**: `npm run ios` diff --git a/android/app/build.gradle b/android/app/build.gradle index 9567efa94b03..2cf9fbd5727f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -90,8 +90,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001037600 - versionName "1.3.76-0" + versionCode 1001037703 + versionName "1.3.77-3" } flavorDimensions "default" diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 7e1870e8b30b..2eab8de1eb7b 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -4,6 +4,7 @@ + + +``` + ### Labels, Placeholders, & Hints Labels are required for each input and should clearly mark the field. Optional text may appear below a field when a hint, suggestion, or context feels necessary. If validation fails on such a field, its error should clearly explain why without relying on the hint. Inline errors should always replace the microcopy hints. Placeholders should not be used as it’s customary for labels to appear inside form fields and animate them above the field when focused. @@ -13,7 +27,8 @@ Labels are required for each input and should clearly mark the field. Optional t Labels and hints are enabled by passing the appropriate props to each input: ```jsx - @@ -24,7 +39,8 @@ Labels and hints are enabled by passing the appropriate props to each input: If a field has a character limit we should give that field a max limit. This is done by passing the maxLength prop to TextInput. ```jsx - ``` @@ -42,7 +58,8 @@ We should always set people up for success on native platforms by enabling the b We have a couple of keyboard types [defined](https://github.com/Expensify/App/blob/572caa9e7cf32a2d64fe0e93d171bb05a1dfb217/src/CONST.js#L357-L360) and should be used like so: ```jsx - ``` @@ -56,7 +73,8 @@ As a best practice we should avoid asking for information we can get via other m Browsers use the name prop to autofill information into the input. Here's a [reference](https://developers.google.com/web/fundamentals/design-and-ux/input/forms#recommended_input_name_and_autocomplete_attribute_values) for available values for the name prop. ```jsx - ``` @@ -91,7 +109,7 @@ To give a slightly more detailed example of how this would work with phone numbe Form inputs will NOT store draft values by default. This is to avoid accidentally storing any sensitive information like passwords, SSN or bank account information. We need to explicitly tell each form input to save draft values by passing the shouldSaveDraft prop to the input. Saving draft values is highly desirable and we should always try to save draft values. This way when a user continues a given flow they can easily pick up right where they left off if they accidentally exited a flow. Inputs with saved draft values [will be cleared when a user logs out](https://github.com/Expensify/App/blob/aa1f0f34eeba5d761657168255a1ae9aebdbd95e/src/libs/actions/SignInRedirect.js#L52) (like most data). Additionally, we should clear draft data once the form is successfully submitted by calling `Onyx.set(ONYXKEY.FORM_ID, null)` in the onSubmit callback passed to Form. ```jsx - ``` @@ -178,9 +196,9 @@ Submit buttons shall not be disabled or blocked from being pressed in most cases The only time we won’t allow a user to press the submit button is when we have submitted the form and are waiting for a response (e.g. from the API). In this case we will show a loading indicator and additional taps on the submit button will have no effect. This is handled by the Form component and will also ensure that a form cannot be submitted multiple times. -## Using Form.js +## Using Form -The example below shows how to use [Form.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/components/Form.js) in our app. You can also refer to [Form.stories.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/stories/Form.stories.js) for more examples. +The example below shows how to use [FormProvider](https://github.com/Expensify/App/blob/029d009731dcd3c44cd1321672b9672ef0d3d7d9/src/components/Form/FormProvider.js) and [InputWrapper](https://github.com/Expensify/App/blob/029d009731dcd3c44cd1321672b9672ef0d3d7d9/src/components/Form/InputWrapper.js) in our app. You can also refer to [Form.stories.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/stories/Form.stories.js) for more examples. ```jsx function validate(values) { @@ -201,43 +219,47 @@ function onSubmit(values) { }, 1000); } -
- // Wrapping TextInput in a View to show that Form inputs can be nested in other components + // Wrapping InputWrapper in a View to show that Form inputs can be nested in other components - - - + ``` -`Form.js` also works with inputs nested in a custom component, e.g. [AddressForm](https://github.com/Expensify/App/blob/86579225ff30b21dea507347735259637a2df461/src/pages/ReimbursementAccount/AddressForm.js). The only exception is that the nested component shouldn't be wrapped around any HoC. +`FormProvider` also works with inputs nested in a custom component, e.g. [AddressForm](https://github.com/Expensify/App/blob/86579225ff30b21dea507347735259637a2df461/src/pages/ReimbursementAccount/AddressForm.js). The only exception is that the nested component shouldn't be wrapped around any HoC and all inputs in the component needs to be wrapped with `InputWrapper`. ```jsx const BankAccountForm = () => ( <> - - ( ); // ... -
- + ``` ### Props provided to Form inputs @@ -266,7 +288,7 @@ The following prop is available to form inputs: - value: The value to show for the input. - onValueChange: A callback that is called when the input's value changes. -Form.js will automatically provide the following props to any input with the inputID prop. +InputWrapper component will automatically provide the following props to any input with the inputID prop. - ref: A React ref that must be attached to the input. - value: The input value. @@ -287,13 +309,13 @@ An example of this can be seen in the [ACHContractStep](https://github.com/Expen ### Safe Area Padding -Any `Form.js` that has a button will also add safe area padding by default. If the `
` is inside a `` we will want to disable the default safe area padding applied there e.g. +Any `FormProvider.js` that has a button will also add safe area padding by default. If the `` is inside a `` we will want to disable the default safe area padding applied there e.g. ```js - + {...} - + ``` diff --git a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/Global-Reimbursement.md b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/Global-Reimbursement.md deleted file mode 100644 index 073d3a9bd700..000000000000 --- a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/Global-Reimbursement.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Global Reimbursement -description: Global Reimbursement ---- -## Resource Coming Soon! diff --git a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/International-Reimbursements.md b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/International-Reimbursements.md new file mode 100644 index 000000000000..7313c73ac6e6 --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/International-Reimbursements.md @@ -0,0 +1,105 @@ +--- +title: International Reimbursements +description: International Reimbursements +--- +# Overview + +If your company’s business bank account is in the US, Canada, the UK, Europe, or Australia, you now have the option to send direct reimbursements to nearly any country across the globe! +The process to enable global reimbursements is dependent on the currency of your reimbursement bank account, so be sure to review the corresponding instructions below. + +# How to request international reimbursements + +## The reimbursement account is in USD + +If your reimbursement bank account is in USD, the first step is connecting the bank account to Expensify. +The individual who plans on sending reimbursements internationally should head to **Settings > Account > Payments > Add Verified Bank Account**. From there, you will provide company details, input personal information, and upload a copy of your ID. + +Once the USD bank account is verified (or if you already had a USD business bank account connected), click the support icon in your Expensify account to inform your Setup Specialist, Account Manager, or Concierge that you’d like to enable international reimbursements. From there, Expensify will ask you to confirm the currencies of the reimbursement and employee bank accounts. + +Our team will assess your account, and if you meet the criteria, international reimbursements will be enabled. + +## The reimbursement account is in AUD, CAD, GBP, EUR + +To request international reimbursements, contact Expensify Support to make that request. + +You can do this by clicking on the support icon and informing your Setup Specialist, Account Manager, or Concierge that you’d like to set up global reimbursements on your account. +From there, Expensify will ask you to confirm both the currencies of the reimbursement and employee bank accounts. + +Our team will assess your account, and if you meet the criteria, international reimbursements will be enabled. + +# How to verify the bank account for sending international payments + +Once international payments are enabled on your Expensify account, the next step is verifying the bank account to send the reimbursements. + +## The reimbursement account is in USD + +First, confirm the workspace settings are set up correctly by doing the following: +1. Head to **Settings > Workspaces > Group > _[Workspace Name]_ > Reports** and check that the workspace currency is USD +2. Under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements**, set the reimbursement method to direct +3. Under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements**, set the USD bank account to the default account + +Once that’s all set, head to **Settings > Account > Payments**, and click **Enable Global Reimbursement** on the bank account (this button may not show for up to 60 minutes after the Expensify team confirms international reimbursements are available on your account). + +From there, you’ll fill out a form via DocuSign. Once the form is complete, it is automatically sent to our Compliance Team for review. Our Support Team will contact you with more details if additional information is required. + +## The reimbursement account is in AUD, CAD, GBP, EUR + +First, confirm the workspace currency corresponds with the currency of the reimbursement bank account. You can do this under **Settings > Workspaces > Group > _[Workspace Name]_ > Reports**. It should be AUD, CAD, GBP, or EUR. + +Next, add the bank account to Expensify: +1. Head to **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements** and set the reimbursement method to direct (this button may not show for up to 60 minutes after the Expensify team confirms international reimbursements are available on your account) +2. Click **Add Business Bank Account** +3. If the incorrect country shows as the default, click **Switch Country** to select the correct country +4. Enter the bank account details +5. Click **Save & Continue** + +From there, you’ll fill out a form via DocuSign. Once the form is complete, it is automatically sent to our Compliance Team for review. Our Support Team will contact you with more details if additional information is required. + +# How to start reimbursing internationally + +After the bank account is verified for international payments, set the correct bank account as the reimbursement account. + +You can do this under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements** by selecting the reimbursement account as the default account. + +Finally, have your employees add their deposit-only bank accounts. They can do this by logging into their Expensify accounts, heading to **Settings > Account > Payments**, and clicking **Add Deposit-Only Bank Account**. + +# Deep Dive + +## Documents requested + +Our Compliance Team may ask for additional information depending on who initiates the verification or what information you provide on the DocuSign form. + +Examples of additional requested information: +- The reimburser’s proof of address and ID +- Company directors’ proofs of address and IDs +- An authorization letter +- An independently certified documentation such as shareholder agreement from a lawyer, notary, or public accountant if an individual owns more than 25% of the company + +# FAQ + +## How many people can send reimbursements internationally? + +Once your company is authorized to send global payments, only the individual who went through the verification can reimburse international employees. + +## How long does it take to verify an account for international payments? + +It varies! The verification process can take a few business days to several weeks. It depends on whether or not the information in the DocuSign form is correct if our Compliance Team requires any additional information, and how responsive the employee verifying the company’s details is to our requests. + +## If I already have a USD bank account connected to Expensify, do I need to go through the verification process again to enable international payments? + +If you’ve already connected a US business bank account, you can request to enable global reimbursements by contacting Expensify Support immediately. However, additional steps are required to verify the bank account for international payments. + +## My employee says they don’t have the option to add their non-USD bank account as a deposit account – what should they do? + +Have the employee double-check that their default workspace is set as the workspace that's connected to the bank you're using to send international payments. + +An employee can confirm their default workspace is under **Settings > Workspaces > Group**. The default workspace has a green checkmark next to it. They can change their default workspace by clicking **Default Workspace** on the correct workspace. + +## Who is the “Authorized User” on the International Reimbursement DocuSign form? + +This is the person who will process international reimbursements. The authorized user should be the same person who manages the bank account connection in Expensify. + +## Who should I enter as the “User” on the International Reimbursement form? + +You can leave this form section blank since the “User” is Expensify. + diff --git a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/business-bank-accounts/Add-a-Business-Bank-Account-(AUD).md b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/business-bank-accounts/Add-a-Business-Bank-Account-(AUD).md new file mode 100644 index 000000000000..6f0c738693ca --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/business-bank-accounts/Add-a-Business-Bank-Account-(AUD).md @@ -0,0 +1,50 @@ +--- +title: Add-a-Business-Bank-Account-(AUD).md +description: This article provides insight on setting up and using an Australian Business Bank account in Expensify. +--- + +# How to add an Australian business bank account (for admins) +A withdrawal account is the business bank account that you want to use to pay your employee reimbursements. + +_Your policy currency must be set to AUD and reimbursement setting set to Indirect to continue. If your main policy is used for something other than AUD, then you will need to create a new one and set that policy to AUD._ +To set this up, you’ll run through the following steps: + +1. Go to *Settings > Your Account > Payments* and click *Add Verified Bank Account* +![Click the Verified Bank Account button in the bottom right-hand corner of the screen](https://help.expensify.com/assets/images/add-vba-australian-account.png){:width="100%"} + +2. Enter the required information to connect to your business bank account. If you don't know your Bank User ID/Direct Entry ID/APCA Number, please contact your bank and they will be able to provide this. +![Enter your information in each of the required fields](https://help.expensify.com/assets/images/add-vba-australian-account-modal.png){:width="100%"} + +3. Link the withdrawal account to your policy by heading to *Settings > Policies > Group > [Policy name] > Reimbursement* +4. Click *Direct* reimbursement +5. Set the default withdrawal account for processing reimbursements +6. Tell your employees to add their deposit accounts and start reimbursing. + +# How to delete a bank account +If you’re no longer using a bank account you previously connected to Expensify, you can delete it by doing the following: + +1. Navigate to Settings > Accounts > Payments +2. Click *Delete* +![Click the Delete button](https://help.expensify.com/assets/images/delete-australian-bank-account.png){:width="100%"} + +You can complete this process either via the web app (on a computer), or via the mobile app. + +# Deep Dive +## Bank-specific batch payment support + +If you are new to using Batch Payments in Australia, to reimburse your staff or process payroll, you may want to check out these bank-specific instructions for how to upload your .aba file: + +ANZ Bank - [Import a file for payroll payments](https://www.anz.com.au/support/internet-banking/pay-transfer-business/payroll/import-file/) +CommBank - [Importing and using
 Direct Entry (EFT) files](https://www.commbank.com.au/business/pds/003-279-importing-a-de-file.pdf) +Westpac - [Importing Payment Files](https://www.westpac.com.au/business-banking/online-banking/support-faqs/import-files/) +NAB - [Quick Reference Guide - Upload a payment file](https://www.nab.com.au/business/online-banking/nab-connect/help) +Bendigo Bank - [Bulk payments user guide](https://www.bendigobank.com.au/globalassets/documents/business/bulk-payments-user-guide.pdf) +Bank of Queensland - [Payments file upload facility FAQ](https://www.boq.com.au/help-and-support/online-banking/ob-faqs-and-support/faq-pfuf) + +*Note:* Some financial institutions require an ABA file to include a *self-balancing transaction*. If you are unsure, please check with your bank to ensure whether to tick this option or not, as selecting an incorrect option will result in the ABA file not working with your bank's internet banking platform. + +## Enable Global Reimbursement + +If you have employees in other countries outside of Australia, you can now reimburse them directly using Global Reimbursement. + +To do this, you’ll first need to delete any existing Australian business bank accounts. Then, you’ll want to follow the instructions to enable Global Reimbursements diff --git a/docs/articles/expensify-classic/exports/Default-Export-Templates.md b/docs/articles/expensify-classic/exports/Default-Export-Templates.md index 7650cff38946..f6043aaea2eb 100644 --- a/docs/articles/expensify-classic/exports/Default-Export-Templates.md +++ b/docs/articles/expensify-classic/exports/Default-Export-Templates.md @@ -2,4 +2,29 @@ title: Default Export Templates description: Default Export Templates --- -## Resource Coming Soon! +# Overview +Use default export templates for exporting report data to a CSV format, for data analysis, or uploading to an accounting software. +Below is a breakdown of the available default templates. +# How to use default export templates +- **All Data - Expense Level Export** - This export prints a line for each expense with all of the data associated with the expenses. This is useful if you want to see all of the data stored in Expensify for each expense. +- **All Data - Report Level Export** - This export prints a line per report, giving a summary of the report data. +- **Basic Export** - A simpler expense level export without as much detail. This exports the data visible on the PDF of the report. Basics such as date, amount, merchant, category, tag, reimbursable state, description, receipt URL, and original expense currency and amount. +- **Canadian Multiple Tax Export** - Exports a line per expense with all available info on the taxes applied to the expenses on your report(s). This is useful if you need to see the tax spend. +- **Category Export** - Exports category names with the total amount attributed to each category on the report. While you can also access this information on the Insights page, it can be convenient to export to a CSV to run further analysis in your favorite spreadsheet program. +- **Per Diem Export** - This exports basic expense details only for the per diem expenses on the report. Useful for reviewing employee Per Diem spend. +- **Tag Export** - Exports tag names into columns with the total amount attributed to each tag on the report. + +# How to export using a default template +1. Navigate to your Reports page +2. Select the reports you want to export (you can use the filters to help you find the reports you’re after) +3. Click the **Export to** in the top right corner +4. Select the export template you’d like to use + +# FAQ +## Why are my numbers exporting in a weird format? +Do your numbers look something like this: 1.7976931348623157e+308? This means that your spreadsheet program is formatting long numbers in an exponential or scientific format. If that happens, you can correct it by changing the data to Plain Text or a Number in your spreadsheet program. +## Why are my leading zeros missing? +Is the export showing “1” instead of “01”? This means that your spreadsheet program is cutting off the leading zero. This is a common issue with viewing exported data in Excel. Unfortunately, we don’t have a good solution for this. We recommend checking your spreadsheet program’s help documents for suggestions for formatting. +## I want a report that is not in the default list, how can I build that? +For a guide on building your own custom template check out Exports > Custom Exports in the Help pages! + diff --git a/docs/articles/expensify-classic/exports/Other-Export-Options.md b/docs/articles/expensify-classic/exports/Other-Export-Options.md new file mode 100644 index 000000000000..31f5aaf93032 --- /dev/null +++ b/docs/articles/expensify-classic/exports/Other-Export-Options.md @@ -0,0 +1,39 @@ +--- +title: Other Export Options +description: Other Export Options +--- + +# Overview +Here’s a quick look at how to export your expense and report data into a spreadsheet, accounting package, or PDF. We’ll also show you how to print out your reports in a few easy steps. + +# How to export expenses and reports to a CSV or accounting package +From the **Expenses** page, you can export individual expenses into a CSV. From the Reports page, you can export entire reports into a CSV or connected accounting package. Here’s how to do both: + +1. Go to either the Expenses or Reports page +2. On the left hand side, select the expenses/reports you’d like to export +3. Click **Export to** at the top right of the page +4. Choose the desired export option + +You can use one of the default templates or create your own template. The default templates and the option to export to a connected accounting package are only available on the **Reports** page. Visit the specific help page for your accounting package to learn more about how to get this set up. + +# How to export a report as a PDF +1. Go to the **Reports** page +2. Click into a report +3. Click on **Details** in the top right of the report +4. Click the **download icon** to generate a PDF + +The PDF will include all expenses, any attached receipts, and all report notes. + +# How to print a report +1. Go to the Reports page +2. Click into a report +3. Click on **Details** in the top right of the report +4. Click the **print icon** + +# FAQ +## Why isn’t my report exporting? +Big reports with lots of expenses may cause the PDF download to fail due to images with large resolutions. In that case, try breaking the report into multiple smaller reports. Also, please note that a report must have at least one expense to be exported or saved as a PDF. +## Can I download multiple PDFs at once? +No, you can’t download multiple reports as PDFs at the same time. If you’d like to export multiple reports, an alternative to consider is the CSV export option. +## The data exported to Excel is showing incorrectly. How can I fix this? +When opening a CSV file export from Expensify in Excel, it’ll automatically register report IDs and transaction IDs as numbers and assign the number format to the report ID column. If a number is greater than a certain length, Excel will contract the number and display it in exponential form. To prevent this, the number needs to be imported as text, which can be done by opening Excel and clicking File > Import > select your CSV file > follow the prompts and on step 3 set the report ID/transactionID column to import as Text. diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md b/docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md index 3ee1c8656b4b..f7a5127c9c0e 100644 --- a/docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md +++ b/docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md @@ -1,5 +1,55 @@ --- -title: Coming Soon -description: Coming Soon +title: Gusto Integration +description: Automatically sync employees between Gusto and Expensify --- -## Resource Coming Soon! + +# Overview + +Expensify's direct integration with Gusto will automatically: + +- **Create new Expensify accounts** for full-time, active employees when they're hired +- **Update the approval workflow in Expensify** based on any changes in Gusto +- **Deprovision an employee's Expensify account** upon Gusto termination date + +# How to connect the Gusto integration +## Before connecting Expensify with Gusto, please review the prerequisites: + +- You must be an admin in both Gusto and in Expensify to establish the integration +- You must have a paid group workspace in Expensify (i.e. a Control or Collect workspace) +- Every employee record in Gusto must have an email address, since that’s how each employee will sign into Expensify. We recommend that each employee's Gusto record use their work email address. +- Gusto will add all employees to one Expensify workspace, so if you have more than one workspace, you'll need to choose one to connect to Gusto + +## To connect your Expensify workspace to Gusto: + +1. Navigate to **Settings > Workspaces > _[Workspace Name]_ > Connections** +2. Scroll down to HR Integrations, click the **Connect with Gusto** radio button, then click the **Connect with Gusto** button +3. Login to your Gusto account using your Gusto admin credentials and authorize Expensify to access your Gusto account + +## To configure the connection: + +1. Select the Approval Workflow that works best for your team + a. **Basic Approval** - Each employee will submit expense reports to one final approver. By default, the final approver is the workspace's Billing Owner in Expensify. + b. **Manager Approval** - Expense reports will first be submitted to each employee's direct manager as listed in Gusto, and then forwarded to one final approver (the Expensify workspace's Billing Owner by default). This option is only available on the Control workspace plan. + c. **Configure Manually** - Use the Members table to manually configure how employees submit reports. In this case, you're choosing to not import employee managers, and you will need to manually set and update the approval workflow for each employee. This option is only available on the Control workspace plan. +2. Click **Save** in the bottom right corner to sync employees into Expensify +3. If the connection is successful, you'll see a summary of how many employees were synced. If any employees were skipped, we'll tell you why. + +# FAQ +## Can I import different sets of employees into different Expensify workspaces? + +No - Gusto will add all employees to one Expensify workspace, so if you have more than one workspace, you'll need to choose when connecting. + +## Can I change the Approval Workflow mode after connecting? + +Yes! You can change the Approval Workflow mode in two ways: + +1. Go to **Settings > Workspaces > _[Workspace Name]_ > Members**, then scroll down to Approval Mode below the list of workspace members +2. Go to **Settings > Workspaces > _[Workspace Name]_ > Connections**, click Configure under Gusto, then select the desired Approval Mode and **Save** + + +## Why do my employees have duplicate Expensify accounts after I set up the Gusto integration? + +If your employees are set up in Expensify with their company emails, but with their personal emails in Gusto, then they will end up with duplicate Expensify accounts after you connect the two systems. The Gusto integration imports users from Gusto using the emails entered in Gusto - if it's a different email from an existing account in Expensify, then a new, separate account will be created. + +To resolve this, you can ask each affected employee to merge their existing Expensify account with the new Expensify account by navigating to **Settings > Account > Account Details** and scrolling down to **Merge Accounts**. + diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Workday.md b/docs/articles/expensify-classic/integrations/HR-integrations/Workday.md index 3ee1c8656b4b..e9077fc40a50 100644 --- a/docs/articles/expensify-classic/integrations/HR-integrations/Workday.md +++ b/docs/articles/expensify-classic/integrations/HR-integrations/Workday.md @@ -1,5 +1,104 @@ --- -title: Coming Soon -description: Coming Soon +title: Workday Integration +description: Automatically sync employees between Workday and Expensify --- -## Resource Coming Soon! + +# Overview +By leveraging Expensify's [Employee Updater API](https://integrations.expensify.com/Integration-Server/doc/employeeUpdater/), you can set up a fully customizable integration between Workday and Expensify. This integration can: + +- **Provision new employees in Expensify:** Employees are automatically invited to the correct Expensify workspace on their start date based on data in Workday. +- **Update employees and approval workflows:** Any changes to employee email and manager are automatically updated in Expensify. +- **Deprovision employees:** Employees can optionally be removed from their primary Expensify workspace on their termination date. +Please note that while your Account Manager can help advise on setting up the Workday integration, the Expensify API is a self-serve tool. + +# How to set up an Advanced Custom Report in Workday +The first step to integrating Workday with Expensify is to create an advanced custom report in Workday. This report can: +- Map Workday column data to an Expensify Workspace for import. +- Import employee names, email addresses and manager emails into the Expensify Workspace. +- Set the employee’s **Submits To** column in the Expensify Members table. +- Set the employee's Expensify **Custom Field 1 & 2**, typically used for Employee ID, Cost Center and/or Legal Entity. +- Add employees to different Expensify Domain Groups. +- Auto-assign Expensify Cards. + +In order to complete the steps below, you'll need a Workday System Administrator to create an **Integration System User** and **Integration System Security Group**. + +## Create an Integration System User +1. Search "create user" and click **Create Integration System User**. +2. Add a password, leave **Require New Password at Next Sign In** unchecked, set **Session Timeout Minutes** to 0, and check **Do Not Allow UI Sessions**. +3. Click **OK**. + +## Create a Security Group +1. Search "create security group", then click **Create Security Group**. +2. Create a **Constrained** security group and specify the **Organizations** you'd like to sync data from. +3. Add the **Integration System User** you created to your **Security Group**. +4. Search and select "security group membership and access". +5. Search for the security group you just created. +6. Click the ellipsis, then **Security Group > Maintain Domain Permissions for Security Group**. +7. Under **Integration Permissions**, add "External Account Provisioning" to **Domain Security Workspaces permitting Put access** and "Worker Data: Workers" to **Domain Security Workspaces permitting Get access**. +8. Click **OK** and **Done**. +9. Search **Activate Pending Security Workspace Changes** and complete the task for activating the security workspace change, adding a comment if required and checking the **Confirmed** check-box. + +## Create the Advanced Custom Report +Before completing the steps below, you will need Workday Report Writer access to create an Advanced Custom Report in Workday and enable it as a RAAS (Report as a Service). + +1. Search “Create Custom Report” and click **Create Custom Report**. +2. Enter the report details: + - Give the report a **Name**. + - Set the **Report Type** to **Advanced**. + - Check **Enable As Web Service**. + - Uncheck **Optimized for Performance**. + - For **Data Source**, search and select **All Active and Terminated Employees**. + - Click **OK**. +3. Select the **Column Data** you’d like to sync with Expensify. Typical fields synced with Expensify from Workday are as follows (Required fields are marked with \*): + - First Name + - Last Name + - Primary Work Email\* + - Employee ID\* + - Expensify Workspace ID\* + - Worker’s Manager [Primary Work Email]\* + - Domain Group ID (If you want to specify a Domain Group in Expensify, please work with your Account Manager to get your Domain Group IDs) + - Cost Center + - Entity ID (sometimes called Legal Entity) + - Active/Inactive + - Termination Date + - Note: _if there is field data you want to import that is not listed above, or you have any special requests, let your Expensify Account Manager know and we will work with you to accommodate the request._ +4. Rename the columns so they match Expensify's API key names (The full list of names are found here): + - employeeID + - firstName + - lastName + - employeeEmail + - managerEmail + - workspaceID + - domainGroupID + - approvesTo +Switch to the **Share** tab, and share the report with your **Integration System User** and **Security Group**. + +## Enable your report as a Report as a Service (RAAS) + +1. In your Workday tenant, search “view custom report” and select it. On the **View Custom Report** screen, click **My Reports**. +2. Select the report you have created and click **OK**. +3. Click **Actions > Web Service > View URLs** and click **OK**. +4. Scroll to the **JSON** section, right-click **JSON**, then select **Copy URL**. + +## Activate the Workday Integration + +If you would like to enable and run the API job that performs a recurring sync, you can do so by following Expensify’s API reference documentation [here](https://integrations.expensify.com/Integration-Server/doc/employeeUpdater/#api-principles). + +If you would like Expensify to perform the sync on your behalf, please follow the steps below. + +1. To generate your **Expensify API Credentials**, log into Expensify with an account that has both Workspace Admin and Domain Admin access, then head to https://www.expensify.com/tools/integrations/ where you will find your partnerUserID and partnerUserSecret. +2. Go to **Settings > Workspaces > Group > _[Workspace Name]_ > Connections > HR Integrations** and click **Connect to Workday**. +3. In the form, supply the following details: + - partnerUserID + - partnerUserSecret + - Workday ISU Username (e.g. ISU_Expensify) + - Workday password + - Workday REST Web Services URL + - Preferred go live date (e.g. YYYY/MM/DD, or leave blank) + - Expensify Card Auto-Assignment? (Y/N) + - Note: If using Expensify Cards, card auto-assignment occurs when a Smart Limit for a Group is enabled. + - Deprovision Users? (Y/N) + +After you submit the form, the request is sent to your Expensify Account Manager. Your Account Manager will create a recurring sync that will retrieve the data columns from your Workday Web Services URL and apply the rule mappings you have specified above. + +If we have any questions, we will reach out to you via direct message. diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md b/docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md index 3ee1c8656b4b..b863b8e5a61c 100644 --- a/docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md +++ b/docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md @@ -1,5 +1,24 @@ --- -title: Coming Soon -description: Coming Soon +title: Lyft & Expensify +description: Setting up and using Expensify's Lyft integration --- -## Resource Coming Soon! + + +# Overview +You can link Expensify directly to your Lyft account. This means that your receipts for work-related Lyft rides will populate automatically in Expensify. + +# How to connect a Lyft Business profile for individual use +If you use Lyft for work, you can connect your business profile to Expensify to have your Business-related trips populate directly in your Expensify account. +1. Open the Lyft mobile app and tap your profile photo in the upper left. +2. Go to Settings. +3. Select Business profile, and create one if you don’t already have one. +4. Tap Expense management and choose Expensify. You'll be asked to enter your email, make sure it matches the email you use to access Expensify. +You're all set! Switch into business profile mode each time you take a ride for work, and your receipts will automatically populate in Expensify. + +# How to set up Lyft for Business +If you have a Lyft for Business account for your company, setting up the Expensify and Lyft integration for your whole team is very straightforward: +1. Open your Lyft for Business portal from a web browser. +2. Navigate to People > Business Profile (+) and input each team member's work email. +3. Once invited, each employee will receive an email prompting Lyft Business Profile setup. +4. After they set up their profiles, employees can then switch into business profile mode each time they take a ride for work, and their receipts will automatically populate in Expensify. +Now, when any employee completes a ride on a Lyft Business Profile, it will show up in the "Rides" section of your Lyft for Business portal. diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md b/docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md index 3ee1c8656b4b..237047fa270e 100644 --- a/docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md +++ b/docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md @@ -1,5 +1,47 @@ --- -title: Coming Soon -description: Coming Soon +title: Navan Integration +description: Connecting Navan and Expensify --- -## Resource Coming Soon! +# Overview +Booking travel through Navan? Link your Expensify and Navan accounts to automatically send flight receipts to Expensify for easy reporting. + +# How to connect Navan to Expensify +To set up the integration, run through the following steps: +1. Sign in at navan.com +2. Click on your profile in the upper right corner +3. Select “Integrations” from the drop-down menu +4. In the Expensify box, click the “Enable” link +5. Uncheck the box that says “Disallow company card expensing” +6. Check the box that says “Automatically push expenses when booking a flight” +7. If you’re using a central booking account, and you’d like all expenses to be sent to one Expensify account, click “Edit” next to “Expensify” in Navan and enter the email address you’d like to send receipts to + +Once you complete these steps, any flights you book through Navan will automatically be added to an expense report in Expensify. + +If you booked your Navan flight using your Expensify Card, the Navan expense will automatically merge with the card expense. Learn more about the Expensify Card [here](https://use.expensify.com/company-credit-card). + + +# FAQ + +## How do I expense a prepaid hotel booking in Expensify using the Navan integration? +Bookings that weren’t made in Navan directly (such as a prepaid hotel booking) won’t auto-import into Expensify. To import these trips into Expensify, follow these steps: + +1. Click the “Trips” tab in Navan. +2. Select the trip or hotel that you'd like to expense. +3. Click the “Expense to Expensify” link at the bottom of the page. + +This also works for importing flights that were booked prior to setting up the integration. + +## What kind of data is shared between Expensify and Navan? +Travel booking details from Navan such as flight, hotel, and rental car costs will sync to Expensify to help auto-generate expense reports. + +## What should I do if an expense doesn't sync correctly? +If an expense isn’t syncing correctly, check the integration settings in Navan and confirm that there are no sync errors. If there are no errors but the problems persist, contact the support teams of either platform for assistance. + +## Are manual adjustments to expenses in Expensify reflected in Navan? +Manual adjustments to expenses made in Expensify won't retroactively adjust data in the Navan. Always verify any changes on both platforms to ensure consistency. + +## Is there a cost associated with this integration? +Costs depend on your subscription plans with Expensify and Navan. Expensify doesn’t charge extra for this integration. + +## How do I disconnect the integration? +To disconnect the integration, navigate to the integrations section in Navan, find Expensify, and select the option to disable the integration. diff --git a/docs/assets/images/add-australian-deposit-only-account-modal.png b/docs/assets/images/add-australian-deposit-only-account-modal.png new file mode 100644 index 000000000000..1196a57c8f8f Binary files /dev/null and b/docs/assets/images/add-australian-deposit-only-account-modal.png differ diff --git a/docs/assets/images/add-australian-deposit-only-account.png b/docs/assets/images/add-australian-deposit-only-account.png new file mode 100644 index 000000000000..4cea4fb11757 Binary files /dev/null and b/docs/assets/images/add-australian-deposit-only-account.png differ diff --git a/docs/assets/images/add-vba-australian-account-modal.png b/docs/assets/images/add-vba-australian-account-modal.png new file mode 100644 index 000000000000..ee624eca3814 Binary files /dev/null and b/docs/assets/images/add-vba-australian-account-modal.png differ diff --git a/docs/assets/images/add-vba-australian-account.png b/docs/assets/images/add-vba-australian-account.png new file mode 100644 index 000000000000..f064225e176a Binary files /dev/null and b/docs/assets/images/add-vba-australian-account.png differ diff --git a/docs/assets/images/delete-australian-bank-account.png b/docs/assets/images/delete-australian-bank-account.png new file mode 100644 index 000000000000..2148973e5a6c Binary files /dev/null and b/docs/assets/images/delete-australian-bank-account.png differ diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index d7c58d4c9048..5e079008b394 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.76 + 1.3.77 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.3.76.0 + 1.3.77.3 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index c25fd5343c7a..17c6c668e648 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.3.76 + 1.3.77 CFBundleSignature ???? CFBundleVersion - 1.3.76.0 + 1.3.77.3 diff --git a/package-lock.json b/package-lock.json index 85a4e754ad48..f8d39ff23582 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.76-0", + "version": "1.3.77-3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.76-0", + "version": "1.3.77-3", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -50,7 +50,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#1609f1848cc0c2528064519c3ea48b4953a708ee", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#ab4895807dd9a26f64bfaee80db15ee2c48a5124", "fbjs": "^3.0.2", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", @@ -66,6 +66,7 @@ "prop-types": "^15.7.2", "pusher-js": "8.3.0", "react": "18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-collapse": "^5.1.0", "react-content-loader": "^6.1.0", "react-dom": "18.1.0", @@ -78,6 +79,7 @@ "react-native-dev-menu": "^4.1.1", "react-native-device-info": "^10.3.0", "react-native-document-picker": "^8.0.0", + "react-native-draggable-flatlist": "^4.0.1", "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "2.12.0", @@ -90,7 +92,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.97", + "react-native-onyx": "1.0.98", "react-native-pager-view": "^6.2.0", "react-native-pdf": "^6.7.1", "react-native-performance": "^5.1.0", @@ -161,6 +163,7 @@ "@types/mock-fs": "^4.13.1", "@types/pusher-js": "^5.1.0", "@types/react": "^18.2.12", + "@types/react-beautiful-dnd": "^13.1.4", "@types/react-collapse": "^5.0.1", "@types/react-dom": "^18.2.4", "@types/react-pdf": "^5.7.2", @@ -18517,6 +18520,15 @@ "@types/unist": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "dev": true, @@ -18788,6 +18800,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-beautiful-dnd": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.4.tgz", + "integrity": "sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-collapse": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/react-collapse/-/react-collapse-5.0.1.tgz", @@ -18822,6 +18843,17 @@ "pdfjs-dist": "^2.10.377" } }, + "node_modules/@types/react-redux": { + "version": "7.1.26", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.26.tgz", + "integrity": "sha512-UKPo7Cm7rswYU6PH6CmTNCRv5NYF3HrgKuHEYTK8g/3czYLrUux50gQ2pkxc9c7ZpQZi+PNhgmI8oNIRoiVIxg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/react-test-renderer": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz", @@ -24506,6 +24538,14 @@ "version": "3.3.0", "license": "MIT" }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/css-color-keywords": { "version": "1.0.0", "license": "ISC", @@ -28107,8 +28147,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#1609f1848cc0c2528064519c3ea48b4953a708ee", - "integrity": "sha512-sUd/ky6xCB/mShVaD2nVkedGL2xy+h6Jf5MfX9GOiYX8wB2D8uZSpqswz515uwcp8RDWrA5wxM2cR6pBXNfgxw==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#ab4895807dd9a26f64bfaee80db15ee2c48a5124", + "integrity": "sha512-F5WjTSz/UwnYE99NcdAFiDLmNFCq32S8sZXF9Ekf4hXzGMnPFsAsxA2UBYwE8SiFqgF86hceYt9qrjv1yCxLPw==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -40631,6 +40671,11 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "node_modules/ramda": { "version": "0.29.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", @@ -40733,6 +40778,24 @@ "node": ">=0.10.0" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-collapse": { "version": "5.1.1", "license": "MIT", @@ -41044,6 +41107,19 @@ } } }, + "node_modules/react-native-draggable-flatlist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz", + "integrity": "sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q==", + "dependencies": { + "@babel/preset-typescript": "^7.17.12" + }, + "peerDependencies": { + "react-native": ">=0.64.0", + "react-native-gesture-handler": ">=2.0.0", + "react-native-reanimated": ">=2.8.0" + } + }, "node_modules/react-native-fast-image": { "version": "8.6.3", "license": "(MIT AND Apache-2.0)", @@ -41210,9 +41286,9 @@ } }, "node_modules/react-native-onyx": { - "version": "1.0.97", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.97.tgz", - "integrity": "sha512-6w4pp9Ktm4lQ6jIS+ZASQ5tYwRU1lt751yxfddvmN646XZefj4iDvC7uQaUnAgg1xL52dEV5RZWaI3sQ3e9AGQ==", + "version": "1.0.98", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.98.tgz", + "integrity": "sha512-2wJNmZVBJs2Y0p1G/es4tQZnplJR8rOyVbHv9KZaq/SXluLUnIovttf1MMhVXidDLT+gcE+u20Mck/Gpb8bY0w==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -41756,6 +41832,35 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, "node_modules/react-refresh": { "version": "0.11.0", "dev": true, @@ -46824,6 +46929,14 @@ "react": ">=16.8" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/use-resize-observer": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", @@ -61516,6 +61629,15 @@ "@types/unist": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "6.1.0", "dev": true @@ -61754,6 +61876,15 @@ "csstype": "^3.0.2" } }, + "@types/react-beautiful-dnd": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.4.tgz", + "integrity": "sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-collapse": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/react-collapse/-/react-collapse-5.0.1.tgz", @@ -61786,6 +61917,17 @@ "pdfjs-dist": "^2.10.377" } }, + "@types/react-redux": { + "version": "7.1.26", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.26.tgz", + "integrity": "sha512-UKPo7Cm7rswYU6PH6CmTNCRv5NYF3HrgKuHEYTK8g/3czYLrUux50gQ2pkxc9c7ZpQZi+PNhgmI8oNIRoiVIxg==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/react-test-renderer": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz", @@ -65786,6 +65928,14 @@ "crypto-js": { "version": "3.3.0" }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, "css-color-keywords": { "version": "1.0.0" }, @@ -68273,9 +68423,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#1609f1848cc0c2528064519c3ea48b4953a708ee", - "integrity": "sha512-sUd/ky6xCB/mShVaD2nVkedGL2xy+h6Jf5MfX9GOiYX8wB2D8uZSpqswz515uwcp8RDWrA5wxM2cR6pBXNfgxw==", - "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#1609f1848cc0c2528064519c3ea48b4953a708ee", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#ab4895807dd9a26f64bfaee80db15ee2c48a5124", + "integrity": "sha512-F5WjTSz/UwnYE99NcdAFiDLmNFCq32S8sZXF9Ekf4hXzGMnPFsAsxA2UBYwE8SiFqgF86hceYt9qrjv1yCxLPw==", + "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#ab4895807dd9a26f64bfaee80db15ee2c48a5124", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", @@ -76812,6 +76962,11 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "ramda": { "version": "0.29.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", @@ -76879,6 +77034,20 @@ "loose-envify": "^1.1.0" } }, + "react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "requires": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + } + }, "react-collapse": { "version": "5.1.1", "requires": {} @@ -77196,6 +77365,14 @@ "invariant": "^2.2.4" } }, + "react-native-draggable-flatlist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz", + "integrity": "sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q==", + "requires": { + "@babel/preset-typescript": "^7.17.12" + } + }, "react-native-fast-image": { "version": "8.6.3", "requires": {} @@ -77293,9 +77470,9 @@ } }, "react-native-onyx": { - "version": "1.0.97", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.97.tgz", - "integrity": "sha512-6w4pp9Ktm4lQ6jIS+ZASQ5tYwRU1lt751yxfddvmN646XZefj4iDvC7uQaUnAgg1xL52dEV5RZWaI3sQ3e9AGQ==", + "version": "1.0.98", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.98.tgz", + "integrity": "sha512-2wJNmZVBJs2Y0p1G/es4tQZnplJR8rOyVbHv9KZaq/SXluLUnIovttf1MMhVXidDLT+gcE+u20Mck/Gpb8bY0w==", "requires": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -77533,6 +77710,26 @@ "react-script-hook": "^1.6.0" } }, + "react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, "react-refresh": { "version": "0.11.0", "dev": true @@ -81021,6 +81218,12 @@ "integrity": "sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg==", "requires": {} }, + "use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "requires": {} + }, "use-resize-observer": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", diff --git a/package.json b/package.json index d56f5f3af9b9..ac834af01b29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.76-0", + "version": "1.3.77-3", "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.", @@ -93,7 +93,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#1609f1848cc0c2528064519c3ea48b4953a708ee", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#ab4895807dd9a26f64bfaee80db15ee2c48a5124", "fbjs": "^3.0.2", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", @@ -109,6 +109,7 @@ "prop-types": "^15.7.2", "pusher-js": "8.3.0", "react": "18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-collapse": "^5.1.0", "react-content-loader": "^6.1.0", "react-dom": "18.1.0", @@ -121,6 +122,7 @@ "react-native-dev-menu": "^4.1.1", "react-native-device-info": "^10.3.0", "react-native-document-picker": "^8.0.0", + "react-native-draggable-flatlist": "^4.0.1", "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "2.12.0", @@ -133,7 +135,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.97", + "react-native-onyx": "1.0.98", "react-native-pager-view": "^6.2.0", "react-native-pdf": "^6.7.1", "react-native-performance": "^5.1.0", @@ -204,6 +206,7 @@ "@types/mock-fs": "^4.13.1", "@types/pusher-js": "^5.1.0", "@types/react": "^18.2.12", + "@types/react-beautiful-dnd": "^13.1.4", "@types/react-collapse": "^5.0.1", "@types/react-dom": "^18.2.4", "@types/react-pdf": "^5.7.2", diff --git a/patches/react-beautiful-dnd+13.1.1.patch b/patches/react-beautiful-dnd+13.1.1.patch new file mode 100644 index 000000000000..577d54d42004 --- /dev/null +++ b/patches/react-beautiful-dnd+13.1.1.patch @@ -0,0 +1,259 @@ +diff --git a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.cjs.js b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.cjs.js +index 12884e9..3a16e5e 100644 +--- a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.cjs.js ++++ b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.cjs.js +@@ -6227,8 +6227,10 @@ function useTouchSensor(api) { + x: clientX, + y: clientY + }; ++ var handle = api.findClosestDragHandle(event); ++ !handle ? process.env.NODE_ENV !== "production" ? invariant(false, 'Touch sensor unable to find drag handle') : invariant(false) : void 0; + unbindEventsRef.current(); +- startPendingDrag(actions, point); ++ startPendingDrag(actions, point, handle); + } + }; + }, [api]); +@@ -6268,7 +6270,7 @@ function useTouchSensor(api) { + phase.actions.abort(); + } + }, [stop]); +- var bindCapturingEvents = useMemoOne.useCallback(function bindCapturingEvents() { ++ var bindCapturingEvents = useMemoOne.useCallback(function bindCapturingEvents(target) { + var options = { + capture: true, + passive: false +@@ -6278,7 +6280,7 @@ function useTouchSensor(api) { + completed: stop, + getPhase: getPhase + }; +- var unbindTarget = bindEvents(window, getHandleBindings(args), options); ++ var unbindTarget = bindEvents(target, getHandleBindings(args), options); + var unbindWindow = bindEvents(window, getWindowBindings(args), options); + + unbindEventsRef.current = function unbindAll() { +@@ -6296,7 +6298,7 @@ function useTouchSensor(api) { + hasMoved: false + }); + }, [getPhase, setPhase]); +- var startPendingDrag = useMemoOne.useCallback(function startPendingDrag(actions, point) { ++ var startPendingDrag = useMemoOne.useCallback(function startPendingDrag(actions, point, target) { + !(getPhase().type === 'IDLE') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected to move from IDLE to PENDING drag') : invariant(false) : void 0; + var longPressTimerId = setTimeout(startDragging, timeForLongPress); + setPhase({ +@@ -6305,7 +6307,7 @@ function useTouchSensor(api) { + actions: actions, + longPressTimerId: longPressTimerId + }); +- bindCapturingEvents(); ++ bindCapturingEvents(target); + }, [bindCapturingEvents, getPhase, setPhase, startDragging]); + useIsomorphicLayoutEffect(function mount() { + listenForCapture(); +@@ -6454,7 +6456,6 @@ function findClosestDragHandleFromEvent(contextId, event) { + + return handle; + } +- + function tryGetClosestDraggableIdFromEvent(contextId, event) { + var handle = findClosestDragHandleFromEvent(contextId, event); + +@@ -6786,6 +6787,9 @@ function useSensorMarshal(_ref4) { + sourceEvent: options && options.sourceEvent ? options.sourceEvent : null + }); + }, [contextId, lockAPI, registry, store]); ++ var findClosestDragHandle = useMemoOne.useCallback(function (event) { ++ return findClosestDragHandleFromEvent(contextId, event); ++ }, [contextId]); + var findClosestDraggableId = useMemoOne.useCallback(function (event) { + return tryGetClosestDraggableIdFromEvent(contextId, event); + }, [contextId]); +@@ -6810,11 +6814,12 @@ function useSensorMarshal(_ref4) { + canGetLock: canGetLock, + tryGetLock: tryGetLock, + findClosestDraggableId: findClosestDraggableId, ++ findClosestDragHandle: findClosestDragHandle, + findOptionsForDraggable: findOptionsForDraggable, + tryReleaseLock: tryReleaseLock, + isLockClaimed: isLockClaimed + }; +- }, [canGetLock, tryGetLock, findClosestDraggableId, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); ++ }, [canGetLock, tryGetLock, findClosestDraggableId, findClosestDragHandle, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); + useValidateSensorHooks(useSensors); + + for (var i = 0; i < useSensors.length; i++) { +diff --git a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.esm.js b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.esm.js +index ecced69..3233bf8 100644 +--- a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.esm.js ++++ b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.esm.js +@@ -6220,8 +6220,10 @@ function useTouchSensor(api) { + x: clientX, + y: clientY + }; ++ var handle = api.findClosestDragHandle(event); ++ !handle ? process.env.NODE_ENV !== "production" ? invariant(false, 'Touch sensor unable to find drag handle') : invariant(false) : void 0; + unbindEventsRef.current(); +- startPendingDrag(actions, point); ++ startPendingDrag(actions, point, handle); + } + }; + }, [api]); +@@ -6261,7 +6263,7 @@ function useTouchSensor(api) { + phase.actions.abort(); + } + }, [stop]); +- var bindCapturingEvents = useCallback(function bindCapturingEvents() { ++ var bindCapturingEvents = useCallback(function bindCapturingEvents(target) { + var options = { + capture: true, + passive: false +@@ -6271,7 +6273,7 @@ function useTouchSensor(api) { + completed: stop, + getPhase: getPhase + }; +- var unbindTarget = bindEvents(window, getHandleBindings(args), options); ++ var unbindTarget = bindEvents(target, getHandleBindings(args), options); + var unbindWindow = bindEvents(window, getWindowBindings(args), options); + + unbindEventsRef.current = function unbindAll() { +@@ -6289,7 +6291,7 @@ function useTouchSensor(api) { + hasMoved: false + }); + }, [getPhase, setPhase]); +- var startPendingDrag = useCallback(function startPendingDrag(actions, point) { ++ var startPendingDrag = useCallback(function startPendingDrag(actions, point, target) { + !(getPhase().type === 'IDLE') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected to move from IDLE to PENDING drag') : invariant(false) : void 0; + var longPressTimerId = setTimeout(startDragging, timeForLongPress); + setPhase({ +@@ -6298,7 +6300,7 @@ function useTouchSensor(api) { + actions: actions, + longPressTimerId: longPressTimerId + }); +- bindCapturingEvents(); ++ bindCapturingEvents(target); + }, [bindCapturingEvents, getPhase, setPhase, startDragging]); + useIsomorphicLayoutEffect(function mount() { + listenForCapture(); +@@ -6447,7 +6449,6 @@ function findClosestDragHandleFromEvent(contextId, event) { + + return handle; + } +- + function tryGetClosestDraggableIdFromEvent(contextId, event) { + var handle = findClosestDragHandleFromEvent(contextId, event); + +@@ -6779,6 +6780,9 @@ function useSensorMarshal(_ref4) { + sourceEvent: options && options.sourceEvent ? options.sourceEvent : null + }); + }, [contextId, lockAPI, registry, store]); ++ var findClosestDragHandle = useCallback(function (event) { ++ return findClosestDragHandleFromEvent(contextId, event); ++ }, [contextId]); + var findClosestDraggableId = useCallback(function (event) { + return tryGetClosestDraggableIdFromEvent(contextId, event); + }, [contextId]); +@@ -6803,11 +6807,12 @@ function useSensorMarshal(_ref4) { + canGetLock: canGetLock, + tryGetLock: tryGetLock, + findClosestDraggableId: findClosestDraggableId, ++ findClosestDragHandle: findClosestDragHandle, + findOptionsForDraggable: findOptionsForDraggable, + tryReleaseLock: tryReleaseLock, + isLockClaimed: isLockClaimed + }; +- }, [canGetLock, tryGetLock, findClosestDraggableId, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); ++ }, [canGetLock, tryGetLock, findClosestDraggableId, findClosestDragHandle, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); + useValidateSensorHooks(useSensors); + + for (var i = 0; i < useSensors.length; i++) { +diff --git a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.js b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.js +index 84b63e9..c62471d 100644 +--- a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.js ++++ b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.js +@@ -9224,8 +9224,10 @@ + x: clientX, + y: clientY + }; ++ var handle = api.findClosestDragHandle(event); ++ !handle ? invariant(false, 'Touch sensor unable to find drag handle') : void 0; + unbindEventsRef.current(); +- startPendingDrag(actions, point); ++ startPendingDrag(actions, point, handle); + } + }; + }, [api]); +@@ -9265,7 +9267,7 @@ + phase.actions.abort(); + } + }, [stop]); +- var bindCapturingEvents = useCallback(function bindCapturingEvents() { ++ var bindCapturingEvents = useCallback(function bindCapturingEvents(target) { + var options = { + capture: true, + passive: false +@@ -9275,7 +9277,7 @@ + completed: stop, + getPhase: getPhase + }; +- var unbindTarget = bindEvents(window, getHandleBindings(args), options); ++ var unbindTarget = bindEvents(target, getHandleBindings(args), options); + var unbindWindow = bindEvents(window, getWindowBindings(args), options); + + unbindEventsRef.current = function unbindAll() { +@@ -9293,7 +9295,7 @@ + hasMoved: false + }); + }, [getPhase, setPhase]); +- var startPendingDrag = useCallback(function startPendingDrag(actions, point) { ++ var startPendingDrag = useCallback(function startPendingDrag(actions, point, target) { + !(getPhase().type === 'IDLE') ? invariant(false, 'Expected to move from IDLE to PENDING drag') : void 0; + var longPressTimerId = setTimeout(startDragging, timeForLongPress); + setPhase({ +@@ -9302,7 +9304,7 @@ + actions: actions, + longPressTimerId: longPressTimerId + }); +- bindCapturingEvents(); ++ bindCapturingEvents(target); + }, [bindCapturingEvents, getPhase, setPhase, startDragging]); + useIsomorphicLayoutEffect$1(function mount() { + listenForCapture(); +@@ -9451,7 +9453,6 @@ + + return handle; + } +- + function tryGetClosestDraggableIdFromEvent(contextId, event) { + var handle = findClosestDragHandleFromEvent(contextId, event); + +@@ -9783,6 +9784,9 @@ + sourceEvent: options && options.sourceEvent ? options.sourceEvent : null + }); + }, [contextId, lockAPI, registry, store]); ++ var findClosestDragHandle = useCallback(function (event) { ++ return findClosestDragHandleFromEvent(contextId, event); ++ }, [contextId]); + var findClosestDraggableId = useCallback(function (event) { + return tryGetClosestDraggableIdFromEvent(contextId, event); + }, [contextId]); +@@ -9807,11 +9811,12 @@ + canGetLock: canGetLock, + tryGetLock: tryGetLock, + findClosestDraggableId: findClosestDraggableId, ++ findClosestDragHandle: findClosestDragHandle, + findOptionsForDraggable: findOptionsForDraggable, + tryReleaseLock: tryReleaseLock, + isLockClaimed: isLockClaimed + }; +- }, [canGetLock, tryGetLock, findClosestDraggableId, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); ++ }, [canGetLock, tryGetLock, findClosestDraggableId, findClosestDragHandle, findOptionsForDraggable, tryReleaseLock, isLockClaimed]); + useValidateSensorHooks(useSensors); + + for (var i = 0; i < useSensors.length; i++) { +diff --git a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.min.js b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.min.js +index a18e84d..9ec9c6d 100644 +--- a/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.min.js ++++ b/node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.min.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react-dom"],t):t((e=e||self).ReactBeautifulDnd={},e.React,e.ReactDOM)}(this,(function(e,t,r){"use strict";var n="default"in t?t.default:t,i="default"in r?r.default:r;function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(){}function l(){return(l=Object.assign||function(e){for(var t=1;t");return t.callbacks},t.setCallbacks=function(e){t.callbacks=e},t}o(t,e);var r=t.prototype;return r.componentDidMount=function(){this.unbind=u(window,[{eventName:"error",fn:this.onWindowError}])},r.componentDidCatch=function(e){if(!(e instanceof c))throw e;this.setState({})},r.componentWillUnmount=function(){this.unbind()},r.render=function(){return this.props.children(this.setCallbacks)},t}(n.Component),p=function(e){return e+1},f=function(e,t){var r=e.droppableId===t.droppableId,n=p(e.index),i=p(t.index);return r?"\n You have moved the item from position "+n+"\n to position "+i+"\n ":"\n You have moved the item from position "+n+"\n in list "+e.droppableId+"\n to list "+t.droppableId+"\n in position "+i+"\n "},g=function(e,t,r){return t.droppableId===r.droppableId?"\n The item "+e+"\n has been combined with "+r.draggableId:"\n The item "+e+"\n in list "+t.droppableId+"\n has been combined with "+r.draggableId+"\n in list "+r.droppableId+"\n "},v=function(e){return"\n The item has returned to its starting position\n of "+p(e.index)+"\n"},m="\n Press space bar to start a drag.\n When dragging you can use the arrow keys to move the item around and escape to cancel.\n Some screen readers may require you to be in focus mode or to use your pass through key\n",b=function(e){return"\n You have lifted an item in position "+p(e.source.index)+"\n"},h=function(e){var t=e.destination;if(t)return f(e.source,t);var r=e.combine;return r?g(e.draggableId,e.source,r):"You are over an area that cannot be dropped on"},y=function(e){if("CANCEL"===e.reason)return"\n Movement cancelled.\n "+v(e.source)+"\n ";var t=e.destination,r=e.combine;return t?"\n You have dropped the item.\n "+f(e.source,t)+"\n ":r?"\n You have dropped the item.\n "+g(e.draggableId,e.source,r)+"\n ":"\n The item has been dropped while not over a drop area.\n "+v(e.source)+"\n "};var x=function(e){var t,r=e.Symbol;return"function"==typeof r?r.observable?t=r.observable:(t=r("observable"),r.observable=t):t="@@observable",t}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof module?module:Function("return this")()),I=function(){return Math.random().toString(36).substring(7).split("").join(".")},D={INIT:"@@redux/INIT"+I(),REPLACE:"@@redux/REPLACE"+I(),PROBE_UNKNOWN_ACTION:function(){return"@@redux/PROBE_UNKNOWN_ACTION"+I()}};function w(e){if("object"!=typeof e||null===e)return!1;for(var t=e;null!==Object.getPrototypeOf(t);)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function E(e,t,r){var n;if("function"==typeof t&&"function"==typeof r||"function"==typeof r&&"function"==typeof arguments[3])throw new Error("It looks like you are passing several store enhancers to createStore(). This is not supported. Instead, compose them together to a single function.");if("function"==typeof t&&void 0===r&&(r=t,t=void 0),void 0!==r){if("function"!=typeof r)throw new Error("Expected the enhancer to be a function.");return r(E)(e,t)}if("function"!=typeof e)throw new Error("Expected the reducer to be a function.");var i=e,o=t,a=[],l=a,u=!1;function c(){l===a&&(l=a.slice())}function s(){if(u)throw new Error("You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.");return o}function d(e){if("function"!=typeof e)throw new Error("Expected the listener to be a function.");if(u)throw new Error("You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://redux.js.org/api-reference/store#subscribelistener for more details.");var t=!0;return c(),l.push(e),function(){if(t){if(u)throw new Error("You may not unsubscribe from a store listener while the reducer is executing. See https://redux.js.org/api-reference/store#subscribelistener for more details.");t=!1,c();var r=l.indexOf(e);l.splice(r,1),a=null}}}function p(e){if(!w(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(u)throw new Error("Reducers may not dispatch actions.");try{u=!0,o=i(o,e)}finally{u=!1}for(var t=a=l,r=0;r=0||(i[r]=e[r]);return i}var K={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},Q={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},Z={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},ee={};function te(e){return L.isMemo(e)?Z:ee[e.$$typeof]||K}ee[L.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},ee[L.Memo]=Z;var re=Object.defineProperty,ne=Object.getOwnPropertyNames,ie=Object.getOwnPropertySymbols,oe=Object.getOwnPropertyDescriptor,ae=Object.getPrototypeOf,le=Object.prototype;var ue=function e(t,r,n){if("string"!=typeof r){if(le){var i=ae(r);i&&i!==le&&e(t,i,n)}var o=ne(r);ie&&(o=o.concat(ie(r)));for(var a=te(t),l=te(r),u=0;u=0;n--){var i=t[n](e);if(i)return i}return function(t,n){throw new Error("Invalid value of type "+typeof e+" for "+r+" argument when connecting component "+n.wrappedComponentName+".")}}function Ne(e,t){return e===t}function Be(e){var t=void 0===e?{}:e,r=t.connectHOC,n=void 0===r?be:r,i=t.mapStateToPropsFactories,o=void 0===i?Ee:i,a=t.mapDispatchToPropsFactories,l=void 0===a?we:a,u=t.mergePropsFactories,c=void 0===u?Se:u,s=t.selectorFactory,d=void 0===s?Ae:s;return function(e,t,r,i){void 0===i&&(i={});var a=i,u=a.pure,s=void 0===u||u,p=a.areStatesEqual,f=void 0===p?Ne:p,g=a.areOwnPropsEqual,v=void 0===g?ye:g,m=a.areStatePropsEqual,b=void 0===m?ye:m,h=a.areMergedPropsEqual,y=void 0===h?ye:h,x=X(a,["pure","areStatesEqual","areOwnPropsEqual","areStatePropsEqual","areMergedPropsEqual"]),I=Re(e,o,"mapStateToProps"),D=Re(t,l,"mapDispatchToProps"),w=Re(r,c,"mergeProps");return n(d,J({methodName:"connect",getDisplayName:function(e){return"Connect("+e+")"},shouldHandleStateChanges:Boolean(e),initMapStateToProps:I,initMapDispatchToProps:D,initMergeProps:w,pure:s,areStatesEqual:f,areOwnPropsEqual:v,areStatePropsEqual:b,areMergedPropsEqual:y},x))}}var Te,Me=Be();function Le(e,r){var n=t.useState((function(){return{inputs:r,result:e()}}))[0],i=t.useRef(n),o=Boolean(r&&i.current.inputs&&function(e,t){if(e.length!==t.length)return!1;for(var r=0;re.bottom,l=n.lefte.right;return!(!a||!l)||(a&&o||l&&i)}},Ot=function(e){var t=St(e.top,e.bottom),r=St(e.left,e.right);return function(e){return t(e.top)&&t(e.bottom)&&r(e.left)&&r(e.right)}},At={direction:"vertical",line:"y",crossAxisLine:"x",start:"top",end:"bottom",size:"height",crossAxisStart:"left",crossAxisEnd:"right",crossAxisSize:"width"},Rt={direction:"horizontal",line:"x",crossAxisLine:"y",start:"left",end:"right",size:"width",crossAxisStart:"top",crossAxisEnd:"bottom",crossAxisSize:"height"},Nt=function(e){var t=e.target,r=e.destination,n=e.viewport,i=e.withDroppableDisplacement,o=e.isVisibleThroughFrameFn,a=i?function(e,t){var r=t.frame?t.frame.scroll.diff.displacement:Fe;return nt(e,r)}(t,r):t;return function(e,t,r){return!!t.subject.active&&r(t.subject.active)(e)}(a,r,o)&&function(e,t,r){return r(t)(e)}(a,n,o)},Bt=function(e){return Nt(l({},e,{isVisibleThroughFrameFn:Pt}))},Tt=function(e){return Nt(l({},e,{isVisibleThroughFrameFn:Ot}))};function Mt(e){var t=e.afterDragging,r=e.destination,n=e.displacedBy,i=e.viewport,o=e.forceShouldAnimate,a=e.last;return t.reduce((function(e,t){var l=function(e,t){var r=e.page.marginBox,n={top:t.point.y,right:0,bottom:0,left:t.point.x};return $e(Ye(r,n))}(t,n),u=t.descriptor.id;if(e.all.push(u),!Bt({target:l,destination:r,viewport:i,withDroppableDisplacement:!0}))return e.invisible[t.descriptor.id]=!0,e;var c={draggableId:u,shouldAnimate:function(e,t,r){if("boolean"==typeof r)return r;if(!t)return!0;var n=t.invisible,i=t.visible;if(n[e])return!1;var o=i[e];return!o||o.shouldAnimate}(u,a,o)};return e.visible[u]=c,e}),{all:[],visible:{},invisible:{}})}function Lt(e){var t=e.insideDestination,r=e.inHomeList,n=e.displacedBy,i=e.destination,o=function(e,t){if(!e.length)return 0;var r=e[e.length-1].descriptor.index;return t.inHomeList?r:r+1}(t,{inHomeList:r});return{displaced:Et,displacedBy:n,at:{type:"REORDER",destination:{droppableId:i.descriptor.id,index:o}}}}function Gt(e){var t=e.draggable,r=e.insideDestination,n=e.destination,i=e.viewport,o=e.displacedBy,a=e.last,l=e.index,u=e.forceShouldAnimate,c=Dt(t,n);if(null==l)return Lt({insideDestination:r,inHomeList:c,displacedBy:o,destination:n});var s=pt(r,(function(e){return e.descriptor.index===l}));if(!s)return Lt({insideDestination:r,inHomeList:c,displacedBy:o,destination:n});var d=It(t,r),p=r.indexOf(s);return{displaced:Mt({afterDragging:d.slice(p),destination:n,displacedBy:o,last:a,viewport:i.frame,forceShouldAnimate:u}),displacedBy:o,at:{type:"REORDER",destination:{droppableId:n.descriptor.id,index:l}}}}function _t(e,t){return Boolean(t.effected[e])}var Ft=function(e){var t=e.isMovingForward,r=e.isInHomeList,n=e.draggable,i=e.draggables,o=e.destination,a=e.insideDestination,l=e.previousImpact,u=e.viewport,c=e.afterCritical,d=l.at;if(d||s(!1),"REORDER"===d.type){var p=function(e){var t=e.isMovingForward,r=e.isInHomeList,n=e.insideDestination,i=e.location;if(!n.length)return null;var o=i.index,a=t?o+1:o-1,l=n[0].descriptor.index,u=n[n.length-1].descriptor.index;return a(r?u:u+1)?null:a}({isMovingForward:t,isInHomeList:r,location:d.destination,insideDestination:a});return null==p?null:Gt({draggable:n,insideDestination:a,destination:o,viewport:u,last:l.displaced,displacedBy:l.displacedBy,index:p})}var f=function(e){var t=e.isMovingForward,r=e.destination,n=e.draggables,i=e.combine,o=e.afterCritical;if(!r.isCombineEnabled)return null;var a=i.draggableId,l=n[a].descriptor.index;return _t(a,o)?t?l:l-1:t?l+1:l}({isMovingForward:t,destination:o,displaced:l.displaced,draggables:i,combine:d.combine,afterCritical:c});return null==f?null:Gt({draggable:n,insideDestination:a,destination:o,viewport:u,last:l.displaced,displacedBy:l.displacedBy,index:f})},jt=function(e){var t=e.afterCritical,r=e.impact,n=e.draggables,i=xt(r);i||s(!1);var o=i.draggableId,a=n[o].page.borderBox.center,l=function(e){var t=e.displaced,r=e.afterCritical,n=e.combineWith,i=e.displacedBy,o=Boolean(t.visible[n]||t.invisible[n]);return _t(n,r)?o?Fe:Ue(i.point):o?i.point:Fe}({displaced:r.displaced,afterCritical:t,combineWith:o,displacedBy:r.displacedBy});return je(a,l)},kt=function(e,t){return t.margin[e.start]+t.borderBox[e.size]/2},Wt=function(e,t,r){return t[e.crossAxisStart]+r.margin[e.crossAxisStart]+r.borderBox[e.crossAxisSize]/2},Ut=function(e){var t=e.axis,r=e.moveRelativeTo,n=e.isMoving;return He(t.line,r.marginBox[t.end]+kt(t,n),Wt(t,r.marginBox,n))},Ht=function(e){var t=e.axis,r=e.moveRelativeTo,n=e.isMoving;return He(t.line,r.marginBox[t.start]-function(e,t){return t.margin[e.end]+t.borderBox[e.size]/2}(t,n),Wt(t,r.marginBox,n))},qt=function(e){var t=e.impact,r=e.draggable,n=e.draggables,i=e.droppable,o=e.afterCritical,a=ht(i.descriptor.id,n),l=r.page,u=i.axis;if(!a.length)return function(e){var t=e.axis,r=e.moveInto,n=e.isMoving;return He(t.line,r.contentBox[t.start]+kt(t,n),Wt(t,r.contentBox,n))}({axis:u,moveInto:i.page,isMoving:l});var c=t.displaced,s=t.displacedBy,d=c.all[0];if(d){var p=n[d];if(_t(d,o))return Ht({axis:u,moveRelativeTo:p.page,isMoving:l});var f=Ze(p.page,s.point);return Ht({axis:u,moveRelativeTo:f,isMoving:l})}var g=a[a.length-1];if(g.descriptor.id===r.descriptor.id)return l.borderBox.center;if(_t(g.descriptor.id,o)){var v=Ze(g.page,Ue(o.displacedBy.point));return Ut({axis:u,moveRelativeTo:v,isMoving:l})}return Ut({axis:u,moveRelativeTo:g.page,isMoving:l})},Vt=function(e,t){var r=e.frame;return r?je(t,r.scroll.diff.displacement):t},zt=function(e){var t=function(e){var t=e.impact,r=e.draggable,n=e.droppable,i=e.draggables,o=e.afterCritical,a=r.page.borderBox.center,l=t.at;return n&&l?"REORDER"===l.type?qt({impact:t,draggable:r,draggables:i,droppable:n,afterCritical:o}):jt({impact:t,draggables:i,afterCritical:o}):a}(e),r=e.droppable;return r?Vt(r,t):t},$t=function(e,t){var r=ke(t,e.scroll.initial),n=Ue(r);return{frame:$e({top:t.y,bottom:t.y+e.frame.height,left:t.x,right:t.x+e.frame.width}),scroll:{initial:e.scroll.initial,max:e.scroll.max,current:t,diff:{value:r,displacement:n}}}};function Yt(e,t){return e.map((function(e){return t[e]}))}var Jt=function(e){var t=e.pageBorderBoxCenter,r=e.draggable,n=function(e,t){return je(e.scroll.diff.displacement,t)}(e.viewport,t),i=ke(n,r.page.borderBox.center);return je(r.client.borderBox.center,i)},Xt=function(e){var t=e.draggable,r=e.destination,n=e.newPageBorderBoxCenter,i=e.viewport,o=e.withDroppableDisplacement,a=e.onlyOnMainAxis,u=void 0!==a&&a,c=ke(n,t.page.borderBox.center),s={target:nt(t.page.borderBox,c),destination:r,withDroppableDisplacement:o,viewport:i};return u?function(e){return Nt(l({},e,{isVisibleThroughFrameFn:(t=e.destination.axis,function(e){var r=St(e.top,e.bottom),n=St(e.left,e.right);return function(e){return t===At?r(e.top)&&r(e.bottom):n(e.left)&&n(e.right)}})}));var t}(s):Tt(s)},Kt=function(e){var t=e.isMovingForward,r=e.draggable,n=e.destination,i=e.draggables,o=e.previousImpact,a=e.viewport,u=e.previousPageBorderBoxCenter,c=e.previousClientSelection,d=e.afterCritical;if(!n.isEnabled)return null;var p=ht(n.descriptor.id,i),f=Dt(r,n),g=function(e){var t=e.isMovingForward,r=e.draggable,n=e.destination,i=e.insideDestination,o=e.previousImpact;if(!n.isCombineEnabled)return null;if(!yt(o))return null;function a(e){var t={type:"COMBINE",combine:{draggableId:e,droppableId:n.descriptor.id}};return l({},o,{at:t})}var u=o.displaced.all,c=u.length?u[0]:null;if(t)return c?a(c):null;var d=It(r,i);if(!c)return d.length?a(d[d.length-1].descriptor.id):null;var p=dt(d,(function(e){return e.descriptor.id===c}));-1===p&&s(!1);var f=p-1;return f<0?null:a(d[f].descriptor.id)}({isMovingForward:t,draggable:r,destination:n,insideDestination:p,previousImpact:o})||Ft({isMovingForward:t,isInHomeList:f,draggable:r,draggables:i,destination:n,insideDestination:p,previousImpact:o,viewport:a,afterCritical:d});if(!g)return null;var v=zt({impact:g,draggable:r,droppable:n,draggables:i,afterCritical:d});if(Xt({draggable:r,destination:n,newPageBorderBoxCenter:v,viewport:a.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0}))return{clientSelection:Jt({pageBorderBoxCenter:v,draggable:r,viewport:a}),impact:g,scrollJumpRequest:null};var m=ke(v,u);return{clientSelection:c,impact:function(e){var t=e.impact,r=e.viewport,n=e.destination,i=e.draggables,o=e.maxScrollChange,a=$t(r,je(r.scroll.current,o)),u=n.frame?lt(n,je(n.frame.scroll.current,o)):n,c=t.displaced,s=Mt({afterDragging:Yt(c.all,i),destination:n,displacedBy:t.displacedBy,viewport:a.frame,last:c,forceShouldAnimate:!1}),d=Mt({afterDragging:Yt(c.all,i),destination:u,displacedBy:t.displacedBy,viewport:r.frame,last:c,forceShouldAnimate:!1}),p={},f={},g=[c,s,d];return c.all.forEach((function(e){var t=function(e,t){for(var r=0;r1?s.sort((function(e,t){return Qt(e)[l.start]-Qt(t)[l.start]}))[0]:c.sort((function(e,t){var n=Ve(r,it(Qt(e))),i=Ve(r,it(Qt(t)));return n!==i?n-i:Qt(e)[l.start]-Qt(t)[l.start]}))[0]}({isMovingForward:t,pageBorderBoxCenter:r,source:i,droppables:a,viewport:l});if(!c)return null;var s=ht(c.descriptor.id,o),d=function(e){var t=e.previousPageBorderBoxCenter,r=e.moveRelativeTo,n=e.insideDestination,i=e.draggable,o=e.draggables,a=e.destination,l=e.viewport,u=e.afterCritical;if(!r){if(n.length)return null;var c={displaced:Et,displacedBy:wt,at:{type:"REORDER",destination:{droppableId:a.descriptor.id,index:0}}},s=zt({impact:c,draggable:i,droppable:a,draggables:o,afterCritical:u}),d=Dt(i,a)?a:nr(a,i,o);return Xt({draggable:i,destination:d,newPageBorderBoxCenter:s,viewport:l.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0})?c:null}var p,f=Boolean(t[a.axis.line]<=r.page.borderBox.center[a.axis.line]),g=(p=r.descriptor.index,r.descriptor.id===i.descriptor.id?p:f?p:p+1),v=tr(a.axis,i.displaceBy);return Gt({draggable:i,insideDestination:n,destination:a,viewport:l,displacedBy:v,last:Et,index:g})}({previousPageBorderBoxCenter:r,destination:c,draggable:n,draggables:o,moveRelativeTo:function(e){var t=e.pageBorderBoxCenter,r=e.viewport,n=e.destination,i=e.insideDestination,o=e.afterCritical;return i.filter((function(e){return Tt({target:er(e,o),destination:n,viewport:r.frame,withDroppableDisplacement:!0})})).sort((function(e,r){var i=qe(t,Vt(n,Zt(e,o))),a=qe(t,Vt(n,Zt(r,o)));return in.left&&r.topn.top))return!1;if(ur(i)(t.center))return!0;var o=e.axis,a=i.center[o.crossAxisLine],l=t[o.crossAxisStart],u=t[o.crossAxisEnd],c=St(i[o.crossAxisStart],i[o.crossAxisEnd]),s=c(l),d=c(u);return!s&&!d||(s?la)}));return i.length?1===i.length?i[0].descriptor.id:function(e){var t=e.pageBorderBox,r=e.draggable,n=e.candidates,i=r.page.borderBox.center,o=n.map((function(e){var r=e.axis,n=He(e.axis.line,t.center[r.line],e.page.borderBox.center[r.crossAxisLine]);return{id:e.descriptor.id,distance:qe(i,n)}})).sort((function(e,t){return t.distance-e.distance}));return o[0]?o[0].id:null}({pageBorderBox:t,draggable:r,candidates:i}):null}var sr=function(e,t){return $e(nt(e,t))};function dr(e){var t=e.displaced,r=e.id;return Boolean(t.visible[r]||t.invisible[r])}var pr=function(e){var t=e.pageOffset,r=e.draggable,n=e.draggables,i=e.droppables,o=e.previousImpact,a=e.viewport,l=e.afterCritical,u=sr(r.page.borderBox,t),c=cr({pageBorderBox:u,draggable:r,droppables:i});if(!c)return Ct;var s=i[c],d=ht(s.descriptor.id,n),p=function(e,t){var r=e.frame;return r?sr(t,r.scroll.diff.value):t}(s,u);return function(e){var t=e.draggable,r=e.pageBorderBoxWithDroppableScroll,n=e.previousImpact,i=e.destination,o=e.insideDestination,a=e.afterCritical;if(!i.isCombineEnabled)return null;var l=i.axis,u=tr(i.axis,t.displaceBy),c=u.value,s=r[l.start],d=r[l.end],p=pt(It(t,o),(function(e){var t=e.descriptor.id,r=e.page.borderBox,i=r[l.size]/4,o=_t(t,a),u=dr({displaced:n.displaced,id:t});return o?u?d>r[l.start]+i&&dr[l.start]-c+i&&sr[l.start]+c+i&&dr[l.start]+i&&st.descriptor.index?r.descriptor.index-1:r.descriptor.index:null}({draggable:r,closest:pt(It(r,i),(function(e){var t=e.descriptor.id,r=e.page.borderBox.center[u.line],n=_t(t,l),i=dr({displaced:o,id:t});return n?i?p<=r:d=1500)return Yr;var o=$r+Jr*(i/1500);return Number(("CANCEL"===n?.6*o:o).toFixed(2))}({current:i.current.client.offset,destination:h,reason:o});r(function(e){return{type:"DROP_ANIMATE",payload:e}}({newHomeClientOffset:h,dropDuration:x,completed:y}))}else r(Gr({completed:y}))}}else r(function(e){return{type:"DROP_PENDING",payload:e}}({reason:o}))}else e(n)}}},Kr=function(e){var t=[],r=null,n=function(){for(var n=arguments.length,i=new Array(n),o=0;ot.startScrollingFrom)return 0;if(e<=t.maxScrollValueAt)return Sn;if(e===t.startScrollingFrom)return 1;var r=An({startOfRange:t.maxScrollValueAt,endOfRange:t.startScrollingFrom,current:e}),n=Sn*Pn(1-r);return Math.ceil(n)}(t,r);return 0===o?0:i?Math.max(function(e,t){var r=t,n=Nn,i=Date.now()-r;if(i>=Nn)return e;if(it.height,o=r.width>t.width;return o||i?o&&i?null:{x:o?0:n.x,y:i?0:n.y}:n}({container:r,subject:n,proposedScroll:c});return s?We(s,Fe)?null:s:null},Gn=ze((function(e){return 0===e?0:e>0?1:-1})),_n=(bn=function(e,t){return e<0?e:e>t?e-t:0},function(e){var t=e.current,r=e.max,n=e.change,i=je(t,n),o={x:bn(i.x,r.x),y:bn(i.y,r.y)};return We(o,Fe)?null:o}),Fn=function(e){var t=e.max,r=e.current,n=e.change,i={x:Math.max(r.x,t.x),y:Math.max(r.y,t.y)},o=Gn(n),a=_n({max:i,current:r,change:o});return!a||(0!==o.x&&0===a.x||0!==o.y&&0===a.y)},jn=function(e,t){return Fn({current:e.scroll.current,max:e.scroll.max,change:t})},kn=function(e,t){var r=e.frame;return!!r&&Fn({current:r.scroll.current,max:r.scroll.max,change:t})},Wn=function(e){var t=e.state,r=e.dragStartTime,n=e.shouldUseTimeDampening,i=e.scrollWindow,o=e.scrollDroppable,a=t.current.page.borderBoxCenter,l=t.dimensions.draggables[t.critical.draggable.id].page.marginBox;if(t.isWindowScrollAllowed){var u=function(e){var t=e.viewport,r=e.subject,n=e.center,i=e.dragStartTime,o=e.shouldUseTimeDampening,a=Ln({dragStartTime:i,container:t.frame,subject:r,center:n,shouldUseTimeDampening:o});return a&&jn(t,a)?a:null}({dragStartTime:r,viewport:t.viewport,subject:l,center:a,shouldUseTimeDampening:n});if(u)return void i(u)}var c=wn({center:a,destination:or(t.impact),droppables:t.dimensions.droppables});if(c){var s=function(e){var t=e.droppable,r=e.subject,n=e.center,i=e.dragStartTime,o=e.shouldUseTimeDampening,a=t.frame;if(!a)return null;var l=Ln({dragStartTime:i,container:a.pageMarginBox,subject:r,center:n,shouldUseTimeDampening:o});return l&&kn(t,l)?l:null}({dragStartTime:r,droppable:c,subject:l,center:a,shouldUseTimeDampening:n});s&&o(c.descriptor.id,s)}},Un=function(e){var t=e.move,r=e.scrollDroppable,n=e.scrollWindow,i=function(e,t){if(!kn(e,t))return t;var n=function(e,t){var r=e.frame;return r&&kn(e,t)?_n({current:r.scroll.current,max:r.scroll.max,change:t}):null}(e,t);if(!n)return r(e.descriptor.id,t),null;var i=ke(t,n);return r(e.descriptor.id,i),ke(t,i)},o=function(e,t,r){if(!e)return r;if(!jn(t,r))return r;var i=function(e,t){if(!jn(e,t))return null;var r=e.scroll.max,n=e.scroll.current;return _n({current:n,max:r,change:t})}(t,r);if(!i)return n(r),null;var o=ke(r,i);return n(o),ke(r,o)};return function(e){var r=e.scrollJumpRequest;if(r){var n=or(e.impact);n||s(!1);var a=i(e.dimensions.droppables[n],r);if(a){var l=e.viewport,u=o(e.isWindowScrollAllowed,l,a);u&&function(e,r){var n=je(e.current.client.selection,r);t({client:n})}(e,u)}}}},Hn=function(e){var t=e.scrollDroppable,r=e.scrollWindow,n=e.move,i=function(e){var t=e.scrollWindow,r=e.scrollDroppable,n=Kr(t),i=Kr(r),o=null,a=function(e){o||s(!1);var t=o,r=t.shouldUseTimeDampening,a=t.dragStartTime;Wn({state:e,scrollWindow:n,scrollDroppable:i,dragStartTime:a,shouldUseTimeDampening:r})};return{start:function(e){o&&s(!1);var t=Date.now(),r=!1,n=function(){r=!0};Wn({state:e,dragStartTime:0,shouldUseTimeDampening:!1,scrollWindow:n,scrollDroppable:n}),o={dragStartTime:t,shouldUseTimeDampening:r},r&&a(e)},stop:function(){o&&(n.cancel(),i.cancel(),o=null)},scroll:a}}({scrollWindow:r,scrollDroppable:t}),o=Un({move:n,scrollWindow:r,scrollDroppable:t});return{scroll:function(e){"DRAGGING"===e.phase&&("FLUID"!==e.movementMode?e.scrollJumpRequest&&o(e):i.scroll(e))},start:i.start,stop:i.stop}},qn={base:hn="data-rbd-drag-handle",draggableId:hn+"-draggable-id",contextId:hn+"-context-id"},Vn=function(){var e="data-rbd-draggable";return{base:e,contextId:e+"-context-id",id:e+"-id"}}(),zn=function(){var e="data-rbd-droppable";return{base:e,contextId:e+"-context-id",id:e+"-id"}}(),$n={contextId:"data-rbd-scroll-container-context-id"},Yn=function(e,t){return e.map((function(e){var r=e.styles[t];return r?e.selector+" { "+r+" }":""})).join(" ")},Jn="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?t.useLayoutEffect:t.useEffect,Xn=function(){var e=document.querySelector("head");return e||s(!1),e},Kn=function(e){var t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.type="text/css",t};function Qn(e,r){var n=Ge((function(){return function(e){var t,r,n,i=(t=e,function(e){return"["+e+'="'+t+'"]'}),o=(r="\n cursor: -webkit-grab;\n cursor: grab;\n ",{selector:i(qn.contextId),styles:{always:"\n -webkit-touch-callout: none;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n touch-action: manipulation;\n ",resting:r,dragging:"pointer-events: none;",dropAnimating:r}}),a=[(n="\n transition: "+Hr.outOfTheWay+";\n ",{selector:i(Vn.contextId),styles:{dragging:n,dropAnimating:n,userCancel:n}}),o,{selector:i(zn.contextId),styles:{always:"overflow-anchor: none;"}},{selector:"body",styles:{dragging:"\n cursor: grabbing;\n cursor: -webkit-grabbing;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n overflow-anchor: none;\n "}}];return{always:Yn(a,"always"),resting:Yn(a,"resting"),dragging:Yn(a,"dragging"),dropAnimating:Yn(a,"dropAnimating"),userCancel:Yn(a,"userCancel")}}(e)}),[e]),i=t.useRef(null),o=t.useRef(null),a=_e(ct((function(e){var t=o.current;t||s(!1),t.textContent=e})),[]),l=_e((function(e){var t=i.current;t||s(!1),t.textContent=e}),[]);Jn((function(){(i.current||o.current)&&s(!1);var t=Kn(r),u=Kn(r);return i.current=t,o.current=u,t.setAttribute("data-rbd-always",e),u.setAttribute("data-rbd-dynamic",e),Xn().appendChild(t),Xn().appendChild(u),l(n.always),a(n.resting),function(){var e=function(e){var t=e.current;t||s(!1),Xn().removeChild(t),e.current=null};e(i),e(o)}}),[r,l,a,n.always,n.resting,e]);var u=_e((function(){return a(n.dragging)}),[a,n.dragging]),c=_e((function(e){a("DROP"!==e?n.userCancel:n.dropAnimating)}),[a,n.dropAnimating,n.userCancel]),d=_e((function(){o.current&&a(n.resting)}),[a,n.resting]);return Ge((function(){return{dragging:u,dropping:c,resting:d}}),[u,c,d])}var Zn=function(e){return e&&e.ownerDocument?e.ownerDocument.defaultView:window};function ei(e){return e instanceof Zn(e).HTMLElement}function ti(e){var r=t.useRef({}),n=t.useRef(null),i=t.useRef(null),o=t.useRef(!1),a=_e((function(e,t){var n={id:e,focus:t};return r.current[e]=n,function(){var t=r.current;t[e]!==n&&delete t[e]}}),[]),l=_e((function(t){var r=function(e,t){var r="["+qn.contextId+'="'+e+'"]',n=ft(document.querySelectorAll(r));if(!n.length)return null;var i=pt(n,(function(e){return e.getAttribute(qn.draggableId)===t}));return i&&ei(i)?i:null}(e,t);r&&r!==document.activeElement&&r.focus()}),[e]),u=_e((function(e,t){n.current===e&&(n.current=t)}),[]),c=_e((function(){i.current||o.current&&(i.current=requestAnimationFrame((function(){i.current=null;var e=n.current;e&&l(e)})))}),[l]),s=_e((function(e){n.current=null;var t=document.activeElement;t&&t.getAttribute(qn.draggableId)===e&&(n.current=e)}),[]);return Jn((function(){return o.current=!0,function(){o.current=!1;var e=i.current;e&&cancelAnimationFrame(e)}}),[]),Ge((function(){return{register:a,tryRecordFocus:s,tryRestoreFocusRecorded:c,tryShiftRecord:u}}),[a,s,c,u])}function ri(){var e={draggables:{},droppables:{}},t=[];function r(e){t.length&&t.forEach((function(t){return t(e)}))}function n(t){return e.draggables[t]||null}function i(t){return e.droppables[t]||null}return{draggable:{register:function(t){e.draggables[t.descriptor.id]=t,r({type:"ADDITION",value:t})},update:function(t,r){var n=e.draggables[r.descriptor.id];n&&n.uniqueId===t.uniqueId&&(delete e.draggables[r.descriptor.id],e.draggables[t.descriptor.id]=t)},unregister:function(t){var i=t.descriptor.id,o=n(i);o&&t.uniqueId===o.uniqueId&&(delete e.draggables[i],r({type:"REMOVAL",value:t}))},getById:function(e){var t=n(e);return t||s(!1),t},findById:n,exists:function(e){return Boolean(n(e))},getAllByType:function(t){return st(e.draggables).filter((function(e){return e.descriptor.type===t}))}},droppable:{register:function(t){e.droppables[t.descriptor.id]=t},unregister:function(t){var r=i(t.descriptor.id);r&&t.uniqueId===r.uniqueId&&delete e.droppables[t.descriptor.id]},getById:function(e){var t=i(e);return t||s(!1),t},findById:i,exists:function(e){return Boolean(i(e))},getAllByType:function(t){return st(e.droppables).filter((function(e){return e.descriptor.type===t}))}},subscribe:function(e){return t.push(e),function(){var r=t.indexOf(e);-1!==r&&t.splice(r,1)}},clean:function(){e.draggables={},e.droppables={},t.length=0}}}var ni=n.createContext(null),ii=function(){var e=document.body;return e||s(!1),e},oi={position:"absolute",width:"1px",height:"1px",margin:"-1px",border:"0",padding:"0",overflow:"hidden",clip:"rect(0 0 0 0)","clip-path":"inset(100%)"};var ai=0,li={separator:"::"};function ui(e,t){return void 0===t&&(t=li),Ge((function(){return""+e+t.separator+ai++}),[t.separator,e])}var ci=n.createContext(null);function si(e){var r=t.useRef(e);return t.useEffect((function(){r.current=e})),r}var di,pi=((di={})[13]=!0,di[9]=!0,di),fi=function(e){pi[e.keyCode]&&e.preventDefault()},gi=function(){var e="visibilitychange";return"undefined"==typeof document?e:pt([e,"ms"+e,"webkit"+e,"moz"+e,"o"+e],(function(e){return"on"+e in document}))||e}();var vi,mi={type:"IDLE"};function bi(e){var t=e.cancel,r=e.completed,n=e.getPhase,i=e.setPhase;return[{eventName:"mousemove",fn:function(e){var t=e.button,r=e.clientX,o=e.clientY;if(0===t){var a={x:r,y:o},l=n();if("DRAGGING"===l.type)return e.preventDefault(),void l.actions.move(a);"PENDING"!==l.type&&s(!1);var u=l.point;if(c=u,d=a,Math.abs(d.x-c.x)>=5||Math.abs(d.y-c.y)>=5){var c,d;e.preventDefault();var p=l.actions.fluidLift(a);i({type:"DRAGGING",actions:p})}}}},{eventName:"mouseup",fn:function(e){var i=n();"DRAGGING"===i.type?(e.preventDefault(),i.actions.drop({shouldBlockNextClick:!0}),r()):t()}},{eventName:"mousedown",fn:function(e){"DRAGGING"===n().type&&e.preventDefault(),t()}},{eventName:"keydown",fn:function(e){if("PENDING"!==n().type)return 27===e.keyCode?(e.preventDefault(),void t()):void fi(e);t()}},{eventName:"resize",fn:t},{eventName:"scroll",options:{passive:!0,capture:!1},fn:function(){"PENDING"===n().type&&t()}},{eventName:"webkitmouseforcedown",fn:function(e){var r=n();"IDLE"===r.type&&s(!1),r.actions.shouldRespectForcePress()?t():e.preventDefault()}},{eventName:gi,fn:t}]}function hi(e){var r=t.useRef(mi),n=t.useRef(a),i=Ge((function(){return{eventName:"mousedown",fn:function(t){if(!t.defaultPrevented&&0===t.button&&!(t.ctrlKey||t.metaKey||t.shiftKey||t.altKey)){var r=e.findClosestDraggableId(t);if(r){var i=e.tryGetLock(r,c,{sourceEvent:t});if(i){t.preventDefault();var o={x:t.clientX,y:t.clientY};n.current(),f(i,o)}}}}}}),[e]),o=Ge((function(){return{eventName:"webkitmouseforcewillbegin",fn:function(t){if(!t.defaultPrevented){var r=e.findClosestDraggableId(t);if(r){var n=e.findOptionsForDraggable(r);n&&(n.shouldRespectForcePress||e.canGetLock(r)&&t.preventDefault())}}}}}),[e]),l=_e((function(){n.current=u(window,[o,i],{passive:!1,capture:!0})}),[o,i]),c=_e((function(){"IDLE"!==r.current.type&&(r.current=mi,n.current(),l())}),[l]),d=_e((function(){var e=r.current;c(),"DRAGGING"===e.type&&e.actions.cancel({shouldBlockNextClick:!0}),"PENDING"===e.type&&e.actions.abort()}),[c]),p=_e((function(){var e=bi({cancel:d,completed:c,getPhase:function(){return r.current},setPhase:function(e){r.current=e}});n.current=u(window,e,{capture:!0,passive:!1})}),[d,c]),f=_e((function(e,t){"IDLE"!==r.current.type&&s(!1),r.current={type:"PENDING",point:t,actions:e},p()}),[p]);Jn((function(){return l(),function(){n.current()}}),[l])}function yi(){}var xi=((vi={})[34]=!0,vi[33]=!0,vi[36]=!0,vi[35]=!0,vi);function Ii(e,t){function r(){t(),e.cancel()}return[{eventName:"keydown",fn:function(n){return 27===n.keyCode?(n.preventDefault(),void r()):32===n.keyCode?(n.preventDefault(),t(),void e.drop()):40===n.keyCode?(n.preventDefault(),void e.moveDown()):38===n.keyCode?(n.preventDefault(),void e.moveUp()):39===n.keyCode?(n.preventDefault(),void e.moveRight()):37===n.keyCode?(n.preventDefault(),void e.moveLeft()):void(xi[n.keyCode]?n.preventDefault():fi(n))}},{eventName:"mousedown",fn:r},{eventName:"mouseup",fn:r},{eventName:"click",fn:r},{eventName:"touchstart",fn:r},{eventName:"resize",fn:r},{eventName:"wheel",fn:r,options:{passive:!0}},{eventName:gi,fn:r}]}function Di(e){var r=t.useRef(yi),n=Ge((function(){return{eventName:"keydown",fn:function(t){if(!t.defaultPrevented&&32===t.keyCode){var n=e.findClosestDraggableId(t);if(n){var o=e.tryGetLock(n,c,{sourceEvent:t});if(o){t.preventDefault();var a=!0,l=o.snapLift();r.current(),r.current=u(window,Ii(l,c),{capture:!0,passive:!1})}}}function c(){a||s(!1),a=!1,r.current(),i()}}}}),[e]),i=_e((function(){r.current=u(window,[n],{passive:!1,capture:!0})}),[n]);Jn((function(){return i(),function(){r.current()}}),[i])}var wi={type:"IDLE"};function Ei(e){var r=t.useRef(wi),n=t.useRef(a),i=_e((function(){return r.current}),[]),o=_e((function(e){r.current=e}),[]),l=Ge((function(){return{eventName:"touchstart",fn:function(t){if(!t.defaultPrevented){var r=e.findClosestDraggableId(t);if(r){var i=e.tryGetLock(r,d,{sourceEvent:t});if(i){var o=t.touches[0],a={x:o.clientX,y:o.clientY};n.current(),v(i,a)}}}}}}),[e]),c=_e((function(){n.current=u(window,[l],{capture:!0,passive:!1})}),[l]),d=_e((function(){var e=r.current;"IDLE"!==e.type&&("PENDING"===e.type&&clearTimeout(e.longPressTimerId),o(wi),n.current(),c())}),[c,o]),p=_e((function(){var e=r.current;d(),"DRAGGING"===e.type&&e.actions.cancel({shouldBlockNextClick:!0}),"PENDING"===e.type&&e.actions.abort()}),[d]),f=_e((function(){var e={capture:!0,passive:!1},t={cancel:p,completed:d,getPhase:i},r=u(window,function(e){var t=e.cancel,r=e.completed,n=e.getPhase;return[{eventName:"touchmove",options:{capture:!1},fn:function(e){var r=n();if("DRAGGING"===r.type){r.hasMoved=!0;var i=e.touches[0],o={x:i.clientX,y:i.clientY};e.preventDefault(),r.actions.move(o)}else t()}},{eventName:"touchend",fn:function(e){var i=n();"DRAGGING"===i.type?(e.preventDefault(),i.actions.drop({shouldBlockNextClick:!0}),r()):t()}},{eventName:"touchcancel",fn:function(e){"DRAGGING"===n().type?(e.preventDefault(),t()):t()}},{eventName:"touchforcechange",fn:function(e){var r=n();"IDLE"===r.type&&s(!1);var i=e.touches[0];if(i&&i.force>=.15){var o=r.actions.shouldRespectForcePress();if("PENDING"!==r.type)return o?r.hasMoved?void e.preventDefault():void t():void e.preventDefault();o&&t()}}},{eventName:gi,fn:t}]}(t),e),o=u(window,function(e){var t=e.cancel,r=e.getPhase;return[{eventName:"orientationchange",fn:t},{eventName:"resize",fn:t},{eventName:"contextmenu",fn:function(e){e.preventDefault()}},{eventName:"keydown",fn:function(e){"DRAGGING"===r().type?(27===e.keyCode&&e.preventDefault(),t()):t()}},{eventName:gi,fn:t}]}(t),e);n.current=function(){r(),o()}}),[p,i,d]),g=_e((function(){var e=i();"PENDING"!==e.type&&s(!1);var t=e.actions.fluidLift(e.point);o({type:"DRAGGING",actions:t,hasMoved:!1})}),[i,o]),v=_e((function(e,t){"IDLE"!==i().type&&s(!1);var r=setTimeout(g,120);o({type:"PENDING",point:t,actions:e,longPressTimerId:r}),f()}),[f,i,o,g]);Jn((function(){return c(),function(){n.current();var e=i();"PENDING"===e.type&&(clearTimeout(e.longPressTimerId),o(wi))}}),[i,c,o]),Jn((function(){return u(window,[{eventName:"touchmove",fn:function(){},options:{capture:!1,passive:!1}}])}),[])}var Ci={input:!0,button:!0,textarea:!0,select:!0,option:!0,optgroup:!0,video:!0,audio:!0};function Si(e,t){var r=t.target;return!!ei(r)&&function e(t,r){if(null==r)return!1;if(Boolean(Ci[r.tagName.toLowerCase()]))return!0;var n=r.getAttribute("contenteditable");return"true"===n||""===n||r!==t&&e(t,r.parentElement)}(e,r)}var Pi=function(e){return $e(e.getBoundingClientRect()).center};var Oi="undefined"==typeof document?"matches":pt(["matches","msMatchesSelector","webkitMatchesSelector"],(function(e){return e in Element.prototype}))||"matches";function Ai(e,t){return e.closest?e.closest(t):function e(t,r){return null==t?null:t[Oi](r)?t:e(t.parentElement,r)}(e,t)}function Ri(e,t){var r,n=t.target;if(!((r=n)instanceof Zn(r).Element))return null;var i=Ai(n,function(e){return"["+qn.contextId+'="'+e+'"]'}(e));return i&&ei(i)?i:null}function Ni(e){e.preventDefault()}function Bi(e){var t=e.expected,r=e.phase,n=e.isLockActive;e.shouldWarn;return!!n()&&t===r}function Ti(e){var t=e.lockAPI,r=e.store,n=e.registry,i=e.draggableId;if(t.isClaimed())return!1;var o=n.draggable.findById(i);return!!o&&(!!o.options.isEnabled&&!!xn(r.getState(),i))}function Mi(e){var t=e.lockAPI,r=e.contextId,n=e.store,i=e.registry,o=e.draggableId,c=e.forceSensorStop,d=e.sourceEvent;if(!Ti({lockAPI:t,store:n,registry:i,draggableId:o}))return null;var p=i.draggable.getById(o),f=function(e,t){var r="["+Vn.contextId+'="'+e+'"]',n=pt(ft(document.querySelectorAll(r)),(function(e){return e.getAttribute(Vn.id)===t}));return n&&ei(n)?n:null}(r,p.descriptor.id);if(!f)return null;if(d&&!p.options.canDragInteractiveElements&&Si(f,d))return null;var g=t.claim(c||a),v="PRE_DRAG";function m(){return p.options.shouldRespectForcePress}function b(){return t.isActive(g)}var h=function(e,t){Bi({expected:e,phase:v,isLockActive:b,shouldWarn:!0})&&n.dispatch(t())}.bind(null,"DRAGGING");function y(e){function r(){t.release(),v="COMPLETED"}function i(t,i){if(void 0===i&&(i={shouldBlockNextClick:!1}),e.cleanup(),i.shouldBlockNextClick){var o=u(window,[{eventName:"click",fn:Ni,options:{once:!0,passive:!1,capture:!0}}]);setTimeout(o)}r(),n.dispatch(_r({reason:t}))}return"PRE_DRAG"!==v&&(r(),"PRE_DRAG"!==v&&s(!1)),n.dispatch(function(e){return{type:"LIFT",payload:e}}(e.liftActionArgs)),v="DRAGGING",l({isActive:function(){return Bi({expected:"DRAGGING",phase:v,isLockActive:b,shouldWarn:!1})},shouldRespectForcePress:m,drop:function(e){return i("DROP",e)},cancel:function(e){return i("CANCEL",e)}},e.actions)}return{isActive:function(){return Bi({expected:"PRE_DRAG",phase:v,isLockActive:b,shouldWarn:!1})},shouldRespectForcePress:m,fluidLift:function(e){var t=Kr((function(e){h((function(){return Nr({client:e})}))}));return l({},y({liftActionArgs:{id:o,clientSelection:e,movementMode:"FLUID"},cleanup:function(){return t.cancel()},actions:{move:t}}),{move:t})},snapLift:function(){var e={moveUp:function(){return h(Br)},moveRight:function(){return h(Mr)},moveDown:function(){return h(Tr)},moveLeft:function(){return h(Lr)}};return y({liftActionArgs:{id:o,clientSelection:Pi(f),movementMode:"SNAP"},cleanup:a,actions:e})},abort:function(){Bi({expected:"PRE_DRAG",phase:v,isLockActive:b,shouldWarn:!0})&&t.release()}}}var Li=[hi,Di,Ei];function Gi(e){var r=e.contextId,n=e.store,i=e.registry,o=e.customSensors,a=e.enableDefaultSensors,l=[].concat(a?Li:[],o||[]),u=t.useState((function(){return function(){var e=null;function t(){e||s(!1),e=null}return{isClaimed:function(){return Boolean(e)},isActive:function(t){return t===e},claim:function(t){e&&s(!1);var r={abandon:t};return e=r,r},release:t,tryAbandon:function(){e&&(e.abandon(),t())}}}()}))[0],c=_e((function(e,t){e.isDragging&&!t.isDragging&&u.tryAbandon()}),[u]);Jn((function(){var e=n.getState();return n.subscribe((function(){var t=n.getState();c(e,t),e=t}))}),[u,n,c]),Jn((function(){return u.tryAbandon}),[u.tryAbandon]);for(var d=_e((function(e){return Ti({lockAPI:u,registry:i,store:n,draggableId:e})}),[u,i,n]),p=_e((function(e,t,o){return Mi({lockAPI:u,registry:i,contextId:r,store:n,draggableId:e,forceSensorStop:t,sourceEvent:o&&o.sourceEvent?o.sourceEvent:null})}),[r,u,i,n]),f=_e((function(e){return function(e,t){var r=Ri(e,t);return r?r.getAttribute(qn.draggableId):null}(r,e)}),[r]),g=_e((function(e){var t=i.draggable.findById(e);return t?t.options:null}),[i.draggable]),v=_e((function(){u.isClaimed()&&(u.tryAbandon(),"IDLE"!==n.getState().phase&&n.dispatch({type:"FLUSH",payload:null}))}),[u,n]),m=_e(u.isClaimed,[u]),b=Ge((function(){return{canGetLock:d,tryGetLock:p,findClosestDraggableId:f,findOptionsForDraggable:g,tryReleaseLock:v,isLockClaimed:m}}),[d,p,f,g,v,m]),h=0;h");return t.callbacks},t.setCallbacks=function(e){t.callbacks=e},t}o(t,e);var r=t.prototype;return r.componentDidMount=function(){this.unbind=u(window,[{eventName:"error",fn:this.onWindowError}])},r.componentDidCatch=function(e){if(!(e instanceof c))throw e;this.setState({})},r.componentWillUnmount=function(){this.unbind()},r.render=function(){return this.props.children(this.setCallbacks)},t}(n.Component),p=function(e){return e+1},f=function(e,t){var r=e.droppableId===t.droppableId,n=p(e.index),i=p(t.index);return r?"\n You have moved the item from position "+n+"\n to position "+i+"\n ":"\n You have moved the item from position "+n+"\n in list "+e.droppableId+"\n to list "+t.droppableId+"\n in position "+i+"\n "},g=function(e,t,r){return t.droppableId===r.droppableId?"\n The item "+e+"\n has been combined with "+r.draggableId:"\n The item "+e+"\n in list "+t.droppableId+"\n has been combined with "+r.draggableId+"\n in list "+r.droppableId+"\n "},v=function(e){return"\n The item has returned to its starting position\n of "+p(e.index)+"\n"},m="\n Press space bar to start a drag.\n When dragging you can use the arrow keys to move the item around and escape to cancel.\n Some screen readers may require you to be in focus mode or to use your pass through key\n",b=function(e){return"\n You have lifted an item in position "+p(e.source.index)+"\n"},h=function(e){var t=e.destination;if(t)return f(e.source,t);var r=e.combine;return r?g(e.draggableId,e.source,r):"You are over an area that cannot be dropped on"},y=function(e){if("CANCEL"===e.reason)return"\n Movement cancelled.\n "+v(e.source)+"\n ";var t=e.destination,r=e.combine;return t?"\n You have dropped the item.\n "+f(e.source,t)+"\n ":r?"\n You have dropped the item.\n "+g(e.draggableId,e.source,r)+"\n ":"\n The item has been dropped while not over a drop area.\n "+v(e.source)+"\n "};var x=function(e){var t,r=e.Symbol;return"function"==typeof r?r.observable?t=r.observable:(t=r("observable"),r.observable=t):t="@@observable",t}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof module?module:Function("return this")()),I=function(){return Math.random().toString(36).substring(7).split("").join(".")},D={INIT:"@@redux/INIT"+I(),REPLACE:"@@redux/REPLACE"+I(),PROBE_UNKNOWN_ACTION:function(){return"@@redux/PROBE_UNKNOWN_ACTION"+I()}};function w(e){if("object"!=typeof e||null===e)return!1;for(var t=e;null!==Object.getPrototypeOf(t);)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function E(e,t,r){var n;if("function"==typeof t&&"function"==typeof r||"function"==typeof r&&"function"==typeof arguments[3])throw new Error("It looks like you are passing several store enhancers to createStore(). This is not supported. Instead, compose them together to a single function.");if("function"==typeof t&&void 0===r&&(r=t,t=void 0),void 0!==r){if("function"!=typeof r)throw new Error("Expected the enhancer to be a function.");return r(E)(e,t)}if("function"!=typeof e)throw new Error("Expected the reducer to be a function.");var i=e,o=t,a=[],l=a,u=!1;function c(){l===a&&(l=a.slice())}function s(){if(u)throw new Error("You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.");return o}function d(e){if("function"!=typeof e)throw new Error("Expected the listener to be a function.");if(u)throw new Error("You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://redux.js.org/api-reference/store#subscribelistener for more details.");var t=!0;return c(),l.push(e),function(){if(t){if(u)throw new Error("You may not unsubscribe from a store listener while the reducer is executing. See https://redux.js.org/api-reference/store#subscribelistener for more details.");t=!1,c();var r=l.indexOf(e);l.splice(r,1),a=null}}}function p(e){if(!w(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(u)throw new Error("Reducers may not dispatch actions.");try{u=!0,o=i(o,e)}finally{u=!1}for(var t=a=l,r=0;r=0||(i[r]=e[r]);return i}var K={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},Q={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},Z={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},ee={};function te(e){return L.isMemo(e)?Z:ee[e.$$typeof]||K}ee[L.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},ee[L.Memo]=Z;var re=Object.defineProperty,ne=Object.getOwnPropertyNames,ie=Object.getOwnPropertySymbols,oe=Object.getOwnPropertyDescriptor,ae=Object.getPrototypeOf,le=Object.prototype;var ue=function e(t,r,n){if("string"!=typeof r){if(le){var i=ae(r);i&&i!==le&&e(t,i,n)}var o=ne(r);ie&&(o=o.concat(ie(r)));for(var a=te(t),l=te(r),u=0;u=0;n--){var i=t[n](e);if(i)return i}return function(t,n){throw new Error("Invalid value of type "+typeof e+" for "+r+" argument when connecting component "+n.wrappedComponentName+".")}}function Ne(e,t){return e===t}function Be(e){var t=void 0===e?{}:e,r=t.connectHOC,n=void 0===r?be:r,i=t.mapStateToPropsFactories,o=void 0===i?Ee:i,a=t.mapDispatchToPropsFactories,l=void 0===a?we:a,u=t.mergePropsFactories,c=void 0===u?Se:u,s=t.selectorFactory,d=void 0===s?Ae:s;return function(e,t,r,i){void 0===i&&(i={});var a=i,u=a.pure,s=void 0===u||u,p=a.areStatesEqual,f=void 0===p?Ne:p,g=a.areOwnPropsEqual,v=void 0===g?ye:g,m=a.areStatePropsEqual,b=void 0===m?ye:m,h=a.areMergedPropsEqual,y=void 0===h?ye:h,x=X(a,["pure","areStatesEqual","areOwnPropsEqual","areStatePropsEqual","areMergedPropsEqual"]),I=Re(e,o,"mapStateToProps"),D=Re(t,l,"mapDispatchToProps"),w=Re(r,c,"mergeProps");return n(d,J({methodName:"connect",getDisplayName:function(e){return"Connect("+e+")"},shouldHandleStateChanges:Boolean(e),initMapStateToProps:I,initMapDispatchToProps:D,initMergeProps:w,pure:s,areStatesEqual:f,areOwnPropsEqual:v,areStatePropsEqual:b,areMergedPropsEqual:y},x))}}var Te,Me=Be();function Le(e,r){var n=t.useState((function(){return{inputs:r,result:e()}}))[0],i=t.useRef(n),o=Boolean(r&&i.current.inputs&&function(e,t){if(e.length!==t.length)return!1;for(var r=0;re.bottom,l=n.lefte.right;return!(!a||!l)||(a&&o||l&&i)}},Ot=function(e){var t=St(e.top,e.bottom),r=St(e.left,e.right);return function(e){return t(e.top)&&t(e.bottom)&&r(e.left)&&r(e.right)}},At={direction:"vertical",line:"y",crossAxisLine:"x",start:"top",end:"bottom",size:"height",crossAxisStart:"left",crossAxisEnd:"right",crossAxisSize:"width"},Rt={direction:"horizontal",line:"x",crossAxisLine:"y",start:"left",end:"right",size:"width",crossAxisStart:"top",crossAxisEnd:"bottom",crossAxisSize:"height"},Nt=function(e){var t=e.target,r=e.destination,n=e.viewport,i=e.withDroppableDisplacement,o=e.isVisibleThroughFrameFn,a=i?function(e,t){var r=t.frame?t.frame.scroll.diff.displacement:Fe;return nt(e,r)}(t,r):t;return function(e,t,r){return!!t.subject.active&&r(t.subject.active)(e)}(a,r,o)&&function(e,t,r){return r(t)(e)}(a,n,o)},Bt=function(e){return Nt(l({},e,{isVisibleThroughFrameFn:Pt}))},Tt=function(e){return Nt(l({},e,{isVisibleThroughFrameFn:Ot}))};function Mt(e){var t=e.afterDragging,r=e.destination,n=e.displacedBy,i=e.viewport,o=e.forceShouldAnimate,a=e.last;return t.reduce((function(e,t){var l=function(e,t){var r=e.page.marginBox,n={top:t.point.y,right:0,bottom:0,left:t.point.x};return $e(Ye(r,n))}(t,n),u=t.descriptor.id;if(e.all.push(u),!Bt({target:l,destination:r,viewport:i,withDroppableDisplacement:!0}))return e.invisible[t.descriptor.id]=!0,e;var c={draggableId:u,shouldAnimate:function(e,t,r){if("boolean"==typeof r)return r;if(!t)return!0;var n=t.invisible,i=t.visible;if(n[e])return!1;var o=i[e];return!o||o.shouldAnimate}(u,a,o)};return e.visible[u]=c,e}),{all:[],visible:{},invisible:{}})}function Lt(e){var t=e.insideDestination,r=e.inHomeList,n=e.displacedBy,i=e.destination,o=function(e,t){if(!e.length)return 0;var r=e[e.length-1].descriptor.index;return t.inHomeList?r:r+1}(t,{inHomeList:r});return{displaced:Et,displacedBy:n,at:{type:"REORDER",destination:{droppableId:i.descriptor.id,index:o}}}}function Gt(e){var t=e.draggable,r=e.insideDestination,n=e.destination,i=e.viewport,o=e.displacedBy,a=e.last,l=e.index,u=e.forceShouldAnimate,c=Dt(t,n);if(null==l)return Lt({insideDestination:r,inHomeList:c,displacedBy:o,destination:n});var s=pt(r,(function(e){return e.descriptor.index===l}));if(!s)return Lt({insideDestination:r,inHomeList:c,displacedBy:o,destination:n});var d=It(t,r),p=r.indexOf(s);return{displaced:Mt({afterDragging:d.slice(p),destination:n,displacedBy:o,last:a,viewport:i.frame,forceShouldAnimate:u}),displacedBy:o,at:{type:"REORDER",destination:{droppableId:n.descriptor.id,index:l}}}}function _t(e,t){return Boolean(t.effected[e])}var Ft=function(e){var t=e.isMovingForward,r=e.isInHomeList,n=e.draggable,i=e.draggables,o=e.destination,a=e.insideDestination,l=e.previousImpact,u=e.viewport,c=e.afterCritical,d=l.at;if(d||s(!1),"REORDER"===d.type){var p=function(e){var t=e.isMovingForward,r=e.isInHomeList,n=e.insideDestination,i=e.location;if(!n.length)return null;var o=i.index,a=t?o+1:o-1,l=n[0].descriptor.index,u=n[n.length-1].descriptor.index;return a(r?u:u+1)?null:a}({isMovingForward:t,isInHomeList:r,location:d.destination,insideDestination:a});return null==p?null:Gt({draggable:n,insideDestination:a,destination:o,viewport:u,last:l.displaced,displacedBy:l.displacedBy,index:p})}var f=function(e){var t=e.isMovingForward,r=e.destination,n=e.draggables,i=e.combine,o=e.afterCritical;if(!r.isCombineEnabled)return null;var a=i.draggableId,l=n[a].descriptor.index;return _t(a,o)?t?l:l-1:t?l+1:l}({isMovingForward:t,destination:o,displaced:l.displaced,draggables:i,combine:d.combine,afterCritical:c});return null==f?null:Gt({draggable:n,insideDestination:a,destination:o,viewport:u,last:l.displaced,displacedBy:l.displacedBy,index:f})},jt=function(e){var t=e.afterCritical,r=e.impact,n=e.draggables,i=xt(r);i||s(!1);var o=i.draggableId,a=n[o].page.borderBox.center,l=function(e){var t=e.displaced,r=e.afterCritical,n=e.combineWith,i=e.displacedBy,o=Boolean(t.visible[n]||t.invisible[n]);return _t(n,r)?o?Fe:Ue(i.point):o?i.point:Fe}({displaced:r.displaced,afterCritical:t,combineWith:o,displacedBy:r.displacedBy});return je(a,l)},kt=function(e,t){return t.margin[e.start]+t.borderBox[e.size]/2},Wt=function(e,t,r){return t[e.crossAxisStart]+r.margin[e.crossAxisStart]+r.borderBox[e.crossAxisSize]/2},Ut=function(e){var t=e.axis,r=e.moveRelativeTo,n=e.isMoving;return He(t.line,r.marginBox[t.end]+kt(t,n),Wt(t,r.marginBox,n))},Ht=function(e){var t=e.axis,r=e.moveRelativeTo,n=e.isMoving;return He(t.line,r.marginBox[t.start]-function(e,t){return t.margin[e.end]+t.borderBox[e.size]/2}(t,n),Wt(t,r.marginBox,n))},qt=function(e){var t=e.impact,r=e.draggable,n=e.draggables,i=e.droppable,o=e.afterCritical,a=ht(i.descriptor.id,n),l=r.page,u=i.axis;if(!a.length)return function(e){var t=e.axis,r=e.moveInto,n=e.isMoving;return He(t.line,r.contentBox[t.start]+kt(t,n),Wt(t,r.contentBox,n))}({axis:u,moveInto:i.page,isMoving:l});var c=t.displaced,s=t.displacedBy,d=c.all[0];if(d){var p=n[d];if(_t(d,o))return Ht({axis:u,moveRelativeTo:p.page,isMoving:l});var f=Ze(p.page,s.point);return Ht({axis:u,moveRelativeTo:f,isMoving:l})}var g=a[a.length-1];if(g.descriptor.id===r.descriptor.id)return l.borderBox.center;if(_t(g.descriptor.id,o)){var v=Ze(g.page,Ue(o.displacedBy.point));return Ut({axis:u,moveRelativeTo:v,isMoving:l})}return Ut({axis:u,moveRelativeTo:g.page,isMoving:l})},Vt=function(e,t){var r=e.frame;return r?je(t,r.scroll.diff.displacement):t},zt=function(e){var t=function(e){var t=e.impact,r=e.draggable,n=e.droppable,i=e.draggables,o=e.afterCritical,a=r.page.borderBox.center,l=t.at;return n&&l?"REORDER"===l.type?qt({impact:t,draggable:r,draggables:i,droppable:n,afterCritical:o}):jt({impact:t,draggables:i,afterCritical:o}):a}(e),r=e.droppable;return r?Vt(r,t):t},$t=function(e,t){var r=ke(t,e.scroll.initial),n=Ue(r);return{frame:$e({top:t.y,bottom:t.y+e.frame.height,left:t.x,right:t.x+e.frame.width}),scroll:{initial:e.scroll.initial,max:e.scroll.max,current:t,diff:{value:r,displacement:n}}}};function Yt(e,t){return e.map((function(e){return t[e]}))}var Jt=function(e){var t=e.pageBorderBoxCenter,r=e.draggable,n=function(e,t){return je(e.scroll.diff.displacement,t)}(e.viewport,t),i=ke(n,r.page.borderBox.center);return je(r.client.borderBox.center,i)},Xt=function(e){var t=e.draggable,r=e.destination,n=e.newPageBorderBoxCenter,i=e.viewport,o=e.withDroppableDisplacement,a=e.onlyOnMainAxis,u=void 0!==a&&a,c=ke(n,t.page.borderBox.center),s={target:nt(t.page.borderBox,c),destination:r,withDroppableDisplacement:o,viewport:i};return u?function(e){return Nt(l({},e,{isVisibleThroughFrameFn:(t=e.destination.axis,function(e){var r=St(e.top,e.bottom),n=St(e.left,e.right);return function(e){return t===At?r(e.top)&&r(e.bottom):n(e.left)&&n(e.right)}})}));var t}(s):Tt(s)},Kt=function(e){var t=e.isMovingForward,r=e.draggable,n=e.destination,i=e.draggables,o=e.previousImpact,a=e.viewport,u=e.previousPageBorderBoxCenter,c=e.previousClientSelection,d=e.afterCritical;if(!n.isEnabled)return null;var p=ht(n.descriptor.id,i),f=Dt(r,n),g=function(e){var t=e.isMovingForward,r=e.draggable,n=e.destination,i=e.insideDestination,o=e.previousImpact;if(!n.isCombineEnabled)return null;if(!yt(o))return null;function a(e){var t={type:"COMBINE",combine:{draggableId:e,droppableId:n.descriptor.id}};return l({},o,{at:t})}var u=o.displaced.all,c=u.length?u[0]:null;if(t)return c?a(c):null;var d=It(r,i);if(!c)return d.length?a(d[d.length-1].descriptor.id):null;var p=dt(d,(function(e){return e.descriptor.id===c}));-1===p&&s(!1);var f=p-1;return f<0?null:a(d[f].descriptor.id)}({isMovingForward:t,draggable:r,destination:n,insideDestination:p,previousImpact:o})||Ft({isMovingForward:t,isInHomeList:f,draggable:r,draggables:i,destination:n,insideDestination:p,previousImpact:o,viewport:a,afterCritical:d});if(!g)return null;var v=zt({impact:g,draggable:r,droppable:n,draggables:i,afterCritical:d});if(Xt({draggable:r,destination:n,newPageBorderBoxCenter:v,viewport:a.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0}))return{clientSelection:Jt({pageBorderBoxCenter:v,draggable:r,viewport:a}),impact:g,scrollJumpRequest:null};var m=ke(v,u);return{clientSelection:c,impact:function(e){var t=e.impact,r=e.viewport,n=e.destination,i=e.draggables,o=e.maxScrollChange,a=$t(r,je(r.scroll.current,o)),u=n.frame?lt(n,je(n.frame.scroll.current,o)):n,c=t.displaced,s=Mt({afterDragging:Yt(c.all,i),destination:n,displacedBy:t.displacedBy,viewport:a.frame,last:c,forceShouldAnimate:!1}),d=Mt({afterDragging:Yt(c.all,i),destination:u,displacedBy:t.displacedBy,viewport:r.frame,last:c,forceShouldAnimate:!1}),p={},f={},g=[c,s,d];return c.all.forEach((function(e){var t=function(e,t){for(var r=0;r1?s.sort((function(e,t){return Qt(e)[l.start]-Qt(t)[l.start]}))[0]:c.sort((function(e,t){var n=Ve(r,it(Qt(e))),i=Ve(r,it(Qt(t)));return n!==i?n-i:Qt(e)[l.start]-Qt(t)[l.start]}))[0]}({isMovingForward:t,pageBorderBoxCenter:r,source:i,droppables:a,viewport:l});if(!c)return null;var s=ht(c.descriptor.id,o),d=function(e){var t=e.previousPageBorderBoxCenter,r=e.moveRelativeTo,n=e.insideDestination,i=e.draggable,o=e.draggables,a=e.destination,l=e.viewport,u=e.afterCritical;if(!r){if(n.length)return null;var c={displaced:Et,displacedBy:wt,at:{type:"REORDER",destination:{droppableId:a.descriptor.id,index:0}}},s=zt({impact:c,draggable:i,droppable:a,draggables:o,afterCritical:u}),d=Dt(i,a)?a:nr(a,i,o);return Xt({draggable:i,destination:d,newPageBorderBoxCenter:s,viewport:l.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0})?c:null}var p,f=Boolean(t[a.axis.line]<=r.page.borderBox.center[a.axis.line]),g=(p=r.descriptor.index,r.descriptor.id===i.descriptor.id?p:f?p:p+1),v=tr(a.axis,i.displaceBy);return Gt({draggable:i,insideDestination:n,destination:a,viewport:l,displacedBy:v,last:Et,index:g})}({previousPageBorderBoxCenter:r,destination:c,draggable:n,draggables:o,moveRelativeTo:function(e){var t=e.pageBorderBoxCenter,r=e.viewport,n=e.destination,i=e.insideDestination,o=e.afterCritical;return i.filter((function(e){return Tt({target:er(e,o),destination:n,viewport:r.frame,withDroppableDisplacement:!0})})).sort((function(e,r){var i=qe(t,Vt(n,Zt(e,o))),a=qe(t,Vt(n,Zt(r,o)));return in.left&&r.topn.top))return!1;if(ur(i)(t.center))return!0;var o=e.axis,a=i.center[o.crossAxisLine],l=t[o.crossAxisStart],u=t[o.crossAxisEnd],c=St(i[o.crossAxisStart],i[o.crossAxisEnd]),s=c(l),d=c(u);return!s&&!d||(s?la)}));return i.length?1===i.length?i[0].descriptor.id:function(e){var t=e.pageBorderBox,r=e.draggable,n=e.candidates,i=r.page.borderBox.center,o=n.map((function(e){var r=e.axis,n=He(e.axis.line,t.center[r.line],e.page.borderBox.center[r.crossAxisLine]);return{id:e.descriptor.id,distance:qe(i,n)}})).sort((function(e,t){return t.distance-e.distance}));return o[0]?o[0].id:null}({pageBorderBox:t,draggable:r,candidates:i}):null}var sr=function(e,t){return $e(nt(e,t))};function dr(e){var t=e.displaced,r=e.id;return Boolean(t.visible[r]||t.invisible[r])}var pr=function(e){var t=e.pageOffset,r=e.draggable,n=e.draggables,i=e.droppables,o=e.previousImpact,a=e.viewport,l=e.afterCritical,u=sr(r.page.borderBox,t),c=cr({pageBorderBox:u,draggable:r,droppables:i});if(!c)return Ct;var s=i[c],d=ht(s.descriptor.id,n),p=function(e,t){var r=e.frame;return r?sr(t,r.scroll.diff.value):t}(s,u);return function(e){var t=e.draggable,r=e.pageBorderBoxWithDroppableScroll,n=e.previousImpact,i=e.destination,o=e.insideDestination,a=e.afterCritical;if(!i.isCombineEnabled)return null;var l=i.axis,u=tr(i.axis,t.displaceBy),c=u.value,s=r[l.start],d=r[l.end],p=pt(It(t,o),(function(e){var t=e.descriptor.id,r=e.page.borderBox,i=r[l.size]/4,o=_t(t,a),u=dr({displaced:n.displaced,id:t});return o?u?d>r[l.start]+i&&dr[l.start]-c+i&&sr[l.start]+c+i&&dr[l.start]+i&&st.descriptor.index?r.descriptor.index-1:r.descriptor.index:null}({draggable:r,closest:pt(It(r,i),(function(e){var t=e.descriptor.id,r=e.page.borderBox.center[u.line],n=_t(t,l),i=dr({displaced:o,id:t});return n?i?p<=r:d=1500)return Yr;var o=$r+Jr*(i/1500);return Number(("CANCEL"===n?.6*o:o).toFixed(2))}({current:i.current.client.offset,destination:h,reason:o});r(function(e){return{type:"DROP_ANIMATE",payload:e}}({newHomeClientOffset:h,dropDuration:x,completed:y}))}else r(Gr({completed:y}))}}else r(function(e){return{type:"DROP_PENDING",payload:e}}({reason:o}))}else e(n)}}},Kr=function(e){var t=[],r=null,n=function(){for(var n=arguments.length,i=new Array(n),o=0;ot.startScrollingFrom)return 0;if(e<=t.maxScrollValueAt)return Sn;if(e===t.startScrollingFrom)return 1;var r=An({startOfRange:t.maxScrollValueAt,endOfRange:t.startScrollingFrom,current:e}),n=Sn*Pn(1-r);return Math.ceil(n)}(t,r);return 0===o?0:i?Math.max(function(e,t){var r=t,n=Nn,i=Date.now()-r;if(i>=Nn)return e;if(it.height,o=r.width>t.width;return o||i?o&&i?null:{x:o?0:n.x,y:i?0:n.y}:n}({container:r,subject:n,proposedScroll:c});return s?We(s,Fe)?null:s:null},Gn=ze((function(e){return 0===e?0:e>0?1:-1})),_n=(bn=function(e,t){return e<0?e:e>t?e-t:0},function(e){var t=e.current,r=e.max,n=e.change,i=je(t,n),o={x:bn(i.x,r.x),y:bn(i.y,r.y)};return We(o,Fe)?null:o}),Fn=function(e){var t=e.max,r=e.current,n=e.change,i={x:Math.max(r.x,t.x),y:Math.max(r.y,t.y)},o=Gn(n),a=_n({max:i,current:r,change:o});return!a||(0!==o.x&&0===a.x||0!==o.y&&0===a.y)},jn=function(e,t){return Fn({current:e.scroll.current,max:e.scroll.max,change:t})},kn=function(e,t){var r=e.frame;return!!r&&Fn({current:r.scroll.current,max:r.scroll.max,change:t})},Wn=function(e){var t=e.state,r=e.dragStartTime,n=e.shouldUseTimeDampening,i=e.scrollWindow,o=e.scrollDroppable,a=t.current.page.borderBoxCenter,l=t.dimensions.draggables[t.critical.draggable.id].page.marginBox;if(t.isWindowScrollAllowed){var u=function(e){var t=e.viewport,r=e.subject,n=e.center,i=e.dragStartTime,o=e.shouldUseTimeDampening,a=Ln({dragStartTime:i,container:t.frame,subject:r,center:n,shouldUseTimeDampening:o});return a&&jn(t,a)?a:null}({dragStartTime:r,viewport:t.viewport,subject:l,center:a,shouldUseTimeDampening:n});if(u)return void i(u)}var c=wn({center:a,destination:or(t.impact),droppables:t.dimensions.droppables});if(c){var s=function(e){var t=e.droppable,r=e.subject,n=e.center,i=e.dragStartTime,o=e.shouldUseTimeDampening,a=t.frame;if(!a)return null;var l=Ln({dragStartTime:i,container:a.pageMarginBox,subject:r,center:n,shouldUseTimeDampening:o});return l&&kn(t,l)?l:null}({dragStartTime:r,droppable:c,subject:l,center:a,shouldUseTimeDampening:n});s&&o(c.descriptor.id,s)}},Un=function(e){var t=e.move,r=e.scrollDroppable,n=e.scrollWindow,i=function(e,t){if(!kn(e,t))return t;var n=function(e,t){var r=e.frame;return r&&kn(e,t)?_n({current:r.scroll.current,max:r.scroll.max,change:t}):null}(e,t);if(!n)return r(e.descriptor.id,t),null;var i=ke(t,n);return r(e.descriptor.id,i),ke(t,i)},o=function(e,t,r){if(!e)return r;if(!jn(t,r))return r;var i=function(e,t){if(!jn(e,t))return null;var r=e.scroll.max,n=e.scroll.current;return _n({current:n,max:r,change:t})}(t,r);if(!i)return n(r),null;var o=ke(r,i);return n(o),ke(r,o)};return function(e){var r=e.scrollJumpRequest;if(r){var n=or(e.impact);n||s(!1);var a=i(e.dimensions.droppables[n],r);if(a){var l=e.viewport,u=o(e.isWindowScrollAllowed,l,a);u&&function(e,r){var n=je(e.current.client.selection,r);t({client:n})}(e,u)}}}},Hn=function(e){var t=e.scrollDroppable,r=e.scrollWindow,n=e.move,i=function(e){var t=e.scrollWindow,r=e.scrollDroppable,n=Kr(t),i=Kr(r),o=null,a=function(e){o||s(!1);var t=o,r=t.shouldUseTimeDampening,a=t.dragStartTime;Wn({state:e,scrollWindow:n,scrollDroppable:i,dragStartTime:a,shouldUseTimeDampening:r})};return{start:function(e){o&&s(!1);var t=Date.now(),r=!1,n=function(){r=!0};Wn({state:e,dragStartTime:0,shouldUseTimeDampening:!1,scrollWindow:n,scrollDroppable:n}),o={dragStartTime:t,shouldUseTimeDampening:r},r&&a(e)},stop:function(){o&&(n.cancel(),i.cancel(),o=null)},scroll:a}}({scrollWindow:r,scrollDroppable:t}),o=Un({move:n,scrollWindow:r,scrollDroppable:t});return{scroll:function(e){"DRAGGING"===e.phase&&("FLUID"!==e.movementMode?e.scrollJumpRequest&&o(e):i.scroll(e))},start:i.start,stop:i.stop}},qn={base:hn="data-rbd-drag-handle",draggableId:hn+"-draggable-id",contextId:hn+"-context-id"},Vn=function(){var e="data-rbd-draggable";return{base:e,contextId:e+"-context-id",id:e+"-id"}}(),zn=function(){var e="data-rbd-droppable";return{base:e,contextId:e+"-context-id",id:e+"-id"}}(),$n={contextId:"data-rbd-scroll-container-context-id"},Yn=function(e,t){return e.map((function(e){var r=e.styles[t];return r?e.selector+" { "+r+" }":""})).join(" ")},Jn="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?t.useLayoutEffect:t.useEffect,Xn=function(){var e=document.querySelector("head");return e||s(!1),e},Kn=function(e){var t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.type="text/css",t};function Qn(e,r){var n=Ge((function(){return function(e){var t,r,n,i=(t=e,function(e){return"["+e+'="'+t+'"]'}),o=(r="\n cursor: -webkit-grab;\n cursor: grab;\n ",{selector:i(qn.contextId),styles:{always:"\n -webkit-touch-callout: none;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n touch-action: manipulation;\n ",resting:r,dragging:"pointer-events: none;",dropAnimating:r}}),a=[(n="\n transition: "+Hr.outOfTheWay+";\n ",{selector:i(Vn.contextId),styles:{dragging:n,dropAnimating:n,userCancel:n}}),o,{selector:i(zn.contextId),styles:{always:"overflow-anchor: none;"}},{selector:"body",styles:{dragging:"\n cursor: grabbing;\n cursor: -webkit-grabbing;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n overflow-anchor: none;\n "}}];return{always:Yn(a,"always"),resting:Yn(a,"resting"),dragging:Yn(a,"dragging"),dropAnimating:Yn(a,"dropAnimating"),userCancel:Yn(a,"userCancel")}}(e)}),[e]),i=t.useRef(null),o=t.useRef(null),a=_e(ct((function(e){var t=o.current;t||s(!1),t.textContent=e})),[]),l=_e((function(e){var t=i.current;t||s(!1),t.textContent=e}),[]);Jn((function(){(i.current||o.current)&&s(!1);var t=Kn(r),u=Kn(r);return i.current=t,o.current=u,t.setAttribute("data-rbd-always",e),u.setAttribute("data-rbd-dynamic",e),Xn().appendChild(t),Xn().appendChild(u),l(n.always),a(n.resting),function(){var e=function(e){var t=e.current;t||s(!1),Xn().removeChild(t),e.current=null};e(i),e(o)}}),[r,l,a,n.always,n.resting,e]);var u=_e((function(){return a(n.dragging)}),[a,n.dragging]),c=_e((function(e){a("DROP"!==e?n.userCancel:n.dropAnimating)}),[a,n.dropAnimating,n.userCancel]),d=_e((function(){o.current&&a(n.resting)}),[a,n.resting]);return Ge((function(){return{dragging:u,dropping:c,resting:d}}),[u,c,d])}var Zn=function(e){return e&&e.ownerDocument?e.ownerDocument.defaultView:window};function ei(e){return e instanceof Zn(e).HTMLElement}function ti(e){var r=t.useRef({}),n=t.useRef(null),i=t.useRef(null),o=t.useRef(!1),a=_e((function(e,t){var n={id:e,focus:t};return r.current[e]=n,function(){var t=r.current;t[e]!==n&&delete t[e]}}),[]),l=_e((function(t){var r=function(e,t){var r="["+qn.contextId+'="'+e+'"]',n=ft(document.querySelectorAll(r));if(!n.length)return null;var i=pt(n,(function(e){return e.getAttribute(qn.draggableId)===t}));return i&&ei(i)?i:null}(e,t);r&&r!==document.activeElement&&r.focus()}),[e]),u=_e((function(e,t){n.current===e&&(n.current=t)}),[]),c=_e((function(){i.current||o.current&&(i.current=requestAnimationFrame((function(){i.current=null;var e=n.current;e&&l(e)})))}),[l]),s=_e((function(e){n.current=null;var t=document.activeElement;t&&t.getAttribute(qn.draggableId)===e&&(n.current=e)}),[]);return Jn((function(){return o.current=!0,function(){o.current=!1;var e=i.current;e&&cancelAnimationFrame(e)}}),[]),Ge((function(){return{register:a,tryRecordFocus:s,tryRestoreFocusRecorded:c,tryShiftRecord:u}}),[a,s,c,u])}function ri(){var e={draggables:{},droppables:{}},t=[];function r(e){t.length&&t.forEach((function(t){return t(e)}))}function n(t){return e.draggables[t]||null}function i(t){return e.droppables[t]||null}return{draggable:{register:function(t){e.draggables[t.descriptor.id]=t,r({type:"ADDITION",value:t})},update:function(t,r){var n=e.draggables[r.descriptor.id];n&&n.uniqueId===t.uniqueId&&(delete e.draggables[r.descriptor.id],e.draggables[t.descriptor.id]=t)},unregister:function(t){var i=t.descriptor.id,o=n(i);o&&t.uniqueId===o.uniqueId&&(delete e.draggables[i],r({type:"REMOVAL",value:t}))},getById:function(e){var t=n(e);return t||s(!1),t},findById:n,exists:function(e){return Boolean(n(e))},getAllByType:function(t){return st(e.draggables).filter((function(e){return e.descriptor.type===t}))}},droppable:{register:function(t){e.droppables[t.descriptor.id]=t},unregister:function(t){var r=i(t.descriptor.id);r&&t.uniqueId===r.uniqueId&&delete e.droppables[t.descriptor.id]},getById:function(e){var t=i(e);return t||s(!1),t},findById:i,exists:function(e){return Boolean(i(e))},getAllByType:function(t){return st(e.droppables).filter((function(e){return e.descriptor.type===t}))}},subscribe:function(e){return t.push(e),function(){var r=t.indexOf(e);-1!==r&&t.splice(r,1)}},clean:function(){e.draggables={},e.droppables={},t.length=0}}}var ni=n.createContext(null),ii=function(){var e=document.body;return e||s(!1),e},oi={position:"absolute",width:"1px",height:"1px",margin:"-1px",border:"0",padding:"0",overflow:"hidden",clip:"rect(0 0 0 0)","clip-path":"inset(100%)"};var ai=0,li={separator:"::"};function ui(e,t){return void 0===t&&(t=li),Ge((function(){return""+e+t.separator+ai++}),[t.separator,e])}var ci=n.createContext(null);function si(e){var r=t.useRef(e);return t.useEffect((function(){r.current=e})),r}var di,pi=((di={})[13]=!0,di[9]=!0,di),fi=function(e){pi[e.keyCode]&&e.preventDefault()},gi=function(){var e="visibilitychange";return"undefined"==typeof document?e:pt([e,"ms"+e,"webkit"+e,"moz"+e,"o"+e],(function(e){return"on"+e in document}))||e}();var vi,mi={type:"IDLE"};function bi(e){var t=e.cancel,r=e.completed,n=e.getPhase,i=e.setPhase;return[{eventName:"mousemove",fn:function(e){var t=e.button,r=e.clientX,o=e.clientY;if(0===t){var a={x:r,y:o},l=n();if("DRAGGING"===l.type)return e.preventDefault(),void l.actions.move(a);"PENDING"!==l.type&&s(!1);var u=l.point;if(c=u,d=a,Math.abs(d.x-c.x)>=5||Math.abs(d.y-c.y)>=5){var c,d;e.preventDefault();var p=l.actions.fluidLift(a);i({type:"DRAGGING",actions:p})}}}},{eventName:"mouseup",fn:function(e){var i=n();"DRAGGING"===i.type?(e.preventDefault(),i.actions.drop({shouldBlockNextClick:!0}),r()):t()}},{eventName:"mousedown",fn:function(e){"DRAGGING"===n().type&&e.preventDefault(),t()}},{eventName:"keydown",fn:function(e){if("PENDING"!==n().type)return 27===e.keyCode?(e.preventDefault(),void t()):void fi(e);t()}},{eventName:"resize",fn:t},{eventName:"scroll",options:{passive:!0,capture:!1},fn:function(){"PENDING"===n().type&&t()}},{eventName:"webkitmouseforcedown",fn:function(e){var r=n();"IDLE"===r.type&&s(!1),r.actions.shouldRespectForcePress()?t():e.preventDefault()}},{eventName:gi,fn:t}]}function hi(e){var r=t.useRef(mi),n=t.useRef(a),i=Ge((function(){return{eventName:"mousedown",fn:function(t){if(!t.defaultPrevented&&0===t.button&&!(t.ctrlKey||t.metaKey||t.shiftKey||t.altKey)){var r=e.findClosestDraggableId(t);if(r){var i=e.tryGetLock(r,c,{sourceEvent:t});if(i){t.preventDefault();var o={x:t.clientX,y:t.clientY};n.current(),f(i,o)}}}}}}),[e]),o=Ge((function(){return{eventName:"webkitmouseforcewillbegin",fn:function(t){if(!t.defaultPrevented){var r=e.findClosestDraggableId(t);if(r){var n=e.findOptionsForDraggable(r);n&&(n.shouldRespectForcePress||e.canGetLock(r)&&t.preventDefault())}}}}}),[e]),l=_e((function(){n.current=u(window,[o,i],{passive:!1,capture:!0})}),[o,i]),c=_e((function(){"IDLE"!==r.current.type&&(r.current=mi,n.current(),l())}),[l]),d=_e((function(){var e=r.current;c(),"DRAGGING"===e.type&&e.actions.cancel({shouldBlockNextClick:!0}),"PENDING"===e.type&&e.actions.abort()}),[c]),p=_e((function(){var e=bi({cancel:d,completed:c,getPhase:function(){return r.current},setPhase:function(e){r.current=e}});n.current=u(window,e,{capture:!0,passive:!1})}),[d,c]),f=_e((function(e,t){"IDLE"!==r.current.type&&s(!1),r.current={type:"PENDING",point:t,actions:e},p()}),[p]);Jn((function(){return l(),function(){n.current()}}),[l])}function yi(){}var xi=((vi={})[34]=!0,vi[33]=!0,vi[36]=!0,vi[35]=!0,vi);function Ii(e,t){function r(){t(),e.cancel()}return[{eventName:"keydown",fn:function(n){return 27===n.keyCode?(n.preventDefault(),void r()):32===n.keyCode?(n.preventDefault(),t(),void e.drop()):40===n.keyCode?(n.preventDefault(),void e.moveDown()):38===n.keyCode?(n.preventDefault(),void e.moveUp()):39===n.keyCode?(n.preventDefault(),void e.moveRight()):37===n.keyCode?(n.preventDefault(),void e.moveLeft()):void(xi[n.keyCode]?n.preventDefault():fi(n))}},{eventName:"mousedown",fn:r},{eventName:"mouseup",fn:r},{eventName:"click",fn:r},{eventName:"touchstart",fn:r},{eventName:"resize",fn:r},{eventName:"wheel",fn:r,options:{passive:!0}},{eventName:gi,fn:r}]}function Di(e){var r=t.useRef(yi),n=Ge((function(){return{eventName:"keydown",fn:function(t){if(!t.defaultPrevented&&32===t.keyCode){var n=e.findClosestDraggableId(t);if(n){var o=e.tryGetLock(n,c,{sourceEvent:t});if(o){t.preventDefault();var a=!0,l=o.snapLift();r.current(),r.current=u(window,Ii(l,c),{capture:!0,passive:!1})}}}function c(){a||s(!1),a=!1,r.current(),i()}}}}),[e]),i=_e((function(){r.current=u(window,[n],{passive:!1,capture:!0})}),[n]);Jn((function(){return i(),function(){r.current()}}),[i])}var wi={type:"IDLE"};function Ei(e){var r=t.useRef(wi),n=t.useRef(a),i=_e((function(){return r.current}),[]),o=_e((function(e){r.current=e}),[]),l=Ge((function(){return{eventName:"touchstart",fn:function(t){if(!t.defaultPrevented){var r=e.findClosestDraggableId(t);if(r){var i=e.tryGetLock(r,d,{sourceEvent:t});if(i){var o=t.touches[0],a={x:o.clientX,y:o.clientY},l=e.findClosestDragHandle(t);l||s(!1),n.current(),v(i,a,l)}}}}}}),[e]),c=_e((function(){n.current=u(window,[l],{capture:!0,passive:!1})}),[l]),d=_e((function(){var e=r.current;"IDLE"!==e.type&&("PENDING"===e.type&&clearTimeout(e.longPressTimerId),o(wi),n.current(),c())}),[c,o]),p=_e((function(){var e=r.current;d(),"DRAGGING"===e.type&&e.actions.cancel({shouldBlockNextClick:!0}),"PENDING"===e.type&&e.actions.abort()}),[d]),f=_e((function(e){var t={capture:!0,passive:!1},r={cancel:p,completed:d,getPhase:i},o=u(e,function(e){var t=e.cancel,r=e.completed,n=e.getPhase;return[{eventName:"touchmove",options:{capture:!1},fn:function(e){var r=n();if("DRAGGING"===r.type){r.hasMoved=!0;var i=e.touches[0],o={x:i.clientX,y:i.clientY};e.preventDefault(),r.actions.move(o)}else t()}},{eventName:"touchend",fn:function(e){var i=n();"DRAGGING"===i.type?(e.preventDefault(),i.actions.drop({shouldBlockNextClick:!0}),r()):t()}},{eventName:"touchcancel",fn:function(e){"DRAGGING"===n().type?(e.preventDefault(),t()):t()}},{eventName:"touchforcechange",fn:function(e){var r=n();"IDLE"===r.type&&s(!1);var i=e.touches[0];if(i&&i.force>=.15){var o=r.actions.shouldRespectForcePress();if("PENDING"!==r.type)return o?r.hasMoved?void e.preventDefault():void t():void e.preventDefault();o&&t()}}},{eventName:gi,fn:t}]}(r),t),a=u(window,function(e){var t=e.cancel,r=e.getPhase;return[{eventName:"orientationchange",fn:t},{eventName:"resize",fn:t},{eventName:"contextmenu",fn:function(e){e.preventDefault()}},{eventName:"keydown",fn:function(e){"DRAGGING"===r().type?(27===e.keyCode&&e.preventDefault(),t()):t()}},{eventName:gi,fn:t}]}(r),t);n.current=function(){o(),a()}}),[p,i,d]),g=_e((function(){var e=i();"PENDING"!==e.type&&s(!1);var t=e.actions.fluidLift(e.point);o({type:"DRAGGING",actions:t,hasMoved:!1})}),[i,o]),v=_e((function(e,t,r){"IDLE"!==i().type&&s(!1);var n=setTimeout(g,120);o({type:"PENDING",point:t,actions:e,longPressTimerId:n}),f(r)}),[f,i,o,g]);Jn((function(){return c(),function(){n.current();var e=i();"PENDING"===e.type&&(clearTimeout(e.longPressTimerId),o(wi))}}),[i,c,o]),Jn((function(){return u(window,[{eventName:"touchmove",fn:function(){},options:{capture:!1,passive:!1}}])}),[])}var Ci={input:!0,button:!0,textarea:!0,select:!0,option:!0,optgroup:!0,video:!0,audio:!0};function Si(e,t){var r=t.target;return!!ei(r)&&function e(t,r){if(null==r)return!1;if(Boolean(Ci[r.tagName.toLowerCase()]))return!0;var n=r.getAttribute("contenteditable");return"true"===n||""===n||r!==t&&e(t,r.parentElement)}(e,r)}var Pi=function(e){return $e(e.getBoundingClientRect()).center};var Oi="undefined"==typeof document?"matches":pt(["matches","msMatchesSelector","webkitMatchesSelector"],(function(e){return e in Element.prototype}))||"matches";function Ai(e,t){return e.closest?e.closest(t):function e(t,r){return null==t?null:t[Oi](r)?t:e(t.parentElement,r)}(e,t)}function Ri(e,t){var r,n=t.target;if(!((r=n)instanceof Zn(r).Element))return null;var i=Ai(n,function(e){return"["+qn.contextId+'="'+e+'"]'}(e));return i&&ei(i)?i:null}function Ni(e){e.preventDefault()}function Bi(e){var t=e.expected,r=e.phase,n=e.isLockActive;e.shouldWarn;return!!n()&&t===r}function Ti(e){var t=e.lockAPI,r=e.store,n=e.registry,i=e.draggableId;if(t.isClaimed())return!1;var o=n.draggable.findById(i);return!!o&&(!!o.options.isEnabled&&!!xn(r.getState(),i))}function Mi(e){var t=e.lockAPI,r=e.contextId,n=e.store,i=e.registry,o=e.draggableId,c=e.forceSensorStop,d=e.sourceEvent;if(!Ti({lockAPI:t,store:n,registry:i,draggableId:o}))return null;var p=i.draggable.getById(o),f=function(e,t){var r="["+Vn.contextId+'="'+e+'"]',n=pt(ft(document.querySelectorAll(r)),(function(e){return e.getAttribute(Vn.id)===t}));return n&&ei(n)?n:null}(r,p.descriptor.id);if(!f)return null;if(d&&!p.options.canDragInteractiveElements&&Si(f,d))return null;var g=t.claim(c||a),v="PRE_DRAG";function m(){return p.options.shouldRespectForcePress}function b(){return t.isActive(g)}var h=function(e,t){Bi({expected:e,phase:v,isLockActive:b,shouldWarn:!0})&&n.dispatch(t())}.bind(null,"DRAGGING");function y(e){function r(){t.release(),v="COMPLETED"}function i(t,i){if(void 0===i&&(i={shouldBlockNextClick:!1}),e.cleanup(),i.shouldBlockNextClick){var o=u(window,[{eventName:"click",fn:Ni,options:{once:!0,passive:!1,capture:!0}}]);setTimeout(o)}r(),n.dispatch(_r({reason:t}))}return"PRE_DRAG"!==v&&(r(),"PRE_DRAG"!==v&&s(!1)),n.dispatch(function(e){return{type:"LIFT",payload:e}}(e.liftActionArgs)),v="DRAGGING",l({isActive:function(){return Bi({expected:"DRAGGING",phase:v,isLockActive:b,shouldWarn:!1})},shouldRespectForcePress:m,drop:function(e){return i("DROP",e)},cancel:function(e){return i("CANCEL",e)}},e.actions)}return{isActive:function(){return Bi({expected:"PRE_DRAG",phase:v,isLockActive:b,shouldWarn:!1})},shouldRespectForcePress:m,fluidLift:function(e){var t=Kr((function(e){h((function(){return Nr({client:e})}))}));return l({},y({liftActionArgs:{id:o,clientSelection:e,movementMode:"FLUID"},cleanup:function(){return t.cancel()},actions:{move:t}}),{move:t})},snapLift:function(){var e={moveUp:function(){return h(Br)},moveRight:function(){return h(Mr)},moveDown:function(){return h(Tr)},moveLeft:function(){return h(Lr)}};return y({liftActionArgs:{id:o,clientSelection:Pi(f),movementMode:"SNAP"},cleanup:a,actions:e})},abort:function(){Bi({expected:"PRE_DRAG",phase:v,isLockActive:b,shouldWarn:!0})&&t.release()}}}var Li=[hi,Di,Ei];function Gi(e){var r=e.contextId,n=e.store,i=e.registry,o=e.customSensors,a=e.enableDefaultSensors,l=[].concat(a?Li:[],o||[]),u=t.useState((function(){return function(){var e=null;function t(){e||s(!1),e=null}return{isClaimed:function(){return Boolean(e)},isActive:function(t){return t===e},claim:function(t){e&&s(!1);var r={abandon:t};return e=r,r},release:t,tryAbandon:function(){e&&(e.abandon(),t())}}}()}))[0],c=_e((function(e,t){e.isDragging&&!t.isDragging&&u.tryAbandon()}),[u]);Jn((function(){var e=n.getState();return n.subscribe((function(){var t=n.getState();c(e,t),e=t}))}),[u,n,c]),Jn((function(){return u.tryAbandon}),[u.tryAbandon]);for(var d=_e((function(e){return Ti({lockAPI:u,registry:i,store:n,draggableId:e})}),[u,i,n]),p=_e((function(e,t,o){return Mi({lockAPI:u,registry:i,contextId:r,store:n,draggableId:e,forceSensorStop:t,sourceEvent:o&&o.sourceEvent?o.sourceEvent:null})}),[r,u,i,n]),f=_e((function(e){return Ri(r,e)}),[r]),g=_e((function(e){return function(e,t){var r=Ri(e,t);return r?r.getAttribute(qn.draggableId):null}(r,e)}),[r]),v=_e((function(e){var t=i.draggable.findById(e);return t?t.options:null}),[i.draggable]),m=_e((function(){u.isClaimed()&&(u.tryAbandon(),"IDLE"!==n.getState().phase&&n.dispatch({type:"FLUSH",payload:null}))}),[u,n]),b=_e(u.isClaimed,[u]),h=Ge((function(){return{canGetLock:d,tryGetLock:p,findClosestDraggableId:g,findClosestDragHandle:f,findOptionsForDraggable:v,tryReleaseLock:m,isLockClaimed:b}}),[d,p,g,f,v,m,b]),y=0;y { +const showActorDetails = (report, shouldEnableDetailPageNavigation = false) => { + // We should navigate to the details page if the report is a IOU/expense report + if (shouldEnableDetailPageNavigation) { + return ReportUtils.navigateToDetailsPage(report); + } + if (ReportUtils.isExpenseReport(report)) { Navigation.navigate(ROUTES.PROFILE.getRoute(report.ownerAccountID)); return; @@ -93,12 +101,12 @@ function AvatarWithDisplayName(props) { const defaultSubscriptSize = isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : props.size; const avatarBorderColor = props.isAnonymous ? themeColors.highlightBG : themeColors.componentBG; - return ( + const headerView = ( {Boolean(props.report && title) && ( showActorDetails(props.report)} + onPress={() => showActorDetails(props.report, props.shouldEnableDetailPageNavigation)} accessibilityLabel={title} accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} > @@ -145,6 +153,21 @@ function AvatarWithDisplayName(props) { )} ); + + if (!props.shouldEnableDetailPageNavigation) { + return headerView; + } + + return ( + ReportUtils.navigateToDetailsPage(props.report)} + style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} + accessibilityLabel={title} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} + > + {headerView} + + ); } AvatarWithDisplayName.propTypes = propTypes; AvatarWithDisplayName.displayName = 'AvatarWithDisplayName'; diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index e7b18bbd8d69..ad7a84cc1828 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -444,9 +444,9 @@ function Composer({ numberOfLines < maxLines ? styles.overflowHidden : {}, StyleSheet.flatten([style, {outline: 'none'}]), - StyleUtils.getComposeTextAreaPadding(numberOfLinesProp, isComposerFullSize), + StyleUtils.getComposeTextAreaPadding(numberOfLines, isComposerFullSize), ], - [style, maxLines, numberOfLinesProp, numberOfLines, isComposerFullSize], + [style, maxLines, numberOfLines, isComposerFullSize], ); return ( diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js deleted file mode 100644 index 62aa1eede16e..000000000000 --- a/src/components/DistanceRequest.js +++ /dev/null @@ -1,337 +0,0 @@ -import React, {useEffect, useMemo, useState, useRef} from 'react'; -import {ScrollView, View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; -import lodashIsNil from 'lodash/isNil'; -import PropTypes from 'prop-types'; -import _ from 'underscore'; -import CONST from '../CONST'; -import ROUTES from '../ROUTES'; -import ONYXKEYS from '../ONYXKEYS'; -import styles from '../styles/styles'; -import variables from '../styles/variables'; -import LinearGradient from './LinearGradient'; -import * as MapboxToken from '../libs/actions/MapboxToken'; -import useNetwork from '../hooks/useNetwork'; -import useLocalize from '../hooks/useLocalize'; -import Navigation from '../libs/Navigation/Navigation'; -import reportPropTypes from '../pages/reportPropTypes'; -import DotIndicatorMessage from './DotIndicatorMessage'; -import * as ErrorUtils from '../libs/ErrorUtils'; -import usePrevious from '../hooks/usePrevious'; -import theme from '../styles/themes/default'; -import * as Transaction from '../libs/actions/Transaction'; -import * as TransactionUtils from '../libs/TransactionUtils'; -import * as IOUUtils from '../libs/IOUUtils'; -import Button from './Button'; -import DistanceMapView from './DistanceMapView'; -import * as Expensicons from './Icon/Expensicons'; -import PendingMapView from './MapView/PendingMapView'; -import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -import * as StyleUtils from '../styles/StyleUtils'; -import transactionPropTypes from './transactionPropTypes'; -import ScreenWrapper from './ScreenWrapper'; -import FullPageNotFoundView from './BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from './HeaderWithBackButton'; - -const MAX_WAYPOINTS = 25; -const MAX_WAYPOINTS_TO_DISPLAY = 4; - -const propTypes = { - /** The transactionID of this request */ - transactionID: PropTypes.string, - - /** The report to which the distance request is associated */ - report: reportPropTypes, - - /** Data about Mapbox token for calling Mapbox API */ - mapboxAccessToken: PropTypes.shape({ - /** Temporary token for Mapbox API */ - token: PropTypes.string, - - /** Time when the token will expire in ISO 8601 */ - expiration: PropTypes.string, - }), - - /** Are we editing an existing distance request, or creating a new one? */ - isEditingRequest: PropTypes.bool, - - /** Called on submit of this page */ - onSubmit: PropTypes.func.isRequired, - - /* Onyx Props */ - transaction: transactionPropTypes, - - /** React Navigation route */ - route: PropTypes.shape({ - /** Params from the route */ - params: PropTypes.shape({ - /** The type of IOU report, i.e. bill, request, send */ - iouType: PropTypes.string, - - /** The report ID of the IOU */ - reportID: PropTypes.string, - }), - }).isRequired, -}; - -const defaultProps = { - transactionID: '', - report: {}, - isEditingRequest: false, - mapboxAccessToken: { - token: '', - }, - transaction: {}, -}; - -function DistanceRequest({transactionID, report, transaction, mapboxAccessToken, route, isEditingRequest, onSubmit}) { - const [shouldShowGradient, setShouldShowGradient] = useState(false); - const [scrollContainerHeight, setScrollContainerHeight] = useState(0); - const [scrollContentHeight, setScrollContentHeight] = useState(0); - const {isOffline} = useNetwork(); - const {translate} = useLocalize(); - - const isEditing = lodashGet(route, 'path', '').includes('address'); - const reportID = lodashGet(report, 'reportID', ''); - const iouType = lodashGet(route, 'params.iouType', ''); - const waypoints = useMemo(() => lodashGet(transaction, 'comment.waypoints', {}), [transaction]); - const previousWaypoints = usePrevious(waypoints); - const numberOfWaypoints = _.size(waypoints); - const numberOfPreviousWaypoints = _.size(previousWaypoints); - const scrollViewRef = useRef(null); - - const lastWaypointIndex = numberOfWaypoints - 1; - const isLoadingRoute = lodashGet(transaction, 'comment.isLoading', false); - const isLoading = lodashGet(transaction, 'isLoading', false); - const hasRouteError = !!lodashGet(transaction, 'errorFields.route'); - const hasRoute = TransactionUtils.hasRoute(transaction); - const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints); - const previousValidatedWaypoints = usePrevious(validatedWaypoints); - const haveValidatedWaypointsChanged = !_.isEqual(previousValidatedWaypoints, validatedWaypoints); - const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError; - const shouldFetchRoute = (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && _.size(validatedWaypoints) > 1; - const waypointMarkers = useMemo( - () => - _.filter( - _.map(waypoints, (waypoint, key) => { - if (!waypoint || lodashIsNil(waypoint.lat) || lodashIsNil(waypoint.lng)) { - return; - } - - const index = TransactionUtils.getWaypointIndex(key); - let MarkerComponent; - if (index === 0) { - MarkerComponent = Expensicons.DotIndicatorUnfilled; - } else if (index === lastWaypointIndex) { - MarkerComponent = Expensicons.Location; - } else { - MarkerComponent = Expensicons.DotIndicator; - } - - return { - id: `${waypoint.lng},${waypoint.lat},${index}`, - coordinate: [waypoint.lng, waypoint.lat], - markerComponent: () => ( - - ), - }; - }), - (waypoint) => waypoint, - ), - [waypoints, lastWaypointIndex], - ); - - // Show up to the max number of waypoints plus 1/2 of one to hint at scrolling - const halfMenuItemHeight = Math.floor(variables.optionRowHeight / 2); - const scrollContainerMaxHeight = variables.optionRowHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight; - - useEffect(() => { - MapboxToken.init(); - return MapboxToken.stop; - }, []); - - useEffect(() => { - if (!transactionID || !_.isEmpty(waypoints)) { - return; - } - // Create the initial start and stop waypoints - Transaction.createInitialWaypoints(transactionID); - }, [transactionID, waypoints]); - - const updateGradientVisibility = (event = {}) => { - // If a waypoint extends past the bottom of the visible area show the gradient, else hide it. - const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight; - setShouldShowGradient(visibleAreaEnd < scrollContentHeight); - }; - useEffect(() => { - if (isOffline || !shouldFetchRoute) { - return; - } - - Transaction.getRoute(transactionID, validatedWaypoints); - }, [shouldFetchRoute, transactionID, validatedWaypoints, isOffline]); - - useEffect(() => { - if (numberOfWaypoints <= numberOfPreviousWaypoints) { - return; - } - scrollViewRef.current.scrollToEnd({animated: true}); - }, [numberOfPreviousWaypoints, numberOfWaypoints]); - - useEffect(updateGradientVisibility, [scrollContainerHeight, scrollContentHeight]); - - const navigateBack = () => { - Navigation.goBack(isEditing ? ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, reportID) : ROUTES.HOME); - }; - - /** - * Takes the user to the page for editing a specific waypoint - * @param {Number} index of the waypoint to edit - */ - const navigateToWaypointEditPage = (index) => { - Navigation.navigate(isEditingRequest ? ROUTES.MONEY_REQUEST_EDIT_WAYPOINT.getRoute(report.reportID, transactionID, index) : ROUTES.MONEY_REQUEST_WAYPOINT.getRoute('request', index)); - }; - - const content = ( - - setScrollContainerHeight(lodashGet(event, 'nativeEvent.layout.height', 0))} - > - setScrollContentHeight(height)} - onScroll={updateGradientVisibility} - scrollEventThrottle={variables.distanceScrollEventThrottle} - ref={scrollViewRef} - > - {_.map(waypoints, (waypoint, key) => { - // key is of the form waypoint0, waypoint1, ... - const index = TransactionUtils.getWaypointIndex(key); - let descriptionKey = 'distance.waypointDescription.'; - let waypointIcon; - if (index === 0) { - descriptionKey += 'start'; - waypointIcon = Expensicons.DotIndicatorUnfilled; - } else if (index === lastWaypointIndex) { - descriptionKey += 'finish'; - waypointIcon = Expensicons.Location; - } else { - descriptionKey += 'stop'; - waypointIcon = Expensicons.DotIndicator; - } - - return ( - navigateToWaypointEditPage(index)} - key={key} - /> - ); - })} - - {shouldShowGradient && ( - - )} - {hasRouteError && ( - - )} - - -