@repobit/dex-system-design 0.24.19 → 0.24.20
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
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.24.20](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.24.19...@repobit/dex-system-design@0.24.20) (2026-09-24)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **DEX-1014:** new adjustments for Card component
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
## [0.24.19](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.24.18...@repobit/dex-system-design@0.24.19) (2026-09-23)
|
|
7
14
|
|
|
8
15
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@repobit/dex-system-design",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.20",
|
|
4
4
|
"description": "Design system based on Web Components.",
|
|
5
5
|
"author": "Iordache Matei Cezar <miordache@bitdefender.com>",
|
|
6
6
|
"homepage": "https://github.com/bitdefender/dex-core#readme",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"url": "https://github.com/bitdefender/dex-core/issues"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@repobit/dex-store": "1.6.
|
|
80
|
-
"@repobit/dex-store-elements": "2.1.
|
|
79
|
+
"@repobit/dex-store": "1.6.36",
|
|
80
|
+
"@repobit/dex-store-elements": "2.1.6",
|
|
81
81
|
"lit": "^3.3.2"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"volta": {
|
|
95
95
|
"node": "24.14.0"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "c5b184f2837dad5acab88a931b12d3d51121ed57"
|
|
98
98
|
}
|
|
@@ -50,6 +50,12 @@ export default css`
|
|
|
50
50
|
gap: var(--spacing-8);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/* Outline-variant sections get extra top padding above the header,
|
|
54
|
+
per the reference design. */
|
|
55
|
+
:host([variant="outline"]) .bd-header-light-carousel-s {
|
|
56
|
+
padding-top: 80px;
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
.bd-light-carousel-s {
|
|
54
60
|
display: flex;
|
|
55
61
|
align-items: center;
|
|
@@ -95,6 +101,56 @@ export default css`
|
|
|
95
101
|
background: #E4F2FF !important;
|
|
96
102
|
}
|
|
97
103
|
|
|
104
|
+
/* === OUTLINE VARIANT — bordered, tinted, fully centered card. Set
|
|
105
|
+
variant="outline" on bd-card-section (propagates to items) or on an
|
|
106
|
+
individual bd-card-item to opt it in/out per-card. === */
|
|
107
|
+
.bd-light-box-outline {
|
|
108
|
+
background-color: var(--color-neutral-25);
|
|
109
|
+
border: 2px solid var(--color-blue-500);
|
|
110
|
+
border-radius: var(--radius-2xl, 1rem);
|
|
111
|
+
padding: 40px;
|
|
112
|
+
align-items: center !important;
|
|
113
|
+
justify-content: center !important;
|
|
114
|
+
text-align: center !important;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.bd-light-box-outline .bd-light-box-header-s {
|
|
118
|
+
align-items: center;
|
|
119
|
+
justify-content: center;
|
|
120
|
+
width: 100%;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.bd-light-box-outline .bd-light-title-badge-wrapper-s {
|
|
124
|
+
justify-content: center;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.bd-light-box-outline .bd-card-title-group {
|
|
128
|
+
align-items: center;
|
|
129
|
+
text-align: center;
|
|
130
|
+
margin-top: 60px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.bd-light-box-outline .bd-card-title-group bd-h {
|
|
134
|
+
color: var(--color-blue-500, #006dff);
|
|
135
|
+
text-align: center;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.bd-light-box-outline .bd-card-item-subtitle,
|
|
139
|
+
.bd-light-box-outline .bd-card-content-wrapper p,
|
|
140
|
+
.bd-light-box-outline .bd-card-content-wrapper ::slotted(*) {
|
|
141
|
+
color: var(--color-neutral-700);
|
|
142
|
+
text-align: center;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.bd-light-box-outline .bd-card-content-wrapper {
|
|
146
|
+
align-items: center;
|
|
147
|
+
text-align: center;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.bd-light-box-outline .bd-card-cta-wrapper {
|
|
151
|
+
justify-content: center;
|
|
152
|
+
}
|
|
153
|
+
|
|
98
154
|
.bd-light-box-center {
|
|
99
155
|
align-items: center !important;
|
|
100
156
|
justify-content: center !important;
|
|
@@ -9,6 +9,13 @@ class Card extends LitElement {
|
|
|
9
9
|
title : { type: String },
|
|
10
10
|
subtitle : { type: String },
|
|
11
11
|
bgBlue : { type: Boolean, reflect: true, attribute: "bg-blue" },
|
|
12
|
+
// "" (default — existing grey-box carousel look) | "outline" — bordered,
|
|
13
|
+
// centered cards with a light-blue tint, blue title and centered icon,
|
|
14
|
+
// matching the reference design. Propagated automatically to every
|
|
15
|
+
// slotted bd-card-item (see _onSlotChange) so callers only set it once,
|
|
16
|
+
// on the section, unless a specific item needs to opt out by setting
|
|
17
|
+
// its own variant attribute explicitly.
|
|
18
|
+
variant : { type: String, reflect: true },
|
|
12
19
|
_itemCount: { state: true }
|
|
13
20
|
};
|
|
14
21
|
|
|
@@ -17,6 +24,7 @@ class Card extends LitElement {
|
|
|
17
24
|
this.title = "";
|
|
18
25
|
this.subtitle = "";
|
|
19
26
|
this.bgBlue = false;
|
|
27
|
+
this.variant = "";
|
|
20
28
|
this._itemCount = 0;
|
|
21
29
|
this._resizeObserver = null;
|
|
22
30
|
}
|
|
@@ -47,8 +55,26 @@ class Card extends LitElement {
|
|
|
47
55
|
this.style.setProperty("--bd-card-width", `${cardW}px`);
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
// Propagates this.variant onto every slotted bd-card-item that didn't
|
|
59
|
+
// itself declare a variant attribute in its ORIGINAL markup. We can't use
|
|
60
|
+
// item.hasAttribute("variant") here — CardItem's own `variant` property
|
|
61
|
+
// has reflect:true, so Lit reflects its default "" onto the attribute on
|
|
62
|
+
// first render, meaning hasAttribute("variant") becomes true for EVERY
|
|
63
|
+
// item almost immediately, even ones the author never touched. Instead
|
|
64
|
+
// we rely on item._authorSetVariant, captured in CardItem's constructor
|
|
65
|
+
// (before Lit's own reflection has a chance to run) — see below.
|
|
66
|
+
_propagateVariant() {
|
|
67
|
+
if (!this.variant) return;
|
|
68
|
+
this.querySelectorAll("bd-card-item").forEach((item) => {
|
|
69
|
+
if (!item._authorSetVariant) {
|
|
70
|
+
item.variant = this.variant;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
50
75
|
_onSlotChange = () => {
|
|
51
76
|
this._itemCount = this.querySelectorAll("bd-card-item").length;
|
|
77
|
+
this._propagateVariant();
|
|
52
78
|
this._updateCardWidth();
|
|
53
79
|
this.requestUpdate();
|
|
54
80
|
this._equalizeHeights();
|
|
@@ -160,6 +186,7 @@ class Card extends LitElement {
|
|
|
160
186
|
}
|
|
161
187
|
|
|
162
188
|
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
|
|
189
|
+
this._propagateVariant();
|
|
163
190
|
this._updateCardWidth();
|
|
164
191
|
this._equalizeHeights();
|
|
165
192
|
|
|
@@ -208,38 +235,61 @@ class CardItem extends LitElement {
|
|
|
208
235
|
icon : { type: String },
|
|
209
236
|
align : { type: String },
|
|
210
237
|
bgBlue : { type: Boolean, reflect: true, attribute: "bg-blue" },
|
|
211
|
-
ctaAlign: { type: String, attribute: "cta-align" }
|
|
238
|
+
ctaAlign: { type: String, attribute: "cta-align" },
|
|
239
|
+
// "" (default) | "outline" — see Card.variant above. Reflected so
|
|
240
|
+
// card.css.js can target it with :host([variant="outline"]).
|
|
241
|
+
variant : { type: String, reflect: true }
|
|
212
242
|
};
|
|
213
243
|
|
|
214
244
|
constructor() {
|
|
215
245
|
super();
|
|
246
|
+
// Captured BEFORE Lit's own property-to-attribute reflection runs (that
|
|
247
|
+
// happens on first update/render, not here). At this point the DOM
|
|
248
|
+
// parser has already set any attribute the author wrote in markup, so
|
|
249
|
+
// this reliably answers "did the author explicitly set variant on this
|
|
250
|
+
// element", independent of whatever default value we assign below.
|
|
251
|
+
this._authorSetVariant = this.hasAttribute("variant");
|
|
252
|
+
|
|
216
253
|
this.title = "";
|
|
217
254
|
this.subtitle = "";
|
|
218
255
|
this.icon = "";
|
|
219
256
|
this.align = "start";
|
|
220
257
|
this.bgBlue = false;
|
|
221
258
|
this.ctaAlign = "start";
|
|
259
|
+
this.variant = "";
|
|
222
260
|
}
|
|
223
261
|
|
|
224
262
|
_renderIcon() {
|
|
225
263
|
const iconEl = this.querySelector("[slot='icon']");
|
|
264
|
+
const isOutline = this.variant === "outline";
|
|
265
|
+
const iconW = isOutline ? 65 : 48;
|
|
266
|
+
const iconH = isOutline ? 75 : 48;
|
|
226
267
|
|
|
227
268
|
if (iconEl) {
|
|
228
269
|
const clone = iconEl.cloneNode(true);
|
|
229
270
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
clone.style.width
|
|
233
|
-
|
|
271
|
+
// The icon components (bd-globe-icon etc.) size their inner <svg>
|
|
272
|
+
// from their own width/height attributes, not from CSS on the host —
|
|
273
|
+
// setting only clone.style.width/height left the SVG's actual
|
|
274
|
+
// width="48" height="48" attributes untouched, so nothing visibly
|
|
275
|
+
// changed. Overwrite the attributes themselves for anything that
|
|
276
|
+
// looks like an icon component (custom element) or a raw <svg>.
|
|
277
|
+
clone.setAttribute("width", iconW);
|
|
278
|
+
clone.setAttribute("height", iconH);
|
|
279
|
+
|
|
280
|
+
clone.style.maxWidth = `${iconW}px`;
|
|
281
|
+
clone.style.maxHeight = `${iconH}px`;
|
|
282
|
+
clone.style.width = `${iconW}px`;
|
|
283
|
+
clone.style.height = `${iconH}px`;
|
|
234
284
|
clone.style.objectFit = "contain";
|
|
235
285
|
clone.style.display = "block";
|
|
236
286
|
|
|
237
287
|
const innerImg = clone.querySelector("img");
|
|
238
288
|
if (innerImg) {
|
|
239
|
-
innerImg.style.maxWidth =
|
|
240
|
-
innerImg.style.maxHeight =
|
|
241
|
-
innerImg.style.width =
|
|
242
|
-
innerImg.style.height =
|
|
289
|
+
innerImg.style.maxWidth = `${iconW}px`;
|
|
290
|
+
innerImg.style.maxHeight = `${iconH}px`;
|
|
291
|
+
innerImg.style.width = `${iconW}px`;
|
|
292
|
+
innerImg.style.height = `${iconH}px`;
|
|
243
293
|
innerImg.style.objectFit = "contain";
|
|
244
294
|
innerImg.style.display = "block";
|
|
245
295
|
innerImg.removeAttribute("width");
|
|
@@ -254,6 +304,7 @@ class CardItem extends LitElement {
|
|
|
254
304
|
src="${this.icon}"
|
|
255
305
|
alt="icon"
|
|
256
306
|
class="bd-light-icon-s"
|
|
307
|
+
style="width: ${iconW}px; height: ${iconH}px;"
|
|
257
308
|
/>`;
|
|
258
309
|
}
|
|
259
310
|
|
|
@@ -272,7 +323,8 @@ class CardItem extends LitElement {
|
|
|
272
323
|
}
|
|
273
324
|
|
|
274
325
|
render() {
|
|
275
|
-
const
|
|
326
|
+
const isOutline = this.variant === "outline";
|
|
327
|
+
const isCentered = this.align === "center" || isOutline;
|
|
276
328
|
const hasContent = this._hasContent();
|
|
277
329
|
const hasCtaSlot = !!this.querySelector("[slot='cta']");
|
|
278
330
|
const ctaJustify = this.ctaAlign === "center"
|
|
@@ -285,7 +337,8 @@ class CardItem extends LitElement {
|
|
|
285
337
|
<div
|
|
286
338
|
class="bd-light-box-s
|
|
287
339
|
${isCentered ? "bd-light-box-center" : ""}
|
|
288
|
-
${this.bgBlue ? "bd-light-box-blue" : ""}
|
|
340
|
+
${this.bgBlue ? "bd-light-box-blue" : ""}
|
|
341
|
+
${isOutline ? "bd-light-box-outline" : ""}"
|
|
289
342
|
>
|
|
290
343
|
<div class="bd-light-box-header-s ${isCentered ? "bd-light-box-header-center" : ""}">
|
|
291
344
|
${this._renderIcon()}
|
|
@@ -27,6 +27,13 @@ Grid columns are calculated automatically:
|
|
|
27
27
|
| 7–8 | 4 | 4+3, 4+4 |
|
|
28
28
|
| 9 | 3 | 3+3+3 |
|
|
29
29
|
| 10+ | 4 | 4+4+... |
|
|
30
|
+
|
|
31
|
+
### Variants
|
|
32
|
+
\`variant="outline"\` on \`bd-card-section\` switches every slotted \`bd-card-item\`
|
|
33
|
+
to a bordered, light-blue-tinted, centered card style (blue title, centered
|
|
34
|
+
icon/text) — set it once on the section, it propagates to all items
|
|
35
|
+
automatically. Leaving \`variant\` unset keeps the existing grey-box look.
|
|
36
|
+
An individual \`bd-card-item\` can opt out with \`variant=""\` explicitly.
|
|
30
37
|
`
|
|
31
38
|
}
|
|
32
39
|
}
|
|
@@ -324,6 +331,54 @@ export const MobileView = {
|
|
|
324
331
|
</bd-card-section>
|
|
325
332
|
` };
|
|
326
333
|
|
|
334
|
+
// ─── Outline Variant ────────────────────────────────────────────────────────
|
|
335
|
+
|
|
336
|
+
export const OutlineVariant = {
|
|
337
|
+
name : 'Outline Variant — Trusted For The AI Era',
|
|
338
|
+
render: () => html`
|
|
339
|
+
<bd-card-section
|
|
340
|
+
title="Trusted For The AI Era"
|
|
341
|
+
subtitle="Pioneering AI in Cybersecurity since 2008."
|
|
342
|
+
variant="outline"
|
|
343
|
+
>
|
|
344
|
+
<bd-card-item title="Transparency">
|
|
345
|
+
<bd-individual-icon slot="icon" width="48" height="48" color="#006DFF"></bd-individual-icon>
|
|
346
|
+
<bd-p>We provide clear information about how our AI makes security decisions and what data it uses, balancing technical transparency with usability.</bd-p>
|
|
347
|
+
</bd-card-item>
|
|
348
|
+
<bd-card-item title="Privacy by Design">
|
|
349
|
+
<bd-globe-icon slot="icon" width="48" height="48" color="#006DFF"></bd-globe-icon>
|
|
350
|
+
<bd-p>We implement privacy-preserving techniques like federated learning and differential privacy to minimize data exposure while maintaining AI effectiveness.</bd-p>
|
|
351
|
+
</bd-card-item>
|
|
352
|
+
<bd-card-item title="Human Guided AI Protection">
|
|
353
|
+
<bd-family-icon slot="icon" width="48" height="48" color="#006DFF"></bd-family-icon>
|
|
354
|
+
<bd-p>While our AI is powerful, we augment it with the deep expertise of Bitdefender Labs.</bd-p>
|
|
355
|
+
</bd-card-item>
|
|
356
|
+
</bd-card-section>
|
|
357
|
+
`,
|
|
358
|
+
parameters: { docs: { description: { story: '`variant="outline"` pe `bd-card-section` — se propagă automat la toate cardurile: contur albastru subțire, fundal albastru foarte deschis, titlu albastru, conținut centrat.' } } }
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
export const OutlineVariantMixed = {
|
|
362
|
+
name : 'Outline Variant — Mixed With Default',
|
|
363
|
+
render: () => html`
|
|
364
|
+
<bd-card-section title="Mixed Variants" variant="outline">
|
|
365
|
+
<bd-card-item title="Outline Card One">
|
|
366
|
+
<bd-individual-icon slot="icon" width="48" height="48" color="#006DFF"></bd-individual-icon>
|
|
367
|
+
<bd-p>This card inherits the outline variant from the section.</bd-p>
|
|
368
|
+
</bd-card-item>
|
|
369
|
+
<bd-card-item title="Opted-out Card" variant="">
|
|
370
|
+
<bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
|
|
371
|
+
<bd-p>This card explicitly sets variant="" to opt out and keep the default grey-box look.</bd-p>
|
|
372
|
+
</bd-card-item>
|
|
373
|
+
<bd-card-item title="Outline Card Two">
|
|
374
|
+
<bd-machine-learning-icon slot="icon" width="48" height="48" color="#006DFF"></bd-machine-learning-icon>
|
|
375
|
+
<bd-p>This card also inherits the outline variant.</bd-p>
|
|
376
|
+
</bd-card-item>
|
|
377
|
+
</bd-card-section>
|
|
378
|
+
`,
|
|
379
|
+
parameters: { docs: { description: { story: 'Un card poate seta `variant=""` explicit ca să rămână pe stilul default, chiar dacă secțiunea are `variant="outline"`.' } } }
|
|
380
|
+
};
|
|
381
|
+
|
|
327
382
|
// ─── Playground ───────────────────────────────────────────────────────────────
|
|
328
383
|
|
|
329
384
|
export const Playground = {
|
|
@@ -331,13 +386,21 @@ export const Playground = {
|
|
|
331
386
|
args: {
|
|
332
387
|
sectionTitle : 'Why Bitdefender',
|
|
333
388
|
sectionSubtitle: '',
|
|
389
|
+
sectionVariant : '',
|
|
334
390
|
itemTitle : 'AI Protection',
|
|
335
391
|
align : 'start',
|
|
336
392
|
bgBlue : false,
|
|
337
393
|
ctaAlign : 'start'
|
|
338
394
|
},
|
|
395
|
+
argTypes: {
|
|
396
|
+
sectionVariant: {
|
|
397
|
+
control : { type: 'select' },
|
|
398
|
+
options : ['', 'outline'],
|
|
399
|
+
description: 'bd-card-section variant — propagates to all items'
|
|
400
|
+
}
|
|
401
|
+
},
|
|
339
402
|
render: (args) => html`
|
|
340
|
-
<bd-card-section title="${args.sectionTitle}" subtitle="${args.sectionSubtitle}">
|
|
403
|
+
<bd-card-section title="${args.sectionTitle}" subtitle="${args.sectionSubtitle}" variant="${args.sectionVariant}">
|
|
341
404
|
<bd-card-item
|
|
342
405
|
title="${args.itemTitle}"
|
|
343
406
|
align="${args.align}"
|
|
@@ -360,5 +423,5 @@ export const Playground = {
|
|
|
360
423
|
</bd-card-item>
|
|
361
424
|
</bd-card-section>
|
|
362
425
|
`,
|
|
363
|
-
parameters: { docs: { description: { story: 'Playground interactiv
|
|
426
|
+
parameters: { docs: { description: { story: 'Playground interactiv — folosește `sectionVariant` din Controls ca să testezi `variant="outline"`.' } } }
|
|
364
427
|
};
|