cloudcommerce 0.22.4 → 0.23.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 (136) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/ecomplus-stores/barra-doce/.eslintrc.cjs +1 -1
  3. package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
  4. package/ecomplus-stores/barra-doce/functions/ssr/.eslintrc.cjs +1 -1
  5. package/ecomplus-stores/barra-doce/functions/ssr/package.json +6 -6
  6. package/ecomplus-stores/barra-doce/functions/ssr/src/components/AccountMenu.vue +1 -1
  7. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductCard.vue +1 -4
  8. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopSidenav.vue +1 -1
  9. package/ecomplus-stores/barra-doce/functions/ssr/src/main/Home.astro +18 -10
  10. package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
  11. package/ecomplus-stores/barra-doce/package.json +4 -1
  12. package/ecomplus-stores/iluminim/.ecomplus.cd.json +3 -3
  13. package/ecomplus-stores/iluminim/.eslintrc.cjs +1 -1
  14. package/ecomplus-stores/iluminim/functions/many/package.json +3 -3
  15. package/ecomplus-stores/iluminim/functions/ssr/.eslintrc.cjs +1 -1
  16. package/ecomplus-stores/iluminim/functions/ssr/package.json +6 -6
  17. package/ecomplus-stores/iluminim/functions/ssr/src/components/AccountMenu.vue +1 -1
  18. package/ecomplus-stores/iluminim/functions/ssr/src/components/ProductCard.vue +5 -5
  19. package/ecomplus-stores/iluminim/functions/ssr/src/components/ShopSidenav.vue +1 -1
  20. package/ecomplus-stores/iluminim/functions/with-apps/package.json +3 -3
  21. package/ecomplus-stores/iluminim/package.json +4 -1
  22. package/package.json +4 -4
  23. package/packages/api/package.json +1 -1
  24. package/packages/api/types/carts.d.ts +8 -0
  25. package/packages/api/types/orders.d.ts +8 -0
  26. package/packages/apps/affilate-program/package.json +1 -1
  27. package/packages/apps/correios/package.json +1 -1
  28. package/packages/apps/custom-payment/package.json +1 -1
  29. package/packages/apps/custom-shipping/package.json +1 -1
  30. package/packages/apps/datafrete/package.json +1 -1
  31. package/packages/apps/discounts/package.json +1 -1
  32. package/packages/apps/emails/package.json +1 -1
  33. package/packages/apps/fb-conversions/package.json +1 -1
  34. package/packages/apps/flash-courier/package.json +1 -1
  35. package/packages/apps/frenet/package.json +1 -1
  36. package/packages/apps/galaxpay/package.json +1 -1
  37. package/packages/apps/google-analytics/package.json +1 -1
  38. package/packages/apps/jadlog/package.json +1 -1
  39. package/packages/apps/loyalty-points/package.json +1 -1
  40. package/packages/apps/melhor-envio/package.json +1 -1
  41. package/packages/apps/mercadopago/package.json +1 -1
  42. package/packages/apps/pagarme/package.json +1 -1
  43. package/packages/apps/paghiper/package.json +1 -1
  44. package/packages/apps/pix/package.json +1 -1
  45. package/packages/apps/tiny-erp/package.json +1 -1
  46. package/packages/apps/webhooks/package.json +1 -1
  47. package/packages/cli/lib/build.js +1 -1
  48. package/packages/cli/package.json +1 -1
  49. package/packages/cli/src/build.ts +1 -1
  50. package/packages/config/package.json +1 -1
  51. package/packages/emails/package.json +1 -1
  52. package/packages/eslint/package.json +3 -3
  53. package/packages/events/package.json +1 -1
  54. package/packages/feeds/package.json +1 -1
  55. package/packages/firebase/package.json +1 -1
  56. package/packages/i18n/lib/en_us/i19minus.txt +1 -0
  57. package/packages/i18n/lib/en_us/i19plus.txt +1 -0
  58. package/packages/i18n/lib/en_us.d.ts +2 -0
  59. package/packages/i18n/lib/en_us.js +2 -0
  60. package/packages/i18n/lib/en_us.js.map +1 -1
  61. package/packages/i18n/lib/pt_br/i19minus.txt +1 -0
  62. package/packages/i18n/lib/pt_br/i19plus.txt +1 -0
  63. package/packages/i18n/lib/pt_br.d.ts +2 -0
  64. package/packages/i18n/lib/pt_br.js +2 -0
  65. package/packages/i18n/lib/pt_br.js.map +1 -1
  66. package/packages/i18n/package.json +1 -1
  67. package/packages/i18n/src/en_us.ts +2 -0
  68. package/packages/i18n/src/pt_br.ts +2 -0
  69. package/packages/modules/package.json +1 -1
  70. package/packages/passport/package.json +1 -1
  71. package/packages/ssr/cloudflare/README.md +3 -0
  72. package/packages/ssr/cloudflare/swr-worker.js +102 -0
  73. package/packages/ssr/lib/firebase/serve-storefront.js +0 -1
  74. package/packages/ssr/lib/firebase/serve-storefront.js.map +1 -1
  75. package/packages/ssr/package.json +6 -4
  76. package/packages/ssr/src/cloudflare/swr-worker.ts +120 -0
  77. package/packages/ssr/src/cloudflare/tsconfig.json +8 -0
  78. package/packages/ssr/src/firebase/serve-storefront.ts +0 -1
  79. package/packages/ssr/tsconfig.json +2 -1
  80. package/packages/storefront/config/storefront.cms.js +1 -1
  81. package/packages/storefront/config/storefront.tailwind.cjs +1 -0
  82. package/packages/storefront/dist/client/_astro/Carousel.63d511ab.js +1 -0
  83. package/packages/storefront/dist/client/_astro/{HeroSlider.8a040a33.js → HeroSlider.8d2ea532.js} +1 -1
  84. package/packages/storefront/dist/client/_astro/{PitchBar.ab0c501e.js → PitchBar.c2a2ad79.js} +1 -1
  85. package/packages/storefront/dist/client/_astro/Prices.8572765c.js +1 -0
  86. package/packages/storefront/dist/client/_astro/ProductShelf.4a105932.js +1 -0
  87. package/packages/storefront/dist/client/_astro/ShopHeader.7ecb7597.js +4 -0
  88. package/packages/storefront/dist/client/_astro/{_...slug_.c13e0486.css → _...slug_.07c1fa58.css} +1 -1
  89. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.48e557ba.js +1 -0
  90. package/packages/storefront/dist/client/_astro/client.9dbf6b61.js +1 -0
  91. package/packages/storefront/dist/client/_astro/{img.abbe849f.js → img.7def76a1.js} +1 -1
  92. package/packages/storefront/dist/client/_astro/index.c0c35ead.js +1 -0
  93. package/packages/storefront/dist/client/sw.js +1 -1
  94. package/packages/storefront/dist/server/chunks/{_...1b951f6c.mjs → _...d3f15170.mjs} +3 -3
  95. package/packages/storefront/dist/server/chunks/{account@_@astro.f6aec583.mjs → account@_@astro.38a725e7.mjs} +3 -3
  96. package/packages/storefront/dist/server/chunks/{astro.b875de26.mjs → astro.6adaff02.mjs} +296 -1146
  97. package/packages/storefront/dist/server/chunks/{endpoint@_@js.5834ad4e.mjs → endpoint@_@js.a92a4584.mjs} +3 -3
  98. package/packages/storefront/dist/server/chunks/{fallback@_@astro.069ddb54.mjs → fallback@_@astro.4e98328e.mjs} +3 -3
  99. package/packages/storefront/dist/server/chunks/{index@_@astro.37e61ebe.mjs → index@_@astro.2dda826c.mjs} +3 -3
  100. package/packages/storefront/dist/server/chunks/{index@_@astro.485287a1.mjs → index@_@astro.db07fb09.mjs} +3 -3
  101. package/packages/storefront/dist/server/chunks/pages/{_...slug_.astro.95bf4c3b.mjs → _...slug_.astro.88866aae.mjs} +812 -150
  102. package/packages/storefront/dist/server/chunks/pages/{account.astro.4b8c2471.mjs → account.astro.53400a42.mjs} +1 -1
  103. package/packages/storefront/dist/server/chunks/pages/{endpoint.js.bd1232b7.mjs → endpoint.js.a11da4ad.mjs} +1 -1
  104. package/packages/storefront/dist/server/chunks/pages/{fallback.astro.b52164bc.mjs → fallback.astro.c1fd06ab.mjs} +2 -2
  105. package/packages/storefront/dist/server/chunks/pages/{index.astro.98167846.mjs → index.astro.c45cc893.mjs} +18 -344
  106. package/packages/storefront/dist/server/entry.mjs +31 -23
  107. package/packages/storefront/dist/server/renderers.mjs +2 -2
  108. package/packages/storefront/package.json +10 -10
  109. package/packages/storefront/src/helpers/sf-utils.ts +12 -0
  110. package/packages/storefront/src/lib/components/Carousel.vue +17 -8
  111. package/packages/storefront/src/lib/components/CarouselControl.vue +1 -1
  112. package/packages/storefront/src/lib/components/CheckoutLink.vue +23 -0
  113. package/packages/storefront/src/lib/components/Drawer.vue +1 -1
  114. package/packages/storefront/src/lib/components/QuantitySelector.vue +107 -0
  115. package/packages/storefront/src/lib/components/QuantitySelectorControl.vue +35 -0
  116. package/packages/storefront/src/lib/components/SocialNetworkIcon.vue +1 -1
  117. package/packages/storefront/src/lib/components/SocialNetworkLink.vue +1 -3
  118. package/packages/storefront/src/lib/composables/use-cart-item.ts +52 -0
  119. package/packages/storefront/src/lib/composables/use-sticky-header.ts +14 -2
  120. package/packages/storefront/src/lib/sf-lib.ts +7 -0
  121. package/packages/storefront/src/lib/state/customer-session.ts +2 -2
  122. package/packages/storefront/src/lib/state/modules-info.ts +1 -1
  123. package/packages/storefront/src/lib/state/shopping-cart/parse-product.ts +23 -21
  124. package/packages/storefront/src/lib/state/shopping-cart.ts +13 -4
  125. package/packages/types/package.json +1 -1
  126. package/packages/storefront/dist/client/_astro/Carousel.8af656b5.js +0 -1
  127. package/packages/storefront/dist/client/_astro/ProductShelf.6351b57b.js +0 -1
  128. package/packages/storefront/dist/client/_astro/ShopHeader.cfab20c7.js +0 -4
  129. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.4cb7dd76.js +0 -1
  130. package/packages/storefront/dist/client/_astro/api.4984c5be.js +0 -1
  131. package/packages/storefront/dist/client/_astro/client.0fb6b44e.js +0 -1
  132. package/packages/storefront/dist/client/_astro/index.7eac5494.js +0 -1
  133. package/packages/storefront/src/helpers/idle-callback.ts +0 -9
  134. package/packages/storefront/src/lib/components/_injection-keys.ts +0 -11
  135. /package/packages/storefront/src/{lib → helpers}/browser-env.ts +0 -0
  136. /package/packages/storefront/src/{lib → helpers}/server-data.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/storefront",
3
3
  "type": "module",
4
- "version": "0.22.4",
4
+ "version": "0.23.1",
5
5
  "description": "E-Com Plus Cloud Commerce storefront with Astro",
6
6
  "bin": {
7
7
  "storefront": "./scripts/build-prod.sh"
@@ -29,8 +29,8 @@
29
29
  "prepare-monorepo": "bash scripts/prepare-monorepo.sh"
30
30
  },
31
31
  "dependencies": {
32
- "@astrojs/image": "0.17.2",
33
- "@astrojs/node": "5.3.0",
32
+ "@astrojs/image": "0.17.3",
33
+ "@astrojs/node": "5.3.2",
34
34
  "@astrojs/vue": "2.2.1",
35
35
  "@cloudcommerce/api": "workspace:*",
36
36
  "@cloudcommerce/config": "workspace:*",
@@ -38,12 +38,12 @@
38
38
  "@ecomplus/utils": "1.5.0-rc.5",
39
39
  "@fastify/deepmerge": "^1.3.0",
40
40
  "@headlessui/vue": "^1.7.15",
41
- "@iconify-json/fa6-brands": "^1.1.11",
42
- "@iconify-json/heroicons": "^1.1.11",
43
- "@iconify-json/logos": "^1.1.33",
41
+ "@iconify-json/fa6-brands": "^1.1.13",
42
+ "@iconify-json/heroicons": "^1.1.12",
43
+ "@iconify-json/logos": "^1.1.34",
44
44
  "@vite-pwa/astro": "^0.1.1",
45
45
  "@vueuse/core": "10.3.0",
46
- "astro": "2.9.6",
46
+ "astro": "2.10.2",
47
47
  "chroma-js": "^2.4.2",
48
48
  "dotenv": "^16.3.1",
49
49
  "firebase": "^10.1.0",
@@ -52,13 +52,13 @@
52
52
  "semver": "^7.5.4",
53
53
  "sharp": "^0.32.4",
54
54
  "tailwindcss": "^3.3.3",
55
- "unocss": "^0.54.1",
56
- "vite": "^4.4.7",
55
+ "unocss": "^0.54.2",
56
+ "vite": "^4.4.9",
57
57
  "vite-plugin-pwa": "^0.16.4",
58
58
  "vue": "^3.3.4"
59
59
  },
60
60
  "devDependencies": {
61
- "@cloudcommerce/eslint": "workspace:^",
61
+ "@cloudcommerce/eslint": "workspace:*",
62
62
  "@cloudcommerce/types": "workspace:*"
63
63
  }
64
64
  }
@@ -0,0 +1,12 @@
1
+ let id = -1;
2
+
3
+ /* eslint-disable-next-line no-plusplus */
4
+ export const useId = () => String(++id);
5
+
6
+ export const requestIdleCallback = (fn: (...args: any[]) => any, fallbackMs = 300) => {
7
+ if (typeof window.requestIdleCallback === 'function') {
8
+ window.requestIdleCallback(fn);
9
+ } else {
10
+ setTimeout(fn, fallbackMs);
11
+ }
12
+ };
@@ -1,6 +1,7 @@
1
- <script setup lang="ts">
2
- /* REFERENCE: https://github.com/bartdominiak/vue-snap */
1
+ <script lang="ts">
3
2
  import {
3
+ type Ref,
4
+ type InjectionKey,
4
5
  onMounted,
5
6
  onBeforeUnmount,
6
7
  ref,
@@ -11,9 +12,20 @@ import {
11
12
  provide,
12
13
  } from 'vue';
13
14
  import { useDebounceFn, useElementHover, useScroll } from '@vueuse/core';
14
- import { carouselKey } from '@@sf/components/_injection-keys';
15
15
  import CarouselControl from '@@sf/components/CarouselControl.vue';
16
16
 
17
+ export type CarouselInject = {
18
+ autoplay: Ref<number | undefined>,
19
+ changeSlide: (direction: number, isPageScroll?: boolean) => void,
20
+ isBoundLeft: Ref<boolean>,
21
+ isBoundRight: Ref<boolean>,
22
+ };
23
+
24
+ export const carouselKey = Symbol('carousel') as InjectionKey<CarouselInject>;
25
+ </script>
26
+
27
+ <script setup lang="ts">
28
+ /* REFERENCE: https://github.com/bartdominiak/vue-snap */
17
29
  export interface Props {
18
30
  as?: string;
19
31
  modelValue?: number;
@@ -27,10 +39,10 @@ const props = withDefaults(defineProps<Props>(), {
27
39
  const emit = defineEmits([
28
40
  'update:modelValue',
29
41
  ]);
30
- const currentIndex = ref(props.modelValue - 1);
42
+ const currentIndex = ref(0);
31
43
  watch(toRef(props, 'modelValue'), (modelValue) => {
32
44
  currentIndex.value = modelValue - 1;
33
- });
45
+ }, { immediate: true });
34
46
  watch(currentIndex, (current, previous) => {
35
47
  if (current !== previous) {
36
48
  emit('update:modelValue', current + 1);
@@ -119,9 +131,6 @@ const changeSlide = (direction: number, isPageScroll: boolean = true) => {
119
131
  direction = direction > 0 ? pageStep : -pageStep;
120
132
  }
121
133
  }
122
- if (!props.autoplay) {
123
- console.log({ direction }, currentIndex.value, slidesWidth.value.length);
124
- }
125
134
  const nextOffsetLeft = calcNextOffsetLeft(direction);
126
135
  wrapper.value?.scrollTo({ left: nextOffsetLeft, behavior: 'smooth' });
127
136
  restartAutoplay();
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { inject } from 'vue';
3
- import { type CarouselInject, carouselKey } from '@@sf/components/_injection-keys';
3
+ import { type CarouselInject, carouselKey } from '@@sf/components/Carousel.vue';
4
4
 
5
5
  export interface Props {
6
6
  isPrev?: boolean;
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue';
3
+
4
+ export interface Props {
5
+ to?: 'cart' | 'checkout';
6
+ cartUrl?: string;
7
+ checkoutUrl?: string;
8
+ }
9
+
10
+ const props = withDefaults(defineProps<Props>(), {
11
+ to: 'cart',
12
+ cartUrl: globalThis.$storefront.settings.cart_url || '/app/#/cart',
13
+ checkoutUrl: globalThis.$storefront.settings.checkout_url || '/app/#/checkout',
14
+ });
15
+ const href = computed(() => {
16
+ if (props.to === 'cart') return props.cartUrl;
17
+ return props.checkoutUrl;
18
+ });
19
+ </script>
20
+
21
+ <template>
22
+ <a :href="href"><slot /></a>
23
+ </template>
@@ -99,7 +99,7 @@ const isPlacementX = computed(() => {
99
99
  data-drawer-close
100
100
  >
101
101
  <slot name="close">
102
- <i class="i-close text-base-400 text-3xl"></i>
102
+ <i class="i-close text-base-400 hover:text-base-600 text-3xl"></i>
103
103
  </slot>
104
104
  </button>
105
105
  <slot />
@@ -0,0 +1,107 @@
1
+ <script lang="ts">
2
+ import {
3
+ type Ref,
4
+ type WritableComputedRef,
5
+ type InjectionKey,
6
+ ref,
7
+ computed,
8
+ provide,
9
+ } from 'vue';
10
+ import { useId } from '@@sf/sf-lib';
11
+ import QuantitySelectorControl from '@@sf/components/QuantitySelectorControl.vue';
12
+
13
+ export type QuantitySelectorInject = {
14
+ value: WritableComputedRef<number>,
15
+ isBoundMin: Ref<boolean>,
16
+ isBoundMax: Ref<boolean>,
17
+ };
18
+
19
+ export const quantitySelectorKey = Symbol('quantitySelector') as
20
+ InjectionKey<QuantitySelectorInject>;
21
+ </script>
22
+
23
+ <script setup lang="ts">
24
+ export interface Props {
25
+ modelValue?: number;
26
+ min?: number;
27
+ max?: number;
28
+ step?: number;
29
+ disabled?: boolean;
30
+ readonly?: boolean;
31
+ }
32
+
33
+ const props = withDefaults(defineProps<Props>(), {
34
+ modelValue: 1,
35
+ min: 1,
36
+ });
37
+ const emit = defineEmits<{
38
+ 'update:modelValue': [value: number]
39
+ }>();
40
+ const input = ref<HTMLInputElement | null>(null);
41
+ const inputId = `NInput${useId()}`;
42
+ const value = computed({
43
+ get() {
44
+ return props.modelValue;
45
+ },
46
+ set(_value) {
47
+ if (_value < props.min) {
48
+ _value = props.min;
49
+ (input.value as HTMLInputElement).value = `${_value}`;
50
+ }
51
+ if (props.max && _value > props.max) {
52
+ _value = props.max;
53
+ (input.value as HTMLInputElement).value = `${_value}`;
54
+ }
55
+ emit('update:modelValue', _value);
56
+ },
57
+ });
58
+ const isBoundMin = computed(() => {
59
+ return props.min >= value.value;
60
+ });
61
+ const isBoundMax = computed(() => {
62
+ return (props.max as number) <= value.value;
63
+ });
64
+ provide(quantitySelectorKey, {
65
+ value,
66
+ isBoundMin,
67
+ isBoundMax,
68
+ });
69
+ </script>
70
+
71
+ <template>
72
+ <div data-quantity-selector>
73
+ <slot name="label" v-bind="{ inputId, value }">
74
+ <label :for="inputId" class="sr-only">
75
+ {{ $t.i19quantity }}
76
+ </label>
77
+ </slot>
78
+ <div class="flex items-center">
79
+ <input
80
+ ref="input"
81
+ type="number"
82
+ :id="inputId"
83
+ v-model="value"
84
+ :min="min"
85
+ :max="max"
86
+ :step="step"
87
+ :disabled="disabled"
88
+ :readonly="readonly"
89
+ class="h-12 w-14 px-2 text-lg border-transparent text-center
90
+ [-moz-appearance:_textfield] [&::-webkit-outer-spin-button]:m-0
91
+ [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:m-0
92
+ [&::-webkit-inner-spin-button]:appearance-none"
93
+ />
94
+ <slot
95
+ name="controls"
96
+ v-bind="{ value, isBoundMin, isBoundMax }"
97
+ >
98
+ <QuantitySelectorControl is-minus class="order-first">
99
+ <slot name="minus" />
100
+ </QuantitySelectorControl>
101
+ <QuantitySelectorControl class="order-last">
102
+ <slot name="plus" />
103
+ </QuantitySelectorControl>
104
+ </slot>
105
+ </div>
106
+ </div>
107
+ </template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import { inject } from 'vue';
3
+ import {
4
+ type QuantitySelectorInject,
5
+ quantitySelectorKey,
6
+ } from '@@sf/components/QuantitySelector.vue';
7
+
8
+ export interface Props {
9
+ isMinus?: boolean;
10
+ }
11
+
12
+ defineProps<Props>();
13
+ const {
14
+ value,
15
+ isBoundMin,
16
+ isBoundMax,
17
+ } = inject(quantitySelectorKey) as QuantitySelectorInject;
18
+ </script>
19
+
20
+ <template>
21
+ <button
22
+ type="button"
23
+ class="w-10 h-12 text-xl leading-12 enabled:text-primary
24
+ enabled:hover:bg-primary-100/70 disabled:opacity-40"
25
+ :data-quantity-selector-control="isMinus ? 'minus' : 'plus'"
26
+ :aria-label="isMinus ? $t.i19minus : $t.i19plus"
27
+ :disabled="isMinus ? isBoundMin : isBoundMax"
28
+ @click.prevent="value += (isMinus ? -1 : 1)"
29
+ >
30
+ <slot>
31
+ <template v-if="isMinus">&minus;</template>
32
+ <template v-else>&plus;</template>
33
+ </slot>
34
+ </button>
35
+ </template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { NetworkName } from '@@sf/server-data';
2
+ import type { NetworkName } from '@@sf/sf-lib';
3
3
  import { computed } from 'vue';
4
4
 
5
5
  export interface Props {
@@ -1,8 +1,6 @@
1
1
  <script setup lang="ts">
2
- import type { NetworkName } from '@@sf/server-data';
2
+ import { type NetworkName, isMobile, socialNetworks } from '@@sf/sf-lib';
3
3
  import { computed } from 'vue';
4
- import { isMobile } from '@@sf/browser-env';
5
- import { socialNetworks } from '@@sf/server-data';
6
4
  import SocialNetworkIcon from '@@sf/components/SocialNetworkIcon.vue';
7
5
 
8
6
  export interface Props {
@@ -0,0 +1,52 @@
1
+ import type { Carts } from '@cloudcommerce/api/types';
2
+ import type { ProductItem } from '@@sf/composables/use-product-card';
3
+ import { computed } from 'vue';
4
+ import { name as getName, img as getImg } from '@ecomplus/utils';
5
+ import { parseProduct } from '@@sf/state/shopping-cart';
6
+
7
+ export type CartItem = Carts['items'][0];
8
+
9
+ export type Props = {
10
+ item?: CartItem;
11
+ product?: ProductItem;
12
+ pictureSize?: string;
13
+ } & ({ item: CartItem } | { product: ProductItem });
14
+
15
+ export const useCartItem = (props: Props) => {
16
+ const parsedItem = computed(() => {
17
+ return !props.item && props.product
18
+ ? parseProduct(props.product)
19
+ : null;
20
+ });
21
+ const cartItem = computed(() => {
22
+ return (props.item || parsedItem.value) as CartItem;
23
+ });
24
+ const title = computed(() => {
25
+ return getName(cartItem.value);
26
+ });
27
+ const link = computed(() => {
28
+ const { slug } = cartItem.value;
29
+ if (typeof slug === 'string') {
30
+ return `/${slug}`;
31
+ }
32
+ return null;
33
+ });
34
+ const image = computed(() => {
35
+ if (cartItem.value.picture) {
36
+ return getImg(cartItem.value.picture, undefined, props.pictureSize || 'small');
37
+ }
38
+ return undefined;
39
+ });
40
+ const finalPrice = computed(() => {
41
+ return cartItem.value.final_price || cartItem.value.price;
42
+ });
43
+ return {
44
+ cartItem,
45
+ title,
46
+ link,
47
+ image,
48
+ finalPrice,
49
+ };
50
+ };
51
+
52
+ export default useCartItem;
@@ -10,7 +10,9 @@ import {
10
10
  useTimeout,
11
11
  useDebounceFn,
12
12
  useScroll,
13
+ watchDebounced,
13
14
  } from '@vueuse/core';
15
+ import { isMobile } from '@@sf/sf-lib';
14
16
 
15
17
  export interface Props {
16
18
  header: Ref<HTMLElement | null>;
@@ -34,12 +36,20 @@ const useStickyHeader = (props: Props) => {
34
36
  const staticHeight = ref(0);
35
37
  const staticY = ref(0);
36
38
  let heightDiv: HTMLElement | undefined;
37
- const { y } = !import.meta.env.SSR ? useScroll(document) : { y: ref(0) };
39
+ const { y: _y } = !import.meta.env.SSR ? useScroll(document) : { y: ref(0) };
40
+ const y = ref(0);
41
+ watchDebounced(_y, (nextY) => {
42
+ y.value = nextY;
43
+ }, {
44
+ debounce: isMobile ? 150 : 50,
45
+ maxWait: 600,
46
+ });
38
47
  const isSticky = computed(() => ready.value && y.value > staticY.value * 1.2);
39
48
  const transition = ref('none');
40
49
  watch(isSticky, async (_isSticky) => {
41
50
  if (canSetStyles && header.value) {
42
- header.value.style.position = _isSticky ? 'sticky' : '';
51
+ header.value.style.position = _isSticky ? 'fixed' : '';
52
+ header.value.style.width = _isSticky ? '100vw' : '';
43
53
  }
44
54
  if (heightDiv) {
45
55
  heightDiv.style.height = _isSticky ? `${staticHeight.value}px` : '';
@@ -56,6 +66,7 @@ const useStickyHeader = (props: Props) => {
56
66
  watch(y, (newY, oldY) => {
57
67
  isScrollUp.value = newY > 0 && newY < oldY;
58
68
  });
69
+
59
70
  if (!import.meta.env.SSR) {
60
71
  onMounted(() => {
61
72
  if (!header.value) throw new Error('<header> (props.header) not set');
@@ -102,6 +113,7 @@ const useStickyHeader = (props: Props) => {
102
113
  }
103
114
  });
104
115
  }
116
+
105
117
  return {
106
118
  staticHeight,
107
119
  staticY,
@@ -0,0 +1,7 @@
1
+ export { i18n, formatMoney } from '@ecomplus/utils';
2
+
3
+ export * from '../helpers/browser-env';
4
+
5
+ export * from '../helpers/server-data';
6
+
7
+ export * from '../helpers/sf-utils';
@@ -3,8 +3,8 @@ import type { Auth } from 'firebase/auth';
3
3
  import api from '@cloudcommerce/api';
4
4
  import { nickname as getNickname } from '@ecomplus/utils';
5
5
  import { computed } from 'vue';
6
- import requestIdleCallback from '../../helpers/idle-callback';
7
- import useStorage from './use-storage';
6
+ import { requestIdleCallback } from '@@sf/sf-lib';
7
+ import useStorage from '@@sf/state/use-storage';
8
8
 
9
9
  const storageKey = 'ecomSession';
10
10
  const emptySession = {
@@ -7,8 +7,8 @@ import { reactive, computed } from 'vue';
7
7
  import { formatMoney } from '@ecomplus/utils';
8
8
  import loadingGlobalInfoPreset from '@@sf/scripts/modules-info-preset';
9
9
  import utm from '@@sf/scripts/session-utm';
10
+ import { requestIdleCallback } from '@@sf/sf-lib';
10
11
  import afetch from '../../helpers/afetch';
11
- import requestIdleCallback from '../../helpers/idle-callback';
12
12
 
13
13
  const emptyInfo = {
14
14
  list_payments: {},
@@ -11,29 +11,31 @@ export default (
11
11
  if (typeof quantity !== 'number' || Number.isNaN(quantity)) {
12
12
  quantity = product.min_quantity || 1;
13
13
  }
14
- const item: any = { ...product };
15
- if (variationId && product.variations) {
16
- Object.assign(item, product.variations.find(({ _id }) => _id === variationId));
17
- delete item.variations;
18
- }
19
- item.product_id = product._id;
20
- if (variationId) {
21
- item.variation_id = variationId;
22
- if (item.picture_id && product.pictures) {
23
- const pictures = product.pictures.filter((picture) => {
24
- return picture._id === item.picture_id;
25
- });
26
- if (pictures.length) {
27
- [item.picture] = pictures;
28
- }
29
- }
14
+ const minQuantity = product.min_quantity || 0;
15
+ const variation = variationId && product.variations
16
+ ? product.variations.find(({ _id }) => _id === variationId)
17
+ : undefined;
18
+ const item: CartItem = {
19
+ product_id: product._id,
20
+ variation_id: variationId,
21
+ sku: variation?.sku || product.sku,
22
+ name: variation?.name || product.name,
23
+ slug: product.slug,
24
+ production_time: variation?.production_time || product.production_time,
25
+ currency_id: product.currency_id,
26
+ currency_symbol: product.currency_symbol,
27
+ base_price: variation?.base_price || product.base_price,
28
+ max_quantity: product.quantity,
29
+ quantity: minQuantity > 0 ? Math.max(minQuantity, quantity) : quantity,
30
+ price: getPrice(product),
31
+ };
32
+ if (variation?.picture_id && product.pictures) {
33
+ item.picture = product.pictures.find((_picture) => {
34
+ return _picture._id === variation.picture_id;
35
+ });
30
36
  }
31
37
  if (!item.picture && product.pictures) {
32
38
  [item.picture] = product.pictures;
33
39
  }
34
- item.max_quantity = item.quantity || product.quantity;
35
- const minQuantity = item.min_quantity || product.min_quantity;
36
- item.quantity = minQuantity > 0 ? Math.max(minQuantity, quantity) : quantity;
37
- item.price = getPrice(item) || getPrice(product);
38
- return item as CartItem;
40
+ return item;
39
41
  };
@@ -1,8 +1,8 @@
1
1
  import type { Products, CartSet, SearchItem } from '@cloudcommerce/api/types';
2
2
  import { computed } from 'vue';
3
- import useStorage from './use-storage';
4
- import addItem from './shopping-cart/add-cart-item';
5
- import parseProduct from './shopping-cart/parse-product';
3
+ import useStorage from '@@sf/state/use-storage';
4
+ import addItem from '@@sf/state/shopping-cart/add-cart-item';
5
+ import parseProduct from '@@sf/state/shopping-cart/parse-product';
6
6
 
7
7
  const storageKey = 'ecomShoppingCart';
8
8
  const emptyCart = {
@@ -72,7 +72,15 @@ const addCartItem = (newItem: CartSet['items'][0]) => {
72
72
  shoppingCart.value.items = cartObj.items;
73
73
  }
74
74
  };
75
-
75
+ const removeCartItem = (itemId: string) => {
76
+ for (let i = 0; i < shoppingCart.value.items.length; i++) {
77
+ const item = shoppingCart.value.items[i];
78
+ if (item._id === itemId) {
79
+ shoppingCart.value.items.splice(i, 1);
80
+ break;
81
+ }
82
+ }
83
+ };
76
84
  const addProductToCart = (
77
85
  product: (Partial<Products> | Partial<SearchItem>) & { _id: Products['_id'] },
78
86
  variationId?: Products['_id'],
@@ -85,6 +93,7 @@ export {
85
93
  totalItems,
86
94
  shoppingCart,
87
95
  addCartItem,
96
+ removeCartItem,
88
97
  parseProduct,
89
98
  addProductToCart,
90
99
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/types",
3
3
  "type": "module",
4
- "version": "0.22.4",
4
+ "version": "0.23.1",
5
5
  "description": "E-Com Plus Cloud Commerce reusable type definitions",
6
6
  "main": "index.ts",
7
7
  "repository": {
@@ -1 +0,0 @@
1
- import{a as q,h as G,c as J}from"./index.7eac5494.js";import{_ as M,d as K,B as X,o as B,a as Q,u as v,b as Y,n as H,j as c,k as h,t as $,c as D,l as Z,E as ee,Q as te,C as ae,g as oe,w as P,h as le,e as F,H as se,I as re}from"./_plugin-vue_export-helper.4cb7dd76.js";const U=Symbol("carousel"),ne=K({__name:"CarouselControl",props:{isPrev:{type:Boolean,default:!1}},setup(r,{expose:u}){u();const{changeSlide:l}=X(U),t={changeSlide:l};return Object.defineProperty(t,"__isScriptSetup",{enumerable:!1,value:!0}),t}}),ue=["aria-label","data-carousel-control"];function ie(r,u,l,t,n,o){return B(),Q("button",{type:"button","aria-label":l.isPrev?"Anterior":"Próximo",onClick:u[0]||(u[0]=m=>t.changeSlide(l.isPrev?-1:1)),class:H(["group absolute top-0 z-1",l.isPrev?"left-0":"right-0"]),"data-carousel-control":l.isPrev?"previous":"next"},[v(r.$slots,"default",{},()=>[Y("i",{class:H(["m-0",l.isPrev?"i-chevron-left group-active:-translate-x-1":"i-chevron-right group-active:translate-x-1"])},null,2)])],10,ue)}const ce=M(ne,[["render",ie]]),de=K({__name:"Carousel",props:{as:{default:"ul"},modelValue:{default:1},autoplay:{}},emits:["update:modelValue"],setup(r,{expose:u,emit:l}){u();const t=r,n=c(t.modelValue-1);h($(t,"modelValue"),e=>{n.value=e-1}),h(n,(e,a)=>{e!==a&&l("update:modelValue",e+1)});const o=c(null),{x:m,isScrolling:L,arrivedState:_}=q(o),T=D(()=>_.left),W=D(()=>_.right),s=c([]),g=c(0),p=c(0),I=c(0),k=()=>{o.value&&(g.value=o.value.scrollWidth,p.value=o.value.offsetWidth)},V=()=>{if(!o.value)return;let e=[...o.value.children];e.length===1&&e[0].tagName.endsWith("SLOT")&&(e=[...e[0].children]),s.value=e.map(a=>({offsetLeft:a.offsetLeft,width:a.offsetWidth}))},z=e=>{let a=n.value+e;if(a>=s.value.length)return 0;a<0&&(a=s.value.length+a);const{offsetLeft:b,width:d}=s.value[a]||{};return d?b:0},x=()=>{const e=s.value.findIndex(a=>Math.abs(a.offsetLeft-m.value)<=5);e>-1&&(n.value=e||0)},E=()=>{const e=g.value-p.value;I.value=s.value.findIndex(({offsetLeft:a})=>a>=e-5)};let i;const f=()=>{t.autoplay&&(clearTimeout(i),i=setTimeout(()=>{C(1)},t.autoplay))},C=(e,a=!0)=>{if(s.value.length<2)return;if(a&&(e===1||e===-1)){let d=0,j=0;for(let S=n.value;S<s.value.length;S++){const{width:A}=s.value[S]||{};if(A&&(d+=1,j+=A,j>=p.value))break}d&&(e=e>0?d:-d)}t.autoplay||console.log({direction:e},n.value,s.value.length);const b=z(e);o.value?.scrollTo({left:b,behavior:"smooth"}),f()};h(L,e=>{e?clearTimeout(i):(x(),f())});const O=c(null),R=G(O);h(R,e=>{e?clearTimeout(i):f()});const w=()=>{o.value&&(k(),V(),x(),E())},y=J(()=>{o.value&&(o.value.scrollLeft=0,w())},400);Z(()=>{w(),ee(()=>{o.value&&[...o.value.children].forEach(e=>{e.setAttribute("tabindex","0")})}),f(),window.addEventListener("resize",y)}),te(()=>{window.removeEventListener("resize",y),clearTimeout(i)}),ae(U,{autoplay:$(t,"autoplay"),changeSlide:C,isBoundLeft:T,isBoundRight:W});const N={props:t,emit:l,currentIndex:n,wrapper:o,currentPos:m,isScrolling:L,arrivedState:_,isBoundLeft:T,isBoundRight:W,slidesWidth:s,wrapperScrollWidth:g,wrapperVisibleWidth:p,indexCount:I,calcWrapperWidth:k,calcSlidesWidth:V,calcNextOffsetLeft:z,calcCurrentIndex:x,calcIndexCount:E,get autoplayTimer(){return i},set autoplayTimer(e){i=e},restartAutoplay:f,changeSlide:C,carousel:O,isHovered:R,calcOnInit:w,onResize:y,CarouselControl:ce};return Object.defineProperty(N,"__isScriptSetup",{enumerable:!1,value:!0}),N}}),fe={ref:"carousel",class:"relative","data-carousel":""};function ve(r,u,l,t,n,o){return B(),Q("div",fe,[(B(),oe(le(l.as),{ref:"wrapper",class:"flex overflow-x-scroll overflow-y-hidden list-none m-0 p-0 snap-x snap-mandatory scroll-smooth [&>*]:snap-start [&>*]:outline-none",style:{"scrollbar-width":"none","-webkit-overflow-scrolling":"touch","-ms-overflow-style":"none"},"data-carousel-wrapper":""},{default:P(()=>[v(r.$slots,"default")]),_:3},512)),v(r.$slots,"controls",se(re({changeSlide:t.changeSlide,isBoundLeft:t.isBoundLeft,isBoundRight:t.isBoundRight,currentPage:t.currentIndex+1,pageCount:t.indexCount+1})),()=>[F(t.CarouselControl,{"is-prev":""},{default:P(()=>[v(r.$slots,"previous")]),_:3}),F(t.CarouselControl,null,{default:P(()=>[v(r.$slots,"next")]),_:3})])],512)}const me=M(de,[["render",ve]]);export{me as C,ce as a};
@@ -1 +0,0 @@
1
- import{L as R,j as O,M as q,N as A,c as d,O as F,_ as N,d as E,m as M,o as i,a as c,x as h,i as f,b as g,y as S,n as B,e as x,w as I,g as j,F as Q,h as T,q as G,f as J,v as K,r as U}from"./_plugin-vue_export-helper.4cb7dd76.js";import{a as D,b as X}from"./api.4984c5be.js";import{C as Y,a as Z}from"./Carousel.8af656b5.js";import{d as $,e as ee,g as te,l as ne,h as ae,w as re}from"./index.7eac5494.js";import{i as se,g as oe}from"./img.abbe849f.js";import"./session-utm.744b0db3.js";const ie=(t,n=R.get("lang"))=>n&&t.i18n&&t.i18n[n]?t.i18n[n]:t.name||t.title||se(t.i18n,n)||"",le=ie,ce=t=>t&&t.min_quantity||1,ue=ce,de=t=>!t.hasOwnProperty("quantity")||t.quantity>=ue(t),W=de,me=t=>{const n=O(t.title||""),r=O(t.titleLink||""),e=O(!1);let m=null;const s=O(null),u=q(t.products||[]);return t.products||(e.value=!0,m=(async()=>{let _=t.searchQuery||"",b;if(t.collectionId){try{const{data:a}=await D.get(`collections/${t.collectionId}`);b=a}catch(a){console.error(a),s.value=a}const l=b?.products;Array.isArray(l)&&l.length&&(_+=`&_id=${l.slice(0,60).join(",")}`),!n.value&&n.value!==null&&b?.name&&(n.value=b?.name)}const v=t.limit||24;let p=`offset=${t.page?(t.page-1)*v:0}&limit=${v}`;t.sort&&(p+=`&sort=${t.sort}`),p+=_;try{const{data:l}=await D.get(`search/v1?${p}`);if(t.isShuffle){let a=l.result.filter(P=>P.available&&W(P)).length,k,C;for(;a;)C=Math.floor(Math.random()*a--),k=l.result[a],l.result[a]=l.result[C],l.result[C]=k}l.result.forEach(a=>u.push(a))}catch(l){console.error(l),s.value=l}e.value=!1})()),{title:n,titleLink:r,isFetching:e,fetching:m,fetchError:s,products:u}},he=t=>{const n=O(!1);let r=null;const e=O(null),{productId:m}=t,s=q({...t.product,_id:t.product?._id||m,price:A(t.product||{})});!t.product&&m&&(n.value=!0,r=(async()=>{try{const{data:a}=await D.get(`products/${m}`);Object.assign(s,a)}catch(a){console.error(a),e.value=a}n.value=!1})());const u=d(()=>le(s)),_=d(()=>{const{slug:a}=s;return typeof a=="string"?`/${a}`:null}),b=d(()=>{const{pictures:a}=s,k=[];return a&&a.forEach(C=>{const P=oe(C);P&&k.push(P)}),k}),v=d(()=>W(s)),w=d(()=>v.value&&s.available&&s.visible),p=d(()=>{if(F(s)){const a=s.base_price;return Math.round((a-A(s))*100/a)}return 0}),l=d(()=>s.has_variations?!0:!!s.variations?.length);return{isFetching:n,fetching:r,fetchError:e,product:s,title:u,link:_,images:b,isInStock:v,isActive:w,discountPercentage:p,hasVariations:l}},z=(t,n)=>{const{type:r,value:e}=n;let m;return e?(r==="percentage"?m=t*((100-e)/100):m=t-e,m>0?m:0):t},_e=t=>{const n=d(()=>t.product||{price:t.price||0,base_price:t.basePrice}),r=d(()=>{const{variations:o}=n.value;if(o){const y=A(n.value);for(let L=0;L<o.length;L++)if(A({...n.value,...o[L]})>y)return!0}return!1}),e=d(()=>{const o=A(n.value),y=$.value;return y&&(!y.min_amount||o>y.min_amount)?z(o,y):o}),m=d(()=>{if(F(n.value))return n.value.base_price;const o=A(n.value);return o>e.value?o:0}),s=d(()=>t.installmentsOption||ee.value||{max_number:1}),u=d(()=>{if(s.value.max_number<=1)return 1;const o=s.value.min_installment||5,y=Math.floor(e.value/o);return Math.min(y,s.value.max_number)}),_=d(()=>s.value.monthly_interest||0),b=d(()=>{if(u.value>=2){if(!_.value)return e.value/u.value;const o=_.value/100;return e.value*o/(1-(1+o)**-u.value)}return 0}),v=d(()=>{const o=t.discountOption||te.value;return o&&(!o.min_amount||o.min_amount<=e.value)&&(!t.isAmountTotal||o.apply_at==="total")?o:{}}),w=d(()=>{const{label:o}=v.value;return o?o.includes(" ")?o:`via ${o}`:""}),p=d(()=>z(e.value,v.value)),l=d(()=>{if(t.loyaltyPointsProgram)return t.loyaltyPointsProgram;const o=ne.value;if(o){const y=Object.keys(o);for(let L=0;L<y.length;L++){const V=o[y[L]];if(V?.earn_percentage&&V.earn_percentage>0)return V}}return{ratio:0}}),a=d(()=>l.value.min_subtotal_to_earn||0),k=d(()=>l.value.name||""),C=d(()=>l.value.earn_percentage||0),P=d(()=>C.value*l.value.ratio),H=d(()=>P.value>=1?e.value*(P.value/100):0);return{hasVariedPrices:r,salePrice:e,comparePrice:m,installmentsObject:s,installmentsNumber:u,monthlyInterest:_,installmentValue:b,discountObject:v,discountLabel:w,priceWithDiscount:p,pointsProgramObject:l,pointsMinPrice:a,pointsProgramName:k,earnPointsPercentage:C,cashbackPercentage:P,cashbackValue:H}},fe=E({__name:"Prices",props:{isBig:{type:Boolean},isLiteral:{type:Boolean},hasCashback:{type:Boolean,default:!0},hasPriceOptions:{type:Boolean,default:!0},product:{},price:{},basePrice:{},isAmountTotal:{type:Boolean},installmentsOption:{},discountOption:{},loyaltyPointsProgram:{}},setup(t,{expose:n}){n();const r=t,{hasVariedPrices:e,salePrice:m,comparePrice:s,cashbackPercentage:u,cashbackValue:_,installmentsNumber:b,monthlyInterest:v,installmentValue:w,priceWithDiscount:p,discountLabel:l}=_e(r),a={props:r,hasVariedPrices:e,salePrice:m,comparePrice:s,cashbackPercentage:u,cashbackValue:_,installmentsNumber:b,monthlyInterest:v,installmentValue:w,priceWithDiscount:p,discountLabel:l};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}}),ge={key:0,class:"text-base-500 mr-1 [font-size:87%]"},ve={key:0},be={key:1},pe={key:0},ye={key:0,class:"relative z-10"},ke=["data-tooltip"],Pe=g("i",{class:"i-arrow-uturn-left mr-1"},null,-1),xe={class:"font-medium"},we=g("small",null," cashback",-1),Ce={key:0},Oe={key:0},Ie={key:1},Le={key:2},Se={key:0},Ae={key:0},Ve={key:1};function je(t,n,r,e,m,s){const u=M("Fade");return i(),c("div",{class:B(["text-base-600 [&>div]:[font-size:90%] [&_small]:lowercase [&_small]:[font-size:92%]",r.isBig?"text-lg":null]),"data-prices":""},[e.comparePrice?(i(),c("span",ge,[r.isLiteral?(i(),c("small",ve,h("De "))):f("",!0),g("s",null,h(t.$money(e.comparePrice)),1),r.isLiteral?(i(),c("small",be,h(" Por"))):f("",!0)])):f("",!0),g("strong",{class:B(["inline-block text-base-800",r.isBig?"text-5xl block":null])},[e.hasVariedPrices?(i(),c("small",pe,h("A partir de "))):f("",!0),S(" "+h(t.$money(e.salePrice)),1)],2),x(u,{slide:"down"},{default:I(()=>[e.cashbackValue&&r.hasCashback?(i(),c("div",ye,[g("span",{"data-tooltip":"Receba $1 de volta".replace("$1",t.$percentage(e.cashbackPercentage))},[Pe,g("span",xe,h(t.$money(e.cashbackValue)),1),we],8,ke)])):f("",!0)]),_:1}),x(u,{slide:"down"},{default:I(()=>[e.installmentValue&&r.hasPriceOptions?(i(),c("div",Ce,[r.isLiteral?(i(),c("small",Oe,h("Até "))):f("",!0),S(" "+h(e.installmentsNumber)+"x ",1),r.isLiteral?(i(),c("small",Ie,h(" De "))):f("",!0),g("span",null,h(t.$money(e.installmentValue)),1),!e.monthlyInterest&&r.isLiteral?(i(),c("small",Le,h("Sem juros"))):f("",!0)])):f("",!0)]),_:1}),x(u,{slide:"down"},{default:I(()=>[e.priceWithDiscount<e.salePrice&&r.hasPriceOptions?(i(),c("div",Se,[e.discountLabel?f("",!0):(i(),c("small",Ae,h("A partir de "))),g("span",null,h(t.$money(e.priceWithDiscount)),1),e.discountLabel?(i(),c("small",Ve,h(` ${e.discountLabel}`),1)):f("",!0)])):f("",!0)]),_:1})],2)}const Be=N(fe,[["render",je]]),De=E({__name:"ProductCard",props:{product:{},productId:{},headingTag:{default:"h3"}},setup(t,{expose:n}){n();const r=t,{product:e,title:m,link:s,images:u,isInStock:_,isActive:b,discountPercentage:v,hasVariations:w}=he({product:r.product,productId:r.productId}),p=O(null),l=ae(p),a=O(!1);re(l,()=>{a.value=!0});const k={props:r,product:e,title:m,link:s,images:u,isInStock:_,isActive:b,discountPercentage:v,hasVariations:w,card:p,isHovered:l,wasHoveredOnce:a,get addProductToCart(){return X},Prices:Be};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}}),Ne=["data-sku"],Ee={class:"aspect-square p-2 motion-safe:group-hover:scale-110 transition-transform"},Me={class:"relative w-full h-full bg-white rounded overflow-hidden group-hover:rounded-none"},Te={key:1,class:"w-full h-full bg-gradient-to-br from-base-50/20 to-base-100"},ze={key:0,class:"uno-bm03rg"},qe={class:"relative flex flex-col grow justify-between p-4 group-hover:backdrop-blur-md bg-white/40 z-10"},Fe={class:"pt-2"},Qe={key:0},We={key:1,class:"ui-badge bg-warning-100 text-warning-700"},He=g("i",{class:"i-plus-20-solid mr-0.5"},null,-1);function Re(t,n,r,e,m,s){const u=M("AImg");return i(),c("article",{ref:"card","data-sku":e.product.sku,class:"relative h-full max-w-[350px] mx-auto py-3 group"},[(i(),j(T(e.link?"ALink":"span"),{href:e.link,class:"flex flex-col h-full rounded overflow-hidden group-hover:shadow group-hover:ring-1 ring-black/5"},{default:I(()=>[g("div",Ee,[g("div",Me,[e.images?.length?(i(),c(Q,{key:0},[x(u,{picture:e.images[0],alt:e.title,class:"absolute top-0 left-0 block w-full h-full object-cover"},null,8,["picture","alt"]),e.images[1]&&e.wasHoveredOnce?(i(),j(u,{key:0,picture:e.images[1],alt:e.title,class:"absolute top-0 left-0 block w-full h-full object-cover opacity-0 group-hover:opacity-100 transition-opacity motion-safe:duration-300 text-transparent z-10"},null,8,["picture","alt"])):f("",!0)],64)):(i(),c("div",Te))])]),e.discountPercentage?(i(),c("span",ze,[S(" -"),g("strong",null,h(e.discountPercentage),1),S("% ")])):f("",!0),g("div",qe,[(i(),j(T(r.headingTag),{class:B(["ui-link no-underline line-clamp-2",[e.isActive?"text-base-700":"text-base-500",e.link?"group-hover:underline group-hover:text-primary":null]])},{default:I(()=>[S(h(e.title),1)]),_:1},8,["class"])),g("div",Fe,[e.isActive?(i(),c("div",Qe,[x(e.Prices,{product:e.product},null,8,["product"])])):(i(),c("span",We,h(e.isInStock?"Inativo":"Sem estoque"),1))]),e.isActive&&!e.hasVariations?(i(),c("button",{key:0,class:"uno-3suct9 ui-btn-sm ui-btn-primary",onClick:n[0]||(n[0]=G(_=>e.addProductToCart(e.product),["prevent"]))},[He,S(" "+h("Adicionar ao carrinho"))])):f("",!0)])]),_:1},8,["href"]))],8,Ne)}const Ge=N(De,[["render",Re]]),Je=E({__name:"ProductShelf",props:{collectionId:{},searchQuery:{},sort:{},title:{},titleLink:{},isShuffle:{type:Boolean},limit:{},page:{},products:{}},async setup(t,{expose:n}){n();const r=t,{title:e,titleLink:m,fetching:s,products:u}=me(r),_={props:r,title:e,titleLink:m,fetching:s,products:u,Carousel:Y,CarouselControl:Z,ProductCard:Ge};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),Ke={class:"ui-section"},Ue={key:0,class:"max-w-prose mx-auto text-center mb-2"},Xe={class:"ui-text-brand text-3xl"},Ye={key:1,class:"text-base-700"},Ze={class:"text-3xl lg:text-2xl leading-none text-primary lg:opacity-0 group-hover/shelf:opacity-90 transition-opacity"};function $e(t,n,r,e,m,s){const u=M("ALink");return i(),c("section",Ke,[e.title?(i(),c("div",Ue,[g("h2",Xe,[e.titleLink?(i(),j(u,{key:0,href:e.titleLink,class:"ui-link"},{default:I(()=>[S(h(e.title),1)]),_:1},8,["href"])):(i(),c("span",Ye,h(e.title),1))])])):f("",!0),x(e.Carousel,{class:"group/shelf"},{controls:I(()=>[J(g("div",Ze,[x(e.CarouselControl,{class:"!top-1/2 !-left-4 w-12 h-12 bg-transparent lg:bg-white/80 lg:hover:bg-primary-300/60 rounded-full lg:shadow-sm lg:ring-1 ring-black/5","is-prev":""}),x(e.CarouselControl,{class:"!top-1/2 !-right-4 w-12 h-12 bg-transparent lg:bg-white/80 lg:hover:bg-primary-300/60 rounded-full lg:shadow-sm lg:ring-1 ring-black/5"})],512),[[K,e.products.length>2]])]),default:I(()=>[(i(!0),c(Q,null,U(e.products,_=>(i(),c("li",{key:_._id,class:"basis-1/2 md:basis-1/3 lg:basis-1/4 shrink-0"},[x(e.ProductCard,{product:_},null,8,["product"])]))),128))]),_:1})])}const ot=N(Je,[["render",$e]]);export{ot as default};