@lifi/widget 4.10.0 → 4.10.1

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.
Files changed (50) hide show
  1. package/README.md +2 -7
  2. package/dist/esm/config/version.d.ts +1 -1
  3. package/dist/esm/config/version.js +1 -1
  4. package/dist/esm/config/version.js.map +1 -1
  5. package/dist/esm/hooks/usePacedValue.js +1 -1
  6. package/dist/esm/hooks/usePacedValue.js.map +1 -1
  7. package/dist/esm/hooks/useRouteExecutionMessage.d.ts.map +1 -1
  8. package/dist/esm/hooks/useRouteExecutionMessage.js +4 -8
  9. package/dist/esm/hooks/useRouteExecutionMessage.js.map +1 -1
  10. package/dist/esm/i18n/bn.json +567 -270
  11. package/dist/esm/i18n/de.json +552 -255
  12. package/dist/esm/i18n/en.json +7 -61
  13. package/dist/esm/i18n/es.json +522 -225
  14. package/dist/esm/i18n/fr.json +541 -244
  15. package/dist/esm/i18n/hi.json +592 -295
  16. package/dist/esm/i18n/id.json +485 -188
  17. package/dist/esm/i18n/it.json +546 -249
  18. package/dist/esm/i18n/ja.json +512 -215
  19. package/dist/esm/i18n/ko.json +553 -256
  20. package/dist/esm/i18n/pl.json +598 -301
  21. package/dist/esm/i18n/pt.json +512 -215
  22. package/dist/esm/i18n/th.json +554 -257
  23. package/dist/esm/i18n/tr.json +538 -241
  24. package/dist/esm/i18n/uk.json +514 -217
  25. package/dist/esm/i18n/vi.json +550 -253
  26. package/dist/esm/i18n/zh.json +528 -231
  27. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +70 -18
  28. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
  29. package/dist/esm/pages/TransactionPage/utils.d.ts +3 -0
  30. package/dist/esm/pages/TransactionPage/utils.d.ts.map +1 -1
  31. package/dist/esm/pages/TransactionPage/utils.js +27 -1
  32. package/dist/esm/pages/TransactionPage/utils.js.map +1 -1
  33. package/dist/esm/shared.d.ts +2 -2
  34. package/dist/esm/shared.js +2 -2
  35. package/dist/esm/stores/routes/utils.d.ts +1 -1
  36. package/dist/esm/stores/routes/utils.d.ts.map +1 -1
  37. package/dist/esm/stores/routes/utils.js +13 -1
  38. package/dist/esm/stores/routes/utils.js.map +1 -1
  39. package/dist/esm/utils/getErrorMessage.js +4 -0
  40. package/dist/esm/utils/getErrorMessage.js.map +1 -1
  41. package/package.json +4 -4
  42. package/src/config/version.ts +1 -1
  43. package/src/hooks/usePacedValue.ts +1 -1
  44. package/src/hooks/useRouteExecutionMessage.ts +10 -13
  45. package/src/pages/TransactionPage/TransactionFailedButtons.test.tsx +497 -0
  46. package/src/pages/TransactionPage/TransactionFailedButtons.tsx +78 -9
  47. package/src/pages/TransactionPage/utils.ts +81 -0
  48. package/src/shared.ts +1 -0
  49. package/src/stores/routes/utils.ts +24 -1
  50. package/src/utils/getErrorMessage.ts +5 -0
package/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  [![license](https://img.shields.io/github/license/lifinance/widget)](/LICENSE)
4
4
  [![npm latest package](https://img.shields.io/npm/v/@lifi/widget/latest.svg)](https://www.npmjs.com/package/@lifi/widget)
5
5
  [![npm downloads](https://img.shields.io/npm/dm/@lifi/widget.svg)](https://www.npmjs.com/package/@lifi/widget)
6
- [![Crowdin](https://badges.crowdin.net/lifi-widget/localized.svg)](https://crowdin.com/project/lifi-widget)
7
6
  [![Follow on Twitter](https://img.shields.io/twitter/follow/lifiprotocol.svg?label=follow+LI.FI)](https://twitter.com/lifiprotocol)
8
7
 
9
8
  </div>
@@ -345,13 +344,9 @@ Visit our [playground](https://playground.li.fi) to see how you can customize yo
345
344
 
346
345
  Please visit [LI.FI Widget Documentation](https://docs.li.fi/widget/install-widget).
347
346
 
348
- ## Contributing Translations
347
+ ## Translations
349
348
 
350
- We appreciate your interest in helping translate our project!
351
-
352
- If you'd like to contribute translations, please visit our Crowdin project page at [Crowdin LI.FI Widget](https://crowdin.com/project/lifi-widget). Register on Crowdin and you can start translating the project into your preferred language. Your contributions will help make our project accessible to a wider audience around the world.
353
-
354
- Thank you for your support!
349
+ The widget has 17 languages. The person or the AI agent that changes an English text in `en.json` also translates it into the 16 other languages, in the same PR. To fix a translation, open a PR that changes the locale file. Follow [TRANSLATING.md](./TRANSLATING.md).
355
350
 
356
351
  ## Changelog
357
352
 
@@ -1,5 +1,5 @@
1
1
  //#region src/config/version.d.ts
2
2
  export declare const name = "@lifi/widget";
3
- export declare const version = "4.10.0";
3
+ export declare const version = "4.10.1";
4
4
  //#endregion
5
5
  //# sourceMappingURL=version.d.ts.map
@@ -1,6 +1,6 @@
1
1
  //#region src/config/version.ts
2
2
  const name = "@lifi/widget";
3
- const version = "4.10.0";
3
+ const version = "4.10.1";
4
4
  //#endregion
5
5
  export { name, version };
6
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.10.0'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
1
+ {"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.10.1'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
@@ -37,6 +37,6 @@ function usePacedValue(live, paced = true) {
37
37
  return value;
38
38
  }
39
39
  //#endregion
40
- export { usePacedValue };
40
+ export { DISPLAY_INTERVAL, usePacedValue };
41
41
 
42
42
  //# sourceMappingURL=usePacedValue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePacedValue.js","names":[],"sources":["../../../src/hooks/usePacedValue.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\n/** Smallest gap between UI updates, in milliseconds. */\nconst DISPLAY_INTERVAL = 1200\n\n/**\n * Returns `live`, but changes it at most once every {@link DISPLAY_INTERVAL}\n * milliseconds. If `live` changes several times within that window, only the\n * newest value is shown.\n *\n * Set `paced` to `false` to turn this off and update on every change.\n */\nexport function usePacedValue<T>(live: T, paced = true): T {\n const [value, setValue] = useState(live)\n\n const shown = useRef(live)\n // 0 so the first update shows immediately, then throttles.\n const windowStart = useRef(0)\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n useEffect(() => {\n if (live === shown.current) {\n return\n }\n if (!paced) {\n shown.current = live\n setValue(live)\n return\n }\n const show = () => {\n windowStart.current = Date.now()\n shown.current = live\n setValue(live)\n }\n const remaining = windowStart.current + DISPLAY_INTERVAL - Date.now()\n if (remaining <= 0) {\n show()\n return\n }\n timer.current = setTimeout(show, remaining)\n return () => clearTimeout(timer.current)\n }, [live, paced])\n\n return value\n}\n"],"mappings":";;;AAGA,MAAM,mBAAmB;;;;;;;;AASzB,SAAgB,cAAiB,MAAS,QAAQ,MAAS;CACzD,MAAM,CAAC,OAAO,YAAY,SAAS,IAAI;CAEvC,MAAM,QAAQ,OAAO,IAAI;CAEzB,MAAM,cAAc,OAAO,CAAC;CAC5B,MAAM,QAAQ,OAAkD,KAAA,CAAS;CAEzE,gBAAgB;EACd,IAAI,SAAS,MAAM,SACjB;EAEF,IAAI,CAAC,OAAO;GACV,MAAM,UAAU;GAChB,SAAS,IAAI;GACb;EACF;EACA,MAAM,aAAa;GACjB,YAAY,UAAU,KAAK,IAAI;GAC/B,MAAM,UAAU;GAChB,SAAS,IAAI;EACf;EACA,MAAM,YAAY,YAAY,UAAU,mBAAmB,KAAK,IAAI;EACpE,IAAI,aAAa,GAAG;GAClB,KAAK;GACL;EACF;EACA,MAAM,UAAU,WAAW,MAAM,SAAS;EAC1C,aAAa,aAAa,MAAM,OAAO;CACzC,GAAG,CAAC,MAAM,KAAK,CAAC;CAEhB,OAAO;AACT"}
1
+ {"version":3,"file":"usePacedValue.js","names":[],"sources":["../../../src/hooks/usePacedValue.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\n/** Smallest gap between UI updates, in milliseconds. */\nexport const DISPLAY_INTERVAL = 1200\n\n/**\n * Returns `live`, but changes it at most once every {@link DISPLAY_INTERVAL}\n * milliseconds. If `live` changes several times within that window, only the\n * newest value is shown.\n *\n * Set `paced` to `false` to turn this off and update on every change.\n */\nexport function usePacedValue<T>(live: T, paced = true): T {\n const [value, setValue] = useState(live)\n\n const shown = useRef(live)\n // 0 so the first update shows immediately, then throttles.\n const windowStart = useRef(0)\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n useEffect(() => {\n if (live === shown.current) {\n return\n }\n if (!paced) {\n shown.current = live\n setValue(live)\n return\n }\n const show = () => {\n windowStart.current = Date.now()\n shown.current = live\n setValue(live)\n }\n const remaining = windowStart.current + DISPLAY_INTERVAL - Date.now()\n if (remaining <= 0) {\n show()\n return\n }\n timer.current = setTimeout(show, remaining)\n return () => clearTimeout(timer.current)\n }, [live, paced])\n\n return value\n}\n"],"mappings":";;;AAGA,MAAa,mBAAmB;;;;;;;;AAShC,SAAgB,cAAiB,MAAS,QAAQ,MAAS;CACzD,MAAM,CAAC,OAAO,YAAY,SAAS,IAAI;CAEvC,MAAM,QAAQ,OAAO,IAAI;CAEzB,MAAM,cAAc,OAAO,CAAC;CAC5B,MAAM,QAAQ,OAAkD,KAAA,CAAS;CAEzE,gBAAgB;EACd,IAAI,SAAS,MAAM,SACjB;EAEF,IAAI,CAAC,OAAO;GACV,MAAM,UAAU;GAChB,SAAS,IAAI;GACb;EACF;EACA,MAAM,aAAa;GACjB,YAAY,UAAU,KAAK,IAAI;GAC/B,MAAM,UAAU;GAChB,SAAS,IAAI;EACf;EACA,MAAM,YAAY,YAAY,UAAU,mBAAmB,KAAK,IAAI;EACpE,IAAI,aAAa,GAAG;GAClB,KAAK;GACL;EACF;EACA,MAAM,UAAU,WAAW,MAAM,SAAS;EAC1C,aAAa,aAAa,MAAM,OAAO;CACzC,GAAG,CAAC,MAAM,KAAK,CAAC;CAEhB,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteExecutionMessage.d.ts","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"mappings":";;;qBAQa,2BACX,OAAO,eACP,QAAQ;EACL;EAA2B"}
1
+ {"version":3,"file":"useRouteExecutionMessage.d.ts","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"mappings":";;;qBASa,2BACX,OAAO,eACP,QAAQ;EACL;EAA2B"}
@@ -1,6 +1,7 @@
1
1
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
2
2
  import { useAvailableChains } from "./useAvailableChains.js";
3
3
  import "../stores/routes/types.js";
4
+ import { getFailedStepAction } from "../stores/routes/utils.js";
4
5
  import { getActionMessage } from "../utils/getActionMessage.js";
5
6
  import { getErrorMessage } from "../utils/getErrorMessage.js";
6
7
  import { useTranslation } from "react-i18next";
@@ -39,14 +40,9 @@ const useRouteExecutionMessage = (route, status) => {
39
40
  });
40
41
  break;
41
42
  case 8: {
42
- const step = route.steps.find((step) => step.execution?.status === "FAILED");
43
- if (!step) break;
44
- const action = step.execution?.actions?.find((action) => action.status === "FAILED") || {
45
- status: "FAILED",
46
- type: "EXECUTION",
47
- error: step.execution?.error
48
- };
49
- const actionMessage = getErrorMessage(t, getChainById, step, action);
43
+ const failed = getFailedStepAction(route);
44
+ if (!failed) break;
45
+ const actionMessage = getErrorMessage(t, getChainById, failed.step, failed.action);
50
46
  title = actionMessage.title;
51
47
  message = actionMessage.message;
52
48
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteExecutionMessage.js","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"sourcesContent":["import type { ExecutionActionType, RouteExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { RouteExecutionStatus } from '../stores/routes/types.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useRouteExecutionMessage = (\n route: RouteExtended,\n status: RouteExecutionStatus\n): { title: string | undefined; message: string | undefined } => {\n const { mode, modeOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n const transactionType =\n route.fromChainId === route.toChainId ? 'swap' : 'bridge'\n\n let title: string | undefined\n let message: string | undefined\n\n switch (status) {\n case RouteExecutionStatus.Pending: {\n // Use the first executing step, not the last one — in a multi-step route\n // the active step is often not the last.\n const activeStep =\n route.steps.find(\n (s) =>\n s.execution?.status === 'PENDING' ||\n s.execution?.status === 'ACTION_REQUIRED'\n ) ?? route.steps.at(-1)\n const lastAction = activeStep?.execution?.actions?.at(-1)\n const actionMessage =\n activeStep && lastAction\n ? getActionMessage(\n t,\n activeStep,\n lastAction.type,\n lastAction.status,\n lastAction.substatus,\n mode,\n modeOptions\n )\n : undefined\n // Fall back to a generic title when the step has no action to describe yet\n // (just after a restart, or before the first action exists).\n title =\n actionMessage?.title ?? t(`main.process.${transactionType}.pending`)\n message = actionMessage?.message\n break\n }\n case RouteExecutionStatus.Done: {\n title =\n mode === 'custom'\n ? t(\n `success.title.${modeOptions?.custom?.type ?? 'checkout'}Successful`\n )\n : t(`success.title.${transactionType}Successful`)\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Partial: {\n title = t(`success.title.${transactionType}PartiallySuccessful`)\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Refunded: {\n title = t('success.title.refundIssued')\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Failed: {\n const step = route.steps.find(\n (step) => step.execution?.status === 'FAILED'\n )\n if (!step) {\n break\n }\n const action = step.execution?.actions?.find(\n (action) => action.status === 'FAILED'\n ) || {\n status: 'FAILED',\n type: 'EXECUTION' as ExecutionActionType,\n error: step.execution?.error,\n } // synthetic action to represent a failed execution with no actions\n const actionMessage = getErrorMessage(t, getChainById, step, action)\n title = actionMessage.title\n message = actionMessage.message\n break\n }\n }\n\n return { title, message }\n}\n"],"mappings":";;;;;;;AAQA,MAAa,4BACX,OACA,WAC+D;CAC/D,MAAM,EAAE,MAAM,gBAAgB,gBAAgB;CAC9C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,kBACJ,MAAM,gBAAgB,MAAM,YAAY,SAAS;CAEnD,IAAI;CACJ,IAAI;CAEJ,QAAQ,QAAR;EACE,KAAA,GAAmC;GAGjC,MAAM,aACJ,MAAM,MAAM,MACT,MACC,EAAE,WAAW,WAAW,aACxB,EAAE,WAAW,WAAW,iBAC5B,KAAK,MAAM,MAAM,GAAG,EAAE;GACxB,MAAM,aAAa,YAAY,WAAW,SAAS,GAAG,EAAE;GACxD,MAAM,gBACJ,cAAc,aACV,iBACE,GACA,YACA,WAAW,MACX,WAAW,QACX,WAAW,WACX,MACA,WACF,IACA,KAAA;GAGN,QACE,eAAe,SAAS,EAAE,gBAAgB,gBAAgB,SAAS;GACrE,UAAU,eAAe;GACzB;EACF;EACA,KAAA;GACE,QACE,SAAS,WACL,EACE,iBAAiB,aAAa,QAAQ,QAAQ,WAAW,WAC3D,IACA,EAAE,iBAAiB,gBAAgB,WAAW;GACpD;EAEF,KAAA;GACE,QAAQ,EAAE,iBAAiB,gBAAgB,oBAAoB;GAC/D,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA;GACE,QAAQ,EAAE,4BAA4B;GACtC,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA,GAAkC;GAChC,MAAM,OAAO,MAAM,MAAM,MACtB,SAAS,KAAK,WAAW,WAAW,QACvC;GACA,IAAI,CAAC,MACH;GAEF,MAAM,SAAS,KAAK,WAAW,SAAS,MACrC,WAAW,OAAO,WAAW,QAChC,KAAK;IACH,QAAQ;IACR,MAAM;IACN,OAAO,KAAK,WAAW;GACzB;GACA,MAAM,gBAAgB,gBAAgB,GAAG,cAAc,MAAM,MAAM;GACnE,QAAQ,cAAc;GACtB,UAAU,cAAc;GACxB;EACF;CACF;CAEA,OAAO;EAAE;EAAO;CAAQ;AAC1B"}
1
+ {"version":3,"file":"useRouteExecutionMessage.js","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"sourcesContent":["import type { RouteExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { RouteExecutionStatus } from '../stores/routes/types.js'\nimport { getFailedStepAction } from '../stores/routes/utils.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useRouteExecutionMessage = (\n route: RouteExtended,\n status: RouteExecutionStatus\n): { title: string | undefined; message: string | undefined } => {\n const { mode, modeOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n const transactionType =\n route.fromChainId === route.toChainId ? 'swap' : 'bridge'\n\n let title: string | undefined\n let message: string | undefined\n\n switch (status) {\n case RouteExecutionStatus.Pending: {\n // Use the first executing step, not the last one — in a multi-step route\n // the active step is often not the last.\n const activeStep =\n route.steps.find(\n (s) =>\n s.execution?.status === 'PENDING' ||\n s.execution?.status === 'ACTION_REQUIRED'\n ) ?? route.steps.at(-1)\n const lastAction = activeStep?.execution?.actions?.at(-1)\n const actionMessage =\n activeStep && lastAction\n ? getActionMessage(\n t,\n activeStep,\n lastAction.type,\n lastAction.status,\n lastAction.substatus,\n mode,\n modeOptions\n )\n : undefined\n // Fall back to a generic title when the step has no action to describe yet\n // (just after a restart, or before the first action exists).\n title =\n actionMessage?.title ?? t(`main.process.${transactionType}.pending`)\n message = actionMessage?.message\n break\n }\n case RouteExecutionStatus.Done: {\n title =\n mode === 'custom'\n ? t(\n `success.title.${modeOptions?.custom?.type ?? 'checkout'}Successful`\n )\n : t(`success.title.${transactionType}Successful`)\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Partial: {\n title = t(`success.title.${transactionType}PartiallySuccessful`)\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Refunded: {\n title = t('success.title.refundIssued')\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Failed: {\n const failed = getFailedStepAction(route)\n if (!failed) {\n break\n }\n const actionMessage = getErrorMessage(\n t,\n getChainById,\n failed.step,\n failed.action\n )\n title = actionMessage.title\n message = actionMessage.message\n break\n }\n }\n\n return { title, message }\n}\n"],"mappings":";;;;;;;;AASA,MAAa,4BACX,OACA,WAC+D;CAC/D,MAAM,EAAE,MAAM,gBAAgB,gBAAgB;CAC9C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,kBACJ,MAAM,gBAAgB,MAAM,YAAY,SAAS;CAEnD,IAAI;CACJ,IAAI;CAEJ,QAAQ,QAAR;EACE,KAAA,GAAmC;GAGjC,MAAM,aACJ,MAAM,MAAM,MACT,MACC,EAAE,WAAW,WAAW,aACxB,EAAE,WAAW,WAAW,iBAC5B,KAAK,MAAM,MAAM,GAAG,EAAE;GACxB,MAAM,aAAa,YAAY,WAAW,SAAS,GAAG,EAAE;GACxD,MAAM,gBACJ,cAAc,aACV,iBACE,GACA,YACA,WAAW,MACX,WAAW,QACX,WAAW,WACX,MACA,WACF,IACA,KAAA;GAGN,QACE,eAAe,SAAS,EAAE,gBAAgB,gBAAgB,SAAS;GACrE,UAAU,eAAe;GACzB;EACF;EACA,KAAA;GACE,QACE,SAAS,WACL,EACE,iBAAiB,aAAa,QAAQ,QAAQ,WAAW,WAC3D,IACA,EAAE,iBAAiB,gBAAgB,WAAW;GACpD;EAEF,KAAA;GACE,QAAQ,EAAE,iBAAiB,gBAAgB,oBAAoB;GAC/D,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA;GACE,QAAQ,EAAE,4BAA4B;GACtC,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA,GAAkC;GAChC,MAAM,SAAS,oBAAoB,KAAK;GACxC,IAAI,CAAC,QACH;GAEF,MAAM,gBAAgB,gBACpB,GACA,cACA,OAAO,MACP,OAAO,MACT;GACA,QAAQ,cAAc;GACtB,UAAU,cAAc;GACxB;EACF;CACF;CAEA,OAAO;EAAE;EAAO;CAAQ;AAC1B"}