@totalpave/cordova-plugin-insets 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,37 @@
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## 0.2.0 (TBD)
8
+
9
+ ### Breaking Changes:
10
+
11
+ These are the breaking changes in this release.
12
+
13
+ #### cordova-android@11 or later requirement
14
+
15
+ Starting with 0.2.0, we will need cordova-android@11 or later.
16
+ This is because we are using API 31+ APIs when available.
17
+ While we SDK guard our usage, we still need to compile with SDK 31+ and cordova-android@11 by default will compile with SDK 32.
18
+
19
+ #### Removal of Babel
20
+
21
+ TotalPave has been removing usage of Babel in their builds across several of their packages and instead letting Typescript transpile down to a sensible ES target.
22
+
23
+ Starting with 0.2.0, we will be targeting [ES 2017](https://caniuse.com/?search=es2017) which has pretty wide support on major browsers dating back about a decade.
24
+
25
+ We find that removing Babel leads to more simplified and less broken sourcemaps, as well as simplier dependency trees.
26
+
27
+ #### Rounded Corners
28
+
29
+ Starting with 0.2.0, coming back to the API 31+ usages, this plugin will now count for rounded corners on devices. If the screen has a rounded corner take the radius of the rounded corner and potentially use it for the inset value.
30
+
31
+ Insets from rounded corners are not additive. If there is an inset present already from a system bar or display cutout, we will use only one or the other, whichever is larger. This is because rounded corners are not resolved in the same way as system bars/display cutouts and any existing inset will likely already clear the rounded corner radius.
32
+
33
+ The API to get rounded corner information is available only on API 31 and later devices. Therefore, older devices, including devices that still have rounded corners but are running on an older API level will not have rounded corners counted for in the given insets.
34
+
35
+ ## 0.1.10 (November 2, 2023)
36
+ - Fixed insets to count for display cutouts, such as camera pinholes or islands.
37
+
7
38
  ## 0.1.7 (July 6, 2023)
8
39
  - Fixed clobbers namespace to merge instead, since this particular plugin targets a shared namespace.
9
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totalpave/cordova-plugin-insets",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "Cordova Android Plugin to receive native information regarding the unsafe area insets.",
5
5
  "main": "www/insets.js",
6
6
  "types": "www/api.d.ts",
@@ -11,6 +11,7 @@
11
11
  "scripts": {
12
12
  "build": "rollup -c rollup.config.js --bundleConfigAsCjs",
13
13
  "version": "NODE_ENV=production npm run-script build",
14
+ "prepack": "ejs --output-file plugin.xml plugin.xml.ejs version=$npm_package_version",
14
15
  "postversion": "git push && git push --tags",
15
16
  "publish-dev": "npm publish --tag dev"
16
17
  },
@@ -25,28 +26,24 @@
25
26
  },
26
27
  "homepage": "https://github.com/totalpaveinc/cordova-plugin-insets#readme",
27
28
  "devDependencies": {
28
- "@babel/core": "7.22.8",
29
- "@babel/preset-env": "7.22.7",
30
- "@babel/preset-typescript": "7.22.5",
31
- "@babel/register": "7.22.5",
32
- "@rollup/plugin-babel": "6.0.3",
33
- "@rollup/plugin-commonjs": "25.0.2",
34
- "@rollup/plugin-node-resolve": "15.1.0",
35
- "@types/cordova": "11.0.0",
36
- "rollup": "3.26.2",
29
+ "@rollup/plugin-commonjs": "25.0.7",
30
+ "@rollup/plugin-node-resolve": "15.2.3",
31
+ "@types/cordova": "11.0.3",
32
+ "ejs": "3.1.9",
33
+ "rollup": "4.6.1",
37
34
  "rollup-plugin-progress": "1.1.2",
38
- "rollup-plugin-typescript2": "0.35.0",
35
+ "rollup-plugin-typescript2": "0.36.0",
39
36
  "ts-node": "10.9.1",
40
- "typescript": "5.1.6"
37
+ "typescript": "5.3.2"
41
38
  },
42
39
  "engines": {
43
40
  "cordovaDependencies": {
44
41
  "0.0.0": {
45
- "cordova-android": ">= 10"
42
+ "cordova-android": ">= 11"
46
43
  }
47
44
  }
48
45
  },
49
46
  "dependencies": {
50
- "tslib": "2.6.0"
47
+ "tslib": "2.6.2"
51
48
  }
52
49
  }
package/plugin.xml CHANGED
@@ -1,5 +1,9 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="@totalpave/cordova-plugin-insets" version="0.1.9">
2
+ <plugin
3
+ xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
+ id="@totalpave/cordova-plugin-insets"
5
+ version="0.2.0"
6
+ >
3
7
  <name>cordova-plugin-insets</name>
4
8
  <description>Cordova Android Plugin to receive native information regarding the unsafe area insets</description>
5
9
  <author>Total Pave Inc.</author>
package/plugin.xml.ejs ADDED
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <plugin
3
+ xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
+ id="@totalpave/cordova-plugin-insets"
5
+ version="<%= version %>"
6
+ >
7
+ <name>cordova-plugin-insets</name>
8
+ <description>Cordova Android Plugin to receive native information regarding the unsafe area insets</description>
9
+ <author>Total Pave Inc.</author>
10
+ <license>Apache 2.0</license>
11
+ <keywords>cordova,cordova-android,unsafe-inset</keywords>
12
+ <repo>https://github.com/totalpaveinc/cordova-plugin-unsafe-insets</repo>
13
+
14
+ <js-module src="www/insets.js" name="Insets">
15
+ <merges target="totalpave" />
16
+ </js-module>
17
+
18
+ <platform name="android">
19
+ <config-file target="res/xml/config.xml" parent="/*">
20
+ <feature name="Insets">
21
+ <param name="android-package" value="com.totalpave.cordova.insets.Insets" />
22
+ </feature>
23
+ </config-file>
24
+
25
+ <source-file src="src/android/com/totalpave/cordova/insets/Insets.java" target-dir="src/com/totalpave/cordova/insets" />
26
+ </platform>
27
+ </plugin>
@@ -15,18 +15,19 @@
15
15
  */
16
16
 
17
17
  package com.totalpave.cordova.insets;
18
+
19
+ import android.os.Build;
20
+ import android.view.RoundedCorner;
21
+ import android.view.WindowInsets;
18
22
  import androidx.core.view.ViewCompat;
19
23
  import androidx.core.view.WindowInsetsCompat;
20
-
21
24
  import org.apache.cordova.CallbackContext;
22
25
  import org.apache.cordova.CordovaPlugin;
23
26
  import org.apache.cordova.PluginResult.Status;
24
27
  import org.apache.cordova.PluginResult;
25
-
26
28
  import org.json.JSONArray;
27
29
  import org.json.JSONObject;
28
30
  import org.json.JSONException;
29
-
30
31
  import java.lang.NumberFormatException;
31
32
 
32
33
  public class Insets extends CordovaPlugin {
@@ -43,12 +44,61 @@ public class Insets extends CordovaPlugin {
43
44
  float density = this.cordova.getActivity().getResources().getDisplayMetrics().density;
44
45
 
45
46
  // Ideally, we'd import this, but it shares the same name as our plugin
46
- androidx.core.graphics.Insets insets = insetProvider.getInsets(WindowInsetsCompat.Type.systemBars());
47
+ int insetTypes = WindowInsetsCompat.Type.displayCutout() | WindowInsetsCompat.Type.systemBars();
48
+ androidx.core.graphics.Insets insets = insetProvider.getInsets(insetTypes);
49
+
50
+ double topLeftRadius = 0.0;
51
+ double topRightRadius = 0.0;
52
+ double botLeftRadius = 0.0;
53
+ double botRightRadius = 0.0;
54
+
55
+ WindowInsets sourceInsets = insetProvider.toWindowInsets();
56
+ if (sourceInsets != null) {
57
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
58
+ RoundedCorner topLeft = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
59
+ RoundedCorner topRight = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
60
+ RoundedCorner botLeft = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
61
+ RoundedCorner botRight = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
62
+
63
+ if (topLeft != null) {
64
+ int radius = topLeft.getRadius();
65
+ topLeftRadius = (double)radius / density;
66
+ }
67
+
68
+ if (topRight != null) {
69
+ int radius = topRight.getRadius();
70
+ topRightRadius = (double)radius / density;
71
+ }
72
+
73
+ if (botLeft != null) {
74
+ int radius = botLeft.getRadius();
75
+ botLeftRadius = (double)radius / density;
76
+ }
77
+
78
+ if (botRight != null) {
79
+ int radius = botRight.getRadius();
80
+ botRightRadius = (double)radius / density;
81
+ }
82
+ }
83
+ }
84
+
85
+ double top = insets.top / density;
86
+ double right = insets.right / density;
87
+ double bottom = insets.bottom / density;
88
+ double left = insets.left / density;
89
+
90
+ // Insets do not include rounded corner radius. If an inset is present, it generally will be big enough to cover the rounded corner. This is a coincidence, not a designed thing.
91
+ // In either case, we need to determine how much space is required to cover the rounded corner and take the higher betwen the inset and the rounded corner.
92
+
93
+ top = Math.max(Math.max(top, topLeftRadius), topRightRadius);
94
+ bottom = Math.max(Math.max(bottom, botLeftRadius), botRightRadius);
95
+ left = Math.max(Math.max(left, topLeftRadius), botLeftRadius);
96
+ right = Math.max(Math.max(right, topRightRadius), botRightRadius);
47
97
 
48
- result.put("top", insets.top / density);
49
- result.put("right", insets.right / density);
50
- result.put("bottom", insets.bottom / density);
51
- result.put("left", insets.left / density);
98
+ result.put("top", top);
99
+ result.put("right", right);
100
+ result.put("bottom", bottom);
101
+ result.put("left", left);
52
102
  } catch (JSONException e) {
53
103
  e.printStackTrace();
54
104
  return insetProvider.CONSUMED; // Stop dispatching to child views
package/www/insets.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"insets.js","sources":["../src/www/Insets.ts"],"sourcesContent":["/*\n Copyright 2022 Total Pave Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\nexport interface IInsetsAPI {\n addListener: (callback: IInsetCallbackFunc) => void;\n removeListener: (callback: IInsetCallbackFunc) => void;\n getInsets: () => IInsets;\n}\ndeclare global {\n interface ITotalpave {\n Insets: IInsetsAPI;\n }\n interface Window {\n totalpave: ITotalpave;\n }\n}\n\nexport const SERVICE_NAME: string = \"Insets\";\n\nexport interface IInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport type IInsetCallbackFunc = (inset: IInsets) => void;\n\nclass InsetsAPI implements IInsetsAPI {\n private initPromise: Promise<void>;\n private listeners: Array<Function> = [];\n private insets: IInsets = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n\n /**\n * Initializes javascript side of the plugin.\n * \n * This function is called automatically on deviceready.\n * @internal\n */\n public __init(): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n this.initPromise = new Promise<void>((resolve, reject) => {\n // no-op on iOS, still installs to iOS so apps don't need to do platform checks.\n if (cordova.platformId === 'ios') {\n resolve();\n return;\n }\n\n // Setup promise resolving mechanism.\n // We don't use the cordova callback functions as they will be called multiple times over the lifespan of an app.\n let func = () => {\n resolve();\n this.removeListener(func);\n }\n this.addListener(func);\n\n // Setup cordova callback.\n let that = this;\n cordova.exec(\n (insets: IInsets) => {\n that.insets = insets;\n for (let i = 0, listeners = that.listeners.slice(), length = listeners.length; i < length; ++i) {\n listeners[i](insets);\n }\n },\n reject,\n SERVICE_NAME,\n \"setListener\",\n []\n );\n });\n }\n\n public addListener(callback: IInsetCallbackFunc) {\n this.listeners.push(callback);\n }\n\n public removeListener(callback: IInsetCallbackFunc) {\n let index = this.listeners.indexOf(callback);\n if (index === -1) {\n return;\n }\n this.listeners.splice(index, 1);\n }\n\n /**\n * @returns Last emitted insets.\n */ \n public getInsets(): IInsets {\n return this.insets;\n }\n};\n\nexport const Insets = new InsetsAPI();\n\ndocument.addEventListener('deviceready', function() {\n Insets.__init();\n});\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;AAcE;AAgBK,MAAM,YAAY,GAAW,QAAQ,CAAC;AAW7C,MAAM,SAAS,CAAA;AAAf,IAAA,WAAA,GAAA;QAEY,IAAS,CAAA,SAAA,GAAoB,EAAE,CAAC;AAChC,QAAA,IAAA,CAAA,MAAM,GAAY;AACtB,YAAA,GAAG,EAAE,CAAC;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,IAAI,EAAE,CAAC;SACV,CAAC;KA8DL;AA5DG;;;;;AAKG;IACI,MAAM,GAAA;QACT,IAAI,IAAI,CAAC,WAAW,EAAE;YAClB,OAAO,IAAI,CAAC,WAAW,CAAC;AAC3B,SAAA;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;;AAErD,YAAA,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE;AAC9B,gBAAA,OAAO,EAAE,CAAC;gBACV,OAAO;AACV,aAAA;;;YAID,IAAI,IAAI,GAAG,MAAK;AACZ,gBAAA,OAAO,EAAE,CAAC;AACV,gBAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,aAAC,CAAA;AACD,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;;YAGvB,IAAI,IAAI,GAAG,IAAI,CAAC;AAChB,YAAA,OAAO,CAAC,IAAI,CACR,CAAC,MAAe,KAAI;AAChB,gBAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;gBACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE;AAC5F,oBAAA,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACxB,iBAAA;aACJ,EACD,MAAM,EACN,YAAY,EACZ,aAAa,EACb,EAAE,CACL,CAAC;AACN,SAAC,CAAC,CAAC;KACN;AAEM,IAAA,WAAW,CAAC,QAA4B,EAAA;AAC3C,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACjC;AAEM,IAAA,cAAc,CAAC,QAA4B,EAAA;QAC9C,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7C,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,OAAO;AACV,SAAA;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACnC;AAED;;AAEG;IACI,SAAS,GAAA;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;KACtB;AACJ,CAAA;AAEY,MAAA,MAAM,GAAG,IAAI,SAAS,GAAG;AAEtC,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAA;IACrC,MAAM,CAAC,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC;;;;"}
1
+ {"version":3,"file":"insets.js","sources":["../src/www/Insets.ts"],"sourcesContent":["/*\n Copyright 2022 Total Pave Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\nexport interface IInsetsAPI {\n addListener: (callback: IInsetCallbackFunc) => void;\n removeListener: (callback: IInsetCallbackFunc) => void;\n getInsets: () => IInsets;\n}\ndeclare global {\n interface ITotalpave {\n Insets: IInsetsAPI;\n }\n interface Window {\n totalpave: ITotalpave;\n }\n}\n\nexport const SERVICE_NAME: string = \"Insets\";\n\nexport interface IInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport type IInsetCallbackFunc = (inset: IInsets) => void;\n\nclass InsetsAPI implements IInsetsAPI {\n private initPromise: Promise<void>;\n private listeners: Array<Function> = [];\n private insets: IInsets = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n\n /**\n * Initializes javascript side of the plugin.\n * \n * This function is called automatically on deviceready.\n * @internal\n */\n public __init(): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n this.initPromise = new Promise<void>((resolve, reject) => {\n // no-op on iOS, still installs to iOS so apps don't need to do platform checks.\n if (cordova.platformId === 'ios') {\n resolve();\n return;\n }\n\n // Setup promise resolving mechanism.\n // We don't use the cordova callback functions as they will be called multiple times over the lifespan of an app.\n let func = () => {\n resolve();\n this.removeListener(func);\n }\n this.addListener(func);\n\n // Setup cordova callback.\n let that = this;\n cordova.exec(\n (insets: IInsets) => {\n that.insets = insets;\n for (let i = 0, listeners = that.listeners.slice(), length = listeners.length; i < length; ++i) {\n listeners[i](insets);\n }\n },\n reject,\n SERVICE_NAME,\n \"setListener\",\n []\n );\n });\n }\n\n public addListener(callback: IInsetCallbackFunc) {\n this.listeners.push(callback);\n }\n\n public removeListener(callback: IInsetCallbackFunc) {\n let index = this.listeners.indexOf(callback);\n if (index === -1) {\n return;\n }\n this.listeners.splice(index, 1);\n }\n\n /**\n * @returns Last emitted insets.\n */ \n public getInsets(): IInsets {\n return this.insets;\n }\n};\n\nexport const Insets = new InsetsAPI();\n\ndocument.addEventListener('deviceready', function() {\n Insets.__init();\n});\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;AAcE;AAgBK,MAAM,YAAY,GAAW,QAAQ,CAAC;AAW7C,MAAM,SAAS,CAAA;AAAf,IAAA,WAAA,GAAA;QAEY,IAAS,CAAA,SAAA,GAAoB,EAAE,CAAC;AAChC,QAAA,IAAA,CAAA,MAAM,GAAY;AACtB,YAAA,GAAG,EAAE,CAAC;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,IAAI,EAAE,CAAC;SACV,CAAC;KA8DL;AA5DG;;;;;AAKG;IACI,MAAM,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;YAClB,OAAO,IAAI,CAAC,WAAW,CAAC;SAC3B;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;;AAErD,YAAA,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE;AAC9B,gBAAA,OAAO,EAAE,CAAC;gBACV,OAAO;aACV;;;YAID,IAAI,IAAI,GAAG,MAAK;AACZ,gBAAA,OAAO,EAAE,CAAC;AACV,gBAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,aAAC,CAAA;AACD,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;;YAGvB,IAAI,IAAI,GAAG,IAAI,CAAC;AAChB,YAAA,OAAO,CAAC,IAAI,CACR,CAAC,MAAe,KAAI;AAChB,gBAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;gBACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE;AAC5F,oBAAA,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;iBACxB;aACJ,EACD,MAAM,EACN,YAAY,EACZ,aAAa,EACb,EAAE,CACL,CAAC;AACN,SAAC,CAAC,CAAC;KACN;AAEM,IAAA,WAAW,CAAC,QAA4B,EAAA;AAC3C,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACjC;AAEM,IAAA,cAAc,CAAC,QAA4B,EAAA;QAC9C,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7C,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,OAAO;SACV;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACnC;AAED;;AAEG;IACI,SAAS,GAAA;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;KACtB;AACJ,CAAA;AAEY,MAAA,MAAM,GAAG,IAAI,SAAS,GAAG;AAEtC,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAA;IACrC,MAAM,CAAC,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC;;;;"}