diff --git a/.github/scripts/findUnusedKeys.sh b/.github/scripts/findUnusedKeys.sh
index 77c3ea25326b..1411fffc8389 100755
--- a/.github/scripts/findUnusedKeys.sh
+++ b/.github/scripts/findUnusedKeys.sh
@@ -6,7 +6,7 @@ LIB_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../../ && pwd)"
readonly SRC_DIR="${LIB_PATH}/src"
readonly STYLES_DIR="${LIB_PATH}/src/styles"
-readonly STYLES_FILE="${LIB_PATH}/src/styles/styles.js"
+readonly STYLES_FILE="${LIB_PATH}/src/styles/styles.ts"
readonly UTILITIES_STYLES_FILE="${LIB_PATH}/src/styles/utilities"
readonly STYLES_KEYS_FILE="${LIB_PATH}/scripts/style_keys_list_temp.txt"
readonly UTILITY_STYLES_KEYS_FILE="${LIB_PATH}/scripts/utility_keys_list_temp.txt"
@@ -210,7 +210,12 @@ find_theme_style_and_store_keys() {
fi
# Check if we are inside an arrow function
- if [[ "$line" =~ ^[[:space:]]*([a-zA-Z0-9_-])+:[[:space:]]*\(.*\)[[:space:]]*'=>'[[:space:]]*\(\{ || "$line" =~ ^[[:space:]]*(const|let|var)[[:space:]]+([a-zA-Z0-9_-]+)[[:space:]]*=[[:space:]]*\(.*\)[[:space:]]*'=>' ]]; then
+ if [[ "$line" =~ ^[[:space:]]*([a-zA-Zgv 0-9_-])+:[[:space:]]*\(.*\)[[:space:]]*'=>'[[:space:]]*\(\{ || "$line" =~ ^[[:space:]]*([a-zA-Zgv 0-9_-])+:[[:space:]]*\(.*\)[[:space:]]*'=>' ]]; then
+ inside_arrow_function=true
+ continue
+ fi
+
+ if [[ "$line" =~ ^[[:space:]]*(const|let|var)[[:space:]]+([a-zA-Z0-9_-]+)[[:space:]]*=[[:space:]]*\(.*\)[[:space:]]*'=>' ]]; then
inside_arrow_function=true
continue
fi
@@ -348,7 +353,7 @@ echo "🔍 Looking for styles."
find_utility_styles_store_prefix
find_utility_usage_as_styles
-# Find and store keys from styles.js
+# Find and store keys from styles.ts
find_styles_object_and_store_keys "$STYLES_FILE"
find_styles_functions_and_store_keys "$STYLES_FILE"
collect_theme_keys_from_styles "$STYLES_FILE"
diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml
index 75f46e68fe5a..e6da6fff1446 100644
--- a/.github/workflows/cherryPick.yml
+++ b/.github/workflows/cherryPick.yml
@@ -11,7 +11,7 @@ jobs:
validateActor:
runs-on: ubuntu-latest
outputs:
- IS_DEPLOYER: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' }}
+ IS_DEPLOYER: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }}
steps:
- name: Check if user is deployer
id: isDeployer
diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml
index 3666e8c7d343..308404b74bc0 100644
--- a/.github/workflows/e2ePerformanceTests.yml
+++ b/.github/workflows/e2ePerformanceTests.yml
@@ -191,14 +191,15 @@ jobs:
if: ${{ always() && runner.debug != null && fromJSON(runner.debug) }}
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log"
- - name: Check if test failed, if so post the results and add the DeployBlocker label
- run: |
- if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then
- gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash
- gh pr comment ${{ inputs.PR_NUMBER }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md
- gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker."
- else
- echo '✅ no performance regression detected'
- fi
- env:
- GITHUB_TOKEN: ${{ github.token }}
+# TODO: Once tests are more reliable we should uncomment this
+# - name: Check if test failed, if so post the results and add the DeployBlocker label
+# run: |
+# if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then
+# gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash
+# gh pr comment ${{ inputs.PR_NUMBER }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md
+# gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker."
+# else
+# echo '✅ no performance regression detected'
+# fi
+# env:
+# GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml
index ad002e164837..f5a5dc5e1616 100644
--- a/.github/workflows/platformDeploy.yml
+++ b/.github/workflows/platformDeploy.yml
@@ -16,7 +16,7 @@ jobs:
validateActor:
runs-on: ubuntu-latest
outputs:
- IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' }}
+ IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }}
steps:
- name: Check if user is deployer
id: isUserDeployer
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 3b049b173a3f..bebbda72c856 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 1001038306
- versionName "1.3.83-6"
+ versionCode 1001038400
+ versionName "1.3.84-0"
}
flavorDimensions "default"
diff --git a/assets/animations/FastMoney.json b/assets/animations/FastMoney.json
new file mode 100644
index 000000000000..95d560319141
--- /dev/null
+++ b/assets/animations/FastMoney.json
@@ -0,0 +1 @@
+{"v":"5.9.6","fr":24,"ip":0,"op":80,"w":375,"h":240,"nm":"C","assets":[{"id":"comp_0","nm":"C","fr":24,"layers":[{"ind":1,"ty":0,"nm":"E","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[174.5,291,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[42,42,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":0,"op":80,"st":0}]},{"id":"comp_1","nm":"E","fr":24,"layers":[{"ind":1,"ty":0,"nm":"t","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[966,966,0],"to":[0,-20,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":16,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":24,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":28,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":32,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":40,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":48,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":56,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":64,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":72,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76,"s":[966,846,0],"to":[0,0,0],"ti":[0,-20,0]},{"t":80,"s":[966,966,0]}],"l":2},"a":{"a":0,"k":[966,543.5,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1087,"ip":0,"op":80,"st":0},{"ind":2,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":0,"op":16,"st":0},{"ind":3,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":16,"op":32,"st":16},{"ind":4,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":32,"op":48,"st":32},{"ind":5,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":48,"op":64,"st":48},{"ind":6,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":64,"op":80,"st":64},{"ind":7,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":0,"op":8,"st":-8},{"ind":8,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":8,"op":24,"st":8},{"ind":9,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":24,"op":40,"st":24},{"ind":10,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":40,"op":56,"st":40},{"ind":11,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":56,"op":72,"st":56},{"ind":12,"ty":0,"nm":"l","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[1060,966,0],"l":2},"a":{"a":0,"k":[966,966,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1932,"ip":72,"op":80,"st":72},{"ind":13,"ty":0,"nm":"t","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[966,966,0],"to":[0,-20,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":16,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":24,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":28,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":32,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":40,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":48,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":56,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":64,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68,"s":[966,846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":72,"s":[966,966,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76,"s":[966,846,0],"to":[0,0,0],"ti":[0,-20,0]},{"t":80,"s":[966,966,0]}],"l":2},"a":{"a":0,"k":[966,543.5,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1087,"ip":0,"op":80,"st":0},{"ind":14,"ty":0,"nm":"u","parent":1,"refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[966,543,0],"l":2},"a":{"a":0,"k":[966,543.5,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"w":1932,"h":1087,"ip":0,"op":80,"st":0},{"ind":15,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[0]},{"t":54,"s":[9]}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[1304.5,374.75,0],"to":[12.667,-19,0],"ti":[-13.167,5,0]},{"t":54,"s":[1362.5,335.75,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":50,"s":[100,100,100]},{"t":54,"s":[25,25,100]}],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":16,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[0]},{"t":54,"s":[6]}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[1341.898,405.813,0],"to":[13.5,0.917,0],"ti":[-11.5,-9.417,0]},{"t":54,"s":[1395.898,426.313,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":50,"s":[100,100,100]},{"t":54,"s":[25,25,100]}],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":17,"ty":4,"nm":"s","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-278.97,470.86,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-8.927,0],[1.705,-3.01],[7.797,-1.705]],"o":[[4.514,-11.535],[7.87,0],[-1.705,3.009],[-7.797,1.706]],"v":[[-14.694,12.137],[6.068,-12.137],[12.99,-2.507],[-0.378,5.015]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.553,0.784,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1285.643,129.839]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":50,"op":55,"st":0},{"ind":18,"ty":4,"nm":"s","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-316.368,439.797,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[11.736,1.103],[-9.329,0],[0.702,-4.112],[5.019,0.247]],"o":[[5.818,-4.313],[9.328,0],[-0.702,3.01],[-10.432,-0.903]],"v":[[-16.349,-0.224],[4.012,-6.643],[15.647,1.582],[6.72,6.397]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.553,0.784,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1321,152.732]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":50,"op":55,"st":0}]},{"id":"comp_2","nm":"t","fr":24,"layers":[{"ind":1,"ty":3,"nm":"m","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[1028,525.5,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":8,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":24,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":28,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":32,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":36,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":40,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":44,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":48,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":52,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":56,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":64,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":68,"s":[91,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":72,"s":[101,91,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":76,"s":[91,103,100]},{"t":80,"s":[101,91,100]}],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":2,"ty":3,"nm":"b","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[909,531.5,0],"to":[1,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":28,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68,"s":[915,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[909,531.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76,"s":[915,531.5,0],"to":[0,0,0],"ti":[1,0,0]},{"t":80,"s":[909,531.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":8,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":24,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":28,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":32,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":36,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":40,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":44,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":48,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":52,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":56,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":64,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":68,"s":[80,103,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":72,"s":[111,65,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":76,"s":[80,103,100]},{"t":80,"s":[111,65,100]}],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":3,"ty":3,"nm":"h","parent":4,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[10,137,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":4,"ty":3,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":44,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":64,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":68,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":76,"s":[0]},{"t":80,"s":[10]}]},"p":{"a":0,"k":[-36,63,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":5,"ty":3,"nm":"a","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[-160]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[-4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[-160]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[-4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[-160]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":44,"s":[-4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[-160]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[-4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":64,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":68,"s":[-160]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[-112]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":76,"s":[-4]},{"t":80,"s":[-112]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[890,395.5,0],"to":[2.5,-2,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[905,383.5,0],"to":[0,0,0],"ti":[-2.5,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8,"s":[890,395.5,0],"to":[2.5,1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12,"s":[920,393.5,0],"to":[0,0,0],"ti":[2.5,1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[890,395.5,0],"to":[-2.5,-1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[905,383.5,0],"to":[0,0,0],"ti":[-2.5,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[890,395.5,0],"to":[2.5,1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":28,"s":[920,393.5,0],"to":[0,0,0],"ti":[2.5,1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[890,395.5,0],"to":[-2.5,-1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[905,383.5,0],"to":[0,0,0],"ti":[-2.5,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[890,395.5,0],"to":[2.5,1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[920,393.5,0],"to":[0,0,0],"ti":[2.5,1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48,"s":[890,395.5,0],"to":[-2.5,-1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[905,383.5,0],"to":[0,0,0],"ti":[-2.5,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[890,395.5,0],"to":[2.5,1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[920,393.5,0],"to":[0,0,0],"ti":[2.5,1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[890,395.5,0],"to":[-2.5,-1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68,"s":[905,383.5,0],"to":[0,0,0],"ti":[-2.5,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[890,395.5,0],"to":[2.5,1.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76,"s":[920,393.5,0],"to":[0,0,0],"ti":[5,-0.333,0]},{"t":80,"s":[890,395.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":6,"ty":3,"nm":"h","parent":7,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":44,"s":[24]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":47,"s":[0]},{"t":49,"s":[-20]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":44,"s":[-125,-9.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":47,"s":[-125,-9.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":49,"s":[-125,-9.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":7,"ty":3,"nm":"a","parent":8,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":44,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":47,"s":[0]},{"t":49,"s":[-19]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":44,"s":[75,-34,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":47,"s":[75,-34,0],"to":[0,0,0],"ti":[0,0,0]},{"t":49,"s":[75,-34,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":8,"ty":3,"nm":"a","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":44,"s":[24]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":47,"s":[0]},{"t":49,"s":[30]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":44,"s":[1122,363.5,0],"to":[5,1.333,0],"ti":[-3.333,-2.333,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":47,"s":[1152,371.5,0],"to":[3.333,2.333,0],"ti":[1.667,-1,0]},{"t":49,"s":[1142,377.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":9,"ty":3,"nm":"h","parent":10,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[-10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[0]},{"t":59,"s":[-54]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":50,"s":[70,-59,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":53,"s":[70,-59,0],"to":[0,0,0],"ti":[0,0,0]},{"t":59,"s":[70,-59,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":10,"ty":3,"nm":"a","parent":11,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[0]},{"t":59,"s":[-11]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":50,"s":[121,-15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":53,"s":[121,-15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":59,"s":[121,-15,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":11,"ty":3,"nm":"a","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[2]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[0]},{"t":59,"s":[20]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":50,"s":[1150,365.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.659,"y":0.854},"o":{"x":0.297,"y":0},"t":53,"s":[1150,365.5,0],"to":[-1.038,0.389,0],"ti":[2.52,-0.945,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.425,"y":0.211},"t":56,"s":[1144.19,387.679,0],"to":[-3.951,1.482,0],"ti":[1.628,-0.611,0]},{"t":59,"s":[1134,371.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":12,"ty":4,"nm":"h","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[208.53,96.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.2,6.65],[-11.98,5.54],[-6.96,-4.61],[0.1,-7.55],[0,0]],"o":[[0,0],[-5.9,0.34],[-0.21,-6.66],[11.99,-5.53],[6.97,4.61],[-0.1,7.56],[0,0]],"v":[[-16.11,18.555],[-16.12,18.555],[-26.52,9.685],[-11.78,-13.365],[18.64,-11.005],[26.63,5.195],[19.56,15.265]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[804.229,508.235]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.55,-2.56]],"o":[[-0.38,4.04],[0,0]],"v":[[0.06,-4.945],[0.32,4.945]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[787.789,521.845]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.59,-0.76],[-0.11,0.24],[0,0]],"o":[[0.76,3.53],[4.3,1.27],[0,0],[0,0]],"v":[[-5.495,-3.85],[-0.485,2.58],[5.495,0.2],[5.495,0.19]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[793.614,530.64]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.48,-2.41],[-2.62,0.23],[-0.21,0.37]],"o":[[-0.42,5.63],[1.84,3],[4.74,-0.43],[0,0]],"v":[[-6.755,-7.855],[-4.845,3.955],[2.435,7.625],[7.175,2.625]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[803.954,526.885]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.77,-2.08],[-2.7,0.54],[2.35,4.24],[0.06,4.63]],"o":[[0.46,4.14],[2.45,2.88],[4.64,-0.93],[-1.44,-2.85],[0,0]],"v":[[-9.3,-3.17],[-5.71,6.09],[2.68,9.45],[6.95,0.08],[4.48,-9.99]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[816.839,523.42]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.64,-0.93],[2.45,2.88],[4.74,-0.43],[1.84,3],[4.3,1.27],[0.76,3.53],[0,0],[0.2,6.65],[-11.98,5.54],[-6.96,-4.61],[0.1,-7.55]],"o":[[2.35,4.24],[-2.7,0.54],[-0.21,0.37],[-2.62,0.23],[-0.11,0.24],[-2.59,-0.76],[0,0],[-5.9,0.34],[-0.21,-6.66],[11.99,-5.53],[6.97,4.61],[-0.1,7.56]],"v":[[19.56,11.46],[15.29,20.83],[6.9,17.47],[2.16,22.47],[-5.12,18.8],[-11.1,21.18],[-16.11,14.75],[-16.12,14.75],[-26.52,5.88],[-11.78,-17.17],[18.64,-14.81],[26.63,1.39]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[804.229,512.04]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":80,"st":0},{"ind":13,"ty":4,"nm":"a","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[168.53,183.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.79,-4.94]],"o":[[6.76,-0.53],[0,0]],"v":[[-8.2,-2.515],[8.2,3.045]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[810.199,470.945]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[7.72,-0.59]],"o":[[-3.14,-5.15],[0,0]],"v":[[8.145,3.715],[-8.145,-3.125]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[813.384,459.555]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.28,-4.54]],"o":[[6.87,-2.29],[0,0]],"v":[[-8.365,-0.545],[8.365,2.835]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[808.274,482.105]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.37,9.86]],"o":[[-0.37,9.86],[0,0]],"v":[[-7.815,-5.235],[8.185,-4.625]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[806.914,502.335]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.54,4.98],[-0.91,4.23],[-1.27,3.87],[-16.55,15.32]],"o":[[0,-5.38],[0.48,-4.53],[0.88,-4.14],[6.98,-21.31],[0,0]],"v":[[-21.145,47.33],[-20.335,31.79],[-18.245,18.66],[-15.005,6.66],[21.145,-47.33]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[820.244,449.77]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.68,4.15],[-0.85,3.53],[-1.15,3.48],[-12.89,12.79]],"o":[[0.36,-4.37],[0.59,-3.7],[0.89,-3.66],[5.88,-17.68],[0,0]],"v":[[-17.46,40.015],[-15.91,27.245],[-13.75,16.395],[-10.69,5.685],[17.46,-40.015]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[832.559,457.695]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-16.55,15.32],[0,0],[5.88,-17.68],[0,0],[7.72,-0.59]],"o":[[0,0],[-12.89,12.79],[0,0],[-3.14,-5.15],[6.98,-21.31]],"v":[[13.76,-30.47],[22.39,-15.23],[-5.76,30.47],[-6.1,30.36],[-22.39,23.52]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[827.629,432.91]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.28,-4.54],[0,0],[0.36,-4.37],[-0.37,9.86],[-0.54,4.98]],"o":[[0,0],[-0.68,4.15],[-0.37,9.86],[0,-5.38],[6.87,-2.29]],"v":[[8.95,-8.48],[8.96,-8.48],[7.41,4.29],[-8.59,3.68],[-7.78,-11.86]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[807.689,493.42]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.14,-5.15],[0,0],[0.89,-3.66],[0,0],[6.76,-0.53],[-1.27,3.87]],"o":[[0,0],[-1.15,3.48],[0,0],[-3.79,-4.94],[0.88,-4.14],[7.72,-0.59]],"v":[[9.595,-1.695],[9.935,-1.585],[6.875,9.125],[6.465,9.025],[-9.935,3.465],[-6.695,-8.535]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[811.934,464.965]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.79,-4.94],[0,0],[0.59,-3.7],[0,0],[6.87,-2.29],[-0.91,4.23]],"o":[[0,0],[-0.85,3.53],[0,0],[-4.28,-4.54],[0.48,-4.53],[6.76,-0.53]],"v":[[9.04,-2.43],[9.45,-2.33],[7.29,8.52],[7.28,8.52],[-9.45,5.14],[-7.36,-7.99]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[809.359,476.42]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":80,"st":0},{"ind":14,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":79,"op":80,"st":0},{"ind":15,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":63,"op":74,"st":0},{"ind":16,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":47,"op":58,"st":0},{"ind":17,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":31,"op":42,"st":0},{"ind":18,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":15,"op":26,"st":0},{"ind":19,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":10,"st":0},{"ind":20,"ty":4,"nm":"h","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-187.47,521.11,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.16,-0.19],[3.84,0],[3.82,-0.13],[0.38,-2.68],[0,0]],"o":[[-1.74,0.1],[-1.91,0.31],[-6.18,0],[-3.82,0.13],[-0.38,2.67],[0,0]],"v":[[16.135,-3.325],[12.025,-2.855],[4.485,-2.215],[-9.325,-3.665],[-15.755,0.235],[-14.695,3.795]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1164.344,61.285]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[5.22,0.9],[1.21,-0.17],[0.01,-2.03],[-0.25,-0.13],[0,0]],"o":[[-8.92,1.02],[-1.75,-0.3],[-2.4,0.34],[-0.02,2.87],[0.02,0.01],[0,0]],"v":[[14.59,-2.46],[-6.43,-3.61],[-10.88,-3.79],[-14.57,-0.17],[-12.3,3.95],[-12.27,3.96]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1160.539,68.96]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[9.68,0.77],[0.84,-0.37],[-4.65,-0.93]],"o":[[-12.23,1.66],[-1.38,-0.02],[-4.17,1.76],[0,0]],"v":[[15.53,-4.375],[-8.04,-4.375],[-11.36,-3.825],[-8.94,4.395]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1159.599,76.735]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.98,-0.25],[1.1,-1.06],[0,-1],[-5.86,-0.63],[-3.95,0],[-8.15,2.81],[-0.51,6.88],[7.13,1.4],[4.87,3.95],[1.15,-1.91],[-7.42,-3.29]],"o":[[-6.4,0.97],[-2.55,-0.16],[-0.66,0.61],[0,2.68],[5.86,0.64],[3.95,0],[8.15,-2.8],[0.51,-6.88],[-7.13,-1.4],[-4.87,-3.95],[-1.15,1.91],[0,0]],"v":[[-3.255,11.595],[-22.745,12.485],[-28.345,13.875],[-29.365,16.305],[-22.105,22.165],[-5.675,21.025],[15.605,19.235],[28.855,5.095],[18.535,-10.705],[-0.295,-18.855],[-8.475,-20.005],[-2.645,-8.835]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1179.014,67.265]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.91,0.31],[-1.15,1.91],[-4.87,-3.95],[-7.13,-1.4],[0.51,-6.88],[8.15,-2.8],[3.95,0],[5.86,0.64],[0,2.68],[-0.66,0.61],[0,0],[-4.17,1.76],[-0.02,2.87],[-2.4,0.34],[0,0],[-0.38,2.67],[-3.82,0.13],[-6.18,0]],"o":[[-7.42,-3.29],[1.15,-1.91],[4.87,3.95],[7.13,1.4],[-0.51,6.88],[-8.15,2.81],[-3.95,0],[-5.86,-0.63],[0,-1],[0,0],[-4.65,-0.93],[-0.25,-0.13],[0.01,-2.03],[0,0],[0,0],[0.38,-2.68],[3.82,-0.13],[3.84,0]],"v":[[0.145,-8.835],[-5.685,-20.005],[2.495,-18.855],[21.325,-10.705],[31.645,5.095],[18.395,19.235],[-2.885,21.025],[-19.315,22.165],[-26.575,16.305],[-25.555,13.875],[-25.565,13.865],[-27.985,5.645],[-30.255,1.525],[-26.565,-2.095],[-26.575,-2.185],[-27.635,-5.745],[-21.205,-9.645],[-7.395,-8.195]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1176.224,67.265]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":44,"op":50,"st":0},{"ind":21,"ty":4,"nm":"a","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-362.47,461.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.48,-5]],"o":[[0,0],[2,5.67],[0,0]],"v":[[-0.94,-8.03],[-0.94,-8.02],[-1.24,8.03]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1233.839,72.2]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.58,5.79]],"o":[[2.18,-5.01],[0,0]],"v":[[-0.535,8.145],[-1.645,-8.145]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1219.294,72.085]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.74,-4.81]],"o":[[1.86,5.95],[0,0]],"v":[[-0.09,-8.025],[-1.77,8.025]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1247.969,72.955]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-10.36,1.72]],"o":[[-10.36,1.73],[0,0]],"v":[[3.795,-9.17],[6.565,7.45]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1201.674,73.11]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[89.82,6.06],[5.16,0.17],[5.24,0.02],[4.15,-0.07]],"o":[[-13.75,-27.12],[-4.83,-0.32],[-4.93,-0.18],[-3.97,-0.03],[0,0]],"v":[[89.84,32.59],[-47.43,-31.51],[-62.41,-32.26],[-77.66,-32.56],[-89.84,-32.5]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1295.309,96.44]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[60.81,4.09],[4.61,0.12],[4.68,-0.07],[3.54,-0.15]],"o":[[-15.72,-30],[-4.46,-0.3],[-4.54,-0.12],[-3.47,0.04],[0,0]],"v":[[80.59,27.725],[-42.63,-26.945],[-56.23,-27.575],[-70.07,-27.655],[-80.59,-27.365]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1288.829,107.925]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-13.75,-27.12],[0,0],[60.81,4.09],[1.86,5.95]],"o":[[0,0],[-15.72,-30],[2.74,-4.81],[89.82,6.06]],"v":[[69.475,28.74],[53.745,35.36],[-69.475,-19.31],[-67.795,-35.36]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1315.674,100.29]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.18,-5.01],[0,0],[3.54,-0.15],[-10.36,1.73],[-3.97,-0.03]],"o":[[2.58,5.79],[0,0],[-3.47,0.04],[-10.36,1.72],[4.15,-0.07],[0,0]],"v":[[9.625,-9.125],[10.735,7.165],[10.735,7.205],[0.215,7.495],[-2.555,-9.125],[9.625,-9.185]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1208.024,73.065]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.83,-0.32],[2.74,-4.81],[4.61,0.12],[0,0],[2,5.67]],"o":[[1.86,5.95],[-4.46,-0.3],[0,0],[2.48,-5],[5.16,0.17]],"v":[[6.71,-7.65],[5.03,8.4],[-8.57,7.77],[-8.57,7.65],[-8.27,-8.4]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1241.169,72.58]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.93,-0.18],[2.48,-5],[0,0],[4.68,-0.07],[0,0],[2.58,5.79],[0,0]],"o":[[2,5.67],[0,0],[-4.54,-0.12],[0,0],[2.18,-5.01],[0,0],[5.24,0.02]],"v":[[6.535,-7.935],[6.235,8.115],[6.235,8.235],[-7.605,8.155],[-7.605,8.115],[-8.715,-8.175],[-8.715,-8.235]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1226.364,72.115]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":44,"op":50,"st":0},{"ind":22,"ty":4,"nm":"m","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-12.47,67.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.462,-5.128],[-0.013,-0.349],[2.171,-0.112],[0.287,5.602],[0,0.45],[-1.984,0.087]],"o":[[0.037,0.337],[0.287,5.602],[-2.17,0.113],[-0.025,-0.474],[0,-4.965],[2.034,-0.1]],"v":[[3.73,-1.229],[3.805,-0.206],[0.386,10.136],[-4.055,0.193],[-4.092,-1.192],[-0.649,-10.149]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1053.325,418.603]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.287,-5.602],[2.171,-0.112],[0.287,5.601],[-2.184,0.112]],"o":[[0.287,5.602],[-2.171,0.112],[-0.287,-5.602],[2.17,-0.112]],"v":[[3.93,-0.206],[0.524,10.149],[-3.93,0.206],[-0.511,-10.149]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1027.587,422.096]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.137,8.271],[-2.358,5.477],[-1.547,0.449],[-0.4,0],[-1.273,-1.847],[-0.698,-8.01],[0.586,-5.365]],"o":[[-2.982,-6.749],[-0.137,-8.434],[0.686,-1.572],[0.399,-0.113],[2.071,0],[3.955,5.751],[0.537,5.938],[0,0]],"v":[[-5.801,24.515],[-10.367,0.911],[-6.911,-21.109],[-3.281,-24.352],[-2.083,-24.515],[3.319,-21.258],[9.968,0.325],[9.744,17.666]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1053.138,416.55]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.424,7.66],[-2.658,6.151],[-1.559,0.449],[-0.399,0],[-1.26,-1.847],[-0.524,-8.746],[1.148,-6.063]],"o":[[-2.982,-6.101],[-0.537,-9.332],[0.673,-1.572],[0.399,-0.113],[2.058,0],[4.33,6.262],[0.474,7.71],[0,0]],"v":[[-5.153,24.802],[-10.168,3.331],[-6.812,-21.396],[-3.182,-24.639],[-1.984,-24.802],[3.405,-21.545],[10.23,2.196],[8.907,23.704]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1027.637,419.332]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.036,8.982],[1.909,-1.559],[-0.112,0.499],[-1.971,2.92],[-0.274,-0.149],[-0.212,-14.971]],"o":[[0.2,-12.014],[-2.033,1.984],[-0.262,-3.007],[0.063,-0.312],[3.693,-0.536],[0.449,0.262],[0,0]],"v":[[-1.004,19.742],[-3.039,-9.762],[-10.161,-1.392],[-10.885,-11.496],[-4.573,-21.079],[7.492,-22.676],[10.997,22.824]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1001.095,419.988]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-17.404,1.036],[-7.723,0.449],[-4.204,0.287],[-0.199,-11.166]],"o":[[9.731,-1.21],[8.92,-0.536],[6.312,-0.349],[3.518,18.789],[0,0]],"v":[[-45.792,-14.684],[-1.054,-18.115],[24.447,-19.587],[40.515,-20.548],[45.792,20.548]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1026.296,406.046]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.062],[-1.048,-8.583],[0.087,-2.27]],"o":[[0.013,0.062],[1.435,8.421],[0.687,5.664],[0,0]],"v":[[-2.651,-20.329],[-2.626,-20.142],[1.528,7.754],[2.564,20.329]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[981.982,411.691]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-10.542,-17.217]],"o":[[1.647,20.111],[0,0]],"v":[[-9.319,-28.514],[9.319,28.514]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1082.319,362.05]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-13.711,-19.325]],"o":[[1.335,23.667],[0,0]],"v":[[-11.59,-33.111],[11.59,33.111]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1077.004,366.934]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.886,-20.972]],"o":[[4.629,22.456],[0,0]],"v":[[-2.315,-31.196],[0.155,31.196]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[961.535,374.276]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.163,-15.108],[0,0]],"o":[[2.907,14.859],[0,0],[0,0]],"v":[[-1.516,-19.706],[1.353,19.606],[1.353,19.706]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[951.267,364.982]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.584,14.41]],"o":[[51.662,64.574],[0,0]],"v":[[-39.479,-28.607],[37.896,-35.967]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1004.426,369.192]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.345,21.433]],"o":[[40.222,51.961],[0,0]],"v":[[-32.73,-24.222],[32.73,-27.739]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.253,358.931]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.15,-0.786],[-6.25,0.2],[0.399,6.326],[0.2,0.761],[0.012,0.05],[-0.012,-0.05],[-0.25,-0.761],[-5.526,0.686],[0.461,5.714]],"o":[[0,0.798],[1.135,5.565],[6.276,-0.212],[-0.05,-0.785],[-0.012,-0.05],[0,0.05],[0.025,0.785],[1.672,5.465],[5.776,-0.711],[0,0]],"v":[[-22.961,-4.753],[-22.724,-2.383],[-10.336,7.872],[-0.231,-5.502],[-0.617,-7.834],[-0.655,-7.984],[-0.643,-7.834],[-0.231,-5.502],[13.443,4.055],[22.5,-8.072]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[837.613,133.101]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[-0.012,0.012],[0,0]],"v":[[0.006,-0.013],[0.006,0.013]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[860.107,125.017]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.137,-0.536],[0.125,0.549]],"o":[[-0.05,-0.549],[0.037,0.562]],"v":[[0.131,0.823],[-0.131,-0.823]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[859.982,124.181]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.751,0.436],[-0.499,5.664],[0.038,0.562],[-0.05,-0.537],[-5.365,0.387],[0.15,4.978],[0.163,0.649],[-0.15,-0.599],[-6.139,0.337],[-0.324,5.464],[0.063,0.636]],"o":[[1.31,5.564],[5.764,-0.425],[0.05,-0.537],[-0.062,0.562],[0.449,5.127],[5.264,-0.374],[-0.025,-0.624],[0.038,0.662],[1.073,4.74],[4.778,-0.275],[0.038,-0.574],[0,0]],"v":[[-32.63,-2.364],[-19.968,7.118],[-8.54,-3.861],[-8.528,-5.508],[-8.54,-3.861],[2.339,4.772],[11.708,-4.784],[11.433,-6.681],[11.708,-4.784],[23.186,2.427],[32.592,-5.745],[32.568,-7.554]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[892.743,127.394]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.51,-2.408],[6.936,-2.396],[-0.088,-4.915],[4.977,0.062],[3.606,-3.318],[-5.827,1.073],[5.277,-2.283],[-8.596,-1.697],[-6.114,0.948],[-5.726,-2.694],[-8.571,-3.243],[3.58,-3.955],[-5.777,-3.219],[4.067,-1.148]],"o":[[-6.413,-3.581],[-4.754,1.646],[-4.804,-1.272],[-4.966,-0.05],[2.233,-5.339],[-4.966,-2.907],[6.5,-5.689],[1.372,-5.863],[6.262,-0.961],[6.238,-6.512],[-5.377,0.649],[6.574,-0.449],[-4.255,0.062],[-4.067,1.148]],"v":[[18.651,6.755],[-2.707,4.859],[-11.989,15.238],[-26.648,12.619],[-40.397,17.197],[-27.197,6.705],[-43.865,5.671],[-19.425,-0.793],[-5.539,-11.072],[13.024,-8.391],[38.288,-13.954],[24.228,-6.743],[43.865,-2.814],[30.578,-1.379]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[912.349,159.082]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.449,-0.936],[-22.631,1.46],[-7.485,-0.012],[0,0]],"o":[[0,0],[1.996,4.105],[8.558,7.136],[11.166,0.025],[0,0]],"v":[[-38.456,-12.208],[-37.846,-10.685],[-5.783,2.901],[19.081,12.182],[38.456,7.466]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.181,132.334]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.753,9.107],[6.912,13.836],[2.046,8.084],[0.137,0.411],[0,0]],"o":[[0,0],[4.579,-8.771],[19.313,-6.799],[-0.349,-1.385],[-0.05,-0.15],[0,0]],"v":[[-15.601,44.694],[-4.111,30.111],[-3.712,-4.622],[9.912,-41.712],[9.126,-44.47],[9.051,-44.694]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[804.864,172.456]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.41,3.668],[19.05,32.337],[40.684,-11.253],[-18.377,-38.537],[-4.341,-8.795],[-5.177,-12.488],[-4.579,-11.477],[-2.657,-6.038],[-0.324,-0.711],[-9.681,-6.201],[-5.589,-1.934],[-4.117,-0.736],[-3.519,-0.174],[-4.715,0.612],[-3.593,1.01],[-1.56,0.562],[-3.406,2.183],[-2.881,2.844],[-3.655,10.355],[-0.723,3.269],[5.489,15.645]],"o":[[-12.625,-32.923],[-20.822,-35.307],[-47.046,12.999],[4.728,7.673],[5.951,12.077],[5.54,13.349],[3.144,7.872],[0.337,0.748],[4.529,10.018],[4.828,3.094],[3.88,1.372],[3.431,0.649],[4.703,0.25],[3.668,-0.474],[1.584,-0.449],[3.892,-1.397],[3.406,-2.171],[7.399,-7.298],[1.098,-3.106],[3.443,-15.37],[-1.372,-3.917]],"v":[[93.076,18.676],[47.365,-70.413],[-52.878,-120.628],[-85.04,-28.258],[-71.442,-3.369],[-54.737,33.959],[-39.541,71.81],[-30.833,92.857],[-29.86,95.028],[-7.853,119.63],[7.842,127.215],[19.868,130.396],[30.311,131.631],[44.495,131.107],[55.411,128.887],[60.127,127.377],[71.08,121.988],[80.525,114.44],[97.229,87.467],[99.974,77.898],[97.243,30.029]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[992.162,312.777]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-52.473,25.813],[9.956,24.44],[27.634,44.239],[18.502,-2.532],[7.648,-24.839],[-5.551,-18.152],[-9.581,-18.826]],"o":[[22.906,57.189],[53.346,-29.642],[-6.774,-18.801],[-42.28,-67.693],[-25.762,3.531],[-5.577,18.128],[7.548,24.664],[10.717,21.046]],"v":[[-57.956,82.414],[70.657,128.999],[103.455,5.926],[52.966,-87.118],[-66.839,-146.953],[-118.426,-104.285],[-116.081,-52.037],[-83.669,14.934]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1000.297,322.459]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[65.173,27.584]],"o":[[4.104,-129.161],[0,0]],"v":[[85.721,159.689],[-89.825,-159.689]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1072.088,304.481]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[11.952,33.335],[38.75,35.231]],"o":[[-3.531,-44.476],[-22.306,-62.229],[0,0]],"v":[[63.776,138.923],[38.375,16.949],[-63.776,-138.923]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[864.629,341.54]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[8.769,-0.587],[14.896,-0.986],[0.038,0],[5.963,-0.399],[34.994,-2.271],[7.647,-0.499],[9.943,-0.649],[2.907,-0.187],[-0.487,14.06],[0.062,4.965],[0.087,2.433],[23.729,48.481],[29.704,29.218],[3.069,2.845],[27.584,13.649],[-46.087,6.164]],"o":[[-0.587,20.548],[-14.846,0.985],[-0.037,0.012],[-5.277,0.349],[-30.229,2.008],[-8.109,0.536],[-11.915,0.773],[-23.404,1.509],[8.147,-2.844],[0.212,-6.2],[-0.025,-2.433],[-1.797,-53.708],[-19.375,-39.623],[-3.032,-2.981],[-28.894,-26.798],[0,0],[0,0]],"v":[[242.177,154.847],[224.602,184.789],[179.989,187.747],[179.864,187.758],[162.96,188.882],[59.673,195.643],[35.957,197.19],[2.908,199.336],[-39.921,202.106],[-29.154,170.641],[-29.104,153.375],[-29.279,146.089],[-69.576,-10.719],[-145.927,-114.879],[-155.072,-123.612],[-242.178,-185.08],[-136.499,-202.106]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[935.003,332.216]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.878,0.623],[-7.697,0.848],[0,0],[-7.56,0.686],[-7.96,0.511],[-6.475,0.237],[-6.724,-0.05],[-10.171,-1.561]],"o":[[4.778,-0.636],[7.585,-0.948],[0,0],[7.623,-0.848],[8.234,-0.761],[6.824,-0.449],[7.348,-0.262],[6.961,0.075],[0,0]],"v":[[-82.507,5.115],[-68.01,3.219],[-45.03,0.499],[-45.005,0.499],[-22.187,-1.809],[2.166,-3.73],[22.152,-4.753],[43.311,-5.065],[82.507,-2.441]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882,124.768]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.191,-4.241],[-10.742,-20.323],[-0.612,-96.038],[0.063,-3.206],[0.35,-5.364]],"o":[[14.268,4.61],[52.46,32.985],[21.733,41.145],[0.025,3.132],[-0.112,5.178],[0,0]],"v":[[-106.576,-182.624],[-69.408,-165.199],[43.859,-44.509],[106.55,157.286],[106.487,166.805],[105.801,182.624]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1071.083,304.95]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.445,0.162],[13.062,-0.387],[33.46,4.841],[0.112,-1.735]],"o":[[2.358,-0.2],[-6.761,-3.967],[0,0],[-0.374,7.049],[0,0]],"v":[[28.882,20.728],[36.104,20.18],[6.886,13.967],[-35.256,-20.728],[-36.104,-5.819]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[942.078,508.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.684,5.839],[18.165,5.515],[12.9,-1.859],[0,0],[15.919,1.634],[-10.28,0.636],[3.643,0.037],[-12.937,9.419],[-14.272,2.059],[0,0],[-17.055,10.006],[3.132,2.358]],"o":[[0,0],[0,0],[-9.606,1.372],[0,0],[0,0],[0,0],[0,0],[0,0],[14.272,-2.046],[0,0],[0,0],[0,0]],"v":[[47.807,-16.038],[13.885,-16.212],[-1.597,-5.021],[-16.58,-11.833],[-49.978,-2.563],[-37.153,4.835],[-47.183,11.048],[-17.541,6.794],[3.281,13.318],[19.35,0.368],[49.978,-2.9],[38.25,-6.543]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1046.863,493.732]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0.013],[19.862,-2.433],[25.226,8.246],[7.772,-0.4]],"o":[[-0.012,-0.012],[-7.174,-8.546],[0,0],[-5.514,-1.809],[0,0]],"v":[[43.784,25.014],[43.771,24.989],[4.797,12.351],[-23.948,-22.269],[-43.784,-24.614]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.905,502.87]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[9.394,-3.668],[3.256,-24.402],[9.182,-18.489]],"o":[[0,0],[-10.729,4.179],[0,0],[0,0]],"v":[[38.906,-28.676],[21.302,-25.93],[-4.947,12.818],[-38.906,29.599]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1136.831,490.925]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[7.91,-0.761],[0.387,-0.025],[7.623,1.821],[2.021,0.849],[3.955,6.337],[2.669,10.591]],"o":[[-3.369,-0.287],[-0.374,0.037],[-7.173,0.637],[-2.133,-0.499],[-5.864,-2.445],[0,0],[0,0]],"v":[[34.645,13.492],[16.742,15.239],[15.594,15.338],[-7.324,14.303],[-13.561,12.294],[-28.657,-0.493],[-34.645,-16.124]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1049.807,318.273]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.718,0.512],[-2.969,1.048],[-1.697,1.123],[-1.435,2.396],[-0.487,2.757],[1.172,15.257]],"o":[[3.443,-0.299],[3.243,-0.449],[1.996,-0.686],[2.233,-1.435],[1.21,-1.958],[0,0],[0,0]],"v":[[-17.902,19.961],[-6.998,18.888],[2.445,16.742],[8.01,14.06],[13.586,8.383],[16.156,1.335],[16.731,-19.961]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[956.725,326.201]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.939,-3.751],[1.94,3.751]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[973.699,287.83]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.202,-3.787],[2.202,3.787]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[992.3,286.011]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.21,0.374],[0,0],[0,0],[0,0],[7.785,-5.065],[0.499,-0.262],[1.023,-0.386],[0.025,-0.012],[2.345,-0.387],[1.934,0.062],[1.31,0.224]],"o":[[-10.604,-3.156],[0,0],[0,0],[0,0],[-0.437,0.287],[-0.836,0.449],[-0.012,0],[-1.734,0.637],[-2.134,0.349],[-1.435,-0.025],[-1.335,-0.212]],"v":[[-7.785,7.117],[-24.328,-3.999],[7.66,-7.03],[22.743,-8.452],[16.543,4.335],[15.158,5.147],[12.388,6.393],[12.326,6.418],[6.238,7.978],[0.137,8.39],[-3.98,8.004]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[982.438,289.242]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1.637,3.113],[-1.636,-3.113]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[992.466,300.133]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1.884,5.732],[-1.884,-5.732]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[961.004,268.806]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.806,7.803],[-6.805,-7.803]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[999.473,264.328]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.087,-0.324]],"o":[[0,0],[0,0]],"v":[[-0.081,-0.25],[0.081,0.25]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[996.042,238.21]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.012],[9.108,-6.488]],"o":[[0.012,0.012],[0.749,2.358],[0,0]],"v":[[1.547,-9.133],[1.559,-9.095],[-4.554,9.133]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[994.589,247.604]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.467,-0.624],[4.529,6.524],[0.013,0.025],[0,0],[-1.771,1.822],[-15.856,-0.723],[-5.838,-2.171],[-0.436,-0.174],[-0.025,-0.012],[-0.149,-0.063]],"o":[[-3.816,2.789],[-18.651,2.595],[-0.025,-0.025],[-2.832,-4.092],[0,0],[4.529,-4.603],[4.804,0.225],[0.425,0.149],[0.013,0.013],[0.137,0.062],[0,0]],"v":[[26.189,10.884],[10.227,16.337],[-22.422,4.485],[-22.472,4.41],[-26.189,-3.2],[-23.52,-6.307],[7.083,-18.209],[23.052,-14.79],[24.337,-14.304],[24.4,-14.279],[24.836,-14.104]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.415,246.039]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[50.953,-4.398],[25.989,-2.264],[-17.289,1.429],[-50.953,4.398]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.327,274.832]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[13.605,-1.285],[-13.605,1.285]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[955.558,220.494]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.633,-4.554]],"o":[[1.984,0.936],[0,0]],"v":[[-4.154,-3.35],[4.154,3.35]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.969,235.11]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.087,-0.163]],"o":[[0.1,0.15],[0,0]],"v":[[-0.131,-0.231],[0.131,0.231]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[996.279,238.74]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.518,-17.179],[1.668,-17.042],[36.612,14.809],[70.157,42.318],[20.032,47.021],[17.075,47.595],[-21.724,50.34],[-70.157,54.045],[-65.755,24.016],[-59.152,-12.563],[-54.486,-33.635],[-49.957,-54.045],[-25.517,-36.541],[-8.488,-24.34]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[995.13,255.127]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.187,-4.117],[5.016,-0.15],[0.187,4.117],[-5.027,0.162]],"o":[[0.187,4.117],[-5.027,0.15],[-0.2,-4.117],[5.016,-0.15]],"v":[[9.095,-0.275],[0.349,7.461],[-9.082,0.287],[-0.337,-7.46]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[744.487,154.473]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.125,-0.125],[8.059,-1.197],[-0.574,0]],"o":[[0.137,0.112],[-8.596,1.16],[-1.809,-0.386],[1.759,0]],"v":[[13.593,-1.959],[13.992,-1.596],[-11.06,1.959],[-13.417,1.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[785.502,131.479]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-8.596,1.16],[17.503,-5.414],[9.17,-5.576],[0,0],[-1.734,16.655],[0,0],[1.185,11.153],[3.717,0.798]],"o":[[7.386,7.024],[9.606,16.493],[0,0],[0.399,0.187],[1.759,-17.017],[0,0],[-0.786,-7.51],[8.059,-1.198]],"v":[[14.708,-39.155],[4.029,-3.699],[-4.48,39.155],[-19.151,25.669],[-7.998,13.318],[-22.095,-11.334],[0.798,-24.833],[-10.343,-35.599]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[784.785,169.038]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.349,-1.385],[19.313,-6.799],[4.579,-8.771],[0,0],[0,0],[3.069,2.845],[0,0],[9.606,16.493],[7.386,7.024],[-4.878,0.624]],"o":[[2.046,8.084],[6.912,13.836],[-4.753,9.107],[0,0],[-3.032,-2.982],[0,0],[9.17,-5.576],[17.503,-5.414],[4.778,-0.636],[0.137,0.412]],"v":[[14.578,-41.919],[0.954,-4.829],[0.555,29.904],[-10.935,44.488],[-11.122,44.676],[-20.267,35.942],[-19.893,35.53],[-11.384,-7.324],[-0.705,-42.78],[13.792,-44.676]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[800.198,172.662]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[5.776,-0.711],[1.672,5.464],[0.2,0.761],[-7.561,0.686],[0,0],[-0.137,-0.536]],"o":[[0.462,5.714],[-5.527,0.687],[-0.05,-0.786],[7.623,-0.848],[0,0],[0.037,0.562],[-0.012,0.013]],"v":[[11.328,-5.371],[2.271,6.755],[-11.403,-2.801],[-11.79,-5.134],[11.029,-7.442],[11.066,-7.043],[11.328,-5.396]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[848.785,130.401]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.531,-44.476],[0,0],[7.773,-0.399],[0,0],[23.729,48.481],[29.705,29.218],[0,0],[-4.753,9.107],[0,0],[-22.306,-62.229]],"o":[[0,0],[-5.514,-1.809],[0,0],[-1.796,-53.708],[-19.374,-39.623],[0,0],[0,0],[0,0],[38.75,35.231],[11.952,33.335]],"v":[[69.664,138.88],[68.217,139.017],[48.38,136.672],[46.983,136.722],[6.686,-20.086],[-69.665,-124.246],[-69.478,-124.433],[-57.988,-139.017],[-57.888,-138.967],[44.263,16.905]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[858.741,341.584]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.776,-3.219],[4.067,-1.148],[1.51,-2.408],[6.937,-2.396],[-0.087,-4.915],[4.978,0.063],[3.605,-3.318],[-5.826,1.073],[5.277,-2.284],[-8.596,-1.697],[-6.113,0.948],[-5.726,-2.694],[-8.57,-3.244],[3.581,-3.955]],"o":[[-4.254,0.062],[-4.067,1.147],[-6.412,-3.581],[-4.753,1.646],[-4.803,-1.272],[-4.965,-0.049],[2.233,-5.34],[-4.965,-2.907],[6.499,-5.689],[1.372,-5.864],[6.263,-0.961],[6.238,-6.512],[-5.377,0.649],[6.575,-0.449]],"v":[[43.865,-2.813],[30.577,-1.378],[18.65,6.756],[-2.708,4.86],[-11.99,15.239],[-26.648,12.619],[-40.397,17.198],[-27.198,6.706],[-43.865,5.671],[-19.424,-0.792],[-5.54,-11.072],[13.024,-8.39],[38.287,-13.954],[24.227,-6.743]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[912.349,159.082]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.886,-20.972],[0,0],[3.144,7.872],[2.907,14.858],[0,0],[-2.969,1.048]],"o":[[4.629,22.456],[0,0],[-2.657,-6.038],[0.163,-15.108],[0,0],[3.244,-0.449],[0,0]],"v":[[2.433,-31.208],[4.903,31.183],[4.541,31.345],[-4.167,10.299],[-7.036,-29.012],[-7.061,-29.199],[2.383,-31.345]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[956.788,374.289]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-2.832,-4.092],[-0.025,-0.025],[-8.995,-1.697],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.013,0.025],[3.306,5.514],[0,0],[0,0]],"v":[[17.242,13.642],[17.392,15.364],[-17.391,18.333],[-16.272,18.246],[-9.668,-18.333],[-8.421,-18.059],[-4.703,-10.449],[-4.653,-10.374],[13.624,1.441],[13.474,2.177]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[945.647,260.897]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.919,-0.237],[4.529,-4.604],[-12.576,1.647]],"o":[[-15.857,-0.724],[2.558,-3.893],[3.443,-0.449]],"v":[[15.302,-5.589],[-15.302,6.313],[5.758,-5.327]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[955.197,233.419]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[14.485,7.154],[14.036,7.779],[-13.174,10.349],[-14.484,10.062],[-9.955,-10.349]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[955.128,211.431]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[7.987,-1.328],[4.044,0.58],[1.21,0.374],[0,0]],"o":[[-2.032,3.204],[-4.038,1.029],[-1.335,-0.212],[-4.467,-1.559],[0,0]],"v":[[18.357,-4.305],[5.813,3.276],[-6.312,3.664],[-10.117,2.778],[-18.357,-1.227]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[984.77,293.581]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.435,-0.025],[2.233,0.786],[-1.335,-0.212]],"o":[[-3.019,0.075],[1.21,0.375],[1.31,0.225]],"v":[[3.961,0.599],[-3.961,-0.674],[-0.156,0.212]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[978.614,297.033]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.564,-2.745],[7.822,6.113],[5.302,4.017],[-0.773,-0.013],[-6.849,-2.133]],"o":[[-7.96,0.961],[-6.799,1.909],[0.636,0.025],[10.068,0.785],[5.502,1.709]],"v":[[22.188,5.077],[-3.562,-1.348],[-22.188,-6.039],[-20.055,-5.976],[5.57,-1.66]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[964.953,126.489]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[4.804,0.225],[3.444,-0.449],[2.558,-3.892],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[-5.838,-2.171],[-2.919,-0.237],[-12.575,1.647],[-1.771,1.822],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[25.332,0.074],[25.157,0.537],[9.188,-2.882],[-0.356,-2.62],[-21.415,9.02],[-24.084,12.126],[-25.332,11.852],[-20.666,-9.219],[-19.356,-8.934],[7.853,-11.503],[8.303,-12.126]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[961.31,230.712]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-8.344,-4.205],[0.125,0],[5.502,1.709],[10.068,0.786],[0,0]],"o":[[0,0],[-0.125,0.012],[-5.564,-2.745],[-6.849,-2.133],[3.007,0.062],[0,0]],"v":[[-1.572,-3.419],[21.059,5.49],[21.059,5.526],[4.441,-1.211],[-21.184,-5.526],[-10.174,-4.391]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[966.082,126.04]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.57,-1.747],[3.494,-6.15],[1.447,-1.322],[2.109,-0.848],[-0.175,2.944],[0,0],[0,0],[-4.192,-1.085]],"o":[[3.418,3.481],[-1.197,2.371],[-1.472,1.048],[-7.273,1.634],[2.969,-2.233],[0,0],[4.716,-9.519],[4.179,1.772]],"v":[[10.087,-8.889],[10.648,5.695],[6.656,11.172],[1.315,14.029],[-13.13,6.693],[-4.036,0.992],[-14.141,-5.009],[0.007,-14.578]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[983.38,245.564]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-0.012],[9.107,-6.487],[-1.198,2.371],[3.418,3.481],[-0.773,-0.499],[0,0]],"o":[[0.749,2.358],[1.447,-1.322],[3.493,-6.15],[0.998,0.674],[0,0],[0.012,0.012]],"v":[[1.56,-8.197],[-4.554,10.031],[-0.562,4.553],[-1.122,-10.031],[1.534,-8.247],[1.547,-8.234]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[994.589,246.706]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.749,2.358],[0.012,0.012],[-0.063,-0.037],[8.197,-7.224],[6.637,-1.247],[5.264,0.985],[3.306,5.514],[-18.651,2.595],[-2.956,1.198],[-1.697,1.547]],"o":[[0,-0.012],[0.062,0.05],[0,0],[-2.882,2.545],[-7.411,1.385],[-8.995,-1.697],[4.528,6.525],[4.466,-0.624],[1.822,-0.412],[9.107,-6.487]],"v":[[25.469,-13.212],[25.457,-13.249],[25.644,-13.125],[21.489,4.242],[7.554,10.217],[-11.409,10.617],[-29.686,-1.198],[2.963,10.654],[14.016,7.872],[19.356,5.015]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[970.679,251.721]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.023,-0.387],[0.025,-0.013],[4.18,-0.537],[0.761,-0.012],[1.31,0.225],[0,0],[0,0],[0,0]],"o":[[0,0],[-0.836,0.45],[-0.013,0],[-2.507,0.786],[-0.786,0.1],[-1.435,-0.025],[0,0],[0,0],[0,0],[0,0]],"v":[[9.943,-0.387],[10.979,0.674],[8.209,1.922],[8.146,1.946],[-1.722,3.755],[-4.042,3.917],[-8.159,3.531],[-8.06,2.894],[-10.979,-2.133],[7.885,-3.917]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[986.617,293.714]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.836,0.449],[-0.437,0.287],[1.635,-0.524]],"o":[[0.499,-0.262],[-1.16,0.886],[1.023,-0.387]],"v":[[0.693,-0.219],[2.077,-1.03],[-2.078,1.03]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[996.903,294.607]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.828,-3.044],[0,0],[11.165,0.025],[8.558,7.136],[1.996,4.104],[0.062,0.636],[0,0],[-6.063,-0.474],[0.637,0.025],[-6.799,1.909],[-7.96,0.96]],"o":[[0,0],[0,0],[-7.486,-0.013],[-22.631,1.459],[0.037,-0.574],[0,0],[6.961,0.075],[-0.774,-0.012],[5.303,4.017],[7.822,6.113],[4.853,2.395]],"v":[[38.182,7.629],[38.145,7.679],[18.77,12.395],[-6.094,3.113],[-38.157,-10.473],[-38.182,-12.282],[-38.182,-12.42],[-18.595,-11.609],[-20.729,-11.671],[-2.102,-6.98],[23.648,-0.555]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[963.493,132.122]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.472,-1.098],[0.499,-0.262],[0,0]],"o":[[0,0],[-1.061,1.996],[-0.437,0.287],[0,0],[0,0]],"v":[[-4.086,-1.909],[4.086,-2.682],[0.393,1.871],[-0.992,2.682],[-2.028,1.622]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[998.588,291.706]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-7.411,1.385],[-2.882,2.546],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[5.265,0.985],[6.637,-1.247],[0,0],[0,0]],"v":[[23.561,6.019],[23.598,6.456],[-19.68,10.149],[-19.831,8.427],[-23.597,-3.037],[-23.448,-3.773],[-4.484,-4.174],[9.451,-10.149],[9.95,-9.588]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[982.718,266.112]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.212,-14.971],[0,0],[3.88,1.373],[0,0],[1.035,8.983],[1.909,-1.56],[-0.112,0.499],[-1.971,2.919],[-0.274,-0.15]],"o":[[0,0],[-4.117,-0.736],[0,0],[0.2,-12.014],[-2.034,1.984],[-0.262,-3.007],[0.063,-0.312],[3.693,-0.537],[0.449,0.262]],"v":[[10.998,22.643],[10.936,23.006],[-1.091,19.824],[-1.004,19.561],[-3.037,-9.944],[-10.161,-1.572],[-10.885,-11.678],[-4.572,-21.259],[7.492,-22.855]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1001.095,420.168]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-17.404,1.036],[0,0],[0.399,-0.112],[0.673,-1.572],[-0.537,-9.331],[-2.982,-6.1],[0,0],[3.431,0.648],[0,0],[0.449,0.262],[3.693,-0.537],[0.062,-0.312],[-0.262,-3.006],[0,0],[1.435,8.421],[0,0]],"o":[[0,0],[-0.4,0],[-1.559,0.449],[-2.658,6.15],[0.424,7.661],[0,0],[-3.518,-0.175],[0,0],[-0.213,-14.971],[-0.275,-0.15],[-1.971,2.919],[-0.112,0.499],[0,0],[-1.048,-8.584],[0,0],[9.731,-1.21]],"v":[[22.737,-28.239],[23.149,-21.639],[21.951,-21.477],[18.321,-18.233],[14.965,6.493],[19.98,27.964],[19.967,28.239],[9.525,27.004],[9.588,26.642],[6.082,-18.857],[-5.982,-17.26],[-12.295,-7.679],[-11.571,2.426],[-18.994,3.275],[-23.149,-24.621],[-22.001,-24.808]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1002.505,416.17]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.287,-5.602],[2.171,-0.112],[0.287,5.601],[-2.184,0.112]],"o":[[0.287,5.602],[-2.171,0.112],[-0.287,-5.602],[2.17,-0.112]],"v":[[3.93,-0.206],[0.524,10.149],[-3.93,0.206],[-0.511,-10.149]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1027.587,422.096]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[8.196,-7.223],[0,0],[0,0]],"v":[[19.786,14.609],[19.324,15.108],[-5.64,17.241],[-5.677,16.806],[-19.288,1.199],[-19.787,0.637],[-15.633,-16.73],[-15.159,-17.241]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1011.955,255.326]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.864,-2.445],[0,0],[40.222,51.961],[0,0],[-0.487,2.758],[1.172,15.258],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[-2.345,21.433],[0,0],[1.21,-1.959],[0,0],[0,0],[0,0],[0,0],[2.67,10.592],[3.955,6.338]],"v":[[32.967,-13.842],[32.705,-13.217],[-32.755,-9.699],[-32.967,-9.824],[-30.397,-16.874],[-29.823,-38.169],[-29.873,-38.942],[8.926,-41.687],[11.883,-42.262],[17.871,-26.629]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1003.279,344.409]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.147,-6.063],[0,0],[4.703,0.25],[0,0],[0.424,7.66],[0,0],[-2.171,0.112],[0.287,5.601]],"o":[[0.474,7.71],[0,0],[-4.716,0.611],[0,0],[-2.981,-6.101],[0,0],[0.287,5.602],[2.171,-0.113],[0,0]],"v":[[9.962,-11.565],[8.64,9.943],[8.752,10.792],[-5.433,11.315],[-5.421,11.041],[-10.436,-10.43],[-4.248,-10.792],[0.206,-0.848],[3.612,-11.203]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1027.905,433.093]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.133,-0.499],[0,0],[51.662,64.575],[0,0],[-1.435,2.395],[0,0],[-2.345,21.434],[0,0]],"o":[[0,0],[1.584,14.409],[0,0],[2.233,-1.435],[0,0],[40.222,51.962],[0,0],[2.021,0.849]],"v":[[38.164,-35.288],[38.001,-34.638],[-39.374,-27.279],[-39.586,-27.602],[-34.008,-33.279],[-33.797,-33.154],[31.664,-36.672],[31.925,-37.297]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1004.32,367.864]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.012,-0.349],[2.17,-0.112],[0.287,5.602],[0,0.45],[-1.983,0.087],[-0.461,-5.128]],"o":[[0.287,5.602],[-2.171,0.113],[-0.025,-0.474],[0,-4.965],[2.034,-0.1],[0.038,0.337]],"v":[[3.805,-0.206],[0.387,10.136],[-4.055,0.193],[-4.092,-1.192],[-0.649,-10.149],[3.73,-1.229]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1053.325,418.603]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.16,0.886],[0,0],[0,0],[0,0],[-10.604,-3.156],[-3.019,0.074],[-2.133,0.349],[-1.734,0.637],[-0.013,0]],"o":[[7.785,-5.065],[0,0],[0,0],[0,0],[2.233,0.786],[1.934,0.062],[2.345,-0.387],[0.025,-0.012],[1.634,-0.524]],"v":[[3.851,4.023],[10.051,-8.764],[-5.032,-7.342],[-37.02,-4.311],[-20.477,6.806],[-12.555,8.079],[-6.454,7.666],[-0.366,6.106],[-0.303,6.082]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[70.157,7.89],[20.032,12.595],[17.075,13.168],[-21.724,15.913],[-70.157,19.618],[-65.755,-10.41],[-64.533,-10.324],[-32.092,-13.293],[11.187,-16.986],[36.151,-19.119],[36.612,-19.618]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[995.13,289.554]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.699,-8.009],[0,0],[2.034,-0.1],[0,-4.965],[0,0],[-2.358,5.477],[-1.547,0.449],[-0.399,0],[-1.272,-1.846]],"o":[[0,0],[-0.461,-5.127],[-1.983,0.087],[0,0],[-0.138,-8.433],[0.687,-1.572],[0.399,-0.112],[2.071,0],[3.955,5.751]],"v":[[10.236,12.126],[4.185,12.625],[-0.194,3.706],[-3.637,12.662],[-10.099,12.713],[-6.644,-9.307],[-3.013,-12.55],[-1.816,-12.713],[3.586,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1052.869,404.748]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.2,-11.166],[0,0],[3.406,-2.171],[0,0],[0.537,5.939],[3.955,5.752],[2.071,0],[0,0],[-4.205,0.287]],"o":[[0,0],[-2.882,2.844],[0,0],[0.586,-5.365],[-0.698,-8.009],[-1.273,-1.846],[0,0],[6.313,-0.35],[3.518,18.788]],"v":[[10.374,16.461],[10.973,17.085],[1.528,24.634],[1.167,24.085],[1.391,6.742],[-5.259,-14.84],[-10.661,-18.097],[-10.973,-23.673],[5.096,-24.634]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1061.715,410.132]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.984,0.936],[0.012,0.012],[0.424,0.15],[0,0],[0,0],[0,0],[0,0],[0,0],[1.937,0.43],[0,0],[0,0],[4.728,7.673],[-47.047,13],[-20.822,-35.306],[-12.625,-32.923],[0,0],[7.909,-0.761],[0.387,-0.025],[7.623,1.821],[2.021,0.849],[3.955,6.337],[2.67,10.592],[0,0],[0,0],[0,0],[0,0],[0.062,0.05]],"o":[[-2.632,-4.554],[-0.025,-0.012],[-0.437,-0.175],[0,0],[0,0],[0,0],[0,0],[0,0],[1.938,0.43],[0,0],[0,0],[-4.342,-8.796],[-18.377,-38.537],[40.683,-11.253],[19.051,32.337],[0,0],[-3.368,-0.287],[-0.375,0.037],[-7.174,0.636],[-2.133,-0.499],[-5.864,-2.445],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.063,-0.037],[0,0]],"v":[[9.133,-19.188],[0.824,-25.887],[0.761,-25.912],[-0.523,-26.399],[-0.35,-26.861],[-17.379,-39.061],[-41.819,-56.564],[-46.348,-36.155],[-51.014,-15.084],[-57.617,21.496],[-62.018,51.525],[-66.271,51.762],[-79.87,26.873],[-47.707,-65.498],[52.535,-15.283],[98.246,73.806],[97.46,74.118],[79.558,75.866],[78.41,75.965],[55.492,74.929],[49.254,72.921],[34.158,60.134],[28.17,44.501],[74.929,39.798],[44.75,12.288],[9.806,-19.561],[9.332,-19.051],[9.145,-19.176]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[986.991,257.647]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.048,-8.584],[0.087,-2.27],[0,0],[4.528,10.018],[0.336,0.749],[0,0],[4.629,22.456],[0,0],[-1.696,1.123],[0,0],[1.584,14.409],[0,0],[-7.173,0.636],[0,0],[-13.711,-19.325],[0,0],[7.398,-7.298],[0,0],[3.518,18.789],[6.313,-0.349],[8.92,-0.536],[9.731,-1.21]],"o":[[1.435,8.421],[0.687,5.664],[0,0],[-9.681,-6.2],[-0.325,-0.711],[0,0],[0.886,-20.972],[0,0],[1.996,-0.686],[0,0],[51.662,64.574],[0,0],[7.623,1.822],[0,0],[1.335,23.666],[0,0],[-3.655,10.354],[0,0],[-0.199,-11.165],[-4.204,0.287],[-7.722,0.449],[-17.404,1.036],[0,0]],"v":[[-44.925,9.057],[-40.771,36.954],[-39.735,49.528],[-39.972,49.915],[-61.979,25.314],[-62.952,23.142],[-62.591,22.98],[-65.061,-39.41],[-65.111,-39.548],[-59.547,-42.23],[-59.334,-41.905],[18.04,-49.267],[18.202,-49.915],[41.12,-48.879],[41.133,-48.668],[64.313,17.553],[65.111,17.754],[48.406,44.725],[47.807,44.101],[42.53,3.007],[26.461,3.967],[0.961,5.439],[-43.777,8.871]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1024.281,382.492]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-10.542,-17.217],[0,0],[1.098,-3.106],[0,0],[1.335,23.667],[0,0],[-0.374,0.038],[0,0]],"o":[[0,0],[-0.724,3.269],[0,0],[-13.711,-19.325],[0,0],[0.387,-0.025],[0,0],[1.647,20.111]],"v":[[12.869,23.685],[13.368,23.798],[10.623,33.366],[9.825,33.168],[-13.355,-33.055],[-13.368,-33.267],[-12.22,-33.366],[-5.77,-33.342]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1078.769,366.878]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.372,-3.917],[3.443,-15.37],[0,0],[1.647,20.111],[0,0],[-3.368,-0.287],[0,0]],"o":[[5.489,15.645],[0,0],[-10.542,-17.216],[0,0],[7.91,-0.761],[0,0],[1.41,3.668]],"v":[[8.341,-18.258],[11.073,29.611],[10.573,29.499],[-8.065,-27.528],[-14.516,-27.552],[3.388,-29.299],[4.173,-29.611]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1081.064,361.064]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[14.272,-2.046],[0,0],[0,0],[0,0],[0,0],[0,0],[-9.606,1.372],[0,0],[0,0]],"o":[[3.131,2.358],[-17.054,10.005],[0,0],[-14.273,2.059],[-12.937,9.419],[3.643,0.037],[-10.28,0.636],[15.919,1.634],[0,0],[12.9,-1.859],[18.165,5.515],[-1.685,5.839]],"v":[[38.25,-6.544],[49.977,-2.901],[19.349,0.368],[3.281,13.317],[-17.542,6.793],[-47.184,11.047],[-37.153,4.835],[-49.978,-2.564],[-16.581,-11.834],[-1.598,-5.022],[13.885,-16.212],[47.807,-16.038]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1046.863,493.732]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-14.846,0.986],[0.012,-0.3],[26.436,-1.747],[-0.225,0.174]],"o":[[-0.013,0.287],[-0.05,1.197],[0.212,-0.187],[14.896,-0.986]],"v":[[22.631,-1.753],[22.594,-0.867],[-22.631,1.753],[-21.982,1.204]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1136.975,518.758]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.391,2.757],[4.624,-10.238],[4.778,-0.312]],"o":[[-0.599,9.22],[-4.073,3.633],[1.048,-17.615]],"v":[[8.64,-14.715],[2.661,8.661],[-8.64,14.715]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1168.245,502.29]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-32.661,6.088],[0.349,-5.364],[1.048,-17.616],[14.896,-0.985],[-13.699,1.385]],"o":[[-0.112,5.177],[-4.392,2.757],[-14.846,0.985],[6.2,-5.177],[0,0]],"v":[[31.289,-24.103],[30.603,-8.284],[13.324,21.147],[-31.289,24.103],[-2.158,13.374]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1146.282,495.859]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.162,0.025],[0,0],[1.011,-0.649],[-0.112,5.177]],"o":[[0,0],[0,0],[0.35,-5.365],[0.163,-0.038]],"v":[[0.362,-7.96],[0.811,7.012],[-0.811,7.96],[-0.125,-7.859]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1177.695,479.615]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.475,7.71],[4.329,6.263],[2.058,0],[0,0],[-7.722,0.45],[0,0],[0.399,-0.112],[0.686,-1.572],[-0.137,-8.434],[-2.982,-6.75],[0,0],[3.668,-0.474]],"o":[[1.148,-6.063],[-0.524,-8.746],[-1.26,-1.846],[0,0],[8.92,-0.537],[0,0],[-0.399,0],[-1.547,0.449],[-2.358,5.477],[0.138,8.271],[0,0],[-3.593,1.01],[0,0]],"v":[[-1.603,27.865],[-0.281,6.357],[-7.105,-17.385],[-12.494,-20.641],[-12.906,-27.24],[12.594,-28.713],[12.906,-23.136],[11.709,-22.974],[8.078,-19.73],[4.622,2.29],[9.189,25.894],[9.426,26.493],[-1.491,28.713]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1038.148,415.172]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[9.394,-3.668],[0,0],[65.173,27.584],[0,0],[0,0],[0,0],[-10.742,-20.323],[-0.611,-96.039]],"o":[[0,0],[0,0],[4.105,-129.161],[0,0],[11.166,0.025],[0,0],[52.461,32.986],[21.732,41.145],[0,0]],"v":[[95.789,159.876],[78.186,162.622],[77.861,161.797],[-97.685,-157.582],[-97.685,-157.856],[-78.31,-162.572],[-78.273,-162.622],[34.995,-41.932],[97.685,159.865]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1079.948,302.373]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.725,-0.05],[0,0],[0.037,-0.574],[4.778,-0.275],[1.073,4.741],[0.162,0.648]],"o":[[7.348,-0.262],[0,0],[0.062,0.637],[-0.325,5.465],[-6.138,0.337],[-0.025,-0.624],[0,0]],"v":[[-10.61,-4.891],[10.549,-5.202],[10.549,-5.065],[10.573,-3.256],[1.167,4.916],[-10.312,-2.295],[-10.586,-4.191]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[914.763,124.905]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.21,-1.959],[2.234,-1.434],[1.996,-0.686],[3.244,-0.449],[3.444,-0.299],[0,0],[5.951,12.076],[0,0],[0,0]],"o":[[1.173,15.258],[-0.486,2.757],[-1.435,2.395],[-1.696,1.123],[-2.969,1.048],[-3.718,0.512],[0,0],[-5.177,-12.488],[0,0],[0,0],[0,0]],"v":[[25.781,-19.862],[25.207,1.434],[22.637,8.483],[17.06,14.16],[11.496,16.842],[2.052,18.987],[-8.852,20.061],[-10.249,20.634],[-26.954,-16.693],[-26.467,-16.93],[25.731,-20.634]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[947.674,326.101]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-15.857,-0.724],[-3.618,-1.534],[4.716,-9.519],[0,0],[2.97,-2.234],[-7.273,1.635],[4.466,-0.623],[4.529,6.525],[0.012,0.024],[0.462,2.52],[-1.285,1.959]],"o":[[5.003,0.387],[-4.191,-1.085],[0,0],[0,0],[-0.174,2.944],[-2.956,1.198],[-18.651,2.595],[-0.025,-0.025],[-1.385,-2.333],[0,0],[4.529,-4.604]],"v":[[9.064,-18.208],[21.951,-15.052],[7.804,-5.483],[17.909,0.518],[8.814,6.22],[23.261,13.555],[12.208,16.337],[-20.441,4.485],[-20.491,4.411],[-23.261,-2.95],[-21.539,-6.306]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[961.434,246.038]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.718,0.512],[0,0],[0.162,-15.108],[5.539,13.349]],"o":[[3.443,-0.299],[0,0],[2.907,14.859],[-4.578,-11.477],[0,0]],"v":[[-6.281,-18.676],[4.622,-19.749],[4.647,-19.562],[7.516,19.749],[-7.679,-18.102]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[945.104,364.838]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.762,-3.967],[2.357,-0.2],[9.943,-0.649],[0,0],[-0.012,0.324],[-0.375,7.049],[0,0]],"o":[[-2.445,0.162],[-11.915,0.773],[-5.077,-20.548],[0,0],[0.113,-1.735],[33.46,4.841],[13.062,-0.387]],"v":[[36.117,19.106],[28.894,19.655],[-4.155,21.801],[-36.118,-6.394],[-36.093,-6.892],[-35.244,-21.801],[6.899,12.894]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[942.066,509.751]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.892,-1.397],[1.585,-0.45],[0,0],[0.137,8.271],[0,0],[-0.025,-0.474],[-2.171,0.112],[0.286,5.602],[0.037,0.337],[0,0],[0.586,-5.365],[0,0]],"o":[[-1.56,0.561],[0,0],[-2.982,-6.75],[0,0],[0,0.449],[0.287,5.602],[2.171,-0.113],[-0.013,-0.349],[0,0],[0.537,5.939],[0,0],[-3.406,2.184]],"v":[[-0.917,10.885],[-5.633,12.395],[-5.87,11.796],[-10.436,-11.808],[-3.974,-11.858],[-3.936,-10.474],[0.505,-0.53],[3.924,-10.873],[3.849,-11.896],[9.899,-12.395],[9.675,4.947],[10.037,5.495]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1053.206,429.27]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-11.914,0.773],[0.324,1.36],[0.037,0.112]],"o":[[-17.74,1.497],[-0.025,-0.113],[9.943,-0.649]],"v":[[16.524,-1.922],[-16.437,0.562],[-16.524,0.225]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[954.436,531.328]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.15,-0.599],[5.265,-0.374],[0.449,5.128],[0.038,0.562],[0,0],[-6.475,0.237],[0,0]],"o":[[0.15,4.978],[-5.365,0.387],[0.05,-0.536],[0,0],[6.825,-0.449],[0,0],[0.037,0.661]],"v":[[10.068,-3.674],[0.699,5.882],[-10.18,-2.751],[-10.168,-4.398],[-10.218,-5.246],[9.769,-6.269],[9.794,-5.57]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[894.384,126.283]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.067,1.148],[-4.255,0.063],[6.575,-0.449],[-5.377,0.649],[6.238,-6.513],[6.263,-0.96],[1.373,-5.863],[6.5,-5.689],[-4.966,-2.907],[2.234,-5.339],[-4.966,-0.05],[-4.803,-1.273],[-4.754,1.647],[-6.412,-3.58]],"o":[[4.067,-1.148],[-5.777,-3.218],[3.58,-3.954],[-8.571,-3.243],[-5.727,-2.695],[-6.113,0.949],[-8.596,-1.696],[5.277,-2.283],[-5.826,1.073],[3.606,-3.318],[4.978,0.062],[-0.088,-4.916],[6.936,-2.395],[1.51,-2.408]],"v":[[-38.406,-167.051],[-25.12,-168.486],[-44.757,-172.415],[-30.697,-179.626],[-55.96,-174.061],[-74.523,-176.744],[-88.41,-166.464],[-112.85,-160.001],[-96.182,-158.966],[-109.382,-148.474],[-95.633,-153.052],[-80.974,-150.432],[-71.692,-160.812],[-50.333,-158.916]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[-17.054,10.006],[3.132,2.357],[-1.685,5.839],[18.165,5.514],[12.899,-1.859],[0,0],[15.919,1.635],[-10.28,0.637],[3.643,0.038],[-12.938,9.419],[-14.273,2.058],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[-9.607,1.372],[0,0],[0,0],[0,0],[0,0],[0,0],[14.272,-2.046],[0,0]],"v":[[115.506,166.077],[103.779,162.434],[113.336,152.939],[79.414,152.766],[63.932,163.957],[48.948,157.145],[15.551,166.413],[28.376,173.811],[18.345,180.025],[47.988,175.771],[68.81,182.296],[84.878,169.345]],"c":true}},"nm":"P"},{"ind":2,"ty":"sh","ks":{"a":0,"k":{"i":[[-52.473,25.812],[9.956,24.44],[27.633,44.239],[18.501,-2.533],[7.647,-24.839],[-5.552,-18.152],[-9.581,-18.826],[0,0]],"o":[[53.346,-29.642],[-6.774,-18.801],[-42.281,-67.694],[-25.763,3.531],[-5.577,18.127],[7.548,24.665],[10.717,21.047],[22.905,57.188]],"v":[[89.62,126.704],[122.418,3.631],[71.929,-89.413],[-47.876,-149.247],[-99.463,-106.58],[-97.117,-54.332],[-64.706,12.638],[-38.993,80.12]],"c":true}},"nm":"P"},{"ind":3,"ty":"sh","ks":{"a":0,"k":{"i":[[9.182,-18.489],[0,0],[34.995,-2.271],[19.862,-2.433],[25.226,8.247],[0,0],[11.951,33.335],[38.75,35.231],[0,0],[6.911,13.836],[2.046,8.084],[0,0],[-6.251,0.2],[0.399,6.325],[-5.527,0.687],[0.462,5.714],[-5.751,0.436],[-0.499,5.664],[-5.365,0.387],[0.149,4.978],[-6.139,0.337],[-0.324,5.464],[-22.631,1.46],[-7.485,-0.012],[0,0],[4.105,-129.162],[0,0],[3.256,-24.403]],"o":[[0,0],[-30.229,2.008],[-7.173,-8.546],[0,0],[0,0],[-3.53,-44.476],[-22.307,-62.229],[0,0],[4.579,-8.771],[19.312,-6.799],[0,0],[1.136,5.564],[6.275,-0.212],[1.672,5.464],[5.776,-0.711],[1.31,5.564],[5.764,-0.425],[0.449,5.127],[5.264,-0.374],[1.073,4.74],[4.778,-0.275],[1.996,4.105],[8.558,7.136],[0,0],[65.173,27.584],[0,0],[-10.729,4.18],[0,0]],"v":[[116.592,195.77],[116.629,196.344],[13.342,203.105],[-25.632,190.467],[-54.376,155.847],[-52.929,155.71],[-78.329,33.735],[-180.481,-122.137],[-180.581,-122.187],[-180.181,-156.921],[-166.557,-194.01],[-166.445,-194.035],[-154.057,-183.78],[-143.952,-197.154],[-130.278,-187.598],[-121.221,-199.724],[-108.557,-190.242],[-97.13,-201.221],[-86.251,-192.588],[-76.882,-202.145],[-65.404,-194.934],[-55.997,-203.105],[-23.935,-189.52],[0.93,-180.237],[0.93,-179.962],[176.475,139.417],[176.8,140.24],[150.551,178.99]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[981.333,324.754]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.028,0.15],[0.187,4.117],[5.015,-0.15],[-0.199,-4.117]],"o":[[5.015,-0.15],[-0.188,-4.117],[-5.028,0.162],[0.187,4.117]],"v":[[5.04,-9.089],[13.786,-16.824],[4.354,-24.009],[-4.392,-16.262]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[27.584,13.648],[-46.235,6.85],[-0.786,-7.51],[0,0],[1.76,-17.017],[0.399,0.187],[0,0]],"o":[[-28.893,-26.798],[0,0],[3.718,0.799],[1.185,11.153],[0,0],[-1.734,16.655],[0,0],[0,0]],"v":[[40.134,37.584],[-46.971,-23.884],[34.645,-37.584],[45.786,-26.816],[22.893,-13.317],[36.99,11.335],[25.837,23.686],[40.509,37.171]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[739.797,171.022]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.774,-18.801],[53.347,-29.642],[22.905,57.189],[10.717,21.046],[7.548,24.664],[-5.577,18.128],[-25.762,3.531],[-42.281,-67.694]],"o":[[9.956,24.44],[-52.473,25.813],[0,0],[-9.581,-18.826],[-5.551,-18.153],[7.647,-24.839],[18.502,-2.532],[27.633,44.239]],"v":[[103.455,5.926],[70.656,128.999],[-57.956,82.415],[-83.669,14.934],[-116.081,-52.036],[-118.426,-104.285],[-66.839,-146.952],[52.966,-87.118]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.579,-11.477],[-2.658,-6.038],[-0.324,-0.711],[-9.681,-6.201],[-5.589,-1.934],[-4.117,-0.736],[-3.519,-0.174],[-4.715,0.612],[-3.593,1.01],[-1.56,0.562],[-3.406,2.183],[-2.882,2.844],[-3.655,10.355],[-0.724,3.269],[5.489,15.645],[1.41,3.668],[19.05,32.337],[40.684,-11.253],[-18.377,-38.537],[-4.341,-8.795],[-5.177,-12.488]],"o":[[3.144,7.872],[0.337,0.748],[4.529,10.018],[4.828,3.094],[3.88,1.372],[3.431,0.649],[4.703,0.25],[3.668,-0.474],[1.584,-0.449],[3.892,-1.397],[3.406,-2.171],[7.398,-7.298],[1.098,-3.106],[3.443,-15.37],[-1.372,-3.917],[-12.625,-32.923],[-20.822,-35.307],[-47.046,13],[4.728,7.673],[5.951,12.077],[5.54,13.349]],"v":[[-47.676,62.129],[-38.968,83.176],[-37.995,85.347],[-15.988,109.949],[-0.293,117.534],[11.733,120.715],[22.176,121.95],[36.36,121.426],[47.277,119.206],[51.993,117.696],[62.946,112.307],[72.39,104.759],[89.095,77.786],[91.84,68.217],[89.108,20.348],[84.941,8.995],[39.23,-80.094],[-61.013,-130.309],[-93.175,-37.939],[-79.577,-13.05],[-62.872,24.278]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1000.297,322.458]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.135,5.564],[0,0],[0.137,0.412],[-7.697,0.848],[-0.25,-0.761],[6.276,-0.212]],"o":[[0,0],[-0.35,-1.385],[7.585,-0.948],[0.025,0.786],[0.399,6.325],[-6.25,0.2]],"v":[[-10.997,-2.502],[-11.109,-2.477],[-11.895,-5.234],[11.085,-7.953],[11.497,-5.62],[1.391,7.753]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[825.886,133.22]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.335,-0.848],[-1.31,-1.36],[4.179,1.772]],"o":[[2.059,0.898],[-2.57,-1.747],[1.933,0.487]],"v":[[-0.05,-0.537],[5.04,2.845],[-5.04,-2.845]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[988.426,233.831]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[6.2,-5.177],[0.038,0],[5.963,-0.399],[0,0],[0,0],[-10.729,4.179],[0,0],[0,0],[0.063,-3.207],[0,0]],"o":[[-0.037,0.012],[-5.277,0.35],[0,0],[9.182,-18.489],[3.256,-24.402],[9.394,-3.668],[0,0],[0.025,3.131],[-32.661,6.088],[-13.699,1.385]],"v":[[-22.799,28.75],[-22.924,28.763],[-39.828,29.885],[-39.866,29.312],[-5.907,12.531],[20.342,-26.217],[37.944,-28.962],[39.842,-28.974],[39.778,-19.456],[6.332,18.022]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1137.792,491.211]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.05,-0.537],[5.764,-0.424],[1.31,5.564],[-0.013,0.012],[0.125,0.549],[0,0],[-7.959,0.511]],"o":[[-0.062,0.561],[-0.499,5.664],[-5.752,0.437],[0,0],[-0.05,-0.549],[0,0],[8.234,-0.761],[0,0]],"v":[[12.201,-6.107],[12.189,-4.46],[0.761,6.518],[-11.902,-2.963],[-11.902,-2.988],[-12.164,-4.635],[-12.202,-5.034],[12.151,-6.955]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[872.015,127.993]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.171,-0.112],[-0.287,-5.602],[0,0],[-2.658,6.15],[-1.559,0.449],[-0.4,0],[-1.26,-1.846],[-0.525,-8.745],[0,0]],"o":[[-2.183,0.112],[0,0],[-0.537,-9.332],[0.673,-1.572],[0.399,-0.112],[2.058,0],[4.329,6.263],[0,0],[-0.287,-5.601]],"v":[[-0.324,3.349],[-3.742,13.704],[-9.93,14.066],[-6.574,-10.66],[-2.945,-13.905],[-1.747,-14.066],[3.642,-10.811],[10.468,12.931],[4.116,13.293]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1027.4,408.597]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.829,3.094],[0,0],[0.686,5.664],[0,0],[-2.034,1.983],[0.2,-12.014]],"o":[[-5.589,-1.934],[0,0],[0.087,-2.271],[0,0],[1.909,-1.559],[1.035,8.982],[0,0]],"v":[[8.103,14.883],[-7.592,7.299],[-7.354,6.911],[-8.39,-5.664],[-0.967,-6.513],[6.157,-14.883],[8.19,14.622]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[991.9,425.109]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.907,-0.187],[-0.487,14.06],[0,0],[0,0],[-5.077,-20.547]],"o":[[8.147,-2.844],[0,0],[-0.012,0.325],[0,0],[-23.404,1.51]],"v":[[-21.414,15.732],[-10.648,-15.732],[-10.523,-15.732],[-10.549,-15.233],[21.414,12.962]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[916.497,518.59]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[33.46,4.841],[0.112,-1.735],[0,0],[0.062,4.965],[0.087,2.433],[0,0],[-5.514,-1.809],[0,0],[-7.173,-8.546],[7.647,-0.499],[-2.445,0.162],[13.062,-0.387]],"o":[[-0.374,7.049],[0,0],[0.212,-6.201],[-0.025,-2.433],[0,0],[7.773,-0.399],[25.226,8.246],[19.861,-2.433],[-8.109,0.536],[2.358,-0.2],[-6.762,-3.967],[0,0]],"v":[[-43.378,-15.682],[-44.226,-0.773],[-44.351,-0.773],[-44.301,-18.04],[-44.476,-25.326],[-43.079,-25.376],[-23.242,-23.03],[5.502,11.59],[44.476,24.228],[20.76,25.775],[27.983,25.226],[-1.235,19.013]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0,0.698,0.408,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[950.2,503.631]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-4.466,-1.56]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-10.605,-3.156]],"v":[[-18.196,-4.042],[13.792,-7.074],[13.792,-7.061],[18.196,0.512],[-0.668,2.296],[-8.777,3.069],[-1.653,7.074]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[976.306,289.285]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.06,1.996],[0,0],[0,0],[0,0],[0,0],[7.785,-5.066]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[1.472,-1.098]],"v":[[4.242,1.84],[-3.93,2.613],[-8.334,-4.959],[-8.334,-4.972],[6.75,-6.394],[0.549,6.394]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[998.431,287.183]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":80,"st":0},{"ind":23,"ty":4,"nm":"a","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.53,196.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33],[-1.52,-8.7]],"o":[[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33],[0,4.67]],"v":[[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22],[52.945,-11.41]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.52,-8.7],[2.2,0.33],[18.19,-7.67],[10.85,6.16],[-10.17,6.5],[-18.01,1.33]],"o":[[0,4.67],[-18.61,-2.32],[-24.82,9.99],[-11.12,-7.86],[10.18,-6.5],[18.02,-1.33]],"v":[[52.945,-11.41],[48.855,-5.73],[-7.545,1.83],[-41.825,17.17],[-29.705,-6.04],[18.515,-22]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[882.434,400.25]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":80,"st":0},{"ind":24,"ty":4,"nm":"b","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[106.53,61.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.88,24.951],[0,0],[0,0],[25.866,-7.144]],"o":[[0,0],[24.365,5.284],[0,0],[0,0],[-30.822,8.513]],"v":[[-33.188,8.953],[-9.998,-5.137],[12.312,-28.621],[28.163,-27.74],[7.321,20.108]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[894.218,513.63]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.189,4.119],[-5.021,0.155],[-0.188,-4.118],[5.022,-0.155]],"o":[[-0.189,-4.119],[5.022,-0.155],[0.189,4.119],[-5.021,0.155]],"v":[[-9.092,0.28],[-0.342,-7.458],[9.092,-0.281],[0.342,7.457]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[873.947,500.296]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-26.316,0.733],[-22.016,0.44],[7.682,30.609],[0,0],[0,0]],"o":[[1.018,18.715],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-42.772,-24.016],[-10.703,24.048],[27.606,22.728],[35.091,-24.387],[35.229,-24.662],[-42.766,-24.782]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.031,0.322,0.224,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[894.189,510.13]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":80,"st":0},{"ind":26,"ty":4,"nm":"a","parent":8,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-337.47,377.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.92,6.26],[-0.44,18.57],[2.07,4.77],[-6.4,3.28],[-3.12,-7.87],[0,-14],[10.37,-9.68],[4.19,4.89]],"o":[[6.93,-6.25],[0.6,-15.94],[-2.07,-4.77],[6.4,-3.28],[3.12,7.88],[-0.35,27.66],[-5.48,4.86],[-4.19,-4.89]],"v":[[-14.19,32.465],[7.93,-11.985],[3.24,-36.115],[4.43,-49.915],[20.26,-40.685],[24.46,-13.995],[-4.37,43.805],[-20.27,48.305]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1367.229,174.165]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.12,-7.87],[0,-14],[10.37,-9.68],[4.19,4.89],[-6.92,6.26],[-0.44,18.57],[2.07,4.77],[-6.4,3.28]],"o":[[3.12,7.88],[-0.35,27.66],[-5.48,4.86],[-4.19,-4.89],[6.93,-6.25],[0.6,-15.94],[-2.07,-4.77],[6.4,-3.28]],"v":[[20.26,-40.685],[24.46,-13.995],[-4.37,43.805],[-20.27,48.305],[-14.19,32.465],[7.93,-11.985],[3.24,-36.115],[4.43,-49.915]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1367.229,174.165]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":44,"op":50,"st":0},{"ind":27,"ty":4,"nm":"h","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-327.47,181.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6,3.3],[-3.14,1.95],[-1.46,-2.02],[0.11,-0.22],[0,0]],"o":[[1.73,-10.14],[6,-3.3],[3.15,-1.95],[1.4,1.95],[0,0],[0,0]],"v":[[-19.38,13.575],[-2.52,-2.815],[10.09,-11.625],[17.98,-11.425],[17.99,-6.595],[17.98,-6.585]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1356.769,387.245]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.49,1.76]],"o":[[8.06,-2.61],[0,0]],"v":[[-7.06,3.495],[7.06,-3.495]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1367.689,384.155]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.09,0],[2.34,-3],[0,0]],"o":[[1.87,-1.32],[4.39,0],[0,0],[0,0]],"v":[[-5.37,-1.205],[-0.15,-3.365],[3.03,3.355],[3.03,3.365]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1380.129,381.855]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.76,2.29]],"o":[[7.52,-0.89],[0,0]],"v":[[-8.52,2.91],[8.52,-2.91]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1374.639,388.13]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.74,0.55],[0.62,-5.61]],"o":[[1.08,-0.65],[3.32,-2.45],[0,0]],"v":[[-5.23,0.79],[-2.5,-1.03],[4.61,3.48]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1388.389,384.42]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-13.18,0.39],[-8.88,-2.35],[-0.13,3],[5.22,-0.13],[0,1.96],[-8.35,-0.26],[-3.79,6.27],[4.31,-1.31],[14.36,-0.13]],"o":[[-1.43,9.4],[13.18,-0.39],[6.78,0.65],[0.13,-3],[-5.22,0.14],[0,-1.96],[8.35,0.26],[3.78,-6.26],[-4.31,1.3],[0,0]],"v":[[-31.135,-3.98],[-15.205,16.25],[6.205,17.56],[14.035,12.99],[6.205,7.5],[-1.895,3.33],[6.855,-1.11],[28.785,-7.9],[24.475,-16.9],[3.985,-10.64]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1368.524,404.8]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.34,-3],[-0.74,0.55],[0.62,-5.61],[3.78,-6.26],[8.35,0.26],[0,-1.96],[-5.22,0.14],[0.13,-3],[6.78,0.65],[13.18,-0.39],[-1.43,9.4],[-6,3.3],[-3.14,1.95],[-1.46,-2.02],[0.11,-0.22],[-2.09,0]],"o":[[1.08,-0.65],[3.32,-2.45],[4.31,-1.31],[-3.79,6.27],[-8.35,-0.26],[0,1.96],[5.22,-0.13],[-0.13,3],[-8.88,-2.35],[-13.18,0.39],[1.73,-10.14],[6,-3.3],[3.15,-1.95],[1.4,1.95],[1.87,-1.32],[4.39,0]],"v":[[14.635,-13.13],[17.365,-14.95],[24.475,-10.44],[28.785,-1.44],[6.855,5.35],[-1.895,9.79],[6.205,13.96],[14.035,19.45],[6.205,24.02],[-15.205,22.71],[-31.135,2.48],[-14.275,-13.91],[-1.665,-22.72],[6.225,-22.52],[6.235,-17.69],[11.455,-19.85]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1368.523,398.34]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":50,"op":60,"st":0},{"ind":28,"ty":4,"nm":"a","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-307.47,72.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-5.08,2.86]],"o":[[0,0],[4.98,3.32],[0,0]],"v":[[-7.525,-2.78],[-7.515,-2.78],[7.525,-0.08]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1343.894,447.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.68,1.63]],"o":[[4.65,3.8],[0,0]],"v":[[-7.74,-2.515],[7.74,0.885]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1343.679,461.675]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.15,2.36]],"o":[[4.61,4.25],[0,0]],"v":[[-7.99,-2.95],[7.99,0.59]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1344.369,432.32]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.72,-16.11]],"o":[[-0.14,-13.51],[0,0]],"v":[[-7.92,5.085],[8.06,8.425]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1343.359,408.045]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.45,24.03],[-0.14,5.24],[0.14,4.94],[0.47,5.65]],"o":[[11.89,-18.09],[0.5,-4.92],[0.13,-4.67],[-0.16,-5.31],[0,0]],"v":[[-11.115,54.29],[10.025,-8.2],[10.985,-23.44],[10.955,-37.85],[10.015,-54.29]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1341.404,470.76]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.45,24.25],[-0.02,5.15],[0.17,5.37],[0.3,5.73]],"o":[[12.33,-18.83],[0.28,-4.59],[0.01,-4.79],[-0.16,-5.12],[0,0]],"v":[[-9.785,53.19],[9.335,-7.16],[9.775,-21.73],[9.535,-36.94],[8.835,-53.19]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1326.604,466.32]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.68,1.63],[0,0],[11.89,-18.09],[0,0],[-1.45,24.25]],"o":[[0,0],[-2.45,24.03],[0,0],[12.33,-18.83],[4.65,3.8]],"v":[[17.295,-29.545],[17.305,-29.545],[-3.835,32.945],[-17.305,27.405],[1.815,-32.945]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1334.124,492.105]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.08,2.86],[0,0],[0.5,-4.92],[0,0],[4.65,3.8],[-0.02,5.15]],"o":[[0,0],[-0.14,5.24],[0,0],[-5.68,1.63],[0.28,-4.59],[4.98,3.32]],"v":[[7.255,-7.1],[8.225,-7.07],[7.265,8.17],[7.255,8.17],[-8.225,4.77],[-7.785,-9.8]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1344.164,454.39]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.72,-16.11],[-0.16,-5.31],[4.61,4.25],[0,0],[0.3,5.73]],"o":[[0.47,5.65],[-6.15,2.36],[0,0],[-0.16,-5.12],[-0.14,-13.51]],"v":[[7.59,-0.975],[8.53,15.465],[-7.45,11.925],[-7.69,11.935],[-8.39,-4.315]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1343.828,417.445]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.15,2.36],[0.13,-4.67],[0,0],[4.98,3.32],[0.17,5.37],[0,0]],"o":[[0.14,4.94],[0,0],[-5.08,2.86],[0.01,-4.79],[0,0],[4.61,4.25]],"v":[[8.03,-6.85],[8.06,7.56],[7.09,7.53],[-7.95,4.83],[-8.19,-10.38],[-7.95,-10.39]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1344.329,439.76]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":50,"op":60,"st":0},{"ind":29,"ty":4,"nm":"a","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-236.47,7.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-8.38,11.87],[-5.84,-2.17],[7.86,-10.82],[21.86,-3.46],[1.34,4.81]],"o":[[30.14,-14.58],[6.71,-8.68],[5.85,2.17],[-15.05,21.51],[-3.83,0.29],[-1.33,-4.81]],"v":[[-34.315,26.33],[25.055,-29.36],[39.485,-38.52],[35.535,-18.38],[-34.685,40.4],[-44.005,35.65]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1289.524,551.75]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.84,-2.17],[7.86,-10.82],[21.86,-3.46],[1.34,4.81],[0,0],[-8.38,11.87]],"o":[[5.85,2.17],[-15.05,21.51],[-3.83,0.29],[-1.33,-4.81],[30.14,-14.58],[6.71,-8.68]],"v":[[39.485,-38.52],[35.535,-18.38],[-34.685,40.4],[-44.005,35.65],[-34.315,26.33],[25.055,-29.36]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1289.524,551.75]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":50,"op":60,"st":0}]},{"id":"comp_3","nm":"l","fr":24,"layers":[{"ind":1,"ty":3,"nm":"l","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[19]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":8,"s":[19]},{"i":{"x":[0.593],"y":[0.843]},"o":{"x":[0.175],"y":[0.072]},"t":9,"s":[19]},{"i":{"x":[0.698],"y":[1]},"o":{"x":[0.351],"y":[1.186]},"t":10,"s":[6.793]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[4]},{"t":15,"s":[-34]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":1,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":4,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":7,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":8,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.593,"y":0.593},"o":{"x":0.167,"y":0.167},"t":9,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.698,"y":0.698},"o":{"x":0.351,"y":0.351},"t":10,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":12,"s":[-79,97,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[-79,97,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":1,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":8,"s":[100,100,100]},{"i":{"x":[0.593,0.593,0.593],"y":[1,1,1]},"o":{"x":[0.175,0.175,0.175],"y":[0,0,0]},"t":9,"s":[100,100,100]},{"i":{"x":[0.698,0.698,0.698],"y":[1,1,1]},"o":{"x":[0.351,0.351,0.351],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[100,100,100]},{"t":15,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":2,"ty":3,"nm":"l","parent":3,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[-6]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[6]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[11]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[39]},{"i":{"x":[0.593],"y":[1]},"o":{"x":[0.175],"y":[0]},"t":9,"s":[-5]},{"i":{"x":[0.698],"y":[1]},"o":{"x":[0.351],"y":[0]},"t":10,"s":[-5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[-5]},{"t":15,"s":[-14]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":1,"s":[10,135,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":4,"s":[10,135,0],"to":[-0.206,-0.114,0],"ti":[0.564,0.209,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":7,"s":[8.763,134.314,0],"to":[-0.564,-0.209,0],"ti":[-0.206,-0.114,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[6.619,133.749,0],"to":[0.206,0.114,0],"ti":[-0.564,-0.209,0]},{"i":{"x":0.593,"y":0.593},"o":{"x":0.167,"y":0.167},"t":9,"s":[10,135,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.698,"y":0.698},"o":{"x":0.351,"y":0.351},"t":10,"s":[10,135,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":12,"s":[10,135,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[10,135,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":1,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":8,"s":[100,100,100]},{"i":{"x":[0.593,0.593,0.593],"y":[1,1,1]},"o":{"x":[0.175,0.175,0.175],"y":[0,0,0]},"t":9,"s":[100,100,100]},{"i":{"x":[0.698,0.698,0.698],"y":[1,1,1]},"o":{"x":[0.351,0.351,0.351],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[100,100,100]},{"t":15,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":3,"ty":3,"nm":"l","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[16]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[16]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[-54]},{"i":{"x":[0.593],"y":[0.843]},"o":{"x":[0.175],"y":[0.072]},"t":9,"s":[-65]},{"i":{"x":[0.698],"y":[1]},"o":{"x":[0.351],"y":[1.186]},"t":10,"s":[-93.482]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[-100]},{"t":15,"s":[-81]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[993,865,0],"to":[-4,-9.5,0],"ti":[-3.5,-10,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":4,"s":[969,808,0],"to":[3.5,10,0],"ti":[-3.833,-15.833,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":7,"s":[1014,925,0],"to":[3.833,15.833,0],"ti":[-1.333,7.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[992,903,0],"to":[1.333,-7.667,0],"ti":[-1.5,15,0]},{"i":{"x":0.593,"y":0.843},"o":{"x":0.167,"y":0.167},"t":9,"s":[1022,879,0],"to":[1.036,-10.364,0],"ti":[6.778,15.785,0]},{"i":{"x":0.698,"y":1},"o":{"x":0.296,"y":1},"t":10,"s":[1009.1,821.8,0],"to":[-3.032,-7.061,0],"ti":[2.112,-2.266,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":12,"s":[1001,813,0],"to":[-6.833,7.333,0],"ti":[3.333,-18.333,0]},{"t":15,"s":[981,923,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":1,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":8,"s":[100,100,100]},{"i":{"x":[0.593,0.593,0.593],"y":[1,1,1]},"o":{"x":[0.175,0.175,0.175],"y":[0,0,0]},"t":9,"s":[100,100,100]},{"i":{"x":[0.698,0.698,0.698],"y":[1,1,1]},"o":{"x":[0.351,0.351,0.351],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[100,100,100]},{"t":15,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":4,"ty":3,"nm":"l","parent":5,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,171,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":5,"ty":3,"nm":"l","parent":6,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[114,137,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":6,"ty":3,"nm":"l","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":2},"p":{"a":0,"k":[1005,948,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":16,"st":0},{"ind":7,"ty":4,"nm":"l","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[353.53,-209.39,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.87],[3.87,0],[0,3.88],[-3.87,0]],"o":[[0,3.88],[-3.87,0],[0,-3.87],[3.87,0]],"v":[[7.01,0],[0,7.01],[-7.01,0],[0,-7.01]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[653.369,810.09]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.57,-4.41],[-3.65,-27.85],[-5.48,0],[0,0]],"o":[[-4.08,-2.78],[-3.57,4.42],[4.7,24.38],[5.48,0],[0,0]],"v":[[9.305,-42.03],[-4.715,-37.92],[-12.695,11.43],[10.865,44.81],[16.345,40.13]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[638.504,835.55]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.67,6.05]],"o":[[5.61,2.49],[0,0]],"v":[[-8.92,1.38],[8.92,-3.87]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[660.379,853.62]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5,3.48]],"o":[[5.97,3.15],[0,0]],"v":[[-9.235,-0.935],[9.235,-2.215]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[657.774,844.495]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.18,3.71],[-0.03,0.02]],"o":[[3.23,2.81],[0.03,-0.01],[0,0]],"v":[[-8.855,-2.215],[8.765,-1.495],[8.855,-1.545]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[657.064,833.335]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.13,-1.55],[3.22,-8.76],[-3.27,-12.43],[-8.88,-1.56],[-3.14,2.01],[2.23,7.26],[0.41,1.22],[0.21,4.39],[-1.83,3.66]],"o":[[-6.1,0.15],[-4.96,1.85],[-5.89,16.08],[2.85,11.54],[3.48,0.62],[8.64,-5.55],[-0.63,-2.07],[-0.94,-3.96],[-0.29,-6.33],[0,0]],"v":[[11.25,-42.18],[-3.93,-40.41],[-15.9,-25.83],[-17.53,19.4],[3.04,41.56],[13.15,39.62],[17.49,15.64],[15.8,10.61],[14.02,-2.27],[16.15,-18.31]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[651.809,834.11]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-8.88,-1.56],[0,0],[5.48,0],[4.7,24.38],[-3.57,4.42],[-4.08,-2.78],[0,0],[3.22,-8.76],[-3.27,-12.43]],"o":[[0,0],[0,0],[-5.48,0],[-3.65,-27.85],[3.57,-4.41],[0,0],[-4.96,1.85],[-5.89,16.08],[2.85,11.54]],"v":[[16.345,40.12],[16.345,40.13],[10.865,44.81],[-12.695,11.43],[-4.715,-37.92],[9.305,-42.03],[9.375,-41.85],[-2.595,-27.27],[-4.225,17.96]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[638.504,835.55]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.87,0],[0,-3.87],[3.87,0],[0,3.88]],"o":[[3.87,0],[0,3.88],[-3.87,0],[0,-3.87]],"v":[[0,-7.01],[7.01,0],[0,7.01],[-7.01,0]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[653.369,810.09]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,3.88],[3.87,0],[0,-3.87],[-3.87,0]],"o":[[0,-3.87],[-3.87,0],[0,3.88],[3.87,0]],"v":[[8.57,-24.02],[1.56,-31.03],[-5.45,-24.02],[1.56,-17.01]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.29,-6.33],[-0.94,-3.96],[-0.63,-2.07],[8.64,-5.55],[3.48,0.62],[2.85,11.54],[-5.89,16.08],[-4.96,1.85],[-6.1,0.15],[0,0]],"o":[[0.21,4.39],[0.41,1.22],[2.23,7.26],[-3.14,2.01],[-8.88,-1.56],[-3.27,-12.43],[3.22,-8.76],[4.13,-1.55],[0,0],[-1.83,3.66]],"v":[[14.02,-2.27],[15.8,10.61],[17.49,15.64],[13.15,39.62],[3.04,41.56],[-17.53,19.4],[-15.9,-25.83],[-3.93,-40.41],[11.25,-42.18],[16.15,-18.31]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"fl","c":{"a":0,"k":[0.996,0.839,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[651.809,834.11]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":1,"op":16,"st":0},{"ind":8,"ty":4,"nm":"l","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[224.53,-162.39,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.28,-2.57]],"o":[[-0.74,3.44],[0,0]],"v":[[-0.14,-4.455],[0.88,4.455]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[673.919,796.385]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.82,-11.57]],"o":[[11.77,-3.09],[0,0]],"v":[[-9.94,-3.275],[9.12,6.365]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[684.739,804.115]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.04,-4.79]],"o":[[1.34,6.88],[0,0]],"v":[[-4.355,-8.905],[4.355,8.905]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[746.554,785.915]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.55,7.69]],"o":[[-3.12,-3.73],[0,0]],"v":[[4.335,9.085],[-4.335,-9.085]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[738.144,789.425]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.42,-5.91]],"o":[[0.61,6.84],[0,0]],"v":[[-3.86,-9.71],[3.86,9.71]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[730.019,792.67]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.9,-5.76]],"o":[[0.83,5.76],[0,0]],"v":[[-4.185,-8.42],[4.185,8.42]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[754.804,781.74]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.04,-0.04],[14.57,-7.41],[2.97,-1.28],[0,0],[2.62,-1.01],[0.31,-0.11],[2.4,-0.81],[26.95,-1.17],[3.58,-0.11],[-2.74,-8.72],[-5.32,2.37],[-16.13,1.82],[-1.12,0.14],[-12.94,4.79],[-3.1,1.39],[-1.86,0.9],[-0.99,0.52],[-2.74,1.67],[-5.43,6.05]],"o":[[-0.04,0.04],[-11.85,10.76],[-2.59,1.32],[0,0],[-2.33,1.01],[-0.32,0.11],[-2.73,0.94],[-15.05,5.03],[-3.1,0.14],[-6.17,0.42],[2.73,8.72],[4.17,-4.04],[1.03,-0.12],[14.02,-1.72],[2.74,-1.01],[1.71,-0.76],[0.97,-0.47],[2.65,-1.38],[18.46,-11.15],[0,0]],"v":[[58.025,-35.74],[57.895,-35.62],[22.145,-9.36],[13.825,-5.46],[13.825,-5.45],[6.405,-2.42],[5.455,-2.09],[-2.195,0.53],[-54.595,9.14],[-64.605,9.5],[-71.285,25],[-60.395,33.37],[-34.495,28.05],[-31.265,27.66],[5.525,19.95],[14.255,16.37],[19.615,13.88],[22.565,12.4],[30.685,7.81],[74.025,-25.71]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[728.354,782.43]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.28,-2.57],[0.82,-11.57],[4.17,-4.04],[2.73,8.72],[-6.17,0.42],[-3.1,0.14],[0,0]],"o":[[11.77,-3.09],[-16.13,1.82],[-5.32,2.37],[-2.74,-8.72],[3.58,-0.11],[0,0],[-0.74,3.44]],"v":[[0.295,-4.03],[19.355,5.61],[-6.545,10.93],[-17.435,2.56],[-10.755,-12.94],[-0.745,-13.3],[-0.725,-12.94]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.996,0.839,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[674.504,804.87]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-15.05,5.03],[-4.42,-5.91],[14.02,-1.72],[1.03,-0.12],[11.77,-3.09],[-0.74,3.44],[0,0]],"o":[[0.61,6.84],[-12.94,4.79],[-1.12,0.14],[0.82,-11.57],[-1.28,-2.57],[0,0],[26.95,-1.17]],"v":[[22.7,-13.76],[30.42,5.66],[-6.37,13.37],[-9.6,13.76],[-28.66,4.12],[-29.68,-4.79],[-29.7,-5.15]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[703.459,796.72]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.12,-3.73],[0,0],[2.74,-1.01],[0.61,6.84],[-2.73,0.94]],"o":[[0,0],[-3.1,1.39],[-4.42,-5.91],[2.4,-0.81],[1.55,7.69]],"v":[[8.095,7.15],[8.225,7.44],[-0.505,11.02],[-8.225,-8.4],[-0.575,-11.02]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[734.384,791.36]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.04,-4.79],[0,0],[0.97,-0.47],[1.71,-0.76],[0,0],[1.55,7.69],[-0.32,0.11],[-2.33,1.01],[0,0]],"o":[[0,0],[-0.99,0.52],[-1.86,0.9],[0,0],[-3.12,-3.73],[0.31,-0.11],[2.62,-1.01],[0,0],[1.34,6.88]],"v":[[8.545,6.93],[8.555,6.94],[5.605,8.42],[0.245,10.91],[0.115,10.62],[-8.555,-7.55],[-7.605,-7.88],[-0.185,-10.91],[-0.165,-10.88]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[742.364,787.89]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.9,-5.76],[0,0],[2.65,-1.38],[0,0],[1.34,6.88],[0,0],[0,0],[-2.59,1.32],[0,0]],"o":[[0,0],[-2.74,1.67],[0,0],[-5.04,-4.79],[0,0],[0,0],[2.97,-1.28],[0,0],[0.83,5.76]],"v":[[8.38,6.21],[8.43,6.29],[0.31,10.88],[0.3,10.87],[-8.41,-6.94],[-8.43,-6.97],[-8.43,-6.98],[-0.11,-10.88],[0.01,-10.63]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[750.609,783.95]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[18.46,-11.15],[0,0],[0.83,5.76],[0,0],[-11.85,10.76]],"o":[[0,0],[0,0],[-5.43,6.05],[0,0],[-4.9,-5.76],[0,0],[14.57,-7.41],[0,0]],"v":[[9.9,-21.575],[25.98,-11.945],[25.9,-11.805],[-17.44,21.715],[-17.49,21.635],[-25.86,4.795],[-25.98,4.545],[9.77,-21.715]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[776.479,768.525]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":1,"op":16,"st":0},{"ind":9,"ty":4,"nm":"l","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[184.53,-77.39,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.88,0],[0.42,-9.78],[14.11,-21.77],[-6.21,-7.49],[-6.67,6.4],[-8.91,14.32],[0.72,10.97]],"o":[[-7.79,0],[-0.42,9.78],[-14.11,21.78],[4.01,5.64],[5.38,-4.95],[16.59,-28.29],[-0.72,-10.97]],"v":[[20.42,-52.47],[10.32,-36.16],[-8.19,13.2],[-25.76,46.83],[-8.19,45.01],[14.51,14.79],[31.25,-39.33]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[810.569,711.71]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.72,-10.97],[16.59,-28.29],[5.38,-4.95],[4.01,5.64],[-14.11,21.78],[-0.42,9.78],[-7.79,0]],"o":[[0.72,10.97],[-8.91,14.32],[-6.67,6.4],[-6.21,-7.49],[14.11,-21.77],[0.42,-9.78],[4.88,0]],"v":[[31.25,-39.33],[14.51,14.79],[-8.19,45.01],[-25.76,46.83],[-8.19,13.2],[10.32,-36.16],[20.42,-52.47]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[810.569,711.71]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":1,"op":16,"st":0},{"ind":10,"ty":4,"nm":"l","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-272.47,-255.39,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.09],[4.08,0],[0,4.09],[-4.09,0]],"o":[[0,4.09],[-4.09,0],[0,-4.09],[4.08,0]],"v":[[7.4,0],[0,7.4],[-7.4,0],[0,-7.4]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1292.479,858.84]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.71,4.93]],"o":[[1.52,-7.73],[0,0]],"v":[[0.135,9.5],[-1.655,-9.5]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1331.114,855.78]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.42,-7.86]],"o":[[1.88,4.97],[0,0]],"v":[[-1.335,-9.375],[-0.085,9.375]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1341.204,854.165]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.89,6.41]],"o":[[1.97,-6.4],[0,0]],"v":[[-1.005,9.605],[-0.885,-9.605]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1320.884,857.185]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-7.27,-4.65],[-25.22,0.66],[-4.16,4.3],[3.44,1.87]],"o":[[-3.96,1.59],[7.27,4.64],[24.66,0.06],[4.15,-4.3],[0,0]],"v":[[-44.125,-8.175],[-40.285,3.765],[1.895,10.145],[43.935,-1.525],[43.935,-10.805]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1315.384,874.345]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.79,-6.43],[-5.04,-2.26],[-12.46,5.79],[-1.81,3.86],[0.59,3.54],[11.85,-1.75],[2.06,-0.35],[3.07,-0.26],[5.42,0.88]],"o":[[-3.45,6.89],[1.28,2.99],[15.88,7.12],[6.96,-3.23],[1.45,-3.06],[-1.33,-8.01],[-2.43,0.36],[-3.38,0.56],[-4.14,0.35],[0,0]],"v":[[-38.64,-17.155],[-43.44,3.815],[-34.34,11.785],[31.99,11.785],[44.62,1.185],[45.64,-8.695],[21.45,-17.155],[14.76,-16.075],[5.3,-14.775],[-8.52,-15.375]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1314.698,862.355]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.09,0],[0,-4.09],[4.08,0],[0,4.09]],"o":[[4.08,0],[0,4.09],[-4.09,0],[0,-4.09]],"v":[[0,-7.4],[7.4,0],[0,7.4],[-7.4,0]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1292.479,858.84]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.81,3.86],[4.15,-4.3],[24.66,0.06],[7.27,4.64],[-3.96,1.59],[-5.04,-2.26],[-12.46,5.79]],"o":[[3.44,1.87],[-4.16,4.3],[-25.22,0.66],[-7.27,-4.65],[1.28,2.99],[15.88,7.12],[6.96,-3.23]],"v":[[43.935,-10.805],[43.935,-1.525],[1.895,10.145],[-40.285,3.765],[-44.125,-8.175],[-35.025,-0.205],[31.305,-0.205]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1315.384,874.345]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,4.09],[4.08,0],[0,-4.09],[-4.09,0]],"o":[[0,-4.09],[-4.09,0],[0,4.09],[4.08,0]],"v":[[-14.82,-3.515],[-22.22,-10.915],[-29.62,-3.515],[-22.22,3.885]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.38,0.56],[-2.43,0.36],[-1.33,-8.01],[1.45,-3.06],[6.96,-3.23],[15.88,7.12],[1.28,2.99],[-3.45,6.89],[0,0],[-4.14,0.35]],"o":[[2.06,-0.35],[11.85,-1.75],[0.59,3.54],[-1.81,3.86],[-12.46,5.79],[-5.04,-2.26],[-2.79,-6.43],[0,0],[5.42,0.88],[3.07,-0.26]],"v":[[14.76,-16.075],[21.45,-17.155],[45.64,-8.695],[44.62,1.185],[31.99,11.785],[-34.34,11.785],[-43.44,3.815],[-38.64,-17.155],[-8.52,-15.375],[5.3,-14.775]],"c":true}},"nm":"P"},{"ty":"mm","mm":1,"nm":"M"},{"ty":"fl","c":{"a":0,"k":[0.996,0.839,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1314.699,862.355]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":1,"st":0},{"ind":11,"ty":4,"nm":"l","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-318.47,-134.39,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-13.78,-0.14],[0,0]],"o":[[5.39,4.71],[0,0],[0,0]],"v":[[-11.665,-3.32],[11.595,3.32],[11.665,3.32]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1330.394,784.82]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-10.94,-0.02]],"o":[[4.88,4.66],[0,0]],"v":[[-11.595,-3.715],[11.595,3.715]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1327.094,792.145]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-10.49,0.76]],"o":[[4.87,6.32],[0,0]],"v":[[-11.525,-4.55],[11.525,3.79]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1323.494,799.4]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-9.69,1.43]],"o":[[6.2,3.77],[0,0]],"v":[[-11.62,-2.91],[11.62,1.48]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1333.009,778.23]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.89,-2.26]],"o":[[3.16,2.26],[0,0]],"v":[[-6.79,-3.385],[6.79,3.385]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1289.779,838.855]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.64,-7.83]],"o":[[7.52,-12.63],[0,0]],"v":[[-10.71,9.56],[10.71,-1.73]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1307.279,832.68]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.27,-12.72],[2.21,-6.83],[0.92,-2.19],[1.25,-2.43],[1.32,-2.24],[2.29,-3.36],[5.58,-7.23],[0.9,-1.82],[-8.27,-0.63],[-10.81,13.47],[-4.47,6.49],[-5.06,9.57],[-1.13,2.41],[-0.95,2.49],[-0.61,2.63],[7.6,26.4]],"o":[[3.32,13.67],[-0.59,5.85],[-0.65,2.01],[-0.91,2.2],[-1.04,2.05],[-1.74,2.97],[-9.12,13.39],[-3.56,4.62],[-2.32,4.7],[8.27,0.64],[3.16,-3.93],[5.75,-8.36],[1.31,-2.47],[1.24,-2.65],[1.13,-2.97],[4.77,-20.67],[0,0]],"v":[[10.655,-65.52],[13.215,-33.08],[9.565,-14.48],[7.235,-8.19],[4.005,-1.26],[0.475,5.16],[-5.545,14.63],[-28.505,45.78],[-35.435,55.51],[-31.315,70.61],[-5.315,57.29],[6.495,41.26],[23.525,13.5],[27.195,6.17],[30.495,-1.55],[33.135,-9.98],[31.985,-71.25]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1311.494,789.69]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.89,-2.26],[-6.64,-7.83],[3.16,-3.93],[8.27,0.64],[-2.32,4.7],[-3.56,4.62]],"o":[[7.52,-12.63],[-4.47,6.49],[-10.81,13.47],[-8.27,-0.63],[0.9,-1.82],[3.16,2.26]],"v":[[1.62,0.21],[23.04,-11.08],[11.23,4.95],[-14.77,18.27],[-18.89,3.17],[-11.96,-6.56]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.996,0.839,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1294.948,842.03]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.74,2.97],[-10.49,0.76],[5.75,-8.36],[7.52,-12.63],[3.16,2.26],[-9.12,13.39]],"o":[[4.87,6.32],[-5.06,9.57],[-6.64,-7.83],[-5.89,-2.26],[5.58,-7.23],[2.29,-3.36]],"v":[[2.965,-23.695],[26.015,-15.355],[8.985,12.405],[-12.435,23.695],[-26.015,16.925],[-3.055,-14.225]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1309.004,818.545]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-10.94,-0.02],[1.31,-2.47],[4.87,6.32],[-1.04,2.05]],"o":[[-1.13,2.41],[-10.49,0.76],[1.32,-2.24],[4.88,4.66]],"v":[[13.36,-0.33],[9.69,7],[-13.36,-1.34],[-9.83,-7.76]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1325.329,796.19]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-13.78,-0.14],[1.24,-2.65],[4.88,4.66],[-0.91,2.2]],"o":[[-0.95,2.49],[-10.94,-0.02],[1.25,-2.43],[5.39,4.71]],"v":[[13.245,-0.54],[9.945,7.18],[-13.245,-0.25],[-10.015,-7.18]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1328.744,788.68]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-9.69,1.43],[1.13,-2.97],[5.39,4.71],[-0.65,2.01],[0,0]],"o":[[-0.61,2.63],[-13.78,-0.14],[0.92,-2.19],[0,0],[6.2,3.77]],"v":[[12.95,-1.965],[10.31,6.465],[-12.95,-0.175],[-10.62,-6.465],[-10.29,-6.355]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1331.679,781.675]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.77,-20.67],[6.2,3.77],[0,0],[-0.59,5.85],[3.32,13.67]],"o":[[7.6,26.4],[-9.69,1.43],[0,0],[2.21,-6.83],[1.27,-12.72],[0,0]],"v":[[7.41,-31.35],[8.56,29.92],[-14.68,25.53],[-15.01,25.42],[-11.36,6.82],[-13.92,-25.62]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1336.069,749.79]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":1,"st":0},{"ind":12,"ty":4,"nm":"l","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-8},"p":{"a":0,"k":[-294.274,-127.049,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,176,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.86,18.12]],"o":[[4.86,18.11],[0,0]],"v":[[-13.095,-6.19],[8.235,-11.92]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1335.244,730.36]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-9.81,-9.55]],"o":[[-10.99,-7.08],[0,0]],"v":[[13.125,-2.715],[-3.315,9.795]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1267.284,637.015]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[27.65,20.4]],"o":[[-13.33,-35.3],[0,0]],"v":[[31.535,42.07],[-31.535,-42.07]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1311.944,676.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[23.79,22.12]],"o":[[-12.16,-31.02],[0,0]],"v":[[29.09,38.68],[-29.09,-38.68]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1293.059,685.49]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-13.33,-35.3],[4.86,18.11],[23.79,22.12],[-10.99,-7.08]],"o":[[4.86,18.12],[-12.16,-31.02],[-9.81,-9.55],[27.65,20.4]],"v":[[42.23,33.69],[20.9,39.42],[-37.28,-37.94],[-20.84,-50.45]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1301.249,684.75]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":1,"st":0}]},{"id":"comp_4","nm":"u","fr":24,"layers":[{"ind":1,"ty":3,"nm":"h","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[82.5,-21.5,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":2,"ty":3,"nm":"a","parent":3,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":44,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":64,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":68,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":76,"s":[0]},{"t":80,"s":[-10]}]},"p":{"a":0,"k":[148,23,0],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":3,"ty":3,"nm":"a","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[152]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":12,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[152]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[152]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":44,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[152]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":64,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":68,"s":[152]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[89]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":76,"s":[0]},{"t":80,"s":[89]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[1132,358.5,0],"to":[0,-0.833,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":28,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[1132,358.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76,"s":[1132,353.5,0],"to":[0,0,0],"ti":[0,-0.833,0]},{"t":80,"s":[1132,358.5,0]}],"l":2},"a":{"a":0,"k":[50,50,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":80,"st":0},{"ind":4,"ty":4,"nm":"h","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-246.97,338.11,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.01,-3.81],[0,0]],"o":[[-4.07,-4.27],[-3.01,3.81],[0,0]],"v":[[7.035,-2.385],[-4.025,-1.525],[-6.335,6.655]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1256.284,224.005]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.79,2.34]],"o":[[2.34,0.83],[0,0]],"v":[[-3.33,-0.2],[3.33,-1.17]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1265.639,242.16]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.86,-2.46],[0.64,-1.17],[-0.49,-1.89],[0,0]],"o":[[-4,-3.97],[-0.96,0.83],[-2.55,4.64],[0,0],[0,0]],"v":[[7.95,-3.705],[-2.97,-4.695],[-5.4,-1.655],[-7.37,7.665],[-7.37,7.675]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1266.479,226.535]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.01,0],[3.34,-2.1],[0.87,-1.23],[-2.19,-4.06],[-0.58,-0.48],[-0.18,0.28],[0,0]],"o":[[0,0],[-2.89,-4.76],[-1.23,0.76],[-2.76,3.95],[0.35,0.67],[4.39,3.17],[0,0],[0,0]],"v":[[9.105,-7.665],[9.095,-7.675],[-1.395,-10.435],[-4.595,-7.375],[-6.915,7.625],[-5.515,9.365],[2.055,7.855],[2.065,7.845]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1275.884,233.365]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.43,4.27],[-0.06,0.13],[2.7,1.95]],"o":[[2.7,2.32],[0.07,-0.12],[1.29,-2.82],[0,0]],"v":[[-7.1,1.37],[5.62,1.74],[5.81,1.37],[2.42,-6.01]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1256.689,240.22]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.7,0.57],[1.23,0.04],[1.21,-6.18],[-12.11,-3.78],[-8.62,14.11],[4.17,1.79],[1.87,-0.89],[0.96,-3.7],[-0.39,-1.74],[-1,-0.54],[-0.59,7.74]],"o":[[-1.85,-1.34],[-1,-0.33],[-3.88,-0.14],[-1.59,8.15],[13.19,3.27],[7.15,-13.9],[-1.66,-0.71],[-2.83,1.35],[-0.87,3.36],[0.33,1.46],[2.18,1.2],[0,0]],"v":[[-9.74,-9.17],[-15.48,-12.1],[-18.9,-12.71],[-28.39,-4.96],[-11.12,15.5],[22.83,4.38],[21.64,-18.06],[16.13,-17.68],[9.73,-9.72],[9.09,-2.15],[11.12,0.8],[19.73,-7.63]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1268.849,243.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.18,0.28],[-0.87,3.36],[-2.83,1.35],[-1.66,-0.71],[7.15,-13.9],[13.19,3.27],[-1.59,8.15],[-3.88,-0.14],[-1,-0.33],[-1.85,-1.34],[0,0],[1.29,-2.82],[0.07,-0.12],[-2.79,2.34],[-0.58,-0.48]],"o":[[-0.39,-1.74],[0.96,-3.7],[1.87,-0.89],[4.17,1.79],[-8.62,14.11],[-12.11,-3.78],[1.21,-6.18],[1.23,0.04],[1.7,0.57],[0,0],[2.7,1.95],[-0.06,0.13],[2.34,0.83],[0.35,0.67],[4.39,3.17]],"v":[[9.09,-2.15],[9.73,-9.72],[16.13,-17.68],[21.64,-18.06],[22.83,4.38],[-11.12,15.5],[-28.39,-4.96],[-18.9,-12.71],[-15.48,-12.1],[-9.74,-9.17],[-9.74,-9.16],[-6.35,-1.78],[-6.54,-1.41],[0.12,-2.38],[1.52,-0.64]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1268.849,243.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4,-3.97],[0,0],[0.87,-1.23],[-2.19,-4.06],[2.34,0.83],[-0.06,0.13],[2.7,1.95],[0,0],[-2.55,4.64],[-0.96,0.83]],"o":[[0,0],[-1.23,0.76],[-2.76,3.95],[-2.79,2.34],[0.07,-0.12],[1.29,-2.82],[0,0],[-0.49,-1.89],[0.64,-1.17],[2.86,-2.46]],"v":[[7.92,-8.265],[7.98,-8.165],[4.78,-5.105],[2.46,9.895],[-4.2,10.865],[-4.01,10.495],[-7.4,3.115],[-7.4,3.105],[-5.43,-6.215],[-3,-9.255]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1266.509,231.095]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.07,-4.27],[0,0],[0.64,-1.17],[-0.49,-1.89],[1.7,0.57],[1.23,0.04],[-3.01,3.81]],"o":[[0,0],[-0.96,0.83],[-2.55,4.64],[-1.85,-1.34],[-1,-0.33],[0,0],[3.01,-3.81]],"v":[[6.94,-4.155],[7.13,-3.935],[4.7,-0.895],[2.73,8.425],[-3.01,5.495],[-6.43,4.885],[-4.12,-3.295]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1256.379,225.775]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.23,0.76],[-2.89,-4.76],[0.96,-3.7],[-0.39,-1.74],[4.39,3.17],[0.35,0.67],[-2.76,3.95]],"o":[[3.34,-2.1],[-2.83,1.35],[-0.87,3.36],[-0.18,0.28],[-0.58,-0.48],[-2.19,-4.06],[0.87,-1.23]],"v":[[-1.39,-10.435],[9.1,-7.675],[2.7,0.285],[2.06,7.855],[-5.51,9.365],[-6.91,7.625],[-4.59,-7.375]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1275.879,233.365]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":44,"st":0},{"ind":5,"ty":4,"nm":"a","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-214.47,266.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.13,0.64]],"o":[[4.18,5.01],[0,0]],"v":[[-7.73,-3.595],[7.73,2.955]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1257.679,280.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.39,0.92],[0,0]],"o":[[5.39,3.9],[0,0],[0,0]],"v":[[-8.085,-2.695],[8.075,1.775],[8.085,1.775]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1260.544,269.825]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.42,-1.15]],"o":[[0,0],[3.14,4.74],[0,0]],"v":[[-7.165,-4.425],[-7.165,-4.415],[7.165,4.425]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1252.934,293.195]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.63,0.66]],"o":[[0.36,-5.98],[0,0]],"v":[[3.075,4.925],[-3.435,-4.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1268.064,251.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.3,-0.31]],"o":[[1.23,-7.85],[0,0]],"v":[[-5.175,5.245],[5.175,-4.935]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1259.454,251.735]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-7.05,15.66],[-1.54,4.9],[-0.91,4.19],[-0.62,5.21]],"o":[[11.12,-10.34],[1.99,-4.4],[1.23,-3.86],[1.06,-4.76],[0,0]],"v":[[-19.435,39.785],[8.395,1.185],[13.705,-12.755],[16.915,-24.835],[19.435,-39.785]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1251.704,296.435]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.68,-3.22],[0.94,-3.16],[1.58,-3.65]],"o":[[-0.53,3.56],[-0.74,3.51],[-1.22,4.13],[0,0]],"v":[[4.255,-15.895],[2.435,-5.745],[-0.075,4.255],[-4.255,15.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1250.024,272.875]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[9.56,-10.05]],"o":[[-5.12,11.94],[0,0]],"v":[[10.875,-15.895],[-10.875,15.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1234.894,304.675]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.42,-1.15],[11.12,-10.34],[0,0],[-5.12,11.94]],"o":[[-7.05,15.66],[0,0],[9.56,-10.05],[3.14,4.74]],"v":[[18.04,-14.88],[-9.79,23.72],[-18.04,8.07],[3.71,-23.72]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1242.059,312.5]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.22,4.13],[-6.13,0.64],[1.99,-4.4],[3.14,4.74],[0,0]],"o":[[4.18,5.01],[-1.54,4.9],[-6.42,-1.15],[0,0],[1.58,-3.65]],"v":[[-5.64,-10.245],[9.82,-3.695],[4.51,10.245],[-9.82,1.405],[-9.82,1.395]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1255.589,287.375]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.3,-0.31],[0.36,-5.98],[1.06,-4.76],[5.39,3.9],[-0.53,3.56]],"o":[[4.63,0.66],[-0.62,5.21],[-5.39,0.92],[0.68,-3.22],[1.23,-7.85]],"v":[[2.65,-12.705],[9.16,-2.855],[6.64,12.095],[-9.52,7.625],[-7.7,-2.525]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1261.979,259.505]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.74,3.51],[-5.39,0.92],[1.23,-3.86],[4.18,5.01]],"o":[[5.39,3.9],[-0.91,4.19],[-6.13,0.64],[0.94,-3.16]],"v":[[-6.825,-8.595],[9.335,-4.125],[6.125,7.955],[-9.335,1.405]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1259.284,275.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":44,"st":0},{"ind":6,"ty":4,"nm":"a","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-116.47,239.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-25.92,23.58],[-1.5,-2.76],[8.92,-8.56],[30.96,-0.76],[0.38,8.8]],"o":[[50.97,3.27],[5.48,-4.99],[1.5,2.76],[-7.4,7.61],[-30.96,0.76],[-0.38,-8.79]],"v":[[-50.885,6.21],[42.105,-19.95],[54.035,-19.35],[48.835,-2.67],[-18.395,24.18],[-57.375,14.62]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1181.913,340.52]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.5,-2.76],[8.92,-8.56],[30.96,-0.76],[0.38,8.8],[0,0],[-25.92,23.58]],"o":[[1.5,2.76],[-7.4,7.61],[-30.96,0.76],[-0.38,-8.79],[50.97,3.27],[5.48,-4.99]],"v":[[54.035,-19.35],[48.835,-2.67],[-18.395,24.18],[-57.375,14.62],[-50.885,6.21],[42.105,-19.95]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1181.914,340.52]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":44,"st":0},{"ind":7,"ty":4,"nm":"h","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-246.97,338.11,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.01,-3.81],[0,0]],"o":[[-4.07,-4.27],[-3.01,3.81],[0,0]],"v":[[7.035,-2.385],[-4.025,-1.525],[-6.335,6.655]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1256.284,224.005]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.79,2.34]],"o":[[2.34,0.83],[0,0]],"v":[[-3.33,-0.2],[3.33,-1.17]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1265.639,242.16]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.86,-2.46],[0.64,-1.17],[-0.49,-1.89],[0,0]],"o":[[-4,-3.97],[-0.96,0.83],[-2.55,4.64],[0,0],[0,0]],"v":[[7.95,-3.705],[-2.97,-4.695],[-5.4,-1.655],[-7.37,7.665],[-7.37,7.675]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1266.479,226.535]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.01,0],[3.34,-2.1],[0.87,-1.23],[-2.19,-4.06],[-0.58,-0.48],[-0.18,0.28],[0,0]],"o":[[0,0],[-2.89,-4.76],[-1.23,0.76],[-2.76,3.95],[0.35,0.67],[4.39,3.17],[0,0],[0,0]],"v":[[9.105,-7.665],[9.095,-7.675],[-1.395,-10.435],[-4.595,-7.375],[-6.915,7.625],[-5.515,9.365],[2.055,7.855],[2.065,7.845]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1275.884,233.365]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.43,4.27],[-0.06,0.13],[2.7,1.95]],"o":[[2.7,2.32],[0.07,-0.12],[1.29,-2.82],[0,0]],"v":[[-7.1,1.37],[5.62,1.74],[5.81,1.37],[2.42,-6.01]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1256.689,240.22]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.7,0.57],[1.23,0.04],[1.21,-6.18],[-12.11,-3.78],[-8.62,14.11],[4.17,1.79],[1.87,-0.89],[0.96,-3.7],[-0.39,-1.74],[-1,-0.54],[-0.59,7.74]],"o":[[-1.85,-1.34],[-1,-0.33],[-3.88,-0.14],[-1.59,8.15],[13.19,3.27],[7.15,-13.9],[-1.66,-0.71],[-2.83,1.35],[-0.87,3.36],[0.33,1.46],[2.18,1.2],[0,0]],"v":[[-9.74,-9.17],[-15.48,-12.1],[-18.9,-12.71],[-28.39,-4.96],[-11.12,15.5],[22.83,4.38],[21.64,-18.06],[16.13,-17.68],[9.73,-9.72],[9.09,-2.15],[11.12,0.8],[19.73,-7.63]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1268.849,243.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.18,0.28],[-0.87,3.36],[-2.83,1.35],[-1.66,-0.71],[7.15,-13.9],[13.19,3.27],[-1.59,8.15],[-3.88,-0.14],[-1,-0.33],[-1.85,-1.34],[0,0],[1.29,-2.82],[0.07,-0.12],[-2.79,2.34],[-0.58,-0.48]],"o":[[-0.39,-1.74],[0.96,-3.7],[1.87,-0.89],[4.17,1.79],[-8.62,14.11],[-12.11,-3.78],[1.21,-6.18],[1.23,0.04],[1.7,0.57],[0,0],[2.7,1.95],[-0.06,0.13],[2.34,0.83],[0.35,0.67],[4.39,3.17]],"v":[[9.09,-2.15],[9.73,-9.72],[16.13,-17.68],[21.64,-18.06],[22.83,4.38],[-11.12,15.5],[-28.39,-4.96],[-18.9,-12.71],[-15.48,-12.1],[-9.74,-9.17],[-9.74,-9.16],[-6.35,-1.78],[-6.54,-1.41],[0.12,-2.38],[1.52,-0.64]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1268.849,243.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4,-3.97],[0,0],[0.87,-1.23],[-2.19,-4.06],[2.34,0.83],[-0.06,0.13],[2.7,1.95],[0,0],[-2.55,4.64],[-0.96,0.83]],"o":[[0,0],[-1.23,0.76],[-2.76,3.95],[-2.79,2.34],[0.07,-0.12],[1.29,-2.82],[0,0],[-0.49,-1.89],[0.64,-1.17],[2.86,-2.46]],"v":[[7.92,-8.265],[7.98,-8.165],[4.78,-5.105],[2.46,9.895],[-4.2,10.865],[-4.01,10.495],[-7.4,3.115],[-7.4,3.105],[-5.43,-6.215],[-3,-9.255]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1266.509,231.095]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-4.07,-4.27],[0,0],[0.64,-1.17],[-0.49,-1.89],[1.7,0.57],[1.23,0.04],[-3.01,3.81]],"o":[[0,0],[-0.96,0.83],[-2.55,4.64],[-1.85,-1.34],[-1,-0.33],[0,0],[3.01,-3.81]],"v":[[6.94,-4.155],[7.13,-3.935],[4.7,-0.895],[2.73,8.425],[-3.01,5.495],[-6.43,4.885],[-4.12,-3.295]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1256.379,225.775]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.23,0.76],[-2.89,-4.76],[0.96,-3.7],[-0.39,-1.74],[4.39,3.17],[0.35,0.67],[-2.76,3.95]],"o":[[3.34,-2.1],[-2.83,1.35],[-0.87,3.36],[-0.18,0.28],[-0.58,-0.48],[-2.19,-4.06],[0.87,-1.23]],"v":[[-1.39,-10.435],[9.1,-7.675],[2.7,0.285],[2.06,7.855],[-5.51,9.365],[-6.91,7.625],[-4.59,-7.375]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1275.879,233.365]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":60,"op":80,"st":0},{"ind":8,"ty":4,"nm":"a","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-214.47,266.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.13,0.64]],"o":[[4.18,5.01],[0,0]],"v":[[-7.73,-3.595],[7.73,2.955]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1257.679,280.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.39,0.92],[0,0]],"o":[[5.39,3.9],[0,0],[0,0]],"v":[[-8.085,-2.695],[8.075,1.775],[8.085,1.775]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1260.544,269.825]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.42,-1.15]],"o":[[0,0],[3.14,4.74],[0,0]],"v":[[-7.165,-4.425],[-7.165,-4.415],[7.165,4.425]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1252.934,293.195]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.63,0.66]],"o":[[0.36,-5.98],[0,0]],"v":[[3.075,4.925],[-3.435,-4.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1268.064,251.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.3,-0.31]],"o":[[1.23,-7.85],[0,0]],"v":[[-5.175,5.245],[5.175,-4.935]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1259.454,251.735]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-7.05,15.66],[-1.54,4.9],[-0.91,4.19],[-0.62,5.21]],"o":[[11.12,-10.34],[1.99,-4.4],[1.23,-3.86],[1.06,-4.76],[0,0]],"v":[[-19.435,39.785],[8.395,1.185],[13.705,-12.755],[16.915,-24.835],[19.435,-39.785]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1251.704,296.435]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.68,-3.22],[0.94,-3.16],[1.58,-3.65]],"o":[[-0.53,3.56],[-0.74,3.51],[-1.22,4.13],[0,0]],"v":[[4.255,-15.895],[2.435,-5.745],[-0.075,4.255],[-4.255,15.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1250.024,272.875]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[9.56,-10.05]],"o":[[-5.12,11.94],[0,0]],"v":[[10.875,-15.895],[-10.875,15.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1234.894,304.675]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-6.42,-1.15],[11.12,-10.34],[0,0],[-5.12,11.94]],"o":[[-7.05,15.66],[0,0],[9.56,-10.05],[3.14,4.74]],"v":[[18.04,-14.88],[-9.79,23.72],[-18.04,8.07],[3.71,-23.72]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1242.059,312.5]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.22,4.13],[-6.13,0.64],[1.99,-4.4],[3.14,4.74],[0,0]],"o":[[4.18,5.01],[-1.54,4.9],[-6.42,-1.15],[0,0],[1.58,-3.65]],"v":[[-5.64,-10.245],[9.82,-3.695],[4.51,10.245],[-9.82,1.405],[-9.82,1.395]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1255.589,287.375]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-5.3,-0.31],[0.36,-5.98],[1.06,-4.76],[5.39,3.9],[-0.53,3.56]],"o":[[4.63,0.66],[-0.62,5.21],[-5.39,0.92],[0.68,-3.22],[1.23,-7.85]],"v":[[2.65,-12.705],[9.16,-2.855],[6.64,12.095],[-9.52,7.625],[-7.7,-2.525]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.443,0.004,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1261.979,259.505]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.74,3.51],[-5.39,0.92],[1.23,-3.86],[4.18,5.01]],"o":[[5.39,3.9],[-0.91,4.19],[-6.13,0.64],[0.94,-3.16]],"v":[[-6.825,-8.595],[9.335,-4.125],[6.125,7.955],[-9.335,1.405]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.98,0.941,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1259.284,275.725]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":60,"op":80,"st":0},{"ind":9,"ty":4,"nm":"a","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-116.47,239.61,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-25.92,23.58],[-1.5,-2.76],[8.92,-8.56],[30.96,-0.76],[0.38,8.8]],"o":[[50.97,3.27],[5.48,-4.99],[1.5,2.76],[-7.4,7.61],[-30.96,0.76],[-0.38,-8.79]],"v":[[-50.885,6.21],[42.105,-19.95],[54.035,-19.35],[48.835,-2.67],[-18.395,24.18],[-57.375,14.62]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1181.913,340.52]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.5,-2.76],[8.92,-8.56],[30.96,-0.76],[0.38,8.8],[0,0],[-25.92,23.58]],"o":[[1.5,2.76],[-7.4,7.61],[-30.96,0.76],[-0.38,-8.79],[50.97,3.27],[5.48,-4.99]],"v":[[54.035,-19.35],[48.835,-2.67],[-18.395,24.18],[-57.375,14.62],[-50.885,6.21],[42.105,-19.95]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0,0.549,0.349,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1181.914,340.52]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":60,"op":80,"st":0}]}],"layers":[{"ind":1,"ty":0,"nm":"C","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[187.5,120,0],"l":2},"a":{"a":0,"k":[187.5,200,0],"l":2},"s":{"a":0,"k":[60,60,100],"l":2}},"ao":0,"w":375,"h":400,"ip":0,"op":80,"st":0}],"markers":[]}
\ No newline at end of file
diff --git a/assets/images/eReceipt_background.svg b/assets/images/eReceipt_background.svg
new file mode 100644
index 000000000000..5070ed3b2f24
--- /dev/null
+++ b/assets/images/eReceipt_background.svg
@@ -0,0 +1,1635 @@
+
+
+
diff --git a/assets/images/simple-illustrations/simple-illustration__handearth.svg b/assets/images/simple-illustrations/simple-illustration__handearth.svg
new file mode 100644
index 000000000000..f79e3f73293b
--- /dev/null
+++ b/assets/images/simple-illustrations/simple-illustration__handearth.svg
@@ -0,0 +1,30 @@
+
+
+
diff --git a/docs/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription.md b/docs/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription.md
index 8e2aa7d4a377..67a96610633d 100644
--- a/docs/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription.md
+++ b/docs/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription.md
@@ -1,5 +1,45 @@
---
title: Annual Subscription
-description: Annual Subscription
+description: Learn more about managing your Annual Subscription.
---
-## Resource Coming Soon!
+# Overview
+An Annual Subscription offers a 50% cost savings on active user pricing while allowing your company to manage multiple Workspaces across your organization and maintain predictable cost for your Expensify activity.
+
+_For pricing details, see [expensify.com/pricing](http://www.expensify.com/pricing), and find more ways to save with the Expensify Card here._
+
+# How to set subscription size
+When you first create a subscription, the best practice is to set your subscription size by entering the average number of active users you expect to have each month for the next year. For example, if you expect to have an average of 10 users each month, even if they are not always the same users, set your subscription size to 10. No need to provision and deprovision access to your team, so you still enjoy flexible usage across the entire company!
+
+If your Workspaces have more than 10 active users in a month, you will pay the unbundled Pay-per-use rate for the additional users. If you’d like to avoid this, you can enable Auto Increase so your subscription size increases based on Workspace user activity.
+
+An ‘Active User’ is anyone who chats, creates, submits, approves, reimburses, or exports a report in Expensify. This includes actions taken by Copilots and any automated settings.
+
+To set your subscription size, go to **Settings > Workspaces > Groups > Subscription**.
+
+If you do not set a specific subscription size, this will be automatically updated based on your past activity:
+
+* If you’ve never had activity in Expensify, your subscription size will be set after your first month. Work with your Setup Specialist or Account Manager to determine the best subscription size for your team!
+
+* For existing Workspaces switching to an Annual Subscription, the subscription size is set to the number of active users on your last month’s billing history.
+
+* If Auto Increase is not selected, and you have more active users than you’ve input as the subscription size, you will be billed for those at the Pay-per-use rate.
+
+# How to adjust subscription size
+You can add users to your subscription at any time. However, note that when your subscription size is increased, you will start a new 12-month subscription at that new subscription size.
+
+You can increase your subscription size manually or automatically.
+
+* To manually increase the size, just update the number in your subscription settings (**Settings > Workspaces > Groups > Subscription**).
+
+* To automatically increase your subscription size, enable **Auto Increase**. This feature manages your subscription by automatically increasing the count whenever there is activity that exceeds your subscription size. (**Settings > Workspaces > Groups > Subscription**)
+
+Note: After increasing your subscription size, you won't be able to decrease it for the next 12 months. If your active user numbers tend to fluctuate, you might want to keep this feature disabled. This way, you'll only pay for additional active users in the months they are active. Keep in mind that increasing the subscription size will reset your 12-month subscription period.
+
+# How to disable Auto Renew
+By default, your subscription is set to automatically renew after a year. To disable this, click the toggle from your subscription settings before the current subscription ends. (**Settings > Workspaces > Groups > Subscription**)
+
+If Auto Renew is disabled, then the last bill at the annual rate will be issued on the date listed under the Auto Renew settings. For example, if your subscription expires on March 1, 2021, then February 2021 will be the last month billed at the annual rate. If you do not set a new subscription, March activity will be billed at the Pay-per-use rate.
+
+We recommend that you review your user count annually on a proactive basis. Set a reminder to review your active user numbers a month before your subscription expires! If you’d like assistance determining your subscription number, please contact your Account Manager or concierge@expensify.com.
+
+If you need to decrease your subscription size, you can do this in the first billing month before you are billed. Using the example above, this would be during March 2021.
diff --git a/docs/articles/expensify-classic/get-paid-back/Distance-Tracking.md b/docs/articles/expensify-classic/get-paid-back/Distance-Tracking.md
new file mode 100644
index 000000000000..c0d8956f71ac
--- /dev/null
+++ b/docs/articles/expensify-classic/get-paid-back/Distance-Tracking.md
@@ -0,0 +1,81 @@
+---
+title: Distance Tracking in Expensify
+description: Learn how distance tracking works in Expensify!
+---
+
+# Overview
+
+Expensify provides a convenient feature for tracking your mileage-related expenses. You'll find all the essential information to begin logging your trips below.
+
+# How to Use Distance Tracking
+## Mobile App
+
+First, you’ll want to click the **+** in the top right corner.
+
+If you select **Manually Create**, you’ll be prompted to enter your mileage, select a rate, and code the expense before clicking **Save**.
+
+ ![Click manually create or odometer to create a distance request.](https://help.expensify.com/assets/images/ExpensifyHelp_CreateExpense_Mobile.png){:width="100%"}
+
+If you select **Manually Create**:
+ - Enter your mileage.
+ - Select a rate.
+ - Code the expense.
+ - Click **Save**.
+
+![Enter your mileage, rate, code the expense, and click save.](https://help.expensify.com/assets/images/ExpensifyHelp_ManualDistance_Mobile.png){:width="100%"}
+
+If you select **Odometer**:
+ - Enter your vehicle’s mileage reading before and after your trip.
+ - Select your rate.
+ - Code the expense.
+ - Click **Save**.
+
+![Etner your mileage readings, your rate, code the expense, and click save.](https://help.expensify.com/assets/images/ExpensifyHelp_Odometer_Mobile.png){:width="100%"}
+
+The **Start GPS** option also exists on the mobile app. However, we’ve learned that most customers prefer to track their mileage after their trips (thus not needing to hit that start button!)
+
+We’ve temporarily paused the development of GPS mileage tracking in the mobile app, and we recommend you use one of the above options instead!
+
+
+## Web
+
+Navigate to the **Expenses** page, click **New Expense**, and review the two **Distance** options.
+
+![Select manually create or create from map to create a new distance request.](https://help.expensify.com/assets/images/ExpensifyHelp_CreateExpense.png){:width="100%"}
+
+If you select **Manually Create**:
+ - Enter the number of miles for your trip.
+ - Mileage rate is automatically selected based on your history, or manually select it if it's your first time.
+ - Complete any other applicable coding fields.
+ - Click **Save**.
+
+![Enter the number of miles, select your rate, code the expense, and click save.](https://help.expensify.com/assets/images/ExpensifyHelp_ManualDistance.png){:width="100%"}
+
+For **Create from Map** expenses:
+ - Add your start and end location, and the distance will be calculated.
+ - You can also click **Add Destination** for multiple stops.
+ - Leave **Create Receipt** selected if you want a map receipt generated.
+ - Click **Save**.
+
+![Enter your start and end locations, and click save.](https://help.expensify.com/assets/images/ExpensifyHelp_ManualDistanceMap.png){:width="100%"}
+
+Once you click **Save**, review the details from your map selection.
+ - Select your rate.
+ - Enter any other applicable coding.
+ - Click **Save**.
+
+![Select your rate, code the expense, and click save.](https://help.expensify.com/assets/images/ExpensifyHelp_ManualDistanceConfirm.png){:width="100%"}
+
+# Mileage Tracking FAQs
+## **How can I change the rate of my mileage expenses?**
+You can change the rate by going to Settings > Workspaces > [Your Workspace] > Expenses > Distance > Add a Mileage Rate.
+If you submit mileage expenses on a group workspace, only workspace admins can do this.
+
+## **Do you plan to add the "Create from Map" option to the mobile app or "Odometer" option to web?**
+Not now, but if that changes, you'll be the first to know!
+
+## **Will you restart maintenance on the mobile app's GPS option anytime soon?**
+Not now, but if that changes, you'll be the first to know!
+
+## **Does Expensify automatically update IRS Mileage rates?**
+ We never automatically update mileage rates in Expensify because different companies want the new rates to become effective on different dates.
diff --git a/docs/articles/expensify-classic/get-paid-back/Mileage.md b/docs/articles/expensify-classic/get-paid-back/Mileage.md
deleted file mode 100644
index 248e80e1c115..000000000000
--- a/docs/articles/expensify-classic/get-paid-back/Mileage.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Mileage
-description: Mileage
----
-## Resource Coming Soon!
diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.md b/docs/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.md
new file mode 100644
index 000000000000..ac37a01b3e6b
--- /dev/null
+++ b/docs/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.md
@@ -0,0 +1,71 @@
+---
+title: Importing Receipts from Various Platforms to Expensify
+description: Detailed guide on how to import receipts from multiple travel platforms into Expensify.
+---
+
+# Overview
+You can automatically import receipts from many travel platforms into Expensify, to make tracking expenses while traveling for business a breeze. Read on to learn how to import receipts from Bolt Work, Spot Hero, Trainline, Grab, HotelTonight, and Kayak for Business.
+
+## How to Connect to Bolt Work
+
+### Set Up Bolt Work Profile
+- Open the Bolt app, go to the side navigation menu, and select Payment.
+- At the bottom, select Set up work profile and follow the instructions, entering your work email for verification.
+
+### Link to Expensify
+- In the Bolt app, go to Work Rides.
+- Select Add expense provider, choose Expensify, and enter the associated email to receive a verification link.
+- Ensure you select your work ride profile as the payment method before booking.
+
+## How to Connect to SpotHero
+
+### Set up a Business Profile
+- Open the SpotHero app, click the hamburger icon, and go to Account Settings.
+- Click Set up Business Profile.
+- Specify the email connected to Expensify and set up your payment method.
+- Upon checkout, choose between Business and Personal Profiles in the "Payment Details" section.
+- If you want, you can set a weekly or monthly cadence for consolidated SpotHero expense reports in your Business Profile settings. This will batch all of your SpotHero expenses to import into Expensify at that cadence.
+
+## How to Connect to Trainline
+- To send a ticket receipt to Expensify:
+ - In the Trainline app, navigate to the My Tickets tab.
+ - Tap Manage my booking > Expense receipt > Send to Expensify.
+- That’s it!
+
+## How to Connect to Grab
+- In the Grab app, tap on your name, go to “Profiles”, and “Add a business profile”.
+- Follow instructions and enter your work email for verification.
+- In your profile, tap on Business > Expense Solution > Expensify > Save.
+- Before booking, select your Business profile and confirm.
+
+## How to Connect to HotelTonight
+- In HotelTonight, go to the Bookings tab and select your booking.
+- Select Receipt > Expensify, enter your Expensify email, and send.
+
+## How to Connect to Kayak for Business
+
+### Admin Setup
+- Admins should go to “Company Settings” and click on “Connect to Expensify”.
+- Bookings made by employees will automatically be sent to Expensify.
+
+### Traveler Setup
+- From your account settings, choose whether expenses should be sent to Expensify automatically or manually.
+- We recommend sending them automatically, so you can travel without even thinking about your expense reports.
+
+# FAQ
+
+**Q: What if I don’t have the option for Send to Expensify in Trainline?**
+
+A: This can happen if the native iOS Mail app is not installed on an Apple device. However, you can still use the native iOS share to Expensify function for Trainline receipts.
+
+**Q: Why should I choose automatic mode in Kayak for Business?**
+
+A: Automatic mode is less effort as it’s easier to delete an expense in Expensify than to remember to forward a forgotten receipt.
+
+**Q: Can I receive consolidated reports from SpotHero?**
+
+A: Yes, you can set a weekly or monthly cadence for SpotHero expenses to be emailed in a consolidated report.
+
+**Q: Do I need to select a specific profile before booking in Bolt Work and Grab?**
+
+A: Yes, ensure you have selected your work or business profile as the payment method before booking.
diff --git a/docs/articles/expensify-classic/manage-employees-and-report-approvals/Removing-Members.md b/docs/articles/expensify-classic/manage-employees-and-report-approvals/Removing-Members.md
new file mode 100644
index 000000000000..76ebba9ef76b
--- /dev/null
+++ b/docs/articles/expensify-classic/manage-employees-and-report-approvals/Removing-Members.md
@@ -0,0 +1,34 @@
+---
+title: Remove a Workspace Member
+description: How to remove a member from a Workspace in Expensify
+---
+
+Removing a member from a workspace disables their ability to use the workspace. Please note that it does not delete their account or deactivate the Expensify Card.
+
+## How to Remove a Workspace Member
+1. Important: Make sure the employee has submitted all Draft reports and the reports have been approved, reimbursed, etc.
+2. Go to Settings > Workspaces > Group > [Workspace Name] > Members > Workspace Members
+3. Select the member you'd like to remove and click the **Remove** button at the top of the Members table.
+4. If this member was an approver, make sure that reports are not routing to them in the workflow.
+
+# FAQ
+
+## Will reports from this member on this workspace still be available?
+Yes, as long as the reports have been submitted. You can navigate to the Reports page and enter the member's email in the search field to find them. However, Draft reports will be removed from the workspace, so these will no longer be visible to the Workspace Admin.
+
+## Can members still access their reports on a workspace after they have been removed?
+Yes. Any report that has been approved will now show the workspace as “(not shared)” in their account. If it is a Draft Report they will still be able to edit it and add it to a new workspace. If the report is Approved or Reimbursed they will not be able to edit it further.
+
+## Who can remove members from a workspace?
+Only Workspace Admins. It is not possible for a member to add or remove themselves from a workspace. It is not possible for a Domain Admin who is not also a Workspace Admin to remove a member from a workspace.
+
+## How do I remove a member from a workspace if I am seeing an error message?
+If a member is a **preferred exporter, billing owner, report approver** or has **processing reports**, to remove them the workspace you will first need to:
+
+* **Preferred Exporter** - go to Settings > Workspaces > Group > [Workspace Name] > Connections > Configure and select a different Workspace Admin in the dropdown for **Preferred Exporter**.
+* **Billing Owner** - take over billing on the Settings > Workspaces > Group > [Workspace Name] > Overview page.
+* **Processing reports** - approve or reject the member’s reports on your Reports page.
+* **Approval Workflow** - remove them as a workflow approver on your Settings > Workspaces > Group > [Workspace Name] > Members > Approval Mode > page by changing the "**Submit reports to**" field.
+
+## How do I remove a user completely from a company account?
+If you have a Control Workspace and have Domain Control enabled, you will need to remove them from the domain to delete members' accounts entirely and deactivate the Expensify Card.
diff --git a/docs/articles/expensify-classic/send-payments/Third-Party-Payments.md b/docs/articles/expensify-classic/send-payments/Third-Party-Payments.md
index f61f26d91059..14ade143a35b 100644
--- a/docs/articles/expensify-classic/send-payments/Third-Party-Payments.md
+++ b/docs/articles/expensify-classic/send-payments/Third-Party-Payments.md
@@ -1,8 +1,63 @@
---
title: Third Party Payments
-description: Third Party Payments
+description: A help article that covers Third Party Payment options including PayPal, Venmo, Wise, and Paylocity.
---
-## Resource Coming Soon!
+# Expensify Third Party Payment Options
+Expensify offers convenient third party payment options that allow you to streamline the process of reimbursing expenses and managing your finances. With these options, you can pay your expenses and get reimbursed faster and more efficiently. In this guide, we'll walk you through the steps to set up and use Expensify's third party payment options.
-
\ No newline at end of file
+## Overview
+
+Expensify offers integration with various third party payment providers, making it easy to reimburse employees and manage your expenses seamlessly. Some of the key benefits of using third-party payment options in Expensify include:
+
+- Faster Reimbursements: Expedite the reimbursement process and reduce the time it takes for employees to receive their funds.
+- Secure Transactions: Benefit from the security features and protocols provided by trusted payment providers.
+- Centralized Expense Management: Consolidate all your expenses and payments within Expensify for a more efficient financial workflow.
+
+## Setting Up Third Party Payments
+
+To get started with third party payments in Expensify, follow these steps:
+
+1. **Log in to Expensify**: Access your Expensify account using your credentials.
+
+2. **Navigate to Settings**: Click on the "Settings" option in the top-right corner of the Expensify dashboard.
+
+3. **Select Payments**: In the Settings menu, find and click on the "Payments" or "Payment Methods" section.
+
+4. **Choose Third Party Payment Provider**: Select your preferred third party payment provider from the available options. Expensify may support providers such as PayPal, Venmo, Wise, and Paylocity.
+
+5. **Link Your Account**: Follow the prompts to link your third party payment account with Expensify. You may need to enter your account details and grant necessary permissions.
+
+6. **Verify Your Account**: Confirm your linked account to ensure it's correctly integrated with Expensify.
+
+## Using Third Party Payments
+
+Once you've set up your third party payment option, you can start using it to reimburse expenses and manage payments:
+
+1. **Create an Expense Report**: Begin by creating an expense report in Expensify, adding all relevant expenses.
+
+2. **Submit for Approval**: After reviewing and verifying the expenses, submit the report for approval within Expensify.
+
+3. **Approval and Reimbursement**: Once the report is approved, the approved expenses can be reimbursed directly through your chosen third party payment provider. Expensify will automatically initiate the payment process.
+
+4. **Track Payment Status**: You can track the status of payments and view transaction details within your Expensify account.
+
+## FAQ’s
+
+### Q: Are there any fees associated with using third party payment options in Expensify?
+
+A: The fees associated with third party payments may vary depending on the payment provider you choose. Be sure to review the terms and conditions of your chosen provider for details on any applicable fees.
+
+### Q: Can I use multiple third party payment providers with Expensify?
+
+A: Expensify allows you to link multiple payment providers if needed. You can select the most suitable payment method for each expense report.
+
+### Q: Is there a limit on the amount I can reimburse using third party payments?
+
+A: The reimbursement limit may depend on the policies and settings configured within your Expensify account and the limits imposed by your chosen payment provider.
+
+With Expensify's third party payment options, you can simplify your expense management and reimbursement processes. By following the steps outlined in this guide, you can set up and use third party payments efficiently.
+
+
+
+
diff --git a/docs/assets/images/Auto-Reconciliation_Image2.png b/docs/assets/images/Auto-Reconciliation_Image2.png
new file mode 100644
index 000000000000..5c7ed2d6b7ea
Binary files /dev/null and b/docs/assets/images/Auto-Reconciliation_Image2.png differ
diff --git a/docs/assets/images/Auto-Reconciliaton_Image1.png b/docs/assets/images/Auto-Reconciliaton_Image1.png
new file mode 100644
index 000000000000..9fcb7e316aaf
Binary files /dev/null and b/docs/assets/images/Auto-Reconciliaton_Image1.png differ
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 77e9c5a29f14..32506cc25a89 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.3.83
+ 1.3.84
CFBundleSignature
????
CFBundleURLTypes
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.3.83.6
+ 1.3.84.0
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index dab444c9efec..8e2c10ee1c71 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.3.83
+ 1.3.84
CFBundleSignature
????
CFBundleVersion
- 1.3.83.6
+ 1.3.84.0
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 54d0525fd3c9..cb120bca2b88 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -251,9 +251,9 @@ PODS:
- nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30908.0)
- nanopb/encode (2.30908.0)
- - Onfido (27.4.0)
- - onfido-react-native-sdk (7.4.0):
- - Onfido (= 27.4.0)
+ - Onfido (28.3.0)
+ - onfido-react-native-sdk (8.3.0):
+ - Onfido (~> 28.3.0)
- React
- OpenSSL-Universal (1.1.1100)
- Plaid (4.1.0)
@@ -819,7 +819,7 @@ PODS:
- SDWebImage/Core (~> 5.10)
- SocketRocket (0.6.1)
- Turf (2.6.1)
- - VisionCamera (2.15.4):
+ - VisionCamera (2.16.2):
- React
- React-callinvoker
- React-Core
@@ -1204,8 +1204,8 @@ SPEC CHECKSUMS:
MapboxMaps: af50ec61a7eb3b032c3f7962c6bd671d93d2a209
MapboxMobileEvents: de50b3a4de180dd129c326e09cd12c8adaaa46d6
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
- Onfido: e36f284b865adcf99d9c905590a64ac09d4a576b
- onfido-react-native-sdk: 4ecde1a97435dcff9f00a878e3f8d1eb14fabbdc
+ Onfido: c7d010d9793790d44a07799d9be25aa8e3814ee7
+ onfido-react-native-sdk: b346a620af5669f9fecb6dc3052314a35a94ad9f
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
@@ -1287,7 +1287,7 @@ SPEC CHECKSUMS:
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Turf: 469ce2c3d22e5e8e4818d5a3b254699a5c89efa4
- VisionCamera: d3ec8883417a6a4a0e3a6ba37d81d22db7611601
+ VisionCamera: 95f969b8950b411285579d633a1014782fe0e634
Yoga: 3efc43e0d48686ce2e8c60f99d4e6bd349aff981
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
diff --git a/package-lock.json b/package-lock.json
index 57cde7e879ee..4030bc26bf7e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.3.83-6",
+ "version": "1.3.84-0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.3.83-6",
+ "version": "1.3.84-0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -22,7 +22,7 @@
"@kie/act-js": "^2.0.1",
"@kie/mock-github": "^1.0.0",
"@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52",
- "@onfido/react-native-sdk": "7.4.0",
+ "@onfido/react-native-sdk": "8.3.0",
"@react-native-async-storage/async-storage": "^1.17.10",
"@react-native-camera-roll/camera-roll": "5.4.0",
"@react-native-clipboard/clipboard": "^1.12.1",
@@ -94,7 +94,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.98",
+ "react-native-onyx": "1.0.100",
"react-native-pager-view": "^6.2.0",
"react-native-pdf": "^6.7.1",
"react-native-performance": "^5.1.0",
@@ -6384,10 +6384,9 @@
}
},
"node_modules/@onfido/react-native-sdk": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.4.0.tgz",
- "integrity": "sha512-qeeaXLxVXz+J0lrqMwQGP52fXhCnTmEAC5K8jZe8YTqst2s1FZZGKkd1bxTloHG5hBBTa39SwWVUKmgPUm+Ssw==",
- "license": "MIT",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-8.3.0.tgz",
+ "integrity": "sha512-nnhuvezd35v08WXUTQlX+gr4pbnNnwNV5KscC/jJrfjGikNUJnhnAHYxfnfJccTn44qUC6vRaKWq2GfpMUnqNA==",
"peerDependencies": {
"react": ">=17.0.0",
"react-native": ">=0.68.2 <1.0.x"
@@ -44692,9 +44691,9 @@
}
},
"node_modules/react-native-onyx": {
- "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==",
+ "version": "1.0.100",
+ "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.100.tgz",
+ "integrity": "sha512-m4bOF/uOtYpfL83fqoWhw7TYV4oKGXt0sfGoel/fhaT1HzXKheXc//ibt/G3VrTCf5nmRv7bXgsXkWjUYLH3UQ==",
"dependencies": {
"ascii-table": "0.0.9",
"fast-equals": "^4.0.3",
@@ -57609,9 +57608,9 @@
}
},
"@onfido/react-native-sdk": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.4.0.tgz",
- "integrity": "sha512-qeeaXLxVXz+J0lrqMwQGP52fXhCnTmEAC5K8jZe8YTqst2s1FZZGKkd1bxTloHG5hBBTa39SwWVUKmgPUm+Ssw==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-8.3.0.tgz",
+ "integrity": "sha512-nnhuvezd35v08WXUTQlX+gr4pbnNnwNV5KscC/jJrfjGikNUJnhnAHYxfnfJccTn44qUC6vRaKWq2GfpMUnqNA==",
"requires": {}
},
"@pkgjs/parseargs": {
@@ -85254,9 +85253,9 @@
}
},
"react-native-onyx": {
- "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==",
+ "version": "1.0.100",
+ "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.100.tgz",
+ "integrity": "sha512-m4bOF/uOtYpfL83fqoWhw7TYV4oKGXt0sfGoel/fhaT1HzXKheXc//ibt/G3VrTCf5nmRv7bXgsXkWjUYLH3UQ==",
"requires": {
"ascii-table": "0.0.9",
"fast-equals": "^4.0.3",
diff --git a/package.json b/package.json
index 129582d17515..aa0875865393 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.3.83-6",
+ "version": "1.3.84-0",
"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.",
@@ -12,7 +12,7 @@
"startAndroidEmulator": "scripts/start-android.sh",
"postinstall": "scripts/postInstall.sh",
"clean": "npx react-native clean-project-auto",
- "android": "scripts/set-pusher-suffix.sh && npx react-native run-android --variant=developmentDebug --appId=com.expensify.chat.dev",
+ "android": "scripts/set-pusher-suffix.sh && npx react-native run-android --mode=developmentDebug --appId=com.expensify.chat.dev",
"ios": "scripts/set-pusher-suffix.sh && npx react-native run-ios --list-devices --configuration=\"DebugDevelopment\" --scheme=\"New Expensify Dev\"",
"pod-install": "cd ios && bundle exec pod install",
"ipad": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (12.9-inch) (6th generation)\\\" --configuration=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"",
@@ -67,7 +67,7 @@
"@kie/act-js": "^2.0.1",
"@kie/mock-github": "^1.0.0",
"@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52",
- "@onfido/react-native-sdk": "7.4.0",
+ "@onfido/react-native-sdk": "8.3.0",
"@react-native-async-storage/async-storage": "^1.17.10",
"@react-native-camera-roll/camera-roll": "5.4.0",
"@react-native-clipboard/clipboard": "^1.12.1",
@@ -139,7 +139,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.98",
+ "react-native-onyx": "1.0.100",
"react-native-pager-view": "^6.2.0",
"react-native-pdf": "^6.7.1",
"react-native-performance": "^5.1.0",
diff --git a/patches/@onfido+react-native-sdk+7.4.0.patch b/patches/@onfido+react-native-sdk+8.3.0.patch
similarity index 90%
rename from patches/@onfido+react-native-sdk+7.4.0.patch
rename to patches/@onfido+react-native-sdk+8.3.0.patch
index b84225c0f667..12245cb58355 100644
--- a/patches/@onfido+react-native-sdk+7.4.0.patch
+++ b/patches/@onfido+react-native-sdk+8.3.0.patch
@@ -1,8 +1,8 @@
diff --git a/node_modules/@onfido/react-native-sdk/android/build.gradle b/node_modules/@onfido/react-native-sdk/android/build.gradle
-index 781925b..9e16430 100644
+index b4c7106..d5083d3 100644
--- a/node_modules/@onfido/react-native-sdk/android/build.gradle
+++ b/node_modules/@onfido/react-native-sdk/android/build.gradle
-@@ -134,9 +134,9 @@ afterEvaluate { project ->
+@@ -135,9 +135,9 @@ afterEvaluate { project ->
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports {
diff --git a/src/CONST.ts b/src/CONST.ts
index b9141c9c0d4b..0a86aaf7648a 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -668,6 +668,7 @@ const CONST = {
TOOLTIP_SENSE: 1000,
TRIE_INITIALIZATION: 'trie_initialization',
COMMENT_LENGTH_DEBOUNCE_TIME: 500,
+ SEARCH_FOR_REPORTS_DEBOUNCE_TIME: 300,
},
PRIORITY_MODE: {
GSD: 'gsd',
@@ -1242,6 +1243,7 @@ const CONST = {
CLOSED: 6,
STATE_SUSPENDED: 7,
},
+ ACTIVE_STATES: [2, 3, 4, 7],
},
AVATAR_ROW_SIZE: {
DEFAULT: 4,
@@ -2660,8 +2662,8 @@ const CONST = {
ATTACHMENT: 'common.attachment',
},
TEACHERS_UNITE: {
- PUBLIC_ROOM_ID: '207591744844000',
- POLICY_ID: 'ABD1345ED7293535',
+ PUBLIC_ROOM_ID: '7470147100835202',
+ POLICY_ID: 'B795B6319125BDF2',
POLICY_NAME: 'Expensify.org / Teachers Unite!',
PUBLIC_ROOM_NAME: '#teachers-unite',
},
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index f7c4a11bc52f..d9ea3488f85f 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -26,6 +26,9 @@ const ONYXKEYS = {
/** Boolean flag set whenever the sidebar has loaded */
IS_SIDEBAR_LOADED: 'isSidebarLoaded',
+ /** Boolean flag set whenever we are searching for reports in the server */
+ IS_SEARCHING_FOR_REPORTS: 'isSearchingForReports',
+
/** Note: These are Persisted Requests - not all requests in the main queue as the key name might lead one to believe */
PERSISTED_REQUESTS: 'networkRequestQueue',
@@ -47,6 +50,9 @@ const ONYXKEYS = {
// draft status
CUSTOM_STATUS_DRAFT: 'customStatusDraft',
+ // keep edit message focus state
+ INPUT_FOCUSED: 'inputFocused',
+
/** Contains all the personalDetails the user has access to, keyed by accountID */
PERSONAL_DETAILS_LIST: 'personalDetailsList',
@@ -312,6 +318,7 @@ type OnyxValues = {
[ONYXKEYS.MODAL]: OnyxTypes.Modal;
[ONYXKEYS.NETWORK]: OnyxTypes.Network;
[ONYXKEYS.CUSTOM_STATUS_DRAFT]: OnyxTypes.CustomStatusDraft;
+ [ONYXKEYS.INPUT_FOCUSED]: boolean;
[ONYXKEYS.PERSONAL_DETAILS_LIST]: Record;
[ONYXKEYS.PRIVATE_PERSONAL_DETAILS]: OnyxTypes.PrivatePersonalDetails;
[ONYXKEYS.TASK]: OnyxTypes.Task;
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 7df37045b959..69f905e4a7a3 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -19,6 +19,8 @@ export default {
WORKSPACES: 'Settings_Workspaces',
SECURITY: 'Settings_Security',
STATUS: 'Settings_Status',
+ WALLET: 'Settings_Wallet',
+ WALLET_DOMAIN_CARDS: 'Settings_Wallet_DomainCards',
},
SAVE_THE_WORLD: {
ROOT: 'SaveTheWorld_Root',
diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js
index b8bfb4c36122..61b138747950 100755
--- a/src/components/AttachmentModal.js
+++ b/src/components/AttachmentModal.js
@@ -376,7 +376,7 @@ function AttachmentModal(props) {
text: props.translate('common.download'),
onSelected: () => downloadAttachment(source),
});
- if (TransactionUtils.hasReceipt(props.transaction) && !TransactionUtils.isReceiptBeingScanned(props.transaction)) {
+ if (TransactionUtils.hasReceipt(props.transaction) && !TransactionUtils.isReceiptBeingScanned(props.transaction) && !isSettled) {
menuItems.push({
icon: Expensicons.Trashcan,
text: props.translate('receipt.deleteReceipt'),
@@ -469,7 +469,7 @@ function AttachmentModal(props) {
)}
)}
- {isAttachmentReceipt ? (
+ {isAttachmentReceipt && (
- ) : (
-
)}
+ {!isAttachmentReceipt && (
+
+ )}
{props.children &&
props.children({
diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
index 3aeef8482e2d..096b6d60d428 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js
+++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
@@ -10,6 +10,7 @@ import Button from '../../Button';
import AttachmentView from '../AttachmentView';
import SafeAreaConsumer from '../../SafeAreaConsumer';
import ReportAttachmentsContext from '../../../pages/home/report/ReportAttachmentsContext';
+import * as AttachmentsPropTypes from '../propTypes';
const propTypes = {
/** Attachment required information such as the source and file name */
@@ -20,8 +21,8 @@ const propTypes = {
/** Whether source URL requires authentication */
isAuthTokenRequired: PropTypes.bool,
- /** The source (URL) of the attachment */
- source: PropTypes.string,
+ /** URL to full-sized attachment or SVG function */
+ source: AttachmentsPropTypes.attachmentSourcePropType.isRequired,
/** Additional information about the attachment file */
file: PropTypes.shape({
@@ -31,6 +32,9 @@ const propTypes = {
/** Whether the attachment has been flagged */
hasBeenFlagged: PropTypes.bool,
+
+ /** The id of the transaction related to the attachment */
+ transactionID: PropTypes.string,
}).isRequired,
/** Whether the attachment is currently being viewed in the carousel */
@@ -97,6 +101,7 @@ function CarouselItem({item, isFocused, onPress}) {
isFocused={isFocused}
onPress={onPress}
isUsedInCarousel
+ transactionID={item.transactionID}
/>
diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js
index f4d3036ff802..a1b07fb99dd8 100755
--- a/src/components/Attachments/AttachmentView/index.js
+++ b/src/components/Attachments/AttachmentView/index.js
@@ -3,6 +3,7 @@ import {View, ActivityIndicator} from 'react-native';
import _ from 'underscore';
import PropTypes from 'prop-types';
import Str from 'expensify-common/lib/str';
+import {withOnyx} from 'react-native-onyx';
import styles from '../../../styles/styles';
import Icon from '../../Icon';
import * as Expensicons from '../../Icon/Expensicons';
@@ -17,7 +18,10 @@ import AttachmentViewPdf from './AttachmentViewPdf';
import addEncryptedAuthTokenToURL from '../../../libs/addEncryptedAuthTokenToURL';
import * as StyleUtils from '../../../styles/StyleUtils';
import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes';
+import * as TransactionUtils from '../../../libs/TransactionUtils';
+import DistanceEReceipt from '../../DistanceEReceipt';
import useNetwork from '../../../hooks/useNetwork';
+import ONYXKEYS from '../../../ONYXKEYS';
const propTypes = {
...attachmentViewPropTypes,
@@ -38,6 +42,10 @@ const propTypes = {
/** Denotes whether it is a workspace avatar or not */
isWorkspaceAvatar: PropTypes.bool,
+
+ /** The id of the transaction related to the attachment */
+ // eslint-disable-next-line react/no-unused-prop-types
+ transactionID: PropTypes.string,
};
const defaultProps = {
@@ -47,6 +55,7 @@ const defaultProps = {
onToggleKeyboard: () => {},
containerStyles: [],
isWorkspaceAvatar: false,
+ transactionID: '',
};
function AttachmentView({
@@ -64,9 +73,9 @@ function AttachmentView({
isFocused,
isWorkspaceAvatar,
fallbackSource,
+ transaction,
}) {
const [loadComplete, setLoadComplete] = useState(false);
-
const [imageError, setImageError] = useState(false);
useNetwork({onReconnect: () => setImageError(false)});
@@ -113,6 +122,10 @@ function AttachmentView({
);
}
+ if (TransactionUtils.isDistanceRequest(transaction)) {
+ return ;
+ }
+
// For this check we use both source and file.name since temporary file source is a blob
// both PDFs and images will appear as images when pasted into the text field.
// We also check for numeric source since this is how static images (used for preview) are represented in RN.
@@ -168,4 +181,12 @@ AttachmentView.propTypes = propTypes;
AttachmentView.defaultProps = defaultProps;
AttachmentView.displayName = 'AttachmentView';
-export default compose(memo, withLocalize)(AttachmentView);
+export default compose(
+ memo,
+ withLocalize,
+ withOnyx({
+ transaction: {
+ key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
+ },
+ }),
+)(AttachmentView);
diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js
new file mode 100644
index 000000000000..7c7837b8413d
--- /dev/null
+++ b/src/components/DistanceEReceipt.js
@@ -0,0 +1,121 @@
+import React, {useMemo} from 'react';
+import {View, ScrollView} from 'react-native';
+import lodashGet from 'lodash/get';
+import _ from 'underscore';
+import Text from './Text';
+import styles from '../styles/styles';
+import transactionPropTypes from './transactionPropTypes';
+import * as ReceiptUtils from '../libs/ReceiptUtils';
+import * as ReportUtils from '../libs/ReportUtils';
+import * as CurrencyUtils from '../libs/CurrencyUtils';
+import * as TransactionUtils from '../libs/TransactionUtils';
+import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot';
+import ThumbnailImage from './ThumbnailImage';
+import useLocalize from '../hooks/useLocalize';
+import Icon from './Icon';
+import themeColors from '../styles/themes/default';
+import * as Expensicons from './Icon/Expensicons';
+import EReceiptBackground from '../../assets/images/eReceipt_background.svg';
+import useNetwork from '../hooks/useNetwork';
+import PendingMapView from './MapView/PendingMapView';
+
+const propTypes = {
+ /** The transaction for the distance request */
+ transaction: transactionPropTypes,
+};
+
+const defaultProps = {
+ transaction: {},
+};
+
+function DistanceEReceipt({transaction}) {
+ const {translate} = useLocalize();
+ const {isOffline} = useNetwork();
+ const {thumbnail} = TransactionUtils.hasReceipt(transaction) ? ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename) : {};
+ const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction);
+ const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd');
+ const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || '');
+ const waypoints = lodashGet(transaction, 'comment.waypoints', {});
+ const sortedWaypoints = useMemo(
+ () =>
+ // The waypoint keys are sometimes out of order
+ _.chain(waypoints)
+ .keys()
+ .sort((keyA, keyB) => TransactionUtils.getWaypointIndex(keyA) - TransactionUtils.getWaypointIndex(keyB))
+ .map((key) => ({[key]: waypoints[key]}))
+ .reduce((result, obj) => (obj ? _.assign(result, obj) : result), {})
+ .value(),
+ [waypoints],
+ );
+ return (
+
+
+
+
+
+ {isOffline || !thumbnailSource ? (
+
+ ) : (
+
+ )}
+
+
+ {formattedTransactionAmount}
+ {transactionMerchant}
+
+
+ {_.map(sortedWaypoints, (waypoint, key) => {
+ const index = TransactionUtils.getWaypointIndex(key);
+ let descriptionKey = 'distance.waypointDescription.';
+ if (index === 0) {
+ descriptionKey += 'start';
+ } else if (index === _.size(waypoints) - 1) {
+ descriptionKey += 'finish';
+ } else {
+ descriptionKey += 'stop';
+ }
+ return (
+
+ {translate(descriptionKey)}
+ {waypoint.address || ''}
+
+ );
+ })}
+
+ {translate('common.date')}
+ {transactionDate}
+
+
+
+
+ {translate('eReceipt.guaranteed')}
+
+
+
+
+ );
+}
+
+export default DistanceEReceipt;
+DistanceEReceipt.displayName = 'DistanceEReceipt';
+DistanceEReceipt.propTypes = propTypes;
+DistanceEReceipt.defaultProps = defaultProps;
diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js
index 76471aeab51a..ada40c24ed89 100644
--- a/src/components/Form/FormProvider.js
+++ b/src/components/Form/FormProvider.js
@@ -11,6 +11,7 @@ import compose from '../../libs/compose';
import {withNetwork} from '../OnyxProvider';
import stylePropTypes from '../../styles/stylePropTypes';
import networkPropTypes from '../networkPropTypes';
+import CONST from '../../CONST';
const propTypes = {
/** A unique Onyx key identifying the form */
@@ -98,19 +99,75 @@ function getInitialValueByType(valueType) {
}
}
-function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, children, formState, network, enabledWhenOffline, onSubmit, ...rest}) {
+function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnChange, children, formState, network, enabledWhenOffline, onSubmit, ...rest}) {
const inputRefs = useRef(null);
const touchedInputs = useRef({});
const [inputValues, setInputValues] = useState({});
const [errors, setErrors] = useState({});
+ const hasServerError = useMemo(() => Boolean(formState) && !_.isEmpty(formState.errors), [formState]);
const onValidate = useCallback(
- (values) => {
+ (values, shouldClearServerError = true) => {
+ const trimmedStringValues = {};
+ _.each(values, (inputValue, inputID) => {
+ if (_.isString(inputValue)) {
+ trimmedStringValues[inputID] = inputValue.trim();
+ } else {
+ trimmedStringValues[inputID] = inputValue;
+ }
+ });
+
+ if (shouldClearServerError) {
+ FormActions.setErrors(formID, null);
+ }
+ FormActions.setErrorFields(formID, null);
+
const validateErrors = validate(values) || {};
- setErrors(validateErrors);
- return validateErrors;
+
+ // Validate the input for html tags. It should supercede any other error
+ _.each(trimmedStringValues, (inputValue, inputID) => {
+ // If the input value is empty OR is non-string, we don't need to validate it for HTML tags
+ if (!inputValue || !_.isString(inputValue)) {
+ return;
+ }
+ const foundHtmlTagIndex = inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
+ const leadingSpaceIndex = inputValue.search(CONST.VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX);
+
+ // Return early if there are no HTML characters
+ if (leadingSpaceIndex === -1 && foundHtmlTagIndex === -1) {
+ return;
+ }
+
+ const matchedHtmlTags = inputValue.match(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
+ let isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(inputValue));
+ // Check for any matches that the original regex (foundHtmlTagIndex) matched
+ if (matchedHtmlTags) {
+ // Check if any matched inputs does not match in WHITELISTED_TAGS list and return early if needed.
+ for (let i = 0; i < matchedHtmlTags.length; i++) {
+ const htmlTag = matchedHtmlTags[i];
+ isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(htmlTag));
+ if (!isMatch) {
+ break;
+ }
+ }
+ }
+ // Add a validation error here because it is a string value that contains HTML characters
+ validateErrors[inputID] = 'common.error.invalidCharacter';
+ });
+
+ if (!_.isObject(validateErrors)) {
+ throw new Error('Validate callback must return an empty object or an object with shape {inputID: error}');
+ }
+
+ const touchedInputErrors = _.pick(validateErrors, (inputValue, inputID) => Boolean(touchedInputs.current[inputID]));
+
+ if (!_.isEqual(errors, touchedInputErrors)) {
+ setErrors(touchedInputErrors);
+ }
+
+ return touchedInputErrors;
},
- [validate],
+ [errors, formID, validate],
);
/**
@@ -186,6 +243,18 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c
propsToParse.onTouched(event);
}
},
+ onPress: (event) => {
+ setTouchedInput(inputID);
+ if (_.isFunction(propsToParse.onPress)) {
+ propsToParse.onPress(event);
+ }
+ },
+ onPressIn: (event) => {
+ setTouchedInput(inputID);
+ if (_.isFunction(propsToParse.onPressIn)) {
+ propsToParse.onPressIn(event);
+ }
+ },
onBlur: (event) => {
// Only run validation when user proactively blurs the input.
if (Visibility.isVisible() && Visibility.hasFocus()) {
@@ -195,7 +264,7 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c
setTimeout(() => {
setTouchedInput(inputID);
if (shouldValidateOnBlur) {
- onValidate(inputValues);
+ onValidate(inputValues, !hasServerError);
}
}, 200);
}
@@ -228,7 +297,7 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c
},
};
},
- [errors, formState, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange],
+ [errors, formState, hasServerError, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange],
);
const value = useMemo(() => ({registerInput}), [registerInput]);
@@ -237,6 +306,7 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c
{/* eslint-disable react/jsx-props-no-spreading */}
{},
payeePersonalDetails: null,
canModifyParticipants: false,
isReadOnly: false,
@@ -182,6 +193,7 @@ const defaultProps = {
transaction: {},
mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'},
isDistanceRequest: false,
+ isScanRequest: false,
shouldShowSmartScanFields: true,
isPolicyExpenseChat: false,
};
@@ -197,6 +209,8 @@ function MoneyRequestConfirmationList(props) {
const isSplitBill = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.SPLIT;
const isTypeSend = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.SEND;
+ const isSplitWithScan = isSplitBill && props.isScanRequest;
+
const {unit, rate, currency} = props.mileageRate;
const distance = lodashGet(transaction, 'routes.route0.distance', 0);
const shouldCalculateDistanceAmount = props.isDistanceRequest && props.iouAmount === 0;
@@ -211,9 +225,9 @@ function MoneyRequestConfirmationList(props) {
// Do not hide fields in case of send money request
const shouldShowAllFields = props.isDistanceRequest || shouldExpandFields || !props.shouldShowSmartScanFields || isTypeSend || props.isEditingSplitBill;
- // In Send Money flow, we don't allow the Merchant or Date to be edited. For distance requests, don't show the merchant as there's already another "Distance" menu item
- const shouldShowDate = shouldShowAllFields && !isTypeSend;
- const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !props.isDistanceRequest;
+ // In Send Money and Split Bill with Scan flow, we don't allow the Merchant or Date to be edited. For distance requests, don't show the merchant as there's already another "Distance" menu item
+ const shouldShowDate = shouldShowAllFields && !isTypeSend && !isSplitWithScan;
+ const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !props.isDistanceRequest && !isSplitWithScan;
// Fetches the first tag list of the policy
const policyTag = PolicyUtils.getTag(props.policyTags);
diff --git a/src/components/MoneyRequestHeader.js b/src/components/MoneyRequestHeader.js
index 0f2d19d424b6..e35574486e21 100644
--- a/src/components/MoneyRequestHeader.js
+++ b/src/components/MoneyRequestHeader.js
@@ -19,6 +19,7 @@ import ConfirmModal from './ConfirmModal';
import useLocalize from '../hooks/useLocalize';
import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar';
import * as TransactionUtils from '../libs/TransactionUtils';
+import * as ReportActionsUtils from '../libs/ReportActionsUtils';
import * as HeaderUtils from '../libs/HeaderUtils';
import reportActionPropTypes from '../pages/home/report/reportActionPropTypes';
import transactionPropTypes from './transactionPropTypes';
@@ -81,7 +82,9 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
}, [parentReportAction, setIsDeleteModalVisible]);
const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction);
- const canModifyRequest = isActionOwner && !isSettled && !isApproved;
+ const isPending = TransactionUtils.isPending(transaction);
+
+ const canModifyRequest = isActionOwner && !isSettled && !isApproved && !ReportActionsUtils.isDeletedAction(parentReportAction);
useEffect(() => {
if (canModifyRequest) {
@@ -110,6 +113,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
<>
Navigation.goBack(ROUTES.HOME, false, true)}
/>
- {isScanning && }
+ {isPending && (
+
+ )}
+ {isScanning && (
+
+ )}
+
- {translate('iou.receiptStatusTitle')}
+ {title}
- {translate('iou.receiptStatusText')}
+ {description}
);
}
MoneyRequestHeaderStatusBar.displayName = 'MoneyRequestHeaderStatusBar';
+MoneyRequestHeaderStatusBar.propTypes = propTypes;
export default MoneyRequestHeaderStatusBar;
diff --git a/src/components/NewDatePicker/CalendarPicker/index.js b/src/components/NewDatePicker/CalendarPicker/index.js
index 1e1ef3c3fad3..d03c36997845 100644
--- a/src/components/NewDatePicker/CalendarPicker/index.js
+++ b/src/components/NewDatePicker/CalendarPicker/index.js
@@ -125,8 +125,8 @@ class CalendarPicker extends React.PureComponent {
const currentMonthView = this.state.currentDateView.getMonth();
const currentYearView = this.state.currentDateView.getFullYear();
const calendarDaysMatrix = generateMonthMatrix(currentYearView, currentMonthView);
- const hasAvailableDatesNextMonth = moment(this.props.maxDate).endOf('month').startOf('day') > moment(this.state.currentDateView).add(1, 'months');
- const hasAvailableDatesPrevMonth = moment(this.props.minDate).startOf('day') < moment(this.state.currentDateView).subtract(1, 'months').endOf('month');
+ const hasAvailableDatesNextMonth = moment(this.props.maxDate).endOf('month').endOf('day') >= moment(this.state.currentDateView).add(1, 'months');
+ const hasAvailableDatesPrevMonth = moment(this.props.minDate).startOf('month').startOf('day') <= moment(this.state.currentDateView).subtract(1, 'months');
return (
diff --git a/src/components/OptionsList/BaseOptionsList.js b/src/components/OptionsList/BaseOptionsList.js
index 23049b65f198..edea0b8d1aba 100644
--- a/src/components/OptionsList/BaseOptionsList.js
+++ b/src/components/OptionsList/BaseOptionsList.js
@@ -66,6 +66,7 @@ function BaseOptionsList({
isDisabled,
innerRef,
isRowMultilineSupported,
+ isLoadingNewOptions,
}) {
const flattenedData = useRef();
const previousSections = usePrevious(sections);
@@ -245,7 +246,9 @@ function BaseOptionsList({
) : (
<>
- {headerMessage ? (
+ {/* If we are loading new options we will avoid showing any header message. This is mostly because one of the header messages says there are no options. */}
+ {/* This is misleading because we might be in the process of loading fresh options from the server. */}
+ {!isLoadingNewOptions && headerMessage ? (
{headerMessage}
diff --git a/src/components/OptionsList/optionsListPropTypes.js b/src/components/OptionsList/optionsListPropTypes.js
index 165cec699b80..dc716453b2a8 100644
--- a/src/components/OptionsList/optionsListPropTypes.js
+++ b/src/components/OptionsList/optionsListPropTypes.js
@@ -87,6 +87,9 @@ const propTypes = {
/** Whether to wrap large text up to 2 lines */
isRowMultilineSupported: PropTypes.bool,
+
+ /** Whether we are loading new options */
+ isLoadingNewOptions: PropTypes.bool,
};
const defaultProps = {
@@ -113,6 +116,7 @@ const defaultProps = {
shouldPreventDefaultFocusOnSelectRow: false,
showScrollIndicator: false,
isRowMultilineSupported: false,
+ isLoadingNewOptions: false,
};
export {propTypes, defaultProps};
diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js
index e72bb7ef4b8e..3c9d401cdbdb 100755
--- a/src/components/OptionsSelector/BaseOptionsSelector.js
+++ b/src/components/OptionsSelector/BaseOptionsSelector.js
@@ -17,6 +17,7 @@ import {propTypes as optionsSelectorPropTypes, defaultProps as optionsSelectorDe
import setSelection from '../../libs/setSelection';
import compose from '../../libs/compose';
import getPlatform from '../../libs/getPlatform';
+import FormHelpMessage from '../FormHelpMessage';
const propTypes = {
/** padding bottom style of safe area */
@@ -392,6 +393,7 @@ class BaseOptionsSelector extends Component {
blurOnSubmit={Boolean(this.state.allOptions.length)}
spellCheck={false}
shouldInterceptSwipe={this.props.shouldTextInputInterceptSwipe}
+ isLoading={this.props.isLoadingNewOptions}
/>
);
const optionsList = (
@@ -428,6 +430,7 @@ class BaseOptionsSelector extends Component {
isLoading={!this.props.shouldShowOptions}
showScrollIndicator={this.props.showScrollIndicator}
isRowMultilineSupported={this.props.isRowMultilineSupported}
+ isLoadingNewOptions={this.props.isLoadingNewOptions}
shouldPreventDefaultFocusOnSelectRow={this.props.shouldPreventDefaultFocusOnSelectRow}
/>
);
@@ -453,6 +456,13 @@ class BaseOptionsSelector extends Component {
{this.props.children}
{this.props.shouldShowTextInput && textInput}
+ {Boolean(this.props.textInputAlert) && (
+
+ )}
{optionsList}
>
diff --git a/src/components/RNTextInput.js b/src/components/RNTextInput.js
index 37020204a6ee..5a790cde91d7 100644
--- a/src/components/RNTextInput.js
+++ b/src/components/RNTextInput.js
@@ -21,6 +21,7 @@ function RNTextInput(props) {
return (
{
if (!_.isFunction(props.forwardedRef)) {
return;
diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js
index c7ca93e87694..720fa292de53 100644
--- a/src/components/ReportActionItem/MoneyRequestPreview.js
+++ b/src/components/ReportActionItem/MoneyRequestPreview.js
@@ -175,7 +175,7 @@ function MoneyRequestPreview(props) {
const receiptImages = hasReceipt ? [ReceiptUtils.getThumbnailAndImageURIs(props.transaction.receipt.source, props.transaction.filename || '')] : [];
const getSettledMessage = () => {
- if (isExpensifyCardTransaction || isDistanceRequest) {
+ if (isExpensifyCardTransaction) {
return props.translate('common.done');
}
switch (lodashGet(props.action, 'originalMessage.paymentType', '')) {
@@ -222,7 +222,7 @@ function MoneyRequestPreview(props) {
const getDisplayAmountText = () => {
if (isDistanceRequest) {
- return CurrencyUtils.convertToDisplayString(TransactionUtils.getAmount(props.transaction), props.transaction.currency);
+ return requestAmount ? CurrencyUtils.convertToDisplayString(requestAmount, props.transaction.currency) : props.translate('common.tbd');
}
if (isScanning) {
@@ -252,7 +252,8 @@ function MoneyRequestPreview(props) {
{hasReceipt && (
)}
{_.isEmpty(props.transaction) &&
@@ -262,20 +263,7 @@ function MoneyRequestPreview(props) {
) : (
-
- {getPreviewHeaderText()}
- {isSettled && (
- <>
-
- {getSettledMessage()}
- >
- )}
-
+ {getPreviewHeaderText() + (isSettled ? ` • ${getSettledMessage()}` : '')}
{hasFieldErrors && (
ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]);
@@ -109,11 +121,24 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should
const shouldShowTag = isPolicyExpenseChat && Permissions.canUseTags(betas) && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagsList)));
const shouldShowBillable = isPolicyExpenseChat && Permissions.canUseTags(betas) && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true));
- let description = `${translate('iou.amount')} • ${translate('iou.cash')}`;
- if (isSettled) {
- description += ` • ${translate('iou.settledExpensify')}`;
- } else if (report.isWaitingOnBankAccount) {
- description += ` • ${translate('iou.pending')}`;
+ let amountDescription = `${translate('iou.amount')}`;
+
+ if (isExpensifyCardTransaction) {
+ if (formattedOriginalAmount) {
+ amountDescription += ` • ${translate('iou.original')} ${formattedOriginalAmount}`;
+ }
+ if (TransactionUtils.isPending(transaction)) {
+ amountDescription += ` • ${translate('iou.pending')}`;
+ }
+ } else {
+ if (!isDistanceRequest) {
+ amountDescription += ` • ${translate('iou.cash')}`;
+ }
+ if (isSettled) {
+ amountDescription += ` • ${translate('iou.settledExpensify')}`;
+ } else if (report.isWaitingOnBankAccount) {
+ amountDescription += ` • ${translate('iou.pending')}`;
+ }
}
// A temporary solution to hide the transaction detail
@@ -130,7 +155,6 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should
hasErrors = canEdit && TransactionUtils.hasMissingSmartscanFields(transaction);
}
- const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const pendingAction = lodashGet(transaction, 'pendingAction');
const getPendingFieldAction = (fieldPath) => lodashGet(transaction, fieldPath) || pendingAction;
@@ -156,7 +180,7 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should
title={formattedTransactionAmount ? formattedTransactionAmount.toString() : ''}
shouldShowTitleIcon={isSettled}
titleIcon={Expensicons.Checkmark}
- description={description}
+ description={amountDescription}
titleStyle={styles.newKansasLarge}
interactive={canEdit}
shouldShowRightIcon={canEdit}
@@ -178,18 +202,6 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should
numberOfLinesTitle={0}
/>
-
- Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
- brickRoadIndicator={hasErrors && transactionDate === '' ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''}
- error={hasErrors && transactionDate === '' ? translate('common.error.enterDate') : ''}
- />
-
{isDistanceRequest ? (
)}
+
+ Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
+ brickRoadIndicator={hasErrors && transactionDate === '' ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''}
+ error={hasErrors && transactionDate === '' ? translate('common.error.enterDate') : ''}
+ />
+
{shouldShowCategory && (
)}
+ {isExpensifyCardTransaction ? (
+
+
+
+ ) : null}
{shouldShowBillable && (
{translate('common.billable')}
diff --git a/src/components/ReportActionItem/ReportActionItemImages.js b/src/components/ReportActionItem/ReportActionItemImages.js
index 7e6287720952..ce49f519df66 100644
--- a/src/components/ReportActionItem/ReportActionItemImages.js
+++ b/src/components/ReportActionItem/ReportActionItemImages.js
@@ -5,6 +5,8 @@ import _ from 'underscore';
import styles from '../../styles/styles';
import Text from '../Text';
import ReportActionItemImage from './ReportActionItemImage';
+import * as StyleUtils from '../../styles/StyleUtils';
+import variables from '../../styles/variables';
const propTypes = {
/** array of image and thumbnail URIs */
@@ -48,10 +50,22 @@ function ReportActionItemImages({images, size, total, isHovered}) {
const numberOfShownImages = size || images.length;
const shownImages = images.slice(0, size);
const remaining = (total || images.length) - size;
+ const MAX_REMAINING = 9;
+
+ // The height varies depending on the number of images we are displaying.
+ let heightStyle = {};
+ if (numberOfShownImages === 1) {
+ heightStyle = StyleUtils.getHeight(variables.reportActionImagesSingleImageHeight);
+ } else if (numberOfShownImages === 2) {
+ heightStyle = StyleUtils.getHeight(variables.reportActionImagesDoubleImageHeight);
+ } else if (numberOfShownImages > 2) {
+ heightStyle = StyleUtils.getHeight(variables.reportActionImagesMultipleImageHeight);
+ }
const hoverStyle = isHovered ? styles.reportPreviewBoxHoverBorder : undefined;
+
return (
-
+
{_.map(shownImages, ({thumbnail, image}, index) => {
const isLastImage = index === numberOfShownImages - 1;
@@ -68,8 +82,10 @@ function ReportActionItemImages({images, size, total, isHovered}) {
image={image}
/>
{isLastImage && remaining > 0 && (
-
- +{remaining}
+
+
+
+ {remaining > MAX_REMAINING ? `${MAX_REMAINING}+` : `+${remaining}`}
)}
diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js
index f9001ed51258..0ddd8098f460 100644
--- a/src/components/ReportActionItem/ReportPreview.js
+++ b/src/components/ReportActionItem/ReportPreview.js
@@ -127,7 +127,7 @@ function ReportPreview(props) {
const hasErrors = hasReceipts && ReportUtils.hasMissingSmartscanFields(props.iouReportID);
const lastThreeTransactionsWithReceipts = ReportUtils.getReportPreviewDisplayTransactions(props.action);
const lastThreeReceipts = _.map(lastThreeTransactionsWithReceipts, ({receipt, filename}) => ReceiptUtils.getThumbnailAndImageURIs(receipt.source, filename || ''));
-
+ const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(props.iouReportID);
const hasOnlyOneReceiptRequest = numberOfRequests === 1 && hasReceipts;
const previewSubtitle = hasOnlyOneReceiptRequest
? TransactionUtils.getMerchant(transactionsWithReceipts[0])
@@ -166,7 +166,11 @@ function ReportPreview(props) {
return props.translate('iou.managerApproved', {manager: ReportUtils.getDisplayNameForParticipant(managerID, true)});
}
const managerName = isPolicyExpenseChat ? ReportUtils.getPolicyName(props.chatReport) : ReportUtils.getDisplayNameForParticipant(managerID, true);
- return props.translate(iouSettled || props.iouReport.isWaitingOnBankAccount ? 'iou.payerPaid' : 'iou.payerOwes', {payer: managerName});
+ let paymentVerb = hasNonReimbursableTransactions ? 'iou.payerSpent' : 'iou.payerOwes';
+ if (iouSettled || props.iouReport.isWaitingOnBankAccount) {
+ paymentVerb = 'iou.payerPaid';
+ }
+ return props.translate(paymentVerb, {payer: managerName});
};
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
diff --git a/src/components/Section.js b/src/components/Section.js
index cd390be0d00b..c0b07d1c1453 100644
--- a/src/components/Section.js
+++ b/src/components/Section.js
@@ -14,6 +14,9 @@ const propTypes = {
/** The text to display in the title of the section */
title: PropTypes.string.isRequired,
+ /** The text to display in the subtitle of the section */
+ subtitle: PropTypes.string,
+
/** The icon to display along with the title */
icon: PropTypes.func,
@@ -27,6 +30,18 @@ const propTypes = {
// eslint-disable-next-line react/forbid-prop-types
containerStyles: PropTypes.arrayOf(PropTypes.object),
+ /** Customize the Section container */
+ // eslint-disable-next-line react/forbid-prop-types
+ titleStyles: PropTypes.arrayOf(PropTypes.object),
+
+ /** Customize the Section container */
+ // eslint-disable-next-line react/forbid-prop-types
+ subtitleStyles: PropTypes.arrayOf(PropTypes.object),
+
+ /** Customize the Section container */
+ // eslint-disable-next-line react/forbid-prop-types
+ childrenStyles: PropTypes.arrayOf(PropTypes.object),
+
/** Customize the Icon container */
// eslint-disable-next-line react/forbid-prop-types
iconContainerStyles: PropTypes.arrayOf(PropTypes.object),
@@ -39,21 +54,24 @@ const defaultProps = {
IconComponent: null,
containerStyles: [],
iconContainerStyles: [],
+ titleStyles: [],
+ subtitleStyles: [],
+ childrenStyles: [],
+ subtitle: null,
};
-function Section(props) {
- const IconComponent = props.IconComponent;
+function Section({children, childrenStyles, containerStyles, icon, IconComponent, iconContainerStyles, menuItems, subtitle, subtitleStyles, title, titleStyles}) {
return (
<>
-
-
+
+
- {props.title}
+ {title}
-
- {Boolean(props.icon) && (
+
+ {Boolean(icon) && (
@@ -62,9 +80,15 @@ function Section(props) {
- {props.children}
+ {Boolean(subtitle) && (
+
+ {subtitle}
+
+ )}
+
+ {children}
- {Boolean(props.menuItems) && }
+ {Boolean(menuItems) && }
>
);
diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js
index 86ed932ab0d6..fdb1f92ca73b 100644
--- a/src/components/SelectionList/BaseSelectionList.js
+++ b/src/components/SelectionList/BaseSelectionList.js
@@ -22,8 +22,8 @@ import Log from '../../libs/Log';
import OptionsListSkeletonView from '../OptionsListSkeletonView';
import useActiveElement from '../../hooks/useActiveElement';
import BaseListItem from './BaseListItem';
-import themeColors from '../../styles/themes/default';
import ArrowKeyFocusManager from '../ArrowKeyFocusManager';
+import themeColors from '../../styles/themes/default';
const propTypes = {
...keyboardStatePropTypes,
@@ -426,7 +426,7 @@ function BaseSelectionList({
onScrollBeginDrag={onScrollBeginDrag}
keyExtractor={(item) => item.keyForList}
extraData={focusedIndex}
- indicatorStyle={themeColors.selectionListIndicatorColor}
+ indicatorStyle={themeColors.white}
keyboardShouldPersistTaps="always"
showsVerticalScrollIndicator={showScrollIndicator}
initialNumToRender={12}
diff --git a/src/components/SignInButtons/GoogleSignIn/index.native.js b/src/components/SignInButtons/GoogleSignIn/index.native.js
index 9e638f0723cf..099fbfde22fd 100644
--- a/src/components/SignInButtons/GoogleSignIn/index.native.js
+++ b/src/components/SignInButtons/GoogleSignIn/index.native.js
@@ -25,14 +25,18 @@ function googleSignInRequest() {
.then((response) => response.idToken)
.then((token) => Session.beginGoogleSignIn(token))
.catch((error) => {
+ // Handle unexpected error shape
+ if (error === undefined || error.code === undefined) {
+ Log.alert(`[Google Sign In] Google sign in failed: ${error}`);
+ }
+ /** The logged code is useful for debugging any new errors that are not specifically handled. To decode, see:
+ - The common status codes documentation: https://developers.google.com/android/reference/com/google/android/gms/common/api/CommonStatusCodes
+ - The Google Sign In codes documentation: https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes
+ */
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
- Log.alert('[Google Sign In] Google sign in cancelled', true, {error});
- } else if (error.code === statusCodes.IN_PROGRESS) {
- Log.alert('[Google Sign In] Google sign in already in progress', true, {error});
- } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
- Log.alert('[Google Sign In] Google play services not available or outdated', true, {error});
+ Log.info('[Google Sign In] Google Sign In cancelled');
} else {
- Log.alert('[Google Sign In] Unknown Google sign in error', true, {error});
+ Log.alert(`[Google Sign In] Error Code: ${error.code}. ${error.message}`, {}, false);
}
});
}
diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js
index cfc042b4f370..9bfdc79fad68 100644
--- a/src/components/TextInput/BaseTextInput.js
+++ b/src/components/TextInput/BaseTextInput.js
@@ -1,6 +1,6 @@
import _ from 'underscore';
import React, {useState, useRef, useEffect, useCallback, useMemo} from 'react';
-import {Animated, View, StyleSheet} from 'react-native';
+import {Animated, View, StyleSheet, ActivityIndicator} from 'react-native';
import Str from 'expensify-common/lib/str';
import RNTextInput from '../RNTextInput';
import TextInputLabel from './TextInputLabel';
@@ -47,19 +47,11 @@ function BaseTextInput(props) {
return;
}
- let focusTimeout;
if (props.shouldDelayFocus) {
- focusTimeout = setTimeout(() => input.current.focus(), CONST.ANIMATED_TRANSITION);
- return;
+ const focusTimeout = setTimeout(() => input.current.focus(), CONST.ANIMATED_TRANSITION);
+ return () => clearTimeout(focusTimeout);
}
input.current.focus();
-
- return () => {
- if (!focusTimeout) {
- return;
- }
- clearTimeout(focusTimeout);
- };
// We only want this to run on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -372,6 +364,13 @@ function BaseTextInput(props) {
// `dataset.submitOnEnter` is used to indicate that pressing Enter on this input should call the submit callback.
dataSet={{submitOnEnter: isMultiline && props.submitOnEnter}}
/>
+ {props.isLoading && (
+
+ )}
{Boolean(props.secureTextEntry) && (
e.preventDefault()}
+ onTouchStart={(e) => e.preventDefault()}
>
{},
+ onItemSelected: () => {},
+};
+
+function ValueSelectorModal({currentValue, items, selectedItem, label, isVisible, onClose, onItemSelected}) {
+ const [sectionsData, setSectionsData] = useState([]);
+
+ useEffect(() => {
+ const itemsData = _.map(items, (item) => ({value: item.value, keyForList: item.value, text: item.label, isSelected: item === selectedItem}));
+ setSectionsData(itemsData);
+ }, [items, selectedItem]);
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+ValueSelectorModal.propTypes = propTypes;
+ValueSelectorModal.defaultProps = defaultProps;
+ValueSelectorModal.displayName = 'ValueSelectorModal';
+
+export default ValueSelectorModal;
diff --git a/src/components/ValuePicker/index.js b/src/components/ValuePicker/index.js
new file mode 100644
index 000000000000..161fbbfadb8b
--- /dev/null
+++ b/src/components/ValuePicker/index.js
@@ -0,0 +1,102 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import PropTypes from 'prop-types';
+import _ from 'lodash';
+import styles from '../../styles/styles';
+import MenuItemWithTopDescription from '../MenuItemWithTopDescription';
+import ValueSelectorModal from './ValueSelectorModal';
+import FormHelpMessage from '../FormHelpMessage';
+import refPropTypes from '../refPropTypes';
+
+const propTypes = {
+ /** Form Error description */
+ errorText: PropTypes.string,
+
+ /** Item to display */
+ value: PropTypes.string,
+
+ /** A placeholder value to display */
+ placeholder: PropTypes.string,
+
+ /** Items to pick from */
+ items: PropTypes.arrayOf(PropTypes.shape({value: PropTypes.string, label: PropTypes.string})),
+
+ /** Label of picker */
+ label: PropTypes.string,
+
+ /** Callback to call when the input changes */
+ onInputChange: PropTypes.func,
+
+ /** A ref to forward to MenuItemWithTopDescription */
+ forwardedRef: refPropTypes,
+};
+
+const defaultProps = {
+ value: undefined,
+ label: undefined,
+ placeholder: '',
+ items: {},
+ forwardedRef: undefined,
+ errorText: '',
+ onInputChange: () => {},
+};
+
+function ValuePicker({value, label, items, placeholder, errorText, onInputChange, forwardedRef}) {
+ const [isPickerVisible, setIsPickerVisible] = useState(false);
+
+ const showPickerModal = () => {
+ setIsPickerVisible(true);
+ };
+
+ const hidePickerModal = () => {
+ setIsPickerVisible(false);
+ };
+
+ const updateInput = (item) => {
+ if (item.value !== value) {
+ onInputChange(item.value);
+ }
+ hidePickerModal();
+ };
+
+ const descStyle = value.length === 0 ? styles.textNormal : null;
+ const selectedItem = _.find(items, {value});
+ const selectedLabel = selectedItem ? selectedItem.label : '';
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+ValuePicker.propTypes = propTypes;
+ValuePicker.defaultProps = defaultProps;
+ValuePicker.displayName = 'ValuePicker';
+
+export default React.forwardRef((props, ref) => (
+
+));
diff --git a/src/components/WalletSection.js b/src/components/WalletSection.js
new file mode 100644
index 000000000000..ec8a1680937c
--- /dev/null
+++ b/src/components/WalletSection.js
@@ -0,0 +1,45 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import Section from './Section';
+import styles from '../styles/styles';
+
+const propTypes = {
+ /** Contents to display inside the section */
+ children: PropTypes.node,
+
+ /** The icon to display along with the title */
+ icon: PropTypes.func,
+
+ /** The text to display in the subtitle of the section */
+ subtitle: PropTypes.string,
+
+ /** The text to display in the title of the section */
+ title: PropTypes.string.isRequired,
+};
+
+const defaultProps = {
+ children: null,
+ icon: null,
+ subtitle: null,
+};
+
+function WalletSection({children, icon, subtitle, title}) {
+ return (
+
+ );
+}
+
+WalletSection.defaultProps = defaultProps;
+WalletSection.displayName = 'WalletSection';
+WalletSection.propTypes = propTypes;
+
+export default WalletSection;
diff --git a/src/hooks/useDragAndDrop.js b/src/hooks/useDragAndDrop.ts
similarity index 83%
rename from src/hooks/useDragAndDrop.js
rename to src/hooks/useDragAndDrop.ts
index fb1d158e4063..27230dd94679 100644
--- a/src/hooks/useDragAndDrop.js
+++ b/src/hooks/useDragAndDrop.ts
@@ -1,4 +1,4 @@
-import {useEffect, useRef, useState, useCallback} from 'react';
+import React, {useEffect, useRef, useState, useCallback} from 'react';
import {useIsFocused} from '@react-navigation/native';
const COPY_DROP_EFFECT = 'copy';
@@ -8,15 +8,22 @@ const DRAG_OVER_EVENT = 'dragover';
const DRAG_LEAVE_EVENT = 'dragleave';
const DROP_EVENT = 'drop';
+type DragAndDropParams = {
+ dropZone: React.MutableRefObject;
+ onDrop?: (event?: DragEvent) => void;
+ shouldAllowDrop?: boolean;
+ isDisabled?: boolean;
+ shouldAcceptDrop?: (event?: DragEvent) => boolean;
+};
+
+type DragAndDropOptions = {
+ isDraggingOver: boolean;
+};
+
/**
- * @param {Object} dropZone – ref to the dropZone component
- * @param {Function} [onDrop]
- * @param {Boolean} [shouldAllowDrop]
- * @param {Boolean} [isDisabled]
- * @param {Function} [shouldAcceptDrop]
- * @returns {{isDraggingOver: Boolean}}
+ * @param dropZone – ref to the dropZone component
*/
-export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllowDrop = true, isDisabled = false, shouldAcceptDrop = () => true}) {
+export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllowDrop = true, isDisabled = false, shouldAcceptDrop = () => true}: DragAndDropParams): DragAndDropOptions {
const isFocused = useIsFocused();
const [isDraggingOver, setIsDraggingOver] = useState(false);
@@ -36,23 +43,24 @@ export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllow
}, [isFocused, isDisabled]);
const setDropEffect = useCallback(
- (event) => {
+ (event: DragEvent) => {
const effect = shouldAllowDrop && shouldAcceptDrop(event) ? COPY_DROP_EFFECT : NONE_DROP_EFFECT;
- // eslint-disable-next-line no-param-reassign
- event.dataTransfer.dropEffect = effect;
- // eslint-disable-next-line no-param-reassign
- event.dataTransfer.effectAllowed = effect;
+
+ if (event.dataTransfer) {
+ // eslint-disable-next-line no-param-reassign
+ event.dataTransfer.dropEffect = effect;
+ // eslint-disable-next-line no-param-reassign
+ event.dataTransfer.effectAllowed = effect;
+ }
},
[shouldAllowDrop, shouldAcceptDrop],
);
/**
* Handles all types of drag-N-drop events on the drop zone associated with composer
- *
- * @param {Object} event native Event
*/
const dropZoneDragHandler = useCallback(
- (event) => {
+ (event: DragEvent) => {
if (!isFocused || isDisabled || !shouldAcceptDrop(event)) {
return;
}
diff --git a/src/languages/en.ts b/src/languages/en.ts
index b6f3fe877011..4f96314c4efa 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -27,6 +27,7 @@ import type {
SettleExpensifyCardParams,
RequestAmountParams,
SplitAmountParams,
+ DidSplitAmountMessageParams,
AmountEachParams,
PayerOwesAmountParams,
PayerOwesParams,
@@ -517,6 +518,7 @@ export default {
approved: 'Approved',
cash: 'Cash',
card: 'Card',
+ original: 'Original',
split: 'Split',
addToSplit: 'Add to split',
splitBill: 'Split bill',
@@ -534,6 +536,7 @@ export default {
receiptStatusTitle: 'Scanning…',
receiptStatusText: "Only you can see this receipt when it's scanning. Check back later or enter the details now.",
receiptScanningFailed: 'Receipt scanning failed. Enter the details manually.',
+ transactionPendingText: 'It takes a few days from the date the card was used for the transaction to post.',
requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} requests${scanningReceipts > 0 ? `, ${scanningReceipts} scanning` : ''}`,
deleteRequest: 'Delete request',
deleteConfirmation: 'Are you sure that you want to delete this request?',
@@ -544,11 +547,14 @@ export default {
requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`,
requestedAmount: ({formattedAmount, comment}: RequestedAmountMessageParams) => `requested ${formattedAmount}${comment ? ` for ${comment}` : ''}`,
splitAmount: ({amount}: SplitAmountParams) => `split ${amount}`,
+ didSplitAmount: ({formattedAmount, comment}: DidSplitAmountMessageParams) => `split ${formattedAmount}${comment ? ` for ${comment}` : ''}`,
amountEach: ({amount}: AmountEachParams) => `${amount} each`,
payerOwesAmount: ({payer, amount}: PayerOwesAmountParams) => `${payer} owes ${amount}`,
payerOwes: ({payer}: PayerOwesParams) => `${payer} owes: `,
payerPaidAmount: ({payer, amount}: PayerPaidAmountParams): string => `${payer} paid ${amount}`,
payerPaid: ({payer}: PayerPaidParams) => `${payer} paid: `,
+ payerSpentAmount: ({payer, amount}: PayerPaidAmountParams): string => `${payer} spent ${amount}`,
+ payerSpent: ({payer}: PayerPaidParams) => `${payer} spent: `,
managerApproved: ({manager}: ManagerApprovedParams) => `${manager} approved:`,
payerSettled: ({amount}: PayerSettledParams) => `paid ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`,
@@ -836,6 +842,19 @@ export default {
setDefaultFailure: 'Something went wrong. Please chat with Concierge for further assistance.',
},
addBankAccountFailure: 'An unexpected error occurred while trying to add your bank account. Please try again.',
+ getPaidFaster: 'Get paid faster',
+ addPaymentMethod: 'Add a payment method to send and receive payments directly in the app.',
+ getPaidBackFaster: 'Get paid back faster',
+ secureAccessToYourMoney: 'Secure access to your money',
+ receiveMoney: 'Receive money in your local currency',
+ expensifyWallet: 'Expensify Wallet',
+ sendAndReceiveMoney: 'Send and receive money from your Expensify Wallet.',
+ bankAccounts: 'Bank accounts',
+ addBankAccountToSendAndReceive: 'Add a bank account to send and receive payments directly in the app.',
+ addBankAccount: 'Add bank account',
+ assignedCards: 'Assigned cards',
+ assignedCardsDescription: 'These are cards assigned by a Workspace admin to manage company spend.',
+ expensifyCard: 'Expensify Card',
},
cardPage: {
expensifyCard: 'Expensify Card',
@@ -912,6 +931,7 @@ export default {
},
welcomeMessagePage: {
welcomeMessage: 'Welcome message',
+ welcomeMessageOptional: 'Welcome message (optional)',
explainerText: 'Set a custom welcome message that will be sent to users when they join this room.',
},
languagePage: {
@@ -1612,6 +1632,9 @@ export default {
screenShare: 'Screen share',
screenShareRequest: 'Expensify is inviting you to a screen share',
},
+ search: {
+ resultsAreLimited: 'Search results are limited.',
+ },
genericErrorPage: {
title: 'Uh-oh, something went wrong!',
body: {
@@ -1842,11 +1865,11 @@ export default {
selectSuggestedAddress: 'Please select a suggested address or use current location',
},
},
- globalNavigationOptions: {
- chats: 'Chats',
- },
eReceipt: {
guaranteed: 'Guaranteed eReceipt',
transactionDate: 'Transaction date',
},
+ globalNavigationOptions: {
+ chats: 'Chats',
+ },
} satisfies TranslationBase;
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 956a9764c8f4..cd585ae88e7e 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -27,6 +27,7 @@ import type {
SettleExpensifyCardParams,
RequestAmountParams,
SplitAmountParams,
+ DidSplitAmountMessageParams,
AmountEachParams,
PayerOwesAmountParams,
PayerOwesParams,
@@ -509,6 +510,7 @@ export default {
approved: 'Aprobado',
cash: 'Efectivo',
card: 'Tarjeta',
+ original: 'Original',
split: 'Dividir',
addToSplit: 'Añadir para dividir',
splitBill: 'Dividir factura',
@@ -526,6 +528,7 @@ export default {
receiptStatusTitle: 'Escaneando…',
receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.',
receiptScanningFailed: 'El escaneo de recibo ha fallado. Introduce los detalles manualmente.',
+ transactionPendingText: 'La transacción tarda unos días en contabilizarse desde la fecha en que se utilizó la tarjeta.',
requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} solicitudes${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}`,
deleteRequest: 'Eliminar pedido',
deleteConfirmation: '¿Estás seguro de que quieres eliminar este pedido?',
@@ -536,11 +539,14 @@ export default {
requestAmount: ({amount}: RequestAmountParams) => `solicitar ${amount}`,
requestedAmount: ({formattedAmount, comment}: RequestedAmountMessageParams) => `solicité ${formattedAmount}${comment ? ` para ${comment}` : ''}`,
splitAmount: ({amount}: SplitAmountParams) => `dividir ${amount}`,
+ didSplitAmount: ({formattedAmount, comment}: DidSplitAmountMessageParams) => `dividió ${formattedAmount}${comment ? ` para ${comment}` : ''}`,
amountEach: ({amount}: AmountEachParams) => `${amount} cada uno`,
payerOwesAmount: ({payer, amount}: PayerOwesAmountParams) => `${payer} debe ${amount}`,
payerOwes: ({payer}: PayerOwesParams) => `${payer} debe: `,
payerPaidAmount: ({payer, amount}: PayerPaidAmountParams) => `${payer} pagó ${amount}`,
payerPaid: ({payer}: PayerPaidParams) => `${payer} pagó: `,
+ payerSpentAmount: ({payer, amount}: PayerPaidAmountParams): string => `${payer} gastó ${amount}`,
+ payerSpent: ({payer}: PayerPaidParams) => `${payer} gastó: `,
managerApproved: ({manager}: ManagerApprovedParams) => `${manager} aprobó:`,
payerSettled: ({amount}: PayerSettledParams) => `pagó ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} añada una cuenta bancaria`,
@@ -832,6 +838,19 @@ export default {
setDefaultFailure: 'No se ha podido configurar el método de pago.',
},
addBankAccountFailure: 'Ocurrió un error inesperado al intentar añadir la cuenta bancaria. Inténtalo de nuevo.',
+ getPaidFaster: 'Cobra más rápido',
+ addPaymentMethod: 'Añade un método de pago para enviar y recibir pagos directamente en la aplicación.',
+ getPaidBackFaster: 'Recibe tus pagos más rápido',
+ secureAccessToYourMoney: 'Acceso seguro a tu dinero',
+ receiveMoney: 'Recibe dinero en tu moneda local',
+ expensifyWallet: 'Billetera Expensify',
+ sendAndReceiveMoney: 'Envía y recibe dinero desde tu Billetera Expensify.',
+ bankAccounts: 'Cuentas bancarias',
+ addBankAccountToSendAndReceive: 'Añade una cuenta bancaria para enviar y recibir pagos directamente en la aplicación.',
+ addBankAccount: 'Agregar cuenta bancaria',
+ assignedCards: 'Tarjetas asignadas',
+ assignedCardsDescription: 'Son tarjetas asignadas por un administrador del Espacio de Trabajo para gestionar los gastos de la empresa.',
+ expensifyCard: 'Tarjeta Expensify',
},
cardPage: {
expensifyCard: 'Tarjeta Expensify',
@@ -910,6 +929,7 @@ export default {
},
welcomeMessagePage: {
welcomeMessage: 'Mensaje de bienvenida',
+ welcomeMessageOptional: 'Mensaje de bienvenida (opcional)',
explainerText: 'Configura un mensaje de bienvenida privado y personalizado que se enviará cuando los usuarios se unan a esta sala de chat.',
},
languagePage: {
@@ -1636,6 +1656,9 @@ export default {
screenShare: 'Compartir pantalla',
screenShareRequest: 'Expensify te está invitando a compartir la pantalla',
},
+ search: {
+ resultsAreLimited: 'Los resultados de búsqueda están limitados.',
+ },
genericErrorPage: {
title: '¡Uh-oh, algo salió mal!',
body: {
@@ -2327,11 +2350,11 @@ export default {
selectSuggestedAddress: 'Por favor, selecciona una dirección sugerida o usa la ubicación actual.',
},
},
- globalNavigationOptions: {
- chats: 'Chats',
- },
eReceipt: {
guaranteed: 'eRecibo garantizado',
transactionDate: 'Fecha de transacción',
},
+ globalNavigationOptions: {
+ chats: 'Chats',
+ },
} satisfies EnglishTranslation;
diff --git a/src/languages/types.ts b/src/languages/types.ts
index 3ee504ccddd7..9560cd41b25f 100644
--- a/src/languages/types.ts
+++ b/src/languages/types.ts
@@ -106,6 +106,8 @@ type RequestedAmountMessageParams = {formattedAmount: string; comment: string};
type SplitAmountParams = {amount: number};
+type DidSplitAmountMessageParams = {formattedAmount: string; comment: string};
+
type AmountEachParams = {amount: number};
type PayerOwesAmountParams = {payer: string; amount: number};
@@ -269,6 +271,7 @@ export type {
RequestAmountParams,
RequestedAmountMessageParams,
SplitAmountParams,
+ DidSplitAmountMessageParams,
AmountEachParams,
PayerOwesAmountParams,
PayerOwesParams,
diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts
index e6c7480974ca..8df554dd4dbf 100644
--- a/src/libs/CardUtils.ts
+++ b/src/libs/CardUtils.ts
@@ -73,8 +73,8 @@ function getCompanyCards(cardList: {string: Card}) {
*/
function getDomainCards(cardList: Record) {
// eslint-disable-next-line you-dont-need-lodash-underscore/filter
- const activeCards = lodash.filter(cardList, (card) => [2, 3, 4, 7].includes(card.state));
- return lodash.groupBy(activeCards, (card) => card.domainName.toLowerCase());
+ const activeCards = lodash.filter(cardList, (card) => (CONST.EXPENSIFY_CARD.ACTIVE_STATES as ReadonlyArray).includes(card.state));
+ return lodash.groupBy(activeCards, (card) => card.domainName);
}
/**
diff --git a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts
index b22135b4f767..b5c28cfc79e8 100644
--- a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts
+++ b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts
@@ -8,7 +8,7 @@ import UpdateNumberOfLines from './types';
* divide by line height to get the total number of rows for the textarea.
*/
const updateNumberOfLines: UpdateNumberOfLines = (props, event) => {
- const lineHeight = styles.textInputCompose.lineHeight;
+ const lineHeight = styles.textInputCompose.lineHeight ?? 0;
const paddingTopAndBottom = styles.textInputComposeSpacing.paddingVertical * 2;
const inputHeight = event?.nativeEvent?.contentSize?.height ?? null;
if (!inputHeight) {
diff --git a/src/libs/DistanceRequestUtils.js b/src/libs/DistanceRequestUtils.js
index 9b875fb82004..32de571c218c 100644
--- a/src/libs/DistanceRequestUtils.js
+++ b/src/libs/DistanceRequestUtils.js
@@ -89,8 +89,7 @@ const getDistanceMerchant = (hasRoute, distanceInMeters, unit, rate, currency, t
const distanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.miles') : translate('common.kilometers');
const singularDistanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer');
const unitString = distanceInUnits === 1 ? singularDistanceUnit : distanceUnit;
-
- const ratePerUnit = PolicyUtils.getUnitRateValue({rate}, toLocaleDigit);
+ const ratePerUnit = rate ? PolicyUtils.getUnitRateValue({rate}, toLocaleDigit) : translate('common.tbd');
const currencySymbol = CurrencyUtils.getCurrencySymbol(currency) || `${currency} `;
return `${distanceInUnits} ${unitString} @ ${currencySymbol}${ratePerUnit} / ${singularDistanceUnit}`;
diff --git a/src/libs/EmojiUtils.js b/src/libs/EmojiUtils.js
index af498831f4a4..a44a69f087ab 100644
--- a/src/libs/EmojiUtils.js
+++ b/src/libs/EmojiUtils.js
@@ -426,7 +426,7 @@ function suggestEmojis(text, lang, limit = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMO
* @returns {Number}
*/
const getPreferredSkinToneIndex = (val) => {
- if (!_.isNull(val) && Number.isInteger(Number(val))) {
+ if (!_.isNull(val) && !_.isUndefined(val) && Number.isInteger(Number(val))) {
return val;
}
diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js
index 65ba40886fda..07b12486b8b2 100644
--- a/src/libs/Navigation/Navigation.js
+++ b/src/libs/Navigation/Navigation.js
@@ -172,6 +172,11 @@ function dismissModal(targetReportID) {
const action = getActionFromState(state, linkingConfig.config);
action.type = 'REPLACE';
navigationRef.current.dispatch(action);
+ // If not-found page is in the route stack, we need to close it
+ } else if (targetReportID && _.some(rootState.routes, (route) => route.name === SCREENS.NOT_FOUND)) {
+ const lastRouteIndex = rootState.routes.length - 1;
+ const centralRouteIndex = _.findLastIndex(rootState.routes, (route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR);
+ navigationRef.current.dispatch({...StackActions.pop(lastRouteIndex - centralRouteIndex), target: rootState.key});
} else {
navigationRef.current.dispatch({...StackActions.pop(), target: rootState.key});
}
diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js
index 34a52adfeca9..c7a3b14e4fb0 100644
--- a/src/libs/Navigation/NavigationRoot.js
+++ b/src/libs/Navigation/NavigationRoot.js
@@ -101,7 +101,7 @@ function NavigationRoot(props) {
const animateStatusBarBackgroundColor = () => {
const currentRoute = navigationRef.getCurrentRoute();
- const currentScreenBackgroundColor = themeColors.PAGE_BACKGROUND_COLORS[currentRoute.name] || themeColors.appBG;
+ const currentScreenBackgroundColor = (currentRoute.params && currentRoute.params.backgroundColor) || themeColors.PAGE_BACKGROUND_COLORS[currentRoute.name] || themeColors.appBG;
prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current;
statusBarBackgroundColor.current = currentScreenBackgroundColor;
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 4467746475aa..051c19312f09 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -444,6 +444,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
isArchivedRoom: false,
shouldShowSubscript: false,
isPolicyExpenseChat: false,
+ isOwnPolicyExpenseChat: false,
isExpenseReport: false,
policyID: null,
isOptimisticPersonalDetail: false,
@@ -463,12 +464,13 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
result.isChatRoom = ReportUtils.isChatRoom(report);
result.isDefaultRoom = ReportUtils.isDefaultRoom(report);
result.isArchivedRoom = ReportUtils.isArchivedRoom(report);
- result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report);
result.isExpenseReport = ReportUtils.isExpenseReport(report);
result.isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
result.isThread = ReportUtils.isChatThread(report);
result.isTaskReport = ReportUtils.isTaskReport(report);
result.shouldShowSubscript = ReportUtils.shouldReportShowSubscript(report);
+ result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report);
+ result.isOwnPolicyExpenseChat = report.isOwnPolicyExpenseChat || false;
result.allReportErrors = getAllReportErrors(report, reportActions);
result.brickRoadIndicator = !_.isEmpty(result.allReportErrors) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '';
result.pendingAction = report.pendingFields ? report.pendingFields.addWorkspaceRoom || report.pendingFields.createChat : null;
@@ -553,6 +555,10 @@ function getPolicyExpenseReportOption(report) {
forcePolicyNamePreview: false,
},
);
+
+ // Update text & alternateText because createOption returns workspace name only if report is owned by the user
+ option.text = ReportUtils.getPolicyName(expenseReport);
+ option.alternateText = Localize.translateLocal('workspace.common.workspace');
option.selected = report.selected;
return option;
}
diff --git a/src/libs/Pusher/EventType.js b/src/libs/Pusher/EventType.ts
similarity index 97%
rename from src/libs/Pusher/EventType.js
rename to src/libs/Pusher/EventType.ts
index 85ccc5e17242..89e8a0ca0260 100644
--- a/src/libs/Pusher/EventType.js
+++ b/src/libs/Pusher/EventType.ts
@@ -11,4 +11,4 @@ export default {
MULTIPLE_EVENT_TYPE: {
ONYX_API_UPDATE: 'onyxApiUpdate',
},
-};
+} as const;
diff --git a/src/libs/Pusher/library/index.js b/src/libs/Pusher/library/index.js
deleted file mode 100644
index 12cfae7df02f..000000000000
--- a/src/libs/Pusher/library/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * We use the standard pusher-js module to support pusher on web environments.
- * @see: https://github.com/pusher/pusher-js
- */
-import Pusher from 'pusher-js/with-encryption';
-
-export default Pusher;
diff --git a/src/libs/Pusher/library/index.native.js b/src/libs/Pusher/library/index.native.js
deleted file mode 100644
index 7b87d0c8bdfb..000000000000
--- a/src/libs/Pusher/library/index.native.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * We use the pusher-js/react-native module to support pusher on native environments.
- * @see: https://github.com/pusher/pusher-js
- */
-import Pusher from 'pusher-js/react-native';
-
-export default Pusher;
diff --git a/src/libs/Pusher/library/index.native.ts b/src/libs/Pusher/library/index.native.ts
new file mode 100644
index 000000000000..f50834366515
--- /dev/null
+++ b/src/libs/Pusher/library/index.native.ts
@@ -0,0 +1,10 @@
+/**
+ * We use the pusher-js/react-native module to support pusher on native environments.
+ * @see: https://github.com/pusher/pusher-js
+ */
+import PusherImplementation from 'pusher-js/react-native';
+import Pusher from './types';
+
+const PusherNative: Pusher = PusherImplementation;
+
+export default PusherNative;
diff --git a/src/libs/Pusher/library/index.ts b/src/libs/Pusher/library/index.ts
new file mode 100644
index 000000000000..6a7104a1d2a5
--- /dev/null
+++ b/src/libs/Pusher/library/index.ts
@@ -0,0 +1,10 @@
+/**
+ * We use the standard pusher-js module to support pusher on web environments.
+ * @see: https://github.com/pusher/pusher-js
+ */
+import PusherImplementation from 'pusher-js/with-encryption';
+import type Pusher from './types';
+
+const PusherWeb: Pusher = PusherImplementation;
+
+export default PusherWeb;
diff --git a/src/libs/Pusher/library/types.ts b/src/libs/Pusher/library/types.ts
new file mode 100644
index 000000000000..cc8c70fccdbb
--- /dev/null
+++ b/src/libs/Pusher/library/types.ts
@@ -0,0 +1,10 @@
+import PusherClass from 'pusher-js/with-encryption';
+import {LiteralUnion} from 'type-fest';
+
+type Pusher = typeof PusherClass;
+
+type SocketEventName = LiteralUnion<'error' | 'connected' | 'disconnected' | 'state_change', string>;
+
+export default Pusher;
+
+export type {SocketEventName};
diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.ts
similarity index 72%
rename from src/libs/Pusher/pusher.js
rename to src/libs/Pusher/pusher.ts
index 4f2b63d36c0c..dad963e933fe 100644
--- a/src/libs/Pusher/pusher.js
+++ b/src/libs/Pusher/pusher.ts
@@ -1,9 +1,48 @@
import Onyx from 'react-native-onyx';
-import _ from 'underscore';
+import {Channel, ChannelAuthorizerGenerator, Options} from 'pusher-js/with-encryption';
+import isObject from 'lodash/isObject';
+import {LiteralUnion, ValueOf} from 'type-fest';
import ONYXKEYS from '../../ONYXKEYS';
import Pusher from './library';
import TYPE from './EventType';
import Log from '../Log';
+import DeepValueOf from '../../types/utils/DeepValueOf';
+import {SocketEventName} from './library/types';
+import CONST from '../../CONST';
+import {OnyxUpdateEvent, OnyxUpdatesFromServer} from '../../types/onyx';
+
+type States = {
+ previous: string;
+ current: string;
+};
+
+type Args = {
+ appKey: string;
+ cluster: string;
+ authEndpoint: string;
+};
+
+type PushJSON = OnyxUpdateEvent[] | OnyxUpdatesFromServer;
+
+type EventCallbackError = {type: ValueOf; data: {code: number}};
+
+type ChunkedDataEvents = {chunks: unknown[]; receivedFinal: boolean};
+
+type EventData = {id?: string; chunk?: unknown; final?: boolean; index: number};
+
+type SocketEventCallback = (eventName: SocketEventName, data?: States | EventCallbackError) => void;
+
+type PusherWithAuthParams = InstanceType & {
+ config: {
+ auth?: {
+ params?: unknown;
+ };
+ };
+};
+
+type PusherEventName = LiteralUnion, string>;
+
+type PusherSubscribtionErrorData = {type?: string; error?: string; status?: string};
let shouldForceOffline = false;
Onyx.connect({
@@ -16,33 +55,23 @@ Onyx.connect({
},
});
-let socket;
+let socket: PusherWithAuthParams | null;
let pusherSocketID = '';
-const socketEventCallbacks = [];
-let customAuthorizer;
+const socketEventCallbacks: SocketEventCallback[] = [];
+let customAuthorizer: ChannelAuthorizerGenerator;
/**
* Trigger each of the socket event callbacks with the event information
- *
- * @param {String} eventName
- * @param {*} data
*/
-function callSocketEventCallbacks(eventName, data) {
- _.each(socketEventCallbacks, (cb) => cb(eventName, data));
+function callSocketEventCallbacks(eventName: SocketEventName, data?: EventCallbackError | States) {
+ socketEventCallbacks.forEach((cb) => cb(eventName, data));
}
/**
* Initialize our pusher lib
- *
- * @param {Object} args
- * @param {String} args.appKey
- * @param {String} args.cluster
- * @param {String} args.authEndpoint
- * @param {Object} [params]
- * @public
- * @returns {Promise} resolves when Pusher has connected
+ * @returns resolves when Pusher has connected
*/
-function init(args, params) {
+function init(args: Args, params?: unknown): Promise {
return new Promise((resolve) => {
if (socket) {
return resolve();
@@ -55,7 +84,7 @@ function init(args, params) {
// }
// };
- const options = {
+ const options: Options = {
cluster: args.cluster,
authEndpoint: args.authEndpoint,
};
@@ -65,7 +94,6 @@ function init(args, params) {
}
socket = new Pusher(args.appKey, options);
-
// If we want to pass params in our requests to api.php we'll need to add it to socket.config.auth.params
// as per the documentation
// (https://pusher.com/docs/channels/using_channels/connection#channels-options-parameter).
@@ -77,21 +105,21 @@ function init(args, params) {
}
// Listen for connection errors and log them
- socket.connection.bind('error', (error) => {
+ socket?.connection.bind('error', (error: EventCallbackError) => {
callSocketEventCallbacks('error', error);
});
- socket.connection.bind('connected', () => {
- pusherSocketID = socket.connection.socket_id;
+ socket?.connection.bind('connected', () => {
+ pusherSocketID = socket?.connection.socket_id ?? '';
callSocketEventCallbacks('connected');
resolve();
});
- socket.connection.bind('disconnected', () => {
+ socket?.connection.bind('disconnected', () => {
callSocketEventCallbacks('disconnected');
});
- socket.connection.bind('state_change', (states) => {
+ socket?.connection.bind('state_change', (states: States) => {
callSocketEventCallbacks('state_change', states);
});
});
@@ -99,12 +127,8 @@ function init(args, params) {
/**
* Returns a Pusher channel for a channel name
- *
- * @param {String} channelName
- *
- * @returns {Channel}
*/
-function getChannel(channelName) {
+function getChannel(channelName: string): Channel | undefined {
if (!socket) {
return;
}
@@ -114,19 +138,14 @@ function getChannel(channelName) {
/**
* Binds an event callback to a channel + eventName
- * @param {Pusher.Channel} channel
- * @param {String} eventName
- * @param {Function} [eventCallback]
- *
- * @private
*/
-function bindEventToChannel(channel, eventName, eventCallback = () => {}) {
+function bindEventToChannel(channel: Channel | undefined, eventName: PusherEventName, eventCallback: (data: PushJSON) => void = () => {}) {
if (!eventName) {
return;
}
- const chunkedDataEvents = {};
- const callback = (eventData) => {
+ const chunkedDataEvents: Record = {};
+ const callback = (eventData: string | Record | EventData) => {
if (shouldForceOffline) {
Log.info('[Pusher] Ignoring a Push event because shouldForceOffline = true');
return;
@@ -134,7 +153,7 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) {
let data;
try {
- data = _.isObject(eventData) ? eventData : JSON.parse(eventData);
+ data = isObject(eventData) ? eventData : JSON.parse(eventData);
} catch (err) {
Log.alert('[Pusher] Unable to parse single JSON event data from Pusher', {error: err, eventData});
return;
@@ -164,7 +183,7 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) {
// Only call the event callback if we've received the last packet and we don't have any holes in the complete
// packet.
- if (chunkedEvent.receivedFinal && chunkedEvent.chunks.length === _.keys(chunkedEvent.chunks).length) {
+ if (chunkedEvent.receivedFinal && chunkedEvent.chunks.length === Object.keys(chunkedEvent.chunks).length) {
try {
eventCallback(JSON.parse(chunkedEvent.chunks.join('')));
} catch (err) {
@@ -181,22 +200,14 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) {
}
};
- channel.bind(eventName, callback);
+ channel?.bind(eventName, callback);
}
/**
* Subscribe to a channel and an event
- *
- * @param {String} channelName
- * @param {String} eventName
- * @param {Function} [eventCallback]
- * @param {Function} [onResubscribe] Callback to be called when reconnection happen
- *
- * @return {Promise}
- *
- * @public
+ * @param [onResubscribe] Callback to be called when reconnection happen
*/
-function subscribe(channelName, eventName, eventCallback = () => {}, onResubscribe = () => {}) {
+function subscribe(channelName: string, eventName: PusherEventName, eventCallback: (data: PushJSON) => void = () => {}, onResubscribe = () => {}): Promise {
return new Promise((resolve, reject) => {
// We cannot call subscribe() before init(). Prevent any attempt to do this on dev.
if (!socket) {
@@ -226,7 +237,7 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri
onResubscribe();
});
- channel.bind('pusher:subscription_error', (data = {}) => {
+ channel.bind('pusher:subscription_error', (data: PusherSubscribtionErrorData = {}) => {
const {type, error, status} = data;
Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', {
channelName,
@@ -245,12 +256,8 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri
/**
* Unsubscribe from a channel and optionally a specific event
- *
- * @param {String} channelName
- * @param {String} [eventName]
- * @public
*/
-function unsubscribe(channelName, eventName = '') {
+function unsubscribe(channelName: string, eventName: PusherEventName = '') {
const channel = getChannel(channelName);
if (!channel) {
@@ -269,18 +276,14 @@ function unsubscribe(channelName, eventName = '') {
Log.info('[Pusher] Unsubscribing from channel', false, {channelName});
channel.unbind();
- socket.unsubscribe(channelName);
+ socket?.unsubscribe(channelName);
}
}
/**
* Are we already in the process of subscribing to this channel?
- *
- * @param {String} channelName
- *
- * @returns {Boolean}
*/
-function isAlreadySubscribing(channelName) {
+function isAlreadySubscribing(channelName: string): boolean {
if (!socket) {
return false;
}
@@ -291,12 +294,8 @@ function isAlreadySubscribing(channelName) {
/**
* Are we already subscribed to this channel?
- *
- * @param {String} channelName
- *
- * @returns {Boolean}
*/
-function isSubscribed(channelName) {
+function isSubscribed(channelName: string): boolean {
if (!socket) {
return false;
}
@@ -307,12 +306,8 @@ function isSubscribed(channelName) {
/**
* Sends an event over a specific event/channel in pusher.
- *
- * @param {String} channelName
- * @param {String} eventName
- * @param {Object} payload
*/
-function sendEvent(channelName, eventName, payload) {
+function sendEvent(channelName: string, eventName: PusherEventName, payload: Record) {
// Check to see if we are subscribed to this channel before sending the event. Sending client events over channels
// we are not subscribed too will throw errors and cause reconnection attempts. Subscriptions are not instant and
// can happen later than we expect.
@@ -325,15 +320,13 @@ function sendEvent(channelName, eventName, payload) {
return;
}
- socket.send_event(eventName, payload, channelName);
+ socket?.send_event(eventName, payload, channelName);
}
/**
* Register a method that will be triggered when a socket event happens (like disconnecting)
- *
- * @param {Function} cb
*/
-function registerSocketEventCallback(cb) {
+function registerSocketEventCallback(cb: SocketEventCallback) {
socketEventCallbacks.push(cb);
}
@@ -341,10 +334,8 @@ function registerSocketEventCallback(cb) {
* A custom authorizer allows us to take a more fine-grained approach to
* authenticating Pusher. e.g. we can handle failed attempts to authorize
* with an expired authToken and retry the attempt.
- *
- * @param {Function} authorizer
*/
-function registerCustomAuthorizer(authorizer) {
+function registerCustomAuthorizer(authorizer: ChannelAuthorizerGenerator) {
customAuthorizer = authorizer;
}
@@ -376,18 +367,13 @@ function reconnect() {
socket.connect();
}
-/**
- * @returns {String}
- */
-function getPusherSocketID() {
+function getPusherSocketID(): string {
return pusherSocketID;
}
if (window) {
/**
* Pusher socket for debugging purposes
- *
- * @returns {Function}
*/
window.getPusherInstance = () => socket;
}
@@ -407,3 +393,5 @@ export {
TYPE,
getPusherSocketID,
};
+
+export type {EventCallbackError, States, PushJSON};
diff --git a/src/libs/PusherConnectionManager.ts b/src/libs/PusherConnectionManager.ts
index 4ab08d6dc760..9b1f6ebe1b2a 100644
--- a/src/libs/PusherConnectionManager.ts
+++ b/src/libs/PusherConnectionManager.ts
@@ -1,11 +1,10 @@
-import {ValueOf} from 'type-fest';
+import {ChannelAuthorizationCallback} from 'pusher-js/with-encryption';
import * as Pusher from './Pusher/pusher';
import * as Session from './actions/Session';
import Log from './Log';
import CONST from '../CONST';
-
-type EventCallbackError = {type: ValueOf; data: {code: number}};
-type CustomAuthorizerChannel = {name: string};
+import {SocketEventName} from './Pusher/library/types';
+import {EventCallbackError, States} from './Pusher/pusher';
function init() {
/**
@@ -14,30 +13,32 @@ function init() {
* current valid token to generate the signed auth response
* needed to subscribe to Pusher channels.
*/
- Pusher.registerCustomAuthorizer((channel: CustomAuthorizerChannel) => ({
- authorize: (socketID: string, callback: () => void) => {
- Session.authenticatePusher(socketID, channel.name, callback);
+ Pusher.registerCustomAuthorizer((channel) => ({
+ authorize: (socketId: string, callback: ChannelAuthorizationCallback) => {
+ Session.authenticatePusher(socketId, channel.name, callback);
},
}));
- Pusher.registerSocketEventCallback((eventName: string, error: EventCallbackError) => {
+ Pusher.registerSocketEventCallback((eventName: SocketEventName, error?: EventCallbackError | States) => {
switch (eventName) {
case 'error': {
- const errorType = error?.type;
- const code = error?.data?.code;
- if (errorType === CONST.ERROR.PUSHER_ERROR && code === 1006) {
- // 1006 code happens when a websocket connection is closed. There may or may not be a reason attached indicating why the connection was closed.
- // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5
- Log.hmmm('[PusherConnectionManager] Channels Error 1006', {error});
- } else if (errorType === CONST.ERROR.PUSHER_ERROR && code === 4201) {
- // This means the connection was closed because Pusher did not receive a reply from the client when it pinged them for a response
- // https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/#4200-4299
- Log.hmmm('[PusherConnectionManager] Pong reply not received', {error});
- } else if (errorType === CONST.ERROR.WEB_SOCKET_ERROR) {
- // It's not clear why some errors are wrapped in a WebSocketError type - this error could mean different things depending on the contents.
- Log.hmmm('[PusherConnectionManager] WebSocketError', {error});
- } else {
- Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} [PusherConnectionManager] Unknown error event`, {error});
+ if (error && 'type' in error) {
+ const errorType = error?.type;
+ const code = error?.data?.code;
+ if (errorType === CONST.ERROR.PUSHER_ERROR && code === 1006) {
+ // 1006 code happens when a websocket connection is closed. There may or may not be a reason attached indicating why the connection was closed.
+ // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5
+ Log.hmmm('[PusherConnectionManager] Channels Error 1006', {error});
+ } else if (errorType === CONST.ERROR.PUSHER_ERROR && code === 4201) {
+ // This means the connection was closed because Pusher did not receive a reply from the client when it pinged them for a response
+ // https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/#4200-4299
+ Log.hmmm('[PusherConnectionManager] Pong reply not received', {error});
+ } else if (errorType === CONST.ERROR.WEB_SOCKET_ERROR) {
+ // It's not clear why some errors are wrapped in a WebSocketError type - this error could mean different things depending on the contents.
+ Log.hmmm('[PusherConnectionManager] WebSocketError', {error});
+ } else {
+ Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} [PusherConnectionManager] Unknown error event`, {error});
+ }
}
break;
}
diff --git a/src/libs/PusherUtils.ts b/src/libs/PusherUtils.ts
index 5baa4b68d5f8..d47283f21bbf 100644
--- a/src/libs/PusherUtils.ts
+++ b/src/libs/PusherUtils.ts
@@ -4,9 +4,7 @@ import Log from './Log';
import NetworkConnection from './NetworkConnection';
import * as Pusher from './Pusher/pusher';
import CONST from '../CONST';
-import {OnyxUpdateEvent, OnyxUpdatesFromServer} from '../types/onyx';
-
-type PushJSON = OnyxUpdateEvent[] | OnyxUpdatesFromServer;
+import {PushJSON} from './Pusher/pusher';
type Callback = (data: OnyxUpdate[]) => Promise;
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 8bb67d639486..8c8f203f8f18 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -1267,6 +1267,17 @@ function isWaitingForTaskCompleteFromAssignee(report, parentReportAction = {}) {
return isTaskReport(report) && isReportManager(report) && isOpenTaskReport(report, parentReportAction);
}
+/**
+ * Returns number of transactions that are nonReimbursable
+ *
+ * @param {Object|null} iouReportID
+ * @returns {Number}
+ */
+function hasNonReimbursableTransactions(iouReportID) {
+ const allTransactions = TransactionUtils.getAllReportTransactions(iouReportID);
+ return _.filter(allTransactions, (transaction) => transaction.reimbursable === false).length > 0;
+}
+
/**
* @param {Object} report
* @param {Object} allReportsDict
@@ -1344,6 +1355,10 @@ function getMoneyRequestReportName(report, policy = undefined) {
return `${payerPaidAmountMesssage} • ${Localize.translateLocal('iou.pending')}`;
}
+ if (hasNonReimbursableTransactions(report.reportID)) {
+ return Localize.translateLocal('iou.payerSpentAmount', {payer: payerName, amount: formattedAmount});
+ }
+
if (report.hasOutstandingIOU) {
return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount});
}
@@ -1373,6 +1388,8 @@ function getTransactionDetails(transaction, createdDateFormat = CONST.DATE.FNS_F
tag: TransactionUtils.getTag(transaction),
mccGroup: TransactionUtils.getMCCGroup(transaction),
cardID: TransactionUtils.getCardID(transaction),
+ originalAmount: TransactionUtils.getOriginalAmount(transaction),
+ originalCurrency: TransactionUtils.getOriginalCurrency(transaction),
};
}
@@ -1481,7 +1498,7 @@ function getTransactionReportName(reportAction) {
return Localize.translateLocal('parentReportAction.reversedTransaction');
}
- if (ReportActionsUtils.isDeletedParentAction(reportAction)) {
+ if (ReportActionsUtils.isDeletedAction(reportAction)) {
return Localize.translateLocal('parentReportAction.deletedRequest');
}
@@ -1519,6 +1536,17 @@ function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceip
return reportActionMessage;
}
+ if (!isIOUReport(report) && ReportActionsUtils.isSplitBillAction(reportAction)) {
+ // This covers group chats where the last action is a split bill action
+ const linkedTransaction = TransactionUtils.getLinkedTransaction(reportAction);
+ if (_.isEmpty(linkedTransaction)) {
+ return reportActionMessage;
+ }
+ const {amount, currency, comment} = getTransactionDetails(linkedTransaction);
+ const formattedAmount = CurrencyUtils.convertToDisplayString(amount, currency);
+ return Localize.translateLocal('iou.didSplitAmount', {formattedAmount, comment});
+ }
+
const totalAmount = getMoneyRequestTotal(report);
const payerName = isExpenseReport(report) ? getPolicyName(report) : getDisplayNameForParticipant(report.managerID, true);
const formattedAmount = CurrencyUtils.convertToDisplayString(totalAmount, report.currency);
@@ -1552,7 +1580,8 @@ function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceip
return Localize.translateLocal('iou.waitingOnBankAccount', {submitterDisplayName});
}
- return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount});
+ const containsNonReimbursable = hasNonReimbursableTransactions(report.reportID);
+ return Localize.translateLocal(containsNonReimbursable ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', {payer: payerName, amount: formattedAmount});
}
/**
@@ -2581,6 +2610,7 @@ function buildOptimisticTaskReportAction(taskReportID, actionName, message = '')
* @param {String} notificationPreference
* @param {String} parentReportActionID
* @param {String} parentReportID
+ * @param {String} welcomeMessage
* @returns {Object}
*/
function buildOptimisticChatReport(
@@ -2596,6 +2626,7 @@ function buildOptimisticChatReport(
notificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
parentReportActionID = '',
parentReportID = '',
+ welcomeMessage = '',
) {
const currentTime = DateUtils.getDBTime();
return {
@@ -2622,7 +2653,7 @@ function buildOptimisticChatReport(
stateNum: 0,
statusNum: 0,
visibility,
- welcomeMessage: '',
+ welcomeMessage,
writeCapability,
};
}
@@ -3973,6 +4004,7 @@ export {
areAllRequestsBeingSmartScanned,
getReportPreviewDisplayTransactions,
getTransactionsWithReceipts,
+ hasNonReimbursableTransactions,
hasMissingSmartscanFields,
getIOUReportActionDisplayMessage,
isWaitingForTaskCompleteFromAssignee,
diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts
index 43b1c2f39902..393de4e0d6e3 100644
--- a/src/libs/TransactionUtils.ts
+++ b/src/libs/TransactionUtils.ts
@@ -225,6 +225,21 @@ function getCurrency(transaction: Transaction): string {
return transaction?.currency ?? CONST.CURRENCY.USD;
}
+/**
+ * Return the original currency field from the transaction.
+ */
+function getOriginalCurrency(transaction: Transaction): string {
+ return transaction?.originalCurrency ?? '';
+}
+
+/**
+ * Return the absolute value of the original amount field from the transaction.
+ */
+function getOriginalAmount(transaction: Transaction): number {
+ const amount = transaction?.originalAmount ?? 0;
+ return Math.abs(amount);
+}
+
/**
* Return the merchant field from the transaction, return the modifiedMerchant if present.
*/
@@ -293,6 +308,9 @@ function isDistanceRequest(transaction: Transaction): boolean {
return type === CONST.TRANSACTION.TYPE.CUSTOM_UNIT && customUnitName === CONST.CUSTOM_UNITS.NAME_DISTANCE;
}
+/**
+ * Determine whether a transaction is made with an Expensify card.
+ */
function isExpensifyCardTransaction(transaction: Transaction): boolean {
if (!transaction.cardID) {
return false;
@@ -300,6 +318,9 @@ function isExpensifyCardTransaction(transaction: Transaction): boolean {
return isExpensifyCard(transaction.cardID);
}
+/**
+ * Check if the transaction status is set to Pending.
+ */
function isPending(transaction: Transaction): boolean {
if (!transaction.status) {
return false;
@@ -307,6 +328,9 @@ function isPending(transaction: Transaction): boolean {
return transaction.status === CONST.TRANSACTION.STATUS.PENDING;
}
+/**
+ * Check if the transaction status is set to Posted.
+ */
function isPosted(transaction: Transaction): boolean {
if (!transaction.status) {
return false;
@@ -428,6 +452,8 @@ export {
getAmount,
getCurrency,
getCardID,
+ getOriginalCurrency,
+ getOriginalAmount,
getMerchant,
getMCCGroup,
getCreated,
diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js
index 7500af6d829e..a1d64154906c 100644
--- a/src/libs/actions/App.js
+++ b/src/libs/actions/App.js
@@ -44,6 +44,19 @@ Onyx.connect({
callback: (val) => (preferredLocale = val),
});
+let priorityMode;
+Onyx.connect({
+ key: ONYXKEYS.NVP_PRIORITY_MODE,
+ callback: (nextPriorityMode) => {
+ // When someone switches their priority mode we need to fetch all their chats because only #focus mode works with a subset of a user's chats. This is only possible via the OpenApp command.
+ if (nextPriorityMode === CONST.PRIORITY_MODE.DEFAULT && priorityMode === CONST.PRIORITY_MODE.GSD) {
+ // eslint-disable-next-line no-use-before-define
+ openApp();
+ }
+ priorityMode = nextPriorityMode;
+ },
+});
+
let resolveIsReadyPromise;
const isReadyToOpenApp = new Promise((resolve) => {
resolveIsReadyPromise = resolve;
@@ -207,7 +220,8 @@ function getOnyxDataForOpenOrReconnect(isOpenApp = false) {
*/
function openApp() {
getPolicyParamsForOpenOrReconnect().then((policyParams) => {
- API.read('OpenApp', policyParams, getOnyxDataForOpenOrReconnect(true));
+ const params = {enablePriorityModeFilter: true, ...policyParams};
+ API.read('OpenApp', params, getOnyxDataForOpenOrReconnect(true));
});
}
diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js
index b1cb09a8a5e2..4d3c880b5983 100644
--- a/src/libs/actions/BankAccounts.js
+++ b/src/libs/actions/BankAccounts.js
@@ -57,10 +57,10 @@ function clearOnfidoToken() {
/**
* Helper method to build the Onyx data required during setup of a Verified Business Bank Account
- *
+ * @param {String | undefined} currentStep The name of the bank account setup step for which we will update the draft value when we receive the response from the API.
* @returns {Object}
*/
-function getVBBADataForOnyx() {
+function getVBBADataForOnyx(currentStep = undefined) {
return {
optimisticData: [
{
@@ -79,6 +79,12 @@ function getVBBADataForOnyx() {
value: {
isLoading: false,
errors: null,
+ // When setting up a bank account, we save the draft form values in Onyx.
+ // When we update the information for a step, the value of some fields that are returned from the API
+ // can be different from the value that we stored as the draft in Onyx (i.e. the phone number is formatted).
+ // This is why we store the current step used to call the API in order to update the corresponding draft data in Onyx.
+ // If currentStep is undefined that means this step don't need to update the data of the draft in Onyx.
+ draftStep: currentStep,
},
},
],
@@ -222,7 +228,7 @@ function deletePaymentBankAccount(bankAccountID) {
* @param {Boolean} [params.isOnfidoSetupComplete]
*/
function updatePersonalInformationForBankAccount(params) {
- API.write('UpdatePersonalInformationForBankAccount', params, getVBBADataForOnyx());
+ API.write('UpdatePersonalInformationForBankAccount', params, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.REQUESTOR));
}
/**
@@ -269,6 +275,10 @@ function validateBankAccount(bankAccountID, validateCode) {
);
}
+function clearReimbursementAccount() {
+ Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT, null);
+}
+
function openReimbursementAccountPage(stepToOpen, subStep, localCurrentStep) {
const onyxData = {
optimisticData: [
@@ -339,7 +349,7 @@ function openReimbursementAccountPage(stepToOpen, subStep, localCurrentStep) {
* @param {String} policyID
*/
function updateCompanyInformationForBankAccount(bankAccount, policyID) {
- API.write('UpdateCompanyInformationForBankAccount', {...bankAccount, policyID}, getVBBADataForOnyx());
+ API.write('UpdateCompanyInformationForBankAccount', {...bankAccount, policyID}, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.COMPANY));
}
/**
@@ -376,7 +386,7 @@ function connectBankAccountManually(bankAccountID, accountNumber, routingNumber,
routingNumber,
plaidMask,
},
- getVBBADataForOnyx(),
+ getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT),
);
}
@@ -430,6 +440,7 @@ export {
deletePaymentBankAccount,
handlePlaidError,
openPersonalBankAccountSetupView,
+ clearReimbursementAccount,
openReimbursementAccountPage,
updateBeneficialOwnersForBankAccount,
updateCompanyInformationForBankAccount,
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index c469ed02a084..a95d69243ec8 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -1767,7 +1767,8 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC
updatedMoneyRequestReport.lastMessageHtml = lastMessage[0].html;
// Update the last message of the chat report
- const messageText = Localize.translateLocal('iou.payerOwesAmount', {
+ const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport);
+ const messageText = Localize.translateLocal(hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', {
payer: updatedMoneyRequestReport.managerEmail,
amount: CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedMoneyRequestReport.currency),
});
@@ -1987,7 +1988,8 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
updatedIOUReport.lastVisibleActionCreated = lastVisibleAction.created;
updatedReportPreviewAction = {...reportPreviewAction};
- const messageText = Localize.translateLocal('iou.payerOwesAmount', {
+ const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport);
+ const messageText = Localize.translateLocal(hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', {
payer: updatedIOUReport.managerEmail,
amount: CurrencyUtils.convertToDisplayString(updatedIOUReport.total, updatedIOUReport.currency),
});
@@ -2819,9 +2821,12 @@ function setMoneyRequestReceipt(receiptPath, receiptFilename) {
Onyx.merge(ONYXKEYS.IOU, {receiptPath, receiptFilename, merchant: ''});
}
-function createEmptyTransaction() {
+function setUpDistanceTransaction() {
const transactionID = NumberUtils.rand64();
- Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {transactionID});
+ Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
+ transactionID,
+ comment: {type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, customUnit: {name: CONST.CUSTOM_UNITS.NAME_DISTANCE}},
+ });
Onyx.merge(ONYXKEYS.IOU, {transactionID});
}
@@ -2916,7 +2921,7 @@ export {
setMoneyRequestBillable,
setMoneyRequestParticipants,
setMoneyRequestReceipt,
- createEmptyTransaction,
+ setUpDistanceTransaction,
navigateToNextPage,
updateDistanceRequest,
replaceReceipt,
diff --git a/src/libs/actions/InputFocus/index.desktop.ts b/src/libs/actions/InputFocus/index.desktop.ts
new file mode 100644
index 000000000000..b6cf1aba6138
--- /dev/null
+++ b/src/libs/actions/InputFocus/index.desktop.ts
@@ -0,0 +1,29 @@
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../../../ONYXKEYS';
+import ReportActionComposeFocusManager from '../../ReportActionComposeFocusManager';
+
+function inputFocusChange(focus: boolean) {
+ Onyx.set(ONYXKEYS.INPUT_FOCUSED, focus);
+}
+
+let refSave: HTMLElement | undefined;
+function composerFocusKeepFocusOn(ref: HTMLElement, isFocused: boolean, modal: {willAlertModalBecomeVisible: boolean; isVisible: boolean}, onyxFocused: boolean) {
+ if (isFocused && !onyxFocused) {
+ inputFocusChange(true);
+ ref.focus();
+ }
+ if (isFocused) {
+ refSave = ref;
+ }
+ if (!isFocused && !onyxFocused && !modal.willAlertModalBecomeVisible && !modal.isVisible && refSave) {
+ if (!ReportActionComposeFocusManager.isFocused()) {
+ refSave.focus();
+ } else {
+ refSave = undefined;
+ }
+ }
+}
+
+const callback = (method: () => void) => method();
+
+export {composerFocusKeepFocusOn, inputFocusChange, callback};
diff --git a/src/libs/actions/InputFocus/index.ts b/src/libs/actions/InputFocus/index.ts
new file mode 100644
index 000000000000..1840b0625626
--- /dev/null
+++ b/src/libs/actions/InputFocus/index.ts
@@ -0,0 +1,5 @@
+function inputFocusChange() {}
+function composerFocusKeepFocusOn() {}
+const callback = () => {};
+
+export {composerFocusKeepFocusOn, inputFocusChange, callback};
diff --git a/src/libs/actions/InputFocus/index.website.ts b/src/libs/actions/InputFocus/index.website.ts
new file mode 100644
index 000000000000..7c044b169a03
--- /dev/null
+++ b/src/libs/actions/InputFocus/index.website.ts
@@ -0,0 +1,30 @@
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../../../ONYXKEYS';
+import * as Browser from '../../Browser';
+import ReportActionComposeFocusManager from '../../ReportActionComposeFocusManager';
+
+function inputFocusChange(focus: boolean) {
+ Onyx.set(ONYXKEYS.INPUT_FOCUSED, focus);
+}
+
+let refSave: HTMLElement | undefined;
+function composerFocusKeepFocusOn(ref: HTMLElement, isFocused: boolean, modal: {willAlertModalBecomeVisible: boolean; isVisible: boolean}, onyxFocused: boolean) {
+ if (isFocused && !onyxFocused) {
+ inputFocusChange(true);
+ ref.focus();
+ }
+ if (isFocused) {
+ refSave = ref;
+ }
+ if (!isFocused && !onyxFocused && !modal.willAlertModalBecomeVisible && !modal.isVisible && refSave) {
+ if (!ReportActionComposeFocusManager.isFocused()) {
+ refSave.focus();
+ } else {
+ refSave = undefined;
+ }
+ }
+}
+
+const callback = (method: () => void) => !Browser.isMobile() && method();
+
+export {composerFocusKeepFocusOn, inputFocusChange, callback};
diff --git a/src/libs/actions/ReimbursementAccount/index.js b/src/libs/actions/ReimbursementAccount/index.js
index 49ff30e7be8e..68774d0ba8b0 100644
--- a/src/libs/actions/ReimbursementAccount/index.js
+++ b/src/libs/actions/ReimbursementAccount/index.js
@@ -31,6 +31,7 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) {
*/
function updateReimbursementAccountDraft(bankAccountData) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, bankAccountData);
+ Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {draftStep: undefined});
}
/**
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index bbc5ddeadd82..c56e9c567745 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -1,6 +1,7 @@
import {InteractionManager} from 'react-native';
import _ from 'underscore';
import lodashGet from 'lodash/get';
+import lodashDebounce from 'lodash/debounce';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import Onyx from 'react-native-onyx';
import Str from 'expensify-common/lib/str';
@@ -1429,8 +1430,9 @@ function navigateToConciergeChat(ignoreConciergeReportID = false) {
* @param {String} visibility
* @param {Array} policyMembersAccountIDs
* @param {String} writeCapability
+ * @param {String} welcomeMessage
*/
-function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs, writeCapability = CONST.REPORT.WRITE_CAPABILITIES.ALL) {
+function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs, writeCapability = CONST.REPORT.WRITE_CAPABILITIES.ALL, welcomeMessage = '') {
// The participants include the current user (admin), and for restricted rooms, the policy members. Participants must not be empty.
const members = visibility === CONST.REPORT.VISIBILITY.RESTRICTED ? policyMembersAccountIDs : [];
const participants = _.unique([currentUserAccountID, ...members]);
@@ -1447,6 +1449,9 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI
// The room might contain all policy members so notifying always should be opt-in only.
CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY,
+ '',
+ '',
+ welcomeMessage,
);
const createdReportAction = ReportUtils.buildOptimisticCreatedReportAction(CONST.POLICY.OWNER_EMAIL_FAKE);
@@ -1511,6 +1516,7 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI
reportID: policyReport.reportID,
createdReportActionID: createdReportAction.reportActionID,
writeCapability,
+ welcomeMessage,
},
{optimisticData, successData, failureData},
);
@@ -2221,7 +2227,63 @@ function savePrivateNotesDraft(reportID, note) {
Onyx.merge(`${ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT}${reportID}`, note);
}
+/**
+ * @private
+ * @param {string} searchInput
+ */
+function searchForReports(searchInput) {
+ // We do not try to make this request while offline because it sets a loading indicator optimistically
+ if (isNetworkOffline) {
+ Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, false);
+ return;
+ }
+
+ API.read(
+ 'SearchForReports',
+ {searchInput},
+ {
+ successData: [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS,
+ value: false,
+ },
+ ],
+ failureData: [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS,
+ value: false,
+ },
+ ],
+ },
+ );
+}
+
+/**
+ * @private
+ * @param {string} searchInput
+ */
+const debouncedSearchInServer = lodashDebounce(searchForReports, CONST.TIMING.SEARCH_FOR_REPORTS_DEBOUNCE_TIME, {leading: false});
+
+/**
+ * @param {string} searchInput
+ */
+function searchInServer(searchInput) {
+ if (isNetworkOffline) {
+ Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, false);
+ return;
+ }
+
+ // Why not set this in optimistic data? It won't run until the API request happens and while the API request is debounced
+ // we want to show the loading state right away. Otherwise, we will see a flashing UI where the client options are sorted and
+ // tell the user there are no options, then we start searching, and tell them there are no options again.
+ Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, true);
+ debouncedSearchInServer(searchInput);
+}
+
export {
+ searchInServer,
addComment,
addAttachment,
reconnect,
diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js
index 565f36d69e54..64bff8655403 100755
--- a/src/pages/NewChatPage.js
+++ b/src/pages/NewChatPage.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import React, {useState, useEffect, useMemo} from 'react';
+import React, {useState, useEffect, useMemo, useCallback} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
@@ -20,6 +20,7 @@ import compose from '../libs/compose';
import personalDetailsPropType from './personalDetailsPropType';
import reportPropTypes from './reportPropTypes';
import variables from '../styles/variables';
+import useNetwork from '../hooks/useNetwork';
const propTypes = {
/** Beta features list */
@@ -34,22 +35,27 @@ const propTypes = {
...windowDimensionsPropTypes,
...withLocalizePropTypes,
+
+ /** Whether we are searching for reports in the server */
+ isSearchingForReports: PropTypes.bool,
};
const defaultProps = {
betas: [],
personalDetails: {},
reports: {},
+ isSearchingForReports: false,
};
const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE);
-function NewChatPage({betas, isGroupChat, personalDetails, reports, translate}) {
+function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, isSearchingForReports}) {
const [searchTerm, setSearchTerm] = useState('');
const [filteredRecentReports, setFilteredRecentReports] = useState([]);
const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]);
const [filteredUserToInvite, setFilteredUserToInvite] = useState();
const [selectedOptions, setSelectedOptions] = useState([]);
+ const {isOffline} = useNetwork();
const maxParticipantsReached = selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS;
const headerMessage = OptionsListUtils.getHeaderMessage(
@@ -167,6 +173,13 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [reports, personalDetails, searchTerm]);
+ // When search term updates we will fetch any reports
+ const setSearchTermAndSearchInServer = useCallback((text = '') => {
+ if (text.length) {
+ Report.searchInServer(text);
+ }
+ setSearchTerm(text);
+ }, []);
return (
createChat(option)}
- onChangeText={setSearchTerm}
+ onChangeText={setSearchTermAndSearchInServer}
headerMessage={headerMessage}
boldStyle
shouldPreventDefaultFocusOnSelectRow={!Browser.isMobile()}
shouldShowOptions={isOptionsDataReady}
shouldShowConfirmButton
confirmButtonText={selectedOptions.length > 1 ? translate('newChatPage.createGroup') : translate('newChatPage.createChat')}
+ textInputAlert={isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''}
onConfirmSelection={createGroup}
textInputLabel={translate('optionsSelector.nameEmailOrPhoneNumber')}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
+ isLoadingNewOptions={isSearchingForReports}
/>
@@ -230,5 +245,9 @@ export default compose(
betas: {
key: ONYXKEYS.BETAS,
},
+ isSearchingForReports: {
+ key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS,
+ initWithStoredValues: false,
+ },
}),
)(NewChatPage);
diff --git a/src/pages/ReimbursementAccount/AddressForm.js b/src/pages/ReimbursementAccount/AddressForm.js
index d8fbc0290136..5ddea09c6f4e 100644
--- a/src/pages/ReimbursementAccount/AddressForm.js
+++ b/src/pages/ReimbursementAccount/AddressForm.js
@@ -145,6 +145,7 @@ function AddressForm(props) {
errorText={props.errors.zipCode ? props.translate('bankAccount.error.zipCode') : ''}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
hint={props.translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})}
+ containerStyles={[styles.mt2]}
/>
>
);
diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
index c6f53c2474f4..a99e3d7332a0 100644
--- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
+++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
@@ -105,10 +105,12 @@ class ReimbursementAccountPage extends React.Component {
this.goBack = this.goBack.bind(this);
this.requestorStepRef = React.createRef();
- // The first time we open this page, the props.reimbursementAccount has not been loaded from the server.
- // Calculating shouldShowContinueSetupButton on the default data doesn't make sense, and we should recalculate
+ // The first time we open this page, props.reimbursementAccount is either not available in Onyx
+ // or only partial data loaded where props.reimbursementAccount.achData.currentStep is not available
+ // Calculating shouldShowContinueSetupButton on first page open doesn't make sense, and we should recalculate
// it once we get the response from the server the first time in componentDidUpdate.
- const hasACHDataBeenLoaded = this.props.reimbursementAccount !== ReimbursementAccountProps.reimbursementAccountDefaultProps;
+ const hasACHDataBeenLoaded =
+ this.props.reimbursementAccount !== ReimbursementAccountProps.reimbursementAccountDefaultProps && _.has(this.props.reimbursementAccount, 'achData.currentStep');
this.state = {
hasACHDataBeenLoaded,
shouldShowContinueSetupButton: hasACHDataBeenLoaded ? this.getShouldShowContinueSetupButtonInitialValue() : false,
@@ -157,6 +159,12 @@ class ReimbursementAccountPage extends React.Component {
return;
}
+ // Update the data that is returned from back-end to draft value
+ const draftStep = this.props.reimbursementAccount.draftStep;
+ if (draftStep) {
+ BankAccounts.updateReimbursementAccountDraft(this.getBankAccountFields(this.getFieldsForStep(draftStep)));
+ }
+
const currentStepRouteParam = this.getStepToOpenFromRouteParams();
if (currentStepRouteParam === currentStep) {
// The route is showing the correct step, no need to update the route param or clear errors.
@@ -177,6 +185,46 @@ class ReimbursementAccountPage extends React.Component {
Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(this.getRouteForCurrentStep(currentStep), policyId, backTo));
}
+ componentWillUnmount() {
+ BankAccounts.clearReimbursementAccount();
+ }
+
+ getFieldsForStep(step) {
+ switch (step) {
+ case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT:
+ return ['routingNumber', 'accountNumber', 'bankName', 'plaidAccountID', 'plaidAccessToken', 'isSavings'];
+ case CONST.BANK_ACCOUNT.STEP.COMPANY:
+ return [
+ 'companyName',
+ 'addressStreet',
+ 'addressZipCode',
+ 'addressCity',
+ 'addressState',
+ 'companyPhone',
+ 'website',
+ 'companyTaxID',
+ 'incorporationType',
+ 'incorporationDate',
+ 'incorporationState',
+ ];
+ case CONST.BANK_ACCOUNT.STEP.REQUESTOR:
+ return ['firstName', 'lastName', 'dob', 'ssnLast4', 'requestorAddressStreet', 'requestorAddressCity', 'requestorAddressState', 'requestorAddressZipCode'];
+ default:
+ return [];
+ }
+ }
+
+ /**
+ * @param {Array} fieldNames
+ *
+ * @returns {*}
+ */
+ getBankAccountFields(fieldNames) {
+ return {
+ ..._.pick(lodashGet(this.props.reimbursementAccount, 'achData'), ...fieldNames),
+ };
+ }
+
/*
* Calculates the state used to show the "Continue with setup" view. If a bank account setup is already in progress and
* no specific further step was passed in the url we'll show the workspace bank account reset modal if the user wishes to start over
diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js
index 141f4e841853..272fb30de858 100755
--- a/src/pages/SearchPage.js
+++ b/src/pages/SearchPage.js
@@ -20,6 +20,8 @@ import compose from '../libs/compose';
import personalDetailsPropType from './personalDetailsPropType';
import reportPropTypes from './reportPropTypes';
import Performance from '../libs/Performance';
+import networkPropTypes from '../components/networkPropTypes';
+import {withNetwork} from '../components/OnyxProvider';
const propTypes = {
/* Onyx Props */
@@ -37,12 +39,20 @@ const propTypes = {
...windowDimensionsPropTypes,
...withLocalizePropTypes,
+
+ /** Network info */
+ network: networkPropTypes,
+
+ /** Whether we are searching for reports in the server */
+ isSearchingForReports: PropTypes.bool,
};
const defaultProps = {
betas: [],
personalDetails: {},
reports: {},
+ network: {},
+ isSearchingForReports: false,
};
class SearchPage extends Component {
@@ -75,6 +85,10 @@ class SearchPage extends Component {
}
onChangeText(searchValue = '') {
+ if (searchValue.length) {
+ Report.searchInServer(searchValue);
+ }
+
this.setState({searchValue}, this.debouncedUpdateOptions);
}
@@ -187,9 +201,13 @@ class SearchPage extends Component {
showTitleTooltip
shouldShowOptions={didScreenTransitionEnd && isOptionsDataReady}
textInputLabel={this.props.translate('optionsSelector.nameEmailOrPhoneNumber')}
+ textInputAlert={
+ this.props.network.isOffline ? `${this.props.translate('common.youAppearToBeOffline')} ${this.props.translate('search.resultsAreLimited')}` : ''
+ }
onLayout={this.searchRendered}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
autoFocus
+ isLoadingNewOptions={this.props.isSearchingForReports}
/>
>
@@ -205,6 +223,7 @@ SearchPage.defaultProps = defaultProps;
export default compose(
withLocalize,
withWindowDimensions,
+ withNetwork(),
withOnyx({
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
@@ -215,5 +234,9 @@ export default compose(
betas: {
key: ONYXKEYS.BETAS,
},
+ isSearchingForReports: {
+ key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS,
+ initWithStoredValues: false,
+ },
}),
)(SearchPage);
diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js
index 8a7da6a7930d..51981d5fe80e 100644
--- a/src/pages/home/ReportScreen.js
+++ b/src/pages/home/ReportScreen.js
@@ -172,7 +172,6 @@ function ReportScreen({
const isLoading = !reportID || !isSidebarLoaded || _.isEmpty(personalDetails);
const parentReportAction = ReportActionsUtils.getParentReportAction(report);
- const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction);
const isSingleTransactionView = ReportUtils.isMoneyRequest(report);
const policy = policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] || {};
@@ -189,7 +188,7 @@ function ReportScreen({
/>
);
- if (isSingleTransactionView && !isDeletedParentAction) {
+ if (isSingleTransactionView) {
headerView = (
{
if (value.length === 0) {
return;
@@ -599,6 +605,9 @@ export default compose(
key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
selector: EmojiUtils.getPreferredSkinToneIndex,
},
+ editFocused: {
+ key: ONYXKEYS.INPUT_FOCUSED,
+ },
parentReportActions: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`,
canEvict: false,
diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js
index cb756ee40491..39f950b18ebe 100644
--- a/src/pages/home/report/ReportActionItemMessageEdit.js
+++ b/src/pages/home/report/ReportActionItemMessageEdit.js
@@ -35,6 +35,9 @@ import useReportScrollManager from '../../../hooks/useReportScrollManager';
import * as EmojiPickerAction from '../../../libs/actions/EmojiPickerAction';
import focusWithDelay from '../../../libs/focusWithDelay';
import * as Browser from '../../../libs/Browser';
+import * as InputFocus from '../../../libs/actions/InputFocus';
+import onyxSubscribe from '../../../libs/onyxSubscribe';
+import ONYXKEYS from '../../../ONYXKEYS';
const propTypes = {
/** All the data of the action */
@@ -111,6 +114,8 @@ function ReportActionItemMessageEdit(props) {
const [selection, setSelection] = useState(getInitialSelection());
const [isFocused, setIsFocused] = useState(false);
const [hasExceededMaxCommentLength, setHasExceededMaxCommentLength] = useState(false);
+ const [modal, setModal] = useState(false);
+ const [onyxFocused, setOnyxFocused] = useState(false);
const textInputRef = useRef(null);
const isFocusedRef = useRef(false);
@@ -128,6 +133,36 @@ function ReportActionItemMessageEdit(props) {
isFocusedRef.current = isFocused;
}, [isFocused]);
+ useEffect(() => {
+ InputFocus.composerFocusKeepFocusOn(textInputRef.current, isFocused, modal, onyxFocused);
+ }, [isFocused, modal, onyxFocused]);
+
+ useEffect(() => {
+ const unsubscribeOnyxModal = onyxSubscribe({
+ key: ONYXKEYS.MODAL,
+ callback: (modalArg) => {
+ if (_.isNull(modalArg)) {
+ return;
+ }
+ setModal(modalArg);
+ },
+ });
+
+ const unsubscribeOnyxFocused = onyxSubscribe({
+ key: ONYXKEYS.INPUT_FOCUSED,
+ callback: (modalArg) => {
+ if (_.isNull(modalArg)) {
+ return;
+ }
+ setOnyxFocused(modalArg);
+ },
+ });
+ return () => {
+ unsubscribeOnyxModal();
+ unsubscribeOnyxFocused();
+ };
+ }, []);
+
// We consider the report action active if it's focused, its emoji picker is open or its context menu is open
const isActive = useCallback(
() => isFocusedRef.current || EmojiPickerAction.isActive(props.action.reportActionID) || ReportActionContextMenu.isActiveReportAction(props.action.reportActionID),
@@ -238,6 +273,8 @@ function ReportActionItemMessageEdit(props) {
* Delete the draft of the comment being edited. This will take the comment out of "edit mode" with the old content.
*/
const deleteDraft = useCallback(() => {
+ InputFocus.callback(() => setIsFocused(false));
+ InputFocus.inputFocusChange(false);
debouncedSaveDraft.cancel();
Report.saveReportActionDraft(props.reportID, props.action, '');
diff --git a/src/pages/home/report/ReportAttachments.js b/src/pages/home/report/ReportAttachments.js
index 4146be0d3971..5f194d10bce3 100644
--- a/src/pages/home/report/ReportAttachments.js
+++ b/src/pages/home/report/ReportAttachments.js
@@ -30,7 +30,7 @@ function ReportAttachments(props) {
defaultOpen
report={report}
source={source}
- onModalHide={() => Navigation.dismissModal(reportID)}
+ onModalHide={() => Navigation.dismissModal()}
onCarouselAttachmentChange={(attachment) => {
const route = ROUTES.REPORT_ATTACHMENTS.getRoute(reportID, attachment.source);
Navigation.navigate(route);
diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js
index e8132c942854..2237e6448504 100644
--- a/src/pages/home/report/ReportFooter.js
+++ b/src/pages/home/report/ReportFooter.js
@@ -116,7 +116,9 @@ ReportFooter.defaultProps = defaultProps;
export default compose(
withWindowDimensions,
withOnyx({
- shouldShowComposeInput: {key: ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT},
- initialValue: false,
+ shouldShowComposeInput: {
+ key: ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT,
+ initialValue: false,
+ },
}),
)(ReportFooter);
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index 6b232cf31f40..d3ff3070466f 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -70,7 +70,7 @@ function SidebarLinks({onLinkClick, insets, optionListItems, isLoading, priority
const unsubscribeOnyxModal = onyxSubscribe({
key: ONYXKEYS.MODAL,
callback: (modalArg) => {
- if (_.isNull(modalArg)) {
+ if (_.isNull(modalArg) || typeof modalArg !== 'object') {
return;
}
modal.current = modalArg;
diff --git a/src/pages/iou/NewDistanceRequestPage.js b/src/pages/iou/NewDistanceRequestPage.js
index 562ea66453a1..c6ac7d72d5f8 100644
--- a/src/pages/iou/NewDistanceRequestPage.js
+++ b/src/pages/iou/NewDistanceRequestPage.js
@@ -49,7 +49,7 @@ function NewDistanceRequestPage({iou, report, route}) {
if (iou.transactionID) {
return;
}
- IOU.createEmptyTransaction();
+ IOU.setUpDistanceTransaction();
}, [iou.transactionID]);
return (
diff --git a/src/pages/iou/ReceiptSelector/NavigationAwareCamera.js b/src/pages/iou/ReceiptSelector/NavigationAwareCamera.js
index 9289fc6a2434..a419af5768b5 100644
--- a/src/pages/iou/ReceiptSelector/NavigationAwareCamera.js
+++ b/src/pages/iou/ReceiptSelector/NavigationAwareCamera.js
@@ -13,6 +13,9 @@ const propTypes = {
/* Callback function passing torch/flashlight capability as bool param of the browser */
onTorchAvailability: PropTypes.func,
+
+ /* Whether we're in a tab navigator */
+ isInTabNavigator: PropTypes.bool.isRequired,
};
const defaultProps = {
diff --git a/src/pages/iou/ReceiptSelector/NavigationAwareCamera.native.js b/src/pages/iou/ReceiptSelector/NavigationAwareCamera.native.js
index 8fa153550cbe..56fc311f0d46 100644
--- a/src/pages/iou/ReceiptSelector/NavigationAwareCamera.native.js
+++ b/src/pages/iou/ReceiptSelector/NavigationAwareCamera.native.js
@@ -11,19 +11,29 @@ const propTypes = {
/* Forwarded ref */
forwardedRef: refPropTypes.isRequired,
+
+ /* Whether we're in a tab navigator */
+ isInTabNavigator: PropTypes.bool.isRequired,
};
// Wraps a camera that will only be active when the tab is focused or as soon as it starts to become focused.
-function NavigationAwareCamera({cameraTabIndex, forwardedRef, ...props}) {
+function NavigationAwareCamera({cameraTabIndex, forwardedRef, isInTabNavigator, ...props}) {
// Get navigation to get initial isFocused value (only needed once during init!)
const navigation = useNavigation();
const [isCameraActive, setIsCameraActive] = useState(navigation.isFocused());
// Retrieve the animation value from the tab navigator, which ranges from 0 to the total number of pages displayed.
// Even a minimal scroll towards the camera page (e.g., a value of 0.001 at start) should activate the camera for immediate responsiveness.
- const tabPositionAnimation = useTabAnimation();
+
+ // STOP!!!!!!! This is not a pattern to be followed! We are conditionally rendering this hook becase when used in the edit flow we'll never be inside a tab navigator.
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const tabPositionAnimation = isInTabNavigator ? useTabAnimation() : null;
useEffect(() => {
+ if (!isInTabNavigator) {
+ return;
+ }
+
const listenerId = tabPositionAnimation.addListener(({value}) => {
// Activate camera as soon the index is animating towards the `cameraTabIndex`
setIsCameraActive(value > cameraTabIndex - 1 && value < cameraTabIndex + 1);
@@ -32,7 +42,7 @@ function NavigationAwareCamera({cameraTabIndex, forwardedRef, ...props}) {
return () => {
tabPositionAnimation.removeListener(listenerId);
};
- }, [cameraTabIndex, tabPositionAnimation]);
+ }, [cameraTabIndex, tabPositionAnimation, isInTabNavigator]);
// Note: The useEffect can be removed once VisionCamera V3 is used.
// Its only needed for android, because there is a native cameraX android bug. With out this flow would break the camera:
diff --git a/src/pages/iou/ReceiptSelector/TabNavigationAwareCamera.js b/src/pages/iou/ReceiptSelector/TabNavigationAwareCamera.js
deleted file mode 100644
index 744a10376237..000000000000
--- a/src/pages/iou/ReceiptSelector/TabNavigationAwareCamera.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import React, {useEffect, useState} from 'react';
-import {Camera} from 'react-native-vision-camera';
-import {useTabAnimation} from '@react-navigation/material-top-tabs';
-import {useNavigation} from '@react-navigation/native';
-import PropTypes from 'prop-types';
-import refPropTypes from '../../../components/refPropTypes';
-
-const propTypes = {
- /* The index of the tab that contains this camera */
- cameraTabIndex: PropTypes.number.isRequired,
-
- /* Forwarded ref */
- forwardedRef: refPropTypes.isRequired,
-};
-
-// Wraps a camera that will only be active when the tab is focused or as soon as it starts to become focused.
-function TabNavigationAwareCamera({cameraTabIndex, forwardedRef, ...props}) {
- // Get navigation to get initial isFocused value (only needed once during init!)
- const navigation = useNavigation();
- const [isCameraActive, setIsCameraActive] = useState(navigation.isFocused());
-
- // Get the animation value from the tab navigator. Its a value between 0 and the
- // number of pages we render in the tab navigator. When we even just slightly start to scroll to the camera page,
- // (value is e.g. 0.001 on animation start) we want to activate the camera, so its as fast as possible active.
- const tabPositionAnimation = useTabAnimation();
-
- useEffect(() => {
- const listenerId = tabPositionAnimation.addListener(({value}) => {
- // Activate camera as soon the index is animating towards the `cameraTabIndex`
- setIsCameraActive(value > cameraTabIndex - 1 && value < cameraTabIndex + 1);
- });
-
- return () => {
- tabPositionAnimation.removeListener(listenerId);
- };
- }, [cameraTabIndex, tabPositionAnimation]);
-
- // Note: The useEffect can be removed once VisionCamera V3 is used.
- // Its only needed for android, because there is a native cameraX android bug. With out this flow would break the camera:
- // 1. Open camera tab
- // 2. Take a picture
- // 3. Go back from the opened screen
- // 4. The camera is not working anymore
- useEffect(() => {
- const removeBlurListener = navigation.addListener('blur', () => {
- setIsCameraActive(false);
- });
- const removeFocusListener = navigation.addListener('focus', () => {
- setIsCameraActive(true);
- });
-
- return () => {
- removeBlurListener();
- removeFocusListener();
- };
- }, [navigation]);
-
- return (
-
- );
-}
-
-TabNavigationAwareCamera.propTypes = propTypes;
-TabNavigationAwareCamera.displayName = 'TabNavigationAwareCamera';
-
-export default React.forwardRef((props, ref) => (
-
-));
diff --git a/src/pages/iou/ReceiptSelector/index.native.js b/src/pages/iou/ReceiptSelector/index.native.js
index f2654a9faefb..6503d488e805 100644
--- a/src/pages/iou/ReceiptSelector/index.native.js
+++ b/src/pages/iou/ReceiptSelector/index.native.js
@@ -25,7 +25,6 @@ import {iouPropTypes, iouDefaultProps} from '../propTypes';
import NavigationAwareCamera from './NavigationAwareCamera';
import Navigation from '../../../libs/Navigation/Navigation';
import * as FileUtils from '../../../libs/fileDownload/FileUtils';
-import TabNavigationAwareCamera from './TabNavigationAwareCamera';
const propTypes = {
/** React Navigation route */
@@ -76,8 +75,6 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
const {translate} = useLocalize();
- const CameraComponent = isInTabNavigator ? TabNavigationAwareCamera : NavigationAwareCamera;
-
useEffect(() => {
const refreshCameraPermissionStatus = () => {
CameraPermission.getCameraPermissionStatus()
@@ -190,13 +187,14 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
)}
{cameraPermissionStatus === RESULTS.GRANTED && device != null && (
-
)}
diff --git a/src/pages/iou/propTypes/index.js b/src/pages/iou/propTypes/index.js
index 586f8424a2c2..d41b4cbf1724 100644
--- a/src/pages/iou/propTypes/index.js
+++ b/src/pages/iou/propTypes/index.js
@@ -21,6 +21,9 @@ const iouPropTypes = PropTypes.shape({
/** The category name */
category: PropTypes.string,
+ /** Whether the request is billable */
+ billable: PropTypes.bool,
+
/** The tag */
tag: PropTypes.string,
@@ -42,6 +45,7 @@ const iouDefaultProps = {
merchant: '',
category: '',
tag: '',
+ billable: false,
created: '',
participants: [],
receiptPath: '',
diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js
index de0e0a16c214..ea7d477717f7 100644
--- a/src/pages/iou/steps/MoneyRequestConfirmPage.js
+++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js
@@ -66,6 +66,7 @@ function MoneyRequestConfirmPage(props) {
const prevMoneyRequestId = useRef(props.iou.id);
const iouType = useRef(lodashGet(props.route, 'params.iouType', ''));
const isDistanceRequest = MoneyRequestUtils.isDistanceRequest(iouType.current, props.selectedTab);
+ const isScanRequest = MoneyRequestUtils.isScanRequest(props.selectedTab);
const reportID = useRef(lodashGet(props.route, 'params.reportID', ''));
const participants = useMemo(
() =>
@@ -378,6 +379,7 @@ function MoneyRequestConfirmPage(props) {
bankAccountRoute={ReportUtils.getBankAccountRoute(props.report)}
iouMerchant={props.iou.merchant}
iouCreated={props.iou.created}
+ isScanRequest={isScanRequest}
isDistanceRequest={isDistanceRequest}
listStyles={[StyleUtils.getMaximumHeight(windowHeight / 3)]}
shouldShowSmartScanFields={_.isEmpty(props.iou.receiptPath)}
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
index 7783b6c58ace..560a395e6844 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
@@ -39,6 +39,9 @@ function VerifyStep({account, session}) {
useEffect(() => {
Session.clearAccountMessages();
+ return () => {
+ Session.clearAccountMessages();
+ };
}, []);
useEffect(() => {
diff --git a/src/pages/settings/Wallet/PaymentMethodList.js b/src/pages/settings/Wallet/PaymentMethodList.js
index d757db370b05..2943fa9544ae 100644
--- a/src/pages/settings/Wallet/PaymentMethodList.js
+++ b/src/pages/settings/Wallet/PaymentMethodList.js
@@ -22,6 +22,11 @@ import FormAlertWrapper from '../../../components/FormAlertWrapper';
import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as PaymentMethods from '../../../libs/actions/PaymentMethods';
import Log from '../../../libs/Log';
+import stylePropTypes from '../../../styles/stylePropTypes';
+import Navigation from '../../../libs/Navigation/Navigation';
+import ROUTES from '../../../ROUTES';
+import getBankIcon from '../../../components/Icon/BankIcons';
+import assignedCardPropTypes from './assignedCardPropTypes';
const propTypes = {
/** What to do when a menu item is pressed */
@@ -30,12 +35,24 @@ const propTypes = {
/** List of bank accounts */
bankAccountList: PropTypes.objectOf(bankAccountPropTypes),
+ /** List of assigned cards */
+ cardList: PropTypes.objectOf(assignedCardPropTypes),
+
/** List of user's cards */
fundList: PropTypes.objectOf(cardPropTypes),
+ /** Whether the add bank account button should be shown on the list */
+ shouldShowAddBankAccount: PropTypes.bool,
+
/** Whether the add Payment button be shown on the list */
shouldShowAddPaymentMethodButton: PropTypes.bool,
+ /** Whether the assigned cards should be shown on the list */
+ shouldShowAssignedCards: PropTypes.bool,
+
+ /** Whether the empty list message should be shown when the list is empty */
+ shouldShowEmptyListMessage: PropTypes.bool,
+
/** Are we loading payment methods? */
isLoadingPaymentMethods: PropTypes.bool,
@@ -69,18 +86,28 @@ const propTypes = {
/** React ref being forwarded to the PaymentMethodList Button */
buttonRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ /** To enable/disable scrolling */
+ shouldEnableScroll: PropTypes.bool,
+
+ /** List container style */
+ style: stylePropTypes,
+
...withLocalizePropTypes,
};
const defaultProps = {
bankAccountList: {},
+ cardList: {},
fundList: null,
userWallet: {
walletLinkedAccountID: 0,
walletLinkedAccountType: '',
},
isLoadingPaymentMethods: true,
+ shouldShowAddBankAccount: true,
shouldShowAddPaymentMethodButton: true,
+ shouldShowAssignedCards: false,
+ shouldShowEmptyListMessage: true,
filterType: '',
actionPaymentMethodType: '',
activePaymentMethodID: '',
@@ -88,6 +115,8 @@ const defaultProps = {
listHeaderComponent: null,
buttonRef: () => {},
onListContentSizeChange: () => {},
+ shouldEnableScroll: true,
+ style: {},
};
/**
@@ -143,11 +172,46 @@ function shouldShowDefaultBadge(filteredPaymentMethods, isDefault = false) {
function isPaymentMethodActive(actionPaymentMethodType, activePaymentMethodID, paymentMethod) {
return paymentMethod.accountType === actionPaymentMethodType && paymentMethod.methodID === activePaymentMethodID;
}
-function PaymentMethodList(props) {
- const {actionPaymentMethodType, activePaymentMethodID, bankAccountList, fundList, filterType, network, onPress, shouldShowSelectedState, selectedMethodID, translate} = props;
-
+function PaymentMethodList({
+ actionPaymentMethodType,
+ activePaymentMethodID,
+ bankAccountList,
+ buttonRef,
+ cardList,
+ fundList,
+ filterType,
+ isLoadingPaymentMethods,
+ listHeaderComponent,
+ network,
+ onListContentSizeChange,
+ onPress,
+ shouldEnableScroll,
+ shouldShowSelectedState,
+ shouldShowAddPaymentMethodButton,
+ shouldShowAddBankAccount,
+ shouldShowEmptyListMessage,
+ shouldShowAssignedCards,
+ selectedMethodID,
+ style,
+ translate,
+}) {
const filteredPaymentMethods = useMemo(() => {
const paymentCardList = fundList || {};
+
+ if (shouldShowAssignedCards) {
+ const assignedCards = _.filter(cardList, (card) => CONST.EXPENSIFY_CARD.ACTIVE_STATES.includes(card.state));
+ return _.map(assignedCards, (card) => {
+ const icon = getBankIcon(card.bank);
+ return {
+ key: card.key,
+ title: translate('walletPage.expensifyCard'),
+ description: card.domainName,
+ onPress: () => Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARDS.getRoute(card.domainName)),
+ ...icon,
+ };
+ });
+ }
+
// Hide any billing cards that are not P2P debit cards for now because you cannot make them your default method, or delete them
const filteredCardList = _.filter(paymentCardList, (card) => card.accountData.additionalData.isP2PDebitCard);
let combinedPaymentMethods = PaymentUtils.formatPaymentMethods(bankAccountList, filteredCardList);
@@ -174,14 +238,26 @@ function PaymentMethodList(props) {
}));
return combinedPaymentMethods;
- }, [actionPaymentMethodType, activePaymentMethodID, bankAccountList, filterType, network, onPress, fundList]);
+ }, [fundList, shouldShowAssignedCards, bankAccountList, filterType, network.isOffline, cardList, translate, actionPaymentMethodType, activePaymentMethodID, onPress]);
/**
* Render placeholder when there are no payments methods
*
* @return {React.Component}
*/
- const renderListEmptyComponent = useCallback(() => {translate('paymentMethodList.addFirstPaymentMethod')}, [translate]);
+ const renderListEmptyComponent = () => {translate('paymentMethodList.addFirstPaymentMethod')};
+
+ const renderListFooterComponent = useCallback(
+ () => (
+
+ ),
+ [onPress, translate],
+ );
/**
* Create a menuItem for each passed paymentMethod
@@ -209,13 +285,14 @@ function PaymentMethodList(props) {
iconHeight={item.iconSize}
iconWidth={item.iconSize}
badgeText={shouldShowDefaultBadge(filteredPaymentMethods, item.isDefault) ? translate('paymentMethodList.defaultPaymentMethod') : null}
- wrapperStyle={item.wrapperStyle}
+ wrapperStyle={styles.paymentMethod}
+ shouldShowRightIcon={shouldShowAssignedCards}
shouldShowSelectedState={shouldShowSelectedState}
isSelected={selectedMethodID === item.methodID}
/>
),
- [shouldShowSelectedState, selectedMethodID, filteredPaymentMethods, translate],
+ [filteredPaymentMethods, translate, shouldShowAssignedCards, shouldShowSelectedState, selectedMethodID],
);
return (
@@ -224,25 +301,28 @@ function PaymentMethodList(props) {
data={filteredPaymentMethods}
renderItem={renderItem}
keyExtractor={(item) => item.key}
- ListEmptyComponent={renderListEmptyComponent(translate)}
- ListHeaderComponent={props.listHeaderComponent}
- onContentSizeChange={props.onListContentSizeChange}
+ ListEmptyComponent={shouldShowEmptyListMessage ? renderListEmptyComponent : null}
+ ListHeaderComponent={listHeaderComponent}
+ ListFooterComponent={shouldShowAddBankAccount ? renderListFooterComponent : null}
+ onContentSizeChange={onListContentSizeChange}
+ scrollEnabled={shouldEnableScroll}
+ style={style}
/>
- {props.shouldShowAddPaymentMethodButton && (
+ {shouldShowAddPaymentMethodButton && (
{(isOffline) => (
)}
@@ -262,6 +342,9 @@ export default compose(
bankAccountList: {
key: ONYXKEYS.BANK_ACCOUNT_LIST,
},
+ cardList: {
+ key: ONYXKEYS.CARD_LIST,
+ },
fundList: {
key: ONYXKEYS.FUND_LIST,
},
diff --git a/src/pages/settings/Wallet/WalletEmptyState.js b/src/pages/settings/Wallet/WalletEmptyState.js
new file mode 100644
index 000000000000..adfd2cf49cee
--- /dev/null
+++ b/src/pages/settings/Wallet/WalletEmptyState.js
@@ -0,0 +1,62 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import IllustratedHeaderPageLayout from '../../../components/IllustratedHeaderPageLayout';
+import useLocalize from '../../../hooks/useLocalize';
+import * as LottieAnimations from '../../../components/LottieAnimations';
+import Button from '../../../components/Button';
+import Navigation from '../../../libs/Navigation/Navigation';
+import ROUTES from '../../../ROUTES';
+import * as Illustrations from '../../../components/Icon/Illustrations';
+import FeatureList from '../../../components/FeatureList';
+import themeColors from '../../../styles/themes/default';
+
+const propTypes = {
+ /** The function that is called when a menu item is pressed */
+ onAddPaymentMethod: PropTypes.func.isRequired,
+};
+
+const WALLET_FEATURES = [
+ {
+ icon: Illustrations.MoneyIntoWallet,
+ translationKey: 'walletPage.getPaidBackFaster',
+ },
+ {
+ icon: Illustrations.OpenSafe,
+ translationKey: 'walletPage.secureAccessToYourMoney',
+ },
+ {
+ icon: Illustrations.HandEarth,
+ translationKey: 'walletPage.receiveMoney',
+ },
+];
+
+function WalletEmptyState({onAddPaymentMethod}) {
+ const {translate} = useLocalize();
+ return (
+ Navigation.goBack(ROUTES.SETTINGS)}
+ title={translate('common.wallet')}
+ footer={
+
+ }
+ >
+
+
+ );
+}
+
+WalletEmptyState.displayName = 'WalletEmptyState';
+WalletEmptyState.propTypes = propTypes;
+
+export default WalletEmptyState;
diff --git a/src/pages/settings/Wallet/WalletPage/BaseWalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
similarity index 50%
rename from src/pages/settings/Wallet/WalletPage/BaseWalletPage.js
rename to src/pages/settings/Wallet/WalletPage/WalletPage.js
index 2b53f96df010..ec9ff537189e 100644
--- a/src/pages/settings/Wallet/WalletPage/BaseWalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -1,18 +1,17 @@
import React, {useCallback, useEffect, useState, useRef} from 'react';
-import {ActivityIndicator, View, InteractionManager} from 'react-native';
+import {ActivityIndicator, View, InteractionManager, ScrollView} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import PaymentMethodList from '../PaymentMethodList';
import ROUTES from '../../../../ROUTES';
import HeaderWithBackButton from '../../../../components/HeaderWithBackButton';
import ScreenWrapper from '../../../../components/ScreenWrapper';
-import Navigation from '../../../../libs/Navigation/Navigation';
+import Navigation, {navigationRef} from '../../../../libs/Navigation/Navigation';
import styles from '../../../../styles/styles';
import compose from '../../../../libs/compose';
import * as BankAccounts from '../../../../libs/actions/BankAccounts';
import Popover from '../../../../components/Popover';
import MenuItem from '../../../../components/MenuItem';
-import Text from '../../../../components/Text';
import * as PaymentMethods from '../../../../libs/actions/PaymentMethods';
import getClickedTargetLocation from '../../../../libs/getClickedTargetLocation';
import CurrentWalletBalance from '../../../../components/CurrentWalletBalance';
@@ -32,8 +31,11 @@ import themeColors from '../../../../styles/themes/default';
import variables from '../../../../styles/variables';
import useLocalize from '../../../../hooks/useLocalize';
import useWindowDimensions from '../../../../hooks/useWindowDimensions';
+import WalletEmptyState from '../WalletEmptyState';
+import * as Illustrations from '../../../../components/Icon/Illustrations';
+import WalletSection from '../../../../components/WalletSection';
-function BaseWalletPage(props) {
+function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymentMethods, network, shouldListenForResize, userWallet, walletTerms}) {
const {translate} = useLocalize();
const {isSmallScreenWidth, windowWidth} = useWindowDimensions();
const [shouldShowAddPaymentMenu, setShouldShowAddPaymentMenu] = useState(false);
@@ -58,13 +60,18 @@ function BaseWalletPage(props) {
});
const [showConfirmDeleteContent, setShowConfirmDeleteContent] = useState(false);
+ const hasBankAccount = !_.isEmpty(bankAccountList) || !_.isEmpty(fundList);
+ const hasWallet = userWallet.walletLinkedAccountID > 0;
+ const hasAssignedCard = !_.isEmpty(cardList);
+ const shouldShowEmptyState = !hasBankAccount && !hasWallet && !hasAssignedCard;
+
const updateShouldShowLoadingSpinner = useCallback(() => {
// In order to prevent a loop, only update state of the spinner if there is a change
- const showLoadingSpinner = props.isLoadingPaymentMethods || false;
+ const showLoadingSpinner = isLoadingPaymentMethods || false;
if (showLoadingSpinner !== shouldShowLoadingSpinner) {
- setShouldShowLoadingSpinner(props.isLoadingPaymentMethods && !props.network.isOffline);
+ setShouldShowLoadingSpinner(isLoadingPaymentMethods && !network.isOffline);
}
- }, [props.isLoadingPaymentMethods, props.network.isOffline, shouldShowLoadingSpinner]);
+ }, [isLoadingPaymentMethods, network.isOffline, shouldShowLoadingSpinner]);
const debounceSetShouldShowLoadingSpinner = _.debounce(updateShouldShowLoadingSpinner, CONST.TIMING.SHOW_LOADING_SPINNER_DEBOUNCE_TIME);
@@ -82,13 +89,12 @@ function BaseWalletPage(props) {
setAnchorPosition({
anchorPositionTop: position.top + position.height + variables.addPaymentPopoverTopSpacing,
-
- // We want the position to be 13px to the right of the left border
- anchorPositionRight: windowWidth - position.right + variables.addPaymentPopoverRightSpacing,
- anchorPositionHorizontal: position.x,
+ // We want the position to be 23px to the right of the left border
+ anchorPositionRight: windowWidth - position.right - variables.addBankAccountLeftSpacing,
+ anchorPositionHorizontal: position.x + (shouldShowEmptyState ? -variables.addPaymentMethodLeftSpacing : variables.addBankAccountLeftSpacing),
anchorPositionVertical: position.y,
});
- }, [windowWidth]);
+ }, [shouldShowEmptyState, windowWidth]);
const getSelectedPaymentMethodID = useCallback(() => {
if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
@@ -207,9 +213,9 @@ function BaseWalletPage(props) {
}, [setShouldShowDefaultDeleteMenu, setShowConfirmDeleteContent]);
const makeDefaultPaymentMethod = useCallback(() => {
- const paymentCardList = props.fundList || {};
+ const paymentCardList = fundList || {};
// Find the previous default payment method so we can revert if the MakeDefaultPaymentMethod command errors
- const paymentMethods = PaymentUtils.formatPaymentMethods(props.bankAccountList, paymentCardList);
+ const paymentMethods = PaymentUtils.formatPaymentMethods(bankAccountList, paymentCardList);
const previousPaymentMethod = _.find(paymentMethods, (method) => method.isDefault);
const currentPaymentMethod = _.find(paymentMethods, (method) => method.methodID === paymentMethod.methodID);
@@ -223,8 +229,8 @@ function BaseWalletPage(props) {
paymentMethod.selectedPaymentMethod.bankAccountID,
paymentMethod.selectedPaymentMethod.fundID,
paymentMethod.selectedPaymentMethodType,
- props.bankAccountList,
- props.fundList,
+ bankAccountList,
+ fundList,
]);
const deletePaymentMethod = useCallback(() => {
@@ -239,87 +245,32 @@ function BaseWalletPage(props) {
Navigation.navigate(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE);
};
- const listHeaderComponent = useCallback(
- () => (
- <>
- {Permissions.canUseWallet(props.betas) && (
- <>
-
- {shouldShowLoadingSpinner ? (
-
- ) : (
-
-
-
- )}
-
- {props.userWallet.currentBalance > 0 && (
-
-
- {(triggerKYCFlow, buttonRef) => (
-
- )}
-
-
- )}
- >
- )}
- {translate('walletPage.paymentMethodsTitle')}
- >
- ),
- [props.betas, props.network.isOffline, props.userWallet.currentBalance, props.walletTerms.errors, shouldShowLoadingSpinner, translate],
- );
-
useEffect(() => {
PaymentMethods.openWalletPage();
}, []);
useEffect(() => {
// If the user was previously offline, skip debouncing showing the loader
- if (!props.network.isOffline) {
+ if (!network.isOffline) {
updateShouldShowLoadingSpinner();
} else {
debounceSetShouldShowLoadingSpinner();
}
- }, [props.network.isOffline, debounceSetShouldShowLoadingSpinner, updateShouldShowLoadingSpinner]);
+ }, [network.isOffline, debounceSetShouldShowLoadingSpinner, updateShouldShowLoadingSpinner]);
useEffect(() => {
- if (props.network.isOffline) {
+ if (network.isOffline) {
return;
}
PaymentMethods.openWalletPage();
- }, [props.network.isOffline]);
+ }, [network.isOffline]);
useEffect(() => {
- if (!props.shouldListenForResize) {
+ if (!shouldListenForResize) {
return;
}
setMenuPosition();
- }, [props.shouldListenForResize, setMenuPosition]);
+ }, [shouldListenForResize, setMenuPosition]);
useEffect(() => {
if (!shouldShowDefaultDeleteMenu) {
@@ -329,9 +280,9 @@ function BaseWalletPage(props) {
// We should reset selected payment method state values and close corresponding modals if the selected payment method is deleted
let shouldResetPaymentMethodData = false;
- if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT && _.isEmpty(props.bankAccountList[paymentMethod.methodID])) {
+ if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT && _.isEmpty(bankAccountList[paymentMethod.methodID])) {
shouldResetPaymentMethodData = true;
- } else if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD && _.isEmpty(props.fundList[paymentMethod.methodID])) {
+ } else if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD && _.isEmpty(fundList[paymentMethod.methodID])) {
shouldResetPaymentMethodData = true;
}
if (shouldResetPaymentMethodData) {
@@ -340,42 +291,193 @@ function BaseWalletPage(props) {
hideDefaultDeleteMenu();
}
}
- }, [hideDefaultDeleteMenu, paymentMethod.methodID, paymentMethod.selectedPaymentMethodType, props.bankAccountList, props.fundList, shouldShowDefaultDeleteMenu]);
+ }, [hideDefaultDeleteMenu, paymentMethod.methodID, paymentMethod.selectedPaymentMethodType, bankAccountList, fundList, shouldShowDefaultDeleteMenu]);
+
+ useEffect(() => {
+ if (!shouldShowEmptyState) {
+ return;
+ }
+ navigationRef.setParams({backgroundColor: themeColors.walletPageBG});
+ }, [shouldShowEmptyState]);
const shouldShowMakeDefaultButton =
!paymentMethod.isSelectedPaymentMethodDefault &&
- Permissions.canUseWallet(props.betas) &&
+ Permissions.canUseWallet(betas) &&
!(paymentMethod.formattedSelectedPaymentMethod.type === CONST.PAYMENT_METHODS.BANK_ACCOUNT && paymentMethod.selectedPaymentMethod.type === CONST.BANK_ACCOUNT.TYPE.BUSINESS);
// Determines whether or not the modal popup is mounted from the bottom of the screen instead of the side mount on Web or Desktop screens
const isPopoverBottomMount = anchorPosition.anchorPositionTop === 0 || isSmallScreenWidth;
return (
-
- Navigation.goBack(ROUTES.SETTINGS)}
- />
-
- PaymentMethods.clearWalletError()}
- errors={props.userWallet.errors}
- errorRowStyles={[styles.ph6]}
- >
- {}}
+ <>
+ {shouldShowEmptyState ? (
+
+ ) : (
+
+ Navigation.goBack(ROUTES.SETTINGS)}
/>
-
-
+
+
+
+ {hasWallet && (
+
+ <>
+ {shouldShowLoadingSpinner ? (
+
+ ) : (
+
+
+
+ )}
+
+ {(triggerKYCFlow, buttonRef) => (
+
+ )}
+
+ >
+
+ )}
+ {hasAssignedCard ? (
+
+ {}}
+ />
+
+ ) : null}
+
+ {}}
+ shouldEnableScroll={false}
+ style={styles.mt5}
+ />
+
+
+
+
+
+ {!showConfirmDeleteContent ? (
+
+ {isPopoverBottomMount && (
+
+ )}
+ {shouldShowMakeDefaultButton && (
+
+ ) : (
+ {
+ deletePaymentMethod();
+ hideDefaultDeleteMenu();
+ }}
+ onCancel={hideDefaultDeleteMenu}
+ contentStyles={!isSmallScreenWidth ? [styles.sidebarPopover, styles.willChangeTransform] : undefined}
+ title={translate('walletPage.deleteAccount')}
+ prompt={translate('walletPage.deleteConfirmation')}
+ confirmText={translate('common.delete')}
+ cancelText={translate('common.cancel')}
+ anchorPosition={{
+ top: anchorPosition.anchorPositionTop,
+ right: anchorPosition.anchorPositionRight,
+ }}
+ shouldShowCancelButton
+ danger
+ />
+ )}
+
+
+ )}
addPaymentMethodTypePressed(method)}
anchorRef={addPaymentMethodAnchorRef}
/>
-
- {!showConfirmDeleteContent ? (
-
- {isPopoverBottomMount && (
-
- )}
- {shouldShowMakeDefaultButton && (
- {
- makeDefaultPaymentMethod();
- setShouldShowDefaultDeleteMenu(false);
- }}
- text={translate('walletPage.setDefaultConfirmation')}
- />
- )}
- {
- setShowConfirmDeleteContent(true);
- }}
- style={[shouldShowMakeDefaultButton ? styles.mt4 : {}]}
- text={translate('common.delete')}
- danger
- />
-
- ) : (
- {
- deletePaymentMethod();
- hideDefaultDeleteMenu();
- }}
- onCancel={hideDefaultDeleteMenu}
- contentStyles={!isSmallScreenWidth ? [styles.sidebarPopover, styles.willChangeTransform] : undefined}
- title={translate('walletPage.deleteAccount')}
- prompt={translate('walletPage.deleteConfirmation')}
- confirmText={translate('common.delete')}
- cancelText={translate('common.cancel')}
- anchorPosition={{
- top: anchorPosition.anchorPositionTop,
- right: anchorPosition.anchorPositionRight,
- }}
- shouldShowCancelButton
- danger
- />
- )}
-
-
+ >
);
}
-BaseWalletPage.propTypes = propTypes;
-BaseWalletPage.defaultProps = defaultProps;
-BaseWalletPage.displayName = 'BaseWalletPage';
+WalletPage.propTypes = propTypes;
+WalletPage.defaultProps = defaultProps;
+WalletPage.displayName = 'WalletPage';
export default compose(
withNetwork(),
@@ -461,6 +502,9 @@ export default compose(
betas: {
key: ONYXKEYS.BETAS,
},
+ cardList: {
+ key: ONYXKEYS.CARD_LIST,
+ },
walletTransfer: {
key: ONYXKEYS.WALLET_TRANSFER,
},
@@ -480,4 +524,4 @@ export default compose(
key: ONYXKEYS.IS_LOADING_PAYMENT_METHODS,
},
}),
-)(BaseWalletPage);
+)(WalletPage);
diff --git a/src/pages/settings/Wallet/WalletPage/index.js b/src/pages/settings/Wallet/WalletPage/index.js
index 23a3b44d0801..4e2777f00ae8 100644
--- a/src/pages/settings/Wallet/WalletPage/index.js
+++ b/src/pages/settings/Wallet/WalletPage/index.js
@@ -1,10 +1,10 @@
import React from 'react';
-import BaseWalletPage from './BaseWalletPage';
+import WalletPage from './WalletPage';
-function WalletPage() {
- return ;
+function WalletPageComponent() {
+ return ;
}
-WalletPage.displayName = 'WalletPage';
+WalletPageComponent.displayName = 'WalletPage';
-export default WalletPage;
+export default WalletPageComponent;
diff --git a/src/pages/settings/Wallet/WalletPage/index.native.js b/src/pages/settings/Wallet/WalletPage/index.native.js
index d8e291e66aa6..79b626e6e709 100644
--- a/src/pages/settings/Wallet/WalletPage/index.native.js
+++ b/src/pages/settings/Wallet/WalletPage/index.native.js
@@ -1,3 +1,3 @@
-import BaseWalletPage from './BaseWalletPage';
+import WalletPage from './WalletPage';
-export default BaseWalletPage;
+export default WalletPage;
diff --git a/src/pages/settings/Wallet/WalletPage/walletPagePropTypes.js b/src/pages/settings/Wallet/WalletPage/walletPagePropTypes.js
index cdfe19cbf2b4..3c411d7984e4 100644
--- a/src/pages/settings/Wallet/WalletPage/walletPagePropTypes.js
+++ b/src/pages/settings/Wallet/WalletPage/walletPagePropTypes.js
@@ -44,6 +44,7 @@ const defaultProps = {
shouldListenForResize: false,
userWallet: {},
bankAccountList: {},
+ cardList: {},
fundList: null,
walletTerms: {},
};
diff --git a/src/pages/settings/Wallet/assignedCardPropTypes.js b/src/pages/settings/Wallet/assignedCardPropTypes.js
index 06779e473579..e45b57a05d31 100644
--- a/src/pages/settings/Wallet/assignedCardPropTypes.js
+++ b/src/pages/settings/Wallet/assignedCardPropTypes.js
@@ -8,14 +8,11 @@ const assignedCardPropTypes = PropTypes.shape({
bank: PropTypes.string,
availableSpend: PropTypes.number,
domainName: PropTypes.string,
- lastFourPAN: PropTypes.string,
- cardName: PropTypes.string,
+ maskedPan: PropTypes.string,
isVirtual: PropTypes.bool,
fraud: PropTypes.oneOf([CONST.EXPENSIFY_CARD.FRAUD_TYPES.DOMAIN, CONST.EXPENSIFY_CARD.FRAUD_TYPES.USER, CONST.EXPENSIFY_CARD.FRAUD_TYPES.NONE]),
cardholderFirstName: PropTypes.string,
cardholderLastName: PropTypes.string,
- errors: PropTypes.objectOf(PropTypes.string),
- isLoading: PropTypes.bool,
});
export default assignedCardPropTypes;
diff --git a/src/pages/signin/SignInPageLayout/Footer.js b/src/pages/signin/SignInPageLayout/Footer.js
index 62733f3cec9e..2fb5e45db760 100644
--- a/src/pages/signin/SignInPageLayout/Footer.js
+++ b/src/pages/signin/SignInPageLayout/Footer.js
@@ -10,8 +10,6 @@ import variables from '../../../styles/variables';
import * as Expensicons from '../../../components/Icon/Expensicons';
import TextLink from '../../../components/TextLink';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
-import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
-import compose from '../../../libs/compose';
import Licenses from '../Licenses';
import Socials from '../Socials';
import Hoverable from '../../../components/Hoverable';
@@ -20,12 +18,14 @@ import * as Session from '../../../libs/actions/Session';
import SignInGradient from '../../../../assets/images/home-fade-gradient--mobile.svg';
const propTypes = {
- ...windowDimensionsPropTypes,
...withLocalizePropTypes,
scrollPageToTop: PropTypes.func.isRequired,
+ shouldShowSmallScreen: PropTypes.bool,
};
-const defaultProps = {};
+const defaultProps = {
+ shouldShowSmallScreen: false,
+};
const navigateHome = (scrollPageToTop) => {
scrollPageToTop();
@@ -150,7 +150,7 @@ const columns = ({scrollPageToTop}) => [
];
function Footer(props) {
- const isVertical = props.isSmallScreenWidth;
+ const isVertical = props.shouldShowSmallScreen;
const imageDirection = isVertical ? styles.flexRow : styles.flexColumn;
const imageStyle = isVertical ? styles.pr0 : styles.alignSelfCenter;
const columnDirection = isVertical ? styles.flexColumn : styles.flexRow;
@@ -225,4 +225,4 @@ Footer.propTypes = propTypes;
Footer.displayName = 'Footer';
Footer.defaultProps = defaultProps;
-export default compose(withLocalize, withWindowDimensions)(Footer);
+export default withLocalize(Footer);
diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js
index 1f70364c307b..fdc88b6ede9e 100644
--- a/src/pages/signin/SignInPageLayout/index.js
+++ b/src/pages/signin/SignInPageLayout/index.js
@@ -170,7 +170,10 @@ function SignInPageLayout(props) {
-
+
)}
diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js
index e1fbab65486b..da0bf845cc81 100644
--- a/src/pages/workspace/WorkspaceNewRoomPage.js
+++ b/src/pages/workspace/WorkspaceNewRoomPage.js
@@ -1,4 +1,4 @@
-import React, {useState, useCallback, useMemo, useRef} from 'react';
+import React, {useState, useEffect, useCallback, useMemo, useRef} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import {withOnyx} from 'react-native-onyx';
@@ -9,12 +9,12 @@ import * as App from '../../libs/actions/App';
import useLocalize from '../../hooks/useLocalize';
import styles from '../../styles/styles';
import RoomNameInput from '../../components/RoomNameInput';
-import Picker from '../../components/Picker';
import KeyboardAvoidingView from '../../components/KeyboardAvoidingView';
import ScreenWrapper from '../../components/ScreenWrapper';
import ONYXKEYS from '../../ONYXKEYS';
import CONST from '../../CONST';
import Text from '../../components/Text';
+import TextInput from '../../components/TextInput';
import Permissions from '../../libs/Permissions';
import * as ErrorUtils from '../../libs/ErrorUtils';
import * as ValidationUtils from '../../libs/ValidationUtils';
@@ -26,6 +26,7 @@ import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoun
import compose from '../../libs/compose';
import variables from '../../styles/variables';
import useDelayedInputFocus from '../../hooks/useDelayedInputFocus';
+import ValuePicker from '../../components/ValuePicker';
const propTypes = {
/** All reports shared with the user */
@@ -73,6 +74,7 @@ function WorkspaceNewRoomPage(props) {
const {translate} = useLocalize();
const [visibility, setVisibility] = useState(CONST.REPORT.VISIBILITY.RESTRICTED);
const [policyID, setPolicyID] = useState(null);
+ const [writeCapability, setWriteCapability] = useState(CONST.REPORT.WRITE_CAPABILITIES.ALL);
const visibilityDescription = useMemo(() => translate(`newRoomPage.${visibility}Description`), [translate, visibility]);
const isPolicyAdmin = useMemo(() => {
if (!policyID) {
@@ -87,9 +89,17 @@ function WorkspaceNewRoomPage(props) {
*/
const submit = (values) => {
const policyMembers = _.map(_.keys(props.allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${values.policyID}`]), (accountID) => Number(accountID));
- Report.addPolicyReport(values.policyID, values.roomName, values.visibility, policyMembers, values.writeCapability);
+ Report.addPolicyReport(policyID, values.roomName, visibility, policyMembers, writeCapability, values.welcomeMessage);
};
+ useEffect(() => {
+ if (isPolicyAdmin) {
+ return;
+ }
+
+ setWriteCapability(CONST.REPORT.WRITE_CAPABILITIES.ALL);
+ }, [isPolicyAdmin]);
+
/**
* @param {Object} values - form input values passed by the Form component
* @returns {Boolean}
@@ -166,8 +176,8 @@ function WorkspaceNewRoomPage(props) {
>
{({insets}) => (
-
-
+
+
+
+
{isPolicyAdmin && (
-
-
+
)}
-
-
+
{visibilityDescription}
diff --git a/src/stories/ReportActionItemImages.stories.js b/src/stories/ReportActionItemImages.stories.js
new file mode 100644
index 000000000000..e619cc2ee143
--- /dev/null
+++ b/src/stories/ReportActionItemImages.stories.js
@@ -0,0 +1,142 @@
+import React from 'react';
+import ReportActionItemImages from '../components/ReportActionItem/ReportActionItemImages';
+import PressableWithoutFeedback from '../components/Pressable/PressableWithoutFeedback';
+
+/**
+ * We use the Component Story Format for writing stories. Follow the docs here:
+ *
+ * https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format
+ */
+const story = {
+ title: 'Components/ReportActionItemImages',
+ component: ReportActionItemImages,
+};
+
+function Template(args) {
+ return (
+
+ {({hovered}) => (
+
+ )}
+
+ );
+}
+
+// Arguments can be passed to the component by binding
+// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
+const Default = Template.bind({});
+Default.args = {
+ images: [{image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg', thumbnail: ''}],
+ size: 1,
+ total: 1,
+};
+
+const TwoImages = Template.bind({});
+TwoImages.args = {
+ images: [
+ {
+ image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://i.guim.co.uk/img/media/7d04c4cb7510a4bd9a8bec449f53425aeccee895/298_266_1150_690/master/1150.jpg?width=1200&quality=85&auto=format&fit=max&s=4ae508ecb99c15ec04610b617efb3fa7',
+ thumbnail: '',
+ },
+ ],
+ size: 2,
+ total: 2,
+};
+
+const ThreeImages = Template.bind({});
+ThreeImages.args = {
+ images: [
+ {
+ image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://i.guim.co.uk/img/media/7d04c4cb7510a4bd9a8bec449f53425aeccee895/298_266_1150_690/master/1150.jpg?width=1200&quality=85&auto=format&fit=max&s=4ae508ecb99c15ec04610b617efb3fa7',
+ thumbnail: '',
+ },
+ {
+ image: 'https://cdn.theatlantic.com/thumbor/d8lh_KAZuOgBYslMOP4T0iu9Fks=/0x62:2000x1187/1600x900/media/img/mt/2018/03/AP_325360162607/original.jpg',
+ thumbnail: '',
+ },
+ ],
+ size: 3,
+ total: 3,
+};
+
+const FourImages = Template.bind({});
+FourImages.args = {
+ images: [
+ {
+ image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://i.guim.co.uk/img/media/7d04c4cb7510a4bd9a8bec449f53425aeccee895/298_266_1150_690/master/1150.jpg?width=1200&quality=85&auto=format&fit=max&s=4ae508ecb99c15ec04610b617efb3fa7',
+ thumbnail: '',
+ },
+ {
+ image: 'https://cdn.theatlantic.com/thumbor/d8lh_KAZuOgBYslMOP4T0iu9Fks=/0x62:2000x1187/1600x900/media/img/mt/2018/03/AP_325360162607/original.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg',
+ thumbnail: '',
+ },
+ ],
+ size: 4,
+ total: 4,
+};
+
+const ThreePlusTwoImages = Template.bind({});
+ThreePlusTwoImages.args = {
+ images: [
+ {
+ image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://i.guim.co.uk/img/media/7d04c4cb7510a4bd9a8bec449f53425aeccee895/298_266_1150_690/master/1150.jpg?width=1200&quality=85&auto=format&fit=max&s=4ae508ecb99c15ec04610b617efb3fa7',
+ thumbnail: '',
+ },
+ {
+ image: 'https://cdn.theatlantic.com/thumbor/d8lh_KAZuOgBYslMOP4T0iu9Fks=/0x62:2000x1187/1600x900/media/img/mt/2018/03/AP_325360162607/original.jpg',
+ thumbnail: '',
+ },
+ ],
+ size: 3,
+ total: 5,
+};
+
+const ThreePlusTenImages = Template.bind({});
+ThreePlusTenImages.args = {
+ images: [
+ {
+ image: 'https://c02.purpledshub.com/uploads/sites/41/2021/05/sleeping-cat-27126ee.jpg',
+ thumbnail: '',
+ },
+ {
+ image: 'https://i.guim.co.uk/img/media/7d04c4cb7510a4bd9a8bec449f53425aeccee895/298_266_1150_690/master/1150.jpg?width=1200&quality=85&auto=format&fit=max&s=4ae508ecb99c15ec04610b617efb3fa7',
+ thumbnail: '',
+ },
+ {
+ image: 'https://cdn.theatlantic.com/thumbor/d8lh_KAZuOgBYslMOP4T0iu9Fks=/0x62:2000x1187/1600x900/media/img/mt/2018/03/AP_325360162607/original.jpg',
+ thumbnail: '',
+ },
+ ],
+ size: 3,
+ total: 13,
+};
+
+export default story;
+export {Default, TwoImages, ThreeImages, FourImages, ThreePlusTwoImages, ThreePlusTenImages};
diff --git a/src/styles/StyleUtils.ts b/src/styles/StyleUtils.ts
index 3cd89dcf349f..62da2bf3be4b 100644
--- a/src/styles/StyleUtils.ts
+++ b/src/styles/StyleUtils.ts
@@ -1,20 +1,23 @@
-import {EdgeInsets} from 'react-native-safe-area-context';
-import {Animated, PressableStateCallbackType, TextStyle, ViewStyle} from 'react-native';
import {CSSProperties} from 'react';
+import {Animated, DimensionValue, ImageStyle, PressableStateCallbackType, TextStyle, ViewStyle} from 'react-native';
+import {EdgeInsets} from 'react-native-safe-area-context';
import {ValueOf} from 'type-fest';
import CONST from '../CONST';
+import * as Browser from '../libs/Browser';
+import * as UserUtils from '../libs/UserUtils';
+import colors from './colors';
import fontFamily from './fontFamily';
+import styles from './styles';
import themeColors from './themes/default';
-import variables from './variables';
-import colors from './colors';
+import cursor from './utilities/cursor';
import positioning from './utilities/positioning';
-import styles from './styles';
import spacing from './utilities/spacing';
-import * as UserUtils from '../libs/UserUtils';
-import * as Browser from '../libs/Browser';
-import cursor from './utilities/cursor';
+import variables from './variables';
import {Transaction} from '../types/onyx';
+type AllStyles = ViewStyle | TextStyle | ImageStyle;
+type ParsableStyle = AllStyles | ((state: PressableStateCallbackType) => AllStyles);
+
type ColorValue = ValueOf;
type AvatarSizeName = ValueOf;
type EReceiptColorName = ValueOf;
@@ -40,12 +43,11 @@ type ButtonSizeValue = ValueOf;
type EmptyAvatarSizeName = ValueOf>;
type ButtonStateName = ValueOf;
type AvatarSize = {width: number};
-type ParsableStyle = ViewStyle | CSSProperties | ((state: PressableStateCallbackType) => ViewStyle | CSSProperties);
type WorkspaceColorStyle = {backgroundColor: ColorValue; fill: ColorValue};
type EreceiptColorStyle = {backgroundColor: ColorValue; color: ColorValue};
-type ModalPaddingStylesArgs = {
+type ModalPaddingStylesParams = {
shouldAddBottomSafeAreaMargin: boolean;
shouldAddTopSafeAreaMargin: boolean;
shouldAddBottomSafeAreaPadding: boolean;
@@ -61,13 +63,19 @@ type ModalPaddingStylesArgs = {
insets: EdgeInsets;
};
-type AvatarBorderStyleArgs = {
+type AvatarBorderStyleParams = {
isHovered: boolean;
isPressed: boolean;
isInReportAction: boolean;
shouldUseCardBackground: boolean;
};
+type GetBaseAutoCompleteSuggestionContainerStyleParams = {
+ left: number;
+ bottom: number;
+ width: number;
+};
+
const workspaceColorOptions: WorkspaceColorStyle[] = [
{backgroundColor: colors.blue200, fill: colors.blue700},
{backgroundColor: colors.blue400, fill: colors.blue800},
@@ -138,7 +146,7 @@ const avatarSizes: Record = {
[CONST.AVATAR_SIZE.SMALL_NORMAL]: variables.avatarSizeSmallNormal,
};
-const emptyAvatarStyles: Record = {
+const emptyAvatarStyles: Record = {
[CONST.AVATAR_SIZE.SMALL]: styles.emptyAvatarSmall,
[CONST.AVATAR_SIZE.MEDIUM]: styles.emptyAvatarMedium,
[CONST.AVATAR_SIZE.LARGE]: styles.emptyAvatarLarge,
@@ -178,21 +186,21 @@ function getAvatarSize(size: AvatarSizeName): number {
/**
* Return the height of magic code input container
*/
-function getHeightOfMagicCodeInput(): ViewStyle | CSSProperties {
+function getHeightOfMagicCodeInput(): ViewStyle {
return {height: styles.magicCodeInputContainer.minHeight - styles.textInputContainer.borderBottomWidth};
}
/**
* Return the style from an empty avatar size constant
*/
-function getEmptyAvatarStyle(size: EmptyAvatarSizeName): ViewStyle | CSSProperties | undefined {
+function getEmptyAvatarStyle(size: EmptyAvatarSizeName): ViewStyle | undefined {
return emptyAvatarStyles[size];
}
/**
* Return the width style from an avatar size constant
*/
-function getAvatarWidthStyle(size: AvatarSizeName): ViewStyle | CSSProperties {
+function getAvatarWidthStyle(size: AvatarSizeName): ViewStyle {
const avatarSize = getAvatarSize(size);
return {
width: avatarSize,
@@ -202,7 +210,7 @@ function getAvatarWidthStyle(size: AvatarSizeName): ViewStyle | CSSProperties {
/**
* Return the style from an avatar size constant
*/
-function getAvatarStyle(size: AvatarSizeName): ViewStyle | CSSProperties {
+function getAvatarStyle(size: AvatarSizeName): ViewStyle {
const avatarSize = getAvatarSize(size);
return {
height: avatarSize,
@@ -215,7 +223,7 @@ function getAvatarStyle(size: AvatarSizeName): ViewStyle | CSSProperties {
/**
* Get Font size of '+1' text on avatar overlay
*/
-function getAvatarExtraFontSizeStyle(size: AvatarSizeName): TextStyle | CSSProperties {
+function getAvatarExtraFontSizeStyle(size: AvatarSizeName): TextStyle {
return {
fontSize: avatarFontSizes[size],
};
@@ -224,7 +232,7 @@ function getAvatarExtraFontSizeStyle(size: AvatarSizeName): TextStyle | CSSPrope
/**
* Get Bordersize of Avatar based on avatar size
*/
-function getAvatarBorderWidth(size: AvatarSizeName): ViewStyle | CSSProperties {
+function getAvatarBorderWidth(size: AvatarSizeName): ViewStyle {
return {
borderWidth: avatarBorderWidths[size],
};
@@ -233,7 +241,7 @@ function getAvatarBorderWidth(size: AvatarSizeName): ViewStyle | CSSProperties {
/**
* Return the border radius for an avatar
*/
-function getAvatarBorderRadius(size: AvatarSizeName, type: string): ViewStyle | CSSProperties {
+function getAvatarBorderRadius(size: AvatarSizeName, type: string): ViewStyle {
if (type === CONST.ICON_TYPE_WORKSPACE) {
return {borderRadius: avatarBorderSizes[size]};
}
@@ -245,7 +253,7 @@ function getAvatarBorderRadius(size: AvatarSizeName, type: string): ViewStyle |
/**
* Return the border style for an avatar
*/
-function getAvatarBorderStyle(size: AvatarSizeName, type: string): ViewStyle | CSSProperties {
+function getAvatarBorderStyle(size: AvatarSizeName, type: string): ViewStyle {
return {
overflow: 'hidden',
...getAvatarBorderRadius(size, type),
@@ -255,7 +263,7 @@ function getAvatarBorderStyle(size: AvatarSizeName, type: string): ViewStyle | C
/**
* Helper method to return workspace avatar color styles
*/
-function getDefaultWorkspaceAvatarColor(workspaceName: string): ViewStyle | CSSProperties {
+function getDefaultWorkspaceAvatarColor(workspaceName: string): ViewStyle {
const colorHash = UserUtils.hashText(workspaceName.trim(), workspaceColorOptions.length);
return workspaceColorOptions[colorHash];
@@ -282,7 +290,7 @@ function getEReceiptColorStyles(colorCode: EReceiptColorName): EreceiptColorStyl
/**
* Takes safe area insets and returns padding to use for a View
*/
-function getSafeAreaPadding(insets?: EdgeInsets, insetsPercentage: number = variables.safeInsertPercentage): ViewStyle | CSSProperties {
+function getSafeAreaPadding(insets?: EdgeInsets, insetsPercentage: number = variables.safeInsertPercentage): ViewStyle {
return {
paddingTop: insets?.top,
paddingBottom: (insets?.bottom ?? 0) * insetsPercentage,
@@ -294,11 +302,11 @@ function getSafeAreaPadding(insets?: EdgeInsets, insetsPercentage: number = vari
/**
* Takes safe area insets and returns margin to use for a View
*/
-function getSafeAreaMargins(insets?: EdgeInsets): ViewStyle | CSSProperties {
+function getSafeAreaMargins(insets?: EdgeInsets): ViewStyle {
return {marginBottom: (insets?.bottom ?? 0) * variables.safeInsertPercentage};
}
-function getZoomCursorStyle(isZoomed: boolean, isDragging: boolean): ViewStyle | CSSProperties {
+function getZoomCursorStyle(isZoomed: boolean, isDragging: boolean): ViewStyle {
if (!isZoomed) {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -309,6 +317,7 @@ function getZoomCursorStyle(isZoomed: boolean, isDragging: boolean): ViewStyle |
return isDragging ? styles.cursorGrabbing : styles.cursorZoomOut;
}
+// NOTE: asserting some web style properties to a valid type, because it isn't possible to augment them.
function getZoomSizingStyle(
isZoomed: boolean,
imgWidth: number,
@@ -317,28 +326,28 @@ function getZoomSizingStyle(
containerHeight: number,
containerWidth: number,
isLoading: boolean,
-): ViewStyle | CSSProperties | undefined {
+): ViewStyle | undefined {
// Hide image until finished loading to prevent showing preview with wrong dimensions
if (isLoading || imgWidth === 0 || imgHeight === 0) {
return undefined;
}
- const top = `${Math.max((containerHeight - imgHeight) / 2, 0)}px`;
- const left = `${Math.max((containerWidth - imgWidth) / 2, 0)}px`;
+ const top = `${Math.max((containerHeight - imgHeight) / 2, 0)}px` as DimensionValue;
+ const left = `${Math.max((containerWidth - imgWidth) / 2, 0)}px` as DimensionValue;
// Return different size and offset style based on zoomScale and isZoom.
if (isZoomed) {
// When both width and height are smaller than container(modal) size, set the height by multiplying zoomScale if it is zoomed in.
if (zoomScale >= 1) {
return {
- height: `${imgHeight * zoomScale}px`,
- width: `${imgWidth * zoomScale}px`,
+ height: `${imgHeight * zoomScale}px` as DimensionValue,
+ width: `${imgWidth * zoomScale}px` as DimensionValue,
};
}
// If image height and width are bigger than container size, display image with original size because original size is bigger and position absolute.
return {
- height: `${imgHeight}px`,
- width: `${imgWidth}px`,
+ height: `${imgHeight}px` as DimensionValue,
+ width: `${imgWidth}px` as DimensionValue,
top,
left,
};
@@ -347,8 +356,8 @@ function getZoomSizingStyle(
// If image is not zoomed in and image size is smaller than container size, display with original size based on offset and position absolute.
if (zoomScale > 1) {
return {
- height: `${imgHeight}px`,
- width: `${imgWidth}px`,
+ height: `${imgHeight}px` as DimensionValue,
+ width: `${imgWidth}px` as DimensionValue,
top,
left,
};
@@ -356,11 +365,11 @@ function getZoomSizingStyle(
// If image is bigger than container size, display full image in the screen with scaled size (fit by container size) and position absolute.
// top, left offset should be different when displaying long or wide image.
- const scaledTop = `${Math.max((containerHeight - imgHeight * zoomScale) / 2, 0)}px`;
- const scaledLeft = `${Math.max((containerWidth - imgWidth * zoomScale) / 2, 0)}px`;
+ const scaledTop = `${Math.max((containerHeight - imgHeight * zoomScale) / 2, 0)}px` as DimensionValue;
+ const scaledLeft = `${Math.max((containerWidth - imgWidth * zoomScale) / 2, 0)}px` as DimensionValue;
return {
- height: `${imgHeight * zoomScale}px`,
- width: `${imgWidth * zoomScale}px`,
+ height: `${imgHeight * zoomScale}px` as DimensionValue,
+ width: `${imgWidth * zoomScale}px` as DimensionValue,
top: scaledTop,
left: scaledLeft,
};
@@ -369,7 +378,7 @@ function getZoomSizingStyle(
/**
* Returns auto grow text input style
*/
-function getWidthStyle(width: number): ViewStyle | CSSProperties {
+function getWidthStyle(width: number): ViewStyle {
return {
width,
};
@@ -378,7 +387,7 @@ function getWidthStyle(width: number): ViewStyle | CSSProperties {
/**
* Returns auto grow height text input style
*/
-function getAutoGrowHeightInputStyle(textInputHeight: number, maxHeight: number): ViewStyle | CSSProperties {
+function getAutoGrowHeightInputStyle(textInputHeight: number, maxHeight: number): ViewStyle {
if (textInputHeight > maxHeight) {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -402,7 +411,7 @@ function getAutoGrowHeightInputStyle(textInputHeight: number, maxHeight: number)
/**
* Returns a style with backgroundColor and borderColor set to the same color
*/
-function getBackgroundAndBorderStyle(backgroundColor: string): ViewStyle | CSSProperties {
+function getBackgroundAndBorderStyle(backgroundColor: string): ViewStyle {
return {
backgroundColor,
borderColor: backgroundColor,
@@ -412,7 +421,7 @@ function getBackgroundAndBorderStyle(backgroundColor: string): ViewStyle | CSSPr
/**
* Returns a style with the specified backgroundColor
*/
-function getBackgroundColorStyle(backgroundColor: string): ViewStyle | CSSProperties {
+function getBackgroundColorStyle(backgroundColor: string): ViewStyle {
return {
backgroundColor,
};
@@ -421,7 +430,7 @@ function getBackgroundColorStyle(backgroundColor: string): ViewStyle | CSSProper
/**
* Returns a style for text color
*/
-function getTextColorStyle(color: string): TextStyle | CSSProperties {
+function getTextColorStyle(color: string): TextStyle {
return {
color,
};
@@ -430,7 +439,7 @@ function getTextColorStyle(color: string): TextStyle | CSSProperties {
/**
* Returns a style with the specified borderColor
*/
-function getBorderColorStyle(borderColor: string): ViewStyle | CSSProperties {
+function getBorderColorStyle(borderColor: string): ViewStyle {
return {
borderColor,
};
@@ -439,7 +448,7 @@ function getBorderColorStyle(borderColor: string): ViewStyle | CSSProperties {
/**
* Returns the width style for the wordmark logo on the sign in page
*/
-function getSignInWordmarkWidthStyle(environment: string, isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getSignInWordmarkWidthStyle(environment: string, isSmallScreenWidth: boolean): ViewStyle {
if (environment === CONST.ENVIRONMENT.DEV) {
return isSmallScreenWidth ? {width: variables.signInLogoWidthPill} : {width: variables.signInLogoWidthLargeScreenPill};
}
@@ -471,7 +480,7 @@ function hexadecimalToRGBArray(hexadecimal: string): number[] | undefined {
/**
* Returns a background color with opacity style
*/
-function getBackgroundColorWithOpacityStyle(backgroundColor: string, opacity: number): ViewStyle | CSSProperties {
+function getBackgroundColorWithOpacityStyle(backgroundColor: string, opacity: number): ViewStyle {
const result = hexadecimalToRGBArray(backgroundColor);
if (result !== undefined) {
return {
@@ -484,8 +493,8 @@ function getBackgroundColorWithOpacityStyle(backgroundColor: string, opacity: nu
/**
* Generate a style for the background color of the Badge
*/
-function getBadgeColorStyle(success: boolean, error: boolean, isPressed = false, isAdHoc = false): ViewStyle | CSSProperties {
- if (success) {
+function getBadgeColorStyle(isSuccess: boolean, isError: boolean, isPressed = false, isAdHoc = false): ViewStyle {
+ if (isSuccess) {
if (isAdHoc) {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -495,7 +504,7 @@ function getBadgeColorStyle(success: boolean, error: boolean, isPressed = false,
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return isPressed ? styles.badgeSuccessPressed : styles.badgeSuccess;
}
- if (error) {
+ if (isError) {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return isPressed ? styles.badgeDangerPressed : styles.badgeDanger;
@@ -509,7 +518,7 @@ function getBadgeColorStyle(success: boolean, error: boolean, isPressed = false,
* @param buttonState - One of {'default', 'hovered', 'pressed'}
* @param isMenuItem - whether this button is apart of a list
*/
-function getButtonBackgroundColorStyle(buttonState: ButtonStateName = CONST.BUTTON_STATES.DEFAULT, isMenuItem = false): ViewStyle | CSSProperties {
+function getButtonBackgroundColorStyle(buttonState: ButtonStateName = CONST.BUTTON_STATES.DEFAULT, isMenuItem = false): ViewStyle {
switch (buttonState) {
case CONST.BUTTON_STATES.PRESSED:
return {backgroundColor: themeColors.buttonPressedBG};
@@ -552,7 +561,7 @@ function getAnimatedFABStyle(rotate: Animated.Value, backgroundColor: Animated.V
};
}
-function getWidthAndHeightStyle(width: number, height: number | undefined = undefined): ViewStyle | CSSProperties {
+function getWidthAndHeightStyle(width: number, height?: number): ViewStyle {
return {
width,
height: height ?? width,
@@ -573,17 +582,17 @@ function getModalPaddingStyles({
modalContainerStylePaddingTop,
modalContainerStylePaddingBottom,
insets,
-}: ModalPaddingStylesArgs): ViewStyle | CSSProperties {
+}: ModalPaddingStylesParams): ViewStyle {
// use fallback value for safeAreaPaddingBottom to keep padding bottom consistent with padding top.
// More info: issue #17376
- const safeAreaPaddingBottomWithFallback = insets.bottom === 0 ? modalContainerStylePaddingTop || 0 : safeAreaPaddingBottom;
+ const safeAreaPaddingBottomWithFallback = insets.bottom === 0 ? modalContainerStylePaddingTop ?? 0 : safeAreaPaddingBottom;
return {
- marginTop: (modalContainerStyleMarginTop || 0) + (shouldAddTopSafeAreaMargin ? safeAreaPaddingTop : 0),
- marginBottom: (modalContainerStyleMarginBottom || 0) + (shouldAddBottomSafeAreaMargin ? safeAreaPaddingBottomWithFallback : 0),
- paddingTop: shouldAddTopSafeAreaPadding ? (modalContainerStylePaddingTop || 0) + safeAreaPaddingTop : modalContainerStylePaddingTop || 0,
- paddingBottom: shouldAddBottomSafeAreaPadding ? (modalContainerStylePaddingBottom || 0) + safeAreaPaddingBottomWithFallback : modalContainerStylePaddingBottom || 0,
- paddingLeft: safeAreaPaddingLeft || 0,
- paddingRight: safeAreaPaddingRight || 0,
+ marginTop: (modalContainerStyleMarginTop ?? 0) + (shouldAddTopSafeAreaMargin ? safeAreaPaddingTop : 0),
+ marginBottom: (modalContainerStyleMarginBottom ?? 0) + (shouldAddBottomSafeAreaMargin ? safeAreaPaddingBottomWithFallback : 0),
+ paddingTop: shouldAddTopSafeAreaPadding ? (modalContainerStylePaddingTop ?? 0) + safeAreaPaddingTop : modalContainerStylePaddingTop ?? 0,
+ paddingBottom: shouldAddBottomSafeAreaPadding ? (modalContainerStylePaddingBottom ?? 0) + safeAreaPaddingBottomWithFallback : modalContainerStylePaddingBottom ?? 0,
+ paddingLeft: safeAreaPaddingLeft ?? 0,
+ paddingRight: safeAreaPaddingRight ?? 0,
};
}
@@ -601,7 +610,7 @@ function getFontFamilyMonospace({fontStyle, fontWeight}: TextStyle): string {
/**
* Gives the width for Emoji picker Widget
*/
-function getEmojiPickerStyle(isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getEmojiPickerStyle(isSmallScreenWidth: boolean): ViewStyle {
if (isSmallScreenWidth) {
return {
width: CONST.SMALL_EMOJI_PICKER_SIZE.WIDTH,
@@ -616,7 +625,7 @@ function getEmojiPickerStyle(isSmallScreenWidth: boolean): ViewStyle | CSSProper
/**
* Generate the styles for the ReportActionItem wrapper view.
*/
-function getReportActionItemStyle(isHovered = false): ViewStyle | CSSProperties {
+function getReportActionItemStyle(isHovered = false): ViewStyle {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
@@ -634,7 +643,7 @@ function getReportActionItemStyle(isHovered = false): ViewStyle | CSSProperties
/**
* Generate the wrapper styles for the mini ReportActionContextMenu.
*/
-function getMiniReportActionContextMenuWrapperStyle(isReportActionItemGrouped: boolean): ViewStyle | CSSProperties {
+function getMiniReportActionContextMenuWrapperStyle(isReportActionItemGrouped: boolean): ViewStyle {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
@@ -646,7 +655,7 @@ function getMiniReportActionContextMenuWrapperStyle(isReportActionItemGrouped: b
};
}
-function getPaymentMethodMenuWidth(isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getPaymentMethodMenuWidth(isSmallScreenWidth: boolean): ViewStyle {
const margin = 20;
return {width: !isSmallScreenWidth ? variables.sideBarWidth - margin * 2 : undefined};
}
@@ -732,14 +741,14 @@ function getThemeBackgroundColor(bgColor: string = themeColors.appBG): string {
/**
* Parse styleParam and return Styles array
*/
-function parseStyleAsArray(styleParam: ViewStyle | CSSProperties | Array): Array {
+function parseStyleAsArray(styleParam: T | T[]): T[] {
return Array.isArray(styleParam) ? styleParam : [styleParam];
}
/**
* Parse style function and return Styles object
*/
-function parseStyleFromFunction(style: ParsableStyle, state: PressableStateCallbackType): Array {
+function parseStyleFromFunction(style: ParsableStyle, state: PressableStateCallbackType): AllStyles[] {
const functionAppliedStyle = typeof style === 'function' ? style(state) : style;
return parseStyleAsArray(functionAppliedStyle);
}
@@ -747,8 +756,8 @@ function parseStyleFromFunction(style: ParsableStyle, state: PressableStateCallb
/**
* Receives any number of object or array style objects and returns them all as an array
*/
-function combineStyles(...allStyles: Array>) {
- let finalStyles: Array> = [];
+function combineStyles(...allStyles: Array): T[] {
+ let finalStyles: T[] = [];
allStyles.forEach((style) => {
finalStyles = finalStyles.concat(parseStyleAsArray(style));
});
@@ -758,7 +767,7 @@ function combineStyles(...allStyles: Array 0 ? -overlapSize : 0,
zIndex: index + 2,
@@ -853,7 +862,7 @@ function getHorizontalStackedAvatarStyle(index: number, overlapSize: number): Vi
/**
* Get computed avatar styles of '+1' overlay based on size
*/
-function getHorizontalStackedOverlayAvatarStyle(oneAvatarSize: AvatarSize, oneAvatarBorderWidth: number): ViewStyle | CSSProperties {
+function getHorizontalStackedOverlayAvatarStyle(oneAvatarSize: AvatarSize, oneAvatarBorderWidth: number): ViewStyle {
return {
borderWidth: oneAvatarBorderWidth,
borderRadius: oneAvatarSize.width,
@@ -863,7 +872,7 @@ function getHorizontalStackedOverlayAvatarStyle(oneAvatarSize: AvatarSize, oneAv
};
}
-function getErrorPageContainerStyle(safeAreaPaddingBottom = 0): ViewStyle | CSSProperties {
+function getErrorPageContainerStyle(safeAreaPaddingBottom = 0): ViewStyle {
return {
backgroundColor: themeColors.componentBG,
paddingBottom: 40 + safeAreaPaddingBottom,
@@ -873,7 +882,7 @@ function getErrorPageContainerStyle(safeAreaPaddingBottom = 0): ViewStyle | CSSP
/**
* Gets the correct size for the empty state background image based on screen dimensions
*/
-function getReportWelcomeBackgroundImageStyle(isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getReportWelcomeBackgroundImageStyle(isSmallScreenWidth: boolean): ViewStyle {
if (isSmallScreenWidth) {
return {
height: CONST.EMPTY_STATE_BACKGROUND.SMALL_SCREEN.IMAGE_HEIGHT,
@@ -892,7 +901,7 @@ function getReportWelcomeBackgroundImageStyle(isSmallScreenWidth: boolean): View
/**
* Gets the correct top margin size for the chat welcome message based on screen dimensions
*/
-function getReportWelcomeTopMarginStyle(isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getReportWelcomeTopMarginStyle(isSmallScreenWidth: boolean): ViewStyle {
if (isSmallScreenWidth) {
return {
marginTop: CONST.EMPTY_STATE_BACKGROUND.SMALL_SCREEN.VIEW_HEIGHT,
@@ -907,7 +916,7 @@ function getReportWelcomeTopMarginStyle(isSmallScreenWidth: boolean): ViewStyle
/**
* Returns fontSize style
*/
-function getFontSizeStyle(fontSize: number): TextStyle | CSSProperties {
+function getFontSizeStyle(fontSize: number): TextStyle {
return {
fontSize,
};
@@ -916,7 +925,7 @@ function getFontSizeStyle(fontSize: number): TextStyle | CSSProperties {
/**
* Returns lineHeight style
*/
-function getLineHeightStyle(lineHeight: number): TextStyle | CSSProperties {
+function getLineHeightStyle(lineHeight: number): TextStyle {
return {
lineHeight,
};
@@ -925,7 +934,7 @@ function getLineHeightStyle(lineHeight: number): TextStyle | CSSProperties {
/**
* Gets the correct size for the empty state container based on screen dimensions
*/
-function getReportWelcomeContainerStyle(isSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getReportWelcomeContainerStyle(isSmallScreenWidth: boolean): ViewStyle {
if (isSmallScreenWidth) {
return {
minHeight: CONST.EMPTY_STATE_BACKGROUND.SMALL_SCREEN.CONTAINER_MINHEIGHT,
@@ -944,12 +953,12 @@ function getReportWelcomeContainerStyle(isSmallScreenWidth: boolean): ViewStyle
/**
* Gets styles for AutoCompleteSuggestion row
*/
-function getAutoCompleteSuggestionItemStyle(highlightedEmojiIndex: number, rowHeight: number, hovered: boolean, currentEmojiIndex: number): Array {
+function getAutoCompleteSuggestionItemStyle(highlightedEmojiIndex: number, rowHeight: number, isHovered: boolean, currentEmojiIndex: number): ViewStyle[] {
let backgroundColor;
if (currentEmojiIndex === highlightedEmojiIndex) {
backgroundColor = themeColors.activeComponentBG;
- } else if (hovered) {
+ } else if (isHovered) {
backgroundColor = themeColors.hoverComponentBG;
}
@@ -969,14 +978,19 @@ function getAutoCompleteSuggestionItemStyle(highlightedEmojiIndex: number, rowHe
/**
* Gets the correct position for the base auto complete suggestion container
*/
-function getBaseAutoCompleteSuggestionContainerStyle({left, bottom, width}: {left: number; bottom: number; width: number}): ViewStyle | CSSProperties {
- return {position: 'fixed', bottom, left, width};
+function getBaseAutoCompleteSuggestionContainerStyle({left, bottom, width}: GetBaseAutoCompleteSuggestionContainerStyleParams): ViewStyle {
+ return {
+ ...positioning.pFixed,
+ bottom,
+ left,
+ width,
+ };
}
/**
* Gets the correct position for auto complete suggestion container
*/
-function getAutoCompleteSuggestionContainerStyle(itemsHeight: number): ViewStyle | CSSProperties {
+function getAutoCompleteSuggestionContainerStyle(itemsHeight: number): ViewStyle {
'worklet';
const borderWidth = 2;
@@ -994,11 +1008,11 @@ function getAutoCompleteSuggestionContainerStyle(itemsHeight: number): ViewStyle
/**
* Select the correct color for text.
*/
-function getColoredBackgroundStyle(isColored: boolean): ViewStyle | CSSProperties {
+function getColoredBackgroundStyle(isColored: boolean): ViewStyle {
return {backgroundColor: isColored ? themeColors.link : undefined};
}
-function getEmojiReactionBubbleStyle(isHovered: boolean, hasUserReacted: boolean, isContextMenu = false): ViewStyle | CSSProperties {
+function getEmojiReactionBubbleStyle(isHovered: boolean, hasUserReacted: boolean, isContextMenu = false): ViewStyle {
let backgroundColor = themeColors.border;
if (isHovered) {
@@ -1024,7 +1038,7 @@ function getEmojiReactionBubbleStyle(isHovered: boolean, hasUserReacted: boolean
};
}
-function getEmojiReactionBubbleTextStyle(isContextMenu = false): TextStyle | CSSProperties {
+function getEmojiReactionBubbleTextStyle(isContextMenu = false): TextStyle {
if (isContextMenu) {
return {
fontSize: 17,
@@ -1038,7 +1052,7 @@ function getEmojiReactionBubbleTextStyle(isContextMenu = false): TextStyle | CSS
};
}
-function getEmojiReactionCounterTextStyle(hasUserReacted: boolean): TextStyle | CSSProperties {
+function getEmojiReactionCounterTextStyle(hasUserReacted: boolean): TextStyle {
if (hasUserReacted) {
return {color: themeColors.reactionActiveText};
}
@@ -1051,7 +1065,7 @@ function getEmojiReactionCounterTextStyle(hasUserReacted: boolean): TextStyle |
*
* @param direction - The direction of the rotation (CONST.DIRECTION.LEFT or CONST.DIRECTION.RIGHT).
*/
-function getDirectionStyle(direction: string): ViewStyle | CSSProperties {
+function getDirectionStyle(direction: ValueOf): ViewStyle {
if (direction === CONST.DIRECTION.LEFT) {
return {transform: [{rotate: '180deg'}]};
}
@@ -1062,11 +1076,11 @@ function getDirectionStyle(direction: string): ViewStyle | CSSProperties {
/**
* Returns a style object with display flex or none basing on the condition value.
*/
-function displayIfTrue(condition: boolean): ViewStyle | CSSProperties {
+function displayIfTrue(condition: boolean): ViewStyle {
return {display: condition ? 'flex' : 'none'};
}
-function getGoogleListViewStyle(shouldDisplayBorder: boolean): ViewStyle | CSSProperties {
+function getGoogleListViewStyle(shouldDisplayBorder: boolean): ViewStyle {
if (shouldDisplayBorder) {
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -1086,7 +1100,7 @@ function getGoogleListViewStyle(shouldDisplayBorder: boolean): ViewStyle | CSSPr
/**
* Gets the correct height for emoji picker list based on screen dimensions
*/
-function getEmojiPickerListHeight(hasAdditionalSpace: boolean, windowHeight: number): ViewStyle | CSSProperties {
+function getEmojiPickerListHeight(hasAdditionalSpace: boolean, windowHeight: number): ViewStyle {
const style = {
...spacing.ph4,
height: hasAdditionalSpace ? CONST.NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT + CONST.CATEGORY_SHORTCUT_BAR_HEIGHT : CONST.NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT,
@@ -1106,7 +1120,7 @@ function getEmojiPickerListHeight(hasAdditionalSpace: boolean, windowHeight: num
/**
* Returns style object for the user mention component based on whether the mention is ours or not.
*/
-function getMentionStyle(isOurMention: boolean): ViewStyle | CSSProperties {
+function getMentionStyle(isOurMention: boolean): ViewStyle {
const backgroundColor = isOurMention ? themeColors.ourMentionBG : themeColors.mentionBG;
return {
backgroundColor,
@@ -1125,7 +1139,7 @@ function getMentionTextColor(isOurMention: boolean): string {
/**
* Returns padding vertical based on number of lines
*/
-function getComposeTextAreaPadding(numberOfLines: number, isComposerFullSize: boolean): ViewStyle | CSSProperties {
+function getComposeTextAreaPadding(numberOfLines: number, isComposerFullSize: boolean): ViewStyle {
let paddingValue = 5;
// Issue #26222: If isComposerFullSize paddingValue will always be 5 to prevent padding jumps when adding multiple lines.
if (!isComposerFullSize) {
@@ -1146,14 +1160,14 @@ function getComposeTextAreaPadding(numberOfLines: number, isComposerFullSize: bo
/**
* Returns style object for the mobile on WEB
*/
-function getOuterModalStyle(windowHeight: number, viewportOffsetTop: number): ViewStyle | CSSProperties {
+function getOuterModalStyle(windowHeight: number, viewportOffsetTop: number): ViewStyle {
return Browser.isMobile() ? {maxHeight: windowHeight, marginTop: viewportOffsetTop} : {};
}
/**
* Returns style object for flexWrap depending on the screen size
*/
-function getWrappingStyle(isExtraSmallScreenWidth: boolean): ViewStyle | CSSProperties {
+function getWrappingStyle(isExtraSmallScreenWidth: boolean): ViewStyle {
return {
flexWrap: isExtraSmallScreenWidth ? 'wrap' : 'nowrap',
};
@@ -1162,7 +1176,7 @@ function getWrappingStyle(isExtraSmallScreenWidth: boolean): ViewStyle | CSSProp
/**
* Returns the text container styles for menu items depending on if the menu item container a small avatar
*/
-function getMenuItemTextContainerStyle(isSmallAvatarSubscriptMenu: boolean): ViewStyle | CSSProperties {
+function getMenuItemTextContainerStyle(isSmallAvatarSubscriptMenu: boolean): ViewStyle {
return {
minHeight: isSmallAvatarSubscriptMenu ? variables.avatarSizeSubscript : variables.componentSizeNormal,
};
@@ -1171,7 +1185,7 @@ function getMenuItemTextContainerStyle(isSmallAvatarSubscriptMenu: boolean): Vie
/**
* Returns link styles based on whether the link is disabled or not
*/
-function getDisabledLinkStyles(isDisabled = false): ViewStyle | CSSProperties {
+function getDisabledLinkStyles(isDisabled = false): ViewStyle {
const disabledLinkStyles = {
color: themeColors.textSupporting,
...cursor.cursorDisabled,
@@ -1195,7 +1209,7 @@ function getColorStyle(color: string): ViewStyle | CSSProperties {
/**
* Returns the checkbox pressable style
*/
-function getCheckboxPressableStyle(borderRadius = 6): ViewStyle | CSSProperties {
+function getCheckboxPressableStyle(borderRadius = 6): ViewStyle {
return {
padding: 2,
justifyContent: 'center',
@@ -1208,7 +1222,7 @@ function getCheckboxPressableStyle(borderRadius = 6): ViewStyle | CSSProperties
/**
* Returns the checkbox container style
*/
-function getCheckboxContainerStyle(size: number, borderRadius = 4): ViewStyle | CSSProperties {
+function getCheckboxContainerStyle(size: number, borderRadius = 4): ViewStyle {
return {
backgroundColor: themeColors.componentBG,
height: size,
@@ -1225,7 +1239,7 @@ function getCheckboxContainerStyle(size: number, borderRadius = 4): ViewStyle |
/**
* Returns style object for the dropbutton height
*/
-function getDropDownButtonHeight(buttonSize: ButtonSizeValue): ViewStyle | CSSProperties {
+function getDropDownButtonHeight(buttonSize: ButtonSizeValue): ViewStyle {
if (buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE) {
return {
height: variables.componentSizeLarge,
@@ -1239,7 +1253,7 @@ function getDropDownButtonHeight(buttonSize: ButtonSizeValue): ViewStyle | CSSPr
/**
* Returns fitting fontSize and lineHeight values in order to prevent large amounts from being cut off on small screen widths.
*/
-function getAmountFontSizeAndLineHeight(baseFontSize: number, baseLineHeight: number, isSmallScreenWidth: boolean, windowWidth: number): ViewStyle | CSSProperties {
+function getAmountFontSizeAndLineHeight(baseFontSize: number, baseLineHeight: number, isSmallScreenWidth: boolean, windowWidth: number): TextStyle {
let toSubtract = 0;
if (isSmallScreenWidth) {
@@ -1299,40 +1313,25 @@ function getTransparentColor(color: string) {
}
export {
+ combineStyles,
+ displayIfTrue,
+ getAmountFontSizeAndLineHeight,
+ getAnimatedFABStyle,
+ getAutoCompleteSuggestionContainerStyle,
+ getAutoCompleteSuggestionItemStyle,
+ getAutoGrowHeightInputStyle,
+ getAvatarBorderRadius,
+ getAvatarBorderStyle,
+ getAvatarBorderWidth,
+ getAvatarExtraFontSizeStyle,
getAvatarSize,
- getAvatarWidthStyle,
getAvatarStyle,
- getAvatarExtraFontSizeStyle,
- getAvatarBorderWidth,
- getAvatarBorderStyle,
- getEmptyAvatarStyle,
- getErrorPageContainerStyle,
- getSafeAreaPadding,
- getSafeAreaMargins,
- getZoomCursorStyle,
- getZoomSizingStyle,
- getWidthStyle,
- getAutoGrowHeightInputStyle,
+ getAvatarWidthStyle,
getBackgroundAndBorderStyle,
getBackgroundColorStyle,
- getTextColorStyle,
- getBorderColorStyle,
getBackgroundColorWithOpacityStyle,
getBadgeColorStyle,
getButtonBackgroundColorStyle,
- getIconFillColor,
- getAnimatedFABStyle,
- getWidthAndHeightStyle,
- getModalPaddingStyles,
- getFontFamilyMonospace,
- getEmojiPickerStyle,
- getReportActionItemStyle,
- getMiniReportActionContextMenuWrapperStyle,
- getPaymentMethodMenuWidth,
- getThemeBackgroundColor,
- parseStyleAsArray,
- parseStyleFromFunction,
- combineStyles,
getPaddingLeft,
hasSafeAreas,
getHeight,
@@ -1348,36 +1347,51 @@ export {
getReportWelcomeTopMarginStyle,
getReportWelcomeContainerStyle,
getBaseAutoCompleteSuggestionContainerStyle,
- getAutoCompleteSuggestionItemStyle,
- getAutoCompleteSuggestionContainerStyle,
+ getBorderColorStyle,
+ getCheckboxContainerStyle,
+ getCheckboxPressableStyle,
getColoredBackgroundStyle,
+ getComposeTextAreaPadding,
getColorStyle,
getDefaultWorkspaceAvatarColor,
- getAvatarBorderRadius,
+ getDirectionStyle,
+ getDisabledLinkStyles,
+ getDropDownButtonHeight,
+ getEmojiPickerListHeight,
+ getEmojiPickerStyle,
getEmojiReactionBubbleStyle,
getEmojiReactionBubbleTextStyle,
getEmojiReactionCounterTextStyle,
- getDirectionStyle,
- displayIfTrue,
+ getEmptyAvatarStyle,
+ getErrorPageContainerStyle,
+ getFontFamilyMonospace,
getFontSizeStyle,
- getLineHeightStyle,
- getSignInWordmarkWidthStyle,
getGoogleListViewStyle,
- getEmojiPickerListHeight,
+ getHeightOfMagicCodeInput,
+ getIconFillColor,
+ getLineHeightStyle,
getMentionStyle,
getMentionTextColor,
- getComposeTextAreaPadding,
- getHeightOfMagicCodeInput,
+ getMenuItemTextContainerStyle,
+ getMiniReportActionContextMenuWrapperStyle,
+ getModalPaddingStyles,
getOuterModalStyle,
+ getPaymentMethodMenuWidth,
+ getReportActionItemStyle,
+ getSafeAreaMargins,
+ getSafeAreaPadding,
+ getSignInWordmarkWidthStyle,
+ getTextColorStyle,
+ getThemeBackgroundColor,
+ getTransparentColor,
+ getWidthAndHeightStyle,
+ getWidthStyle,
getWrappingStyle,
- getMenuItemTextContainerStyle,
- getDisabledLinkStyles,
- getCheckboxPressableStyle,
- getCheckboxContainerStyle,
- getDropDownButtonHeight,
- getAmountFontSizeAndLineHeight,
+ getZoomCursorStyle,
+ getZoomSizingStyle,
+ parseStyleAsArray,
+ parseStyleFromFunction,
getContainerStyles,
- getTransparentColor,
getEReceiptColorStyles,
getEReceiptColorCode,
};
diff --git a/src/styles/ThemeStylesProvider.tsx b/src/styles/ThemeStylesProvider.tsx
index d0db784ca8ca..4e6f91baf34a 100644
--- a/src/styles/ThemeStylesProvider.tsx
+++ b/src/styles/ThemeStylesProvider.tsx
@@ -5,7 +5,7 @@ import ThemeStylesContext from './ThemeStylesContext';
// TODO: Rename this to "styles" once the app is migrated to theme switching hooks and HOCs
import {stylesGenerator as stylesUntyped} from './styles';
-const styles = stylesUntyped as (theme: Record) => Record;
+const styles = stylesUntyped;
type ThemeStylesProviderProps = {
children: React.ReactNode;
diff --git a/src/styles/addOutlineWidth/index.ts b/src/styles/addOutlineWidth/index.ts
index 257a3de2b6cd..6fe2ecf85978 100644
--- a/src/styles/addOutlineWidth/index.ts
+++ b/src/styles/addOutlineWidth/index.ts
@@ -9,11 +9,11 @@ import AddOutlineWidth from './types';
/**
* Adds the addOutlineWidth property to an object to be used when styling
*/
-const addOutlineWidth: AddOutlineWidth = (obj, val, error = false) => ({
+const addOutlineWidth: AddOutlineWidth = (obj, val, hasError = false) => ({
...obj,
outlineWidth: val,
outlineStyle: val ? 'auto' : 'none',
- boxShadow: val !== 0 ? `0px 0px 0px ${val}px ${error ? themeDefault.danger : themeDefault.borderFocus}` : 'none',
+ boxShadow: val !== 0 ? `0px 0px 0px ${val}px ${hasError ? themeDefault.danger : themeDefault.borderFocus}` : 'none',
});
export default addOutlineWidth;
diff --git a/src/styles/addOutlineWidth/types.ts b/src/styles/addOutlineWidth/types.ts
index 422d135ef759..7a3a86506959 100644
--- a/src/styles/addOutlineWidth/types.ts
+++ b/src/styles/addOutlineWidth/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {TextStyle} from 'react-native';
-type AddOutlineWidth = (obj: TextStyle | CSSProperties, val?: number, error?: boolean) => TextStyle | CSSProperties;
+type AddOutlineWidth = (obj: TextStyle, val?: number, hasError?: boolean) => TextStyle;
export default AddOutlineWidth;
diff --git a/src/styles/cardStyles/index.ts b/src/styles/cardStyles/index.ts
index 823081b62904..1f28ca4f4b78 100644
--- a/src/styles/cardStyles/index.ts
+++ b/src/styles/cardStyles/index.ts
@@ -1,10 +1,11 @@
+import positioning from '../utilities/positioning';
import GetCardStyles from './types';
/**
* Get card style for cardStyleInterpolator
*/
const getCardStyles: GetCardStyles = (screenWidth) => ({
- position: 'fixed',
+ ...positioning.pFixed,
width: screenWidth,
height: '100%',
});
diff --git a/src/styles/cardStyles/types.ts b/src/styles/cardStyles/types.ts
index e1598b7696ff..134b93eae32f 100644
--- a/src/styles/cardStyles/types.ts
+++ b/src/styles/cardStyles/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
-type GetCardStyles = (screenWidth: number) => Partial>;
+type GetCardStyles = (screenWidth: number) => ViewStyle;
export default GetCardStyles;
diff --git a/src/styles/codeStyles/types.ts b/src/styles/codeStyles/types.ts
index 7397b3c6543c..25e35f492089 100644
--- a/src/styles/codeStyles/types.ts
+++ b/src/styles/codeStyles/types.ts
@@ -1,8 +1,7 @@
-import {CSSProperties} from 'react';
import {TextStyle, ViewStyle} from 'react-native';
-type CodeWordWrapperStyles = ViewStyle | CSSProperties;
-type CodeWordStyles = TextStyle | CSSProperties;
-type CodeTextStyles = TextStyle | CSSProperties;
+type CodeWordWrapperStyles = ViewStyle;
+type CodeWordStyles = TextStyle;
+type CodeTextStyles = TextStyle;
-export type {CodeWordWrapperStyles, CodeWordStyles, CodeTextStyles};
+export type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles};
diff --git a/src/styles/containerComposeStyles/index.native.ts b/src/styles/containerComposeStyles/index.native.ts
index 6b6bcf71cfcf..ea525dc652cf 100644
--- a/src/styles/containerComposeStyles/index.native.ts
+++ b/src/styles/containerComposeStyles/index.native.ts
@@ -1,6 +1,6 @@
-import {StyleProp, ViewStyle} from 'react-native';
import styles from '../styles';
+import ContainerComposeStyles from './types';
-const containerComposeStyles: StyleProp = [styles.textInputComposeSpacing];
+const containerComposeStyles: ContainerComposeStyles = [styles.textInputComposeSpacing];
export default containerComposeStyles;
diff --git a/src/styles/containerComposeStyles/index.ts b/src/styles/containerComposeStyles/index.ts
index 6968e23a507e..fbbf35a20818 100644
--- a/src/styles/containerComposeStyles/index.ts
+++ b/src/styles/containerComposeStyles/index.ts
@@ -1,7 +1,7 @@
-import {StyleProp, ViewStyle} from 'react-native';
import styles from '../styles';
+import ContainerComposeStyles from './types';
// We need to set paddingVertical = 0 on web to avoid displaying a normal pointer on some parts of compose box when not in focus
-const containerComposeStyles: StyleProp = [styles.textInputComposeSpacing, {paddingVertical: 0}];
+const containerComposeStyles: ContainerComposeStyles = [styles.textInputComposeSpacing, {paddingVertical: 0}];
export default containerComposeStyles;
diff --git a/src/styles/containerComposeStyles/types.ts b/src/styles/containerComposeStyles/types.ts
new file mode 100644
index 000000000000..278039691b8a
--- /dev/null
+++ b/src/styles/containerComposeStyles/types.ts
@@ -0,0 +1,5 @@
+import {ViewStyle} from 'react-native';
+
+type ContainerComposeStyles = ViewStyle[];
+
+export default ContainerComposeStyles;
diff --git a/src/styles/editedLabelStyles/index.ts b/src/styles/editedLabelStyles/index.ts
index 6e6164810b52..5764735d0dea 100644
--- a/src/styles/editedLabelStyles/index.ts
+++ b/src/styles/editedLabelStyles/index.ts
@@ -1,7 +1,10 @@
-import EditedLabelStyles from './types';
import display from '../utilities/display';
import flex from '../utilities/flex';
+import EditedLabelStyles from './types';
-const editedLabelStyles: EditedLabelStyles = {...display.dInlineFlex, ...flex.alignItemsBaseline};
+const editedLabelStyles: EditedLabelStyles = {
+ ...display.dInlineFlex,
+ ...flex.alignItemsBaseline,
+};
export default editedLabelStyles;
diff --git a/src/styles/editedLabelStyles/types.ts b/src/styles/editedLabelStyles/types.ts
index 8d96c9216ed2..20bcc8c55f15 100644
--- a/src/styles/editedLabelStyles/types.ts
+++ b/src/styles/editedLabelStyles/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {TextStyle} from 'react-native';
-type EditedLabelStyles = CSSProperties | TextStyle;
+type EditedLabelStyles = TextStyle;
export default EditedLabelStyles;
diff --git a/src/styles/fontFamily/bold/index.android.js b/src/styles/fontFamily/bold/index.android.js
deleted file mode 100644
index 73ba56dc4262..000000000000
--- a/src/styles/fontFamily/bold/index.android.js
+++ /dev/null
@@ -1,4 +0,0 @@
-const singleBold = 'ExpensifyNeue-Bold';
-const multiBold = 'ExpensifyNeue-Bold';
-
-export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/index.android.ts b/src/styles/fontFamily/bold/index.android.ts
new file mode 100644
index 000000000000..828b9425e8d4
--- /dev/null
+++ b/src/styles/fontFamily/bold/index.android.ts
@@ -0,0 +1,6 @@
+import FontFamilyBoldStyles from './types';
+
+const singleBold: FontFamilyBoldStyles = 'ExpensifyNeue-Bold';
+const multiBold: FontFamilyBoldStyles = 'ExpensifyNeue-Bold';
+
+export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/index.ios.js b/src/styles/fontFamily/bold/index.ios.js
deleted file mode 100644
index a0523831a058..000000000000
--- a/src/styles/fontFamily/bold/index.ios.js
+++ /dev/null
@@ -1,4 +0,0 @@
-const singleBold = 'ExpensifyNeue-Regular';
-const multiBold = 'ExpensifyNeue-Regular';
-
-export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/index.ios.ts b/src/styles/fontFamily/bold/index.ios.ts
new file mode 100644
index 000000000000..31b7e3d82c05
--- /dev/null
+++ b/src/styles/fontFamily/bold/index.ios.ts
@@ -0,0 +1,6 @@
+import FontFamilyBoldStyles from './types';
+
+const singleBold: FontFamilyBoldStyles = 'ExpensifyNeue-Regular';
+const multiBold: FontFamilyBoldStyles = 'ExpensifyNeue-Regular';
+
+export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/index.js b/src/styles/fontFamily/bold/index.js
deleted file mode 100644
index 401a808d29d6..000000000000
--- a/src/styles/fontFamily/bold/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-const singleBold = 'ExpensifyNeue-Regular';
-const multiBold = 'ExpensifyNeue-Regular, Segoe UI Emoji, Noto Color Emoji';
-
-export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/index.ts b/src/styles/fontFamily/bold/index.ts
new file mode 100644
index 000000000000..c416bff3aadc
--- /dev/null
+++ b/src/styles/fontFamily/bold/index.ts
@@ -0,0 +1,6 @@
+import FontFamilyBoldStyles from './types';
+
+const singleBold: FontFamilyBoldStyles = 'ExpensifyNeue-Regular';
+const multiBold: FontFamilyBoldStyles = 'ExpensifyNeue-Regular, Segoe UI Emoji, Noto Color Emoji';
+
+export {singleBold, multiBold};
diff --git a/src/styles/fontFamily/bold/types.ts b/src/styles/fontFamily/bold/types.ts
new file mode 100644
index 000000000000..258b23de94a2
--- /dev/null
+++ b/src/styles/fontFamily/bold/types.ts
@@ -0,0 +1,5 @@
+import {TextStyle} from 'react-native';
+
+type FontFamilyBoldStyles = NonNullable;
+
+export default FontFamilyBoldStyles;
diff --git a/src/styles/fontFamily/types.ts b/src/styles/fontFamily/types.ts
index 4c9a121e80d7..c688f40927be 100644
--- a/src/styles/fontFamily/types.ts
+++ b/src/styles/fontFamily/types.ts
@@ -1,3 +1,5 @@
+import {TextStyle} from 'react-native';
+
type FontFamilyKeys =
| 'EXP_NEUE_ITALIC'
| 'EXP_NEUE_BOLD'
@@ -10,6 +12,6 @@ type FontFamilyKeys =
| 'MONOSPACE_BOLD'
| 'MONOSPACE_BOLD_ITALIC';
-type FontFamilyStyles = Record;
+type FontFamilyStyles = Record>;
export default FontFamilyStyles;
diff --git a/src/styles/fontWeight/bold/types.ts b/src/styles/fontWeight/bold/types.ts
index 3c9930a63d87..00e72d0e879c 100644
--- a/src/styles/fontWeight/bold/types.ts
+++ b/src/styles/fontWeight/bold/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {TextStyle} from 'react-native';
-type FontWeightBoldStyles = (TextStyle | CSSProperties)['fontWeight'];
+type FontWeightBoldStyles = NonNullable;
export default FontWeightBoldStyles;
diff --git a/src/styles/getModalStyles.ts b/src/styles/getModalStyles.ts
index 32e6cf6f98e7..d52d29568c2d 100644
--- a/src/styles/getModalStyles.ts
+++ b/src/styles/getModalStyles.ts
@@ -1,16 +1,17 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
-import {ValueOf} from 'type-fest';
import {ModalProps} from 'react-native-modal';
+import {ValueOf} from 'type-fest';
import CONST from '../CONST';
-import variables from './variables';
-import themeColors from './themes/default';
import styles from './styles';
+import themeColors from './themes/default';
+import variables from './variables';
function getCenteredModalStyles(windowWidth: number, isSmallScreenWidth: boolean, isFullScreenWhenSmall = false): ViewStyle {
+ const modalStyles = styles.centeredModalStyles(isSmallScreenWidth, isFullScreenWhenSmall);
+
return {
- borderWidth: styles.centeredModalStyles(isSmallScreenWidth, isFullScreenWhenSmall).borderWidth,
- width: isSmallScreenWidth ? '100%' : windowWidth - styles.centeredModalStyles(isSmallScreenWidth, isFullScreenWhenSmall).marginHorizontal * 2,
+ borderWidth: modalStyles.borderWidth,
+ width: isSmallScreenWidth ? '100%' : windowWidth - modalStyles.marginHorizontal * 2,
};
}
@@ -26,7 +27,7 @@ type WindowDimensions = {
type GetModalStyles = {
modalStyle: ViewStyle;
- modalContainerStyle: ViewStyle | Pick;
+ modalContainerStyle: ViewStyle;
swipeDirection: ModalProps['swipeDirection'];
animationIn: ModalProps['animationIn'];
animationOut: ModalProps['animationOut'];
diff --git a/src/styles/getNavigationModalCardStyles/index.desktop.js b/src/styles/getNavigationModalCardStyles/index.desktop.ts
similarity index 57%
rename from src/styles/getNavigationModalCardStyles/index.desktop.js
rename to src/styles/getNavigationModalCardStyles/index.desktop.ts
index 54c9790253d6..75b5636f9bd8 100644
--- a/src/styles/getNavigationModalCardStyles/index.desktop.js
+++ b/src/styles/getNavigationModalCardStyles/index.desktop.ts
@@ -1,4 +1,7 @@
-export default () => ({
+import positioning from '../utilities/positioning';
+import GetNavigationModalCardStyles from './types';
+
+const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
// position: fixed is set instead of position absolute to workaround Safari known issues of updating heights in DOM.
// Safari issues:
// https://github.com/Expensify/App/issues/12005
@@ -6,5 +9,8 @@ export default () => ({
// https://github.com/Expensify/App/issues/20709
width: '100%',
height: '100%',
- position: 'fixed',
+
+ ...positioning.pFixed,
});
+
+export default getNavigationModalCardStyles;
diff --git a/src/styles/getNavigationModalCardStyles/index.ts b/src/styles/getNavigationModalCardStyles/index.ts
index 8e2bffc1ecfc..d3cf49c6c89c 100644
--- a/src/styles/getNavigationModalCardStyles/index.ts
+++ b/src/styles/getNavigationModalCardStyles/index.ts
@@ -1,3 +1,7 @@
-export default () => ({
+import GetNavigationModalCardStyles from './types';
+
+const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
height: '100%',
});
+
+export default getNavigationModalCardStyles;
diff --git a/src/styles/getNavigationModalCardStyles/index.website.ts b/src/styles/getNavigationModalCardStyles/index.website.ts
index 9879e4c1567b..75b5636f9bd8 100644
--- a/src/styles/getNavigationModalCardStyles/index.website.ts
+++ b/src/styles/getNavigationModalCardStyles/index.website.ts
@@ -1,3 +1,4 @@
+import positioning from '../utilities/positioning';
import GetNavigationModalCardStyles from './types';
const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
@@ -8,7 +9,8 @@ const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
// https://github.com/Expensify/App/issues/20709
width: '100%',
height: '100%',
- position: 'fixed',
+
+ ...positioning.pFixed,
});
export default getNavigationModalCardStyles;
diff --git a/src/styles/getNavigationModalCardStyles/types.ts b/src/styles/getNavigationModalCardStyles/types.ts
index 504b659c87b7..877981dd4dd2 100644
--- a/src/styles/getNavigationModalCardStyles/types.ts
+++ b/src/styles/getNavigationModalCardStyles/types.ts
@@ -1,9 +1,7 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
-import {Merge} from 'type-fest';
type GetNavigationModalCardStylesParams = {isSmallScreenWidth: number};
-type GetNavigationModalCardStyles = (params: GetNavigationModalCardStylesParams) => Merge>;
+type GetNavigationModalCardStyles = (params: GetNavigationModalCardStylesParams) => ViewStyle;
export default GetNavigationModalCardStyles;
diff --git a/src/styles/getReportActionContextMenuStyles.ts b/src/styles/getReportActionContextMenuStyles.ts
index 9c0e159eb5fe..cd3843169a43 100644
--- a/src/styles/getReportActionContextMenuStyles.ts
+++ b/src/styles/getReportActionContextMenuStyles.ts
@@ -1,16 +1,13 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
import styles from './styles';
-import variables from './variables';
import themeColors from './themes/default';
+import variables from './variables';
-type StylesArray = Array;
-
-const defaultWrapperStyle: ViewStyle | CSSProperties = {
+const defaultWrapperStyle: ViewStyle = {
backgroundColor: themeColors.componentBG,
};
-const miniWrapperStyle: StylesArray = [
+const miniWrapperStyle: ViewStyle[] = [
styles.flexRow,
defaultWrapperStyle,
{
@@ -18,11 +15,12 @@ const miniWrapperStyle: StylesArray = [
borderWidth: 1,
borderColor: themeColors.border,
// In Safari, when welcome messages use a code block (triple backticks), they would overlap the context menu below when there is no scrollbar without the transform style.
- transform: 'translateZ(0)',
+ // NOTE: asserting "transform" to a valid type, because it isn't possible to augment "transform".
+ transform: 'translateZ(0)' as unknown as ViewStyle['transform'],
},
];
-const bigWrapperStyle: StylesArray = [styles.flexColumn, defaultWrapperStyle];
+const bigWrapperStyle: ViewStyle[] = [styles.flexColumn, defaultWrapperStyle];
/**
* Generate the wrapper styles for the ReportActionContextMenu.
@@ -30,7 +28,7 @@ const bigWrapperStyle: StylesArray = [styles.flexColumn, defaultWrapperStyle];
* @param isMini
* @param isSmallScreenWidth
*/
-function getReportActionContextMenuStyles(isMini: boolean, isSmallScreenWidth: boolean): StylesArray {
+function getReportActionContextMenuStyles(isMini: boolean, isSmallScreenWidth: boolean): ViewStyle[] {
if (isMini) {
return miniWrapperStyle;
}
diff --git a/src/styles/getTooltipStyles.ts b/src/styles/getTooltipStyles.ts
index be76002bd216..2613cb791688 100644
--- a/src/styles/getTooltipStyles.ts
+++ b/src/styles/getTooltipStyles.ts
@@ -1,11 +1,11 @@
-import {CSSProperties} from 'react';
import {TextStyle, View, ViewStyle} from 'react-native';
-import spacing from './utilities/spacing';
+import fontFamily from './fontFamily';
+import roundToNearestMultipleOfFour from './roundToNearestMultipleOfFour';
import styles from './styles';
import themeColors from './themes/default';
-import fontFamily from './fontFamily';
+import positioning from './utilities/positioning';
+import spacing from './utilities/spacing';
import variables from './variables';
-import roundToNearestMultipleOfFour from './roundToNearestMultipleOfFour';
/** This defines the proximity with the edge of the window in which tooltips should not be displayed.
* If a tooltip is too close to the edge of the screen, we'll shift it towards the center. */
@@ -95,9 +95,9 @@ function isOverlappingAtTop(tooltip: View | HTMLDivElement, xOffset: number, yOf
type TooltipStyles = {
animationStyle: ViewStyle;
- rootWrapperStyle: ViewStyle | CSSProperties;
+ rootWrapperStyle: ViewStyle;
textStyle: TextStyle;
- pointerWrapperStyle: ViewStyle | CSSProperties;
+ pointerWrapperStyle: ViewStyle;
pointerStyle: ViewStyle;
};
@@ -237,7 +237,7 @@ export default function getTooltipStyles(
transform: [{scale}],
},
rootWrapperStyle: {
- position: 'fixed',
+ ...positioning.pFixed,
backgroundColor: themeColors.heading,
borderRadius: variables.componentBorderRadiusSmall,
...tooltipVerticalPadding,
@@ -260,7 +260,7 @@ export default function getTooltipStyles(
textAlign: 'center',
},
pointerWrapperStyle: {
- position: 'fixed',
+ ...positioning.pFixed,
top: pointerWrapperTop,
left: pointerWrapperLeft,
},
diff --git a/src/styles/italic/types.ts b/src/styles/italic/types.ts
index 61e0328e52b6..e9feedbdfac5 100644
--- a/src/styles/italic/types.ts
+++ b/src/styles/italic/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {TextStyle} from 'react-native';
-type ItalicStyles = (TextStyle | CSSProperties)['fontStyle'];
+type ItalicStyles = NonNullable;
export default ItalicStyles;
diff --git a/src/styles/optionAlternateTextPlatformStyles/types.ts b/src/styles/optionAlternateTextPlatformStyles/types.ts
index b2e8e4745fff..aacdef7e3501 100644
--- a/src/styles/optionAlternateTextPlatformStyles/types.ts
+++ b/src/styles/optionAlternateTextPlatformStyles/types.ts
@@ -1,5 +1,5 @@
import {TextStyle} from 'react-native';
-type OptionAlternateTextPlatformStyles = Partial>;
+type OptionAlternateTextPlatformStyles = Pick;
export default OptionAlternateTextPlatformStyles;
diff --git a/src/styles/optionRowStyles/index.native.ts b/src/styles/optionRowStyles/index.native.ts
index 11371509ce73..9c13fdd082a4 100644
--- a/src/styles/optionRowStyles/index.native.ts
+++ b/src/styles/optionRowStyles/index.native.ts
@@ -1,5 +1,5 @@
-import OptionRowStyles from './types';
import styles from '../styles';
+import CompactContentContainerStyles from './types';
/**
* On native platforms, alignItemsBaseline does not work correctly
@@ -7,8 +7,7 @@ import styles from '../styles';
* keeping compactContentContainerStyles as it is.
* https://github.com/Expensify/App/issues/14148
*/
-
-const compactContentContainerStyles: OptionRowStyles = styles.alignItemsCenter;
+const compactContentContainerStyles: CompactContentContainerStyles = styles.alignItemsCenter;
export {
// eslint-disable-next-line import/prefer-default-export
diff --git a/src/styles/optionRowStyles/index.ts b/src/styles/optionRowStyles/index.ts
index fbeca3c702d9..975f4243842e 100644
--- a/src/styles/optionRowStyles/index.ts
+++ b/src/styles/optionRowStyles/index.ts
@@ -1,7 +1,7 @@
-import OptionRowStyles from './types';
+import CompactContentContainerStyles from './types';
import styles from '../styles';
-const compactContentContainerStyles: OptionRowStyles = styles.alignItemsBaseline;
+const compactContentContainerStyles: CompactContentContainerStyles = styles.alignItemsBaseline;
export {
// eslint-disable-next-line import/prefer-default-export
diff --git a/src/styles/optionRowStyles/types.ts b/src/styles/optionRowStyles/types.ts
index c08174470701..fcce41f6bc28 100644
--- a/src/styles/optionRowStyles/types.ts
+++ b/src/styles/optionRowStyles/types.ts
@@ -1,6 +1,5 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
-type OptionRowStyles = CSSProperties | ViewStyle;
+type CompactContentContainerStyles = ViewStyle;
-export default OptionRowStyles;
+export default CompactContentContainerStyles;
diff --git a/src/styles/overflowXHidden/types.ts b/src/styles/overflowXHidden/types.ts
index 7ac572f0e651..0f13ba552c0c 100644
--- a/src/styles/overflowXHidden/types.ts
+++ b/src/styles/overflowXHidden/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
-type OverflowXHiddenStyles = Partial>;
+type OverflowXHiddenStyles = Pick;
export default OverflowXHiddenStyles;
diff --git a/src/styles/pointerEventsAuto/types.ts b/src/styles/pointerEventsAuto/types.ts
index 7c9f0164c936..0ecbc851e000 100644
--- a/src/styles/pointerEventsAuto/types.ts
+++ b/src/styles/pointerEventsAuto/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
-type PointerEventsAutoStyles = Partial>;
+type PointerEventsAutoStyles = Pick;
export default PointerEventsAutoStyles;
diff --git a/src/styles/pointerEventsNone/types.ts b/src/styles/pointerEventsNone/types.ts
index f2f5a0d88a41..766ac3f94349 100644
--- a/src/styles/pointerEventsNone/types.ts
+++ b/src/styles/pointerEventsNone/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
-type PointerEventsNone = Partial>;
+type PointerEventsNone = Pick;
export default PointerEventsNone;
diff --git a/src/styles/styles.js b/src/styles/styles.js
deleted file mode 100644
index 2d1e3cfd57fa..000000000000
--- a/src/styles/styles.js
+++ /dev/null
@@ -1,3834 +0,0 @@
-import {defaultStyles as defaultPickerStyles} from 'react-native-picker-select/src/styles';
-import lodashClamp from 'lodash/clamp';
-import fontFamily from './fontFamily';
-import addOutlineWidth from './addOutlineWidth';
-import defaultTheme from './themes/default';
-import fontWeightBold from './fontWeight/bold';
-import variables from './variables';
-import spacing from './utilities/spacing';
-import sizing from './utilities/sizing';
-import flex from './utilities/flex';
-import display from './utilities/display';
-import overflow from './utilities/overflow';
-import whiteSpace from './utilities/whiteSpace';
-import wordBreak from './utilities/wordBreak';
-import positioning from './utilities/positioning';
-import codeStyles from './codeStyles';
-import visibility from './utilities/visibility';
-import writingDirection from './utilities/writingDirection';
-import optionAlternateTextPlatformStyles from './optionAlternateTextPlatformStyles';
-import pointerEventsNone from './pointerEventsNone';
-import pointerEventsAuto from './pointerEventsAuto';
-import getPopOverVerticalOffset from './getPopOverVerticalOffset';
-import overflowXHidden from './overflowXHidden';
-import CONST from '../CONST';
-import * as Browser from '../libs/Browser';
-import cursor from './utilities/cursor';
-import userSelect from './utilities/userSelect';
-import textUnderline from './utilities/textUnderline';
-import objectFit from './utilities/objectFit';
-
-// touchCallout is an iOS safari only property that controls the display of the callout information when you touch and hold a target
-const touchCalloutNone = Browser.isMobileSafari() ? {WebkitTouchCallout: 'none'} : {};
-// to prevent vertical text offset in Safari for badges, new lineHeight values have been added
-const lineHeightBadge = Browser.isSafari() ? {lineHeight: variables.lineHeightXSmall} : {lineHeight: variables.lineHeightNormal};
-
-const picker = (theme) => ({
- backgroundColor: theme.transparent,
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeNormal,
- lineHeight: variables.fontSizeNormalHeight,
- paddingBottom: 8,
- paddingTop: 23,
- paddingLeft: 0,
- paddingRight: 25,
- height: variables.inputHeight,
- borderWidth: 0,
- textAlign: 'left',
-});
-
-const link = (theme) => ({
- color: theme.link,
- textDecorationColor: theme.link,
- fontFamily: fontFamily.EXP_NEUE,
-});
-
-const baseCodeTagStyles = (theme) => ({
- borderWidth: 1,
- borderRadius: 5,
- borderColor: theme.border,
- backgroundColor: theme.textBackground,
-});
-
-const headlineFont = {
- fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
- fontWeight: '500',
-};
-
-const webViewStyles = (theme) => ({
- // As of react-native-render-html v6, don't declare distinct styles for
- // custom renderers, the API for custom renderers has changed. Declare the
- // styles in the below "tagStyles" instead. If you need to reuse those
- // styles from the renderer, just pass the "style" prop to the underlying
- // component.
- tagStyles: {
- em: {
- fontFamily: fontFamily.EXP_NEUE,
- fontStyle: 'italic',
- },
-
- del: {
- textDecorationLine: 'line-through',
- textDecorationStyle: 'solid',
- },
-
- strong: {
- fontFamily: fontFamily.EXP_NEUE,
- fontWeight: 'bold',
- },
-
- a: link(theme),
-
- ul: {
- maxWidth: '100%',
- },
-
- ol: {
- maxWidth: '100%',
- },
-
- li: {
- flexShrink: 1,
- },
-
- blockquote: {
- borderLeftColor: theme.border,
- borderLeftWidth: 4,
- paddingLeft: 12,
- marginTop: 4,
- marginBottom: 4,
-
- // Overwrite default HTML margin for blockquotes
- marginLeft: 0,
- },
-
- pre: {
- ...baseCodeTagStyles(theme),
- paddingTop: 12,
- paddingBottom: 12,
- paddingRight: 8,
- paddingLeft: 8,
- fontFamily: fontFamily.MONOSPACE,
- marginTop: 0,
- marginBottom: 0,
- },
-
- code: {
- ...baseCodeTagStyles(theme),
- ...codeStyles.codeTextStyle,
- paddingLeft: 5,
- paddingRight: 5,
- fontFamily: fontFamily.MONOSPACE,
- fontSize: 13,
- },
-
- img: {
- borderColor: theme.border,
- borderRadius: variables.componentBorderRadiusNormal,
- borderWidth: 1,
- ...touchCalloutNone,
- },
-
- p: {
- marginTop: 0,
- marginBottom: 0,
- },
- h1: {
- fontSize: variables.fontSizeLarge,
- marginBottom: 8,
- },
- },
-
- baseFontStyle: {
- color: theme.text,
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE,
- flex: 1,
- lineHeight: variables.fontSizeNormalHeight,
- ...writingDirection.ltr,
- },
-});
-
-const styles = (theme) => ({
- // Add all of our utility and helper styles
- ...spacing,
- ...sizing,
- ...flex,
- ...display,
- ...overflow,
- ...positioning,
- ...wordBreak,
- ...whiteSpace,
- ...writingDirection,
- ...cursor,
- ...userSelect,
- ...textUnderline,
- ...theme, // TODO: Should we do this?
- ...objectFit,
-
- autoCompleteSuggestionsContainer: {
- backgroundColor: theme.appBG,
- borderRadius: 8,
- borderWidth: 1,
- borderColor: theme.border,
- justifyContent: 'center',
- boxShadow: variables.popoverMenuShadow,
- position: 'absolute',
- left: 0,
- right: 0,
- paddingVertical: CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTER_INNER_PADDING,
- },
-
- autoCompleteSuggestionContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- },
-
- emojiSuggestionsEmoji: {
- fontSize: variables.fontSizeMedium,
- width: 51,
- textAlign: 'center',
- },
- emojiSuggestionsText: {
- fontSize: variables.fontSizeMedium,
- flex: 1,
- ...wordBreak.breakWord,
- ...spacing.pr4,
- },
-
- mentionSuggestionsAvatarContainer: {
- width: 24,
- height: 24,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- mentionSuggestionsText: {
- fontSize: variables.fontSizeMedium,
- ...spacing.ml2,
- },
-
- mentionSuggestionsDisplayName: {
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- },
-
- mentionSuggestionsHandle: {
- color: theme.textSupporting,
- },
-
- webViewStyles: webViewStyles(theme),
-
- link: link(theme),
-
- linkMuted: {
- color: theme.textSupporting,
- textDecorationColor: theme.textSupporting,
- fontFamily: fontFamily.EXP_NEUE,
- },
-
- linkMutedHovered: {
- color: theme.textMutedReversed,
- },
-
- highlightBG: {
- backgroundColor: theme.highlightBG,
- },
-
- appBG: {
- backgroundColor: theme.appBG,
- },
-
- h4: {
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeLabel,
- fontWeight: fontWeightBold,
- },
-
- textAlignCenter: {
- textAlign: 'center',
- },
-
- textAlignRight: {
- textAlign: 'right',
- },
-
- textAlignLeft: {
- textAlign: 'left',
- },
-
- textUnderline: {
- textDecorationLine: 'underline',
- },
-
- label: {
- fontSize: variables.fontSizeLabel,
- lineHeight: variables.lineHeightLarge,
- },
-
- textLabel: {
- color: theme.text,
- fontSize: variables.fontSizeLabel,
- lineHeight: variables.lineHeightLarge,
- },
-
- mutedTextLabel: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeLabel,
- lineHeight: variables.lineHeightLarge,
- },
-
- textMicro: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- },
-
- textMicroBold: {
- color: theme.text,
- fontWeight: fontWeightBold,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- },
-
- textMicroSupporting: {
- color: theme.textSupporting,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- },
-
- textExtraSmallSupporting: {
- color: theme.textSupporting,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeExtraSmall,
- },
-
- textNormal: {
- fontSize: variables.fontSizeNormal,
- },
-
- textLarge: {
- fontSize: variables.fontSizeLarge,
- },
-
- textXLarge: {
- fontSize: variables.fontSizeXLarge,
- },
-
- textXXLarge: {
- fontSize: variables.fontSizeXXLarge,
- },
-
- textXXXLarge: {
- fontSize: variables.fontSizeXXXLarge,
- },
-
- textHero: {
- fontSize: variables.fontSizeHero,
- fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
- lineHeight: variables.lineHeightHero,
- },
-
- textStrong: {
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- },
-
- textItalic: {
- fontFamily: fontFamily.EXP_NEUE_ITALIC,
- fontStyle: 'italic',
- },
-
- textHeadline: {
- ...headlineFont,
- ...whiteSpace.preWrap,
- color: theme.heading,
- fontSize: variables.fontSizeXLarge,
- lineHeight: variables.lineHeightXXLarge,
- },
-
- textHeadlineH1: {
- ...headlineFont,
- ...whiteSpace.preWrap,
- color: theme.heading,
- fontSize: variables.fontSizeh1,
- lineHeight: variables.lineHeightSizeh1,
- },
-
- textDecorationNoLine: {
- textDecorationLine: 'none',
- },
-
- textWhite: {
- color: theme.textLight,
- },
-
- textBlue: {
- color: theme.link,
- },
-
- textUppercase: {
- textTransform: 'uppercase',
- },
-
- textNoWrap: {
- ...whiteSpace.noWrap,
- },
-
- colorReversed: {
- color: theme.textReversed,
- },
-
- colorMutedReversed: {
- color: theme.textMutedReversed,
- },
-
- colorMuted: {
- color: theme.textSupporting,
- },
-
- bgTransparent: {
- backgroundColor: 'transparent',
- },
-
- bgDark: {
- backgroundColor: theme.inverse,
- },
-
- opacity0: {
- opacity: 0,
- },
-
- opacity1: {
- opacity: 1,
- },
-
- textDanger: {
- color: theme.danger,
- },
-
- borderRadiusNormal: {
- borderRadius: variables.buttonBorderRadius,
- },
-
- button: {
- backgroundColor: theme.buttonDefaultBG,
- borderRadius: variables.buttonBorderRadius,
- minHeight: variables.componentSizeLarge,
- justifyContent: 'center',
- ...spacing.ph3,
- },
-
- buttonContainer: {
- padding: 1,
- borderRadius: variables.buttonBorderRadius,
- },
-
- buttonText: {
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeNormal,
- fontWeight: fontWeightBold,
- textAlign: 'center',
- flexShrink: 1,
-
- // It is needed to unset the Lineheight. We don't need it for buttons as button always contains single line of text.
- // It allows to vertically center the text.
- lineHeight: undefined,
-
- // Add 1px to the Button text to give optical vertical alignment.
- paddingBottom: 1,
- },
-
- buttonSmall: {
- borderRadius: variables.buttonBorderRadius,
- minHeight: variables.componentSizeSmall,
- paddingTop: 4,
- paddingHorizontal: 14,
- paddingBottom: 4,
- backgroundColor: theme.buttonDefaultBG,
- },
-
- buttonMedium: {
- borderRadius: variables.buttonBorderRadius,
- minHeight: variables.componentSizeNormal,
- paddingTop: 12,
- paddingRight: 16,
- paddingBottom: 12,
- paddingLeft: 16,
- backgroundColor: theme.buttonDefaultBG,
- },
-
- buttonLarge: {
- borderRadius: variables.buttonBorderRadius,
- minHeight: variables.componentSizeLarge,
- paddingTop: 8,
- paddingRight: 10,
- paddingBottom: 8,
- paddingLeft: 18,
- backgroundColor: theme.buttonDefaultBG,
- },
-
- buttonSmallText: {
- fontSize: variables.fontSizeSmall,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- textAlign: 'center',
- },
-
- buttonMediumText: {
- fontSize: variables.fontSizeLabel,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- textAlign: 'center',
- },
-
- buttonLargeText: {
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- textAlign: 'center',
- },
-
- buttonDefaultHovered: {
- backgroundColor: theme.buttonHoveredBG,
- borderWidth: 0,
- },
-
- buttonSuccess: {
- backgroundColor: theme.success,
- borderWidth: 0,
- },
-
- buttonOpacityDisabled: {
- opacity: 0.5,
- },
-
- buttonSuccessHovered: {
- backgroundColor: theme.successHover,
- borderWidth: 0,
- },
-
- buttonDanger: {
- backgroundColor: theme.danger,
- borderWidth: 0,
- },
-
- buttonDangerHovered: {
- backgroundColor: theme.dangerHover,
- borderWidth: 0,
- },
-
- buttonDisabled: {
- backgroundColor: theme.buttonDefaultBG,
- borderWidth: 0,
- },
-
- buttonDivider: {
- height: variables.dropDownButtonDividerHeight,
- borderWidth: 0.7,
- borderColor: theme.text,
- },
-
- noBorderRadius: {
- borderRadius: 0,
- },
-
- noRightBorderRadius: {
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- },
-
- noLeftBorderRadius: {
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- },
-
- buttonCTA: {
- paddingVertical: 6,
- ...spacing.mh4,
- },
-
- buttonCTAIcon: {
- marginRight: 22,
-
- // Align vertically with the Button text
- paddingBottom: 1,
- paddingTop: 1,
- },
-
- buttonConfirm: {
- margin: 20,
- },
-
- attachmentButtonBigScreen: {
- minWidth: 300,
- alignSelf: 'center',
- },
-
- buttonConfirmText: {
- paddingLeft: 20,
- paddingRight: 20,
- },
-
- buttonSuccessText: {
- color: theme.textLight,
- },
-
- buttonDangerText: {
- color: theme.textLight,
- },
-
- hoveredComponentBG: {
- backgroundColor: theme.hoverComponentBG,
- },
-
- activeComponentBG: {
- backgroundColor: theme.activeComponentBG,
- },
-
- touchableButtonImage: {
- alignItems: 'center',
- height: variables.componentSizeNormal,
- justifyContent: 'center',
- width: variables.componentSizeNormal,
- },
-
- visuallyHidden: {
- ...visibility.hidden,
- overflow: 'hidden',
- width: 0,
- height: 0,
- },
-
- visibilityHidden: {
- ...visibility.hidden,
- },
-
- loadingVBAAnimation: {
- width: 140,
- height: 140,
- },
-
- pickerSmall: (backgroundColor = theme.highlightBG) => ({
- inputIOS: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- paddingLeft: 0,
- paddingRight: 17,
- paddingTop: 6,
- paddingBottom: 6,
- borderWidth: 0,
- color: theme.text,
- height: 26,
- opacity: 1,
- backgroundColor: 'transparent',
- },
- done: {
- color: theme.text,
- },
- doneDepressed: {
- fontSize: defaultPickerStyles.done.fontSize,
- },
- modalViewMiddle: {
- backgroundColor: theme.border,
- borderTopWidth: 0,
- },
- modalViewBottom: {
- backgroundColor: theme.highlightBG,
- },
- inputWeb: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- paddingLeft: 0,
- paddingRight: 17,
- paddingTop: 6,
- paddingBottom: 6,
- borderWidth: 0,
- color: theme.text,
- appearance: 'none',
- height: 26,
- opacity: 1,
- backgroundColor,
- ...cursor.cursorPointer,
- },
- inputAndroid: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- paddingLeft: 0,
- paddingRight: 17,
- paddingTop: 6,
- paddingBottom: 6,
- borderWidth: 0,
- color: theme.text,
- height: 26,
- opacity: 1,
- backgroundColor: 'transparent',
- },
- iconContainer: {
- top: 7,
- ...pointerEventsNone,
- },
- icon: {
- width: variables.iconSizeExtraSmall,
- height: variables.iconSizeExtraSmall,
- },
- }),
-
- badge: {
- backgroundColor: theme.border,
- borderRadius: 14,
- height: variables.iconSizeNormal,
- flexDirection: 'row',
- paddingHorizontal: 7,
- alignItems: 'center',
- },
-
- badgeSuccess: {
- backgroundColor: theme.success,
- },
-
- badgeSuccessPressed: {
- backgroundColor: theme.successHover,
- },
-
- badgeAdHocSuccess: {
- backgroundColor: theme.badgeAdHoc,
- },
-
- badgeAdHocSuccessPressed: {
- backgroundColor: theme.badgeAdHocHover,
- },
-
- badgeDanger: {
- backgroundColor: theme.danger,
- },
-
- badgeDangerPressed: {
- backgroundColor: theme.dangerPressed,
- },
-
- badgeText: {
- color: theme.text,
- fontSize: variables.fontSizeSmall,
- ...lineHeightBadge,
- ...whiteSpace.noWrap,
- },
-
- border: {
- borderWidth: 1,
- borderRadius: variables.componentBorderRadius,
- borderColor: theme.border,
- },
-
- borderColorFocus: {
- borderColor: theme.borderFocus,
- },
-
- borderColorDanger: {
- borderColor: theme.danger,
- },
-
- textInputDisabled: {
- // Adding disabled color theme to indicate user that the field is not editable.
- backgroundColor: theme.highlightBG,
- borderBottomWidth: 2,
- borderColor: theme.borderLighter,
- // Adding browser specefic style to bring consistency between Safari and other platforms.
- // Applying the Webkit styles only to browsers as it is not available in native.
- ...(Browser.getBrowser()
- ? {
- WebkitTextFillColor: theme.textSupporting,
- WebkitOpacity: 1,
- }
- : {}),
- color: theme.textSupporting,
- },
-
- uploadReceiptView: (isSmallScreenWidth) => ({
- borderRadius: variables.componentBorderRadiusLarge,
- borderWidth: isSmallScreenWidth ? 0 : 2,
- borderColor: theme.borderFocus,
- borderStyle: 'dotted',
- marginBottom: 20,
- marginLeft: 20,
- marginRight: 20,
- justifyContent: 'center',
- alignItems: 'center',
- paddingVertical: 40,
- gap: 4,
- flex: 1,
- }),
-
- receiptViewTextContainer: {
- paddingHorizontal: 40,
- ...sizing.w100,
- },
-
- cameraView: {
- flex: 1,
- overflow: 'hidden',
- borderRadius: 28,
- borderStyle: 'solid',
- borderWidth: 8,
- backgroundColor: theme.highlightBG,
- borderColor: theme.appBG,
- display: 'flex',
- justifyContent: 'center',
- justifyItems: 'center',
- },
-
- permissionView: {
- paddingVertical: 108,
- paddingHorizontal: 61,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- headerAnonymousFooter: {
- color: theme.heading,
- fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
- fontSize: variables.fontSizeXLarge,
- lineHeight: variables.lineHeightXXLarge,
- },
-
- headerText: {
- color: theme.heading,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeNormal,
- fontWeight: fontWeightBold,
- },
-
- headerGap: {
- height: CONST.DESKTOP_HEADER_PADDING,
- },
-
- reportOptions: {
- marginLeft: 8,
- },
-
- chatItemComposeSecondaryRow: {
- height: CONST.CHAT_FOOTER_SECONDARY_ROW_HEIGHT,
- marginBottom: CONST.CHAT_FOOTER_SECONDARY_ROW_PADDING,
- marginTop: CONST.CHAT_FOOTER_SECONDARY_ROW_PADDING,
- },
-
- chatItemComposeSecondaryRowSubText: {
- color: theme.textSupporting,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- },
-
- chatItemComposeSecondaryRowOffset: {
- marginLeft: variables.chatInputSpacing,
- },
-
- offlineIndicator: {
- marginLeft: variables.chatInputSpacing,
- },
-
- offlineIndicatorMobile: {
- paddingLeft: 20,
- paddingTop: 5,
- paddingBottom: 30,
- marginBottom: -25,
- },
-
- offlineIndicatorRow: {
- height: 25,
- },
-
- // Actions
- actionAvatar: {
- borderRadius: 20,
- },
-
- componentHeightLarge: {
- height: variables.inputHeight,
- },
-
- calendarHeader: {
- height: 50,
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- paddingHorizontal: 15,
- paddingRight: 5,
- ...userSelect.userSelectNone,
- },
-
- calendarDayRoot: {
- flex: 1,
- height: 45,
- justifyContent: 'center',
- alignItems: 'center',
- ...userSelect.userSelectNone,
- },
-
- calendarDayContainer: {
- width: 30,
- height: 30,
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: 15,
- overflow: 'hidden',
- },
-
- calendarDayContainerSelected: {
- backgroundColor: theme.buttonDefaultBG,
- },
-
- /**
- * @param {number} textInputHeight
- * @param {number} minHeight
- * @param {number} maxHeight
- * @returns {object}
- */
- autoGrowHeightInputContainer: (textInputHeight, minHeight, maxHeight) => ({
- height: lodashClamp(textInputHeight, minHeight, maxHeight),
- minHeight,
- }),
-
- autoGrowHeightHiddenInput: (maxWidth, maxHeight) => ({
- maxWidth,
- maxHeight: maxHeight && maxHeight + 1,
- overflow: 'hidden',
- }),
-
- textInputContainer: {
- flex: 1,
- justifyContent: 'center',
- height: '100%',
- backgroundColor: 'transparent',
- borderBottomWidth: 2,
- borderColor: theme.border,
- overflow: 'hidden',
- },
-
- textInputLabel: {
- position: 'absolute',
- left: 0,
- top: 0,
- fontSize: variables.fontSizeNormal,
- color: theme.textSupporting,
- fontFamily: fontFamily.EXP_NEUE,
- width: '100%',
- },
-
- textInputLabelBackground: {
- position: 'absolute',
- top: 0,
- width: '100%',
- height: 23,
- backgroundColor: theme.componentBG,
- },
-
- textInputLabelDesktop: {
- transformOrigin: 'left center',
- },
-
- textInputLabelTransformation: (translateY, translateX, scale) => ({
- transform: [{translateY}, {translateX}, {scale}],
- }),
-
- baseTextInput: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeNormal,
- lineHeight: variables.lineHeightXLarge,
- color: theme.text,
- paddingTop: 23,
- paddingBottom: 8,
- paddingLeft: 0,
- borderWidth: 0,
- },
-
- textInputMultiline: {
- scrollPadding: '23px 0 0 0',
- },
-
- textInputMultilineContainer: {
- paddingTop: 23,
- },
-
- textInputAndIconContainer: {
- flex: 1,
- height: '100%',
- zIndex: -1,
- flexDirection: 'row',
- },
-
- textInputDesktop: addOutlineWidth({}, 0),
-
- textInputIconContainer: {
- paddingHorizontal: 11,
- justifyContent: 'center',
- margin: 1,
- },
-
- secureInput: {
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- },
-
- textInput: {
- backgroundColor: 'transparent',
- borderRadius: variables.componentBorderRadiusNormal,
- height: variables.inputComponentSizeNormal,
- borderColor: theme.border,
- borderWidth: 1,
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeNormal,
- paddingLeft: 12,
- paddingRight: 12,
- paddingTop: 10,
- paddingBottom: 10,
- textAlignVertical: 'center',
- },
-
- textInputPrefixWrapper: {
- position: 'absolute',
- left: 0,
- top: 0,
- height: variables.inputHeight,
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- paddingTop: 23,
- paddingBottom: 8,
- },
-
- textInputPrefix: {
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeNormal,
- textAlignVertical: 'center',
- },
-
- pickerContainer: {
- borderBottomWidth: 2,
- paddingLeft: 0,
- borderStyle: 'solid',
- borderColor: theme.border,
- justifyContent: 'center',
- backgroundColor: 'transparent',
- height: variables.inputHeight,
- overflow: 'hidden',
- },
-
- pickerContainerSmall: {
- height: variables.inputHeightSmall,
- },
-
- pickerLabel: {
- position: 'absolute',
- left: 0,
- top: 6,
- zIndex: 1,
- },
-
- picker: (disabled = false, backgroundColor = theme.appBG) => ({
- iconContainer: {
- top: Math.round(variables.inputHeight * 0.5) - 11,
- right: 0,
- ...pointerEventsNone,
- },
-
- inputWeb: {
- appearance: 'none',
- ...(disabled ? cursor.cursorDisabled : cursor.cursorPointer),
- ...picker(theme),
- backgroundColor,
- },
-
- inputIOS: {
- ...picker(theme),
- },
- done: {
- color: theme.text,
- },
- doneDepressed: {
- fontSize: defaultPickerStyles.done.fontSize,
- },
- modalViewMiddle: {
- backgroundColor: theme.border,
- borderTopWidth: 0,
- },
- modalViewBottom: {
- backgroundColor: theme.highlightBG,
- },
-
- inputAndroid: {
- ...picker(theme),
- },
- }),
-
- disabledText: {
- color: theme.icon,
- },
-
- inputDisabled: {
- backgroundColor: theme.highlightBG,
- color: theme.icon,
- },
-
- noOutline: addOutlineWidth({}, 0),
-
- textLabelSupporting: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeLabel,
- color: theme.textSupporting,
- },
-
- textLabelError: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeLabel,
- color: theme.textError,
- },
-
- textReceiptUpload: {
- ...headlineFont,
- fontSize: variables.fontSizeXLarge,
- color: theme.textLight,
- textAlign: 'center',
- },
-
- subTextReceiptUpload: {
- fontFamily: fontFamily.EXP_NEUE,
- lineHeight: variables.lineHeightLarge,
- textAlign: 'center',
- color: theme.textLight,
- },
-
- furtherDetailsText: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- color: theme.textSupporting,
- },
-
- lh16: {
- lineHeight: 16,
- },
-
- lh20: {
- lineHeight: 20,
- },
-
- lh140Percent: {
- lineHeight: '140%',
- },
-
- formHelp: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeLabel,
- lineHeight: variables.lineHeightLarge,
- marginBottom: 4,
- },
-
- formError: {
- color: theme.textError,
- fontSize: variables.fontSizeLabel,
- lineHeight: variables.formErrorLineHeight,
- marginBottom: 4,
- },
-
- formSuccess: {
- color: theme.success,
- fontSize: variables.fontSizeLabel,
- lineHeight: 18,
- marginBottom: 4,
- },
-
- signInPage: {
- backgroundColor: theme.highlightBG,
- minHeight: '100%',
- flex: 1,
- },
-
- signInPageHeroCenter: {
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- justifyContent: 'center',
- alignItems: 'center',
- },
-
- signInPageGradient: {
- height: '100%',
- width: 540,
- position: 'absolute',
- top: 0,
- left: 0,
- },
-
- signInPageGradientMobile: {
- height: 300,
- width: 800,
- position: 'absolute',
- top: 0,
- left: 0,
- },
-
- signInBackground: {
- position: 'absolute',
- bottom: 0,
- left: 0,
- minHeight: 700,
- },
-
- signInPageInner: {
- marginLeft: 'auto',
- marginRight: 'auto',
- height: '100%',
- width: '100%',
- },
-
- signInPageContentTopSpacer: {
- maxHeight: 132,
- minHeight: 24,
- },
-
- signInPageContentTopSpacerSmallScreens: {
- maxHeight: 132,
- minHeight: 45,
- },
-
- signInPageLeftContainer: {
- paddingLeft: 40,
- paddingRight: 40,
- },
-
- signInPageLeftContainerWide: {
- maxWidth: variables.sideBarWidth,
- },
-
- signInPageWelcomeFormContainer: {
- maxWidth: CONST.SIGN_IN_FORM_WIDTH,
- },
-
- signInPageWelcomeTextContainer: {
- width: CONST.SIGN_IN_FORM_WIDTH,
- },
-
- changeExpensifyLoginLinkContainer: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- ...wordBreak.breakWord,
- },
-
- // Sidebar Styles
- sidebar: {
- backgroundColor: theme.sidebar,
- height: '100%',
- },
-
- sidebarHeaderContainer: {
- flexDirection: 'row',
- paddingHorizontal: 20,
- paddingVertical: 19,
- justifyContent: 'space-between',
- alignItems: 'center',
- },
-
- subNavigationContainer: {
- backgroundColor: theme.sidebar,
- flex: 1,
- borderTopLeftRadius: variables.componentBorderRadiusRounded,
- },
-
- sidebarAnimatedWrapperContainer: {
- height: '100%',
- position: 'absolute',
- },
-
- sidebarFooter: {
- alignItems: 'center',
- display: 'flex',
- justifyContent: 'center',
- paddingVertical: variables.lineHeightXLarge,
- width: '100%',
- },
-
- sidebarAvatar: {
- backgroundColor: theme.icon,
- borderRadius: 20,
- height: variables.componentSizeNormal,
- width: variables.componentSizeNormal,
- },
-
- statusIndicator: (backgroundColor = theme.danger) => ({
- borderColor: theme.sidebar,
- backgroundColor,
- borderRadius: 8,
- borderWidth: 2,
- position: 'absolute',
- right: -2,
- top: -1,
- height: 16,
- width: 16,
- zIndex: 10,
- }),
-
- floatingActionButtonContainer: {
- position: 'absolute',
- left: 16,
- // The bottom of the floating action button should align with the bottom of the compose box.
- // The value should be equal to the height + marginBottom + marginTop of chatItemComposeSecondaryRow
- bottom: 25,
- },
-
- floatingActionButton: {
- backgroundColor: theme.success,
- height: variables.componentSizeNormal,
- width: variables.componentSizeNormal,
- borderRadius: 999,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- sidebarFooterUsername: {
- color: theme.heading,
- fontSize: variables.fontSizeLabel,
- fontWeight: '700',
- width: 200,
- textOverflow: 'ellipsis',
- overflow: 'hidden',
- ...whiteSpace.noWrap,
- },
-
- sidebarFooterLink: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeSmall,
- textDecorationLine: 'none',
- fontFamily: fontFamily.EXP_NEUE,
- lineHeight: 20,
- },
-
- sidebarListContainer: {
- scrollbarWidth: 'none',
- paddingBottom: 4,
- },
-
- sidebarListItem: {
- justifyContent: 'center',
- textDecorationLine: 'none',
- },
-
- RHPNavigatorContainer: (isSmallScreenWidth) => ({
- width: isSmallScreenWidth ? '100%' : variables.sideBarWidth,
- position: 'absolute',
- right: 0,
- height: '100%',
- }),
-
- onlyEmojisText: {
- fontSize: variables.fontSizeOnlyEmojis,
- lineHeight: variables.fontSizeOnlyEmojisHeight,
- },
-
- onlyEmojisTextLineHeight: {
- lineHeight: variables.fontSizeOnlyEmojisHeight,
- },
-
- createMenuPositionSidebar: (windowHeight) => ({
- horizontal: 18,
- vertical: windowHeight - 75,
- }),
-
- createMenuPositionProfile: (windowWidth) => ({
- horizontal: windowWidth - 355,
- ...getPopOverVerticalOffset(162),
- }),
-
- createMenuPositionReportActionCompose: (windowHeight) => ({
- horizontal: 18 + variables.sideBarWidth,
- vertical: windowHeight - 83,
- }),
-
- createMenuPositionRightSidepane: {
- right: 18,
- bottom: 75,
- },
-
- createMenuContainer: {
- width: variables.sideBarWidth - 40,
- paddingVertical: 12,
- },
-
- createMenuHeaderText: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeLabel,
- color: theme.heading,
- },
-
- popoverMenuItem: {
- flexDirection: 'row',
- borderRadius: 0,
- paddingHorizontal: 20,
- paddingVertical: 12,
- justifyContent: 'space-between',
- width: '100%',
- },
-
- popoverMenuIcon: {
- width: variables.componentSizeNormal,
- justifyContent: 'center',
- alignItems: 'center',
- },
-
- popoverMenuText: {
- fontSize: variables.fontSizeNormal,
- color: theme.heading,
- },
-
- popoverInnerContainer: {
- paddingTop: 0, // adjusting this because the mobile modal adds additional padding that we don't need for our layout
- maxHeight: '95%',
- },
-
- menuItemTextContainer: {
- minHeight: variables.componentSizeNormal,
- },
-
- chatLinkRowPressable: {
- minWidth: 0,
- textDecorationLine: 'none',
- flex: 1,
- },
-
- sidebarLink: {
- textDecorationLine: 'none',
- },
-
- sidebarLinkLHN: {
- textDecorationLine: 'none',
- marginLeft: 12,
- marginRight: 12,
- borderRadius: 8,
- },
-
- sidebarLinkInner: {
- alignItems: 'center',
- flexDirection: 'row',
- paddingLeft: 20,
- paddingRight: 20,
- },
-
- sidebarLinkInnerLHN: {
- alignItems: 'center',
- flexDirection: 'row',
- paddingLeft: 8,
- paddingRight: 8,
- },
-
- sidebarLinkText: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeNormal,
- textDecorationLine: 'none',
- overflow: 'hidden',
- },
-
- sidebarLinkHover: {
- backgroundColor: theme.sidebarHover,
- },
-
- sidebarLinkHoverLHN: {
- backgroundColor: theme.highlightBG,
- },
-
- sidebarLinkActive: {
- backgroundColor: theme.border,
- textDecorationLine: 'none',
- },
-
- sidebarLinkActiveLHN: {
- backgroundColor: theme.highlightBG,
- textDecorationLine: 'none',
- },
-
- sidebarLinkTextBold: {
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- color: theme.heading,
- },
-
- sidebarLinkActiveText: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeNormal,
- textDecorationLine: 'none',
- overflow: 'hidden',
- },
-
- optionItemAvatarNameWrapper: {
- minWidth: 0,
- flex: 1,
- },
-
- optionDisplayName: {
- fontFamily: fontFamily.EXP_NEUE,
- minHeight: variables.alternateTextHeight,
- lineHeight: variables.lineHeightXLarge,
- ...whiteSpace.noWrap,
- },
-
- optionDisplayNameCompact: {
- minWidth: 'auto',
- flexBasis: 'auto',
- flexGrow: 0,
- flexShrink: 1,
- },
-
- displayNameTooltipEllipsis: {
- position: 'absolute',
- opacity: 0,
- right: 0,
- bottom: 0,
- },
-
- optionAlternateText: {
- minHeight: variables.alternateTextHeight,
- lineHeight: variables.lineHeightXLarge,
- },
-
- optionAlternateTextCompact: {
- flexShrink: 1,
- flexGrow: 1,
- flexBasis: 'auto',
- ...optionAlternateTextPlatformStyles,
- },
-
- optionRow: {
- minHeight: variables.optionRowHeight,
- paddingTop: 12,
- paddingBottom: 12,
- },
-
- optionRowSelected: {
- backgroundColor: theme.activeComponentBG,
- },
-
- optionRowDisabled: {
- color: theme.textSupporting,
- },
-
- optionRowCompact: {
- height: variables.optionRowHeightCompact,
- paddingTop: 12,
- paddingBottom: 12,
- },
-
- optionsListSectionHeader: {
- marginTop: 8,
- marginBottom: 4,
- },
-
- overlayStyles: (current) => ({
- position: 'fixed',
-
- // We need to stretch the overlay to cover the sidebar and the translate animation distance.
- left: -2 * variables.sideBarWidth,
- top: 0,
- bottom: 0,
- right: 0,
- backgroundColor: theme.overlay,
- opacity: current.progress.interpolate({
- inputRange: [0, 1],
- outputRange: [0, variables.overlayOpacity],
- extrapolate: 'clamp',
- }),
- }),
-
- appContent: {
- backgroundColor: theme.appBG,
- overflow: 'hidden',
- },
-
- appContentHeader: {
- height: variables.contentHeaderHeight,
- justifyContent: 'center',
- display: 'flex',
- paddingRight: 20,
- },
-
- appContentHeaderTitle: {
- alignItems: 'center',
- flexDirection: 'row',
- },
-
- LHNToggle: {
- alignItems: 'center',
- height: variables.contentHeaderHeight,
- justifyContent: 'center',
- paddingRight: 10,
- paddingLeft: 20,
- },
-
- LHNToggleIcon: {
- height: 15,
- width: 18,
- },
-
- chatContentScrollView: {
- flexGrow: 1,
- justifyContent: 'flex-start',
- paddingBottom: 16,
- },
-
- // Chat Item
- chatItem: {
- display: 'flex',
- flexDirection: 'row',
- paddingTop: 8,
- paddingBottom: 8,
- paddingLeft: 20,
- paddingRight: 20,
- },
-
- chatItemRightGrouped: {
- flexGrow: 1,
- flexShrink: 1,
- flexBasis: 0,
- position: 'relative',
- marginLeft: variables.chatInputSpacing,
- },
-
- chatItemRight: {
- flexGrow: 1,
- flexShrink: 1,
- flexBasis: 0,
- position: 'relative',
- },
-
- chatItemMessageHeader: {
- alignItems: 'center',
- display: 'flex',
- flexDirection: 'row',
- flexWrap: 'nowrap',
- },
-
- chatItemMessageHeaderSender: {
- color: theme.heading,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeNormal,
- fontWeight: fontWeightBold,
- lineHeight: variables.lineHeightXLarge,
- ...wordBreak.breakWord,
- },
-
- chatItemMessageHeaderTimestamp: {
- flexShrink: 0,
- color: theme.textSupporting,
- fontSize: variables.fontSizeSmall,
- paddingTop: 2,
- },
-
- chatItemMessage: {
- color: theme.text,
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE,
- lineHeight: variables.lineHeightXLarge,
- maxWidth: '100%',
- ...cursor.cursorAuto,
- ...whiteSpace.preWrap,
- ...wordBreak.breakWord,
- },
-
- renderHTMLTitle: {
- color: theme.text,
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE,
- lineHeight: variables.lineHeightXLarge,
- maxWidth: '100%',
- ...whiteSpace.preWrap,
- ...wordBreak.breakWord,
- },
-
- chatItemComposeWithFirstRow: {
- minHeight: 90,
- },
-
- chatItemFullComposeRow: {
- ...sizing.h100,
- },
-
- chatItemComposeBoxColor: {
- borderColor: theme.border,
- },
-
- chatItemComposeBoxFocusedColor: {
- borderColor: theme.borderFocus,
- },
-
- chatItemComposeBox: {
- backgroundColor: theme.componentBG,
- borderWidth: 1,
- borderRadius: variables.componentBorderRadiusRounded,
- minHeight: variables.componentSizeMedium,
- },
-
- chatItemFullComposeBox: {
- ...flex.flex1,
- ...sizing.h100,
- },
-
- chatFooter: {
- paddingLeft: 20,
- paddingRight: 20,
- display: 'flex',
- backgroundColor: theme.appBG,
- },
-
- chatFooterFullCompose: {
- flex: 1,
- },
-
- chatItemDraft: {
- display: 'flex',
- flexDirection: 'row',
- paddingTop: 8,
- paddingBottom: 8,
- paddingLeft: 20,
- paddingRight: 20,
- },
-
- chatItemReactionsDraftRight: {
- marginLeft: 52,
- },
- chatFooterAtTheTop: {
- flexGrow: 1,
- justifyContent: 'flex-start',
- },
-
- // Be extremely careful when editing the compose styles, as it is easy to introduce regressions.
- // Make sure you run the following tests against any changes: #12669
- textInputCompose: addOutlineWidth(
- {
- backgroundColor: theme.componentBG,
- borderColor: theme.border,
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeNormal,
- borderWidth: 0,
- height: 'auto',
- lineHeight: variables.lineHeightXLarge,
- ...overflowXHidden,
-
- // On Android, multiline TextInput with height: 'auto' will show extra padding unless they are configured with
- // paddingVertical: 0, alignSelf: 'center', and textAlignVertical: 'center'
-
- paddingHorizontal: variables.avatarChatSpacing,
- paddingTop: 0,
- paddingBottom: 0,
- alignSelf: 'center',
- textAlignVertical: 'center',
- },
- 0,
- ),
-
- textInputFullCompose: {
- alignSelf: 'stretch',
- flex: 1,
- maxHeight: '100%',
- textAlignVertical: 'top',
- },
-
- // composer padding should not be modified unless thoroughly tested against the cases in this PR: #12669
- textInputComposeSpacing: {
- paddingVertical: 5,
- ...flex.flexRow,
- flex: 1,
- },
-
- textInputComposeBorder: {
- borderLeftWidth: 1,
- borderColor: theme.border,
- },
-
- chatItemSubmitButton: {
- alignSelf: 'flex-end',
- borderRadius: variables.componentBorderRadiusRounded,
- backgroundColor: theme.transparent,
- height: 40,
- padding: 10,
- margin: 3,
- justifyContent: 'center',
- },
-
- emojiPickerContainer: {
- backgroundColor: theme.componentBG,
- },
-
- emojiHeaderContainer: {
- backgroundColor: theme.componentBG,
- display: 'flex',
- height: CONST.EMOJI_PICKER_HEADER_HEIGHT,
- justifyContent: 'center',
- width: '100%',
- },
-
- emojiSkinToneTitle: {
- ...spacing.pv1,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- color: theme.heading,
- fontSize: variables.fontSizeSmall,
- },
-
- // Emoji Picker Styles
- emojiText: {
- textAlign: 'center',
- fontSize: variables.emojiSize,
- ...spacing.pv0,
- ...spacing.ph0,
- lineHeight: variables.emojiLineHeight,
- },
-
- emojiItem: {
- width: '12.5%',
- textAlign: 'center',
- borderRadius: 8,
- paddingTop: 2,
- paddingBottom: 2,
- height: CONST.EMOJI_PICKER_ITEM_HEIGHT,
- ...userSelect.userSelectNone,
- },
-
- emojiItemHighlighted: {
- transition: '0.2s ease',
- backgroundColor: theme.buttonDefaultBG,
- },
-
- emojiItemKeyboardHighlighted: {
- transition: '0.2s ease',
- borderWidth: 1,
- borderColor: theme.link,
- borderRadius: variables.buttonBorderRadius,
- },
-
- categoryShortcutButton: {
- flex: 1,
- borderRadius: 8,
- height: CONST.EMOJI_PICKER_ITEM_HEIGHT,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- chatItemEmojiButton: {
- alignSelf: 'flex-end',
- borderRadius: variables.buttonBorderRadius,
- height: 40,
- marginVertical: 3,
- paddingHorizontal: 10,
- justifyContent: 'center',
- },
-
- editChatItemEmojiWrapper: {
- marginRight: 3,
- alignSelf: 'flex-end',
- },
-
- hoveredButton: {
- backgroundColor: theme.buttonHoveredBG,
- },
-
- composerSizeButton: {
- alignSelf: 'center',
- height: 32,
- width: 32,
- padding: 6,
- margin: 3,
- borderRadius: variables.componentBorderRadiusRounded,
- backgroundColor: theme.transparent,
- justifyContent: 'center',
- },
-
- chatItemAttachmentPlaceholder: {
- backgroundColor: theme.sidebar,
- borderColor: theme.border,
- borderWidth: 1,
- borderRadius: variables.componentBorderRadiusNormal,
- height: 150,
- textAlign: 'center',
- verticalAlign: 'middle',
- width: 200,
- },
-
- sidebarVisible: {
- borderRightWidth: 1,
- },
-
- sidebarHidden: {
- width: 0,
- borderRightWidth: 0,
- },
-
- exampleCheckImage: {
- width: '100%',
- height: 80,
- borderColor: theme.border,
- borderWidth: 1,
- borderRadius: variables.componentBorderRadiusNormal,
- },
-
- singleAvatar: {
- height: 24,
- width: 24,
- backgroundColor: theme.icon,
- borderRadius: 24,
- },
-
- singleAvatarSmall: {
- height: 18,
- width: 18,
- backgroundColor: theme.icon,
- borderRadius: 18,
- },
-
- singleAvatarMedium: {
- height: 52,
- width: 52,
- backgroundColor: theme.icon,
- borderRadius: 52,
- },
-
- secondAvatar: {
- position: 'absolute',
- right: -18,
- bottom: -18,
- borderWidth: 3,
- borderRadius: 30,
- borderColor: 'transparent',
- },
-
- secondAvatarSmall: {
- position: 'absolute',
- right: -13,
- bottom: -13,
- borderWidth: 3,
- borderRadius: 18,
- borderColor: 'transparent',
- },
-
- secondAvatarMedium: {
- position: 'absolute',
- right: -36,
- bottom: -36,
- borderWidth: 3,
- borderRadius: 52,
- borderColor: 'transparent',
- },
-
- secondAvatarSubscript: {
- position: 'absolute',
- right: -6,
- bottom: -6,
- },
-
- secondAvatarSubscriptCompact: {
- position: 'absolute',
- bottom: -1,
- right: -1,
- },
-
- secondAvatarSubscriptSmallNormal: {
- position: 'absolute',
- bottom: 0,
- right: 0,
- },
-
- secondAvatarInline: {
- bottom: -3,
- right: -25,
- borderWidth: 3,
- borderRadius: 18,
- borderColor: theme.cardBorder,
- backgroundColor: theme.appBG,
- },
-
- avatarLarge: {
- width: variables.avatarSizeLarge,
- height: variables.avatarSizeLarge,
- },
-
- avatarXLarge: {
- width: variables.avatarSizeXLarge,
- height: variables.avatarSizeXLarge,
- },
-
- avatarInnerText: {
- color: theme.textLight,
- fontSize: variables.fontSizeSmall,
- lineHeight: undefined,
- marginLeft: -3,
- textAlign: 'center',
- },
-
- avatarInnerTextSmall: {
- color: theme.textLight,
- fontSize: variables.fontSizeExtraSmall,
- lineHeight: undefined,
- marginLeft: -2,
- textAlign: 'center',
- },
-
- emptyAvatar: {
- height: variables.avatarSizeNormal,
- width: variables.avatarSizeNormal,
- },
-
- emptyAvatarSmallNormal: {
- height: variables.avatarSizeSmallNormal,
- width: variables.avatarSizeSmallNormal,
- },
-
- emptyAvatarSmall: {
- height: variables.avatarSizeSmall,
- width: variables.avatarSizeSmall,
- },
-
- emptyAvatarSmaller: {
- height: variables.avatarSizeSmaller,
- width: variables.avatarSizeSmaller,
- },
-
- emptyAvatarMedium: {
- height: variables.avatarSizeMedium,
- width: variables.avatarSizeMedium,
- },
-
- emptyAvatarLarge: {
- height: variables.avatarSizeLarge,
- width: variables.avatarSizeLarge,
- },
-
- emptyAvatarMargin: {
- marginRight: variables.avatarChatSpacing,
- },
-
- emptyAvatarMarginChat: {
- marginRight: variables.avatarChatSpacing - 12,
- },
-
- emptyAvatarMarginSmall: {
- marginRight: variables.avatarChatSpacing - 4,
- },
-
- emptyAvatarMarginSmaller: {
- marginRight: variables.avatarChatSpacing - 4,
- },
-
- borderTop: {
- borderTopWidth: variables.borderTopWidth,
- borderColor: theme.border,
- },
-
- borderTopRounded: {
- borderTopWidth: 1,
- borderColor: theme.border,
- borderTopLeftRadius: variables.componentBorderRadiusNormal,
- borderTopRightRadius: variables.componentBorderRadiusNormal,
- },
-
- borderBottomRounded: {
- borderBottomWidth: 1,
- borderColor: theme.border,
- borderBottomLeftRadius: variables.componentBorderRadiusNormal,
- borderBottomRightRadius: variables.componentBorderRadiusNormal,
- },
-
- borderBottom: {
- borderBottomWidth: 1,
- borderColor: theme.border,
- },
-
- borderNone: {
- borderWidth: 0,
- borderBottomWidth: 0,
- },
-
- borderRight: {
- borderRightWidth: 1,
- borderColor: theme.border,
- },
-
- borderLeft: {
- borderLeftWidth: 1,
- borderColor: theme.border,
- },
-
- pointerEventsNone,
-
- pointerEventsAuto,
-
- headerBar: {
- overflow: 'hidden',
- justifyContent: 'center',
- display: 'flex',
- paddingLeft: 20,
- height: variables.contentHeaderHeight,
- width: '100%',
- },
-
- imageViewContainer: {
- width: '100%',
- height: '100%',
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- imageModalPDF: {
- flex: 1,
- backgroundColor: theme.modalBackground,
- },
-
- PDFView: {
- // `display: grid` is not supported in native platforms!
- // It's being used on Web/Desktop only to vertically center short PDFs,
- // while preventing the overflow of the top of long PDF files.
- display: 'grid',
- backgroundColor: theme.modalBackground,
- width: '100%',
- height: '100%',
- justifyContent: 'center',
- overflow: 'hidden',
- alignItems: 'center',
- },
-
- PDFViewList: {
- overflowX: 'hidden',
- // There properties disable "focus" effect on list
- boxShadow: 'none',
- outline: 'none',
- },
-
- getPDFPasswordFormStyle: (isSmallScreenWidth) => ({
- width: isSmallScreenWidth ? '100%' : 350,
- ...(isSmallScreenWidth && flex.flex1),
- }),
-
- centeredModalStyles: (isSmallScreenWidth, isFullScreenWhenSmall) => ({
- borderWidth: isSmallScreenWidth && !isFullScreenWhenSmall ? 1 : 0,
- marginHorizontal: isSmallScreenWidth ? 0 : 20,
- }),
-
- imageModalImageCenterContainer: {
- alignItems: 'center',
- flex: 1,
- justifyContent: 'center',
- width: '100%',
- },
-
- defaultAttachmentView: {
- backgroundColor: theme.sidebar,
- borderRadius: variables.componentBorderRadiusNormal,
- borderWidth: 1,
- borderColor: theme.border,
- flexDirection: 'row',
- padding: 20,
- alignItems: 'center',
- },
-
- notFoundTextHeader: {
- ...headlineFont,
- color: theme.heading,
- fontSize: variables.fontSizeXLarge,
- lineHeight: variables.lineHeightXXLarge,
- marginTop: 20,
- marginBottom: 8,
- textAlign: 'center',
- },
-
- blockingViewContainer: {
- paddingBottom: variables.contentHeaderHeight,
- },
-
- defaultModalContainer: {
- backgroundColor: theme.componentBG,
- borderColor: theme.transparent,
- },
-
- reportActionContextMenuMiniButton: {
- ...spacing.p1,
- ...spacing.mv1,
- ...spacing.mh1,
- ...{borderRadius: variables.buttonBorderRadius},
- },
-
- reportActionSystemMessageContainer: {
- marginLeft: 42,
- },
-
- reportDetailsTitleContainer: {
- ...flex.dFlex,
- ...flex.flexColumn,
- ...flex.alignItemsCenter,
- paddingHorizontal: 20,
- paddingBottom: 20,
- },
-
- reportDetailsRoomInfo: {
- ...flex.flex1,
- ...flex.dFlex,
- ...flex.flexColumn,
- ...flex.alignItemsCenter,
- },
-
- reportSettingsVisibilityText: {
- textTransform: 'capitalize',
- },
-
- settingsPageBackground: {
- flexDirection: 'column',
- width: '100%',
- flexGrow: 1,
- },
-
- settingsPageBody: {
- width: '100%',
- justifyContent: 'space-around',
- },
-
- twoFactorAuthSection: {
- backgroundColor: theme.appBG,
- padding: 0,
- },
-
- twoFactorAuthCodesBox: ({isExtraSmallScreenWidth, isSmallScreenWidth}) => {
- let paddingHorizontal = styles.ph9;
-
- if (isSmallScreenWidth) {
- paddingHorizontal = styles.ph4;
- }
-
- if (isExtraSmallScreenWidth) {
- paddingHorizontal = styles.ph2;
- }
-
- return {
- alignItems: 'center',
- justifyContent: 'center',
- backgroundColor: theme.highlightBG,
- paddingVertical: 28,
- borderRadius: 16,
- marginTop: 32,
- ...paddingHorizontal,
- };
- },
-
- twoFactorLoadingContainer: {
- alignItems: 'center',
- justifyContent: 'center',
- height: 210,
- },
-
- twoFactorAuthCodesContainer: {
- alignItems: 'center',
- justifyContent: 'center',
- flexDirection: 'row',
- flexWrap: 'wrap',
- gap: 12,
- },
-
- twoFactorAuthCode: {
- fontFamily: fontFamily.MONOSPACE,
- width: 112,
- textAlign: 'center',
- },
-
- twoFactorAuthCodesButtonsContainer: {
- flexDirection: 'row',
- justifyContent: 'center',
- gap: 12,
- marginTop: 20,
- flexWrap: 'wrap',
- },
-
- twoFactorAuthCodesButton: {
- minWidth: 112,
- },
-
- twoFactorAuthCopyCodeButton: {
- minWidth: 110,
- },
-
- anonymousRoomFooter: (isSmallSizeLayout) => ({
- flexDirection: isSmallSizeLayout ? 'column' : 'row',
- ...(!isSmallSizeLayout && {
- alignItems: 'center',
- justifyContent: 'space-between',
- }),
- padding: 20,
- backgroundColor: theme.cardBG,
- borderRadius: variables.componentBorderRadiusLarge,
- overflow: 'hidden',
- }),
- anonymousRoomFooterWordmarkAndLogoContainer: (isSmallSizeLayout) => ({
- flexDirection: 'row',
- alignItems: 'center',
- ...(isSmallSizeLayout && {
- justifyContent: 'space-between',
- marginTop: 16,
- }),
- }),
- anonymousRoomFooterLogo: {
- width: 88,
- marginLeft: 0,
- height: 20,
- },
- anonymousRoomFooterLogoTaglineText: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeMedium,
- color: theme.textLight,
- },
- signInButtonAvatar: {
- width: 80,
- },
-
- anonymousRoomFooterSignInButton: {
- width: 110,
- },
-
- roomHeaderAvatarSize: {
- height: variables.componentSizeLarge,
- width: variables.componentSizeLarge,
- },
-
- roomHeaderAvatar: {
- backgroundColor: theme.appBG,
- borderRadius: 100,
- borderColor: theme.componentBG,
- borderWidth: 4,
- },
-
- roomHeaderAvatarOverlay: {
- position: 'absolute',
- top: 0,
- right: 0,
- bottom: 0,
- left: 0,
- backgroundColor: theme.overlay,
- opacity: variables.overlayOpacity,
- borderRadius: 88,
- },
-
- rootNavigatorContainerStyles: (isSmallScreenWidth) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}),
- RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}),
-
- avatarInnerTextChat: {
- color: theme.textLight,
- fontSize: variables.fontSizeXLarge,
- fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
- textAlign: 'center',
- fontWeight: 'normal',
- position: 'absolute',
- width: 88,
- left: -16,
- },
-
- pageWrapper: {
- width: '100%',
- alignItems: 'center',
- padding: 20,
- },
-
- avatarSectionWrapper: {
- width: '100%',
- alignItems: 'center',
- paddingHorizontal: 20,
- paddingBottom: 20,
- },
-
- avatarSectionWrapperSkeleton: {
- width: '100%',
- paddingHorizontal: 20,
- paddingBottom: 20,
- },
-
- selectCircle: {
- width: variables.componentSizeSmall,
- height: variables.componentSizeSmall,
- borderColor: theme.border,
- borderWidth: 1,
- borderRadius: variables.componentSizeSmall / 2,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: theme.componentBG,
- marginLeft: 8,
- },
-
- unreadIndicatorContainer: {
- position: 'absolute',
- top: -10,
- left: 0,
- width: '100%',
- height: 20,
- paddingHorizontal: 20,
- flexDirection: 'row',
- alignItems: 'center',
- zIndex: 1,
- ...cursor.cursorDefault,
- },
-
- unreadIndicatorLine: {
- height: 1,
- backgroundColor: theme.unreadIndicator,
- flexGrow: 1,
- marginRight: 8,
- opacity: 0.5,
- },
-
- threadDividerLine: {
- height: 1,
- backgroundColor: theme.border,
- flexGrow: 1,
- marginHorizontal: 20,
- },
-
- unreadIndicatorText: {
- color: theme.unreadIndicator,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontSize: variables.fontSizeSmall,
- fontWeight: fontWeightBold,
- textTransform: 'capitalize',
- },
-
- flipUpsideDown: {
- transform: [{rotate: '180deg'}],
- },
-
- navigationScreenCardStyle: {
- backgroundColor: theme.appBG,
- height: '100%',
- },
-
- invisible: {
- position: 'absolute',
- opacity: 0,
- },
-
- invisiblePopover: {
- position: 'absolute',
- opacity: 0,
- left: -9999,
- },
-
- containerWithSpaceBetween: {
- justifyContent: 'space-between',
- width: '100%',
- flex: 1,
- },
-
- detailsPageSectionContainer: {
- alignSelf: 'flex-start',
- },
-
- attachmentCarouselContainer: {
- height: '100%',
- width: '100%',
- display: 'flex',
- justifyContent: 'center',
- ...cursor.cursorUnset,
- },
-
- attachmentArrow: {
- zIndex: 23,
- position: 'absolute',
- },
-
- attachmentRevealButtonContainer: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- ...spacing.ph4,
- },
-
- arrowIcon: {
- height: 40,
- width: 40,
- alignItems: 'center',
- paddingHorizontal: 0,
- paddingTop: 0,
- paddingBottom: 0,
- },
-
- switchTrack: {
- width: 50,
- height: 28,
- justifyContent: 'center',
- borderRadius: 20,
- padding: 15,
- backgroundColor: theme.success,
- },
-
- switchInactive: {
- backgroundColor: theme.border,
- },
-
- switchThumb: {
- width: 22,
- height: 22,
- borderRadius: 11,
- position: 'absolute',
- left: 4,
- backgroundColor: theme.appBG,
- },
-
- switchThumbTransformation: (translateX) => ({
- transform: [{translateX}],
- }),
-
- radioButtonContainer: {
- backgroundColor: theme.componentBG,
- borderRadius: 10,
- height: 20,
- width: 20,
- borderColor: theme.icon,
- borderWidth: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
-
- checkedContainer: {
- backgroundColor: theme.checkBox,
- },
-
- magicCodeInputContainer: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- minHeight: variables.inputHeight,
- },
-
- magicCodeInput: {
- fontSize: variables.fontSizeXLarge,
- color: theme.heading,
- lineHeight: variables.inputHeight,
- },
-
- // Manually style transparent, in iOS Safari, an input in a container with its opacity set to
- // 0 (completely transparent) cannot handle user interaction, hence the Paste option is never shown
- inputTransparent: {
- color: 'transparent',
- // These properties are available in browser only
- ...(Browser.getBrowser()
- ? {
- caretColor: 'transparent',
- WebkitTextFillColor: 'transparent',
- // After setting the input text color to transparent, it acquires the background-color.
- // However, it is not possible to override the background-color directly as explained in this resource: https://developer.mozilla.org/en-US/docs/Web/CSS/:autofill
- // Therefore, the transition effect needs to be delayed.
- transitionDelay: '99999s',
- transitionProperty: 'background-color',
- }
- : {}),
- },
-
- iouAmountText: {
- ...headlineFont,
- fontSize: variables.iouAmountTextSize,
- color: theme.heading,
- lineHeight: variables.inputHeight,
- },
-
- iouAmountTextInput: addOutlineWidth(
- {
- ...headlineFont,
- fontSize: variables.iouAmountTextSize,
- color: theme.heading,
- padding: 0,
- lineHeight: undefined,
- },
- 0,
- ),
-
- moneyRequestConfirmationAmount: {
- ...headlineFont,
- fontSize: variables.fontSizeh1,
- },
-
- moneyRequestMenuItem: {
- flexDirection: 'row',
- borderRadius: 0,
- justifyContent: 'space-between',
- width: '100%',
- paddingHorizontal: 20,
- paddingVertical: 12,
- },
-
- requestPreviewBox: {
- marginTop: 12,
- maxWidth: variables.sideBarWidth,
- },
-
- moneyRequestPreviewBox: {
- backgroundColor: theme.cardBG,
- borderRadius: variables.componentBorderRadiusLarge,
- maxWidth: variables.sideBarWidth,
- width: '100%',
- },
-
- moneyRequestPreviewBoxText: {
- padding: 16,
- },
-
- amountSplitPadding: {
- paddingTop: 2,
- },
-
- moneyRequestPreviewBoxLoading: {
- // When a new IOU request arrives it is very briefly in a loading state, so set the minimum height of the container to 94 to match the rendered height after loading.
- // Otherwise, the IOU request pay button will not be fully visible and the user will have to scroll up to reveal the entire IOU request container.
- // See https://github.com/Expensify/App/issues/10283.
- minHeight: 94,
- width: '100%',
- },
-
- moneyRequestPreviewBoxAvatar: {
- marginRight: -10,
- marginBottom: 0,
- },
-
- moneyRequestPreviewAmount: {
- ...headlineFont,
- ...whiteSpace.preWrap,
- color: theme.heading,
- },
-
- defaultCheckmarkWrapper: {
- marginLeft: 8,
- alignSelf: 'center',
- },
-
- codeWordWrapper: {
- ...codeStyles.codeWordWrapper,
- },
-
- codeWordStyle: {
- borderLeftWidth: 0,
- borderRightWidth: 0,
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- paddingLeft: 0,
- paddingRight: 0,
- justifyContent: 'center',
- ...codeStyles.codeWordStyle,
- },
-
- codeFirstWordStyle: {
- borderLeftWidth: 1,
- borderTopLeftRadius: 4,
- borderBottomLeftRadius: 4,
- paddingLeft: 5,
- },
-
- codeLastWordStyle: {
- borderRightWidth: 1,
- borderTopRightRadius: 4,
- borderBottomRightRadius: 4,
- paddingRight: 5,
- },
-
- fullScreenLoading: {
- backgroundColor: theme.componentBG,
- opacity: 0.8,
- justifyContent: 'center',
- alignItems: 'center',
- zIndex: 10,
- },
-
- reimbursementAccountFullScreenLoading: {
- backgroundColor: theme.componentBG,
- opacity: 0.8,
- justifyContent: 'flex-start',
- alignItems: 'center',
- zIndex: 10,
- },
-
- hiddenElementOutsideOfWindow: {
- position: 'absolute',
- top: -10000,
- left: 0,
- opacity: 0,
- },
-
- growlNotificationWrapper: {
- zIndex: 2,
- },
-
- growlNotificationContainer: {
- flex: 1,
- justifyContent: 'flex-start',
- position: 'absolute',
- width: '100%',
- top: 20,
- ...spacing.pl5,
- ...spacing.pr5,
- },
-
- growlNotificationDesktopContainer: {
- maxWidth: variables.sideBarWidth,
- right: 0,
- position: 'fixed',
- },
-
- growlNotificationTranslateY: (y) => ({
- transform: [{translateY: y}],
- }),
-
- makeSlideInTranslation: (translationType, fromValue) => ({
- from: {
- [translationType]: fromValue,
- },
- to: {
- [translationType]: 0,
- },
- }),
-
- growlNotificationBox: {
- backgroundColor: theme.inverse,
- borderRadius: variables.componentBorderRadiusNormal,
- alignItems: 'center',
- flexDirection: 'row',
- justifyContent: 'space-between',
- shadowColor: theme.shadow,
- ...spacing.p5,
- },
-
- growlNotificationText: {
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE,
- width: '90%',
- lineHeight: variables.fontSizeNormalHeight,
- color: theme.textReversed,
- ...spacing.ml4,
- },
-
- blockquote: {
- borderLeftColor: theme.border,
- borderLeftWidth: 4,
- paddingLeft: 12,
- marginVertical: 4,
- },
-
- noSelect: {
- boxShadow: 'none',
- outlineStyle: 'none',
- },
-
- cardStyleNavigator: {
- overflow: 'hidden',
- height: '100%',
- },
-
- smallEditIcon: {
- alignItems: 'center',
- backgroundColor: theme.buttonHoveredBG,
- borderColor: theme.textReversed,
- borderRadius: 14,
- borderWidth: 3,
- color: theme.textReversed,
- height: 28,
- width: 28,
- justifyContent: 'center',
- },
-
- smallAvatarEditIcon: {
- position: 'absolute',
- right: -4,
- bottom: -4,
- },
-
- autoGrowHeightMultilineInput: {
- maxHeight: 115,
- },
-
- peopleRow: {
- width: '100%',
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- ...spacing.ph5,
- },
-
- peopleRowBorderBottom: {
- borderColor: theme.border,
- borderBottomWidth: 1,
- ...spacing.pb2,
- },
-
- peopleBadge: {
- backgroundColor: theme.icon,
- ...spacing.ph3,
- },
-
- peopleBadgeText: {
- color: theme.textReversed,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightNormal,
- ...whiteSpace.noWrap,
- },
-
- offlineFeedback: {
- deleted: {
- textDecorationLine: 'line-through',
- textDecorationStyle: 'solid',
- },
- pending: {
- opacity: 0.5,
- },
- error: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- container: {
- ...spacing.pv2,
- },
- textContainer: {
- flexDirection: 'column',
- flex: 1,
- },
- text: {
- color: theme.textSupporting,
- textAlignVertical: 'center',
- fontSize: variables.fontSizeLabel,
- },
- errorDot: {
- marginRight: 12,
- },
- },
-
- dotIndicatorMessage: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- },
-
- locationErrorLinkText: {
- textAlignVertical: 'center',
- fontSize: variables.fontSizeLabel,
- },
-
- sidebarPopover: {
- width: variables.sideBarWidth - 68,
- },
-
- cardOverlay: {
- backgroundColor: theme.overlay,
- position: 'absolute',
- top: 0,
- left: 0,
- width: '100%',
- height: '100%',
- opacity: variables.overlayOpacity,
- },
-
- shortTermsBorder: {
- borderWidth: 1,
- borderColor: theme.border,
- },
-
- shortTermsHorizontalRule: {
- borderBottomWidth: 1,
- borderColor: theme.border,
- ...spacing.mh3,
- },
-
- shortTermsLargeHorizontalRule: {
- borderWidth: 1,
- borderColor: theme.border,
- ...spacing.mh3,
- },
-
- shortTermsRow: {
- flexDirection: 'row',
- padding: 12,
- },
-
- termsCenterRight: {
- marginTop: 'auto',
- marginBottom: 'auto',
- },
-
- shortTermsBoldHeadingSection: {
- paddingRight: 12,
- paddingLeft: 12,
- marginTop: 12,
- },
-
- shortTermsHeadline: {
- ...headlineFont,
- ...whiteSpace.preWrap,
- color: theme.heading,
- fontSize: variables.fontSizeXXXLarge,
- lineHeight: variables.lineHeightXXXLarge,
- },
-
- longTermsRow: {
- flexDirection: 'row',
- marginTop: 20,
- },
-
- collapsibleSectionBorder: {
- borderBottomWidth: 2,
- borderBottomColor: theme.border,
- },
-
- communicationsLinkHeight: {
- height: variables.communicationsLinkHeight,
- },
-
- floatingMessageCounterWrapper: {
- position: 'absolute',
- left: '50%',
- top: 0,
- zIndex: 100,
- ...visibility.hidden,
- },
-
- floatingMessageCounterWrapperAndroid: {
- left: 0,
- width: '100%',
- alignItems: 'center',
- position: 'absolute',
- top: 0,
- zIndex: 100,
- ...visibility.hidden,
- },
-
- floatingMessageCounterSubWrapperAndroid: {
- left: '50%',
- width: 'auto',
- },
-
- floatingMessageCounter: {
- left: '-50%',
- ...visibility.visible,
- },
-
- floatingMessageCounterTransformation: (translateY) => ({
- transform: [{translateY}],
- }),
-
- confirmationAnimation: {
- height: 180,
- width: 180,
- marginBottom: 20,
- },
-
- googleSearchTextInputContainer: {
- flexDirection: 'column',
- },
-
- googleSearchSeparator: {
- height: 1,
- backgroundColor: theme.border,
- },
-
- googleSearchText: {
- color: theme.text,
- fontSize: variables.fontSizeNormal,
- lineHeight: variables.fontSizeNormalHeight,
- fontFamily: fontFamily.EXP_NEUE,
- flex: 1,
- },
-
- threeDotsPopoverOffset: (windowWidth) => ({
- ...getPopOverVerticalOffset(60),
- horizontal: windowWidth - 60,
- }),
-
- threeDotsPopoverOffsetNoCloseButton: (windowWidth) => ({
- ...getPopOverVerticalOffset(60),
- horizontal: windowWidth - 10,
- }),
-
- threeDotsPopoverOffsetAttachmentModal: (windowWidth) => ({
- ...getPopOverVerticalOffset(80),
- horizontal: windowWidth - 140,
- }),
-
- iPhoneXSafeArea: {
- backgroundColor: theme.inverse,
- flex: 1,
- },
-
- transferBalancePayment: {
- borderWidth: 1,
- borderRadius: variables.componentBorderRadiusNormal,
- borderColor: theme.border,
- },
-
- transferBalanceSelectedPayment: {
- borderColor: theme.iconSuccessFill,
- },
-
- transferBalanceBalance: {
- fontSize: 48,
- },
-
- imageCropContainer: {
- overflow: 'hidden',
- alignItems: 'center',
- justifyContent: 'center',
- backgroundColor: theme.imageCropBackgroundColor,
- ...cursor.cursorMove,
- },
-
- sliderKnobTooltipView: {
- height: variables.sliderKnobSize,
- width: variables.sliderKnobSize,
- borderRadius: variables.sliderKnobSize / 2,
- },
-
- sliderKnob: {
- backgroundColor: theme.success,
- position: 'absolute',
- height: variables.sliderKnobSize,
- width: variables.sliderKnobSize,
- borderRadius: variables.sliderKnobSize / 2,
- left: -(variables.sliderKnobSize / 2),
- ...cursor.cursorPointer,
- },
-
- sliderBar: {
- backgroundColor: theme.border,
- height: variables.sliderBarHeight,
- borderRadius: variables.sliderBarHeight / 2,
- alignSelf: 'stretch',
- justifyContent: 'center',
- },
-
- screenCenteredContainer: {
- flex: 1,
- justifyContent: 'center',
- marginBottom: 40,
- padding: 16,
- },
-
- inlineSystemMessage: {
- color: theme.textSupporting,
- fontSize: variables.fontSizeLabel,
- fontFamily: fontFamily.EXP_NEUE,
- marginLeft: 6,
- },
-
- fullScreen: {
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- },
-
- invisibleOverlay: {
- backgroundColor: theme.transparent,
- zIndex: 1000,
- },
-
- reportDropOverlay: {
- backgroundColor: theme.dropUIBG,
- zIndex: 2,
- },
-
- receiptDropOverlay: {
- backgroundColor: theme.receiptDropUIBG,
- zIndex: 2,
- },
-
- receiptImageWrapper: (receiptImageTopPosition) => ({
- position: 'absolute',
- top: receiptImageTopPosition,
- }),
-
- cardSection: {
- backgroundColor: theme.cardBG,
- borderRadius: variables.componentBorderRadiusCard,
- marginBottom: 20,
- marginHorizontal: 16,
- padding: 20,
- width: 'auto',
- textAlign: 'left',
- },
-
- cardSectionTitle: {
- lineHeight: variables.lineHeightXXLarge,
- },
-
- cardMenuItem: {
- paddingLeft: 8,
- paddingRight: 0,
- borderRadius: variables.buttonBorderRadius,
- height: variables.componentSizeLarge,
- alignItems: 'center',
- },
-
- archivedReportFooter: {
- borderRadius: variables.componentBorderRadius,
- ...wordBreak.breakWord,
- },
-
- deeplinkWrapperContainer: {
- padding: 20,
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- backgroundColor: theme.appBG,
- },
-
- deeplinkWrapperMessage: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- deeplinkWrapperFooter: {
- paddingTop: 80,
- paddingBottom: 45,
- },
-
- emojiReactionBubble: {
- borderRadius: 28,
- alignItems: 'center',
- justifyContent: 'center',
- flexDirection: 'row',
- alignSelf: 'flex-start',
- },
-
- emojiReactionListHeader: {
- marginTop: 8,
- paddingBottom: 20,
- borderBottomColor: theme.border,
- borderBottomWidth: 1,
- marginHorizontal: 20,
- },
- emojiReactionListHeaderBubble: {
- paddingVertical: 2,
- paddingHorizontal: 8,
- borderRadius: 28,
- backgroundColor: theme.border,
- alignItems: 'center',
- justifyContent: 'center',
- flexDirection: 'row',
- alignSelf: 'flex-start',
- marginRight: 4,
- },
-
- reactionListHeaderText: {
- color: theme.textSupporting,
- marginLeft: 8,
- alignSelf: 'center',
- },
-
- miniQuickEmojiReactionText: {
- fontSize: 15,
- lineHeight: 20,
- textAlignVertical: 'center',
- },
-
- emojiReactionBubbleText: {
- textAlignVertical: 'center',
- },
-
- reactionCounterText: {
- fontSize: 13,
- marginLeft: 4,
- fontWeight: 'bold',
- },
-
- fontColorReactionLabel: {
- color: theme.tooltipSupportingText,
- },
-
- reactionEmojiTitle: {
- fontSize: variables.iconSizeLarge,
- lineHeight: variables.iconSizeXLarge,
- },
-
- textReactionSenders: {
- color: theme.tooltipPrimaryText,
- ...wordBreak.breakWord,
- },
-
- quickReactionsContainer: {
- gap: 12,
- flexDirection: 'row',
- paddingHorizontal: 25,
- paddingVertical: 12,
- justifyContent: 'space-between',
- },
-
- reactionListContainer: {
- maxHeight: variables.listItemHeightNormal * 5.75,
- ...spacing.pv2,
- },
-
- reactionListContainerFixedWidth: {
- maxWidth: variables.popoverWidth,
- },
-
- validateCodeDigits: {
- color: theme.text,
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeXXLarge,
- letterSpacing: 4,
- },
-
- footerWrapper: {
- fontSize: variables.fontSizeNormal,
- paddingTop: 64,
- maxWidth: 1100, // Match footer across all Expensify platforms
- },
-
- footerColumnsContainer: {
- flex: 1,
- flexWrap: 'wrap',
- marginBottom: 40,
- marginHorizontal: -16,
- },
-
- footerTitle: {
- fontSize: variables.fontSizeLarge,
- color: theme.success,
- marginBottom: 16,
- },
-
- footerRow: {
- paddingVertical: 4,
- marginBottom: 8,
- color: theme.textLight,
- fontSize: variables.fontSizeMedium,
- },
-
- footerBottomLogo: {
- marginTop: 40,
- width: '100%',
- },
-
- datePickerRoot: {
- position: 'relative',
- zIndex: 99,
- },
-
- datePickerPopover: {
- backgroundColor: theme.appBG,
- width: '100%',
- alignSelf: 'center',
- zIndex: 100,
- marginTop: 8,
- },
-
- loginHeroHeader: {
- fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
- color: theme.success,
- fontWeight: '500',
- textAlign: 'center',
- },
-
- newKansasLarge: {
- ...headlineFont,
- fontSize: variables.fontSizeXLarge,
- lineHeight: variables.lineHeightXXLarge,
- },
-
- eReceiptAmountLarge: {
- ...headlineFont,
- fontSize: variables.fontSizeEReceiptLarge,
- lineHeight: variables.lineHeightXXsLarge,
- wordBreak: 'break-word',
- textAlign: 'center',
- },
-
- eReceiptCurrency: {
- ...headlineFont,
- fontSize: variables.fontSizeXXLarge,
- lineHeight: variables.lineHeightXXLarge,
- wordBreak: 'break-all',
- },
-
- eReceiptMerchant: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeXLarge,
- lineHeight: variables.lineHeightXXLarge,
- color: theme.text,
- },
-
- eReceiptWaypointTitle: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- },
-
- eReceiptWaypointAddress: {
- fontFamily: fontFamily.MONOSPACE,
- fontSize: variables.fontSizeNormal,
- lineHeight: variables.lineHeightNormal,
- color: theme.textColorfulBackground,
- },
-
- eReceiptGuaranteed: {
- fontFamily: fontFamily.MONOSPACE,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightSmall,
- color: theme.textColorfulBackground,
- },
-
- eReceiptBackgroundThumbnail: {
- ...sizing.w100,
- position: 'absolute',
- aspectRatio: 335 / 540,
- top: 0,
- minWidth: 217,
- },
-
- eReceiptContainer: {
- flex: 1,
- width: 335,
- minHeight: 540,
- borderRadius: 20,
- overflow: 'hidden',
- },
-
- loginHeroBody: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeSignInHeroBody,
- color: theme.textLight,
- textAlign: 'center',
- },
-
- linkPreviewWrapper: {
- marginTop: 16,
- borderLeftWidth: 4,
- borderLeftColor: theme.border,
- paddingLeft: 12,
- },
-
- linkPreviewImage: {
- flex: 1,
- resizeMode: 'contain',
- borderRadius: 8,
- marginTop: 8,
- },
-
- linkPreviewLogoImage: {
- height: 16,
- width: 16,
- },
-
- contextMenuItemPopoverMaxWidth: {
- maxWidth: 375,
- },
-
- formSpaceVertical: {
- height: 20,
- width: 1,
- },
-
- taskCheckbox: {
- height: 16,
- width: 16,
- },
-
- taskTitleMenuItem: {
- ...writingDirection.ltr,
- ...headlineFont,
- ...spacing.flexWrap,
- ...spacing.flex1,
- fontSize: variables.fontSizeXLarge,
- maxWidth: '100%',
- ...wordBreak.breakWord,
- },
-
- taskDescriptionMenuItem: {
- maxWidth: '100%',
- ...wordBreak.breakWord,
- },
-
- taskTitleDescription: {
- fontFamily: fontFamily.EXP_NEUE,
- fontSize: variables.fontSizeLabel,
- color: theme.textSupporting,
- lineHeight: variables.lineHeightNormal,
- ...spacing.mb1,
- },
-
- taskMenuItemCheckbox: {
- height: 27,
- ...spacing.mr3,
- },
-
- reportHorizontalRule: {
- borderColor: theme.border,
- ...spacing.mh5,
- },
-
- assigneeTextStyle: {
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- minHeight: variables.avatarSizeSubscript,
- },
-
- taskRightIconContainer: {
- width: variables.componentSizeNormal,
- marginLeft: 'auto',
- ...spacing.mt1,
- ...pointerEventsAuto,
- ...spacing.dFlex,
- ...spacing.alignItemsCenter,
- },
-
- shareCodePage: {
- paddingHorizontal: 38.5,
- },
-
- shareCodeContainer: {
- width: '100%',
- alignItems: 'center',
- paddingHorizontal: variables.qrShareHorizontalPadding,
- paddingVertical: 20,
- borderRadius: 20,
- overflow: 'hidden',
- borderColor: theme.borderFocus,
- borderWidth: 2,
- backgroundColor: theme.highlightBG,
- },
-
- splashScreenHider: {
- backgroundColor: theme.splashBG,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- headerEnvBadge: {
- marginLeft: 0,
- marginBottom: 2,
- height: 12,
- paddingLeft: 4,
- paddingRight: 4,
- alignItems: 'center',
- },
-
- headerEnvBadgeText: {
- fontSize: 7,
- fontWeight: fontWeightBold,
- lineHeight: undefined,
- },
-
- expensifyQrLogo: {
- alignSelf: 'stretch',
- height: 27,
- marginBottom: 20,
- },
-
- qrShareTitle: {
- marginTop: 15,
- textAlign: 'center',
- },
-
- loginButtonRow: {
- width: '100%',
- gap: 12,
- ...flex.flexRow,
- ...flex.justifyContentCenter,
- },
-
- loginButtonRowSmallScreen: {
- width: '100%',
- gap: 12,
- ...flex.flexRow,
- ...flex.justifyContentCenter,
- marginBottom: 10,
- },
-
- desktopSignInButtonContainer: {
- width: 40,
- height: 40,
- },
-
- signInIconButton: {
- paddingVertical: 2,
- },
-
- googleButtonContainer: {
- colorScheme: 'light',
- width: 40,
- height: 40,
- alignItems: 'center',
- overflow: 'hidden',
- },
-
- googlePillButtonContainer: {
- colorScheme: 'light',
- height: 40,
- width: 219,
- },
-
- thirdPartyLoadingContainer: {
- alignItems: 'center',
- justifyContent: 'center',
- height: 450,
- },
-
- tabSelectorButton: {
- height: variables.tabSelectorButtonHeight,
- padding: variables.tabSelectorButtonPadding,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- borderRadius: variables.buttonBorderRadius,
- },
-
- tabSelector: {
- flexDirection: 'row',
- paddingHorizontal: 20,
- paddingBottom: 12,
- },
-
- tabText: (isSelected) => ({
- marginLeft: 8,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
- fontWeight: fontWeightBold,
- color: isSelected ? theme.textLight : theme.textSupporting,
- }),
-
- tabBackground: (hovered, isFocused, background) => ({
- backgroundColor: hovered && !isFocused ? theme.highlightBG : background,
- }),
-
- tabOpacity: (hovered, isFocused, activeOpacityValue, inactiveOpacityValue) => (hovered && !isFocused ? inactiveOpacityValue : activeOpacityValue),
-
- /**
- * @param {String} backgroundColor
- * @param {Number} height
- * @returns {Object}
- */
- overscrollSpacer: (backgroundColor, height) => ({
- backgroundColor,
- height,
- width: '100%',
- position: 'absolute',
- top: -height,
- left: 0,
- right: 0,
- }),
-
- dualColorOverscrollSpacer: {
- position: 'absolute',
- top: 0,
- left: 0,
- width: '100%',
- height: '100%',
- zIndex: -1,
- },
-
- willChangeTransform: {
- willChange: 'transform',
- },
-
- dropDownButtonCartIconContainerPadding: {
- paddingRight: 0,
- paddingLeft: 0,
- },
-
- dropDownButtonArrowContain: {
- marginLeft: 12,
- marginRight: 14,
- },
-
- dropDownButtonCartIconView: {
- borderTopRightRadius: variables.buttonBorderRadius,
- borderBottomRightRadius: variables.buttonBorderRadius,
- ...flex.flexRow,
- ...flex.alignItemsCenter,
- },
-
- emojiPickerButtonDropdown: {
- justifyContent: 'center',
- backgroundColor: theme.activeComponentBG,
- width: 86,
- height: 52,
- borderRadius: 26,
- alignItems: 'center',
- paddingLeft: 10,
- paddingRight: 4,
- marginBottom: 32,
- alignSelf: 'flex-start',
- },
-
- emojiPickerButtonDropdownIcon: {
- fontSize: 30,
- },
-
- moneyRequestImage: {
- height: 200,
- borderRadius: 16,
- margin: 20,
- },
-
- reportPreviewBox: {
- backgroundColor: theme.cardBG,
- borderRadius: variables.componentBorderRadiusLarge,
- maxWidth: variables.sideBarWidth,
- width: '100%',
- },
-
- reportPreviewBoxHoverBorder: {
- borderColor: theme.border,
- backgroundColor: theme.border,
- },
-
- reportContainerBorderRadius: {
- borderRadius: variables.componentBorderRadiusLarge,
- },
-
- reportPreviewBoxBody: {
- padding: 16,
- },
-
- reportActionItemImages: {
- flexDirection: 'row',
- borderWidth: 4,
- borderColor: theme.transparent,
- borderTopLeftRadius: variables.componentBorderRadiusLarge,
- borderTopRightRadius: variables.componentBorderRadiusLarge,
- borderBottomLeftRadius: variables.componentBorderRadiusLarge,
- borderBottomRightRadius: variables.componentBorderRadiusLarge,
- overflow: 'hidden',
- height: 200,
- },
-
- reportActionItemImage: {
- flex: 1,
- width: '100%',
- height: '100%',
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- },
-
- reportActionItemImageBorder: {
- borderRightWidth: 2,
- borderColor: theme.cardBG,
- },
-
- reportActionItemImagesMore: {
- position: 'absolute',
- borderRadius: 18,
- backgroundColor: theme.cardBG,
- width: 36,
- height: 36,
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- },
-
- moneyRequestHeaderStatusBarBadge: {
- paddingHorizontal: 8,
- borderRadius: variables.componentBorderRadiusSmall,
- height: variables.inputHeightSmall,
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: theme.border,
- marginRight: 12,
- },
-
- staticHeaderImage: {
- minHeight: 240,
- },
-
- emojiPickerButtonDropdownContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- },
-
- rotate90: {
- transform: [{rotate: '90deg'}],
- },
-
- emojiStatusLHN: {
- fontSize: 22,
- },
- sidebarStatusAvatarContainer: {
- height: 44,
- width: 84,
- backgroundColor: theme.componentBG,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- borderRadius: 42,
- paddingHorizontal: 2,
- marginVertical: -2,
- marginRight: -2,
- },
- sidebarStatusAvatar: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
-
- moneyRequestViewImage: {
- ...spacing.mh5,
- ...spacing.mv3,
- overflow: 'hidden',
- borderWidth: 2,
- borderColor: theme.cardBG,
- borderRadius: variables.componentBorderRadiusLarge,
- height: 200,
- maxWidth: 400,
- },
-
- mapViewContainer: {
- ...flex.flex1,
- ...spacing.p4,
- ...spacing.flex1,
- minHeight: 300,
- maxHeight: 500,
- },
-
- mapView: {
- flex: 1,
- borderRadius: 16,
- overflow: 'hidden',
- },
-
- mapViewOverlay: {
- flex: 1,
- position: 'absolute',
- left: 0,
- top: 0,
- borderRadius: variables.componentBorderRadiusLarge,
- overflow: 'hidden',
- backgroundColor: theme.highlightBG,
- ...sizing.w100,
- ...sizing.h100,
- },
-
- confirmationListMapItem: {
- ...spacing.mv2,
- ...spacing.mh5,
- height: 200,
- },
-
- mapDirection: {
- lineColor: theme.success,
- lineWidth: 7,
- },
-
- mapDirectionLayer: {
- layout: {'line-join': 'round', 'line-cap': 'round'},
- paint: {'line-color': theme.success, 'line-width': 7},
- },
-
- mapPendingView: {
- backgroundColor: theme.highlightBG,
- ...flex.flex1,
- borderRadius: variables.componentBorderRadiusLarge,
- },
- userReportStatusEmoji: {
- flexShrink: 0,
- fontSize: variables.fontSizeNormal,
- marginRight: 4,
- },
- draggableTopBar: {
- height: 30,
- width: '100%',
- },
- videoContainer: {
- ...flex.flex1,
- ...flex.alignItemsCenter,
- ...flex.justifyContentCenter,
- ...objectFit.oFCover,
- },
-
- globalNavigation: {
- width: variables.globalNavigationWidth,
- backgroundColor: theme.highlightBG,
- },
-
- globalNavigationMenuContainer: {
- marginTop: 13,
- },
-
- globalAndSubNavigationContainer: {
- backgroundColor: theme.highlightBG,
- },
-
- globalNavigationSelectionIndicator: (isFocused) => ({
- width: 4,
- height: 52,
- borderTopRightRadius: variables.componentBorderRadiusRounded,
- borderBottomRightRadius: variables.componentBorderRadiusRounded,
- backgroundColor: isFocused ? theme.iconMenu : theme.transparent,
- }),
-
- globalNavigationMenuItem: (isFocused) => (isFocused ? {color: theme.text, fontWeight: fontWeightBold, fontFamily: fontFamily.EXP_NEUE_BOLD} : {color: theme.icon}),
-
- globalNavigationItemContainer: {
- width: variables.globalNavigationWidth,
- height: variables.globalNavigationWidth,
- },
-
- walletCard: {
- borderRadius: variables.componentBorderRadiusLarge,
- position: 'relative',
- alignSelf: 'center',
- overflow: 'hidden',
- },
-
- walletCardMenuItem: {
- color: theme.text,
- fontSize: variables.fontSizeNormal,
- },
-
- walletCardHolder: {
- position: 'absolute',
- left: 16,
- bottom: 16,
- width: variables.cardNameWidth,
- color: theme.text,
- fontSize: variables.fontSizeSmall,
- lineHeight: variables.lineHeightLarge,
- },
-
- aspectRatioLottie: (source) => {
- if (!source.uri && typeof source === 'object' && source.w && source.h) {
- return {aspectRatio: source.w / source.h};
- }
- return {};
- },
-
- receiptDropHeaderGap: {
- backgroundColor: theme.receiptDropUIBG,
- },
-
- checkboxWithLabelCheckboxStyle: {
- marginLeft: -2,
- },
-});
-
-// For now we need to export the styles function that takes the theme as an argument
-// as something named different than "styles", because a lot of files import the "defaultStyles"
-// as "styles", which causes ESLint to throw an error.
-// TODO: Remove "stylesGenerator" and instead only return "styles" once the app is migrated to theme switching hooks and HOCs and "styles/theme/default.js" is not used anywhere anymore (GH issue: https://github.com/Expensify/App/issues/27337)
-const stylesGenerator = styles;
-const defaultStyles = styles(defaultTheme);
-
-export default defaultStyles;
-export {stylesGenerator};
diff --git a/src/styles/styles.ts b/src/styles/styles.ts
new file mode 100644
index 000000000000..ba3c4d888858
--- /dev/null
+++ b/src/styles/styles.ts
@@ -0,0 +1,3979 @@
+/* eslint-disable @typescript-eslint/naming-convention */
+import {LineLayerStyleProps} from '@rnmapbox/maps/src/utils/MapboxStyles';
+import lodashClamp from 'lodash/clamp';
+import {LineLayer} from 'react-map-gl';
+import {AnimatableNumericValue, Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native';
+import {CustomAnimation} from 'react-native-animatable';
+import {PickerStyle} from 'react-native-picker-select';
+import {MixedStyleDeclaration, MixedStyleRecord} from 'react-native-render-html';
+import CONST from '../CONST';
+import * as Browser from '../libs/Browser';
+import addOutlineWidth from './addOutlineWidth';
+import codeStyles from './codeStyles';
+import fontFamily from './fontFamily';
+import fontWeightBold from './fontWeight/bold';
+import getPopOverVerticalOffset from './getPopOverVerticalOffset';
+import optionAlternateTextPlatformStyles from './optionAlternateTextPlatformStyles';
+import overflowXHidden from './overflowXHidden';
+import pointerEventsAuto from './pointerEventsAuto';
+import pointerEventsNone from './pointerEventsNone';
+import defaultTheme from './themes/default';
+import {ThemeDefault} from './themes/types';
+import cursor from './utilities/cursor';
+import display from './utilities/display';
+import flex from './utilities/flex';
+import overflow from './utilities/overflow';
+import positioning from './utilities/positioning';
+import sizing from './utilities/sizing';
+import spacing from './utilities/spacing';
+import textUnderline from './utilities/textUnderline';
+import userSelect from './utilities/userSelect';
+import visibility from './utilities/visibility';
+import whiteSpace from './utilities/whiteSpace';
+import wordBreak from './utilities/wordBreak';
+import writingDirection from './utilities/writingDirection';
+import variables from './variables';
+import colors from './colors';
+import objectFit from './utilities/objectFit';
+
+type AnchorPosition = {
+ horizontal: number;
+ vertical: number;
+};
+
+type WebViewStyle = {
+ tagStyles: MixedStyleRecord;
+ baseFontStyle: MixedStyleDeclaration;
+};
+
+type CustomPickerStyle = PickerStyle & {icon?: ViewStyle};
+
+type OverlayStylesParams = {progress: Animated.AnimatedInterpolation};
+
+type TwoFactorAuthCodesBoxParams = {isExtraSmallScreenWidth: boolean; isSmallScreenWidth: boolean};
+
+type Translation = 'perspective' | 'rotate' | 'rotateX' | 'rotateY' | 'rotateZ' | 'scale' | 'scaleX' | 'scaleY' | 'translateX' | 'translateY' | 'skewX' | 'skewY' | 'matrix';
+
+type OfflineFeedbackStyle = Record<'deleted' | 'pending' | 'error' | 'container' | 'textContainer' | 'text' | 'errorDot', ViewStyle | TextStyle>;
+
+type MapDirectionStyle = Pick;
+
+type MapDirectionLayerStyle = Pick;
+
+type Styles = Record<
+ string,
+ | ViewStyle
+ | TextStyle
+ | ImageStyle
+ | WebViewStyle
+ | OfflineFeedbackStyle
+ | MapDirectionStyle
+ | MapDirectionLayerStyle
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ | ((...args: any[]) => ViewStyle | TextStyle | ImageStyle | AnchorPosition | CustomAnimation | CustomPickerStyle)
+>;
+
+// touchCallout is an iOS safari only property that controls the display of the callout information when you touch and hold a target
+const touchCalloutNone: Pick = Browser.isMobileSafari() ? {WebkitTouchCallout: 'none'} : {};
+// to prevent vertical text offset in Safari for badges, new lineHeight values have been added
+const lineHeightBadge: Pick = Browser.isSafari() ? {lineHeight: variables.lineHeightXSmall} : {lineHeight: variables.lineHeightNormal};
+
+const picker = (theme: ThemeDefault) =>
+ ({
+ backgroundColor: theme.transparent,
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeNormal,
+ lineHeight: variables.fontSizeNormalHeight,
+ paddingBottom: 8,
+ paddingTop: 23,
+ paddingLeft: 0,
+ paddingRight: 25,
+ height: variables.inputHeight,
+ borderWidth: 0,
+ textAlign: 'left',
+ } satisfies TextStyle);
+
+const link = (theme: ThemeDefault) =>
+ ({
+ color: theme.link,
+ textDecorationColor: theme.link,
+ fontFamily: fontFamily.EXP_NEUE,
+ } satisfies ViewStyle & MixedStyleDeclaration);
+
+const baseCodeTagStyles = (theme: ThemeDefault) =>
+ ({
+ borderWidth: 1,
+ borderRadius: 5,
+ borderColor: theme.border,
+ backgroundColor: theme.textBackground,
+ } satisfies ViewStyle & MixedStyleDeclaration);
+
+const headlineFont = {
+ fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
+ fontWeight: '500',
+} satisfies TextStyle;
+
+const webViewStyles = (theme: ThemeDefault) =>
+ ({
+ // As of react-native-render-html v6, don't declare distinct styles for
+ // custom renderers, the API for custom renderers has changed. Declare the
+ // styles in the below "tagStyles" instead. If you need to reuse those
+ // styles from the renderer, just pass the "style" prop to the underlying
+ // component.
+ tagStyles: {
+ em: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontStyle: 'italic',
+ },
+
+ del: {
+ textDecorationLine: 'line-through',
+ textDecorationStyle: 'solid',
+ },
+
+ strong: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontWeight: 'bold',
+ },
+
+ a: link(theme),
+
+ ul: {
+ maxWidth: '100%',
+ },
+
+ ol: {
+ maxWidth: '100%',
+ },
+
+ li: {
+ flexShrink: 1,
+ },
+
+ blockquote: {
+ borderLeftColor: theme.border,
+ borderLeftWidth: 4,
+ paddingLeft: 12,
+ marginTop: 4,
+ marginBottom: 4,
+
+ // Overwrite default HTML margin for blockquotes
+ marginLeft: 0,
+ },
+
+ pre: {
+ ...baseCodeTagStyles(theme),
+ paddingTop: 12,
+ paddingBottom: 12,
+ paddingRight: 8,
+ paddingLeft: 8,
+ fontFamily: fontFamily.MONOSPACE,
+ marginTop: 0,
+ marginBottom: 0,
+ },
+
+ code: {
+ ...baseCodeTagStyles(theme),
+ ...(codeStyles.codeTextStyle as MixedStyleDeclaration),
+ paddingLeft: 5,
+ paddingRight: 5,
+ fontFamily: fontFamily.MONOSPACE,
+ fontSize: 13,
+ },
+
+ img: {
+ borderColor: theme.border,
+ borderRadius: variables.componentBorderRadiusNormal,
+ borderWidth: 1,
+ ...touchCalloutNone,
+ },
+
+ p: {
+ marginTop: 0,
+ marginBottom: 0,
+ },
+ h1: {
+ fontSize: variables.fontSizeLarge,
+ marginBottom: 8,
+ },
+ },
+
+ baseFontStyle: {
+ color: theme.text,
+ fontSize: variables.fontSizeNormal,
+ fontFamily: fontFamily.EXP_NEUE,
+ flex: 1,
+ lineHeight: variables.fontSizeNormalHeight,
+ ...writingDirection.ltr,
+ },
+ } satisfies WebViewStyle);
+
+const styles = (theme: ThemeDefault) =>
+ ({
+ // Add all of our utility and helper styles
+ ...spacing,
+ ...sizing,
+ ...flex,
+ ...display,
+ ...overflow,
+ ...positioning,
+ ...wordBreak,
+ ...whiteSpace,
+ ...writingDirection,
+ ...cursor,
+ ...userSelect,
+ ...textUnderline,
+ ...objectFit,
+
+ autoCompleteSuggestionsContainer: {
+ backgroundColor: theme.appBG,
+ borderRadius: 8,
+ borderWidth: 1,
+ borderColor: theme.border,
+ justifyContent: 'center',
+ boxShadow: variables.popoverMenuShadow,
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ paddingVertical: CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTER_INNER_PADDING,
+ },
+
+ autoCompleteSuggestionContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+
+ emojiSuggestionsEmoji: {
+ fontSize: variables.fontSizeMedium,
+ width: 51,
+ textAlign: 'center',
+ },
+ emojiSuggestionsText: {
+ fontSize: variables.fontSizeMedium,
+ flex: 1,
+ ...wordBreak.breakWord,
+ ...spacing.pr4,
+ },
+
+ mentionSuggestionsAvatarContainer: {
+ width: 24,
+ height: 24,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ mentionSuggestionsText: {
+ fontSize: variables.fontSizeMedium,
+ ...spacing.ml2,
+ },
+
+ mentionSuggestionsDisplayName: {
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ },
+
+ mentionSuggestionsHandle: {
+ color: theme.textSupporting,
+ },
+
+ webViewStyles: webViewStyles(theme),
+
+ link: link(theme),
+
+ linkMuted: {
+ color: theme.textSupporting,
+ textDecorationColor: theme.textSupporting,
+ fontFamily: fontFamily.EXP_NEUE,
+ },
+
+ linkMutedHovered: {
+ color: theme.textMutedReversed,
+ },
+
+ highlightBG: {
+ backgroundColor: theme.highlightBG,
+ },
+
+ appBG: {
+ backgroundColor: theme.appBG,
+ },
+
+ h4: {
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeLabel,
+ fontWeight: fontWeightBold,
+ },
+
+ textAlignCenter: {
+ textAlign: 'center',
+ },
+
+ textAlignRight: {
+ textAlign: 'right',
+ },
+
+ textAlignLeft: {
+ textAlign: 'left',
+ },
+
+ textUnderline: {
+ textDecorationLine: 'underline',
+ },
+
+ label: {
+ fontSize: variables.fontSizeLabel,
+ lineHeight: variables.lineHeightLarge,
+ },
+
+ textLabel: {
+ color: theme.text,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: variables.lineHeightLarge,
+ },
+
+ mutedTextLabel: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: variables.lineHeightLarge,
+ },
+
+ textMicro: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ },
+
+ textMicroBold: {
+ color: theme.text,
+ fontWeight: fontWeightBold,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ },
+
+ textMicroSupporting: {
+ color: theme.textSupporting,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ },
+
+ textExtraSmallSupporting: {
+ color: theme.textSupporting,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeExtraSmall,
+ },
+
+ textNormal: {
+ fontSize: variables.fontSizeNormal,
+ },
+
+ textLarge: {
+ fontSize: variables.fontSizeLarge,
+ },
+
+ textXLarge: {
+ fontSize: variables.fontSizeXLarge,
+ },
+
+ textXXLarge: {
+ fontSize: variables.fontSizeXXLarge,
+ },
+
+ textXXXLarge: {
+ fontSize: variables.fontSizeXXXLarge,
+ },
+
+ textHero: {
+ fontSize: variables.fontSizeHero,
+ fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
+ lineHeight: variables.lineHeightHero,
+ },
+
+ textStrong: {
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ },
+
+ textItalic: {
+ fontFamily: fontFamily.EXP_NEUE_ITALIC,
+ fontStyle: 'italic',
+ },
+
+ textHeadline: {
+ ...headlineFont,
+ ...whiteSpace.preWrap,
+ color: theme.heading,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ },
+
+ textHeadlineH1: {
+ ...headlineFont,
+ ...whiteSpace.preWrap,
+ color: theme.heading,
+ fontSize: variables.fontSizeh1,
+ lineHeight: variables.lineHeightSizeh1,
+ },
+
+ textDecorationNoLine: {
+ textDecorationLine: 'none',
+ },
+
+ textWhite: {
+ color: theme.textLight,
+ },
+
+ textBlue: {
+ color: theme.link,
+ },
+
+ textUppercase: {
+ textTransform: 'uppercase',
+ },
+
+ textNoWrap: {
+ ...whiteSpace.noWrap,
+ },
+
+ colorReversed: {
+ color: theme.textReversed,
+ },
+
+ colorMutedReversed: {
+ color: theme.textMutedReversed,
+ },
+
+ colorMuted: {
+ color: theme.textSupporting,
+ },
+
+ bgTransparent: {
+ backgroundColor: 'transparent',
+ },
+
+ bgDark: {
+ backgroundColor: theme.inverse,
+ },
+
+ opacity0: {
+ opacity: 0,
+ },
+
+ opacity1: {
+ opacity: 1,
+ },
+
+ textDanger: {
+ color: theme.danger,
+ },
+
+ borderRadiusNormal: {
+ borderRadius: variables.buttonBorderRadius,
+ },
+
+ button: {
+ backgroundColor: theme.buttonDefaultBG,
+ borderRadius: variables.buttonBorderRadius,
+ minHeight: variables.componentSizeLarge,
+ justifyContent: 'center',
+ ...spacing.ph3,
+ },
+
+ buttonContainer: {
+ padding: 1,
+ borderRadius: variables.buttonBorderRadius,
+ },
+
+ buttonText: {
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeNormal,
+ fontWeight: fontWeightBold,
+ textAlign: 'center',
+ flexShrink: 1,
+
+ // It is needed to unset the Lineheight. We don't need it for buttons as button always contains single line of text.
+ // It allows to vertically center the text.
+ lineHeight: undefined,
+
+ // Add 1px to the Button text to give optical vertical alignment.
+ paddingBottom: 1,
+ },
+
+ buttonSmall: {
+ borderRadius: variables.buttonBorderRadius,
+ minHeight: variables.componentSizeSmall,
+ paddingTop: 4,
+ paddingHorizontal: 14,
+ paddingBottom: 4,
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
+ buttonMedium: {
+ borderRadius: variables.buttonBorderRadius,
+ minHeight: variables.componentSizeNormal,
+ paddingTop: 12,
+ paddingRight: 16,
+ paddingBottom: 12,
+ paddingLeft: 16,
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
+ buttonLarge: {
+ borderRadius: variables.buttonBorderRadius,
+ minHeight: variables.componentSizeLarge,
+ paddingTop: 8,
+ paddingRight: 10,
+ paddingBottom: 8,
+ paddingLeft: 18,
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
+ buttonSmallText: {
+ fontSize: variables.fontSizeSmall,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ textAlign: 'center',
+ },
+
+ buttonMediumText: {
+ fontSize: variables.fontSizeLabel,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ textAlign: 'center',
+ },
+
+ buttonLargeText: {
+ fontSize: variables.fontSizeNormal,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ textAlign: 'center',
+ },
+
+ buttonDefaultHovered: {
+ backgroundColor: theme.buttonHoveredBG,
+ borderWidth: 0,
+ },
+
+ buttonSuccess: {
+ backgroundColor: theme.success,
+ borderWidth: 0,
+ },
+
+ buttonOpacityDisabled: {
+ opacity: 0.5,
+ },
+
+ buttonSuccessHovered: {
+ backgroundColor: theme.successHover,
+ borderWidth: 0,
+ },
+
+ buttonDanger: {
+ backgroundColor: theme.danger,
+ borderWidth: 0,
+ },
+
+ buttonDangerHovered: {
+ backgroundColor: theme.dangerHover,
+ borderWidth: 0,
+ },
+
+ buttonDisabled: {
+ backgroundColor: theme.buttonDefaultBG,
+ borderWidth: 0,
+ },
+
+ buttonDivider: {
+ height: variables.dropDownButtonDividerHeight,
+ borderWidth: 0.7,
+ borderColor: theme.text,
+ },
+
+ noBorderRadius: {
+ borderRadius: 0,
+ },
+
+ noRightBorderRadius: {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ },
+
+ noLeftBorderRadius: {
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ },
+
+ buttonCTA: {
+ paddingVertical: 6,
+ ...spacing.mh4,
+ },
+
+ buttonCTAIcon: {
+ marginRight: 22,
+
+ // Align vertically with the Button text
+ paddingBottom: 1,
+ paddingTop: 1,
+ },
+
+ buttonConfirm: {
+ margin: 20,
+ },
+
+ attachmentButtonBigScreen: {
+ minWidth: 300,
+ alignSelf: 'center',
+ },
+
+ buttonConfirmText: {
+ paddingLeft: 20,
+ paddingRight: 20,
+ },
+
+ buttonSuccessText: {
+ color: theme.textLight,
+ },
+
+ buttonDangerText: {
+ color: theme.textLight,
+ },
+
+ hoveredComponentBG: {
+ backgroundColor: theme.hoverComponentBG,
+ },
+
+ activeComponentBG: {
+ backgroundColor: theme.activeComponentBG,
+ },
+
+ touchableButtonImage: {
+ alignItems: 'center',
+ height: variables.componentSizeNormal,
+ justifyContent: 'center',
+ width: variables.componentSizeNormal,
+ },
+
+ visuallyHidden: {
+ ...visibility.hidden,
+ overflow: 'hidden',
+ width: 0,
+ height: 0,
+ },
+
+ visibilityHidden: {
+ ...visibility.hidden,
+ },
+
+ loadingVBAAnimation: {
+ width: 140,
+ height: 140,
+ },
+
+ pickerSmall: (backgroundColor = theme.highlightBG) =>
+ ({
+ inputIOS: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ paddingLeft: 0,
+ paddingRight: 17,
+ paddingTop: 6,
+ paddingBottom: 6,
+ borderWidth: 0,
+ color: theme.text,
+ height: 26,
+ opacity: 1,
+ backgroundColor: 'transparent',
+ },
+ done: {
+ color: theme.text,
+ },
+ doneDepressed: {
+ // Extracted from react-native-picker-select, src/styles.js
+ fontSize: 17,
+ },
+ modalViewMiddle: {
+ backgroundColor: theme.border,
+ borderTopWidth: 0,
+ },
+ modalViewBottom: {
+ backgroundColor: theme.highlightBG,
+ },
+ inputWeb: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ paddingLeft: 0,
+ paddingRight: 17,
+ paddingTop: 6,
+ paddingBottom: 6,
+ borderWidth: 0,
+ color: theme.text,
+ appearance: 'none',
+ height: 26,
+ opacity: 1,
+ backgroundColor,
+ ...cursor.cursorPointer,
+ },
+ inputAndroid: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ paddingLeft: 0,
+ paddingRight: 17,
+ paddingTop: 6,
+ paddingBottom: 6,
+ borderWidth: 0,
+ color: theme.text,
+ height: 26,
+ opacity: 1,
+ backgroundColor: 'transparent',
+ },
+ iconContainer: {
+ top: 7,
+ ...pointerEventsNone,
+ },
+ icon: {
+ width: variables.iconSizeExtraSmall,
+ height: variables.iconSizeExtraSmall,
+ },
+ } satisfies CustomPickerStyle),
+
+ badge: {
+ backgroundColor: theme.border,
+ borderRadius: 14,
+ height: variables.iconSizeNormal,
+ flexDirection: 'row',
+ paddingHorizontal: 7,
+ alignItems: 'center',
+ },
+
+ badgeSuccess: {
+ backgroundColor: theme.success,
+ },
+
+ badgeSuccessPressed: {
+ backgroundColor: theme.successHover,
+ },
+
+ badgeAdHocSuccess: {
+ backgroundColor: theme.badgeAdHoc,
+ },
+
+ badgeAdHocSuccessPressed: {
+ backgroundColor: theme.badgeAdHocHover,
+ },
+
+ badgeDanger: {
+ backgroundColor: theme.danger,
+ },
+
+ badgeDangerPressed: {
+ backgroundColor: theme.dangerPressed,
+ },
+
+ badgeText: {
+ color: theme.text,
+ fontSize: variables.fontSizeSmall,
+ ...lineHeightBadge,
+ ...whiteSpace.noWrap,
+ },
+
+ border: {
+ borderWidth: 1,
+ borderRadius: variables.componentBorderRadius,
+ borderColor: theme.border,
+ },
+
+ borderColorFocus: {
+ borderColor: theme.borderFocus,
+ },
+
+ borderColorDanger: {
+ borderColor: theme.danger,
+ },
+
+ textInputDisabled: {
+ // Adding disabled color theme to indicate user that the field is not editable.
+ backgroundColor: theme.highlightBG,
+ borderBottomWidth: 2,
+ borderColor: theme.borderLighter,
+ // Adding browser specefic style to bring consistency between Safari and other platforms.
+ // Applying the Webkit styles only to browsers as it is not available in native.
+ ...(Browser.getBrowser()
+ ? {
+ WebkitTextFillColor: theme.textSupporting,
+ WebkitOpacity: 1,
+ }
+ : {}),
+ color: theme.textSupporting,
+ },
+
+ uploadReceiptView: (isSmallScreenWidth: boolean) =>
+ ({
+ borderRadius: variables.componentBorderRadiusLarge,
+ borderWidth: isSmallScreenWidth ? 0 : 2,
+ borderColor: theme.borderFocus,
+ borderStyle: 'dotted',
+ marginBottom: 20,
+ marginLeft: 20,
+ marginRight: 20,
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingVertical: 40,
+ gap: 4,
+ flex: 1,
+ } satisfies ViewStyle),
+
+ receiptViewTextContainer: {
+ paddingHorizontal: 40,
+ ...sizing.w100,
+ },
+
+ cameraView: {
+ flex: 1,
+ overflow: 'hidden',
+ borderRadius: 28,
+ borderStyle: 'solid',
+ borderWidth: 8,
+ backgroundColor: theme.highlightBG,
+ borderColor: theme.appBG,
+ display: 'flex',
+ justifyContent: 'center',
+ justifyItems: 'center',
+ },
+
+ permissionView: {
+ paddingVertical: 108,
+ paddingHorizontal: 61,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ headerAnonymousFooter: {
+ color: theme.heading,
+ fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ },
+
+ headerText: {
+ color: theme.heading,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeNormal,
+ fontWeight: fontWeightBold,
+ },
+
+ headerGap: {
+ height: CONST.DESKTOP_HEADER_PADDING,
+ },
+
+ reportOptions: {
+ marginLeft: 8,
+ },
+
+ chatItemComposeSecondaryRow: {
+ height: CONST.CHAT_FOOTER_SECONDARY_ROW_HEIGHT,
+ marginBottom: CONST.CHAT_FOOTER_SECONDARY_ROW_PADDING,
+ marginTop: CONST.CHAT_FOOTER_SECONDARY_ROW_PADDING,
+ },
+
+ chatItemComposeSecondaryRowSubText: {
+ color: theme.textSupporting,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ },
+
+ chatItemComposeSecondaryRowOffset: {
+ marginLeft: variables.chatInputSpacing,
+ },
+
+ offlineIndicator: {
+ marginLeft: variables.chatInputSpacing,
+ },
+
+ offlineIndicatorMobile: {
+ paddingLeft: 20,
+ paddingTop: 5,
+ paddingBottom: 30,
+ marginBottom: -25,
+ },
+
+ offlineIndicatorRow: {
+ height: 25,
+ },
+
+ // Actions
+ actionAvatar: {
+ borderRadius: 20,
+ },
+
+ componentHeightLarge: {
+ height: variables.inputHeight,
+ },
+
+ calendarHeader: {
+ height: 50,
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ paddingHorizontal: 15,
+ paddingRight: 5,
+ ...userSelect.userSelectNone,
+ },
+
+ calendarDayRoot: {
+ flex: 1,
+ height: 45,
+ justifyContent: 'center',
+ alignItems: 'center',
+ ...userSelect.userSelectNone,
+ },
+
+ calendarDayContainer: {
+ width: 30,
+ height: 30,
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderRadius: 15,
+ overflow: 'hidden',
+ },
+
+ calendarDayContainerSelected: {
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
+ autoGrowHeightInputContainer: (textInputHeight: number, minHeight: number, maxHeight: number) =>
+ ({
+ height: lodashClamp(textInputHeight, minHeight, maxHeight),
+ minHeight,
+ } satisfies ViewStyle),
+
+ autoGrowHeightHiddenInput: (maxWidth: number, maxHeight?: number) =>
+ ({
+ maxWidth,
+ maxHeight: maxHeight && maxHeight + 1,
+ overflow: 'hidden',
+ } satisfies TextStyle),
+
+ textInputContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ height: '100%',
+ backgroundColor: 'transparent',
+ borderBottomWidth: 2,
+ borderColor: theme.border,
+ overflow: 'hidden',
+ },
+
+ textInputLabel: {
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ fontSize: variables.fontSizeNormal,
+ color: theme.textSupporting,
+ fontFamily: fontFamily.EXP_NEUE,
+ width: '100%',
+ },
+
+ textInputLabelBackground: {
+ position: 'absolute',
+ top: 0,
+ width: '100%',
+ height: 23,
+ backgroundColor: theme.componentBG,
+ },
+
+ textInputLabelDesktop: {
+ transformOrigin: 'left center',
+ },
+
+ textInputLabelTransformation: (translateY: AnimatableNumericValue, translateX: AnimatableNumericValue, scale: AnimatableNumericValue) =>
+ ({
+ transform: [{translateY}, {translateX}, {scale}],
+ } satisfies TextStyle),
+
+ baseTextInput: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeNormal,
+ lineHeight: variables.lineHeightXLarge,
+ color: theme.text,
+ paddingTop: 23,
+ paddingBottom: 8,
+ paddingLeft: 0,
+ borderWidth: 0,
+ },
+
+ textInputMultiline: {
+ scrollPadding: '23px 0 0 0',
+ },
+
+ textInputMultilineContainer: {
+ paddingTop: 23,
+ },
+
+ textInputAndIconContainer: {
+ flex: 1,
+ height: '100%',
+ zIndex: -1,
+ flexDirection: 'row',
+ },
+
+ textInputDesktop: addOutlineWidth({}, 0),
+
+ textInputIconContainer: {
+ paddingHorizontal: 11,
+ justifyContent: 'center',
+ margin: 1,
+ },
+
+ secureInput: {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ },
+
+ textInput: {
+ backgroundColor: 'transparent',
+ borderRadius: variables.componentBorderRadiusNormal,
+ height: variables.inputComponentSizeNormal,
+ borderColor: theme.border,
+ borderWidth: 1,
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeNormal,
+ paddingLeft: 12,
+ paddingRight: 12,
+ paddingTop: 10,
+ paddingBottom: 10,
+ textAlignVertical: 'center',
+ },
+
+ textInputPrefixWrapper: {
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ height: variables.inputHeight,
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingTop: 23,
+ paddingBottom: 8,
+ },
+
+ textInputPrefix: {
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeNormal,
+ textAlignVertical: 'center',
+ },
+
+ pickerContainer: {
+ borderBottomWidth: 2,
+ paddingLeft: 0,
+ borderStyle: 'solid',
+ borderColor: theme.border,
+ justifyContent: 'center',
+ backgroundColor: 'transparent',
+ height: variables.inputHeight,
+ overflow: 'hidden',
+ },
+
+ pickerContainerSmall: {
+ height: variables.inputHeightSmall,
+ },
+
+ pickerLabel: {
+ position: 'absolute',
+ left: 0,
+ top: 6,
+ zIndex: 1,
+ },
+
+ picker: (disabled = false, backgroundColor = theme.appBG) =>
+ ({
+ iconContainer: {
+ top: Math.round(variables.inputHeight * 0.5) - 11,
+ right: 0,
+ ...pointerEventsNone,
+ },
+
+ inputWeb: {
+ appearance: 'none',
+ ...(disabled ? cursor.cursorDisabled : cursor.cursorPointer),
+ ...picker(theme),
+ backgroundColor,
+ },
+
+ inputIOS: {
+ ...picker(theme),
+ },
+ done: {
+ color: theme.text,
+ },
+ doneDepressed: {
+ // Extracted from react-native-picker-select, src/styles.js
+ fontSize: 17,
+ },
+ modalViewMiddle: {
+ backgroundColor: theme.border,
+ borderTopWidth: 0,
+ },
+ modalViewBottom: {
+ backgroundColor: theme.highlightBG,
+ },
+
+ inputAndroid: {
+ ...picker(theme),
+ },
+ } satisfies CustomPickerStyle),
+
+ disabledText: {
+ color: theme.icon,
+ },
+
+ inputDisabled: {
+ backgroundColor: theme.highlightBG,
+ color: theme.icon,
+ },
+
+ noOutline: addOutlineWidth({}, 0),
+
+ textLabelSupporting: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeLabel,
+ color: theme.textSupporting,
+ },
+
+ textLabelError: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeLabel,
+ color: theme.textError,
+ },
+
+ textReceiptUpload: {
+ ...headlineFont,
+ fontSize: variables.fontSizeXLarge,
+ color: theme.textLight,
+ textAlign: 'center',
+ },
+
+ subTextReceiptUpload: {
+ fontFamily: fontFamily.EXP_NEUE,
+ lineHeight: variables.lineHeightLarge,
+ textAlign: 'center',
+ color: theme.textLight,
+ },
+
+ furtherDetailsText: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ color: theme.textSupporting,
+ },
+
+ lh16: {
+ lineHeight: 16,
+ },
+
+ lh20: {
+ lineHeight: 20,
+ },
+
+ lh140Percent: {
+ lineHeight: '140%',
+ },
+
+ formHelp: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: variables.lineHeightLarge,
+ marginBottom: 4,
+ },
+
+ formError: {
+ color: theme.textError,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: variables.formErrorLineHeight,
+ marginBottom: 4,
+ },
+
+ formSuccess: {
+ color: theme.success,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: 18,
+ marginBottom: 4,
+ },
+
+ signInPage: {
+ backgroundColor: theme.highlightBG,
+ minHeight: '100%',
+ flex: 1,
+ },
+
+ signInPageHeroCenter: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+
+ signInPageGradient: {
+ height: '100%',
+ width: 540,
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ },
+
+ signInPageGradientMobile: {
+ height: 300,
+ width: 800,
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ },
+
+ signInBackground: {
+ position: 'absolute',
+ bottom: 0,
+ left: 0,
+ minHeight: 700,
+ },
+
+ signInPageInner: {
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ height: '100%',
+ width: '100%',
+ },
+
+ signInPageContentTopSpacer: {
+ maxHeight: 132,
+ minHeight: 24,
+ },
+
+ signInPageContentTopSpacerSmallScreens: {
+ maxHeight: 132,
+ minHeight: 45,
+ },
+
+ signInPageLeftContainer: {
+ paddingLeft: 40,
+ paddingRight: 40,
+ },
+
+ signInPageLeftContainerWide: {
+ maxWidth: variables.sideBarWidth,
+ },
+
+ signInPageWelcomeFormContainer: {
+ maxWidth: CONST.SIGN_IN_FORM_WIDTH,
+ },
+
+ signInPageWelcomeTextContainer: {
+ width: CONST.SIGN_IN_FORM_WIDTH,
+ },
+
+ changeExpensifyLoginLinkContainer: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ ...wordBreak.breakWord,
+ },
+
+ // Sidebar Styles
+ sidebar: {
+ backgroundColor: theme.sidebar,
+ height: '100%',
+ },
+
+ sidebarHeaderContainer: {
+ flexDirection: 'row',
+ paddingHorizontal: 20,
+ paddingVertical: 19,
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+
+ subNavigationContainer: {
+ backgroundColor: theme.sidebar,
+ flex: 1,
+ borderTopLeftRadius: variables.componentBorderRadiusRounded,
+ },
+
+ sidebarAnimatedWrapperContainer: {
+ height: '100%',
+ position: 'absolute',
+ },
+
+ sidebarFooter: {
+ alignItems: 'center',
+ display: 'flex',
+ justifyContent: 'center',
+ paddingVertical: variables.lineHeightXLarge,
+ width: '100%',
+ },
+
+ sidebarAvatar: {
+ backgroundColor: theme.icon,
+ borderRadius: 20,
+ height: variables.componentSizeNormal,
+ width: variables.componentSizeNormal,
+ },
+
+ statusIndicator: (backgroundColor = theme.danger) =>
+ ({
+ borderColor: theme.sidebar,
+ backgroundColor,
+ borderRadius: 8,
+ borderWidth: 2,
+ position: 'absolute',
+ right: -2,
+ top: -1,
+ height: 16,
+ width: 16,
+ zIndex: 10,
+ } satisfies ViewStyle),
+
+ floatingActionButtonContainer: {
+ position: 'absolute',
+ left: 16,
+
+ // The bottom of the floating action button should align with the bottom of the compose box.
+ // The value should be equal to the height + marginBottom + marginTop of chatItemComposeSecondaryRow
+ bottom: 25,
+ },
+
+ floatingActionButton: {
+ backgroundColor: theme.success,
+ height: variables.componentSizeNormal,
+ width: variables.componentSizeNormal,
+ borderRadius: 999,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ sidebarFooterUsername: {
+ color: theme.heading,
+ fontSize: variables.fontSizeLabel,
+ fontWeight: '700',
+ width: 200,
+ textOverflow: 'ellipsis',
+ overflow: 'hidden',
+ ...whiteSpace.noWrap,
+ },
+
+ sidebarFooterLink: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeSmall,
+ textDecorationLine: 'none',
+ fontFamily: fontFamily.EXP_NEUE,
+ lineHeight: 20,
+ },
+
+ sidebarListContainer: {
+ scrollbarWidth: 'none',
+ paddingBottom: 4,
+ },
+
+ sidebarListItem: {
+ justifyContent: 'center',
+ textDecorationLine: 'none',
+ },
+
+ RHPNavigatorContainer: (isSmallScreenWidth: boolean) =>
+ ({
+ width: isSmallScreenWidth ? '100%' : variables.sideBarWidth,
+ position: 'absolute',
+ right: 0,
+ height: '100%',
+ } satisfies ViewStyle),
+
+ onlyEmojisText: {
+ fontSize: variables.fontSizeOnlyEmojis,
+ lineHeight: variables.fontSizeOnlyEmojisHeight,
+ },
+
+ onlyEmojisTextLineHeight: {
+ lineHeight: variables.fontSizeOnlyEmojisHeight,
+ },
+
+ createMenuPositionSidebar: (windowHeight: number) =>
+ ({
+ horizontal: 18,
+ vertical: windowHeight - 75,
+ } satisfies AnchorPosition),
+
+ createMenuPositionProfile: (windowWidth: number) =>
+ ({
+ horizontal: windowWidth - 355,
+ ...getPopOverVerticalOffset(162),
+ } satisfies AnchorPosition),
+
+ createMenuPositionReportActionCompose: (windowHeight: number) =>
+ ({
+ horizontal: 18 + variables.sideBarWidth,
+ vertical: windowHeight - 83,
+ } satisfies AnchorPosition),
+
+ createMenuPositionRightSidepane: {
+ right: 18,
+ bottom: 75,
+ },
+
+ createMenuContainer: {
+ width: variables.sideBarWidth - 40,
+ paddingVertical: 12,
+ },
+
+ createMenuHeaderText: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeLabel,
+ color: theme.heading,
+ },
+
+ popoverMenuItem: {
+ flexDirection: 'row',
+ borderRadius: 0,
+ paddingHorizontal: 20,
+ paddingVertical: 12,
+ justifyContent: 'space-between',
+ width: '100%',
+ },
+
+ popoverMenuIcon: {
+ width: variables.componentSizeNormal,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+
+ popoverMenuText: {
+ fontSize: variables.fontSizeNormal,
+ color: theme.heading,
+ },
+
+ popoverInnerContainer: {
+ paddingTop: 0, // adjusting this because the mobile modal adds additional padding that we don't need for our layout
+ maxHeight: '95%',
+ },
+
+ menuItemTextContainer: {
+ minHeight: variables.componentSizeNormal,
+ },
+
+ chatLinkRowPressable: {
+ minWidth: 0,
+ textDecorationLine: 'none',
+ flex: 1,
+ },
+
+ sidebarLink: {
+ textDecorationLine: 'none',
+ },
+
+ sidebarLinkLHN: {
+ textDecorationLine: 'none',
+ marginLeft: 12,
+ marginRight: 12,
+ borderRadius: 8,
+ },
+
+ sidebarLinkInner: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ paddingLeft: 20,
+ paddingRight: 20,
+ },
+
+ sidebarLinkInnerLHN: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ paddingLeft: 8,
+ paddingRight: 8,
+ },
+
+ sidebarLinkText: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeNormal,
+ textDecorationLine: 'none',
+ overflow: 'hidden',
+ },
+
+ sidebarLinkHover: {
+ backgroundColor: theme.sidebarHover,
+ },
+
+ sidebarLinkHoverLHN: {
+ backgroundColor: theme.highlightBG,
+ },
+
+ sidebarLinkActive: {
+ backgroundColor: theme.border,
+ textDecorationLine: 'none',
+ },
+
+ sidebarLinkActiveLHN: {
+ backgroundColor: theme.highlightBG,
+ textDecorationLine: 'none',
+ },
+
+ sidebarLinkTextBold: {
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ color: theme.heading,
+ },
+
+ sidebarLinkActiveText: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeNormal,
+ textDecorationLine: 'none',
+ overflow: 'hidden',
+ },
+
+ optionItemAvatarNameWrapper: {
+ minWidth: 0,
+ flex: 1,
+ },
+
+ optionDisplayName: {
+ fontFamily: fontFamily.EXP_NEUE,
+ minHeight: variables.alternateTextHeight,
+ lineHeight: variables.lineHeightXLarge,
+ ...whiteSpace.noWrap,
+ },
+
+ optionDisplayNameCompact: {
+ minWidth: 'auto',
+ flexBasis: 'auto',
+ flexGrow: 0,
+ flexShrink: 1,
+ },
+
+ displayNameTooltipEllipsis: {
+ position: 'absolute',
+ opacity: 0,
+ right: 0,
+ bottom: 0,
+ },
+
+ optionAlternateText: {
+ minHeight: variables.alternateTextHeight,
+ lineHeight: variables.lineHeightXLarge,
+ },
+
+ optionAlternateTextCompact: {
+ flexShrink: 1,
+ flexGrow: 1,
+ flexBasis: 'auto',
+ ...optionAlternateTextPlatformStyles,
+ },
+
+ optionRow: {
+ minHeight: variables.optionRowHeight,
+ paddingTop: 12,
+ paddingBottom: 12,
+ },
+
+ optionRowSelected: {
+ backgroundColor: theme.activeComponentBG,
+ },
+
+ optionRowDisabled: {
+ color: theme.textSupporting,
+ },
+
+ optionRowCompact: {
+ height: variables.optionRowHeightCompact,
+ paddingTop: 12,
+ paddingBottom: 12,
+ },
+
+ optionsListSectionHeader: {
+ marginTop: 8,
+ marginBottom: 4,
+ },
+
+ overlayStyles: (current: OverlayStylesParams) =>
+ ({
+ ...positioning.pFixed,
+ // We need to stretch the overlay to cover the sidebar and the translate animation distance.
+ left: -2 * variables.sideBarWidth,
+ top: 0,
+ bottom: 0,
+ right: 0,
+ backgroundColor: theme.overlay,
+ opacity: current.progress.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, variables.overlayOpacity],
+ extrapolate: 'clamp',
+ }),
+ } satisfies ViewStyle),
+
+ appContent: {
+ backgroundColor: theme.appBG,
+ overflow: 'hidden',
+ },
+
+ appContentHeader: {
+ height: variables.contentHeaderHeight,
+ justifyContent: 'center',
+ display: 'flex',
+ paddingRight: 20,
+ },
+
+ appContentHeaderTitle: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ },
+
+ LHNToggle: {
+ alignItems: 'center',
+ height: variables.contentHeaderHeight,
+ justifyContent: 'center',
+ paddingRight: 10,
+ paddingLeft: 20,
+ },
+
+ LHNToggleIcon: {
+ height: 15,
+ width: 18,
+ },
+
+ chatContentScrollView: {
+ flexGrow: 1,
+ justifyContent: 'flex-start',
+ paddingBottom: 16,
+ },
+
+ // Chat Item
+ chatItem: {
+ display: 'flex',
+ flexDirection: 'row',
+ paddingTop: 8,
+ paddingBottom: 8,
+ paddingLeft: 20,
+ paddingRight: 20,
+ },
+
+ chatItemRightGrouped: {
+ flexGrow: 1,
+ flexShrink: 1,
+ flexBasis: 0,
+ position: 'relative',
+ marginLeft: variables.chatInputSpacing,
+ },
+
+ chatItemRight: {
+ flexGrow: 1,
+ flexShrink: 1,
+ flexBasis: 0,
+ position: 'relative',
+ },
+
+ chatItemMessageHeader: {
+ alignItems: 'center',
+ display: 'flex',
+ flexDirection: 'row',
+ flexWrap: 'nowrap',
+ },
+
+ chatItemMessageHeaderSender: {
+ color: theme.heading,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeNormal,
+ fontWeight: fontWeightBold,
+ lineHeight: variables.lineHeightXLarge,
+ ...wordBreak.breakWord,
+ },
+
+ chatItemMessageHeaderTimestamp: {
+ flexShrink: 0,
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeSmall,
+ paddingTop: 2,
+ },
+
+ chatItemMessage: {
+ color: theme.text,
+ fontSize: variables.fontSizeNormal,
+ fontFamily: fontFamily.EXP_NEUE,
+ lineHeight: variables.lineHeightXLarge,
+ maxWidth: '100%',
+ ...cursor.cursorAuto,
+ ...whiteSpace.preWrap,
+ ...wordBreak.breakWord,
+ },
+
+ renderHTMLTitle: {
+ color: theme.text,
+ fontSize: variables.fontSizeNormal,
+ fontFamily: fontFamily.EXP_NEUE,
+ lineHeight: variables.lineHeightXLarge,
+ maxWidth: '100%',
+ ...whiteSpace.preWrap,
+ ...wordBreak.breakWord,
+ },
+
+ chatItemComposeWithFirstRow: {
+ minHeight: 90,
+ },
+
+ chatItemFullComposeRow: {
+ ...sizing.h100,
+ },
+
+ chatItemComposeBoxColor: {
+ borderColor: theme.border,
+ },
+
+ chatItemComposeBoxFocusedColor: {
+ borderColor: theme.borderFocus,
+ },
+
+ chatItemComposeBox: {
+ backgroundColor: theme.componentBG,
+ borderWidth: 1,
+ borderRadius: variables.componentBorderRadiusRounded,
+ minHeight: variables.componentSizeMedium,
+ },
+
+ chatItemFullComposeBox: {
+ ...flex.flex1,
+ ...sizing.h100,
+ },
+
+ chatFooter: {
+ paddingLeft: 20,
+ paddingRight: 20,
+ display: 'flex',
+ backgroundColor: theme.appBG,
+ },
+
+ chatFooterFullCompose: {
+ flex: 1,
+ },
+
+ chatItemDraft: {
+ display: 'flex',
+ flexDirection: 'row',
+ paddingTop: 8,
+ paddingBottom: 8,
+ paddingLeft: 20,
+ paddingRight: 20,
+ },
+
+ chatItemReactionsDraftRight: {
+ marginLeft: 52,
+ },
+ chatFooterAtTheTop: {
+ flexGrow: 1,
+ justifyContent: 'flex-start',
+ },
+
+ // Be extremely careful when editing the compose styles, as it is easy to introduce regressions.
+ // Make sure you run the following tests against any changes: #12669
+ textInputCompose: addOutlineWidth(
+ {
+ backgroundColor: theme.componentBG,
+ borderColor: theme.border,
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeNormal,
+ borderWidth: 0,
+ height: 'auto',
+ lineHeight: variables.lineHeightXLarge,
+ ...overflowXHidden,
+
+ // On Android, multiline TextInput with height: 'auto' will show extra padding unless they are configured with
+ // paddingVertical: 0, alignSelf: 'center', and textAlignVertical: 'center'
+
+ paddingHorizontal: variables.avatarChatSpacing,
+ paddingTop: 0,
+ paddingBottom: 0,
+ alignSelf: 'center',
+ textAlignVertical: 'center',
+ },
+ 0,
+ ),
+
+ textInputFullCompose: {
+ alignSelf: 'stretch',
+ flex: 1,
+ maxHeight: '100%',
+ textAlignVertical: 'top',
+ },
+
+ // composer padding should not be modified unless thoroughly tested against the cases in this PR: #12669
+ textInputComposeSpacing: {
+ paddingVertical: 5,
+ ...flex.flexRow,
+ flex: 1,
+ },
+
+ textInputComposeBorder: {
+ borderLeftWidth: 1,
+ borderColor: theme.border,
+ },
+
+ chatItemSubmitButton: {
+ alignSelf: 'flex-end',
+ borderRadius: variables.componentBorderRadiusRounded,
+ backgroundColor: theme.transparent,
+ height: 40,
+ padding: 10,
+ margin: 3,
+ justifyContent: 'center',
+ },
+
+ emojiPickerContainer: {
+ backgroundColor: theme.componentBG,
+ },
+
+ emojiHeaderContainer: {
+ backgroundColor: theme.componentBG,
+ display: 'flex',
+ height: CONST.EMOJI_PICKER_HEADER_HEIGHT,
+ justifyContent: 'center',
+ width: '100%',
+ },
+
+ emojiSkinToneTitle: {
+ ...spacing.pv1,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ color: theme.heading,
+ fontSize: variables.fontSizeSmall,
+ },
+
+ // Emoji Picker Styles
+ emojiText: {
+ textAlign: 'center',
+ fontSize: variables.emojiSize,
+ ...spacing.pv0,
+ ...spacing.ph0,
+ lineHeight: variables.emojiLineHeight,
+ },
+
+ emojiItem: {
+ width: '12.5%',
+ textAlign: 'center',
+ borderRadius: 8,
+ paddingTop: 2,
+ paddingBottom: 2,
+ height: CONST.EMOJI_PICKER_ITEM_HEIGHT,
+ ...userSelect.userSelectNone,
+ },
+
+ emojiItemHighlighted: {
+ transition: '0.2s ease',
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
+ emojiItemKeyboardHighlighted: {
+ transition: '0.2s ease',
+ borderWidth: 1,
+ borderColor: theme.link,
+ borderRadius: variables.buttonBorderRadius,
+ },
+
+ categoryShortcutButton: {
+ flex: 1,
+ borderRadius: 8,
+ height: CONST.EMOJI_PICKER_ITEM_HEIGHT,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ chatItemEmojiButton: {
+ alignSelf: 'flex-end',
+ borderRadius: variables.buttonBorderRadius,
+ height: 40,
+ marginVertical: 3,
+ paddingHorizontal: 10,
+ justifyContent: 'center',
+ },
+
+ editChatItemEmojiWrapper: {
+ marginRight: 3,
+ alignSelf: 'flex-end',
+ },
+
+ hoveredButton: {
+ backgroundColor: theme.buttonHoveredBG,
+ },
+
+ composerSizeButton: {
+ alignSelf: 'center',
+ height: 32,
+ width: 32,
+ padding: 6,
+ margin: 3,
+ borderRadius: variables.componentBorderRadiusRounded,
+ backgroundColor: theme.transparent,
+ justifyContent: 'center',
+ },
+
+ chatItemAttachmentPlaceholder: {
+ backgroundColor: theme.sidebar,
+ borderColor: theme.border,
+ borderWidth: 1,
+ borderRadius: variables.componentBorderRadiusNormal,
+ height: 150,
+ textAlign: 'center',
+ verticalAlign: 'middle',
+ width: 200,
+ },
+
+ sidebarVisible: {
+ borderRightWidth: 1,
+ },
+
+ sidebarHidden: {
+ width: 0,
+ borderRightWidth: 0,
+ },
+
+ exampleCheckImage: {
+ width: '100%',
+ height: 80,
+ borderColor: theme.border,
+ borderWidth: 1,
+ borderRadius: variables.componentBorderRadiusNormal,
+ },
+
+ singleAvatar: {
+ height: 24,
+ width: 24,
+ backgroundColor: theme.icon,
+ borderRadius: 24,
+ },
+
+ singleAvatarSmall: {
+ height: 18,
+ width: 18,
+ backgroundColor: theme.icon,
+ borderRadius: 18,
+ },
+
+ singleAvatarMedium: {
+ height: 52,
+ width: 52,
+ backgroundColor: theme.icon,
+ borderRadius: 52,
+ },
+
+ secondAvatar: {
+ position: 'absolute',
+ right: -18,
+ bottom: -18,
+ borderWidth: 3,
+ borderRadius: 30,
+ borderColor: 'transparent',
+ },
+
+ secondAvatarSmall: {
+ position: 'absolute',
+ right: -13,
+ bottom: -13,
+ borderWidth: 3,
+ borderRadius: 18,
+ borderColor: 'transparent',
+ },
+
+ secondAvatarMedium: {
+ position: 'absolute',
+ right: -36,
+ bottom: -36,
+ borderWidth: 3,
+ borderRadius: 52,
+ borderColor: 'transparent',
+ },
+
+ secondAvatarSubscript: {
+ position: 'absolute',
+ right: -6,
+ bottom: -6,
+ },
+
+ secondAvatarSubscriptCompact: {
+ position: 'absolute',
+ bottom: -1,
+ right: -1,
+ },
+
+ secondAvatarSubscriptSmallNormal: {
+ position: 'absolute',
+ bottom: 0,
+ right: 0,
+ },
+
+ secondAvatarInline: {
+ bottom: -3,
+ right: -25,
+ borderWidth: 3,
+ borderRadius: 18,
+ borderColor: theme.cardBorder,
+ backgroundColor: theme.appBG,
+ },
+
+ avatarLarge: {
+ width: variables.avatarSizeLarge,
+ height: variables.avatarSizeLarge,
+ },
+
+ avatarXLarge: {
+ width: variables.avatarSizeXLarge,
+ height: variables.avatarSizeXLarge,
+ },
+
+ avatarInnerText: {
+ color: theme.textLight,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: undefined,
+ marginLeft: -3,
+ textAlign: 'center',
+ },
+
+ avatarInnerTextSmall: {
+ color: theme.textLight,
+ fontSize: variables.fontSizeExtraSmall,
+ lineHeight: undefined,
+ marginLeft: -2,
+ textAlign: 'center',
+ },
+
+ emptyAvatar: {
+ height: variables.avatarSizeNormal,
+ width: variables.avatarSizeNormal,
+ },
+
+ emptyAvatarSmallNormal: {
+ height: variables.avatarSizeSmallNormal,
+ width: variables.avatarSizeSmallNormal,
+ },
+
+ emptyAvatarSmall: {
+ height: variables.avatarSizeSmall,
+ width: variables.avatarSizeSmall,
+ },
+
+ emptyAvatarSmaller: {
+ height: variables.avatarSizeSmaller,
+ width: variables.avatarSizeSmaller,
+ },
+
+ emptyAvatarMedium: {
+ height: variables.avatarSizeMedium,
+ width: variables.avatarSizeMedium,
+ },
+
+ emptyAvatarLarge: {
+ height: variables.avatarSizeLarge,
+ width: variables.avatarSizeLarge,
+ },
+
+ emptyAvatarMargin: {
+ marginRight: variables.avatarChatSpacing,
+ },
+
+ emptyAvatarMarginChat: {
+ marginRight: variables.avatarChatSpacing - 12,
+ },
+
+ emptyAvatarMarginSmall: {
+ marginRight: variables.avatarChatSpacing - 4,
+ },
+
+ emptyAvatarMarginSmaller: {
+ marginRight: variables.avatarChatSpacing - 4,
+ },
+
+ borderTop: {
+ borderTopWidth: variables.borderTopWidth,
+ borderColor: theme.border,
+ },
+
+ borderTopRounded: {
+ borderTopWidth: 1,
+ borderColor: theme.border,
+ borderTopLeftRadius: variables.componentBorderRadiusNormal,
+ borderTopRightRadius: variables.componentBorderRadiusNormal,
+ },
+
+ borderBottomRounded: {
+ borderBottomWidth: 1,
+ borderColor: theme.border,
+ borderBottomLeftRadius: variables.componentBorderRadiusNormal,
+ borderBottomRightRadius: variables.componentBorderRadiusNormal,
+ },
+
+ borderBottom: {
+ borderBottomWidth: 1,
+ borderColor: theme.border,
+ },
+
+ borderNone: {
+ borderWidth: 0,
+ borderBottomWidth: 0,
+ },
+
+ borderRight: {
+ borderRightWidth: 1,
+ borderColor: theme.border,
+ },
+
+ borderLeft: {
+ borderLeftWidth: 1,
+ borderColor: theme.border,
+ },
+
+ pointerEventsNone,
+
+ pointerEventsAuto,
+
+ headerBar: {
+ overflow: 'hidden',
+ justifyContent: 'center',
+ display: 'flex',
+ paddingLeft: 20,
+ height: variables.contentHeaderHeight,
+ width: '100%',
+ },
+
+ imageViewContainer: {
+ width: '100%',
+ height: '100%',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ imageModalPDF: {
+ flex: 1,
+ backgroundColor: theme.modalBackground,
+ },
+
+ PDFView: {
+ // `display: grid` is not supported in native platforms!
+ // It's being used on Web/Desktop only to vertically center short PDFs,
+ // while preventing the overflow of the top of long PDF files.
+ ...display.dGrid,
+ backgroundColor: theme.modalBackground,
+ width: '100%',
+ height: '100%',
+ justifyContent: 'center',
+ overflow: 'hidden',
+ alignItems: 'center',
+ },
+
+ PDFViewList: {
+ overflowX: 'hidden',
+ // There properties disable "focus" effect on list
+ boxShadow: 'none',
+ outline: 'none',
+ },
+
+ getPDFPasswordFormStyle: (isSmallScreenWidth: boolean) =>
+ ({
+ width: isSmallScreenWidth ? '100%' : 350,
+ ...(isSmallScreenWidth && flex.flex1),
+ } satisfies ViewStyle),
+
+ centeredModalStyles: (isSmallScreenWidth: boolean, isFullScreenWhenSmall: boolean) =>
+ ({
+ borderWidth: isSmallScreenWidth && !isFullScreenWhenSmall ? 1 : 0,
+ marginHorizontal: isSmallScreenWidth ? 0 : 20,
+ } satisfies ViewStyle),
+
+ imageModalImageCenterContainer: {
+ alignItems: 'center',
+ flex: 1,
+ justifyContent: 'center',
+ width: '100%',
+ },
+
+ defaultAttachmentView: {
+ backgroundColor: theme.sidebar,
+ borderRadius: variables.componentBorderRadiusNormal,
+ borderWidth: 1,
+ borderColor: theme.border,
+ flexDirection: 'row',
+ padding: 20,
+ alignItems: 'center',
+ },
+
+ notFoundTextHeader: {
+ ...headlineFont,
+ color: theme.heading,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ marginTop: 20,
+ marginBottom: 8,
+ textAlign: 'center',
+ },
+
+ blockingViewContainer: {
+ paddingBottom: variables.contentHeaderHeight,
+ },
+
+ defaultModalContainer: {
+ backgroundColor: theme.componentBG,
+ borderColor: theme.transparent,
+ },
+
+ reportActionContextMenuMiniButton: {
+ ...spacing.p1,
+ ...spacing.mv1,
+ ...spacing.mh1,
+ ...{borderRadius: variables.buttonBorderRadius},
+ },
+
+ reportActionSystemMessageContainer: {
+ marginLeft: 42,
+ },
+
+ reportDetailsTitleContainer: {
+ ...display.dFlex,
+ ...flex.flexColumn,
+ ...flex.alignItemsCenter,
+ paddingHorizontal: 20,
+ paddingBottom: 20,
+ },
+
+ reportDetailsRoomInfo: {
+ ...flex.flex1,
+ ...display.dFlex,
+ ...flex.flexColumn,
+ ...flex.alignItemsCenter,
+ },
+
+ reportSettingsVisibilityText: {
+ textTransform: 'capitalize',
+ },
+
+ settingsPageBackground: {
+ flexDirection: 'column',
+ width: '100%',
+ flexGrow: 1,
+ },
+
+ settingsPageBody: {
+ width: '100%',
+ justifyContent: 'space-around',
+ },
+
+ twoFactorAuthSection: {
+ backgroundColor: theme.appBG,
+ padding: 0,
+ },
+
+ twoFactorAuthCodesBox: ({isExtraSmallScreenWidth, isSmallScreenWidth}: TwoFactorAuthCodesBoxParams) => {
+ let paddingHorizontal = spacing.ph9;
+
+ if (isSmallScreenWidth) {
+ paddingHorizontal = spacing.ph4;
+ }
+
+ if (isExtraSmallScreenWidth) {
+ paddingHorizontal = spacing.ph2;
+ }
+
+ return {
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: theme.highlightBG,
+ paddingVertical: 28,
+ borderRadius: 16,
+ marginTop: 32,
+ ...paddingHorizontal,
+ } satisfies ViewStyle;
+ },
+
+ twoFactorLoadingContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: 210,
+ },
+
+ twoFactorAuthCodesContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 12,
+ },
+
+ twoFactorAuthCode: {
+ fontFamily: fontFamily.MONOSPACE,
+ width: 112,
+ textAlign: 'center',
+ },
+
+ twoFactorAuthCodesButtonsContainer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ gap: 12,
+ marginTop: 20,
+ flexWrap: 'wrap',
+ },
+
+ twoFactorAuthCodesButton: {
+ minWidth: 112,
+ },
+
+ twoFactorAuthCopyCodeButton: {
+ minWidth: 110,
+ },
+
+ anonymousRoomFooter: (isSmallSizeLayout: boolean) =>
+ ({
+ flexDirection: isSmallSizeLayout ? 'column' : 'row',
+ ...(!isSmallSizeLayout && {
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ }),
+ padding: 20,
+ backgroundColor: theme.cardBG,
+ borderRadius: variables.componentBorderRadiusLarge,
+ overflow: 'hidden',
+ } satisfies ViewStyle & TextStyle),
+ anonymousRoomFooterWordmarkAndLogoContainer: (isSmallSizeLayout: boolean) =>
+ ({
+ flexDirection: 'row',
+ alignItems: 'center',
+ ...(isSmallSizeLayout && {
+ justifyContent: 'space-between',
+ marginTop: 16,
+ }),
+ } satisfies ViewStyle),
+ anonymousRoomFooterLogo: {
+ width: 88,
+ marginLeft: 0,
+ height: 20,
+ },
+ anonymousRoomFooterLogoTaglineText: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeMedium,
+ color: theme.textLight,
+ },
+ signInButtonAvatar: {
+ width: 80,
+ },
+
+ anonymousRoomFooterSignInButton: {
+ width: 110,
+ },
+
+ roomHeaderAvatarSize: {
+ height: variables.componentSizeLarge,
+ width: variables.componentSizeLarge,
+ },
+
+ roomHeaderAvatar: {
+ backgroundColor: theme.appBG,
+ borderRadius: 100,
+ borderColor: theme.componentBG,
+ borderWidth: 4,
+ },
+
+ roomHeaderAvatarOverlay: {
+ position: 'absolute',
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ backgroundColor: theme.overlay,
+ opacity: variables.overlayOpacity,
+ borderRadius: 88,
+ },
+
+ rootNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle),
+ RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle),
+
+ avatarInnerTextChat: {
+ color: theme.textLight,
+ fontSize: variables.fontSizeXLarge,
+ fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
+ textAlign: 'center',
+ fontWeight: 'normal',
+ position: 'absolute',
+ width: 88,
+ left: -16,
+ },
+
+ pageWrapper: {
+ width: '100%',
+ alignItems: 'center',
+ padding: 20,
+ },
+
+ avatarSectionWrapper: {
+ width: '100%',
+ alignItems: 'center',
+ paddingHorizontal: 20,
+ paddingBottom: 20,
+ },
+
+ avatarSectionWrapperSkeleton: {
+ width: '100%',
+ paddingHorizontal: 20,
+ paddingBottom: 20,
+ },
+
+ selectCircle: {
+ width: variables.componentSizeSmall,
+ height: variables.componentSizeSmall,
+ borderColor: theme.border,
+ borderWidth: 1,
+ borderRadius: variables.componentSizeSmall / 2,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: theme.componentBG,
+ marginLeft: 8,
+ },
+
+ unreadIndicatorContainer: {
+ position: 'absolute',
+ top: -10,
+ left: 0,
+ width: '100%',
+ height: 20,
+ paddingHorizontal: 20,
+ flexDirection: 'row',
+ alignItems: 'center',
+ zIndex: 1,
+ ...cursor.cursorDefault,
+ },
+
+ unreadIndicatorLine: {
+ height: 1,
+ backgroundColor: theme.unreadIndicator,
+ flexGrow: 1,
+ marginRight: 8,
+ opacity: 0.5,
+ },
+
+ threadDividerLine: {
+ height: 1,
+ backgroundColor: theme.border,
+ flexGrow: 1,
+ marginHorizontal: 20,
+ },
+
+ unreadIndicatorText: {
+ color: theme.unreadIndicator,
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontSize: variables.fontSizeSmall,
+ fontWeight: fontWeightBold,
+ textTransform: 'capitalize',
+ },
+
+ flipUpsideDown: {
+ transform: [{rotate: '180deg'}],
+ },
+
+ navigationScreenCardStyle: {
+ backgroundColor: theme.appBG,
+ height: '100%',
+ },
+
+ invisible: {
+ position: 'absolute',
+ opacity: 0,
+ },
+
+ invisiblePopover: {
+ position: 'absolute',
+ opacity: 0,
+ left: -9999,
+ },
+
+ containerWithSpaceBetween: {
+ justifyContent: 'space-between',
+ width: '100%',
+ flex: 1,
+ },
+
+ detailsPageSectionContainer: {
+ alignSelf: 'flex-start',
+ },
+
+ attachmentCarouselContainer: {
+ height: '100%',
+ width: '100%',
+ display: 'flex',
+ justifyContent: 'center',
+ ...cursor.cursorUnset,
+ },
+
+ attachmentArrow: {
+ zIndex: 23,
+ position: 'absolute',
+ },
+
+ attachmentRevealButtonContainer: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ ...spacing.ph4,
+ },
+
+ arrowIcon: {
+ height: 40,
+ width: 40,
+ alignItems: 'center',
+ paddingHorizontal: 0,
+ paddingTop: 0,
+ paddingBottom: 0,
+ },
+
+ switchTrack: {
+ width: 50,
+ height: 28,
+ justifyContent: 'center',
+ borderRadius: 20,
+ padding: 15,
+ backgroundColor: theme.success,
+ },
+
+ switchInactive: {
+ backgroundColor: theme.border,
+ },
+
+ switchThumb: {
+ width: 22,
+ height: 22,
+ borderRadius: 11,
+ position: 'absolute',
+ left: 4,
+ backgroundColor: theme.appBG,
+ },
+
+ switchThumbTransformation: (translateX: AnimatableNumericValue) =>
+ ({
+ transform: [{translateX}],
+ } satisfies ViewStyle),
+
+ radioButtonContainer: {
+ backgroundColor: theme.componentBG,
+ borderRadius: 10,
+ height: 20,
+ width: 20,
+ borderColor: theme.icon,
+ borderWidth: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+
+ checkedContainer: {
+ backgroundColor: theme.checkBox,
+ },
+
+ magicCodeInputContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ minHeight: variables.inputHeight,
+ },
+
+ magicCodeInput: {
+ fontSize: variables.fontSizeXLarge,
+ color: theme.heading,
+ lineHeight: variables.inputHeight,
+ },
+
+ // Manually style transparent, in iOS Safari, an input in a container with its opacity set to
+ // 0 (completely transparent) cannot handle user interaction, hence the Paste option is never shown
+ inputTransparent: {
+ color: 'transparent',
+ // These properties are available in browser only
+ ...(Browser.getBrowser()
+ ? {
+ caretColor: 'transparent',
+ WebkitTextFillColor: 'transparent',
+ // After setting the input text color to transparent, it acquires the background-color.
+ // However, it is not possible to override the background-color directly as explained in this resource: https://developer.mozilla.org/en-US/docs/Web/CSS/:autofill
+ // Therefore, the transition effect needs to be delayed.
+ transitionDelay: '99999s',
+ transitionProperty: 'background-color',
+ }
+ : {}),
+ },
+
+ iouAmountText: {
+ ...headlineFont,
+ fontSize: variables.iouAmountTextSize,
+ color: theme.heading,
+ lineHeight: variables.inputHeight,
+ },
+
+ iouAmountTextInput: addOutlineWidth(
+ {
+ ...headlineFont,
+ fontSize: variables.iouAmountTextSize,
+ color: theme.heading,
+ padding: 0,
+ lineHeight: undefined,
+ },
+ 0,
+ ),
+
+ moneyRequestConfirmationAmount: {
+ ...headlineFont,
+ fontSize: variables.fontSizeh1,
+ },
+
+ moneyRequestMenuItem: {
+ flexDirection: 'row',
+ borderRadius: 0,
+ justifyContent: 'space-between',
+ width: '100%',
+ paddingHorizontal: 20,
+ paddingVertical: 12,
+ },
+
+ requestPreviewBox: {
+ marginTop: 12,
+ maxWidth: variables.reportPreviewMaxWidth,
+ },
+
+ moneyRequestPreviewBox: {
+ backgroundColor: theme.cardBG,
+ borderRadius: variables.componentBorderRadiusLarge,
+ maxWidth: variables.reportPreviewMaxWidth,
+ width: '100%',
+ },
+
+ moneyRequestPreviewBoxText: {
+ padding: 16,
+ },
+
+ amountSplitPadding: {
+ paddingTop: 2,
+ },
+
+ moneyRequestPreviewBoxLoading: {
+ // When a new IOU request arrives it is very briefly in a loading state, so set the minimum height of the container to 94 to match the rendered height after loading.
+ // Otherwise, the IOU request pay button will not be fully visible and the user will have to scroll up to reveal the entire IOU request container.
+ // See https://github.com/Expensify/App/issues/10283.
+ minHeight: 94,
+ width: '100%',
+ },
+
+ moneyRequestPreviewBoxAvatar: {
+ marginRight: -10,
+ marginBottom: 0,
+ },
+
+ moneyRequestPreviewAmount: {
+ ...headlineFont,
+ ...whiteSpace.preWrap,
+ color: theme.heading,
+ },
+
+ defaultCheckmarkWrapper: {
+ marginLeft: 8,
+ alignSelf: 'center',
+ },
+
+ codeWordWrapper: {
+ ...codeStyles.codeWordWrapper,
+ },
+
+ codeWordStyle: {
+ borderLeftWidth: 0,
+ borderRightWidth: 0,
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ paddingLeft: 0,
+ paddingRight: 0,
+ justifyContent: 'center',
+ ...codeStyles.codeWordStyle,
+ },
+
+ codeFirstWordStyle: {
+ borderLeftWidth: 1,
+ borderTopLeftRadius: 4,
+ borderBottomLeftRadius: 4,
+ paddingLeft: 5,
+ },
+
+ codeLastWordStyle: {
+ borderRightWidth: 1,
+ borderTopRightRadius: 4,
+ borderBottomRightRadius: 4,
+ paddingRight: 5,
+ },
+
+ fullScreenLoading: {
+ backgroundColor: theme.componentBG,
+ opacity: 0.8,
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 10,
+ },
+
+ reimbursementAccountFullScreenLoading: {
+ backgroundColor: theme.componentBG,
+ opacity: 0.8,
+ justifyContent: 'flex-start',
+ alignItems: 'center',
+ zIndex: 10,
+ },
+
+ hiddenElementOutsideOfWindow: {
+ position: 'absolute',
+ top: -10000,
+ left: 0,
+ opacity: 0,
+ },
+
+ growlNotificationWrapper: {
+ zIndex: 2,
+ },
+
+ growlNotificationContainer: {
+ flex: 1,
+ justifyContent: 'flex-start',
+ position: 'absolute',
+ width: '100%',
+ top: 20,
+ ...spacing.pl5,
+ ...spacing.pr5,
+ },
+
+ growlNotificationDesktopContainer: {
+ maxWidth: variables.sideBarWidth,
+ right: 0,
+ ...positioning.pFixed,
+ },
+
+ growlNotificationTranslateY: (translateY: AnimatableNumericValue) =>
+ ({
+ transform: [{translateY}],
+ } satisfies ViewStyle),
+
+ makeSlideInTranslation: (translationType: Translation, fromValue: number) =>
+ ({
+ from: {
+ [translationType]: fromValue,
+ },
+ to: {
+ [translationType]: 0,
+ },
+ } satisfies CustomAnimation),
+
+ growlNotificationBox: {
+ backgroundColor: theme.inverse,
+ borderRadius: variables.componentBorderRadiusNormal,
+ alignItems: 'center',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ shadowColor: theme.shadow,
+ ...spacing.p5,
+ },
+
+ growlNotificationText: {
+ fontSize: variables.fontSizeNormal,
+ fontFamily: fontFamily.EXP_NEUE,
+ width: '90%',
+ lineHeight: variables.fontSizeNormalHeight,
+ color: theme.textReversed,
+ ...spacing.ml4,
+ },
+
+ blockquote: {
+ borderLeftColor: theme.border,
+ borderLeftWidth: 4,
+ paddingLeft: 12,
+ marginVertical: 4,
+ },
+
+ noSelect: {
+ boxShadow: 'none',
+ outlineStyle: 'none',
+ },
+
+ cardStyleNavigator: {
+ overflow: 'hidden',
+ height: '100%',
+ },
+
+ smallEditIcon: {
+ alignItems: 'center',
+ backgroundColor: theme.buttonHoveredBG,
+ borderColor: theme.textReversed,
+ borderRadius: 14,
+ borderWidth: 3,
+ color: theme.textReversed,
+ height: 28,
+ width: 28,
+ justifyContent: 'center',
+ },
+
+ smallAvatarEditIcon: {
+ position: 'absolute',
+ right: -4,
+ bottom: -4,
+ },
+
+ autoGrowHeightMultilineInput: {
+ maxHeight: 115,
+ },
+
+ peopleRow: {
+ width: '100%',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ ...spacing.ph5,
+ },
+
+ peopleRowBorderBottom: {
+ borderColor: theme.border,
+ borderBottomWidth: 1,
+ ...spacing.pb2,
+ },
+
+ peopleBadge: {
+ backgroundColor: theme.icon,
+ ...spacing.ph3,
+ },
+
+ peopleBadgeText: {
+ color: theme.textReversed,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightNormal,
+ ...whiteSpace.noWrap,
+ },
+
+ offlineFeedback: {
+ deleted: {
+ textDecorationLine: 'line-through',
+ textDecorationStyle: 'solid',
+ },
+ pending: {
+ opacity: 0.5,
+ },
+ error: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ container: {
+ ...spacing.pv2,
+ },
+ textContainer: {
+ flexDirection: 'column',
+ flex: 1,
+ },
+ text: {
+ color: theme.textSupporting,
+ textAlignVertical: 'center',
+ fontSize: variables.fontSizeLabel,
+ },
+ errorDot: {
+ marginRight: 12,
+ },
+ },
+
+ dotIndicatorMessage: {
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+
+ locationErrorLinkText: {
+ textAlignVertical: 'center',
+ fontSize: variables.fontSizeLabel,
+ },
+
+ sidebarPopover: {
+ width: variables.sideBarWidth - 68,
+ },
+
+ cardOverlay: {
+ backgroundColor: theme.overlay,
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ height: '100%',
+ opacity: variables.overlayOpacity,
+ },
+
+ shortTermsBorder: {
+ borderWidth: 1,
+ borderColor: theme.border,
+ },
+
+ shortTermsHorizontalRule: {
+ borderBottomWidth: 1,
+ borderColor: theme.border,
+ ...spacing.mh3,
+ },
+
+ shortTermsLargeHorizontalRule: {
+ borderWidth: 1,
+ borderColor: theme.border,
+ ...spacing.mh3,
+ },
+
+ shortTermsRow: {
+ flexDirection: 'row',
+ padding: 12,
+ },
+
+ termsCenterRight: {
+ marginTop: 'auto',
+ marginBottom: 'auto',
+ },
+
+ shortTermsBoldHeadingSection: {
+ paddingRight: 12,
+ paddingLeft: 12,
+ marginTop: 12,
+ },
+
+ shortTermsHeadline: {
+ ...headlineFont,
+ ...whiteSpace.preWrap,
+ color: theme.heading,
+ fontSize: variables.fontSizeXXXLarge,
+ lineHeight: variables.lineHeightXXXLarge,
+ },
+
+ longTermsRow: {
+ flexDirection: 'row',
+ marginTop: 20,
+ },
+
+ collapsibleSectionBorder: {
+ borderBottomWidth: 2,
+ borderBottomColor: theme.border,
+ },
+
+ communicationsLinkHeight: {
+ height: variables.communicationsLinkHeight,
+ },
+
+ floatingMessageCounterWrapper: {
+ position: 'absolute',
+ left: '50%',
+ top: 0,
+ zIndex: 100,
+ ...visibility.hidden,
+ },
+
+ floatingMessageCounterWrapperAndroid: {
+ left: 0,
+ width: '100%',
+ alignItems: 'center',
+ position: 'absolute',
+ top: 0,
+ zIndex: 100,
+ ...visibility.hidden,
+ },
+
+ floatingMessageCounterSubWrapperAndroid: {
+ left: '50%',
+ width: 'auto',
+ },
+
+ floatingMessageCounter: {
+ left: '-50%',
+ ...visibility.visible,
+ },
+
+ floatingMessageCounterTransformation: (translateY: AnimatableNumericValue) =>
+ ({
+ transform: [{translateY}],
+ } satisfies ViewStyle),
+
+ confirmationAnimation: {
+ height: 180,
+ width: 180,
+ marginBottom: 20,
+ },
+
+ googleSearchTextInputContainer: {
+ flexDirection: 'column',
+ },
+
+ googleSearchSeparator: {
+ height: 1,
+ backgroundColor: theme.border,
+ },
+
+ googleSearchText: {
+ color: theme.text,
+ fontSize: variables.fontSizeNormal,
+ lineHeight: variables.fontSizeNormalHeight,
+ fontFamily: fontFamily.EXP_NEUE,
+ flex: 1,
+ },
+
+ threeDotsPopoverOffset: (windowWidth: number) =>
+ ({
+ ...getPopOverVerticalOffset(60),
+ horizontal: windowWidth - 60,
+ } satisfies AnchorPosition),
+
+ threeDotsPopoverOffsetNoCloseButton: (windowWidth: number) =>
+ ({
+ ...getPopOverVerticalOffset(60),
+ horizontal: windowWidth - 10,
+ } satisfies AnchorPosition),
+
+ threeDotsPopoverOffsetAttachmentModal: (windowWidth: number) =>
+ ({
+ ...getPopOverVerticalOffset(80),
+ horizontal: windowWidth - 140,
+ } satisfies AnchorPosition),
+
+ iPhoneXSafeArea: {
+ backgroundColor: theme.inverse,
+ flex: 1,
+ },
+
+ transferBalancePayment: {
+ borderWidth: 1,
+ borderRadius: variables.componentBorderRadiusNormal,
+ borderColor: theme.border,
+ },
+
+ transferBalanceSelectedPayment: {
+ borderColor: theme.iconSuccessFill,
+ },
+
+ transferBalanceBalance: {
+ fontSize: 48,
+ },
+
+ imageCropContainer: {
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: theme.imageCropBackgroundColor,
+ ...cursor.cursorMove,
+ },
+
+ sliderKnobTooltipView: {
+ height: variables.sliderKnobSize,
+ width: variables.sliderKnobSize,
+ borderRadius: variables.sliderKnobSize / 2,
+ },
+
+ sliderKnob: {
+ backgroundColor: theme.success,
+ position: 'absolute',
+ height: variables.sliderKnobSize,
+ width: variables.sliderKnobSize,
+ borderRadius: variables.sliderKnobSize / 2,
+ left: -(variables.sliderKnobSize / 2),
+ ...cursor.cursorPointer,
+ },
+
+ sliderBar: {
+ backgroundColor: theme.border,
+ height: variables.sliderBarHeight,
+ borderRadius: variables.sliderBarHeight / 2,
+ alignSelf: 'stretch',
+ justifyContent: 'center',
+ },
+
+ screenCenteredContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ marginBottom: 40,
+ padding: 16,
+ },
+
+ inlineSystemMessage: {
+ color: theme.textSupporting,
+ fontSize: variables.fontSizeLabel,
+ fontFamily: fontFamily.EXP_NEUE,
+ marginLeft: 6,
+ },
+
+ fullScreen: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ },
+
+ invisibleOverlay: {
+ backgroundColor: theme.transparent,
+ zIndex: 1000,
+ },
+
+ reportDropOverlay: {
+ backgroundColor: theme.dropUIBG,
+ zIndex: 2,
+ },
+
+ receiptDropOverlay: {
+ backgroundColor: theme.receiptDropUIBG,
+ zIndex: 2,
+ },
+
+ receiptImageWrapper: (receiptImageTopPosition: number) =>
+ ({
+ position: 'absolute',
+ top: receiptImageTopPosition,
+ } satisfies ViewStyle),
+
+ cardSection: {
+ backgroundColor: theme.cardBG,
+ borderRadius: variables.componentBorderRadiusCard,
+ marginBottom: 20,
+ marginHorizontal: 16,
+ padding: 20,
+ width: 'auto',
+ textAlign: 'left',
+ },
+
+ cardSectionTitle: {
+ lineHeight: variables.lineHeightXXLarge,
+ },
+
+ cardMenuItem: {
+ paddingLeft: 0,
+ paddingRight: 0,
+ borderRadius: variables.buttonBorderRadius,
+ height: variables.componentSizeLarge,
+ alignItems: 'center',
+ },
+
+ transferBalance: {
+ paddingLeft: 20,
+ paddingRight: 20,
+ borderRadius: 0,
+ height: 64,
+ alignItems: 'center',
+ },
+
+ paymentMethod: {
+ paddingHorizontal: 20,
+ height: 64,
+ },
+
+ archivedReportFooter: {
+ borderRadius: variables.componentBorderRadius,
+ ...wordBreak.breakWord,
+ },
+
+ deeplinkWrapperContainer: {
+ padding: 20,
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: theme.appBG,
+ },
+
+ deeplinkWrapperMessage: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ deeplinkWrapperFooter: {
+ paddingTop: 80,
+ paddingBottom: 45,
+ },
+
+ emojiReactionBubble: {
+ borderRadius: 28,
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexDirection: 'row',
+ alignSelf: 'flex-start',
+ },
+
+ emojiReactionListHeader: {
+ marginTop: 8,
+ paddingBottom: 20,
+ borderBottomColor: theme.border,
+ borderBottomWidth: 1,
+ marginHorizontal: 20,
+ },
+ emojiReactionListHeaderBubble: {
+ paddingVertical: 2,
+ paddingHorizontal: 8,
+ borderRadius: 28,
+ backgroundColor: theme.border,
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexDirection: 'row',
+ alignSelf: 'flex-start',
+ marginRight: 4,
+ },
+
+ reactionListHeaderText: {
+ color: theme.textSupporting,
+ marginLeft: 8,
+ alignSelf: 'center',
+ },
+
+ miniQuickEmojiReactionText: {
+ fontSize: 15,
+ lineHeight: 20,
+ textAlignVertical: 'center',
+ },
+
+ emojiReactionBubbleText: {
+ textAlignVertical: 'center',
+ },
+
+ reactionCounterText: {
+ fontSize: 13,
+ marginLeft: 4,
+ fontWeight: 'bold',
+ },
+
+ fontColorReactionLabel: {
+ color: theme.tooltipSupportingText,
+ },
+
+ reactionEmojiTitle: {
+ fontSize: variables.iconSizeLarge,
+ lineHeight: variables.iconSizeXLarge,
+ },
+
+ textReactionSenders: {
+ color: theme.tooltipPrimaryText,
+ ...wordBreak.breakWord,
+ },
+
+ quickReactionsContainer: {
+ gap: 12,
+ flexDirection: 'row',
+ paddingHorizontal: 25,
+ paddingVertical: 12,
+ justifyContent: 'space-between',
+ },
+
+ reactionListContainer: {
+ maxHeight: variables.listItemHeightNormal * 5.75,
+ ...spacing.pv2,
+ },
+
+ reactionListContainerFixedWidth: {
+ maxWidth: variables.popoverWidth,
+ },
+
+ validateCodeDigits: {
+ color: theme.text,
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeXXLarge,
+ letterSpacing: 4,
+ },
+
+ footerWrapper: {
+ fontSize: variables.fontSizeNormal,
+ paddingTop: 64,
+ maxWidth: 1100, // Match footer across all Expensify platforms
+ },
+
+ footerColumnsContainer: {
+ flex: 1,
+ flexWrap: 'wrap',
+ marginBottom: 40,
+ marginHorizontal: -16,
+ },
+
+ footerTitle: {
+ fontSize: variables.fontSizeLarge,
+ color: theme.success,
+ marginBottom: 16,
+ },
+
+ footerRow: {
+ paddingVertical: 4,
+ marginBottom: 8,
+ color: theme.textLight,
+ fontSize: variables.fontSizeMedium,
+ },
+
+ footerBottomLogo: {
+ marginTop: 40,
+ width: '100%',
+ },
+
+ datePickerRoot: {
+ position: 'relative',
+ zIndex: 99,
+ },
+
+ datePickerPopover: {
+ backgroundColor: theme.appBG,
+ width: '100%',
+ alignSelf: 'center',
+ zIndex: 100,
+ marginTop: 8,
+ },
+
+ loginHeroHeader: {
+ fontFamily: fontFamily.EXP_NEW_KANSAS_MEDIUM,
+ color: theme.success,
+ fontWeight: '500',
+ textAlign: 'center',
+ },
+
+ newKansasLarge: {
+ ...headlineFont,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ },
+
+ eReceiptAmount: {
+ ...headlineFont,
+ fontSize: variables.fontSizeXXXLarge,
+ lineHeight: variables.lineHeightXXXLarge,
+ color: colors.green400,
+ },
+
+ eReceiptAmountLarge: {
+ ...headlineFont,
+ fontSize: variables.fontSizeEReceiptLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ wordBreak: 'break-word',
+ textAlign: 'center',
+ },
+
+ eReceiptCurrency: {
+ ...headlineFont,
+ fontSize: variables.fontSizeXXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ wordBreak: 'break-all',
+ },
+
+ eReceiptMerchant: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+ color: theme.text,
+ },
+
+ eReceiptWaypointTitle: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ color: colors.green400,
+ },
+
+ eReceiptWaypointAddress: {
+ fontFamily: fontFamily.MONOSPACE,
+ fontSize: variables.fontSizeNormal,
+ lineHeight: variables.lineHeightNormal,
+ color: theme.textColorfulBackground,
+ },
+
+ eReceiptGuaranteed: {
+ fontFamily: fontFamily.MONOSPACE,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightSmall,
+ color: theme.textColorfulBackground,
+ },
+
+ eReceiptBackground: {
+ ...sizing.w100,
+ borderRadius: 20,
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ height: 540,
+ },
+
+ eReceiptPanel: {
+ ...spacing.p5,
+ ...spacing.pb8,
+ ...spacing.m5,
+ backgroundColor: colors.green800,
+ borderRadius: 20,
+ width: 335,
+ },
+
+ eReceiptBackgroundThumbnail: {
+ ...sizing.w100,
+ position: 'absolute',
+ aspectRatio: 335 / 540,
+ top: 0,
+ minWidth: 217,
+ },
+
+ eReceiptContainer: {
+ flex: 1,
+ width: 335,
+ minHeight: 540,
+ borderRadius: 20,
+ overflow: 'hidden',
+ },
+
+ loginHeroBody: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeSignInHeroBody,
+ color: theme.textLight,
+ textAlign: 'center',
+ },
+
+ linkPreviewWrapper: {
+ marginTop: 16,
+ borderLeftWidth: 4,
+ borderLeftColor: theme.border,
+ paddingLeft: 12,
+ },
+
+ linkPreviewImage: {
+ flex: 1,
+ resizeMode: 'contain',
+ borderRadius: 8,
+ marginTop: 8,
+ },
+
+ linkPreviewLogoImage: {
+ height: 16,
+ width: 16,
+ },
+
+ contextMenuItemPopoverMaxWidth: {
+ maxWidth: 375,
+ },
+
+ formSpaceVertical: {
+ height: 20,
+ width: 1,
+ },
+
+ taskCheckbox: {
+ height: 16,
+ width: 16,
+ },
+
+ taskTitleMenuItem: {
+ ...writingDirection.ltr,
+ ...headlineFont,
+ ...flex.flexWrap,
+ ...flex.flex1,
+ fontSize: variables.fontSizeXLarge,
+ maxWidth: '100%',
+ ...wordBreak.breakWord,
+ },
+
+ taskDescriptionMenuItem: {
+ maxWidth: '100%',
+ ...wordBreak.breakWord,
+ },
+
+ taskTitleDescription: {
+ fontFamily: fontFamily.EXP_NEUE,
+ fontSize: variables.fontSizeLabel,
+ color: theme.textSupporting,
+ lineHeight: variables.lineHeightNormal,
+ ...spacing.mb1,
+ },
+
+ taskMenuItemCheckbox: {
+ height: 27,
+ ...spacing.mr3,
+ },
+
+ reportHorizontalRule: {
+ borderColor: theme.border,
+ ...spacing.mh5,
+ },
+
+ assigneeTextStyle: {
+ fontFamily: fontFamily.EXP_NEUE_BOLD,
+ fontWeight: fontWeightBold,
+ minHeight: variables.avatarSizeSubscript,
+ },
+
+ taskRightIconContainer: {
+ width: variables.componentSizeNormal,
+ marginLeft: 'auto',
+ ...spacing.mt1,
+ ...pointerEventsAuto,
+ ...display.dFlex,
+ ...flex.alignItemsCenter,
+ },
+
+ shareCodePage: {
+ paddingHorizontal: 38.5,
+ },
+
+ shareCodeContainer: {
+ width: '100%',
+ alignItems: 'center',
+ paddingHorizontal: variables.qrShareHorizontalPadding,
+ paddingVertical: 20,
+ borderRadius: 20,
+ overflow: 'hidden',
+ borderColor: theme.borderFocus,
+ borderWidth: 2,
+ backgroundColor: theme.highlightBG,
+ },
+
+ splashScreenHider: {
+ backgroundColor: theme.splashBG,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ headerEnvBadge: {
+ marginLeft: 0,
+ marginBottom: 2,
+ height: 12,
+ paddingLeft: 4,
+ paddingRight: 4,
+ alignItems: 'center',
+ },
+
+ headerEnvBadgeText: {
+ fontSize: 7,
+ fontWeight: fontWeightBold,
+ lineHeight: undefined,
+ },
+
+ expensifyQrLogo: {
+ alignSelf: 'stretch',
+ height: 27,
+ marginBottom: 20,
+ },
+
+ qrShareTitle: {
+ marginTop: 15,
+ textAlign: 'center',
+ },
+
+ loginButtonRow: {
+ width: '100%',
+ gap: 12,
+ ...flex.flexRow,
+ ...flex.justifyContentCenter,
+ },
+
+ loginButtonRowSmallScreen: {
+ width: '100%',
+ gap: 12,
+ ...flex.flexRow,
+ ...flex.justifyContentCenter,
+ marginBottom: 10,
+ },
+
+ desktopSignInButtonContainer: {
+ width: 40,
+ height: 40,
+ },
+
+ signInIconButton: {
+ paddingVertical: 2,
+ },
+
+ googleButtonContainer: {
+ colorScheme: 'light',
+ width: 40,
+ height: 40,
+ alignItems: 'center',
+ overflow: 'hidden',
+ },
+
+ googlePillButtonContainer: {
+ colorScheme: 'light',
+ height: 40,
+ width: 219,
+ },
+
+ thirdPartyLoadingContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: 450,
+ },
+
+ tabSelectorButton: {
+ height: variables.tabSelectorButtonHeight,
+ padding: variables.tabSelectorButtonPadding,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: variables.buttonBorderRadius,
+ },
+
+ tabSelector: {
+ flexDirection: 'row',
+ paddingHorizontal: 20,
+ paddingBottom: 12,
+ },
+
+ tabText: (isSelected: boolean) =>
+ ({
+ marginLeft: 8,
+ fontFamily: isSelected ? fontFamily.EXP_NEUE_BOLD : fontFamily.EXP_NEUE,
+ fontWeight: isSelected ? fontWeightBold : '400',
+ color: isSelected ? theme.textLight : theme.textSupporting,
+ } satisfies TextStyle),
+
+ tabBackground: (hovered: boolean, isFocused: boolean, background: string) => ({
+ backgroundColor: hovered && !isFocused ? theme.highlightBG : background,
+ }),
+
+ tabOpacity: (hovered: boolean, isFocused: boolean, activeOpacityValue: number, inactiveOpacityValue: number) => ({
+ opacity: hovered && !isFocused ? inactiveOpacityValue : activeOpacityValue,
+ }),
+
+ overscrollSpacer: (backgroundColor: string, height: number) =>
+ ({
+ backgroundColor,
+ height,
+ width: '100%',
+ position: 'absolute',
+ top: -height,
+ left: 0,
+ right: 0,
+ } satisfies ViewStyle),
+
+ dualColorOverscrollSpacer: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ height: '100%',
+ zIndex: -1,
+ },
+
+ willChangeTransform: {
+ willChange: 'transform',
+ },
+
+ dropDownButtonCartIconContainerPadding: {
+ paddingRight: 0,
+ paddingLeft: 0,
+ },
+
+ dropDownButtonArrowContain: {
+ marginLeft: 12,
+ marginRight: 14,
+ },
+
+ dropDownButtonCartIconView: {
+ borderTopRightRadius: variables.buttonBorderRadius,
+ borderBottomRightRadius: variables.buttonBorderRadius,
+ ...flex.flexRow,
+ ...flex.alignItemsCenter,
+ },
+
+ emojiPickerButtonDropdown: {
+ justifyContent: 'center',
+ backgroundColor: theme.activeComponentBG,
+ width: 86,
+ height: 52,
+ borderRadius: 26,
+ alignItems: 'center',
+ paddingLeft: 10,
+ paddingRight: 4,
+ marginBottom: 32,
+ alignSelf: 'flex-start',
+ },
+
+ emojiPickerButtonDropdownIcon: {
+ fontSize: 30,
+ },
+
+ moneyRequestImage: {
+ height: 200,
+ borderRadius: 16,
+ margin: 20,
+ },
+
+ reportPreviewBox: {
+ backgroundColor: theme.cardBG,
+ borderRadius: variables.componentBorderRadiusLarge,
+ maxWidth: variables.sideBarWidth,
+ width: '100%',
+ },
+
+ reportPreviewBoxHoverBorder: {
+ borderColor: theme.border,
+ backgroundColor: theme.border,
+ },
+
+ reportContainerBorderRadius: {
+ borderRadius: variables.componentBorderRadiusLarge,
+ },
+
+ reportPreviewBoxBody: {
+ padding: 16,
+ },
+
+ reportActionItemImages: {
+ flexDirection: 'row',
+ borderWidth: 4,
+ borderColor: theme.transparent,
+ borderTopLeftRadius: variables.componentBorderRadiusLarge,
+ borderTopRightRadius: variables.componentBorderRadiusLarge,
+ overflow: 'hidden',
+ height: variables.reportActionImagesSingleImageHeight,
+ },
+
+ reportActionItemImage: {
+ flex: 1,
+ width: '100%',
+ height: '100%',
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+
+ reportActionItemImageBorder: {
+ borderRightWidth: 4,
+ borderColor: theme.cardBG,
+ },
+
+ reportActionItemImagesMoreContainer: {
+ position: 'absolute',
+ bottom: 0,
+ right: 0,
+ display: 'flex',
+ },
+
+ reportActionItemImagesMore: {
+ borderTopLeftRadius: 12,
+ backgroundColor: theme.border,
+ width: 40,
+ height: 40,
+ },
+
+ reportActionItemImagesMoreHovered: {
+ backgroundColor: theme.cardBG,
+ },
+
+ reportActionItemImagesMoreText: {
+ position: 'absolute',
+ marginLeft: 20,
+ marginTop: 16,
+ color: theme.textSupporting,
+ },
+
+ reportActionItemImagesMoreCornerTriangle: {
+ position: 'absolute',
+ bottom: 0,
+ right: 0,
+ width: 0,
+ height: 0,
+ borderStyle: 'solid',
+ borderWidth: 0,
+ borderBottomWidth: 40,
+ borderLeftWidth: 40,
+ borderColor: 'transparent',
+ borderBottomColor: theme.cardBG,
+ },
+
+ reportActionItemImagesMoreCornerTriangleHighlighted: {
+ borderColor: 'transparent',
+ borderBottomColor: theme.border,
+ },
+
+ moneyRequestHeaderStatusBarBadge: {
+ paddingHorizontal: 8,
+ borderRadius: variables.componentBorderRadiusSmall,
+ height: variables.inputHeightSmall,
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: theme.border,
+ marginRight: 12,
+ },
+
+ staticHeaderImage: {
+ minHeight: 240,
+ },
+
+ emojiPickerButtonDropdownContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+
+ rotate90: {
+ transform: [{rotate: '90deg'}],
+ },
+
+ emojiStatusLHN: {
+ fontSize: 22,
+ },
+ sidebarStatusAvatarContainer: {
+ height: 44,
+ width: 84,
+ backgroundColor: theme.componentBG,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ borderRadius: 42,
+ paddingHorizontal: 2,
+ marginVertical: -2,
+ marginRight: -2,
+ },
+ sidebarStatusAvatar: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ moneyRequestViewImage: {
+ ...spacing.mh5,
+ ...spacing.mv3,
+ overflow: 'hidden',
+ borderWidth: 2,
+ borderColor: theme.cardBG,
+ borderRadius: variables.componentBorderRadiusLarge,
+ height: 200,
+ maxWidth: 400,
+ },
+
+ mapViewContainer: {
+ ...flex.flex1,
+ ...spacing.p4,
+ minHeight: 300,
+ maxHeight: 500,
+ },
+
+ mapView: {
+ flex: 1,
+ borderRadius: 16,
+ overflow: 'hidden',
+ },
+
+ mapViewOverlay: {
+ flex: 1,
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ borderRadius: variables.componentBorderRadiusLarge,
+ overflow: 'hidden',
+ backgroundColor: theme.highlightBG,
+ ...sizing.w100,
+ ...sizing.h100,
+ },
+
+ confirmationListMapItem: {
+ ...spacing.mv2,
+ ...spacing.mh5,
+ height: 200,
+ },
+
+ mapDirection: {
+ lineColor: theme.success,
+ lineWidth: 7,
+ },
+
+ mapDirectionLayer: {
+ layout: {'line-join': 'round', 'line-cap': 'round'},
+ paint: {'line-color': theme.success, 'line-width': 7},
+ },
+
+ mapPendingView: {
+ backgroundColor: theme.highlightBG,
+ ...flex.flex1,
+ borderRadius: variables.componentBorderRadiusLarge,
+ },
+ userReportStatusEmoji: {
+ flexShrink: 0,
+ fontSize: variables.fontSizeNormal,
+ marginRight: 4,
+ },
+ draggableTopBar: {
+ height: 30,
+ width: '100%',
+ },
+
+ videoContainer: {
+ ...flex.flex1,
+ ...flex.alignItemsCenter,
+ ...flex.justifyContentCenter,
+ ...objectFit.oFCover,
+ },
+
+ globalNavigation: {
+ width: variables.globalNavigationWidth,
+ backgroundColor: theme.highlightBG,
+ },
+
+ globalNavigationMenuContainer: {
+ marginTop: 13,
+ },
+
+ globalAndSubNavigationContainer: {
+ backgroundColor: theme.highlightBG,
+ },
+
+ globalNavigationSelectionIndicator: (isFocused: boolean) => ({
+ width: 4,
+ height: 52,
+ borderTopRightRadius: variables.componentBorderRadiusRounded,
+ borderBottomRightRadius: variables.componentBorderRadiusRounded,
+ backgroundColor: isFocused ? theme.iconMenu : theme.transparent,
+ }),
+
+ globalNavigationMenuItem: (isFocused: boolean) => (isFocused ? {color: theme.text, fontWeight: fontWeightBold, fontFamily: fontFamily.EXP_NEUE_BOLD} : {color: theme.icon}),
+
+ globalNavigationItemContainer: {
+ width: variables.globalNavigationWidth,
+ height: variables.globalNavigationWidth,
+ },
+
+ walletCard: {
+ borderRadius: variables.componentBorderRadiusLarge,
+ position: 'relative',
+ alignSelf: 'center',
+ overflow: 'hidden',
+ },
+
+ walletCardMenuItem: {
+ color: theme.text,
+ fontSize: variables.fontSizeNormal,
+ },
+
+ walletCardHolder: {
+ position: 'absolute',
+ left: 16,
+ bottom: 16,
+ width: variables.cardNameWidth,
+ color: theme.text,
+ fontSize: variables.fontSizeSmall,
+ lineHeight: variables.lineHeightLarge,
+ },
+
+ walletBalance: {
+ lineHeight: undefined,
+ fontSize: 45,
+ paddingTop: 0,
+ paddingBottom: 0,
+ },
+
+ aspectRatioLottie: (source) => {
+ if (!source.uri && typeof source === 'object' && source.w && source.h) {
+ return {aspectRatio: source.w / source.h};
+ }
+ return {};
+ },
+
+ receiptDropHeaderGap: {
+ backgroundColor: theme.receiptDropUIBG,
+ },
+
+ checkboxWithLabelCheckboxStyle: {
+ marginLeft: -2,
+ },
+ } satisfies Styles);
+
+// For now we need to export the styles function that takes the theme as an argument
+// as something named different than "styles", because a lot of files import the "defaultStyles"
+// as "styles", which causes ESLint to throw an error.
+// TODO: Remove "stylesGenerator" and instead only return "styles" once the app is migrated to theme switching hooks and HOCs and "styles/theme/default.js" is not used anywhere anymore (GH issue: https://github.com/Expensify/App/issues/27337)
+const stylesGenerator = styles;
+const defaultStyles = styles(defaultTheme);
+
+export default defaultStyles;
+export {stylesGenerator};
diff --git a/src/styles/themes/default.js b/src/styles/themes/default.ts
similarity index 96%
rename from src/styles/themes/default.js
rename to src/styles/themes/default.ts
index db4719f5548a..aabe9140bf9d 100644
--- a/src/styles/themes/default.js
+++ b/src/styles/themes/default.ts
@@ -1,7 +1,6 @@
-/* eslint-disable no-unused-vars */
-import colors from '../colors';
import SCREENS from '../../SCREENS';
-import ROUTES from '../../ROUTES';
+import colors from '../colors';
+import type {ThemeBase} from './types';
const darkTheme = {
// Figma keys
@@ -82,9 +81,10 @@ const darkTheme = {
QRLogo: colors.green400,
starDefaultBG: 'rgb(254, 228, 94)',
loungeAccessOverlay: colors.blue800,
- selectionListIndicatorColor: colors.white,
mapAttributionText: colors.black,
-};
+ PAGE_BACKGROUND_COLORS: {},
+ white: colors.white,
+} satisfies ThemeBase;
darkTheme.PAGE_BACKGROUND_COLORS = {
[SCREENS.HOME]: darkTheme.sidebar,
diff --git a/src/styles/themes/light.js b/src/styles/themes/light.ts
similarity index 94%
rename from src/styles/themes/light.js
rename to src/styles/themes/light.ts
index 3c80eb589a07..cd3079c3313f 100644
--- a/src/styles/themes/light.js
+++ b/src/styles/themes/light.ts
@@ -1,5 +1,6 @@
-import colors from '../colors';
import SCREENS from '../../SCREENS';
+import colors from '../colors';
+import type {ThemeDefault} from './types';
const lightTheme = {
// Figma keys
@@ -60,7 +61,7 @@ const lightTheme = {
heroCard: colors.blue400,
uploadPreviewActivityIndicator: colors.lightHighlightBackground,
dropUIBG: 'rgba(252, 251, 249, 0.92)',
- dropTransparentOverlay: 'rgba(255,255,255,0)',
+ receiptDropUIBG: 'rgba(3, 212, 124, 0.84)',
checkBox: colors.green400,
pickerOptionsTextColor: colors.lightPrimaryText,
imageCropBackgroundColor: colors.lightIcons,
@@ -81,12 +82,15 @@ const lightTheme = {
starDefaultBG: 'rgb(254, 228, 94)',
loungeAccessOverlay: colors.blue800,
mapAttributionText: colors.black,
-};
+ PAGE_BACKGROUND_COLORS: {},
+ white: colors.white,
+} satisfies ThemeDefault;
lightTheme.PAGE_BACKGROUND_COLORS = {
[SCREENS.HOME]: lightTheme.sidebar,
[SCREENS.SAVE_THE_WORLD.ROOT]: colors.tangerine800,
[SCREENS.SETTINGS.PREFERENCES]: colors.blue500,
+ [SCREENS.SETTINGS.WALLET]: colors.green700,
[SCREENS.SETTINGS.WORKSPACES]: colors.pink800,
[SCREENS.SETTINGS.SECURITY]: colors.ice500,
[SCREENS.SETTINGS.STATUS]: colors.green700,
diff --git a/src/styles/themes/types.ts b/src/styles/themes/types.ts
new file mode 100644
index 000000000000..40b8da361654
--- /dev/null
+++ b/src/styles/themes/types.ts
@@ -0,0 +1,8 @@
+import DeepRecord from '../../types/utils/DeepRecord';
+import defaultTheme from './default';
+
+type ThemeBase = DeepRecord;
+
+type ThemeDefault = typeof defaultTheme;
+
+export type {ThemeBase, ThemeDefault};
diff --git a/src/styles/utilities/cursor/types.ts b/src/styles/utilities/cursor/types.ts
index 9ca20c5ae123..e9cfc120b161 100644
--- a/src/styles/utilities/cursor/types.ts
+++ b/src/styles/utilities/cursor/types.ts
@@ -1,4 +1,4 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
type CursorStylesKeys =
| 'cursorDefault'
@@ -13,6 +13,6 @@ type CursorStylesKeys =
| 'cursorInitial'
| 'cursorText';
-type CursorStyles = Record>>;
+type CursorStyles = Record>;
export default CursorStyles;
diff --git a/src/styles/utilities/display.ts b/src/styles/utilities/display.ts
index 868c2bdb0e3b..f14a25d641b1 100644
--- a/src/styles/utilities/display.ts
+++ b/src/styles/utilities/display.ts
@@ -1,4 +1,3 @@
-import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
/**
@@ -20,15 +19,35 @@ export default {
display: 'none',
},
+ /**
+ * Web-only style.
+ */
dInline: {
- display: 'inline',
+ // NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
+ display: 'inline' as ViewStyle['display'],
},
+ /**
+ * Web-only style.
+ */
dInlineFlex: {
- display: 'inline-flex',
+ // NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
+ display: 'inline-flex' as ViewStyle['display'],
},
+ /**
+ * Web-only style.
+ */
dBlock: {
- display: 'block',
+ // NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
+ display: 'block' as ViewStyle['display'],
},
-} satisfies Record;
+
+ /**
+ * Web-only style.
+ */
+ dGrid: {
+ // NOTE: asserting "display" to a valid type, because it isn't possible to augment "display".
+ display: 'grid' as ViewStyle['display'],
+ },
+} satisfies Record;
diff --git a/src/styles/utilities/overflow.ts b/src/styles/utilities/overflow.ts
index 48807283c9b4..9b4fa010af84 100644
--- a/src/styles/utilities/overflow.ts
+++ b/src/styles/utilities/overflow.ts
@@ -1,4 +1,4 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
import overflowAuto from './overflowAuto';
import overscrollBehaviorContain from './overscrollBehaviorContain';
@@ -27,4 +27,4 @@ export default {
overscrollBehaviorContain,
overflowAuto,
-} satisfies Record;
+} satisfies Record;
diff --git a/src/styles/utilities/overflowAuto/index.ts b/src/styles/utilities/overflowAuto/index.ts
index 0eb19068738f..1e7ac8ed8246 100644
--- a/src/styles/utilities/overflowAuto/index.ts
+++ b/src/styles/utilities/overflowAuto/index.ts
@@ -1,7 +1,12 @@
+import {ViewStyle} from 'react-native';
import OverflowAutoStyles from './types';
+/**
+ * Web-only style.
+ */
const overflowAuto: OverflowAutoStyles = {
- overflow: 'auto',
+ // NOTE: asserting "overflow" to a valid type, because it isn't possible to augment "overflow".
+ overflow: 'auto' as ViewStyle['overflow'],
};
export default overflowAuto;
diff --git a/src/styles/utilities/overflowAuto/types.ts b/src/styles/utilities/overflowAuto/types.ts
index faba7c2cbdb8..da7548d49e7b 100644
--- a/src/styles/utilities/overflowAuto/types.ts
+++ b/src/styles/utilities/overflowAuto/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
-type OverflowAutoStyles = Pick;
+type OverflowAutoStyles = Pick;
export default OverflowAutoStyles;
diff --git a/src/styles/utilities/positioning.ts b/src/styles/utilities/positioning.ts
index 651d2a12f2ea..26e6198a5827 100644
--- a/src/styles/utilities/positioning.ts
+++ b/src/styles/utilities/positioning.ts
@@ -11,6 +11,14 @@ export default {
pAbsolute: {
position: 'absolute',
},
+ /**
+ * Web-only style.
+ */
+ pFixed: {
+ // NOTE: asserting "position" to a valid type, because it isn't possible to augment "position".
+ position: 'fixed' as ViewStyle['position'],
+ },
+
t0: {
top: 0,
},
diff --git a/src/styles/utilities/spacing.ts b/src/styles/utilities/spacing.ts
index 372fa7cf636f..e2b161ca0d62 100644
--- a/src/styles/utilities/spacing.ts
+++ b/src/styles/utilities/spacing.ts
@@ -199,6 +199,10 @@ export default {
marginTop: 24,
},
+ mt7: {
+ marginTop: 28,
+ },
+
mt8: {
marginTop: 32,
},
diff --git a/src/styles/utilities/textUnderline/types.ts b/src/styles/utilities/textUnderline/types.ts
index ecc09ed0fe09..f71d2bfdaa9a 100644
--- a/src/styles/utilities/textUnderline/types.ts
+++ b/src/styles/utilities/textUnderline/types.ts
@@ -1,8 +1,8 @@
-import {CSSProperties} from 'react';
+import {TextStyle} from 'react-native';
type TextUnderlineStyles = {
- textUnderlinePositionUnder: Pick;
- textDecorationSkipInkNone: Pick;
+ textUnderlinePositionUnder: Pick;
+ textDecorationSkipInkNone: Pick;
};
export default TextUnderlineStyles;
diff --git a/src/styles/utilities/userSelect/types.ts b/src/styles/utilities/userSelect/types.ts
index 67a8c9c7b9b6..a177bac5a3e7 100644
--- a/src/styles/utilities/userSelect/types.ts
+++ b/src/styles/utilities/userSelect/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {TextStyle} from 'react-native';
-type UserSelectStyles = Record<'userSelectText' | 'userSelectNone', Partial>>;
+type UserSelectStyles = Record<'userSelectText' | 'userSelectNone', Pick>;
export default UserSelectStyles;
diff --git a/src/styles/utilities/visibility/types.ts b/src/styles/utilities/visibility/types.ts
index 9dab3d7c752e..64bdbdd2cca6 100644
--- a/src/styles/utilities/visibility/types.ts
+++ b/src/styles/utilities/visibility/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {ViewStyle} from 'react-native';
-type VisibilityStyles = Record<'visible' | 'hidden', Partial>>;
+type VisibilityStyles = Record<'visible' | 'hidden', Pick>;
export default VisibilityStyles;
diff --git a/src/styles/utilities/whiteSpace/types.ts b/src/styles/utilities/whiteSpace/types.ts
index c42dc14080b1..b10671f04977 100644
--- a/src/styles/utilities/whiteSpace/types.ts
+++ b/src/styles/utilities/whiteSpace/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {TextStyle} from 'react-native';
-type WhiteSpaceStyles = Record<'noWrap' | 'preWrap' | 'pre', Partial>>;
+type WhiteSpaceStyles = Record<'noWrap' | 'preWrap' | 'pre', Pick>;
export default WhiteSpaceStyles;
diff --git a/src/styles/utilities/wordBreak/types.ts b/src/styles/utilities/wordBreak/types.ts
index 003a5ca1c869..0ed520ae119d 100644
--- a/src/styles/utilities/wordBreak/types.ts
+++ b/src/styles/utilities/wordBreak/types.ts
@@ -1,5 +1,5 @@
-import {CSSProperties} from 'react';
+import {TextStyle} from 'react-native';
-type WordBreakStyles = Record<'breakWord' | 'breakAll', Partial>>;
+type WordBreakStyles = Record<'breakWord' | 'breakAll', Pick>;
export default WordBreakStyles;
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 020d742fdeb1..b3a074234828 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -23,7 +23,7 @@ export default {
componentBorderRadiusMedium: 6,
componentBorderRadiusNormal: 8,
componentBorderRadiusLarge: 16,
- componentBorderRadiusCard: 12,
+ componentBorderRadiusCard: 20,
componentBorderRadiusRounded: 24,
appModalAppIconSize: 48,
buttonBorderRadius: 100,
@@ -146,9 +146,11 @@ export default {
listItemHeightNormal: 64,
popoverWidth: 375,
addPaymentPopoverTopSpacing: 8,
- addPaymentPopoverRightSpacing: 13,
+ addPaymentPopoverRightSpacing: 23,
anonymousReportFooterBreakpoint: 650,
dropDownButtonDividerHeight: 28,
+ addPaymentMethodLeftSpacing: 2,
+ addBankAccountLeftSpacing: 3,
eReceiptThumbnailSmallBreakpoint: 110,
eReceiptThumbnailMediumBreakpoint: 335,
eReceiptThumnailCenterReceiptBreakpoint: 200,
@@ -165,6 +167,10 @@ export default {
eReceiptWordmarkWidth: 86,
eReceiptBGHeight: 540,
eReceiptBGHWidth: 335,
+ reportPreviewMaxWidth: 302,
+ reportActionImagesSingleImageHeight: 147,
+ reportActionImagesDoubleImageHeight: 138,
+ reportActionImagesMultipleImageHeight: 110,
// The height of the empty list is 14px (2px for borders and 12px for vertical padding)
// This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility
diff --git a/src/types/modules/pusher.d.ts b/src/types/modules/pusher.d.ts
new file mode 100644
index 000000000000..b54a0508c309
--- /dev/null
+++ b/src/types/modules/pusher.d.ts
@@ -0,0 +1,8 @@
+import Pusher from 'pusher-js/types/src/core/pusher';
+
+declare global {
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+ interface Window {
+ getPusherInstance: () => Pusher | null;
+ }
+}
diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts
index ebe0974db690..0659cc4e4b4a 100644
--- a/src/types/modules/react-native.d.ts
+++ b/src/types/modules/react-native.d.ts
@@ -1,8 +1,343 @@
+/* eslint-disable @typescript-eslint/naming-convention */
+/* eslint-disable @typescript-eslint/no-empty-interface */
/* eslint-disable @typescript-eslint/consistent-type-definitions */
+import {CSSProperties, FocusEventHandler, KeyboardEventHandler, MouseEventHandler, PointerEventHandler, UIEventHandler, WheelEventHandler} from 'react';
import 'react-native';
import {BootSplashModule} from '../../libs/BootSplash/types';
declare module 'react-native' {
+ // <------ REACT NATIVE WEB (0.19.0) ------>
+ // Extracted from react-native-web, packages/react-native-web/src/exports/View/types.js
+ type idRef = string;
+ type idRefList = idRef | idRef[];
+
+ // https://necolas.github.io/react-native-web/docs/accessibility/#accessibility-props-api
+ // Extracted from react-native-web, packages/react-native-web/src/exports/View/types.js
+ interface AccessibilityProps {
+ 'aria-activedescendant'?: idRef;
+ 'aria-atomic'?: boolean;
+ 'aria-autocomplete'?: 'none' | 'list' | 'inline' | 'both';
+ 'aria-busy'?: boolean;
+ 'aria-checked'?: boolean | 'mixed';
+ 'aria-colcount'?: number;
+ 'aria-colindex'?: number;
+ 'aria-colspan'?: number;
+ 'aria-controls'?: idRef;
+ 'aria-current'?: boolean | 'page' | 'step' | 'location' | 'date' | 'time';
+ 'aria-describedby'?: idRef;
+ 'aria-details'?: idRef;
+ 'aria-disabled'?: boolean;
+ 'aria-errormessage'?: idRef;
+ 'aria-expanded'?: boolean;
+ 'aria-flowto'?: idRef;
+ 'aria-haspopup'?: 'dialog' | 'grid' | 'listbox' | 'menu' | 'tree' | false;
+ 'aria-hidden'?: boolean;
+ 'aria-invalid'?: boolean;
+ 'aria-keyshortcuts'?: string[];
+ 'aria-label'?: string;
+ 'aria-labelledby'?: idRef;
+ 'aria-level'?: number;
+ 'aria-live'?: 'assertive' | 'none' | 'polite';
+ 'aria-modal'?: boolean;
+ 'aria-multiline'?: boolean;
+ 'aria-multiselectable'?: boolean;
+ 'aria-orientation'?: 'horizontal' | 'vertical';
+ 'aria-owns'?: idRef;
+ 'aria-placeholder'?: string;
+ 'aria-posinset'?: number;
+ 'aria-pressed'?: boolean | 'mixed';
+ 'aria-readonly'?: boolean;
+ 'aria-required'?: boolean;
+ 'aria-roledescription'?: string;
+ 'aria-rowcount'?: number;
+ 'aria-rowindex'?: number;
+ 'aria-rowspan'?: number;
+ 'aria-selected'?: boolean;
+ 'aria-setsize'?: number;
+ 'aria-sort'?: 'ascending' | 'descending' | 'none' | 'other';
+ 'aria-valuemax'?: number;
+ 'aria-valuemin'?: number;
+ 'aria-valuenow'?: number;
+ 'aria-valuetext'?: string;
+ role?: string;
+
+ // @deprecated
+ accessibilityActiveDescendant?: idRef;
+ accessibilityAtomic?: boolean;
+ accessibilityAutoComplete?: 'none' | 'list' | 'inline' | 'both';
+ accessibilityBusy?: boolean;
+ accessibilityChecked?: boolean | 'mixed';
+ accessibilityColumnCount?: number;
+ accessibilityColumnIndex?: number;
+ accessibilityColumnSpan?: number;
+ accessibilityControls?: idRefList;
+ accessibilityCurrent?: boolean | 'page' | 'step' | 'location' | 'date' | 'time';
+ accessibilityDescribedBy?: idRefList;
+ accessibilityDetails?: idRef;
+ accessibilityDisabled?: boolean;
+ accessibilityErrorMessage?: idRef;
+ accessibilityExpanded?: boolean;
+ accessibilityFlowTo?: idRefList;
+ accessibilityHasPopup?: 'dialog' | 'grid' | 'listbox' | 'menu' | 'tree' | false;
+ accessibilityHidden?: boolean;
+ accessibilityInvalid?: boolean;
+ accessibilityKeyShortcuts?: string[];
+ accessibilityLabel?: string;
+ accessibilityLabelledBy?: idRefList;
+ accessibilityLevel?: number;
+ accessibilityLiveRegion?: 'assertive' | 'none' | 'polite';
+ accessibilityModal?: boolean;
+ accessibilityMultiline?: boolean;
+ accessibilityMultiSelectable?: boolean;
+ accessibilityOrientation?: 'horizontal' | 'vertical';
+ accessibilityOwns?: idRefList;
+ accessibilityPlaceholder?: string;
+ accessibilityPosInSet?: number;
+ accessibilityPressed?: boolean | 'mixed';
+ accessibilityReadOnly?: boolean;
+ accessibilityRequired?: boolean;
+ accessibilityRole?: string;
+ accessibilityRoleDescription?: string;
+ accessibilityRowCount?: number;
+ accessibilityRowIndex?: number;
+ accessibilityRowSpan?: number;
+ accessibilitySelected?: boolean;
+ accessibilitySetSize?: number;
+ accessibilitySort?: 'ascending' | 'descending' | 'none' | 'other';
+ accessibilityValueMax?: number;
+ accessibilityValueMin?: number;
+ accessibilityValueNow?: number;
+ accessibilityValueText?: string;
+ }
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#pointerevent-props-api
+ // Extracted properties from react-native-web, packages/react-native-web/src/exports/View/types.js and packages/react-native-web/src/modules/forwardedProps/index.js
+ // Extracted types from @types/react, index.d.ts
+ interface PointerProps {
+ onAuxClick?: MouseEventHandler;
+ onClick?: MouseEventHandler;
+ onContextMenu?: MouseEventHandler;
+ onGotPointerCapture?: PointerEventHandler;
+ onLostPointerCapture?: PointerEventHandler;
+ onPointerCancel?: PointerEventHandler;
+ onPointerDown?: PointerEventHandler;
+ onPointerEnter?: PointerEventHandler;
+ onPointerMove?: PointerEventHandler;
+ onPointerLeave?: PointerEventHandler;
+ onPointerOut?: PointerEventHandler;
+ onPointerOver?: PointerEventHandler;
+ onPointerUp?: PointerEventHandler;
+ onMouseDown?: MouseEventHandler;
+ onMouseEnter?: MouseEventHandler;
+ onMouseLeave?: MouseEventHandler;
+ onMouseMove?: MouseEventHandler;
+ onMouseOver?: MouseEventHandler;
+ onMouseOut?: MouseEventHandler;
+ onMouseUp?: MouseEventHandler;
+ onScroll?: UIEventHandler;
+ onWheel?: WheelEventHandler;
+ }
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#responderevent-props-api
+ // Extracted from react-native-web, packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js
+ type TouchRecord = {
+ currentPageX: number;
+ currentPageY: number;
+ currentTimeStamp: number;
+ previousPageX: number;
+ previousPageY: number;
+ previousTimeStamp: number;
+ startPageX: number;
+ startPageY: number;
+ startTimeStamp: number;
+ touchActive: boolean;
+ };
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#responderevent-props-api
+ // Extracted from react-native-web, packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js
+ type TouchHistory = Readonly<{
+ indexOfSingleActiveTouch: number;
+ mostRecentTimeStamp: number;
+ numberActiveTouches: number;
+ touchBank: TouchRecord[];
+ }>;
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#responderevent-props-api
+ // Extracted from react-native-web, packages/react-native-web/src/modules/useResponderEvents/createResponderEvent.js
+ type ResponderEvent = {
+ bubbles: boolean;
+ cancelable: boolean;
+ currentTarget?: unknown; // changed from "any" to "unknown"
+ defaultPrevented?: boolean;
+ dispatchConfig: {
+ registrationName?: string;
+ phasedRegistrationNames?: {
+ bubbled: string;
+ captured: string;
+ };
+ };
+ eventPhase?: number;
+ isDefaultPrevented: () => boolean;
+ isPropagationStopped: () => boolean;
+ isTrusted?: boolean;
+ preventDefault: () => void;
+ stopPropagation: () => void;
+ nativeEvent: TouchEvent;
+ persist: () => void;
+ target?: unknown; // changed from "any" to "unknown"
+ timeStamp: number;
+ touchHistory: TouchHistory;
+ };
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#responderevent-props-api
+ // Extracted from react-native-web, packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js
+ interface ResponderProps {
+ // Direct responder events dispatched directly to responder. Do not bubble.
+ onResponderEnd?: (e: ResponderEvent) => void;
+ onResponderGrant?: (e: ResponderEvent) => void | boolean;
+ onResponderMove?: (e: ResponderEvent) => void;
+ onResponderRelease?: (e: ResponderEvent) => void;
+ onResponderReject?: (e: ResponderEvent) => void;
+ onResponderStart?: (e: ResponderEvent) => void;
+ onResponderTerminate?: (e: ResponderEvent) => void;
+ onResponderTerminationRequest?: (e: ResponderEvent) => boolean;
+
+ // On pointer down, should this element become the responder?
+ onStartShouldSetResponder?: (e: ResponderEvent) => boolean;
+ onStartShouldSetResponderCapture?: (e: ResponderEvent) => boolean;
+
+ // On pointer move, should this element become the responder?
+ onMoveShouldSetResponder?: (e: ResponderEvent) => boolean;
+ onMoveShouldSetResponderCapture?: (e: ResponderEvent) => boolean;
+
+ // On scroll, should this element become the responder? Do no bubble
+ onScrollShouldSetResponder?: (e: ResponderEvent) => boolean;
+ onScrollShouldSetResponderCapture?: (e: ResponderEvent) => boolean;
+
+ // On text selection change, should this element become the responder?
+ onSelectionChangeShouldSetResponder?: (e: ResponderEvent) => boolean;
+ onSelectionChangeShouldSetResponderCapture?: (e: ResponderEvent) => boolean;
+ }
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#focusevent-props-api
+ // Extracted properties from react-native-web, packages/react-native-web/src/exports/View/types.js and packages/react-native-web/src/modules/forwardedProps/index.js
+ // Extracted types from @types/react, index.d.ts
+ interface FocusProps {
+ onBlur?: FocusEventHandler;
+ onFocus?: FocusEventHandler;
+ }
+
+ // https://necolas.github.io/react-native-web/docs/interactions/#keyboardevent-props-api
+ // Extracted properties from react-native-web, packages/react-native-web/src/exports/View/types.js and packages/react-native-web/src/modules/forwardedProps/index.js
+ // Extracted types from @types/react, index.d.ts
+ interface KeyboardProps {
+ onKeyDown?: KeyboardEventHandler;
+ onKeyDownCapture?: KeyboardEventHandler;
+ onKeyUp?: KeyboardEventHandler;
+ onKeyUpCapture?: KeyboardEventHandler;
+ }
+
+ /**
+ * Shared props
+ * Extracted from react-native-web, packages/react-native-web/src/exports/View/types.js
+ */
+ interface WebSharedProps extends AccessibilityProps, PointerProps, ResponderProps, FocusProps, KeyboardProps {
+ dataSet?: Record;
+ href?: string;
+ hrefAttrs?: {
+ download?: boolean;
+ rel?: string;
+ target?: string;
+ };
+ tabIndex?: 0 | -1;
+ lang?: string;
+ }
+
+ /**
+ * View
+ * Extracted from react-native-web, packages/react-native-web/src/exports/View/types.js
+ */
+ interface WebViewProps extends WebSharedProps {
+ dir?: 'ltr' | 'rtl';
+ }
+ interface ViewProps extends WebViewProps {}
+
+ /**
+ * Text
+ * Extracted from react-native-web, packages/react-native-web/src/exports/Text/types.js
+ */
+ interface WebTextProps extends WebSharedProps {
+ dir?: 'auto' | 'ltr' | 'rtl';
+ }
+ interface TextProps extends WebTextProps {}
+
+ /**
+ * TextInput
+ * Extracted from react-native-web, packages/react-native-web/src/exports/TextInput/types.js
+ */
+ interface WebTextInputProps extends WebSharedProps {
+ dir?: 'auto' | 'ltr' | 'rtl';
+ disabled?: boolean;
+ enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
+ readOnly?: boolean;
+ }
+ interface TextInputProps extends WebTextInputProps {}
+
+ /**
+ * Image
+ * Extracted from react-native-web, packages/react-native-web/src/exports/Image/types.js
+ */
+ interface WebImageProps extends WebSharedProps {
+ dir?: 'ltr' | 'rtl';
+ draggable?: boolean;
+ }
+ interface ImageProps extends WebImageProps {}
+
+ /**
+ * ScrollView
+ * Extracted from react-native-web, packages/react-native-web/src/exports/ScrollView/ScrollViewBase.js
+ */
+ interface WebScrollViewProps extends WebSharedProps {}
+ interface ScrollViewProps extends WebScrollViewProps {}
+
+ /**
+ * Pressable
+ */
+ // https://necolas.github.io/react-native-web/docs/pressable/#interactionstate
+ // Extracted from react-native-web, packages/react-native-web/src/exports/Pressable/index.js
+ interface WebPressableStateCallbackType {
+ readonly focused: boolean;
+ readonly hovered: boolean;
+ readonly pressed: boolean;
+ }
+ interface PressableStateCallbackType extends WebPressableStateCallbackType {}
+
+ // Extracted from react-native-web, packages/react-native-web/src/exports/Pressable/index.js
+ interface WebPressableProps extends WebSharedProps {
+ delayPressIn?: number;
+ delayPressOut?: number;
+ onPressMove?: null | ((event: GestureResponderEvent) => void);
+ onPressEnd?: null | ((event: GestureResponderEvent) => void);
+ }
+ interface PressableProps extends WebPressableProps {}
+
+ /**
+ * Styles
+ */
+ // We extend CSSProperties (alias to "csstype" library) which provides all CSS style properties for Web,
+ // but properties that are already defined on RN won't be overrided / augmented.
+ interface WebStyle extends CSSProperties {
+ // https://necolas.github.io/react-native-web/docs/styling/#non-standard-properties
+ // Exclusive to react-native-web, "pointerEvents" already included on RN
+ animationKeyframes?: string | Record;
+ writingDirection?: 'auto' | 'ltr' | 'rtl';
+ }
+
+ interface ViewStyle extends WebStyle {}
+ interface TextStyle extends WebStyle {}
+ interface ImageStyle extends WebStyle {}
+ // <------ REACT NATIVE WEB (0.19.0) ------>
+
interface TextInput {
// Typescript type declaration is missing in React Native for setting text selection.
setSelection: (start: number, end: number) => void;
diff --git a/src/types/utils/DeepRecord.ts b/src/types/utils/DeepRecord.ts
new file mode 100644
index 000000000000..fba14c75d679
--- /dev/null
+++ b/src/types/utils/DeepRecord.ts
@@ -0,0 +1,7 @@
+/**
+ * Represents a deeply nested record. It maps keys to values,
+ * and those values can either be of type `TValue` or further nested `DeepRecord` instances.
+ */
+type DeepRecord = {[key: string]: TValue | DeepRecord};
+
+export default DeepRecord;
diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js
index 3df3b137bab3..63fd7a0dd78b 100644
--- a/tests/actions/IOUTest.js
+++ b/tests/actions/IOUTest.js
@@ -1638,7 +1638,7 @@ describe('actions/IOU', () => {
expect(resultAction.message).toEqual(REPORT_ACTION.message);
expect(resultAction.person).toEqual(REPORT_ACTION.person);
- expect(resultAction.pendingAction).toBeNull();
+ expect(resultAction.pendingAction).toBeUndefined();
await waitForBatchedUpdates();
@@ -1647,7 +1647,7 @@ describe('actions/IOU', () => {
// Then check the loading state of our action
const resultActionAfterUpdate = reportActions[reportActionID];
- expect(resultActionAfterUpdate.pendingAction).toBeNull();
+ expect(resultActionAfterUpdate.pendingAction).toBeUndefined();
// When we attempt to delete a money request from the IOU report
fetch.pause();
@@ -1818,7 +1818,7 @@ describe('actions/IOU', () => {
// Then the report should have 2 actions
expect(_.size(reportActions)).toBe(2);
const resultActionAfter = reportActions[reportActionID];
- expect(resultActionAfter.pendingAction).toBeNull();
+ expect(resultActionAfter.pendingAction).toBeUndefined();
fetch.pause();
// When deleting money request
@@ -1903,7 +1903,7 @@ describe('actions/IOU', () => {
expect(resultAction.message).toEqual(REPORT_ACTION.message);
expect(resultAction.person).toEqual(REPORT_ACTION.person);
- expect(resultAction.pendingAction).toBeNull();
+ expect(resultAction.pendingAction).toBeUndefined();
await waitForBatchedUpdates();
@@ -1913,7 +1913,7 @@ describe('actions/IOU', () => {
let resultActionAfterUpdate = reportActions[reportActionID];
// Verify that our action is no longer in the loading state
- expect(resultActionAfterUpdate.pendingAction).toBeNull();
+ expect(resultActionAfterUpdate.pendingAction).toBeUndefined();
await waitForBatchedUpdates();
@@ -1935,7 +1935,7 @@ describe('actions/IOU', () => {
expect(resultAction.message).toEqual(REPORT_ACTION.message);
expect(resultAction.person).toEqual(REPORT_ACTION.person);
- expect(resultAction.pendingAction).toBeNull();
+ expect(resultAction.pendingAction).toBeUndefined();
await waitForBatchedUpdates();
@@ -1945,7 +1945,7 @@ describe('actions/IOU', () => {
resultActionAfterUpdate = reportActions[reportActionID];
// Verify that our action is no longer in the loading state
- expect(resultActionAfterUpdate.pendingAction).toBeNull();
+ expect(resultActionAfterUpdate.pendingAction).toBeUndefined();
fetch.pause();
// When we delete the money request
diff --git a/tests/actions/ReportTest.js b/tests/actions/ReportTest.js
index c7ef68547cdc..68a50fe4f130 100644
--- a/tests/actions/ReportTest.js
+++ b/tests/actions/ReportTest.js
@@ -93,7 +93,7 @@ describe('actions/Report', () => {
expect(resultAction.message).toEqual(REPORT_ACTION.message);
expect(resultAction.person).toEqual(REPORT_ACTION.person);
- expect(resultAction.pendingAction).toBeNull();
+ expect(resultAction.pendingAction).toBeUndefined();
// We subscribed to the Pusher channel above and now we need to simulate a reportComment action
// Pusher event so we can verify that action was handled correctly and merged into the reportActions.
@@ -130,7 +130,7 @@ describe('actions/Report', () => {
const resultAction = reportActions[reportActionID];
// Verify that our action is no longer in the loading state
- expect(resultAction.pendingAction).toBeNull();
+ expect(resultAction.pendingAction).toBeUndefined();
});
});
@@ -608,7 +608,7 @@ describe('actions/Report', () => {
// Expect the reaction to have null where the users reaction used to be
expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
- expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeUndefined();
})
.then(() => {
reportAction = _.first(_.values(reportActions));
@@ -650,7 +650,7 @@ describe('actions/Report', () => {
// Expect the reaction to have null where the users reaction used to be
expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`];
- expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeUndefined();
});
});
});
@@ -717,7 +717,7 @@ describe('actions/Report', () => {
// Expect the reaction to have null where the users reaction used to be
expect(reportActionsReactions).toHaveProperty(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction.reportActionID}`);
const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction.reportActionID}`];
- expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeNull();
+ expect(reportActionReaction[EMOJI.name].users[TEST_USER_ACCOUNT_ID]).toBeUndefined();
});
});
});
diff --git a/tests/unit/MigrationTest.js b/tests/unit/MigrationTest.js
index bed273213c90..d0e7f19d3d3f 100644
--- a/tests/unit/MigrationTest.js
+++ b/tests/unit/MigrationTest.js
@@ -37,18 +37,12 @@ describe('Migrations', () => {
})
.then(PersonalDetailsByAccountID)
.then(() => {
- expect(LogSpy).toHaveBeenCalledWith(
- `[Migrate Onyx] Skipped migration PersonalDetailsByAccountID for ${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1 because there were no reportActions`,
- );
- expect(LogSpy).toHaveBeenCalledWith(
- `[Migrate Onyx] Skipped migration PersonalDetailsByAccountID for ${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2 because there were no reportActions`,
- );
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
- _.each(allReportActions, (reportActionsForReport) => expect(reportActionsForReport).toBeNull());
+ _.each(allReportActions, (reportActionsForReport) => expect(reportActionsForReport).toBeUndefined());
},
});
}));
@@ -377,8 +371,8 @@ describe('Migrations', () => {
waitForCollectionCallback: true,
callback: (allPolicyMemberLists) => {
Onyx.disconnect(connectionID);
- expect(allPolicyMemberLists[`${ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST}1`]).toBeNull();
- expect(allPolicyMemberLists[`${ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST}2`]).toBeNull();
+
+ expect(allPolicyMemberLists).toBeFalsy();
},
});
}));
@@ -554,8 +548,8 @@ describe('Migrations', () => {
Onyx.disconnect(connectionID);
const expectedReportAction = {};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction);
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toMatchObject(expectedReportAction);
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toMatchObject(expectedReportAction);
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toBeUndefined();
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toBeUndefined();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toMatchObject(expectedReportAction);
},
});
@@ -597,8 +591,8 @@ describe('Migrations', () => {
},
};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction1);
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toBeNull();
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toBeNull();
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toBeUndefined();
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toBeUndefined();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toMatchObject(expectedReportAction4);
},
});
@@ -620,10 +614,10 @@ describe('Migrations', () => {
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction = {};
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toBeNull();
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toBeUndefined();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toMatchObject(expectedReportAction);
- expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toBeNull();
+ expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toBeUndefined();
},
});
}));