cloudcommerce 0.34.0 → 0.35.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 (191) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/action.yml +11 -3
  3. package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
  4. package/ecomplus-stores/barra-doce/functions/ssr/package.json +6 -6
  5. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/[...slug].astro +1 -1
  6. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/account.astro +1 -1
  7. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/index.astro +1 -1
  8. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/index.astro +1 -1
  9. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/~fallback.astro +1 -1
  10. package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
  11. package/ecomplus-stores/barra-doce/package.json +2 -2
  12. package/package.json +6 -6
  13. package/packages/api/lib/api.js +1 -1
  14. package/packages/api/lib/api.js.map +1 -1
  15. package/packages/api/package.json +1 -1
  16. package/packages/api/src/api.ts +1 -1
  17. package/packages/apps/affilate-program/package.json +2 -2
  18. package/packages/apps/correios/package.json +2 -2
  19. package/packages/apps/custom-payment/package.json +1 -1
  20. package/packages/apps/custom-shipping/package.json +1 -1
  21. package/packages/apps/datafrete/package.json +2 -2
  22. package/packages/apps/discounts/package.json +1 -1
  23. package/packages/apps/emails/package.json +2 -2
  24. package/packages/apps/fb-conversions/package.json +2 -2
  25. package/packages/apps/flash-courier/package.json +1 -1
  26. package/packages/apps/frenet/package.json +2 -2
  27. package/packages/apps/galaxpay/package.json +2 -2
  28. package/packages/apps/google-analytics/lib/google-analytics-events.js +4 -4
  29. package/packages/apps/google-analytics/lib/google-analytics-events.js.map +1 -1
  30. package/packages/apps/google-analytics/package.json +2 -2
  31. package/packages/apps/google-analytics/src/google-analytics-events.ts +4 -4
  32. package/packages/apps/jadlog/package.json +1 -1
  33. package/packages/apps/loyalty-points/package.json +1 -1
  34. package/packages/apps/mandae/package.json +1 -1
  35. package/packages/apps/melhor-envio/package.json +2 -2
  36. package/packages/apps/mercadopago/package.json +2 -2
  37. package/packages/apps/pagarme/package.json +2 -2
  38. package/packages/apps/pagarme-v5/package.json +2 -2
  39. package/packages/apps/paghiper/package.json +2 -2
  40. package/packages/apps/pix/package.json +2 -2
  41. package/packages/apps/tiny-erp/package.json +2 -2
  42. package/packages/apps/webhooks/package.json +2 -2
  43. package/packages/cli/package.json +4 -1
  44. package/packages/config/package.json +1 -1
  45. package/packages/emails/package.json +1 -1
  46. package/packages/eslint/package.json +1 -1
  47. package/packages/events/package.json +2 -2
  48. package/packages/feeds/package.json +1 -1
  49. package/packages/firebase/package.json +2 -2
  50. package/packages/i18n/package.json +1 -1
  51. package/packages/modules/package.json +2 -2
  52. package/packages/passport/package.json +2 -2
  53. package/packages/ssr/lib/analytics/send-to-ga4.js +44 -0
  54. package/packages/ssr/lib/analytics/send-to-ga4.js.map +1 -0
  55. package/packages/ssr/lib/analytics/send-to-meta.js +44 -0
  56. package/packages/ssr/lib/analytics/send-to-meta.js.map +1 -0
  57. package/packages/ssr/lib/analytics/send-to-tiktok.js +44 -0
  58. package/packages/ssr/lib/analytics/send-to-tiktok.js.map +1 -0
  59. package/packages/ssr/lib/analytics-events.js +52 -24
  60. package/packages/ssr/lib/analytics-events.js.map +1 -1
  61. package/packages/ssr/lib/firebase/serve-storefront.js +16 -3
  62. package/packages/ssr/lib/firebase/serve-storefront.js.map +1 -1
  63. package/packages/ssr/package.json +6 -5
  64. package/packages/ssr/src/analytics/send-to-ga4.ts +56 -0
  65. package/packages/ssr/src/analytics/send-to-meta.ts +50 -0
  66. package/packages/ssr/src/analytics/send-to-tiktok.ts +49 -0
  67. package/packages/ssr/src/analytics-events.ts +57 -27
  68. package/packages/ssr/src/firebase/serve-storefront.ts +17 -3
  69. package/packages/storefront/dist/client/_astro/AccountPage.700be123.js +1 -0
  70. package/packages/storefront/dist/client/_astro/{CartSidebar.8151e4ee.js → CartSidebar.430b55df.js} +1 -1
  71. package/packages/storefront/dist/client/_astro/HeroSlider.bd684ed8.js +1 -0
  72. package/packages/storefront/dist/client/_astro/PitchBar.06e0f831.js +1 -0
  73. package/packages/storefront/dist/client/_astro/{Prices.311303d8.js → Prices.0e829c31.js} +1 -1
  74. package/packages/storefront/dist/client/_astro/ProductDetails.06da998d.js +1 -0
  75. package/packages/storefront/dist/client/_astro/ProductShelf.3f4f38b5.js +1 -0
  76. package/packages/storefront/dist/client/_astro/ProductShelf.bf82838b.js +1 -0
  77. package/packages/storefront/dist/client/_astro/QuantitySelector.ebf60845.js +1 -0
  78. package/packages/storefront/dist/client/_astro/SearchModal.b6aa5ef7.js +1 -0
  79. package/packages/storefront/dist/client/_astro/ShopHeader.2d6e361a.js +4 -0
  80. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.f75743ee.js +1 -0
  81. package/packages/storefront/dist/client/_astro/_slug_.e7cac999.css +1 -0
  82. package/packages/storefront/dist/client/_astro/client.41b42098.js +1 -0
  83. package/packages/storefront/dist/client/_astro/customer-session.5ab9ab1a.js +1 -0
  84. package/packages/storefront/dist/client/_astro/ecom-utils.5cbfb95e.js +1 -0
  85. package/packages/storefront/dist/client/_astro/{format-money.8962a5ab.js → format-money.9cf6b04d.js} +1 -1
  86. package/packages/storefront/dist/client/_astro/{hoisted.57d8d9d0.js → hoisted.085a62c9.js} +1 -1
  87. package/packages/storefront/dist/client/_astro/hoisted.799e5593.js +1 -0
  88. package/packages/storefront/dist/client/_astro/{i18n.78f362d9.js → i18n.29216eeb.js} +1 -1
  89. package/packages/storefront/dist/client/_astro/{img.bfbd75a8.js → img.4f23a3dd.js} +1 -1
  90. package/packages/storefront/dist/client/_astro/index.570b84fe.js +1 -0
  91. package/packages/storefront/dist/client/_astro/index.8ac1db99.js +1 -0
  92. package/packages/storefront/dist/client/_astro/{modules-info.3c447a07.js → modules-info.55780599.js} +1 -1
  93. package/packages/storefront/dist/client/_astro/name.01410784.js +1 -0
  94. package/packages/storefront/dist/client/_astro/shopping-cart.d9f601dd.js +1 -0
  95. package/packages/storefront/dist/client/_astro/{use-analytics.d0c184ef.js → use-analytics.cc95e346.js} +1 -1
  96. package/packages/storefront/dist/client/_astro/{use-product-card.e0990572.js → use-product-card.437911bb.js} +1 -1
  97. package/packages/storefront/dist/server/chunks/{CartSidebar_03b51b57.mjs → CartSidebar_eab28771.mjs} +1 -1
  98. package/packages/storefront/dist/server/chunks/SearchModal_f66549d4.mjs +147 -0
  99. package/packages/storefront/dist/server/chunks/{_.._4def02ff.mjs → _.._5a781fb3.mjs} +1 -1
  100. package/packages/storefront/dist/server/chunks/{account_2ee873cf.mjs → account_519edb70.mjs} +1 -1
  101. package/packages/storefront/dist/server/chunks/astro/{assets-service_66a9c838.mjs → assets-service_a9d9ab5f.mjs} +58 -10
  102. package/packages/storefront/dist/server/chunks/{astro_8447f017.mjs → astro_d98f7186.mjs} +7 -1
  103. package/packages/storefront/dist/server/chunks/{index_5dcbbe32.mjs → index_10e14f85.mjs} +1 -1
  104. package/packages/storefront/dist/server/chunks/{index_37bacd45.mjs → index_5e3ed8a0.mjs} +1 -1
  105. package/packages/storefront/dist/server/chunks/{node_b3ae36f1.mjs → node_1119b0d1.mjs} +1 -1
  106. package/packages/storefront/dist/server/chunks/pages/{__80fd1c60.mjs → __93ade2dd.mjs} +485 -224
  107. package/packages/storefront/dist/server/chunks/pages/account_e5d410a7.mjs +28 -0
  108. package/packages/storefront/dist/server/chunks/pages/{index_8e1d063c.mjs → index_7e25afc1.mjs} +29 -8
  109. package/packages/storefront/dist/server/chunks/pages/node_bd378ac0.mjs +93 -0
  110. package/packages/storefront/dist/server/chunks/pages/{~fallback_6ff698cd.mjs → ~fallback_73578d2f.mjs} +16 -6
  111. package/packages/storefront/dist/server/chunks/{~fallback_7c4b84d5.mjs → ~fallback_41122b9b.mjs} +1 -1
  112. package/packages/storefront/dist/server/entry.mjs +8 -8
  113. package/packages/storefront/dist/server/{manifest_2019b8a9.mjs → manifest_6bc0c00d.mjs} +2 -2
  114. package/packages/storefront/dist/server/renderers.mjs +5 -3
  115. package/packages/storefront/package.json +8 -8
  116. package/packages/storefront/src/lib/assets/forms.css +35 -30
  117. package/packages/storefront/src/lib/components/Carousel.vue +3 -1
  118. package/packages/storefront/src/lib/components/CarouselControl.vue +1 -1
  119. package/packages/storefront/src/lib/components/Drawer.vue +45 -7
  120. package/packages/storefront/src/lib/components/globals/Fade.vue +1 -1
  121. package/packages/storefront/src/lib/composables/use-product-shelf.ts +1 -1
  122. package/packages/storefront/src/lib/scripts/vbeta-app.ts +25 -15
  123. package/packages/storefront/src/lib/ssr-context.ts +11 -8
  124. package/packages/storefront/src/lib/state/search-engine.ts +101 -0
  125. package/packages/storefront/src/lib/state/shopping-cart.ts +52 -65
  126. package/packages/storefront/src/lib/state/use-analytics.ts +2 -1
  127. package/packages/storefront/src/lib/state/use-storage.ts +5 -2
  128. package/packages/test-base/package.json +1 -1
  129. package/packages/types/package.json +1 -1
  130. package/packages/ssr/lib/analytics-providers/google-analytics.js +0 -48
  131. package/packages/ssr/lib/analytics-providers/google-analytics.js.map +0 -1
  132. package/packages/ssr/lib/analytics-providers/meta-conversions-api.js +0 -44
  133. package/packages/ssr/lib/analytics-providers/meta-conversions-api.js.map +0 -1
  134. package/packages/ssr/src/analytics-providers/google-analytics.ts +0 -67
  135. package/packages/ssr/src/analytics-providers/meta-conversions-api.ts +0 -57
  136. package/packages/storefront/dist/client/_astro/AccountPage.6ead88b1.js +0 -1
  137. package/packages/storefront/dist/client/_astro/HeroSlider.46474cda.js +0 -1
  138. package/packages/storefront/dist/client/_astro/PitchBar.fbca6881.js +0 -1
  139. package/packages/storefront/dist/client/_astro/ProductDetails.d66f9f7e.js +0 -1
  140. package/packages/storefront/dist/client/_astro/ProductShelf.9536b4c1.js +0 -1
  141. package/packages/storefront/dist/client/_astro/QuantitySelector.e74e368a.js +0 -1
  142. package/packages/storefront/dist/client/_astro/SearchModal.83b73e0b.js +0 -1
  143. package/packages/storefront/dist/client/_astro/ShopHeader.06f4d486.js +0 -4
  144. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.dd1a60ce.js +0 -1
  145. package/packages/storefront/dist/client/_astro/_slug_.52cde7a0.css +0 -1
  146. package/packages/storefront/dist/client/_astro/client.7c1b0374.js +0 -1
  147. package/packages/storefront/dist/client/_astro/customer-session.2d173cc1.js +0 -1
  148. package/packages/storefront/dist/client/_astro/ecom-icon_12falx.png +0 -0
  149. package/packages/storefront/dist/client/_astro/ecom-icon_15pqnO.png +0 -0
  150. package/packages/storefront/dist/client/_astro/ecom-icon_t3guw.png +0 -0
  151. package/packages/storefront/dist/client/_astro/ecom-utils.c385a436.js +0 -1
  152. package/packages/storefront/dist/client/_astro/headphone_T2Jjc.avif +0 -0
  153. package/packages/storefront/dist/client/_astro/headphone_Z1CG18r.webp +0 -0
  154. package/packages/storefront/dist/client/_astro/hoisted.f16496bc.js +0 -1
  155. package/packages/storefront/dist/client/_astro/index.e02b88b7.js +0 -1
  156. package/packages/storefront/dist/client/_astro/index.e20e07e3.js +0 -1
  157. package/packages/storefront/dist/client/_astro/logo_1UBsBq.webp +0 -0
  158. package/packages/storefront/dist/client/_astro/logo_Z1K5PE9.png +0 -0
  159. package/packages/storefront/dist/client/_astro/logo_Z1KIIl1.avif +0 -0
  160. package/packages/storefront/dist/client/_astro/name.3cd31c8b.js +0 -1
  161. package/packages/storefront/dist/client/_astro/passion_LHbe9.webp +0 -0
  162. package/packages/storefront/dist/client/_astro/passion_Z23MeUb.avif +0 -0
  163. package/packages/storefront/dist/client/_astro/rect8589_1TtOHY.png +0 -0
  164. package/packages/storefront/dist/client/_astro/rect8589_1f5opX.webp +0 -0
  165. package/packages/storefront/dist/client/_astro/rect8589_IUskt.webp +0 -0
  166. package/packages/storefront/dist/client/_astro/rect8589_Uxfdf.png +0 -0
  167. package/packages/storefront/dist/client/_astro/rect8589_Z15uApA.png +0 -0
  168. package/packages/storefront/dist/client/_astro/rect8589_Z1Ap1Im.avif +0 -0
  169. package/packages/storefront/dist/client/_astro/rect8589_Z1JT1HB.webp +0 -0
  170. package/packages/storefront/dist/client/_astro/rect8589_ZY9mtN.avif +0 -0
  171. package/packages/storefront/dist/client/_astro/rect8589_tMFW0.avif +0 -0
  172. package/packages/storefront/dist/client/_astro/rect859_1TgQXS.avif +0 -0
  173. package/packages/storefront/dist/client/_astro/rect859_2Nm1z.avif +0 -0
  174. package/packages/storefront/dist/client/_astro/rect859_DIqwR.png +0 -0
  175. package/packages/storefront/dist/client/_astro/rect859_Z1IKDb2.png +0 -0
  176. package/packages/storefront/dist/client/_astro/rect859_Z29FI4V.webp +0 -0
  177. package/packages/storefront/dist/client/_astro/rect859_Z2kFHGk.avif +0 -0
  178. package/packages/storefront/dist/client/_astro/rect859_ZkpPFI.webp +0 -0
  179. package/packages/storefront/dist/client/_astro/rect859_jXzBi.png +0 -0
  180. package/packages/storefront/dist/client/_astro/rect859_x1l16.webp +0 -0
  181. package/packages/storefront/dist/client/_astro/rect89_1TSfW7.avif +0 -0
  182. package/packages/storefront/dist/client/_astro/rect89_Z1re32x.webp +0 -0
  183. package/packages/storefront/dist/client/_astro/shopping-cart.6b03b120.js +0 -1
  184. package/packages/storefront/dist/client/~fallback.html +0 -74
  185. package/packages/storefront/dist/client/~index.html +0 -120
  186. package/packages/storefront/dist/server/chunks/SearchModal_2afca4fe.mjs +0 -18
  187. package/packages/storefront/dist/server/chunks/pages/account_bfd9a66a.mjs +0 -21
  188. package/packages/storefront/dist/server/chunks/pages/node_530334cf.mjs +0 -160
  189. package/packages/storefront/dist/server/images.dist.csv +0 -30
  190. package/packages/storefront/dist/server/images.src.csv +0 -11
  191. package/packages/storefront/dist/server/static-builds.csv +0 -66
@@ -8,17 +8,25 @@ import {
8
8
 
9
9
  export interface Props {
10
10
  modelValue?: boolean;
11
+ isHidden?: boolean;
11
12
  placement?: 'start' | 'end' | 'top' | 'bottom';
12
13
  position?: 'fixed' | 'absolute';
14
+ animation?: 'slide' | 'scale' | null;
13
15
  hasCloseButton?: boolean;
14
- backdropTarget?: string;
16
+ anchorEl?: HTMLElement | null;
17
+ backdropTarget?: string | null;
18
+ maxWidth?: string;
19
+ class?: string | string[] | Record<string, string | null> | null;
15
20
  }
16
21
 
17
22
  const props = withDefaults(defineProps<Props>(), {
18
23
  modelValue: false,
24
+ isHidden: false,
19
25
  placement: 'start',
20
26
  position: 'fixed',
27
+ animation: 'slide',
21
28
  hasCloseButton: true,
29
+ hasBackdrop: true,
22
30
  backdropTarget: '#teleported-top',
23
31
  });
24
32
  const emit = defineEmits<{
@@ -28,6 +36,7 @@ const close = () => emit('update:modelValue', false);
28
36
  const drawer = ref<HTMLElement | null>(null);
29
37
  const outsideClickListener = (ev: MouseEvent) => {
30
38
  if (!drawer.value?.contains(ev.target as Node)) {
39
+ if (props.anchorEl?.contains(ev.target as Node)) return;
31
40
  close();
32
41
  }
33
42
  };
@@ -54,6 +63,7 @@ watch(toRef(props, 'modelValue'), async (isOpen) => {
54
63
  }
55
64
  });
56
65
  const slideTo = computed(() => {
66
+ if (props.animation !== 'slide') return null;
57
67
  switch (props.placement) {
58
68
  case 'start': return 'left';
59
69
  case 'end': return 'right';
@@ -61,6 +71,27 @@ const slideTo = computed(() => {
61
71
  default: return 'up';
62
72
  }
63
73
  });
74
+ const animationClassName = ref<string | null>(null);
75
+ if (props.animation === 'scale') {
76
+ watch(toRef(props, 'modelValue'), (isShown) => {
77
+ if (!isShown) {
78
+ animationClassName.value = 'transition scale-90';
79
+ } else {
80
+ nextTick(() => {
81
+ setTimeout(() => {
82
+ animationClassName.value = 'transition';
83
+ setTimeout(() => {
84
+ if (props.modelValue) animationClassName.value = '';
85
+ }, 300);
86
+ }, 50);
87
+ });
88
+ }
89
+ }, { immediate: true });
90
+ }
91
+ const customClassList = computed(() => {
92
+ if (Array.isArray(props.class)) return props.class;
93
+ return [props.class];
94
+ });
64
95
  const isFixed = computed(() => {
65
96
  return props.position === 'fixed';
66
97
  });
@@ -73,17 +104,24 @@ const isPlacementX = computed(() => {
73
104
  <Fade :slide="slideTo" speed="slow" is-floating>
74
105
  <dialog
75
106
  v-if="modelValue"
107
+ v-show="!isHidden"
76
108
  ref="drawer"
77
- class="z-50 m-0 w-screen p-0 shadow"
109
+ class="z-40 w-screen p-0"
78
110
  :class="[
79
111
  position,
112
+ isPlacementX ? 'm-0' : 'mx-auto',
113
+ isPlacementX && !maxWidth ? 'max-w-sm' : null,
80
114
  isFixed ? `top-0 ${(isPlacementX ? 'h-screen' : 'max-h-screen')}` : null,
81
115
  isFixed && placement !== 'end' ? 'left-0' : null,
82
116
  isFixed && placement === 'end' ? 'left-auto right-0' : null,
83
- isPlacementX ? 'max-w-sm' : null,
117
+ animationClassName,
118
+ ...customClassList,
84
119
  ]"
85
120
  :style="{
86
- maxWidth: !isPlacementX ? `calc(100vw - ${scrollbarWidth}px)` : undefined,
121
+ maxWidth: maxWidth
122
+ ? `min(${maxWidth}, calc(100vw - ${scrollbarWidth}px))`
123
+ : !isPlacementX
124
+ ? `calc(100vw - ${scrollbarWidth}px)` : undefined,
87
125
  }"
88
126
  :open="modelValue"
89
127
  :data-drawer="placement"
@@ -104,11 +142,11 @@ const isPlacementX = computed(() => {
104
142
  </button>
105
143
  <slot />
106
144
  </div>
107
- <Teleport :to="backdropTarget">
145
+ <Teleport v-if="backdropTarget" :to="backdropTarget">
108
146
  <Fade>
109
147
  <div
110
- v-if="modelValue"
111
- class="fixed left-0 top-0 z-40 h-screen w-screen bg-black/50"
148
+ v-if="modelValue && !isHidden"
149
+ class="fixed left-0 top-0 z-30 h-screen w-screen bg-black/50"
112
150
  data-drawer-backdrop
113
151
  ></div>
114
152
  </Fade>
@@ -3,7 +3,7 @@ import { computed } from 'vue';
3
3
 
4
4
  export interface Props {
5
5
  speed?: 'default' | 'slow' | 'slower',
6
- slide?: 'down' | 'left' | 'right' | 'up',
6
+ slide?: 'down' | 'left' | 'right' | 'up' | null,
7
7
  isFloating?: boolean,
8
8
  isLeaveTo?: boolean,
9
9
  isEnterFrom?: boolean,
@@ -4,7 +4,7 @@ import api from '@cloudcommerce/api';
4
4
  import { inStock as checkInStock } from '@ecomplus/utils';
5
5
 
6
6
  export interface Props {
7
- collectionId: ResourceId | null;
7
+ collectionId?: ResourceId | null;
8
8
  searchQuery?: `&${string}` | '';
9
9
  sort?: '-sales' | '-created_at' | 'price' | '-price' | '-price_discount' | string;
10
10
  title?: string | null;
@@ -33,8 +33,8 @@ const watchAppRoutes = () => {
33
33
  emittedCheckoutSteps.push(evName);
34
34
  if (!params) {
35
35
  params = {
36
- value: fixMoneyValue(shoppingCart.value.subtotal),
37
- items: shoppingCart.value.items.map(getGtagItem),
36
+ value: fixMoneyValue(shoppingCart.subtotal || 0),
37
+ items: shoppingCart.items.map(getGtagItem),
38
38
  };
39
39
  }
40
40
  if (evName !== 'view_cart') {
@@ -63,8 +63,8 @@ const watchAppRoutes = () => {
63
63
  };
64
64
  const params: Gtag.EventParams = {
65
65
  transaction_id: orderId,
66
- value: fixMoneyValue(amount?.total || shoppingCart.value.subtotal),
67
- items: shoppingCart.value.items.map(getGtagItem),
66
+ value: fixMoneyValue(amount?.total || shoppingCart.subtotal || 0),
67
+ items: shoppingCart.items.map(getGtagItem),
68
68
  coupon: order
69
69
  ? order.extra_discount?.discount_coupon
70
70
  : getCouponApplied(),
@@ -182,19 +182,29 @@ if (!import.meta.env.SSR) {
182
182
  if (Object.keys(utm).length) {
183
183
  sessionStorage.setItem('ecomUtm', JSON.stringify(utm));
184
184
  }
185
+ let querystring = window.location.search;
186
+ if (!querystring && window.location.hash) {
187
+ querystring = '?' + window.location.hash.split('?')[1];
188
+ }
189
+ const searchParams = new URLSearchParams(querystring);
190
+ if (searchParams.get('product_id') && searchParams.get('quantity') === '1') {
191
+ localStorage.setItem('ecomShoppingCart__tmp', JSON.stringify({
192
+ items: [{
193
+ product_id: searchParams.get('product_id'),
194
+ variation_id: searchParams.get('variation_id') || undefined,
195
+ quantity: 1,
196
+ }],
197
+ }));
198
+ (window as any).ECOM_CART_STORAGE_KEY = 'ecomShoppingCart__tmp';
199
+ }
185
200
  const { hostname } = window.location;
186
201
  const { domain } = globalThis.$storefront.settings;
187
202
  const apiBaseUri = `https://ecomplus.io/v2/:${window.ECOM_STORE_ID}/`;
188
- // @ts-ignore
189
- window.ECOMCLIENT_API_STORE = apiBaseUri;
190
- // @ts-ignore
191
- window.ECOMCLIENT_API_STORE_CACHE = apiBaseUri;
192
- // @ts-ignore
193
- window.ECOMCLIENT_API_PASSPORT = apiBaseUri;
194
- // @ts-ignore
195
- window.ECOMCLIENT_API_SEARCH = `${apiBaseUri}/search/_els/`;
196
- // @ts-ignore
197
- window.ECOMCLIENT_API_MODULES = hostname !== 'localhost' && hostname !== '127.0.0.1'
203
+ (window as any).ECOMCLIENT_API_STORE = apiBaseUri;
204
+ (window as any).ECOMCLIENT_API_STORE_CACHE = apiBaseUri;
205
+ (window as any).ECOMCLIENT_API_PASSPORT = apiBaseUri;
206
+ (window as any).ECOMCLIENT_API_SEARCH = `${apiBaseUri}/search/_els/`;
207
+ (window as any).ECOMCLIENT_API_MODULES = ['localhost', '127.0.0.1'].includes(hostname)
198
208
  ? `https://${domain}/_api/modules/`
199
209
  : '/_api/modules/';
200
210
 
@@ -227,7 +237,7 @@ if (!import.meta.env.SSR) {
227
237
  };
228
238
 
229
239
  const appScript = document.createElement('script');
230
- appScript.src = 'https://cdn.jsdelivr.net/npm/@ecomplus/storefront-app@2.0.0-beta.188/dist/lib/js/app.js';
240
+ appScript.src = 'https://cdn.jsdelivr.net/npm/@ecomplus/storefront-app@2.0.0-beta.190/dist/lib/js/app.js';
231
241
  appScript.onload = onLoad;
232
242
  document.body.appendChild(appScript);
233
243
  }
@@ -70,13 +70,16 @@ const setResponseCache = (Astro: AstroGlobal, maxAge: number, sMaxAge?: number)
70
70
 
71
71
  export type ApiPrefetchEndpoints = Array<ApiEndpoint | ':slug'>;
72
72
 
73
- const loadRouteContext = async (Astro: Readonly<AstroGlobal>, {
74
- contentCollection,
75
- apiPrefetchEndpoints = globalThis.$apiPrefetchEndpoints,
76
- }: {
77
- contentCollection?: string;
78
- apiPrefetchEndpoints?: ApiPrefetchEndpoints;
79
- } = {}) => {
73
+ const loadRouteContext = async (
74
+ Astro: AstroGlobal | Readonly<AstroGlobal<any, any, any>>,
75
+ {
76
+ contentCollection,
77
+ apiPrefetchEndpoints = globalThis.$apiPrefetchEndpoints,
78
+ }: {
79
+ contentCollection?: string;
80
+ apiPrefetchEndpoints?: ApiPrefetchEndpoints;
81
+ } = {},
82
+ ) => {
80
83
  const startedAt = Date.now();
81
84
  let urlPath = Astro.url.pathname;
82
85
  const isPreview = urlPath.startsWith('/~preview');
@@ -114,7 +117,7 @@ const loadRouteContext = async (Astro: Readonly<AstroGlobal>, {
114
117
  const { slug } = Astro.params;
115
118
  if (isHomepage) {
116
119
  cmsContent = await config.getContent('pages/home');
117
- } else if (slug) {
120
+ } else if (slug && typeof slug === 'string') {
118
121
  if (contentCollection) {
119
122
  cmsContent = await config.getContent(`${contentCollection}/${slug}`);
120
123
  } else if (slug.startsWith('_api/') || slug === '_analytics') {
@@ -0,0 +1,101 @@
1
+ import type { SearchItem } from '@cloudcommerce/types';
2
+ import { ref, watch, shallowReactive } from 'vue';
3
+ import { useDebounceFn } from '@vueuse/core';
4
+ import api from '@cloudcommerce/api';
5
+ import useStorage from '@@sf/state/use-storage';
6
+
7
+ const storageKey = 'ecomSeachHistory';
8
+
9
+ export const searchHistory = useStorage<string[]>(storageKey, []);
10
+
11
+ export const search = async ({
12
+ term,
13
+ params,
14
+ fields,
15
+ url = 'search/v1',
16
+ }: {
17
+ term: string,
18
+ params?: Record<string, any>,
19
+ fields?: readonly string[],
20
+ url?: 'search/v1' | `search/v1?${string}`,
21
+ }) => {
22
+ term = term.trim();
23
+ if (term.length < 2) {
24
+ return { data: { result: [], meta: null } };
25
+ }
26
+ const response = await api.get(url, {
27
+ fields,
28
+ params: {
29
+ ...params,
30
+ term,
31
+ },
32
+ });
33
+ if (response.data.result.length && !searchHistory.includes(term)) {
34
+ const termIndex = searchHistory.findIndex((_term) => term.startsWith(_term));
35
+ if (termIndex > -1) {
36
+ searchHistory[termIndex] = term;
37
+ } else {
38
+ searchHistory.unshift(term);
39
+ }
40
+ while (searchHistory.length > 20) {
41
+ searchHistory.pop();
42
+ }
43
+ }
44
+ return response;
45
+ };
46
+
47
+ export class SearchEngine {
48
+ url: 'search/v1' | `search/v1?${string}`;
49
+ fields?: readonly string[];
50
+ term = ref('');
51
+ params = shallowReactive<Record<string, any>>({});
52
+ pageSize = ref(24);
53
+ pageNumber = ref(1);
54
+ products = shallowReactive<SearchItem[]>([]);
55
+ #search: ReturnType<typeof useDebounceFn<typeof search>>;
56
+ constructor({
57
+ fields,
58
+ url = 'search/v1',
59
+ debounce = 150,
60
+ }: {
61
+ fields?: readonly string[],
62
+ url?: 'search/v1' | `search/v1?${string}`,
63
+ debounce?: number,
64
+ } = {}) {
65
+ this.fields = fields;
66
+ this.url = url;
67
+ this.products = shallowReactive([]);
68
+ this.#search = useDebounceFn(search, debounce);
69
+ watch([this.term, this.params], () => {
70
+ this.pageNumber.value = 1;
71
+ });
72
+ }
73
+
74
+ async fetch(term?: string) {
75
+ if (term && term !== this.term.value) {
76
+ this.term.value = term;
77
+ this.pageNumber.value = 1;
78
+ }
79
+ const limit = this.pageSize.value;
80
+ const offset = limit * (this.pageNumber.value - 1);
81
+ const response = await this.#search({
82
+ term: this.term.value,
83
+ params: {
84
+ limit,
85
+ offset,
86
+ ...this.params,
87
+ },
88
+ url: this.url,
89
+ fields: this.fields,
90
+ });
91
+ if (response) {
92
+ const { data } = response;
93
+ if (data.meta) {
94
+ this.products.splice(0);
95
+ }
96
+ data.result.forEach((item) => this.products.push(item));
97
+ }
98
+ }
99
+ }
100
+
101
+ export default SearchEngine;
@@ -1,6 +1,6 @@
1
1
  import type { Products, CartSet, SearchItem } from '@cloudcommerce/api/types';
2
- import { computed } from 'vue';
3
- import { watchDebounced } from '@vueuse/core';
2
+ import { computed, watch } from 'vue';
3
+ import { useDebounceFn } from '@vueuse/core';
4
4
  import mitt from 'mitt';
5
5
  import useStorage from '@@sf/state/use-storage';
6
6
  import addItem from '@@sf/state/shopping-cart/add-cart-item';
@@ -11,79 +11,31 @@ const storageKey = 'ecomShoppingCart';
11
11
  const emptyCart = {
12
12
  items: [],
13
13
  };
14
- const cart = useStorage<CartSet>(storageKey, emptyCart);
15
-
16
- const cartItems = computed(() => {
17
- return cart.items.map((item) => {
18
- let finalPrice = item.kit_product?.price && item.kit_product.pack_quantity
19
- ? item.kit_product.price / item.kit_product.pack_quantity
20
- : item.price;
21
- if (Array.isArray(item.customizations)) {
22
- item.customizations.forEach((customization) => {
23
- if (customization.add_to_price) {
24
- const { type, addition } = customization.add_to_price;
25
- finalPrice += type === 'fixed'
26
- ? addition
27
- : item.price * (addition / 100);
28
- }
29
- });
30
- }
31
- item.final_price = finalPrice;
32
- const min = item.min_quantity || 1;
33
- const max = item.max_quantity;
34
- if (
35
- typeof item.quantity !== 'number'
36
- || Number.isNaN(item.quantity)
37
- || item.quantity < min
38
- ) {
39
- item.quantity = min;
40
- } else if (max && item.quantity > max) {
41
- item.quantity = max;
42
- }
43
- return item;
44
- });
45
- });
46
- const subtotal = computed(() => {
47
- return cartItems.value.reduce((acc, item) => {
48
- return acc + (item.quantity * (item.final_price || item.price));
49
- }, 0);
50
- });
14
+ const shoppingCart = useStorage<CartSet>(storageKey, emptyCart);
51
15
  const totalItems = computed(() => {
52
- return cartItems.value.reduce((acc, item) => {
16
+ return shoppingCart.items.reduce((acc, item) => {
53
17
  return acc + item.quantity;
54
18
  }, 0);
55
19
  });
56
- const shoppingCart = computed({
57
- get() {
58
- return {
59
- ...cart,
60
- subtotal: subtotal.value,
61
- };
62
- },
63
- set(newCart) {
64
- Object.assign(cart, newCart, {
65
- subtotal: subtotal.value,
66
- });
67
- },
68
- });
69
20
 
70
21
  const addCartItem = (newItem: CartItem) => {
71
- const cartObj = shoppingCart.value;
72
- const upsertedItem = addItem(cartObj, newItem);
73
- if (upsertedItem) {
74
- // Force reactivity
75
- shoppingCart.value.items = cartObj.items;
76
- }
22
+ addItem(shoppingCart, newItem);
77
23
  };
78
24
  const removeCartItem = (itemId: string) => {
79
- for (let i = 0; i < shoppingCart.value.items.length; i++) {
80
- const item = shoppingCart.value.items[i];
25
+ for (let i = 0; i < shoppingCart.items.length; i++) {
26
+ const item = shoppingCart.items[i];
81
27
  if (item._id === itemId) {
82
- shoppingCart.value.items.splice(i, 1);
28
+ shoppingCart.items.splice(i, 1);
83
29
  break;
84
30
  }
85
31
  }
86
32
  };
33
+ const resetCartItems = (items?: CartItem[]) => {
34
+ while (shoppingCart.items.length) {
35
+ shoppingCart.items.pop();
36
+ }
37
+ items?.forEach(addCartItem);
38
+ };
87
39
  const addProductToCart = (
88
40
  product: (Partial<Products> | Partial<SearchItem>) & { _id: Products['_id'] },
89
41
  variationId?: Products['_id'],
@@ -97,6 +49,7 @@ export {
97
49
  shoppingCart,
98
50
  addCartItem,
99
51
  removeCartItem,
52
+ resetCartItems,
100
53
  parseProduct,
101
54
  addProductToCart,
102
55
  };
@@ -106,9 +59,9 @@ type CartEvent = {
106
59
  removeCartItem: CartItem,
107
60
  };
108
61
  const cartEmitter = mitt<CartEvent>();
109
- const cloneItems = () => shoppingCart.value.items.map((item) => ({ ...item }));
62
+ const cloneItems = () => shoppingCart.items.map((item) => ({ ...item }));
110
63
  let oldItems = cloneItems();
111
- watchDebounced(shoppingCart, ({ items }) => {
64
+ const emitCartEvents = useDebounceFn((items: CartItem[]) => {
112
65
  ['addCartItem' as const, 'removeCartItem' as const].forEach((evName) => {
113
66
  const isAdd = evName === 'addCartItem';
114
67
  const baseItems = isAdd ? items : oldItems;
@@ -126,7 +79,41 @@ watchDebounced(shoppingCart, ({ items }) => {
126
79
  });
127
80
  });
128
81
  oldItems = cloneItems();
129
- }, { debounce: 200 });
82
+ }, 200);
83
+
84
+ watch(shoppingCart.items, (items) => {
85
+ items.forEach((item) => {
86
+ let finalPrice = item.kit_product?.price && item.kit_product.pack_quantity
87
+ ? item.kit_product.price / item.kit_product.pack_quantity
88
+ : item.price;
89
+ if (Array.isArray(item.customizations)) {
90
+ item.customizations.forEach((customization) => {
91
+ if (customization.add_to_price) {
92
+ const { type, addition } = customization.add_to_price;
93
+ finalPrice += type === 'fixed'
94
+ ? addition
95
+ : item.price * (addition / 100);
96
+ }
97
+ });
98
+ }
99
+ item.final_price = finalPrice;
100
+ const min = item.min_quantity || 1;
101
+ const max = item.max_quantity;
102
+ if (
103
+ typeof item.quantity !== 'number'
104
+ || Number.isNaN(item.quantity)
105
+ || item.quantity < min
106
+ ) {
107
+ item.quantity = min;
108
+ } else if (max && item.quantity > max) {
109
+ item.quantity = max;
110
+ }
111
+ });
112
+ shoppingCart.subtotal = items.reduce((acc, item) => {
113
+ return acc + (item.quantity * (item.final_price || item.price));
114
+ }, 0);
115
+ emitCartEvents(items);
116
+ });
130
117
 
131
118
  export const cartEvents = {
132
119
  on: cartEmitter.on,
@@ -11,6 +11,7 @@ export const trackingIds: {
11
11
  g_session_id?: string,
12
12
  fbclid?: string,
13
13
  fbp?: string,
14
+ ttclid?: string,
14
15
  client_id?: string,
15
16
  session_id?: string,
16
17
  } = {};
@@ -242,7 +243,7 @@ export const useAnalytics = () => {
242
243
  });
243
244
  }
244
245
  const url = new URL(window.location.toString());
245
- ['gclid', 'fbclid'].forEach((key) => {
246
+ ['gclid', 'fbclid', 'ttclid'].forEach((key) => {
246
247
  const id = trackingIds[key] || url.searchParams.get(key);
247
248
  if (id) {
248
249
  trackingIds[key] = id;
@@ -1,4 +1,5 @@
1
- import { reactive, watch } from 'vue';
1
+ import { reactive } from 'vue';
2
+ import { watchDebounced } from '@vueuse/core';
2
3
 
3
4
  const useStorage = <T extends {}>(
4
5
  key: string,
@@ -19,8 +20,10 @@ const useStorage = <T extends {}>(
19
20
  }
20
21
  }
21
22
  const state = reactive<T>(persistedValue || initialValue);
22
- watch(state, () => {
23
+ watchDebounced(state, () => {
23
24
  storage.setItem(key, JSON.stringify(state));
25
+ }, {
26
+ debounce: 50,
24
27
  });
25
28
  return state;
26
29
  };
@@ -2,7 +2,7 @@
2
2
  "name": "@cloudcommerce/test-base",
3
3
  "private": true,
4
4
  "type": "module",
5
- "version": "0.34.0",
5
+ "version": "0.35.1",
6
6
  "description": "E-Com Plus Cloud Commerce basic setup for testing",
7
7
  "main": "lib/index.js",
8
8
  "repository": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/types",
3
3
  "type": "module",
4
- "version": "0.34.0",
4
+ "version": "0.35.1",
5
5
  "description": "E-Com Plus Cloud Commerce reusable type definitions",
6
6
  "main": "index.ts",
7
7
  "repository": {
@@ -1,48 +0,0 @@
1
- import axios from 'axios';
2
-
3
- const ga4Axios = axios.create({
4
- baseURL: 'https://www.google-analytics.com',
5
- headers: {
6
- 'Content-Type': 'application/json',
7
- },
8
- });
9
- const url = `/mp/collect?api_secret=${process.env.GA_API_TOKEN}`
10
- + `&measurement_id=${process.env.GA_MEASUREMENT_ID}`;
11
- const sendEvent = (analyticsEvents, clientId, sessionId, utm) => {
12
- if (process.env.GA_API_TOKEN && process.env.GA_MEASUREMENT_ID) {
13
- const requests = [];
14
- let events = [];
15
- analyticsEvents.forEach((event, index) => {
16
- if (event.params) {
17
- Object.assign(event.params, { session_id: sessionId });
18
- }
19
- const body = event;
20
- if (body.name === 'page_view') {
21
- body.name = 'campaign_details';
22
- body.params = {
23
- source: utm?.source,
24
- medium: utm?.medium,
25
- campaign: utm?.campaign,
26
- term: utm?.term,
27
- content: utm?.content,
28
- session_id: sessionId,
29
- };
30
- }
31
- events.push(body);
32
- if (events.length === 25 || index === analyticsEvents.length - 1) {
33
- events.push(body);
34
- requests.push(ga4Axios.post(url, {
35
- client_id: clientId,
36
- events,
37
- }));
38
- events = [];
39
- }
40
- });
41
- return requests;
42
- }
43
- // throw new Error('Google Analytics credentials not found');
44
- return null;
45
- };
46
-
47
- export default sendEvent;
48
- // # sourceMappingURL=google-analytics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"google-analytics.js","sourceRoot":"","sources":["../../src/analytics-providers/google-analytics.ts"],"names":[],"mappings":"AACA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAE7C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAE,kCAAkC;IAC3C,OAAO,EAAE;QACP,cAAc,EAAE,kBAAkB;KACnC;CACF,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,0BAA0B,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE;MAC5D,mBAAmB,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;AAEvD,MAAM,SAAS,GAAG,CAChB,eAAiC,EACjC,QAAgB,EAChB,SAAiB,EACjB,GAMC,EACD,EAAE;IACF,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE;QAC7D,MAAM,QAAQ,GAAuC,EAAE,CAAC;QACxD,IAAI,MAAM,GAAqB,EAAE,CAAC;QAElC,eAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACvC,IAAI,KAAK,CAAC,MAAM,EAAE;gBAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;aACxD;YAED,MAAM,IAAI,GAAG,KAAK,CAAC;YACnB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE;gBAC7B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;gBAC/B,IAAI,CAAC,MAAM,GAAG;oBACZ,MAAM,EAAE,GAAG,EAAE,MAAM;oBACnB,MAAM,EAAE,GAAG,EAAE,MAAM;oBACnB,QAAQ,EAAE,GAAG,EAAE,QAAQ;oBACvB,IAAI,EAAE,GAAG,EAAE,IAAI;oBACf,OAAO,EAAE,GAAG,EAAE,OAAO;oBACrB,UAAU,EAAE,SAAS;iBACtB,CAAC;aACH;YAED,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,KAAK,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE;gBAChE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,QAAQ,CAAC,IAAI,CACX,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;oBACjB,SAAS,EAAE,QAAQ;oBACnB,MAAM;iBACP,CAAC,CACH,CAAC;gBACF,MAAM,GAAG,EAAE,CAAC;aACb;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;KACjB;IACD,6DAA6D;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -1,44 +0,0 @@
1
- import axios from 'axios';
2
-
3
- const version = 'v18.0';
4
- const metaAxios = axios.create({
5
- baseURL: `https://graph.facebook.com/${version}`,
6
- headers: {
7
- 'Content-Type': 'application/json',
8
- },
9
- });
10
- const url = `/${process.env.FB_PIXEL_ID}/events?access_token=${process.env.FB_GRAPH_TOKEN}`;
11
- const sendEvent = (metaEvents, pageLocation, userData) => {
12
- if (process.env.FB_PIXEL_ID && process.env.FB_GRAPH_TOKEN) {
13
- const requests = [];
14
- let data = [];
15
- metaEvents.forEach((event, index) => {
16
- const body = event;
17
- if (body.name === 'PageView') {
18
- body.name = 'Lead';
19
- body.params = {
20
- content_name: event.params?.page_title,
21
- };
22
- }
23
- data.push({
24
- event_name: body.name,
25
- event_time: Date.now(),
26
- event_source_url: pageLocation,
27
- action_source: 'website',
28
- user_data: userData,
29
- custom_data: body.params,
30
- });
31
- if (data.length === 1000 || index === metaEvents.length - 1) {
32
- requests.push(metaAxios.post(url, { data }));
33
- data = [];
34
- }
35
- });
36
- return requests;
37
- }
38
- // throw new Error('Meta credentials not found');
39
- return null;
40
- };
41
-
42
- // https://developers.facebook.com/docs/meta-pixel/reference#standard-events
43
- export default sendEvent;
44
- // # sourceMappingURL=meta-conversions-api.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"meta-conversions-api.js","sourceRoot":"","sources":["../../src/analytics-providers/meta-conversions-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAE7C,MAAM,OAAO,GAAG,OAAO,CAAC;AACxB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IAC7B,OAAO,EAAE,8BAA8B,OAAO,EAAE;IAChD,OAAO,EAAE;QACP,cAAc,EAAE,kBAAkB;KACnC;CACF,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,wBAAwB,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;AAE5F,MAAM,SAAS,GAAG,CAChB,UAA4B,EAC5B,YAAoB,EACpB,QAA6C,EAE7C,EAAE;IACF,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;QACzD,MAAM,QAAQ,GAAuC,EAAE,CAAC;QACxD,IAAI,IAAI,GAA2B,EAAE,CAAC;QAEtC,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAClC,MAAM,IAAI,GAAG,KAAK,CAAC;YACnB,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;gBAC5B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;gBACnB,IAAI,CAAC,MAAM,GAAG;oBACZ,YAAY,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU;iBACvC,CAAC;aACH;YAED,IAAI,CAAC,IAAI,CAAC;gBACR,UAAU,EAAE,IAAI,CAAC,IAAI;gBACrB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;gBACtB,gBAAgB,EAAE,YAAY;gBAC9B,aAAa,EAAE,SAAS;gBACxB,SAAS,EAAE,QAAQ;gBACnB,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC3D,QAAQ,CAAC,IAAI,CACX,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAC9B,CAAC;gBACF,IAAI,GAAG,EAAE,CAAC;aACX;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;KACjB;IACD,iDAAiD;IACjD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,4EAA4E;AAC5E,eAAe,SAAS,CAAC"}