@repobit/dex-system-design 0.2.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 +11 -0
- package/README.md +15 -0
- package/package.json +57 -0
- package/src/assets/fonts/IBMPlexMono-Bold.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-BoldItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-Italic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-Light.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-LightItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-Medium.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-MediumItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-Regular.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-SemiBold.woff2 +0 -0
- package/src/assets/fonts/IBMPlexMono-SemiBoldItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-Bold.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-BoldItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-Italic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-Light.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-LightItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-Medium.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-MediumItalic.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-Regular.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-SemiBold.woff2 +0 -0
- package/src/assets/fonts/IBMPlexSans-SemiBoldItalic.woff2 +0 -0
- package/src/assets/fonts/bd-ibm-plex-mono.zip +0 -0
- package/src/assets/fonts/bd-ibm-plex-sans.zip +0 -0
- package/src/assets/icons/badge-icon-individual.png +0 -0
- package/src/assets/icons/bd-icon-family-white.png +0 -0
- package/src/assets/icons/bd-icon-family.png +0 -0
- package/src/assets/icons/bd-icon-user.png +0 -0
- package/src/assets/icons/left_clicked.png +0 -0
- package/src/assets/icons/left_disabled.png +0 -0
- package/src/assets/icons/left_hover.png +0 -0
- package/src/assets/icons/left_normal.png +0 -0
- package/src/assets/icons/light-carousel-img1.png +0 -0
- package/src/assets/icons/light-carousel-img2.png +0 -0
- package/src/assets/icons/light-carousel-img3.png +0 -0
- package/src/assets/icons/more_hover.png +0 -0
- package/src/assets/icons/more_normal.png +0 -0
- package/src/assets/icons/more_pressed.png +0 -0
- package/src/assets/icons/pic1.png +0 -0
- package/src/assets/icons/pic2.png +0 -0
- package/src/assets/icons/pic3.png +0 -0
- package/src/assets/icons/right_clicked.png +0 -0
- package/src/assets/icons/right_disabled.png +0 -0
- package/src/assets/icons/right_hover.png +0 -0
- package/src/assets/icons/right_normal.png +0 -0
- package/src/assets/icons/tabs-img1.png +0 -0
- package/src/assets/icons/tabs-img2.png +0 -0
- package/src/assets/icons/tabs-img3.png +0 -0
- package/src/assets/icons/verified_arrow.png +0 -0
- package/src/components/Button/Button.js +120 -0
- package/src/components/Button/button.css.js +137 -0
- package/src/components/Button/button.stories.js +56 -0
- package/src/components/Button/icons.css +5 -0
- package/src/components/Button/icons.js +24 -0
- package/src/components/Button/index.js +0 -0
- package/src/components/FAQ/faq.css.js +107 -0
- package/src/components/FAQ/faq.js +176 -0
- package/src/components/FAQ/faq.stories.js +45 -0
- package/src/components/Input/Input.js +27 -0
- package/src/components/Input/index.js +0 -0
- package/src/components/Input/input.css.js +68 -0
- package/src/components/carousel/carousel.css.js +304 -0
- package/src/components/carousel/carousel.js +226 -0
- package/src/components/carousel/carousel.stories.js +73 -0
- package/src/components/light-carousel/light-carousel.css.js +149 -0
- package/src/components/light-carousel/light-carousel.js +108 -0
- package/src/components/light-carousel/light-carousel.stories.js +43 -0
- package/src/components/paragraph/paragraph.css.js +16 -0
- package/src/components/paragraph/paragraph.js +59 -0
- package/src/components/pricing-cards/pricing-card.css.js +409 -0
- package/src/components/pricing-cards/pricing-card.js +764 -0
- package/src/components/pricing-cards/pricing-card.stories.js +12 -0
- package/src/components/tabs/tabs.css.js +239 -0
- package/src/components/tabs/tabs.js +183 -0
- package/src/components/tabs/tabs.stories.js +18 -0
- package/src/components/termsOfUse/terms.css.js +38 -0
- package/src/components/termsOfUse/terms.js +226 -0
- package/src/components/termsOfUse/terms.stories.js +14 -0
- package/src/index.js +0 -0
- package/src/stories/Button.js +20 -0
- package/src/stories/Button.stories.js +46 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/Header.js +45 -0
- package/src/stories/Header.stories.js +24 -0
- package/src/stories/Page.js +62 -0
- package/src/stories/Page.stories.js +20 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
- package/src/tokens/colors.js +121 -0
- package/src/tokens/layout.css +46 -0
- package/src/tokens/tokens.css +297 -0
- package/src/tokens/typography.css.js +207 -0
- package/src/tokens/typography.js +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { LitElement, html } from "lit";
|
|
2
|
+
import carouselCSS from "../carousel/carousel.css.js";
|
|
3
|
+
|
|
4
|
+
class CarouselItem extends LitElement {
|
|
5
|
+
static properties = {
|
|
6
|
+
title: { type: String },
|
|
7
|
+
subTitle: { type: String },
|
|
8
|
+
modalText: { type: String },
|
|
9
|
+
icon: { type: String },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
this.title = "";
|
|
15
|
+
this.subTitle = "";
|
|
16
|
+
this.modalText = "";
|
|
17
|
+
this.icon = "";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
render() {
|
|
21
|
+
return html`
|
|
22
|
+
<div class="bd-box">
|
|
23
|
+
${this.icon
|
|
24
|
+
? html`<img src="${this.icon}" alt="icon" class="bd-carousel-icon" />`
|
|
25
|
+
: ""}
|
|
26
|
+
${this.title ? html`<h3>${this.title}</h3>` : ""}
|
|
27
|
+
${this.subTitle ? html`<p>${this.subTitle}</p>` : ""}
|
|
28
|
+
<div
|
|
29
|
+
class="bd-plus-button"
|
|
30
|
+
@click="${() =>
|
|
31
|
+
this.dispatchEvent(
|
|
32
|
+
new CustomEvent("open-modal", {
|
|
33
|
+
detail: {
|
|
34
|
+
title: this.title,
|
|
35
|
+
modalText: this.modalText,
|
|
36
|
+
icon: this.icon,
|
|
37
|
+
},
|
|
38
|
+
bubbles: true,
|
|
39
|
+
composed: true,
|
|
40
|
+
})
|
|
41
|
+
)}"
|
|
42
|
+
></div>
|
|
43
|
+
</div>
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class CustomCarousel extends LitElement {
|
|
49
|
+
static properties = {
|
|
50
|
+
selectedItem: { type: Object },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
constructor() {
|
|
54
|
+
super();
|
|
55
|
+
this.selectedItem = null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
firstUpdated() {
|
|
59
|
+
const track = this.shadowRoot.querySelector(".bd-carousel-track");
|
|
60
|
+
const slot = this.shadowRoot.querySelector("slot");
|
|
61
|
+
|
|
62
|
+
// Ascultă scroll ca să actualizezi săgețile
|
|
63
|
+
track.addEventListener("scroll", () => this.updateArrowStates());
|
|
64
|
+
|
|
65
|
+
// Ascultă schimbările din slot
|
|
66
|
+
slot.addEventListener("slotchange", () => {
|
|
67
|
+
this.waitForImagesToLoad().then(() => {
|
|
68
|
+
this.updateArrowStates();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Așteaptă un layout complet înainte de prima verificare
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
this.waitForImagesToLoad().then(() => {
|
|
75
|
+
this.updateArrowStates();
|
|
76
|
+
});
|
|
77
|
+
}, 0);
|
|
78
|
+
|
|
79
|
+
const arrows = this.shadowRoot.querySelectorAll(".bd-arrow");
|
|
80
|
+
arrows.forEach((arrow) => {
|
|
81
|
+
arrow.addEventListener("mousedown", () =>
|
|
82
|
+
arrow.classList.add("bd-active")
|
|
83
|
+
);
|
|
84
|
+
arrow.addEventListener("mouseup", () =>
|
|
85
|
+
arrow.classList.remove("bd-active")
|
|
86
|
+
);
|
|
87
|
+
arrow.addEventListener("mouseleave", () =>
|
|
88
|
+
arrow.classList.remove("bd-active")
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
this.addEventListener("open-modal", (e) => this.openModal(e.detail));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
waitForImagesToLoad() {
|
|
96
|
+
const assignedElements = this.shadowRoot
|
|
97
|
+
.querySelector("slot")
|
|
98
|
+
.assignedElements({ flatten: true });
|
|
99
|
+
|
|
100
|
+
const images = assignedElements
|
|
101
|
+
.map((el) => el.shadowRoot?.querySelector("img"))
|
|
102
|
+
.filter((img) => img);
|
|
103
|
+
|
|
104
|
+
const promises = images.map(
|
|
105
|
+
(img) =>
|
|
106
|
+
new Promise((resolve) => {
|
|
107
|
+
if (img.complete) {
|
|
108
|
+
resolve();
|
|
109
|
+
} else {
|
|
110
|
+
img.addEventListener("load", resolve, { once: true });
|
|
111
|
+
img.addEventListener("error", resolve, { once: true }); // în caz de eroare de încărcare
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
return Promise.all(promises);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
scrollCarousel(direction) {
|
|
120
|
+
const slot = this.shadowRoot.querySelector("slot");
|
|
121
|
+
const assignedElements = slot.assignedElements({ flatten: true });
|
|
122
|
+
|
|
123
|
+
if (!assignedElements.length) {
|
|
124
|
+
console.warn("No items found in slot!");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const itemWidth = assignedElements[0].offsetWidth || 300;
|
|
129
|
+
const track = this.shadowRoot.querySelector(".bd-carousel-track");
|
|
130
|
+
|
|
131
|
+
if (!track) {
|
|
132
|
+
console.warn("No track found!");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (direction === "left") {
|
|
137
|
+
track.scrollBy({ left: -itemWidth, behavior: "smooth" });
|
|
138
|
+
} else if (direction === "right") {
|
|
139
|
+
track.scrollBy({ left: itemWidth, behavior: "smooth" });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Așteaptă animația scroll-ului și actualizează săgețile
|
|
143
|
+
setTimeout(() => this.updateArrowStates(), 300);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
updateArrowStates() {
|
|
147
|
+
const track = this.shadowRoot.querySelector(".bd-carousel-track");
|
|
148
|
+
const trackWidth = track.offsetWidth;
|
|
149
|
+
const totalWidth = track.scrollWidth;
|
|
150
|
+
const scrollPosition = track.scrollLeft;
|
|
151
|
+
|
|
152
|
+
const leftArrow = this.shadowRoot.querySelector(".bd-left-arrow");
|
|
153
|
+
const rightArrow = this.shadowRoot.querySelector(".bd-right-arrow");
|
|
154
|
+
|
|
155
|
+
if (!leftArrow || !rightArrow) return;
|
|
156
|
+
|
|
157
|
+
if (scrollPosition <= 0) {
|
|
158
|
+
leftArrow.classList.add("bd-disabled");
|
|
159
|
+
} else {
|
|
160
|
+
leftArrow.classList.remove("bd-disabled");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (scrollPosition + trackWidth >= totalWidth - 1) {
|
|
164
|
+
rightArrow.classList.add("bd-disabled");
|
|
165
|
+
} else {
|
|
166
|
+
rightArrow.classList.remove("bd-disabled");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
openModal(item) {
|
|
171
|
+
this.selectedItem = item;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
closeModal() {
|
|
175
|
+
this.selectedItem = null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
render() {
|
|
179
|
+
return html`
|
|
180
|
+
<div class="bd-carousel">
|
|
181
|
+
<div class="bd-header-carousel">
|
|
182
|
+
<h1 class="bd-section-title">${this.title}</h1>
|
|
183
|
+
</div>
|
|
184
|
+
<img
|
|
185
|
+
alt="Left Arrow"
|
|
186
|
+
class="bd-arrow bd-left-arrow"
|
|
187
|
+
@click="${() => this.scrollCarousel("left")}"
|
|
188
|
+
/>
|
|
189
|
+
<div class="bd-carousel-track">
|
|
190
|
+
<slot></slot>
|
|
191
|
+
</div>
|
|
192
|
+
<img
|
|
193
|
+
alt="Right Arrow"
|
|
194
|
+
class="bd-arrow bd-right-arrow"
|
|
195
|
+
@click="${() => this.scrollCarousel("right")}"
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
${this.selectedItem
|
|
200
|
+
? html`
|
|
201
|
+
<div class="bd-modal" @click="${this.closeModal}" ?open="${true}">
|
|
202
|
+
<div
|
|
203
|
+
class="bd-modal-content"
|
|
204
|
+
@click="${(e) => e.stopPropagation()}"
|
|
205
|
+
>
|
|
206
|
+
<img
|
|
207
|
+
src="${this.selectedItem.icon}"
|
|
208
|
+
alt="icon"
|
|
209
|
+
class="bd-carousel-modal-icon"
|
|
210
|
+
/>
|
|
211
|
+
<h2>${this.selectedItem.title}</h2>
|
|
212
|
+
<p>${this.selectedItem.modalText}</p>
|
|
213
|
+
<button @click="${this.closeModal}">Close</button>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
`
|
|
217
|
+
: ""}
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
CarouselItem.styles = [carouselCSS];
|
|
223
|
+
CustomCarousel.styles = [carouselCSS];
|
|
224
|
+
|
|
225
|
+
customElements.define("bd-carousel-item", CarouselItem);
|
|
226
|
+
customElements.define("bd-carousel-section", CustomCarousel);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './carousel.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Components/Carousel Section',
|
|
6
|
+
component: 'bd-carousel-section',
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const Template = (args) => html`
|
|
11
|
+
<bd-carousel-section title=${args.title}>
|
|
12
|
+
<bd-carousel-item
|
|
13
|
+
title="Scam Copilot Bot"
|
|
14
|
+
subTitle="Specialized AI chatbot that helps you identify suspicious online interactions so you don’t become a victim"
|
|
15
|
+
modalText="Specialized AI chatbot that helps you identify suspicious online interactions so you don’t become a victim"
|
|
16
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
17
|
+
></bd-carousel-item>
|
|
18
|
+
|
|
19
|
+
<bd-carousel-item
|
|
20
|
+
title="Scam Wave Alerts"
|
|
21
|
+
subTitle="Proactively informs you about scam outbreaks in your region"
|
|
22
|
+
modalText="Proactively informs you about scam outbreaks in your region"
|
|
23
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
24
|
+
></bd-carousel-item>
|
|
25
|
+
|
|
26
|
+
<bd-carousel-item
|
|
27
|
+
title="AI-Powered Scam Check"
|
|
28
|
+
subTitle="AI-driven tool that instantly evaluates the legitimacy of any link, message, or online interaction"
|
|
29
|
+
modalText="AI-driven tool that instantly evaluates the legitimacy of any link, message, or online interaction"
|
|
30
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
31
|
+
></bd-carousel-item>
|
|
32
|
+
|
|
33
|
+
<bd-carousel-item
|
|
34
|
+
title="Educational Resources"
|
|
35
|
+
subTitle="Access a wealth of information and best practices to stay informed and vigilant against scams"
|
|
36
|
+
modalText="Access a wealth of information and best practices to stay informed and vigilant against scams"
|
|
37
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
38
|
+
></bd-carousel-item>
|
|
39
|
+
|
|
40
|
+
<bd-carousel-item
|
|
41
|
+
title="Phishing Simulator"
|
|
42
|
+
subTitle="Simulates phishing attacks to help you recognize and respond appropriately to real threats"
|
|
43
|
+
modalText="Simulates phishing attacks to help you recognize and respond appropriately to real threats"
|
|
44
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
45
|
+
></bd-carousel-item>
|
|
46
|
+
|
|
47
|
+
<bd-carousel-item
|
|
48
|
+
title="Real-Time Scam Updates"
|
|
49
|
+
subTitle="Stay ahead with up-to-the-minute alerts on the latest scams targeting your region or industry"
|
|
50
|
+
modalText="Stay ahead with up-to-the-minute alerts on the latest scams targeting your region or industry"
|
|
51
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
52
|
+
></bd-carousel-item>
|
|
53
|
+
|
|
54
|
+
<bd-carousel-item
|
|
55
|
+
title="Community Reporting Hub"
|
|
56
|
+
subTitle="A platform where users can report scams and share experiences to help protect others"
|
|
57
|
+
modalText="A platform where users can report scams and share experiences to help protect others"
|
|
58
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
59
|
+
></bd-carousel-item>
|
|
60
|
+
|
|
61
|
+
<bd-carousel-item
|
|
62
|
+
title="Fraud Prevention Workshops"
|
|
63
|
+
subTitle="Interactive workshops that educate users on identifying and avoiding scams"
|
|
64
|
+
modalText="Interactive workshops that educate users on identifying and avoiding scams"
|
|
65
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
66
|
+
></bd-carousel-item>
|
|
67
|
+
</bd-carousel-section>
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
export const Default = Template.bind({});
|
|
71
|
+
Default.args = {
|
|
72
|
+
title: "Need help? We've got answers!",
|
|
73
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export default css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
--background-card-grey: var(--color-neutral-25);
|
|
7
|
+
--border-card-grey: var(--color-neutral-50);
|
|
8
|
+
}
|
|
9
|
+
.bd-section-title {
|
|
10
|
+
font-family: var(--font-family-sans);
|
|
11
|
+
font-weight: var(--font-weight-sans-semibold);
|
|
12
|
+
font-size: 2em;
|
|
13
|
+
}
|
|
14
|
+
.bd-header-light-carousel {
|
|
15
|
+
margin-bottom: 50px;
|
|
16
|
+
margin-top: 50px;
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
.bd-light-carousel {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
position: relative;
|
|
24
|
+
width: 100%;
|
|
25
|
+
margin: var(--size-0) auto;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
}
|
|
29
|
+
.bd-light-carousel-title {
|
|
30
|
+
font-size: 28px;
|
|
31
|
+
font-weight: 700;
|
|
32
|
+
text-align: center;
|
|
33
|
+
color: #e4002b; /* roșu Bitdefender */
|
|
34
|
+
margin-bottom: 32px;
|
|
35
|
+
text-transform: uppercase;
|
|
36
|
+
letter-spacing: 0.5px;
|
|
37
|
+
}
|
|
38
|
+
.bd-light-carousel-track {
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 2em;
|
|
41
|
+
scroll-behavior: smooth;
|
|
42
|
+
flex: 1;
|
|
43
|
+
position: relative;
|
|
44
|
+
padding: var(--size-0) var(--size-20);
|
|
45
|
+
overflow-x: auto;
|
|
46
|
+
overflow-y: hidden;
|
|
47
|
+
scrollbar-width: none;
|
|
48
|
+
-ms-overflow-style: none;
|
|
49
|
+
z-index: 1;
|
|
50
|
+
scroll-snap-type: x mandatory;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.bd-light-carousel-track::-webkit-scrollbar {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.bd-light-box {
|
|
58
|
+
flex: var(--size-0) var(--size-0) auto;
|
|
59
|
+
width: 450px;
|
|
60
|
+
background: var(--background-card-grey);
|
|
61
|
+
border-radius: 28px;
|
|
62
|
+
border: var(--size-2) solid var(--border-card-grey);
|
|
63
|
+
padding: 2em;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
align-items: start;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
text-align: start;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: transform 0.2s ease-in-out;
|
|
71
|
+
min-height: 250px;
|
|
72
|
+
position: relative;
|
|
73
|
+
z-index: 2;
|
|
74
|
+
scroll-snap-align: start;
|
|
75
|
+
font-family: var(--font-family-sans);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.bd-light-box h3 {
|
|
79
|
+
font-size: var(--size-18);
|
|
80
|
+
margin: var(--size-0) var(--size-0) 0.5em var(--size-0);
|
|
81
|
+
font-weight: 600;
|
|
82
|
+
font-family: var(--font-family-sans);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.bd-light-box p {
|
|
86
|
+
font-size: var(--size-16);
|
|
87
|
+
margin: var(--size-0) var(--size-0) 1em var(--size-0);
|
|
88
|
+
font-family: var(--font-family-sans);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.bd-light-icon {
|
|
92
|
+
position: relative;
|
|
93
|
+
bottom: 15px;
|
|
94
|
+
max-width: 100%;
|
|
95
|
+
height: var(--size-40);
|
|
96
|
+
width: var(--size-40);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@media (max-width: 1024px) {
|
|
100
|
+
.bd-light-box {
|
|
101
|
+
width: 380px;
|
|
102
|
+
padding: 1.5em;
|
|
103
|
+
}
|
|
104
|
+
.bd-light-box h3 {
|
|
105
|
+
font-size: 1.1em;
|
|
106
|
+
}
|
|
107
|
+
.bd-light-box p {
|
|
108
|
+
font-size: 0.95em;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@media (max-width: 768px) {
|
|
113
|
+
.bd-light-carousel-track {
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
gap: var(--size-20);
|
|
117
|
+
overflow-x: hidden;
|
|
118
|
+
overflow-y: hidden;
|
|
119
|
+
scroll-behavior: smooth;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.bd-light-box {
|
|
123
|
+
width: 100%;
|
|
124
|
+
max-width: 400px;
|
|
125
|
+
margin: var(--size-0) auto;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.bd-arrow {
|
|
129
|
+
display: none;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@media (max-width: 480px) {
|
|
134
|
+
.bd-light-box {
|
|
135
|
+
width: 100%;
|
|
136
|
+
padding: 1em;
|
|
137
|
+
min-height: 300px;
|
|
138
|
+
}
|
|
139
|
+
.bd-light-box h3 {
|
|
140
|
+
font-size: 1em;
|
|
141
|
+
}
|
|
142
|
+
.bd-light-box p {
|
|
143
|
+
font-size: 0.9em;
|
|
144
|
+
}
|
|
145
|
+
.bd-light-icon {
|
|
146
|
+
bottom: var(--size-10);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import carouselCSS from "../light-carousel/light-carousel.css.js";
|
|
3
|
+
|
|
4
|
+
class CustomLightCarousel extends LitElement {
|
|
5
|
+
static properties = {
|
|
6
|
+
title: { type: String },
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.title = "";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
firstUpdated() {
|
|
15
|
+
this.updateArrowStates();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
scrollCarousel(direction) {
|
|
19
|
+
const track = this.shadowRoot.querySelector(".bd-light-carousel-track");
|
|
20
|
+
const itemWidth = track.firstElementChild
|
|
21
|
+
? track.firstElementChild.offsetWidth
|
|
22
|
+
: 300;
|
|
23
|
+
const trackWidth = track.offsetWidth;
|
|
24
|
+
const scrollPosition = track.scrollLeft;
|
|
25
|
+
|
|
26
|
+
if (direction === "left" && scrollPosition > 0) {
|
|
27
|
+
track.scrollBy({ left: -itemWidth, behavior: "smooth" });
|
|
28
|
+
} else if (
|
|
29
|
+
direction === "right" &&
|
|
30
|
+
scrollPosition + trackWidth < track.scrollWidth
|
|
31
|
+
) {
|
|
32
|
+
track.scrollBy({ left: itemWidth, behavior: "smooth" });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.updateArrowStates();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
updateArrowStates() {
|
|
39
|
+
const track = this.shadowRoot.querySelector(".bd-light-carousel-track");
|
|
40
|
+
const trackWidth = track.offsetWidth;
|
|
41
|
+
const totalWidth = track.scrollWidth;
|
|
42
|
+
const scrollPosition = track.scrollLeft;
|
|
43
|
+
|
|
44
|
+
const leftArrow = this.shadowRoot.querySelector(".bd-light-left-arrow");
|
|
45
|
+
const rightArrow = this.shadowRoot.querySelector(".bd-light-right-arrow");
|
|
46
|
+
|
|
47
|
+
if (scrollPosition === 0) {
|
|
48
|
+
leftArrow.classList.add("bd-disabled");
|
|
49
|
+
} else {
|
|
50
|
+
leftArrow.classList.remove("bd-disabled");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (scrollPosition + trackWidth >= totalWidth) {
|
|
54
|
+
rightArrow.classList.add("bd-disabled");
|
|
55
|
+
} else {
|
|
56
|
+
rightArrow.classList.remove("bd-disabled");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
render() {
|
|
61
|
+
return html`
|
|
62
|
+
<section class="bd-light-carousel">
|
|
63
|
+
<div class="bd-header-light-carousel">
|
|
64
|
+
<h1 class="bd-section-title">${this.title}</h1>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="bd-light-carousel-track">
|
|
68
|
+
<slot></slot>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
</section>
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
class LightCarouselItem extends LitElement {
|
|
77
|
+
static properties = {
|
|
78
|
+
title: { type: String },
|
|
79
|
+
badge: { type: String },
|
|
80
|
+
icon: { type: String },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
constructor() {
|
|
84
|
+
super();
|
|
85
|
+
this.title = "";
|
|
86
|
+
this.badge = "";
|
|
87
|
+
this.icon = "";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
render() {
|
|
91
|
+
return html`
|
|
92
|
+
<div class="bd-light-box">
|
|
93
|
+
|
|
94
|
+
${this.icon
|
|
95
|
+
? html`<img src="${this.icon}" alt="icon" class="bd-light-icon" />`
|
|
96
|
+
: ""}
|
|
97
|
+
${this.title ? html`<h3>${this.title}</h3>` : ""}
|
|
98
|
+
<slot></slot>
|
|
99
|
+
</div>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
CustomLightCarousel.styles = [carouselCSS];
|
|
104
|
+
LightCarouselItem.styles = [carouselCSS];
|
|
105
|
+
|
|
106
|
+
customElements.define("bd-light-carousel-item", LightCarouselItem);
|
|
107
|
+
|
|
108
|
+
customElements.define("bd-light-carousel-section", CustomLightCarousel);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import "./light-carousel.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: "Components/Light Carousel",
|
|
6
|
+
component: "bd-light-carousel-section",
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
argTypes: {
|
|
9
|
+
title: { control: "text" },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Template = (args) => html`
|
|
14
|
+
<bd-light-carousel-section title="${args.title}">
|
|
15
|
+
<bd-light-carousel-item
|
|
16
|
+
title="How does Bitdefender Internet Security protect me?"
|
|
17
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
18
|
+
badge="FAQ"
|
|
19
|
+
>
|
|
20
|
+
<p>Bitdefender Internet Security provides the best protection...</p>
|
|
21
|
+
<p>Bitdefender Internet Security provides the best protection...</p>
|
|
22
|
+
</bd-light-carousel-item>
|
|
23
|
+
|
|
24
|
+
<bd-light-carousel-item
|
|
25
|
+
title="How to install Bitdefender on another device?"
|
|
26
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
27
|
+
>
|
|
28
|
+
<p>You can install Bitdefender on other devices by...</p>
|
|
29
|
+
</bd-light-carousel-item>
|
|
30
|
+
|
|
31
|
+
<bd-light-carousel-item
|
|
32
|
+
title="How to install Bitdefender on another device?"
|
|
33
|
+
icon="src/assets/icons/light-carousel-img1.png"
|
|
34
|
+
>
|
|
35
|
+
<p>You can install Bitdefender on other devices by...</p>
|
|
36
|
+
</bd-light-carousel-item>
|
|
37
|
+
</bd-light-carousel-section>
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
export const Default = Template.bind({});
|
|
41
|
+
Default.args = {
|
|
42
|
+
title: "Need help? We've got answers!",
|
|
43
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { css } from "../../../node_modules/lit-element/lit-element";
|
|
2
|
+
|
|
3
|
+
export default css`
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.bd-font-brand{
|
|
7
|
+
font-family: var(--font-family-sans);
|
|
8
|
+
}
|
|
9
|
+
.bd-font-cod {
|
|
10
|
+
font-family: var(--font-family-mono);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.bd-font-comp {
|
|
14
|
+
font-family: 'Arial',sans-serif;
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import paragraphText from "../paragraph/paragraph.css.js";
|
|
3
|
+
import textCSS from "../../tokens/typography.css.js";
|
|
4
|
+
|
|
5
|
+
class TextFontBrand extends LitElement {
|
|
6
|
+
static properties = {
|
|
7
|
+
text: { type: String }
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.text = "Componenta Text Font Brand.";
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
return html` <p class="bd-font-brand text-display-medium">${this.text}</p> `;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TextFontCod extends LitElement {
|
|
23
|
+
static properties = {
|
|
24
|
+
text: { type: String }
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super();
|
|
29
|
+
this.text = "Componenta Text Font Cod.";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
render() {
|
|
33
|
+
return html` <p class="bd-font-cod">${this.text}</p> `;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TextFontComp extends LitElement {
|
|
39
|
+
static properties = {
|
|
40
|
+
text: { type: String }
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
super();
|
|
45
|
+
this.text = "Componenta Text Font Comp.";
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
render() {
|
|
50
|
+
return html` <p class="bd-font-comp">${this.text}</p> `;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
TextFontBrand.styles = [paragraphText, textCSS];
|
|
54
|
+
TextFontCod.styles = [paragraphText, textCSS];
|
|
55
|
+
TextFontComp.styles = [paragraphText, textCSS];
|
|
56
|
+
|
|
57
|
+
customElements.define("bd-font-brand", TextFontBrand);
|
|
58
|
+
customElements.define("bd-font-cod", TextFontCod);
|
|
59
|
+
customElements.define("bd-font-comp", TextFontComp);
|