cloudcommerce 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/ecomplus-stores/monocard/functions/ssr/package.json +0 -2
- package/ecomplus-stores/tia-sonia/functions/ssr/package.json +0 -2
- package/package.json +6 -6
- package/packages/api/package.json +1 -1
- package/packages/apps/correios/package.json +2 -2
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +2 -2
- package/packages/apps/discounts/package.json +1 -1
- package/packages/apps/emails/package.json +1 -1
- package/packages/apps/fb-conversions/package.json +1 -1
- package/packages/apps/frenet/package.json +2 -2
- package/packages/apps/galaxpay/package.json +2 -2
- package/packages/apps/google-analytics/package.json +2 -2
- package/packages/apps/infinitepay/package.json +2 -2
- package/packages/apps/jadlog/package.json +2 -2
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/melhor-envio/CHANGELOG.md +1 -0
- package/packages/apps/melhor-envio/README.md +1 -0
- package/packages/apps/melhor-envio/events.js +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.d.ts +18 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.js +115 -0
- package/packages/apps/melhor-envio/lib/functions-lib/database.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.d.ts +7 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.js +112 -0
- package/packages/apps/melhor-envio/lib/functions-lib/events-to-melhor-envio.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.d.ts +42 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.js +185 -0
- package/packages/apps/melhor-envio/lib/functions-lib/new-label.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.d.ts +5 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.js +40 -0
- package/packages/apps/melhor-envio/lib/functions-lib/order-is-valid.js.map +1 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.d.ts +2 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.js +164 -0
- package/packages/apps/melhor-envio/lib/functions-lib/tracking-codes.js.map +1 -0
- package/packages/apps/melhor-envio/lib/index.d.ts +1 -0
- package/packages/apps/melhor-envio/lib/index.js +2 -0
- package/packages/apps/melhor-envio/lib/index.js.map +1 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.d.ts +6 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.js +17 -0
- package/packages/apps/melhor-envio/lib/melhor-envio-events.js.map +1 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.d.ts +2 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.js +6 -0
- package/packages/apps/melhor-envio/lib/melhor-envio.js.map +1 -0
- package/packages/apps/melhor-envio/lib-mjs/calculate-melhor-envio.mjs +341 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/client-melhor-envio.mjs +14 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/error-handling.mjs +62 -0
- package/packages/apps/melhor-envio/lib-mjs/functions/new-shipment.mjs +119 -0
- package/packages/apps/melhor-envio/package.json +36 -0
- package/packages/apps/melhor-envio/src/functions-lib/database.ts +140 -0
- package/packages/apps/melhor-envio/src/functions-lib/events-to-melhor-envio.ts +137 -0
- package/packages/apps/melhor-envio/src/functions-lib/new-label.ts +214 -0
- package/packages/apps/melhor-envio/src/functions-lib/order-is-valid.ts +51 -0
- package/packages/apps/melhor-envio/src/functions-lib/tracking-codes.ts +191 -0
- package/packages/apps/melhor-envio/src/index.ts +1 -0
- package/packages/apps/melhor-envio/src/melhor-envio-events.ts +24 -0
- package/packages/apps/melhor-envio/src/melhor-envio.ts +7 -0
- package/packages/apps/melhor-envio/tsconfig.json +6 -0
- package/packages/apps/mercadopago/package.json +2 -2
- package/packages/apps/pagarme/package.json +2 -2
- package/packages/apps/paghiper/package.json +3 -3
- package/packages/apps/pix/package.json +2 -2
- package/packages/apps/tiny-erp/package.json +2 -2
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +3 -3
- package/packages/events/lib/firebase.js +2 -0
- package/packages/events/lib/firebase.js.map +1 -1
- package/packages/events/package.json +2 -1
- package/packages/events/src/firebase.ts +2 -0
- package/packages/firebase/lib/config.d.ts +4 -0
- package/packages/firebase/lib/config.js +7 -0
- package/packages/firebase/lib/config.js.map +1 -1
- package/packages/firebase/package.json +2 -2
- package/packages/firebase/src/config.ts +8 -0
- package/packages/i18n/lib/en_us/i19buyTogether.txt +1 -0
- package/packages/i18n/lib/en_us/i19buyTogetherWith.txt +1 -0
- package/packages/i18n/lib/en_us/i19report.txt +1 -0
- package/packages/i18n/lib/en_us/i19toggleMenu.txt +1 -0
- package/packages/i18n/lib/en_us/i19uponRequest.txt +1 -0
- package/packages/i18n/lib/en_us/i19usedPoints.txt +1 -0
- package/packages/i18n/lib/en_us.d.ts +6 -0
- package/packages/i18n/lib/en_us.js +6 -0
- package/packages/i18n/lib/en_us.js.map +1 -1
- package/packages/i18n/lib/pt_br/i19buyTogether.txt +1 -0
- package/packages/i18n/lib/pt_br/i19buyTogetherWith.txt +1 -0
- package/packages/i18n/lib/pt_br/i19report.txt +1 -0
- package/packages/i18n/lib/pt_br/i19toggleMenu.txt +1 -0
- package/packages/i18n/lib/pt_br/i19uponRequest.txt +1 -0
- package/packages/i18n/lib/pt_br/i19usedPoints.txt +1 -0
- package/packages/i18n/lib/pt_br.d.ts +6 -0
- package/packages/i18n/lib/pt_br.js +6 -0
- package/packages/i18n/lib/pt_br.js.map +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/i18n/src/en_us.ts +6 -0
- package/packages/i18n/src/pt_br.ts +6 -0
- package/packages/modules/lib/firebase/call-app-module.js +5 -0
- package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
- package/packages/modules/package.json +3 -2
- package/packages/modules/src/firebase/call-app-module.ts +5 -0
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +3 -4
- package/packages/storefront/.eslintrc.cjs +1 -1
- package/packages/storefront/astro.config.mjs +8 -1
- package/packages/storefront/dist/client/_astro/PitchBar.209c6645.js +1 -0
- package/packages/storefront/dist/client/_astro/Prices.6fbcb5ac.js +1 -0
- package/packages/storefront/dist/client/_astro/Prices.vue_vue_type_script_setup_true_lang.44f23680.js +1 -0
- package/packages/storefront/dist/client/_astro/ProductCard.ee5eee91.js +1 -0
- package/packages/storefront/dist/client/_astro/ShopHeader.b801c785.js +1 -0
- package/packages/storefront/dist/client/_astro/_...slug_.32968ccf.css +1 -0
- package/packages/storefront/dist/client/_astro/client.5a46cc02.js +1 -0
- package/packages/storefront/dist/client/_astro/index.844a4059.js +1 -0
- package/packages/storefront/dist/client/_astro/{modules-info.dde776b4.js → modules-info.d9373e21.js} +1 -1
- package/packages/storefront/dist/client/_astro/runtime-core.esm-bundler.f04cee62.js +1 -0
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.00313542.js +1 -0
- package/packages/storefront/dist/client/_astro/server.60de185d.css +1 -0
- package/packages/storefront/dist/client/_astro/use-component-variant.58788b6e.js +1 -0
- package/packages/storefront/dist/client/fallback/index.html +13 -7
- package/packages/storefront/dist/client/sw.js +1 -1
- package/packages/storefront/dist/server/chunks/pages/{all.c27193d6.mjs → all.23de4e5c.mjs} +444 -186
- package/packages/storefront/dist/server/chunks/{prerender.89f63027.mjs → prerender.f40361a3.mjs} +0 -0
- package/packages/storefront/dist/server/entry.mjs +39 -4452
- package/packages/storefront/package.json +4 -5
- package/packages/storefront/src/lib/assets/base.css +16 -11
- package/packages/storefront/src/lib/components/Carousel.vue +52 -82
- package/packages/storefront/src/lib/components/Drawer.vue +103 -0
- package/packages/storefront/src/lib/components/PitchBar.vue +16 -11
- package/packages/storefront/src/lib/components/Prices.vue +5 -5
- package/packages/storefront/src/lib/components/ShopHeader.vue +82 -0
- package/packages/storefront/src/lib/components/StickyHeader.vue +71 -43
- package/packages/storefront/src/lib/components/globals/Fade.vue +10 -14
- package/packages/storefront/src/lib/composables/use-component-variant.ts +6 -2
- package/packages/storefront/src/lib/composables/use-prices.ts +4 -2
- package/packages/storefront/src/lib/layouts/BaseBody.astro +1 -0
- package/packages/storefront/src/lib/layouts/PagesHeader.astro +28 -13
- package/packages/storefront/tailwind.config.cjs +4 -0
- package/packages/storefront/uno.config.cjs +1 -1
- package/packages/types/package.json +1 -1
- package/packages/storefront/dist/client/_astro/PitchBar.f3579a5b.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.8e5cead5.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.vue_vue_type_script_setup_true_lang.b8cbeb54.js +0 -1
- package/packages/storefront/dist/client/_astro/ProductCard.6d8b6d86.js +0 -1
- package/packages/storefront/dist/client/_astro/StickyHeader.7b0f3963.js +0 -1
- package/packages/storefront/dist/client/_astro/_...slug_.97285eba.css +0 -1
- package/packages/storefront/dist/client/_astro/client.3e777d4c.js +0 -1
- package/packages/storefront/dist/client/_astro/runtime-core.esm-bundler.7cf33881.js +0 -1
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.1a4c7407.js +0 -1
- package/packages/storefront/dist/client/_astro/server.4d9646d8.css +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcommerce/storefront",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "E-Com Plus Cloud Commerce storefront with Astro",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"repository": {
|
|
@@ -35,22 +35,21 @@
|
|
|
35
35
|
"@cloudcommerce/i18n": "workspace:*",
|
|
36
36
|
"@ecomplus/utils": "1.5.0-rc.3",
|
|
37
37
|
"@fastify/deepmerge": "^1.3.0",
|
|
38
|
-
"@headlessui/vue": "^1.7.
|
|
38
|
+
"@headlessui/vue": "^1.7.8",
|
|
39
39
|
"@iconify-json/fa6-brands": "^1.1.8",
|
|
40
40
|
"@iconify-json/heroicons": "^1.1.8",
|
|
41
41
|
"@iconify-json/logos": "^1.1.22",
|
|
42
42
|
"@vite-pwa/astro": "^0.0.1",
|
|
43
|
-
"@vueuse/core": "^9.
|
|
43
|
+
"@vueuse/core": "^9.12.0",
|
|
44
44
|
"astro": "^2.0.2",
|
|
45
45
|
"chroma-js": "^2.4.2",
|
|
46
46
|
"dotenv": "^16.0.3",
|
|
47
47
|
"firebase": "^9.16.0",
|
|
48
48
|
"image-size": "^1.0.2",
|
|
49
|
-
"lodash": "^4.17.21",
|
|
50
49
|
"semver": "^7.3.8",
|
|
51
50
|
"sharp": "^0.31.3",
|
|
52
51
|
"tailwindcss": "^3.2.4",
|
|
53
|
-
"unocss": "^0.
|
|
52
|
+
"unocss": "^0.49.1",
|
|
54
53
|
"vite": "^4.0.4",
|
|
55
54
|
"vite-plugin-pwa": "^0.14.1",
|
|
56
55
|
"vue": "^3.2.45"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--content-max-width: 80rem;
|
|
3
2
|
--font-size: 14.5px;
|
|
4
3
|
--font-sans: var(--custom-font-sans, ui-sans-serif),
|
|
5
4
|
system-ui, -apple-system, BlinkMacSystemFont,
|
|
@@ -8,6 +7,7 @@
|
|
|
8
7
|
--font-mono: var(--custom-font-mono, ui-monospace),
|
|
9
8
|
SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
10
9
|
--font-family: var(--font-sans);
|
|
10
|
+
--transition-fast: 75ms linear;
|
|
11
11
|
--transition: .15s ease-in-out;
|
|
12
12
|
--transition-slow: .25s ease-in-out;
|
|
13
13
|
--transition-slower: .45s ease-in-out;
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
@media (prefers-reduced-motion: reduce) {
|
|
30
30
|
:root {
|
|
31
|
+
--transition-fast: 0s;
|
|
31
32
|
--transition: 0s;
|
|
32
33
|
--transition-slow: 0s;
|
|
33
34
|
--transition-slower: .15s linear;
|
|
@@ -63,16 +64,6 @@ html {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
body > header,
|
|
67
|
-
body > main,
|
|
68
|
-
body > footer {
|
|
69
|
-
margin-left: auto;
|
|
70
|
-
margin-right: auto;
|
|
71
|
-
}
|
|
72
|
-
body > main {
|
|
73
|
-
max-width: var(--content-max-width);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
67
|
:focus-visible {
|
|
77
68
|
outline-color: var(--c-outline, rgba(var(--rgb-secondary), .1));
|
|
78
69
|
}
|
|
@@ -95,3 +86,17 @@ body {
|
|
|
95
86
|
background: var(--c-background);
|
|
96
87
|
color: var(--c-on-background);
|
|
97
88
|
}
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
Custom elements for responsive tricks in /content JSON.
|
|
92
|
+
Avoids the need of escape \" for class names with common elements.
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
d-md {
|
|
96
|
+
display: none;
|
|
97
|
+
}
|
|
98
|
+
@screen md {
|
|
99
|
+
d-md {
|
|
100
|
+
display: inline;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
onMounted,
|
|
5
5
|
onBeforeUnmount,
|
|
6
6
|
ref,
|
|
7
|
+
computed,
|
|
7
8
|
watch,
|
|
8
9
|
toRef,
|
|
9
10
|
nextTick,
|
|
10
11
|
provide,
|
|
11
12
|
} from 'vue';
|
|
12
|
-
import
|
|
13
|
-
import { useElementHover } from '@vueuse/core';
|
|
13
|
+
import { useDebounceFn, useElementHover, useScroll } from '@vueuse/core';
|
|
14
14
|
import { carouselKey } from './_injection-keys';
|
|
15
15
|
import CarouselControl from './CarouselControl.vue';
|
|
16
16
|
|
|
@@ -20,58 +20,30 @@ export interface Props {
|
|
|
20
20
|
autoplay?: number; // milliseconds
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const approximatelyEqual = (v1, v2, epsilon) => {
|
|
24
|
-
return Math.abs(v1 - v2) <= epsilon;
|
|
25
|
-
};
|
|
26
|
-
const SCROLL_DEBOUNCE = 100;
|
|
27
|
-
const RESIZE_DEBOUNCE = 410;
|
|
28
|
-
|
|
29
23
|
const props = withDefaults(defineProps<Props>(), {
|
|
30
24
|
as: 'ul',
|
|
31
25
|
modelValue: 1,
|
|
32
26
|
});
|
|
33
27
|
const emit = defineEmits([
|
|
34
28
|
'update:modelValue',
|
|
35
|
-
'bound-left',
|
|
36
|
-
'bound-right',
|
|
37
29
|
]);
|
|
38
|
-
|
|
39
|
-
const currentPage = ref(props.modelValue - 1);
|
|
30
|
+
const currentIndex = ref(props.modelValue - 1);
|
|
40
31
|
watch(toRef(props, 'modelValue'), (modelValue) => {
|
|
41
|
-
|
|
32
|
+
currentIndex.value = modelValue - 1;
|
|
42
33
|
});
|
|
43
|
-
watch(
|
|
34
|
+
watch(currentIndex, (current, previous) => {
|
|
44
35
|
if (current !== previous) {
|
|
45
36
|
emit('update:modelValue', current + 1);
|
|
46
37
|
}
|
|
47
38
|
});
|
|
48
39
|
const wrapper = ref<HTMLElement>(null);
|
|
49
|
-
const
|
|
50
|
-
const
|
|
40
|
+
const { x: currentPos, isScrolling, arrivedState } = useScroll(wrapper);
|
|
41
|
+
const isBoundLeft = computed(() => arrivedState.left);
|
|
42
|
+
const isBoundRight = computed(() => arrivedState.right);
|
|
51
43
|
const slidesWidth = ref([]);
|
|
52
44
|
const wrapperScrollWidth = ref(0);
|
|
53
45
|
const wrapperVisibleWidth = ref(0);
|
|
54
|
-
const
|
|
55
|
-
const maxPages = ref(0);
|
|
56
|
-
const onResizeFn = ref(null);
|
|
57
|
-
const onScrollFn = ref(null);
|
|
58
|
-
const calcBounds = () => {
|
|
59
|
-
// Find the closest point, with 5px approximate.
|
|
60
|
-
const _isBoundLeft = approximatelyEqual(currentPos.value, 0, 5);
|
|
61
|
-
const _isBoundRight = approximatelyEqual(
|
|
62
|
-
wrapperScrollWidth.value - wrapperVisibleWidth.value,
|
|
63
|
-
currentPos.value,
|
|
64
|
-
5,
|
|
65
|
-
);
|
|
66
|
-
if (_isBoundLeft) {
|
|
67
|
-
emit('bound-left', true);
|
|
68
|
-
}
|
|
69
|
-
isBoundLeft.value = _isBoundLeft;
|
|
70
|
-
if (_isBoundRight) {
|
|
71
|
-
emit('bound-right', true);
|
|
72
|
-
}
|
|
73
|
-
isBoundRight.value = _isBoundRight;
|
|
74
|
-
};
|
|
46
|
+
const indexCount = ref(0);
|
|
75
47
|
const calcWrapperWidth = () => {
|
|
76
48
|
wrapperScrollWidth.value = wrapper.value.scrollWidth;
|
|
77
49
|
wrapperVisibleWidth.value = wrapper.value.offsetWidth;
|
|
@@ -84,48 +56,27 @@ const calcSlidesWidth = () => {
|
|
|
84
56
|
}));
|
|
85
57
|
};
|
|
86
58
|
const calcNextWidth = (direction) => {
|
|
87
|
-
const nextSlideIndex = direction > 0
|
|
88
|
-
|
|
59
|
+
const nextSlideIndex = direction > 0
|
|
60
|
+
? currentIndex.value : currentIndex.value + direction;
|
|
61
|
+
const width = slidesWidth.value[nextSlideIndex]?.width || 0;
|
|
89
62
|
if (!width) {
|
|
90
63
|
return 0;
|
|
91
64
|
}
|
|
92
65
|
return width * direction;
|
|
93
66
|
};
|
|
94
|
-
const
|
|
95
|
-
const
|
|
67
|
+
const calcCurrentIndex = () => {
|
|
68
|
+
const getCurrentIndex = slidesWidth.value.findIndex((slide: HTMLElement) => {
|
|
96
69
|
// Find the closest point, with 5px approximate.
|
|
97
|
-
return
|
|
70
|
+
return Math.abs(slide.offsetLeft - currentPos.value) <= 5;
|
|
98
71
|
});
|
|
99
|
-
if (
|
|
100
|
-
|
|
72
|
+
if (getCurrentIndex > -1) {
|
|
73
|
+
currentIndex.value = getCurrentIndex || 0;
|
|
101
74
|
}
|
|
102
75
|
};
|
|
103
|
-
const
|
|
104
|
-
currentPos.value = wrapper.value.scrollLeft || 0;
|
|
105
|
-
};
|
|
106
|
-
const calcMaxPages = () => {
|
|
76
|
+
const calcIndexCount = () => {
|
|
107
77
|
const maxPos = wrapperScrollWidth.value - wrapperVisibleWidth.value;
|
|
108
|
-
|
|
109
|
-
.findIndex(({ offsetLeft }) => (offsetLeft >= maxPos));
|
|
110
|
-
};
|
|
111
|
-
const calcOnInit = () => {
|
|
112
|
-
if (!wrapper.value) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
calcWrapperWidth();
|
|
116
|
-
calcSlidesWidth();
|
|
117
|
-
calcCurrentPosition();
|
|
118
|
-
calcCurrentPage();
|
|
119
|
-
calcBounds();
|
|
120
|
-
calcMaxPages();
|
|
121
|
-
};
|
|
122
|
-
const calcOnScroll = () => {
|
|
123
|
-
if (!wrapper.value) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
calcCurrentPosition();
|
|
127
|
-
calcCurrentPage();
|
|
128
|
-
calcBounds();
|
|
78
|
+
indexCount.value = slidesWidth.value
|
|
79
|
+
.findIndex(({ offsetLeft }) => (offsetLeft >= maxPos - 5));
|
|
129
80
|
};
|
|
130
81
|
let autoplayTimer = null;
|
|
131
82
|
const restartAutoplay = () => {
|
|
@@ -140,13 +91,13 @@ const restartAutoplay = () => {
|
|
|
140
91
|
const changeSlide = (direction: number) => {
|
|
141
92
|
if (direction < 0) {
|
|
142
93
|
if (isBoundLeft.value) {
|
|
143
|
-
|
|
144
|
-
|
|
94
|
+
calcIndexCount();
|
|
95
|
+
currentIndex.value = indexCount.value - 1;
|
|
145
96
|
changeSlide(1);
|
|
146
97
|
return;
|
|
147
98
|
}
|
|
148
99
|
} else if (isBoundRight.value) {
|
|
149
|
-
|
|
100
|
+
currentIndex.value = 1;
|
|
150
101
|
changeSlide(-1);
|
|
151
102
|
return;
|
|
152
103
|
}
|
|
@@ -156,37 +107,50 @@ const changeSlide = (direction: number) => {
|
|
|
156
107
|
restartAutoplay();
|
|
157
108
|
}
|
|
158
109
|
};
|
|
110
|
+
watch(isScrolling, (_isScrolling: boolean) => {
|
|
111
|
+
if (_isScrolling) {
|
|
112
|
+
clearTimeout(autoplayTimer);
|
|
113
|
+
} else {
|
|
114
|
+
calcCurrentIndex();
|
|
115
|
+
restartAutoplay();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
159
118
|
const carousel = ref(null);
|
|
160
119
|
const isHovered = useElementHover(carousel);
|
|
161
|
-
watch(isHovered, (_isHovered) => {
|
|
120
|
+
watch(isHovered, (_isHovered: boolean) => {
|
|
162
121
|
if (_isHovered) {
|
|
163
122
|
clearTimeout(autoplayTimer);
|
|
164
123
|
} else {
|
|
165
124
|
restartAutoplay();
|
|
166
125
|
}
|
|
167
126
|
});
|
|
127
|
+
const calcOnInit = () => {
|
|
128
|
+
if (!wrapper.value) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
calcWrapperWidth();
|
|
132
|
+
calcSlidesWidth();
|
|
133
|
+
calcCurrentIndex();
|
|
134
|
+
calcIndexCount();
|
|
135
|
+
};
|
|
136
|
+
const onResize = useDebounceFn(calcOnInit, 400);
|
|
168
137
|
onMounted(() => {
|
|
169
138
|
calcOnInit();
|
|
170
139
|
if (!import.meta.env.SSR) {
|
|
171
|
-
// Assign to new variable and keep reference for removeEventListener (Avoid Memory Leaks)
|
|
172
|
-
onScrollFn.value = debounce(calcOnScroll, SCROLL_DEBOUNCE);
|
|
173
|
-
onResizeFn.value = debounce(calcOnInit, RESIZE_DEBOUNCE);
|
|
174
|
-
wrapper.value.addEventListener('scroll', onScrollFn.value);
|
|
175
|
-
window.addEventListener('resize', onResizeFn.value);
|
|
176
140
|
nextTick(() => {
|
|
177
141
|
[...wrapper.value.children].forEach((slide: HTMLElement) => {
|
|
178
142
|
slide.setAttribute('tabindex', '0');
|
|
179
143
|
});
|
|
180
144
|
});
|
|
181
145
|
restartAutoplay();
|
|
146
|
+
window.addEventListener('resize', onResize);
|
|
182
147
|
}
|
|
183
148
|
});
|
|
184
149
|
onBeforeUnmount(() => {
|
|
185
150
|
if (!import.meta.env.SSR) {
|
|
186
|
-
|
|
187
|
-
window.removeEventListener('resize', onResizeFn.value);
|
|
188
|
-
clearTimeout(autoplayTimer);
|
|
151
|
+
window.removeEventListener('resize', onResize);
|
|
189
152
|
}
|
|
153
|
+
clearTimeout(autoplayTimer);
|
|
190
154
|
});
|
|
191
155
|
provide(carouselKey, {
|
|
192
156
|
autoplay: toRef(props, 'autoplay'),
|
|
@@ -204,7 +168,13 @@ provide(carouselKey, {
|
|
|
204
168
|
<!-- @slot Slot for Arrows -->
|
|
205
169
|
<slot
|
|
206
170
|
name="controls"
|
|
207
|
-
v-bind="{
|
|
171
|
+
v-bind="{
|
|
172
|
+
changeSlide,
|
|
173
|
+
isBoundLeft,
|
|
174
|
+
isBoundRight,
|
|
175
|
+
currentPage: currentIndex + 1,
|
|
176
|
+
pageCount: indexCount + 1,
|
|
177
|
+
}"
|
|
208
178
|
>
|
|
209
179
|
<CarouselControl :direction="-1">
|
|
210
180
|
<slot name="previous" />
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
toRef,
|
|
4
|
+
ref,
|
|
5
|
+
computed,
|
|
6
|
+
watch,
|
|
7
|
+
} from 'vue';
|
|
8
|
+
import useComponentVariant from '@@sf/composables/use-component-variant';
|
|
9
|
+
|
|
10
|
+
export interface Props {
|
|
11
|
+
modelValue?: boolean;
|
|
12
|
+
placement?: 'start' | 'end' | 'top' | 'bottom';
|
|
13
|
+
isTeleported?: boolean;
|
|
14
|
+
hasCloseButton?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
+
modelValue: false,
|
|
19
|
+
placement: 'start',
|
|
20
|
+
isTeleported: false,
|
|
21
|
+
hasCloseButton: true,
|
|
22
|
+
});
|
|
23
|
+
const emit = defineEmits([
|
|
24
|
+
'update:modelValue',
|
|
25
|
+
]);
|
|
26
|
+
const close = () => emit('update:modelValue', false);
|
|
27
|
+
const anchor = ref(null);
|
|
28
|
+
const canvas = ref(null);
|
|
29
|
+
const outsideClickListener = (ev: MouseEvent) => {
|
|
30
|
+
if (!canvas.value?.contains(ev.target)) {
|
|
31
|
+
close();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const escClickListener = (ev: KeyboardEvent) => {
|
|
35
|
+
if (ev.key === 'Escape') {
|
|
36
|
+
close();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
watch(toRef(props, 'modelValue'), async (isOpen) => {
|
|
40
|
+
const header = anchor.value.closest('[class*="backdrop-"]');
|
|
41
|
+
if (isOpen) {
|
|
42
|
+
document.body.style.overflow = 'hidden';
|
|
43
|
+
if (header) {
|
|
44
|
+
header.style.backdropFilter = 'none';
|
|
45
|
+
}
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
document.addEventListener('click', outsideClickListener, { passive: true });
|
|
48
|
+
document.addEventListener('keydown', escClickListener, { passive: true });
|
|
49
|
+
}, 500);
|
|
50
|
+
} else {
|
|
51
|
+
document.body.style.overflow = null;
|
|
52
|
+
if (header) {
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
header.style.backdropFilter = null;
|
|
55
|
+
}, 500);
|
|
56
|
+
}
|
|
57
|
+
document.removeEventListener('click', outsideClickListener);
|
|
58
|
+
document.removeEventListener('keydown', escClickListener);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const slideTo = computed(() => {
|
|
62
|
+
switch (props.placement) {
|
|
63
|
+
case 'start': return 'left';
|
|
64
|
+
case 'end': return 'right';
|
|
65
|
+
case 'top': return 'up';
|
|
66
|
+
default: return 'down';
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const componentVariant = useComponentVariant(props, ['placement']);
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<div ref="anchor" class="relative">
|
|
74
|
+
<Teleport to="#teleported" :disabled="!isTeleported">
|
|
75
|
+
<Fade :slide="slideTo" speed="slow" is-floating>
|
|
76
|
+
<dialog
|
|
77
|
+
v-if="modelValue"
|
|
78
|
+
class="w-screen max-w-sm p-0 z-50"
|
|
79
|
+
:class="isTeleported ? 'fixed top-0 left-0' : 'absolute'"
|
|
80
|
+
:open="modelValue"
|
|
81
|
+
:data-drawer="componentVariant"
|
|
82
|
+
>
|
|
83
|
+
<div ref="canvas" class="relative">
|
|
84
|
+
<button
|
|
85
|
+
v-if="hasCloseButton"
|
|
86
|
+
type="button"
|
|
87
|
+
:aria-label="$t.i19close"
|
|
88
|
+
@click.prevent="close"
|
|
89
|
+
class="absolute top-2"
|
|
90
|
+
:class="placement === 'end' ? 'left-2' : 'right-2'"
|
|
91
|
+
data-drawer-close
|
|
92
|
+
>
|
|
93
|
+
<slot name="close">
|
|
94
|
+
<i class="i-close text-base-400 text-3xl"></i>
|
|
95
|
+
</slot>
|
|
96
|
+
</button>
|
|
97
|
+
<slot />
|
|
98
|
+
</div>
|
|
99
|
+
</dialog>
|
|
100
|
+
</Fade>
|
|
101
|
+
</Teleport>
|
|
102
|
+
</div>
|
|
103
|
+
</template>
|
|
@@ -24,7 +24,7 @@ const countValidSlides = computed(() => {
|
|
|
24
24
|
</script>
|
|
25
25
|
|
|
26
26
|
<template>
|
|
27
|
-
<div
|
|
27
|
+
<div class="bg-base-100" data-pitch-bar>
|
|
28
28
|
<div class="container md:w-2/3 mx-auto px-3 py-1">
|
|
29
29
|
<Carousel :autoplay="countValidSlides > 1 ? 7000 : null">
|
|
30
30
|
<li v-for="(slide, i) in slides" :key="i">
|
|
@@ -32,6 +32,7 @@ const countValidSlides = computed(() => {
|
|
|
32
32
|
:is="slide.href ? 'ALink' : 'span'"
|
|
33
33
|
:href="slide.href"
|
|
34
34
|
:target="slide.target"
|
|
35
|
+
class="inline-block px-8"
|
|
35
36
|
:class="slide.href ? 'hover:underline' : null"
|
|
36
37
|
>
|
|
37
38
|
<slot name="slide" v-bind="{ slide, i, parsedContents }">
|
|
@@ -39,21 +40,25 @@ const countValidSlides = computed(() => {
|
|
|
39
40
|
v-if="parsedContents[i]"
|
|
40
41
|
v-html="parsedContents[i]"
|
|
41
42
|
class="prose text-sm text-base-800"
|
|
43
|
+
data-pitch-bar-slide
|
|
42
44
|
></span>
|
|
43
45
|
</slot>
|
|
44
46
|
</component>
|
|
45
47
|
</li>
|
|
46
48
|
<template #controls>
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
<slot name="controls" v-bind="{ countValidSlides }">
|
|
50
|
+
<div
|
|
51
|
+
v-show="countValidSlides > 1"
|
|
52
|
+
class="text-xl leading-none text-base-400"
|
|
53
|
+
data-pitch-bar-controls
|
|
54
|
+
>
|
|
55
|
+
<CarouselControl
|
|
56
|
+
:direction="-1"
|
|
57
|
+
class="pr-2 bg-base-100 hover:text-base-700"
|
|
58
|
+
/>
|
|
59
|
+
<CarouselControl class="pl-2 bg-base-100 hover:text-base-700" />
|
|
60
|
+
</div>
|
|
61
|
+
</slot>
|
|
57
62
|
</template>
|
|
58
63
|
</Carousel>
|
|
59
64
|
</div>
|
|
@@ -7,7 +7,7 @@ export interface Props {
|
|
|
7
7
|
product?: Partial<Products> & { price: number, final_price?: number };
|
|
8
8
|
price?: number;
|
|
9
9
|
basePrice?: number;
|
|
10
|
-
isAmountTotal?: boolean
|
|
10
|
+
isAmountTotal?: boolean;
|
|
11
11
|
installmentsOption?: ListPaymentsResponse['installments_option'];
|
|
12
12
|
discountOption?: ListPaymentsResponse['discount_option'];
|
|
13
13
|
isBig?: boolean;
|
|
@@ -37,9 +37,9 @@ const componentVariant = useComponentVariant(props);
|
|
|
37
37
|
</script>
|
|
38
38
|
|
|
39
39
|
<template>
|
|
40
|
-
<div
|
|
40
|
+
<div class="text-base-600" :data-prices="componentVariant">
|
|
41
41
|
<slot v-if="comparePrice" name="compare" v-bind="{ salePrice, comparePrice }">
|
|
42
|
-
<span
|
|
42
|
+
<span class="text-base-500 mr-1" data-prices-compare>
|
|
43
43
|
<slot name="compare-pre">
|
|
44
44
|
<small v-if="isLiteral">
|
|
45
45
|
{{ `${$t.i19from} ` }}
|
|
@@ -56,7 +56,7 @@ const componentVariant = useComponentVariant(props);
|
|
|
56
56
|
</span>
|
|
57
57
|
</slot>
|
|
58
58
|
<slot name="sale" v-bind="{ salePrice }">
|
|
59
|
-
<strong
|
|
59
|
+
<strong class="inline-block text-base-800" data-prices-sale>
|
|
60
60
|
<slot name="sale-pre">
|
|
61
61
|
<small v-if="hasVariedPrices">
|
|
62
62
|
{{ `${$t.i19asOf} ` }}
|
|
@@ -74,7 +74,7 @@ const componentVariant = useComponentVariant(props);
|
|
|
74
74
|
name="cashback"
|
|
75
75
|
v-bind="{ salePrice, cashbackValue, cashbackPercentage }"
|
|
76
76
|
>
|
|
77
|
-
<div v-if="hasCashback"
|
|
77
|
+
<div v-if="hasCashback" class="relative z-10" data-prices-cashback>
|
|
78
78
|
<span :data-tooltip="$t.i19get$1back
|
|
79
79
|
.replace('$1', $percentage(cashbackPercentage))">
|
|
80
80
|
<slot name="cashback-pre">
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
import { i19myAccount, i19openCart, i19searchProducts } from '@@i18n';
|
|
4
|
+
import Drawer from '@@sf/components/Drawer.vue';
|
|
5
|
+
import StickyHeader from '@@sf/components/StickyHeader.vue';
|
|
6
|
+
|
|
7
|
+
const buttons = ref({
|
|
8
|
+
search: {
|
|
9
|
+
icon: 'i-search',
|
|
10
|
+
onClick: () => {},
|
|
11
|
+
label: i19searchProducts,
|
|
12
|
+
},
|
|
13
|
+
account: {
|
|
14
|
+
icon: 'i-account',
|
|
15
|
+
onClick: () => {},
|
|
16
|
+
label: i19myAccount,
|
|
17
|
+
},
|
|
18
|
+
cart: {
|
|
19
|
+
icon: 'i-shopping-cart',
|
|
20
|
+
onClick: () => {},
|
|
21
|
+
label: i19openCart,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
const isSidenavOpen = ref(false);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<StickyHeader>
|
|
29
|
+
<div
|
|
30
|
+
class="container lg:max-w-7xl mx-auto px-1 lg:pl-3
|
|
31
|
+
grid grid-flow-col grid-cols-3 justify-between items-center
|
|
32
|
+
md:grid-cols-none md:auto-cols-max"
|
|
33
|
+
data-header
|
|
34
|
+
>
|
|
35
|
+
<slot name="sidenav-toggle">
|
|
36
|
+
<div class="md:hidden" data-sidenav-toggle>
|
|
37
|
+
<button
|
|
38
|
+
class="px-2 my-1"
|
|
39
|
+
:aria-label="$t.i19toggleMenu"
|
|
40
|
+
@click="isSidenavOpen = !isSidenavOpen"
|
|
41
|
+
>
|
|
42
|
+
<slot name="sidenav-toggle-content">
|
|
43
|
+
<i class="i-menu text-base-500 text-3xl"></i>
|
|
44
|
+
</slot>
|
|
45
|
+
</button>
|
|
46
|
+
<Drawer v-model="isSidenavOpen" class="-ml-1 lg:-ml-3">
|
|
47
|
+
MENU
|
|
48
|
+
</Drawer>
|
|
49
|
+
</div>
|
|
50
|
+
</slot>
|
|
51
|
+
<slot name="logo" />
|
|
52
|
+
<slot name="nav" />
|
|
53
|
+
<slot name="buttons">
|
|
54
|
+
<div
|
|
55
|
+
class="px-2 flex justify-end items-center gap-3 lg:gap-4 text-base-800"
|
|
56
|
+
data-header-buttons
|
|
57
|
+
>
|
|
58
|
+
<slot
|
|
59
|
+
name="button"
|
|
60
|
+
v-for="({ icon, onClick, label }, name) in buttons"
|
|
61
|
+
:key="name"
|
|
62
|
+
v-bind="{ name, icon, onClick }"
|
|
63
|
+
>
|
|
64
|
+
<button
|
|
65
|
+
:class="name === 'account' ? 'hidden sm:block' : null"
|
|
66
|
+
:aria-label="label"
|
|
67
|
+
@click="onClick"
|
|
68
|
+
:data-header-button="name"
|
|
69
|
+
>
|
|
70
|
+
<slot name="button-content" v-bind="{ name, icon }">
|
|
71
|
+
<i
|
|
72
|
+
:class="icon"
|
|
73
|
+
class="hover:text-primary w-7 h-7 hover:scale-110 active:scale-125"
|
|
74
|
+
></i>
|
|
75
|
+
</slot>
|
|
76
|
+
</button>
|
|
77
|
+
</slot>
|
|
78
|
+
</div>
|
|
79
|
+
</slot>
|
|
80
|
+
</div>
|
|
81
|
+
</StickyHeader>
|
|
82
|
+
</template>
|