@lightspeed/crane 1.4.2 → 2.0.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.
- package/CHANGELOG.md +51 -0
- package/UPGRADE.md +19 -0
- package/dist/app.d.mts +1 -1028
- package/dist/app.d.ts +1 -1028
- package/dist/app.mjs +1 -1
- package/dist/cli.mjs +20 -7
- package/package.json +4 -3
- package/template/footers/example-footer/ExampleFooter.vue +1 -1
- package/template/footers/example-footer/client.ts +2 -1
- package/template/footers/example-footer/component/LegalLinks.vue +1 -1
- package/template/footers/example-footer/component/MadeWith.vue +1 -1
- package/template/footers/example-footer/component/ReportAbuse.vue +1 -1
- package/template/footers/example-footer/entity/color.ts +2 -2
- package/template/footers/example-footer/server.ts +2 -1
- package/template/headers/example-header/client.ts +2 -1
- package/template/headers/example-header/component/Account.vue +1 -1
- package/template/headers/example-header/component/Cart.vue +1 -1
- package/template/headers/example-header/component/CategoriesDropdown.vue +1 -1
- package/template/headers/example-header/component/Logo.vue +1 -1
- package/template/headers/example-header/component/NavigationMenu.vue +1 -1
- package/template/headers/example-header/component/SearchForm.vue +1 -1
- package/template/headers/example-header/server.ts +2 -1
- package/template/index.d.ts +1 -1
- package/template/layouts/catalog/example-catalog/Main.vue +1 -1
- package/template/layouts/catalog/example-catalog/slots/custom-bottom-bar/client.ts +2 -1
- package/template/layouts/catalog/example-catalog/slots/custom-bottom-bar/server.ts +2 -1
- package/template/layouts/category/example-category/Main.vue +1 -1
- package/template/layouts/category/example-category/settings/content.ts +1 -1
- package/template/layouts/category/example-category/settings/design.ts +1 -1
- package/template/layouts/product/example-product/Main.vue +1 -1
- package/template/layouts/product/example-product/settings/content.ts +1 -1
- package/template/layouts/product/example-product/settings/design.ts +1 -1
- package/template/package.json +6 -3
- package/template/page-templates/example-template/pages/catalog.ts +1 -1
- package/template/page-templates/example-template/pages/category.ts +1 -1
- package/template/page-templates/example-template/pages/product.ts +1 -1
- package/template/preview/sections/preview.html +1 -1
- package/template/preview/shared/api-routes.ts +515 -41
- package/template/preview/shared/mock.ts +43 -41
- package/template/preview/shared/preview.ts +220 -123
- package/template/preview/shared/utils.ts +209 -62
- package/template/preview/ssr-server.ts +430 -0
- package/template/preview/vite.config.js +76 -75
- package/template/reference/sections/about-us/AboutUs.vue +1 -1
- package/template/reference/sections/about-us/client.ts +1 -1
- package/template/reference/sections/about-us/component/Image.vue +1 -1
- package/template/reference/sections/about-us/component/Stats.vue +2 -2
- package/template/reference/sections/about-us/component/Title.vue +1 -1
- package/template/reference/sections/about-us/server.ts +1 -1
- package/template/reference/sections/about-us/util/visibility-provider.ts +1 -1
- package/template/reference/sections/featured-products/FeaturedProducts.vue +65 -0
- package/template/reference/sections/featured-products/assets/arrow.svg +3 -0
- package/template/reference/sections/featured-products/assets/custom_section_showcase_1_preview.png +0 -0
- package/template/reference/sections/featured-products/client.ts +6 -0
- package/template/reference/sections/featured-products/component/ProductItem.vue +71 -0
- package/template/reference/sections/featured-products/component/Title.vue +31 -0
- package/template/reference/sections/featured-products/entity/color.ts +4 -0
- package/template/reference/sections/featured-products/server.ts +6 -0
- package/template/reference/sections/featured-products/settings/content.ts +14 -0
- package/template/reference/sections/featured-products/settings/design.ts +33 -0
- package/template/reference/sections/featured-products/settings/translations.ts +24 -0
- package/template/reference/sections/featured-products/showcases/1.ts +28 -0
- package/template/reference/sections/featured-products/showcases/translations.ts +16 -0
- package/template/reference/sections/featured-products/type.ts +5 -0
- package/template/reference/sections/intro-slider/IntroSlider.vue +1 -1
- package/template/reference/sections/intro-slider/client.ts +2 -1
- package/template/reference/sections/intro-slider/component/Slider.vue +8 -2
- package/template/reference/sections/intro-slider/component/Title.vue +1 -1
- package/template/reference/sections/intro-slider/entity/color.ts +2 -2
- package/template/reference/sections/intro-slider/server.ts +2 -1
- package/template/reference/sections/tag-lines/TagLines.vue +1 -1
- package/template/reference/sections/tag-lines/client.ts +2 -1
- package/template/reference/sections/tag-lines/component/SectionImage.vue +1 -1
- package/template/reference/sections/tag-lines/component/Title.vue +1 -1
- package/template/reference/sections/tag-lines/composables/highlighted-text-image-list.ts +4 -3
- package/template/reference/sections/tag-lines/server.ts +2 -1
- package/template/reference/sections/trending-categories/TrendingCategories.vue +70 -0
- package/template/reference/sections/trending-categories/assets/arrow.svg +3 -0
- package/template/reference/sections/trending-categories/assets/custom_section_showcase_1_preview.png +0 -0
- package/template/reference/sections/trending-categories/client.ts +6 -0
- package/template/reference/sections/trending-categories/component/CategoryItem.vue +62 -0
- package/template/reference/sections/trending-categories/component/Title.vue +32 -0
- package/template/reference/sections/trending-categories/entity/color.ts +4 -0
- package/template/reference/sections/trending-categories/server.ts +6 -0
- package/template/reference/sections/trending-categories/settings/content.ts +14 -0
- package/template/reference/sections/trending-categories/settings/design.ts +33 -0
- package/template/reference/sections/trending-categories/settings/translations.ts +24 -0
- package/template/reference/sections/trending-categories/showcases/1.ts +36 -0
- package/template/reference/sections/trending-categories/showcases/translations.ts +22 -0
- package/template/reference/sections/trending-categories/type.ts +5 -0
- package/template/reference/shared/components/Button.vue +1 -1
- package/template/reference/shared/utils/styles.ts +1 -0
- package/template/reference/templates/reference-template-apparel/pages/catalog.ts +1 -1
- package/template/reference/templates/reference-template-apparel/pages/category.ts +1 -1
- package/template/reference/templates/reference-template-apparel/pages/home.ts +10 -0
- package/template/reference/templates/reference-template-apparel/pages/product.ts +1 -1
- package/template/reference/templates/reference-template-bike/pages/catalog.ts +1 -1
- package/template/reference/templates/reference-template-bike/pages/category.ts +1 -1
- package/template/reference/templates/reference-template-bike/pages/home.ts +10 -0
- package/template/reference/templates/reference-template-bike/pages/product.ts +1 -1
- package/template/sections/example-section/ExampleSection.vue +8 -1
- package/template/sections/example-section/client.ts +2 -1
- package/template/sections/example-section/component/button/Button.vue +1 -1
- package/template/sections/example-section/component/image/Image.vue +1 -1
- package/template/sections/example-section/component/image/ImagesGrid.vue +1 -1
- package/template/sections/example-section/component/selectbox/Selectbox.vue +1 -1
- package/template/sections/example-section/component/title/Title.vue +1 -1
- package/template/sections/example-section/component/toggle/Toggle.vue +1 -1
- package/template/sections/example-section/entity/color.ts +2 -2
- package/template/sections/example-section/server.ts +2 -1
- package/template/sections/example-section/settings/translations.ts +1 -1
- package/template/sections/example-section/showcases/1.ts +2 -22
- package/template/sections/example-section/showcases/2.ts +2 -22
- package/template/sections/example-section/showcases/3.ts +2 -22
- package/template/sections/example-section/showcases/translations.ts +11 -149
- package/template/shared/components/LanguageSelector.vue +1 -1
- package/template/shared/translation.ts +16 -0
- package/template/shared/utils.ts +3 -1
- package/template/tsconfig.json +1 -0
- package/types.d.ts +6 -457
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SectionWrapper :style="backgroundStyle">
|
|
3
|
+
<Title v-if="showTitle" />
|
|
4
|
+
<div class="products-wrapper">
|
|
5
|
+
<ProductItem
|
|
6
|
+
v-for="product in productSelectorContent.products"
|
|
7
|
+
:key="product.id"
|
|
8
|
+
:product="product"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
11
|
+
</SectionWrapper>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed, CSSProperties } from "vue";
|
|
16
|
+
import {
|
|
17
|
+
Color,
|
|
18
|
+
useBackgroundElementDesign,
|
|
19
|
+
useInputboxElementContent,
|
|
20
|
+
useProductSelectorElementContent,
|
|
21
|
+
useTextElementDesign,
|
|
22
|
+
} from "@lightspeed/crane-api";
|
|
23
|
+
import { Content, Design } from "./type";
|
|
24
|
+
import SectionWrapper from "../../shared/components/SectionWrapper.vue";
|
|
25
|
+
import Title from "./component/Title.vue";
|
|
26
|
+
import ProductItem from "./component/ProductItem.vue";
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const titleContent = useInputboxElementContent<Content>("section_title");
|
|
30
|
+
const titleDesign = useTextElementDesign<Design>('section_title');
|
|
31
|
+
|
|
32
|
+
const productSelectorContent =
|
|
33
|
+
useProductSelectorElementContent<Content>("featured_products");
|
|
34
|
+
|
|
35
|
+
const showTitle = computed(() => titleDesign.visible && titleContent.hasContent);
|
|
36
|
+
|
|
37
|
+
const backgroundDesign = useBackgroundElementDesign<Design>("background");
|
|
38
|
+
const background = computed(() => ({
|
|
39
|
+
type: backgroundDesign.background?.type,
|
|
40
|
+
solidColor: backgroundDesign.background?.solid?.color as Color,
|
|
41
|
+
fromColor: backgroundDesign.background?.gradient?.fromColor as Color,
|
|
42
|
+
toColor: backgroundDesign.background?.gradient?.toColor as Color,
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
const backgroundStyle = computed<CSSProperties>(() => {
|
|
46
|
+
if (background.value.type === "gradient") {
|
|
47
|
+
return {
|
|
48
|
+
"background-image": `linear-gradient(to right, ${background.value.fromColor.hex}, ${background.value.toColor.hex})`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return { "background-color": background.value.solidColor.hex };
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<style lang="scss" scoped>
|
|
56
|
+
.products-wrapper {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-wrap: wrap;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
gap: 12px;
|
|
61
|
+
max-width: 1440px;
|
|
62
|
+
margin: 0 auto;
|
|
63
|
+
width: 100%;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill="currentColor" d="M19.22 1.735c.528.012.97.42 1.037.933l.009.112.09 4.09a.97.97 0 01-1 1 1.08 1.08 0 01-1.037-.934l-.008-.111-.037-1.684-6.809 6.809c-.438.439-.877.47-1.314.095l-.101-.094c-.438-.437-.469-.876-.093-1.314l.094-.101 6.809-6.809-1.684-.037a1.08 1.08 0 01-1.034-.916l-.01-.128a.969.969 0 01.888-.997l.111-.003 4.09.09zM19 14.5a4.5 4.5 0 01-4.288 4.495L14.5 19h-7a4.5 4.5 0 01-4.495-4.288L3 14.5v-7a4.5 4.5 0 014.288-4.495L7.5 3h2.625a1 1 0 01.117 1.993L10.125 5H7.5a2.5 2.5 0 00-2.495 2.336L5 7.5v7a2.5 2.5 0 002.336 2.495L7.5 17h7a2.5 2.5 0 002.495-2.336L17 14.5v-2.625a1 1 0 011.993-.117l.007.117V14.5z" />
|
|
3
|
+
</svg>
|
package/template/reference/sections/featured-products/assets/custom_section_showcase_1_preview.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
v-if="product"
|
|
4
|
+
:key="product.id"
|
|
5
|
+
:href="product.url"
|
|
6
|
+
class="product"
|
|
7
|
+
>
|
|
8
|
+
<img v-if="product.fullImageUrl" class="product_image" :src="product.fullImageUrl" :alt="product.name" />
|
|
9
|
+
<h4 class="product__title">
|
|
10
|
+
{{ product.name }}
|
|
11
|
+
</h4>
|
|
12
|
+
<span class="product__price">{{ product.formattedPrice }}</span>
|
|
13
|
+
</a>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
interface Props {
|
|
18
|
+
product: ProductListComponentItem
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { product } = defineProps<Props>();
|
|
22
|
+
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<style scoped lang="scss">
|
|
26
|
+
.product {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
flex: 0 0 auto;
|
|
31
|
+
min-width: 0;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
text-decoration: inherit;
|
|
34
|
+
transition: transform 0.2s ease;
|
|
35
|
+
|
|
36
|
+
@media (max-width: 767px) {
|
|
37
|
+
width: calc(50% - 6px);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@media (min-width: 768px) {
|
|
41
|
+
width: calc(20% - 9.6px);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
transform: translateY(-4px);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.product_image {
|
|
50
|
+
width: 100%;
|
|
51
|
+
height: auto;
|
|
52
|
+
aspect-ratio: 3/4;
|
|
53
|
+
object-fit: cover;
|
|
54
|
+
display: block;
|
|
55
|
+
margin-bottom: 4px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.product__title {
|
|
59
|
+
font-size: 1rem;
|
|
60
|
+
font-weight: 300;
|
|
61
|
+
margin: 0;
|
|
62
|
+
line-height: 1.4;
|
|
63
|
+
color: #111;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.product__price {
|
|
67
|
+
font-size: 1rem;
|
|
68
|
+
font-weight: 600;
|
|
69
|
+
color: #111;
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1
|
|
3
|
+
:style="titleStyle"
|
|
4
|
+
class="section-title"
|
|
5
|
+
>
|
|
6
|
+
{{ titleContent.value }}
|
|
7
|
+
</h1>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { useInputboxElementContent, useTextElementDesign } from "@lightspeed/crane-api";
|
|
12
|
+
import { Content, Design } from "../type";
|
|
13
|
+
import { computed } from "vue";
|
|
14
|
+
|
|
15
|
+
const titleContent = useInputboxElementContent<Content>("section_title");
|
|
16
|
+
const titleDesign = useTextElementDesign<Design>('section_title');
|
|
17
|
+
|
|
18
|
+
const titleStyle = computed(() => ({
|
|
19
|
+
fontSize: `${titleDesign.size}px`,
|
|
20
|
+
fontFamily: titleDesign.font,
|
|
21
|
+
color: (titleDesign.color as Color).hex,
|
|
22
|
+
'font-style': titleDesign.italic ? 'italic' : 'normal',
|
|
23
|
+
'font-weight': titleDesign.bold ? 'bold' : 'normal',
|
|
24
|
+
}));
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style scoped lang="scss">
|
|
28
|
+
.section-title {
|
|
29
|
+
margin-bottom: 1rem;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
section_title: {
|
|
3
|
+
type: 'INPUTBOX',
|
|
4
|
+
label: '$label.section_title.label',
|
|
5
|
+
placeholder: '$label.section_title.placeholder',
|
|
6
|
+
},
|
|
7
|
+
featured_products: {
|
|
8
|
+
type: 'PRODUCT_SELECTOR',
|
|
9
|
+
label: '$label.featured_products.label',
|
|
10
|
+
defaults: {
|
|
11
|
+
maxProducts: 6,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
} as const;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
section_title: {
|
|
3
|
+
type: 'TEXT',
|
|
4
|
+
label: '$label.section_title.label',
|
|
5
|
+
colors: ['#FFFFFF66', '#0000004D', '#00000099', '#64C7FF66', '#F9947266', '#C794CD66', '#FFD17466'],
|
|
6
|
+
sizes: [18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60],
|
|
7
|
+
defaults: {
|
|
8
|
+
font: 'global.fontFamily.body',
|
|
9
|
+
size: 40,
|
|
10
|
+
bold: true,
|
|
11
|
+
italic: false,
|
|
12
|
+
color: '#313131',
|
|
13
|
+
visible: true,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
background: {
|
|
17
|
+
type: 'BACKGROUND',
|
|
18
|
+
label: '$label.background.label',
|
|
19
|
+
colors: [
|
|
20
|
+
'#FFFFFF66',
|
|
21
|
+
'#0000004D',
|
|
22
|
+
'#00000099',
|
|
23
|
+
'#64C7FF66',
|
|
24
|
+
'#F9947266',
|
|
25
|
+
'#C794CD66',
|
|
26
|
+
'#FFD17466',
|
|
27
|
+
],
|
|
28
|
+
defaults: {
|
|
29
|
+
style: 'COLOR',
|
|
30
|
+
color: 'global.color.background',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
} as const;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
'$label.section_title.label': 'Main title',
|
|
4
|
+
'$label.section_title.placeholder':
|
|
5
|
+
'This will be the main title for this section',
|
|
6
|
+
'$label.featured_products.label': 'Trending collections',
|
|
7
|
+
|
|
8
|
+
'$label.background.label': 'Background',
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
nl: {
|
|
12
|
+
'$label.section_title.label': 'Hoofdtitel',
|
|
13
|
+
'$label.section_title.placeholder':
|
|
14
|
+
'Dit wordt de hoofdtitel voor deze sectie',
|
|
15
|
+
'$label.featured_products.label': 'Trending collecties',
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
fr: {
|
|
19
|
+
'$label.section_title.label': 'Titre principal',
|
|
20
|
+
'$label.section_title.placeholder':
|
|
21
|
+
'Ce sera le titre principal de cette section',
|
|
22
|
+
'$label.featured_products.label': 'Collections tendance',
|
|
23
|
+
},
|
|
24
|
+
} as const;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
showcaseId: '1',
|
|
3
|
+
previewImage: {
|
|
4
|
+
set: {
|
|
5
|
+
ORIGINAL: {
|
|
6
|
+
url: 'custom_section_showcase_1_preview.png',
|
|
7
|
+
},
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
blockName: '$label.showcase_1.blockName',
|
|
11
|
+
content: {
|
|
12
|
+
section_title: {
|
|
13
|
+
type: 'INPUTBOX',
|
|
14
|
+
text: '$label.showcase_1.section_title.text',
|
|
15
|
+
},
|
|
16
|
+
featured_products: {
|
|
17
|
+
type: 'PRODUCT_SELECTOR',
|
|
18
|
+
maxProducts: 6,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
design: {
|
|
22
|
+
background: {
|
|
23
|
+
type: 'BACKGROUND',
|
|
24
|
+
style: 'COLOR',
|
|
25
|
+
color: 'global.color.background',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
} as const;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
'$label.showcase_1.blockName': 'Reference Section — Featured Products',
|
|
4
|
+
'$label.showcase_1.section_title.text': 'Featured Products',
|
|
5
|
+
},
|
|
6
|
+
|
|
7
|
+
nl: {
|
|
8
|
+
'$label.showcase_1.blockName': 'Referentiesectie — Aanbevolen producten',
|
|
9
|
+
'$label.showcase_1.section_title.text': 'Aanbevolen producten',
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
fr: {
|
|
13
|
+
'$label.showcase_1.blockName': 'Section de référence — Produits phares',
|
|
14
|
+
'$label.showcase_1.section_title.text': 'Produits phares',
|
|
15
|
+
},
|
|
16
|
+
} as const;
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
useButtonElementContent,
|
|
28
28
|
useButtonElementDesign,
|
|
29
29
|
ButtonContent,
|
|
30
|
-
} from '@lightspeed/crane';
|
|
30
|
+
} from '@lightspeed/crane-api';
|
|
31
31
|
import { computed } from 'vue';
|
|
32
32
|
import { Content, Design } from './type.ts';
|
|
33
33
|
import Slider from './component/Slider.vue';
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
useLayoutElementDesign,
|
|
46
46
|
useImageElementDesign,
|
|
47
47
|
useTextElementDesign,
|
|
48
|
-
} from '@lightspeed/crane';
|
|
48
|
+
} from '@lightspeed/crane-api';
|
|
49
49
|
import { Content, Design } from '../type.ts';
|
|
50
50
|
|
|
51
51
|
type Slide = {
|
|
@@ -117,8 +117,14 @@ const slideSize = computed<number>(() => slideWidth.value + slideGap.value);
|
|
|
117
117
|
|
|
118
118
|
function initializeItems(): void {
|
|
119
119
|
windowWidth.value = window.innerWidth;
|
|
120
|
+
|
|
121
|
+
if (!slides.value || slides.value.length === 0) {
|
|
122
|
+
repeatedItems.value = [];
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
120
126
|
const minItemsToFillViewport = Math.ceil(windowWidth.value / slideSize.value);
|
|
121
|
-
const repeats = Math.ceil(minItemsToFillViewport /
|
|
127
|
+
const repeats = Math.ceil(minItemsToFillViewport / slides.value.length) + 1;
|
|
122
128
|
|
|
123
129
|
repeatedItems.value = Array(repeats).fill(slides.value).flat();
|
|
124
130
|
}
|
|
@@ -14,7 +14,7 @@ import { computed, CSSProperties } from 'vue';
|
|
|
14
14
|
import {
|
|
15
15
|
useLayoutElementDesign,
|
|
16
16
|
useTextareaElementContent, useTextareaElementDesign,
|
|
17
|
-
} from '@lightspeed/crane';
|
|
17
|
+
} from '@lightspeed/crane-api';
|
|
18
18
|
import { Content, Design } from '../type.ts';
|
|
19
19
|
|
|
20
20
|
const titleContent = useTextareaElementContent<Content>('section_title');
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
useImageElementContent,
|
|
53
53
|
useTextElementDesign,
|
|
54
54
|
useInputboxElementContent,
|
|
55
|
-
} from '@lightspeed/crane';
|
|
55
|
+
} from '@lightspeed/crane-api';
|
|
56
56
|
import { computed } from 'vue';
|
|
57
57
|
import { Content, Design } from './type.ts';
|
|
58
58
|
import Tagline from '../../shared/components/Tagline.vue';
|
|
@@ -9,7 +9,7 @@ import { computed, CSSProperties } from 'vue';
|
|
|
9
9
|
import {
|
|
10
10
|
useInputboxElementContent,
|
|
11
11
|
useTextElementDesign,
|
|
12
|
-
} from '@lightspeed/crane';
|
|
12
|
+
} from '@lightspeed/crane-api';
|
|
13
13
|
import { Content, Design } from '../type.ts';
|
|
14
14
|
|
|
15
15
|
const titleContent = useInputboxElementContent<Content>('section_title');
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { computed } from 'vue';
|
|
2
1
|
import {
|
|
3
2
|
EditorTypes,
|
|
4
3
|
ImageContent,
|
|
5
4
|
TextAreaContent,
|
|
6
5
|
useDeckElementContent,
|
|
7
6
|
useTextElementDesign,
|
|
8
|
-
} from '@lightspeed/crane';
|
|
7
|
+
} from '@lightspeed/crane-api';
|
|
8
|
+
import { computed } from 'vue';
|
|
9
|
+
|
|
9
10
|
import { Content, Design } from '../type.ts';
|
|
10
11
|
|
|
11
12
|
export type Highlight = {
|
|
12
13
|
text?: TextAreaContent;
|
|
13
14
|
image?: ImageContent;
|
|
14
15
|
design: TextDesignData;
|
|
15
|
-
}
|
|
16
|
+
};
|
|
16
17
|
|
|
17
18
|
export function useHighlightedTextElementList() {
|
|
18
19
|
const design = computed<TextDesignData[]>(() => [
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SectionWrapper :style="backgroundStyle">
|
|
3
|
+
<Title v-if="showTitle" />
|
|
4
|
+
<div
|
|
5
|
+
v-if="categorySelectorContent.hasContent"
|
|
6
|
+
class="categories-wrapper"
|
|
7
|
+
>
|
|
8
|
+
<CategoryItem v-for="category in categorySelectorContent.categories" :key="category.id" :category="category" />
|
|
9
|
+
</div>
|
|
10
|
+
</SectionWrapper>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { computed, CSSProperties } from "vue";
|
|
15
|
+
import {
|
|
16
|
+
Color,
|
|
17
|
+
useBackgroundElementDesign,
|
|
18
|
+
useCategorySelectorElementContent,
|
|
19
|
+
useInputboxElementContent,
|
|
20
|
+
useTextElementDesign
|
|
21
|
+
} from "@lightspeed/crane-api";
|
|
22
|
+
|
|
23
|
+
import { Content, Design } from "./type";
|
|
24
|
+
import SectionWrapper from "../../shared/components/SectionWrapper.vue";
|
|
25
|
+
import Title from "./component/Title.vue";
|
|
26
|
+
import CategoryItem from "./component/CategoryItem.vue";
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const titleContent = useInputboxElementContent<Content>("section_title");
|
|
30
|
+
const titleDesign = useTextElementDesign<Design>('section_title');
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
const categorySelectorContent = useCategorySelectorElementContent<Content>(
|
|
34
|
+
"trending_categories",
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const showTitle = computed(() => titleDesign.visible && titleContent.hasContent);
|
|
38
|
+
|
|
39
|
+
const backgroundDesign = useBackgroundElementDesign<Design>("background");
|
|
40
|
+
const background = computed(() => ({
|
|
41
|
+
type: backgroundDesign.background?.type,
|
|
42
|
+
solidColor: backgroundDesign.background?.solid?.color as Color,
|
|
43
|
+
fromColor: backgroundDesign.background?.gradient?.fromColor as Color,
|
|
44
|
+
toColor: backgroundDesign.background?.gradient?.toColor as Color,
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
const backgroundStyle = computed<CSSProperties>(() => {
|
|
48
|
+
if (background.value.type === "gradient") {
|
|
49
|
+
return {
|
|
50
|
+
"background-image": `linear-gradient(to right, ${background.value.fromColor.hex}, ${background.value.toColor.hex})`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { "background-color": background.value.solidColor.hex };
|
|
54
|
+
});
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<style lang="scss" scoped>
|
|
58
|
+
.categories-wrapper {
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-wrap: wrap;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
width: 100%;
|
|
63
|
+
margin: 0 auto;
|
|
64
|
+
gap: 12px;
|
|
65
|
+
|
|
66
|
+
@media (min-width: 768px) {
|
|
67
|
+
max-width: 1440px;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill="currentColor" d="M19.22 1.735c.528.012.97.42 1.037.933l.009.112.09 4.09a.97.97 0 01-1 1 1.08 1.08 0 01-1.037-.934l-.008-.111-.037-1.684-6.809 6.809c-.438.439-.877.47-1.314.095l-.101-.094c-.438-.437-.469-.876-.093-1.314l.094-.101 6.809-6.809-1.684-.037a1.08 1.08 0 01-1.034-.916l-.01-.128a.969.969 0 01.888-.997l.111-.003 4.09.09zM19 14.5a4.5 4.5 0 01-4.288 4.495L14.5 19h-7a4.5 4.5 0 01-4.495-4.288L3 14.5v-7a4.5 4.5 0 014.288-4.495L7.5 3h2.625a1 1 0 01.117 1.993L10.125 5H7.5a2.5 2.5 0 00-2.495 2.336L5 7.5v7a2.5 2.5 0 002.336 2.495L7.5 17h7a2.5 2.5 0 002.495-2.336L17 14.5v-2.625a1 1 0 011.993-.117l.007.117V14.5z" />
|
|
3
|
+
</svg>
|
package/template/reference/sections/trending-categories/assets/custom_section_showcase_1_preview.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
v-if="category"
|
|
4
|
+
:key="category.id"
|
|
5
|
+
:href="category.url"
|
|
6
|
+
class="category"
|
|
7
|
+
>
|
|
8
|
+
<img v-if="category.imageUrl" class="category_image" :src="category.imageUrl" :alt="category.name" />
|
|
9
|
+
<h4 class="category__title">{{ category.name }}</h4>
|
|
10
|
+
</a>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
interface Props {
|
|
15
|
+
category: CategoryListComponentItem
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { category } = defineProps<Props>()
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style scoped lang="scss">
|
|
22
|
+
.category {
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
flex: 0 0 auto;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
|
|
30
|
+
@media (max-width: 767px) {
|
|
31
|
+
width: calc(50% - 6px);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@media (min-width: 768px) {
|
|
35
|
+
width: calc(20% - 9.6px);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.category_image {
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: auto;
|
|
42
|
+
aspect-ratio: 3/4;
|
|
43
|
+
object-fit: cover;
|
|
44
|
+
display: block;
|
|
45
|
+
margin-bottom: 4px;
|
|
46
|
+
transition: transform 0.3s ease;
|
|
47
|
+
|
|
48
|
+
.category:hover & {
|
|
49
|
+
transform: scale(1.05);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.category__title {
|
|
54
|
+
font-size: 1rem;
|
|
55
|
+
font-weight: 300;
|
|
56
|
+
margin: 0;
|
|
57
|
+
padding: 24px 6px 0 6px;
|
|
58
|
+
line-height: 1.4;
|
|
59
|
+
color: #111;
|
|
60
|
+
text-align: center;
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1
|
|
3
|
+
:style="titleStyle"
|
|
4
|
+
class="section-title"
|
|
5
|
+
>
|
|
6
|
+
{{ titleContent.value }}
|
|
7
|
+
</h1>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { useInputboxElementContent, useTextElementDesign } from "@lightspeed/crane-api";
|
|
12
|
+
import { Content, Design } from "../type";
|
|
13
|
+
import { computed } from "vue";
|
|
14
|
+
|
|
15
|
+
const titleContent = useInputboxElementContent<Content>("section_title");
|
|
16
|
+
const titleDesign = useTextElementDesign<Design>('section_title');
|
|
17
|
+
|
|
18
|
+
const titleStyle = computed(() => ({
|
|
19
|
+
fontSize: `${titleDesign.size}px`,
|
|
20
|
+
fontFamily: titleDesign.font,
|
|
21
|
+
color: (titleDesign.color as Color).hex,
|
|
22
|
+
'font-style': titleDesign.italic ? 'italic' : 'normal',
|
|
23
|
+
'font-weight': titleDesign.bold ? 'bold' : 'normal',
|
|
24
|
+
}));
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style scoped lang="scss">
|
|
28
|
+
.section-title {
|
|
29
|
+
margin-bottom: 1rem;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
</style>
|