@repobit/dex-system-design 0.5.0 → 0.7.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 +18 -0
- package/package.json +4 -3
- package/src/assets/images/bd-header-img.jpg +0 -0
- package/src/assets/images/bd-header-us.jpg +0 -0
- package/src/components/Button/Button.js +115 -3
- package/src/components/Button/button.css.js +80 -43
- package/src/components/Button/button.stories.js +83 -7
- package/src/components/FAQ/faq.css.js +26 -15
- package/src/components/FAQ/faq.js +23 -114
- package/src/components/FAQ/faq.stories.js +41 -20
- package/src/components/Input/Input.js +2 -2
- package/src/components/anchor/anchor-nav.css.js +92 -0
- package/src/components/anchor/anchor-nav.js +121 -0
- package/src/components/anchor/anchor.stories.js +134 -0
- package/src/components/badge/badge.css.js +27 -0
- package/src/components/badge/badge.js +30 -0
- package/src/components/badge/badge.stories.js +36 -0
- package/src/components/carousel/carousel.css.js +35 -18
- package/src/components/carousel/carousel.js +149 -99
- package/src/components/carousel/carousel.stories.js +202 -46
- package/src/components/checkbox/checkbox.css.js +132 -0
- package/src/components/checkbox/checkbox.js +130 -0
- package/src/components/checkbox/checkbox.stories.js +63 -0
- package/src/components/divider/divider-horizontal.js +29 -0
- package/src/components/divider/divider-vertical.js +32 -0
- package/src/components/divider/divider.css.js +0 -0
- package/src/components/divider/divider.stories.js +77 -0
- package/src/components/header/header.css.js +248 -0
- package/src/components/header/header.js +87 -0
- package/src/components/header/header.stories.js +57 -0
- package/src/components/highlight/highlight-s.css.js +88 -0
- package/src/components/highlight/highlight-s.js +35 -0
- package/src/components/highlight/highlight-s.stories.js +22 -0
- package/src/components/highlight/highlight.css.js +119 -0
- package/src/components/highlight/highlight.js +60 -0
- package/src/components/highlight/highlight.stories.js +53 -0
- package/src/components/light-carousel/light-carousel.css.js +18 -10
- package/src/components/light-carousel/light-carousel.js +29 -16
- package/src/components/light-carousel/light-carousel.stories.js +9 -7
- package/src/components/pricing-cards/pricing-card.css.js +137 -2
- package/src/components/pricing-cards/pricing-card.js +63 -82
- package/src/components/pricing-cards/pricing-card.stories.js +1 -0
- package/src/components/radio/radio.css.js +168 -0
- package/src/components/radio/radio.js +222 -0
- package/src/components/radio/radio.stories.js +103 -0
- package/src/components/tabs/tabs.css.js +25 -7
- package/src/components/tabs/tabs.js +19 -12
- package/src/components/termsOfUse/terms.css.js +6 -0
- package/src/tokens/fonts.stories.js +73 -0
- package/src/tokens/spacing.stories.js +56 -0
- package/src/tokens/tokens-grid.stories.js +83 -0
- package/src/tokens/tokens.css +116 -1
- package/src/tokens/tokens.stories.js +67 -0
- package/src/tokens/typography.stories.js +69 -0
- package/src/tokens/tokens.js +0 -206
- /package/src/assets/{icons → images}/tabs-img1.png +0 -0
- /package/src/assets/{icons → images}/tabs-img2.png +0 -0
- /package/src/assets/{icons → images}/tabs-img3.png +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import pricingCardsCSS from "../pricing-cards/pricing-card.css.js";
|
|
3
3
|
|
|
4
|
-
import "/src/components/
|
|
4
|
+
import "/src/components/Button/Button.js";
|
|
5
5
|
|
|
6
6
|
class PricingContainer extends LitElement {
|
|
7
7
|
static properties = {
|
|
@@ -30,7 +30,6 @@ class PricingContainer extends LitElement {
|
|
|
30
30
|
|
|
31
31
|
if (isNaN(numericValue)) return "";
|
|
32
32
|
|
|
33
|
-
// Foloseste Intl fara separator de mii
|
|
34
33
|
const formattedValue = new Intl.NumberFormat(this.locale, {
|
|
35
34
|
style: "currency",
|
|
36
35
|
currency: this.currency,
|
|
@@ -44,6 +43,9 @@ class PricingContainer extends LitElement {
|
|
|
44
43
|
render() {
|
|
45
44
|
return html`
|
|
46
45
|
<div class="pricing-container">
|
|
46
|
+
<h1 class="bd-section-title">
|
|
47
|
+
Pricing Cards
|
|
48
|
+
</h1>
|
|
47
49
|
<pricing-switch
|
|
48
50
|
.planType=${this.planType}
|
|
49
51
|
@plan-switch=${this.handleSwitch}
|
|
@@ -155,76 +157,55 @@ class PricingCard extends LitElement {
|
|
|
155
157
|
}
|
|
156
158
|
render() {
|
|
157
159
|
return html`
|
|
158
|
-
${this.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
strong
|
|
205
|
-
>Learn More</bd-button>
|
|
206
|
-
</div>
|
|
207
|
-
<hr class="hr-line" />
|
|
208
|
-
${this.features
|
|
209
|
-
? html`<pricing-card-features></pricing-card-features>`
|
|
210
|
-
: ""}
|
|
211
|
-
${this.privacy
|
|
212
|
-
? html`<pricing-card-privacy></pricing-card-privacy>`
|
|
213
|
-
: ""}
|
|
214
|
-
${this.identity
|
|
215
|
-
? html`<pricing-card-identity></pricing-card-identity>`
|
|
216
|
-
: ""}
|
|
217
|
-
${this.identityExtended
|
|
218
|
-
? html`<pricing-card-identity-extended></pricing-card-identity-extended>`
|
|
219
|
-
: ""}
|
|
220
|
-
${this.parentalControl
|
|
221
|
-
? html`<pricing-card-parental-control></pricing-card-parental-control>`
|
|
222
|
-
: ""}
|
|
223
|
-
</div>
|
|
224
|
-
`
|
|
225
|
-
: ""}
|
|
160
|
+
<div class="card ${this.highlight ? "highlight" : ""}">
|
|
161
|
+
${this.highlight
|
|
162
|
+
? html`<div class="highlight-banner">Best value</div>`
|
|
163
|
+
: ""}
|
|
164
|
+
<div class="card-header">
|
|
165
|
+
<p class="card-title">${this.title}</p>
|
|
166
|
+
<span class="badge">
|
|
167
|
+
<img
|
|
168
|
+
src="icons/badge-icon-individual.png"
|
|
169
|
+
alt="icon"
|
|
170
|
+
class="badge-icon"
|
|
171
|
+
/>
|
|
172
|
+
Individual
|
|
173
|
+
</span>
|
|
174
|
+
<p class="badge-subtitle">1 account & 5 devices</p>
|
|
175
|
+
<hr class="hr-line" />
|
|
176
|
+
</div>
|
|
177
|
+
<div class="pricing">
|
|
178
|
+
<div class="pricing-info">
|
|
179
|
+
<p class="original-price">
|
|
180
|
+
${this.formatCurrency(this.originalPrice)}
|
|
181
|
+
</p>
|
|
182
|
+
<p class="discount">${this.discount}</p>
|
|
183
|
+
</div>
|
|
184
|
+
<p class="price">${this.formatCurrency(this.price)}</p>
|
|
185
|
+
<p class="terms">
|
|
186
|
+
First year price. Plus applicable sales tax. See
|
|
187
|
+
<a href="#">terms of use</a> below.
|
|
188
|
+
</p>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="actions">
|
|
191
|
+
<bd-button label="Buy Now" kind="danger" size="md" fullWidth strong>
|
|
192
|
+
Buy Now
|
|
193
|
+
</bd-button>
|
|
194
|
+
|
|
195
|
+
<bd-button label="Learn More" kind="outline" size="md" fullWidth strong>
|
|
196
|
+
Learn More
|
|
197
|
+
</bd-button>
|
|
198
|
+
</div>
|
|
199
|
+
<hr class="hr-line" />
|
|
200
|
+
${this.features ? html`<pricing-card-features></pricing-card-features>` : ""}
|
|
201
|
+
${this.privacy ? html`<pricing-card-privacy></pricing-card-privacy>` : ""}
|
|
202
|
+
${this.identity ? html`<pricing-card-identity></pricing-card-identity>` : ""}
|
|
203
|
+
${this.identityExtended ? html`<pricing-card-identity-extended></pricing-card-identity-extended>` : ""}
|
|
204
|
+
${this.parentalControl ? html`<pricing-card-parental-control></pricing-card-parental-control>` : ""}
|
|
205
|
+
</div>
|
|
226
206
|
`;
|
|
227
207
|
}
|
|
208
|
+
|
|
228
209
|
}
|
|
229
210
|
class PricingCardFamily extends LitElement {
|
|
230
211
|
static properties = {
|
|
@@ -282,7 +263,7 @@ class PricingCardFamily extends LitElement {
|
|
|
282
263
|
<p class="card-title">${this.title}</p>
|
|
283
264
|
<span class="badge">
|
|
284
265
|
<img
|
|
285
|
-
src="
|
|
266
|
+
src="icons/bd-icon-family-white.png"
|
|
286
267
|
alt="icon"
|
|
287
268
|
class="badge-icon-family-subtitle"
|
|
288
269
|
/>
|
|
@@ -382,7 +363,7 @@ class PricingSwitch extends LitElement {
|
|
|
382
363
|
<span class="label right">
|
|
383
364
|
<span class="icon icon-user-sharp-regular">
|
|
384
365
|
<img
|
|
385
|
-
src="
|
|
366
|
+
src="icons/bd-icon-user.png"
|
|
386
367
|
alt="icon"
|
|
387
368
|
class="badge-icon-user"
|
|
388
369
|
height="22"
|
|
@@ -394,7 +375,7 @@ class PricingSwitch extends LitElement {
|
|
|
394
375
|
<span class="label left">
|
|
395
376
|
<span class="icon icon-family-pants-sharp-regular">
|
|
396
377
|
<img
|
|
397
|
-
src="
|
|
378
|
+
src="icons/bd-icon-family.png"
|
|
398
379
|
alt="icon"
|
|
399
380
|
class="badge-icon-family"
|
|
400
381
|
height="24"
|
|
@@ -456,7 +437,7 @@ class PricingCardFeatures extends LitElement {
|
|
|
456
437
|
${features.map(
|
|
457
438
|
(feature) => html` <li class="feature-item">
|
|
458
439
|
<img
|
|
459
|
-
src="
|
|
440
|
+
src="icons/verified_arrow.png"
|
|
460
441
|
alt="icon"
|
|
461
442
|
class="badge-icon"
|
|
462
443
|
/>
|
|
@@ -514,7 +495,7 @@ class PricingCardPrivacy extends LitElement {
|
|
|
514
495
|
${privacy.map(
|
|
515
496
|
(priv) => html` <li class="feature-item">
|
|
516
497
|
<img
|
|
517
|
-
src="
|
|
498
|
+
src="icons/verified_arrow.png"
|
|
518
499
|
alt="icon"
|
|
519
500
|
class="badge-icon"
|
|
520
501
|
/>
|
|
@@ -523,7 +504,7 @@ class PricingCardPrivacy extends LitElement {
|
|
|
523
504
|
? html`<span class="badge-feature"
|
|
524
505
|
>${priv.badge}
|
|
525
506
|
<img
|
|
526
|
-
src="
|
|
507
|
+
src="icons/badge-icon-individual.png"
|
|
527
508
|
alt="icon"
|
|
528
509
|
class="badge-feature-icon"
|
|
529
510
|
/></span>`
|
|
@@ -565,7 +546,7 @@ class PricingCardIdentify extends LitElement {
|
|
|
565
546
|
${identity.map(
|
|
566
547
|
(ident) => html` <li class="feature-item">
|
|
567
548
|
<img
|
|
568
|
-
src="
|
|
549
|
+
src="icons/verified_arrow.png"
|
|
569
550
|
alt="icon"
|
|
570
551
|
class="badge-icon"
|
|
571
552
|
/>
|
|
@@ -574,7 +555,7 @@ class PricingCardIdentify extends LitElement {
|
|
|
574
555
|
? html`<span class="badge-feature"
|
|
575
556
|
>${ident.badge}
|
|
576
557
|
<img
|
|
577
|
-
src="
|
|
558
|
+
src="icons/badge-icon-individual.png"
|
|
578
559
|
alt="icon"
|
|
579
560
|
class="badge-feature-icon"
|
|
580
561
|
/></span>`
|
|
@@ -636,7 +617,7 @@ class PricingCardIdentityExtend extends LitElement {
|
|
|
636
617
|
${identity.map(
|
|
637
618
|
(ident) => html` <li class="feature-item">
|
|
638
619
|
<img
|
|
639
|
-
src="
|
|
620
|
+
src="icons/verified_arrow.png"
|
|
640
621
|
alt="icon"
|
|
641
622
|
class="badge-icon"
|
|
642
623
|
/>
|
|
@@ -645,7 +626,7 @@ class PricingCardIdentityExtend extends LitElement {
|
|
|
645
626
|
? html`<span class="badge-feature"
|
|
646
627
|
>${ident.badge}
|
|
647
628
|
<img
|
|
648
|
-
src="
|
|
629
|
+
src="icons/badge-icon-individual.png"
|
|
649
630
|
alt="icon"
|
|
650
631
|
class="badge-feature-icon"
|
|
651
632
|
/></span>`
|
|
@@ -710,7 +691,7 @@ class PricingCardParentalControl extends LitElement {
|
|
|
710
691
|
${parentalControl.map(
|
|
711
692
|
(parental) => html` <li class="feature-item">
|
|
712
693
|
<img
|
|
713
|
-
src="
|
|
694
|
+
src="icons/verified_arrow.png"
|
|
714
695
|
alt="icon"
|
|
715
696
|
class="badge-icon"
|
|
716
697
|
/>
|
|
@@ -719,7 +700,7 @@ class PricingCardParentalControl extends LitElement {
|
|
|
719
700
|
? html`<span class="badge-feature"
|
|
720
701
|
>${parental.badge}
|
|
721
702
|
<img
|
|
722
|
-
src="
|
|
703
|
+
src="icons/badge-icon-individual.png"
|
|
723
704
|
alt="icon"
|
|
724
705
|
class="badge-feature-icon"
|
|
725
706
|
/></span>`
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export default css`
|
|
4
|
+
:host {
|
|
5
|
+
display: inline-block;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.bd-radio {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
gap: var(--size-8);
|
|
13
|
+
font-family: sans-serif;
|
|
14
|
+
font-size: 14px;
|
|
15
|
+
vertical-align: middle;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.bd-radio.disabled {
|
|
19
|
+
cursor: not-allowed;
|
|
20
|
+
opacity: 0.6;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.radio-label {
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
color: black;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.bd-outer,
|
|
29
|
+
.custom-radio {
|
|
30
|
+
width: var(--size-22);
|
|
31
|
+
height: var(--size-22);
|
|
32
|
+
border:var(--size-2) solid var(--color-blue-500);
|
|
33
|
+
border-radius: 50%;
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
box-sizing: border-box;
|
|
38
|
+
transition: border-color 0.2s ease;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.bd-inner {
|
|
42
|
+
width: var(--size-12);
|
|
43
|
+
height: var(--size-12);
|
|
44
|
+
background-color: var(--color-blue-500);
|
|
45
|
+
border-radius: 50%;
|
|
46
|
+
transform: scale(0);
|
|
47
|
+
transition: transform 0.2s ease, background-color 0.2s ease;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.bd-inner.visible {
|
|
51
|
+
transform: scale(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bd-outer:hover {
|
|
55
|
+
border-color: var(--color-blue-700);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.bd-inner:hover {
|
|
59
|
+
background-color: var(--color-blue-700);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.bd-radio.disabled .bd-outer.checked {
|
|
63
|
+
border-color: #b0b0b0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.bd-outer.checked:hover {
|
|
67
|
+
border-color: var(--color-blue-700);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
.bd-radio.disabled .bd-outer {
|
|
72
|
+
border-color: #b0b0b0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.bd-radio.disabled .bd-inner {
|
|
76
|
+
background-color: #b0b0b0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.bd-radio[disabled] {
|
|
80
|
+
opacity: 0.5;
|
|
81
|
+
cursor: not-allowed;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
.bd-radio.focus .bd-outer,
|
|
86
|
+
.bd-outer.focus {
|
|
87
|
+
outline: var(--size-2) solid var(--color-blue-500);
|
|
88
|
+
outline-offset: var(--size-2);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hidden-input {
|
|
92
|
+
position: absolute;
|
|
93
|
+
width: 1px;
|
|
94
|
+
height: 1px;
|
|
95
|
+
margin: -1px;
|
|
96
|
+
padding: 0;
|
|
97
|
+
border: 0;
|
|
98
|
+
clip: rect(0 0 0 0);
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
.custom-radio::after {
|
|
105
|
+
content: "";
|
|
106
|
+
position: absolute;
|
|
107
|
+
top: 50%;
|
|
108
|
+
left: 50%;
|
|
109
|
+
width: var(--size-12);
|
|
110
|
+
height: var(--size-12);
|
|
111
|
+
background-color: #006dff;
|
|
112
|
+
border-radius: 50%;
|
|
113
|
+
transform: translate(-50%, -50%) scale(0);
|
|
114
|
+
transition: transform 0.2s;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
input:checked + .custom-radio::after {
|
|
118
|
+
transform: translate(-50%, -50%) scale(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.bd-radio:not(.disabled):hover .custom-radio {
|
|
122
|
+
border-color: #004bbd;
|
|
123
|
+
}
|
|
124
|
+
.bd-radio.disabled .bd-inner.visible {
|
|
125
|
+
background-color: #b0b0b0;
|
|
126
|
+
transform: scale(1);
|
|
127
|
+
}
|
|
128
|
+
.bd-radio:not(.disabled):focus-within .custom-radio {
|
|
129
|
+
box-shadow: 0 0 0 3px rgba(0, 109, 255, 0.5);
|
|
130
|
+
}
|
|
131
|
+
.bd-outer:focus {
|
|
132
|
+
outline: none;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.bd-outer:focus-visible {
|
|
136
|
+
outline: var(--size-2) solid var(--color-blue-500);
|
|
137
|
+
outline-offset: var(--size-2);
|
|
138
|
+
}
|
|
139
|
+
.bd-outer:focus:not(:focus-visible) {
|
|
140
|
+
outline: none;
|
|
141
|
+
}
|
|
142
|
+
.bd-outer.focus {
|
|
143
|
+
outline: var(--size-2) solid var(--color-blue-500);
|
|
144
|
+
outline-offset: var(--size-2);
|
|
145
|
+
}
|
|
146
|
+
.bd-outer:active {
|
|
147
|
+
outline: var(--size-2) solid var(--color-blue-500);
|
|
148
|
+
outline-offset: var(--size-2);
|
|
149
|
+
}
|
|
150
|
+
.bd-outer:focus-visible.checked {
|
|
151
|
+
outline: var(--size-2) solid var(--color-blue-500);
|
|
152
|
+
outline-offset: var(--size-2);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.bd-outer:focus-visible.checked .bd-inner {
|
|
156
|
+
background-color: var(--color-blue-500);
|
|
157
|
+
}
|
|
158
|
+
.bd-outer:focus-visible .bd-inner.visible {
|
|
159
|
+
background-color: var(--color-blue-700);
|
|
160
|
+
}
|
|
161
|
+
.bd-outer:focus-visible {
|
|
162
|
+
border-color: var(--color-blue-700);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.bd-outer:focus-visible .bd-inner.visible {
|
|
166
|
+
background-color: var(--color-blue-700);
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import radioCSS from "./radio.css.js";
|
|
3
|
+
|
|
4
|
+
class BdRadio extends LitElement {
|
|
5
|
+
static properties = {
|
|
6
|
+
name: { type: String },
|
|
7
|
+
value: { type: String },
|
|
8
|
+
checked: { type: Boolean, reflect: true },
|
|
9
|
+
disabled: { type: Boolean, reflect: true },
|
|
10
|
+
label: { type: String },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
static styles = [radioCSS];
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
this.name = "";
|
|
18
|
+
this.value = "";
|
|
19
|
+
this.disabled = false;
|
|
20
|
+
this.label = "";
|
|
21
|
+
this._hadKeyboardFocus = false;
|
|
22
|
+
|
|
23
|
+
this._handleDocumentKeydown = (e) => {
|
|
24
|
+
if (e.key === "Tab") {
|
|
25
|
+
this._hadKeyboardFocus = true;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
this._handleDocumentMousedown = () => {
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
this._hadKeyboardFocus = false;
|
|
32
|
+
}, 0);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
connectedCallback() {
|
|
37
|
+
super.connectedCallback();
|
|
38
|
+
document.addEventListener("keydown", this._handleDocumentKeydown);
|
|
39
|
+
document.addEventListener("mousedown", this._handleDocumentMousedown);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
super.disconnectedCallback();
|
|
44
|
+
document.removeEventListener("keydown", this._handleDocumentKeydown);
|
|
45
|
+
document.removeEventListener("mousedown", this._handleDocumentMousedown);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
handleKeydown(e) {
|
|
49
|
+
if (this.disabled) return;
|
|
50
|
+
if (e.key === " " || e.key === "Enter") {
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
this.handleChange();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
handleFocus(e) {
|
|
57
|
+
if (this._hadKeyboardFocus) {
|
|
58
|
+
e.target.classList.add("focus");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
handleBlur(e) {
|
|
62
|
+
e.target.classList.remove("focus");
|
|
63
|
+
}
|
|
64
|
+
handleChange() {
|
|
65
|
+
if (this.disabled) {
|
|
66
|
+
console.warn("Blocked because disabled = true");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.checked = true;
|
|
71
|
+
|
|
72
|
+
this.updateComplete.then(() => {
|
|
73
|
+
const outer = this.renderRoot.querySelector(".bd-outer");
|
|
74
|
+
if (outer) {
|
|
75
|
+
outer.focus();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.dispatchEvent(
|
|
80
|
+
new CustomEvent("change", {
|
|
81
|
+
detail: { value: this.value },
|
|
82
|
+
bubbles: true,
|
|
83
|
+
composed: true,
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
render() {
|
|
89
|
+
return html`
|
|
90
|
+
<label class="bd-radio ${this.disabled ? "disabled" : ""}">
|
|
91
|
+
<span
|
|
92
|
+
class="bd-outer ${this.checked && !this.disabled ? "checked" : ""}"
|
|
93
|
+
role="radio"
|
|
94
|
+
aria-checked="${this.checked}"
|
|
95
|
+
aria-disabled="${this.disabled}"
|
|
96
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
97
|
+
@click=${this.handleChange}
|
|
98
|
+
@keydown=${this.handleKeydown}
|
|
99
|
+
@focus=${this.handleFocus}
|
|
100
|
+
@blur=${this.handleBlur}
|
|
101
|
+
>
|
|
102
|
+
<span class="bd-inner ${this.checked ? "visible" : ""}"></span>
|
|
103
|
+
</span>
|
|
104
|
+
<span class="radio-label">${this.label}</span>
|
|
105
|
+
</label>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
class BdToggleRadio extends LitElement {
|
|
111
|
+
static styles = [radioCSS];
|
|
112
|
+
|
|
113
|
+
static properties = {
|
|
114
|
+
name: { type: String },
|
|
115
|
+
value: { type: String },
|
|
116
|
+
checked: { type: Boolean, reflect: true },
|
|
117
|
+
disabled: { type: Boolean, reflect: true },
|
|
118
|
+
label: { type: String },
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
constructor() {
|
|
122
|
+
super();
|
|
123
|
+
this.name = "";
|
|
124
|
+
this.value = "";
|
|
125
|
+
this.disabled = false;
|
|
126
|
+
this.label = "";
|
|
127
|
+
this._hadKeyboardFocus = false;
|
|
128
|
+
|
|
129
|
+
this._handleDocumentKeydown = (e) => {
|
|
130
|
+
if (e.key === "Tab") {
|
|
131
|
+
this._hadKeyboardFocus = true;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
this._handleDocumentMousedown = () => {
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
this._hadKeyboardFocus = false;
|
|
138
|
+
}, 0);
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
connectedCallback() {
|
|
143
|
+
super.connectedCallback();
|
|
144
|
+
document.addEventListener("keydown", this._handleDocumentKeydown);
|
|
145
|
+
document.addEventListener("mousedown", this._handleDocumentMousedown);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
disconnectedCallback() {
|
|
149
|
+
super.disconnectedCallback();
|
|
150
|
+
document.removeEventListener("keydown", this._handleDocumentKeydown);
|
|
151
|
+
document.removeEventListener("mousedown", this._handleDocumentMousedown);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
handleClick() {
|
|
155
|
+
if (this.disabled) return;
|
|
156
|
+
this.checked = !this.checked;
|
|
157
|
+
|
|
158
|
+
this.dispatchEvent(
|
|
159
|
+
new CustomEvent("change", {
|
|
160
|
+
detail: { value: this.checked ? this.value : null },
|
|
161
|
+
bubbles: true,
|
|
162
|
+
composed: true,
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
handleFocus(e) {
|
|
168
|
+
if (this._hadKeyboardFocus) {
|
|
169
|
+
e.target.classList.add("focus");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
handleBlur(e) {
|
|
174
|
+
e.target.classList.remove("focus");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
handleKeydown(e) {
|
|
178
|
+
if (this.disabled) return;
|
|
179
|
+
if (e.key === " " || e.key === "Enter") {
|
|
180
|
+
e.preventDefault();
|
|
181
|
+
this.handleClick();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
handleClick() {
|
|
186
|
+
if (this.disabled) return;
|
|
187
|
+
this.checked = !this.checked;
|
|
188
|
+
|
|
189
|
+
this.dispatchEvent(
|
|
190
|
+
new CustomEvent("change", {
|
|
191
|
+
detail: { value: this.checked ? this.value : null },
|
|
192
|
+
bubbles: true,
|
|
193
|
+
composed: true,
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
render() {
|
|
198
|
+
return html`
|
|
199
|
+
<label class="bd-radio ${this.disabled ? "disabled" : ""}">
|
|
200
|
+
<span
|
|
201
|
+
class="bd-outer ${this.checked && !this.disabled ? "checked" : ""}"
|
|
202
|
+
role="checkbox"
|
|
203
|
+
aria-checked="${this.checked}"
|
|
204
|
+
aria-disabled="${this.disabled}"
|
|
205
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
206
|
+
@click=${this.handleClick}
|
|
207
|
+
@keydown=${this.handleKeydown}
|
|
208
|
+
@focus=${this.handleFocus}
|
|
209
|
+
@blur=${this.handleBlur}
|
|
210
|
+
>
|
|
211
|
+
<span class="bd-inner ${this.checked ? "visible" : ""}"></span>
|
|
212
|
+
</span>
|
|
213
|
+
<span class="radio-label">${this.label}</span>
|
|
214
|
+
</label>
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
BdRadio.styles = [radioCSS];
|
|
219
|
+
BdToggleRadio.styles = [radioCSS];
|
|
220
|
+
|
|
221
|
+
customElements.define("bd-toggle-radio", BdToggleRadio);
|
|
222
|
+
customElements.define("bd-radio", BdRadio);
|