@repobit/dex-system-design 0.5.0 → 0.6.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/package.json +4 -3
  3. package/src/assets/images/bd-header-img.jpg +0 -0
  4. package/src/assets/images/bd-header-us.jpg +0 -0
  5. package/src/components/Button/Button.js +115 -3
  6. package/src/components/Button/button.css.js +80 -43
  7. package/src/components/Button/button.stories.js +83 -7
  8. package/src/components/FAQ/faq.css.js +27 -16
  9. package/src/components/FAQ/faq.js +23 -114
  10. package/src/components/FAQ/faq.stories.js +41 -20
  11. package/src/components/Input/Input.js +2 -2
  12. package/src/components/Input/input.css.js +1 -1
  13. package/src/components/anchor/anchor-nav.css.js +92 -0
  14. package/src/components/anchor/anchor-nav.js +121 -0
  15. package/src/components/anchor/anchor.stories.js +134 -0
  16. package/src/components/badge/badge.css.js +27 -0
  17. package/src/components/badge/badge.js +30 -0
  18. package/src/components/badge/badge.stories.js +36 -0
  19. package/src/components/carousel/carousel.css.js +36 -19
  20. package/src/components/carousel/carousel.js +149 -99
  21. package/src/components/carousel/carousel.stories.js +202 -46
  22. package/src/components/checkbox/checkbox.css.js +132 -0
  23. package/src/components/checkbox/checkbox.js +130 -0
  24. package/src/components/checkbox/checkbox.stories.js +63 -0
  25. package/src/components/divider/divider-horizontal.js +29 -0
  26. package/src/components/divider/divider-vertical.js +32 -0
  27. package/src/components/divider/divider.css.js +0 -0
  28. package/src/components/divider/divider.stories.js +77 -0
  29. package/src/components/header/header.css.js +248 -0
  30. package/src/components/header/header.js +87 -0
  31. package/src/components/header/header.stories.js +57 -0
  32. package/src/components/highlight/highlight-s.css.js +88 -0
  33. package/src/components/highlight/highlight-s.js +35 -0
  34. package/src/components/highlight/highlight-s.stories.js +22 -0
  35. package/src/components/highlight/highlight.css.js +119 -0
  36. package/src/components/highlight/highlight.js +60 -0
  37. package/src/components/highlight/highlight.stories.js +53 -0
  38. package/src/components/light-carousel/light-carousel.css.js +18 -10
  39. package/src/components/light-carousel/light-carousel.js +29 -16
  40. package/src/components/light-carousel/light-carousel.stories.js +9 -7
  41. package/src/components/paragraph/paragraph.css.js +1 -1
  42. package/src/components/pricing-cards/pricing-card.css.js +138 -3
  43. package/src/components/pricing-cards/pricing-card.js +63 -82
  44. package/src/components/pricing-cards/pricing-card.stories.js +1 -0
  45. package/src/components/radio/radio.css.js +168 -0
  46. package/src/components/radio/radio.js +222 -0
  47. package/src/components/radio/radio.stories.js +103 -0
  48. package/src/components/tabs/tabs.css.js +26 -8
  49. package/src/components/tabs/tabs.js +19 -12
  50. package/src/components/termsOfUse/terms.css.js +7 -1
  51. package/src/tokens/fonts.stories.js +73 -0
  52. package/src/tokens/spacing.stories.js +56 -0
  53. package/src/tokens/tokens-grid.stories.js +83 -0
  54. package/src/tokens/tokens.css +116 -1
  55. package/src/tokens/tokens.stories.js +67 -0
  56. package/src/tokens/typography.stories.js +69 -0
  57. package/src/tokens/tokens.js +0 -206
  58. /package/src/assets/{icons → images}/tabs-img1.png +0 -0
  59. /package/src/assets/{icons → images}/tabs-img2.png +0 -0
  60. /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/button/button.js";
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.planType === "individual"
159
- ? html`
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="src/assets/icons/badge-icon-individual.png"
169
- alt="icon"
170
- class="badge-icon"
171
- />
172
- Individual</span
173
- >
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
192
- label="Buy Now"
193
- kind="danger"
194
- size="md"
195
- fullWidth
196
- strong
197
- >Buy Now</bd-button>
198
-
199
- <bd-button
200
- label="Learn More"
201
- kind="outline"
202
- size="md"
203
- fullWidth
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="src/assets/icons/bd-icon-family-white.png"
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="src/assets/icons/bd-icon-user.png"
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="src/assets/icons/bd-icon-family.png"
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="src/assets/icons/verified_arrow.png"
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="src/assets/icons/verified_arrow.png"
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="src/assets/icons/badge-icon-individual.png"
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="src/assets/icons/verified_arrow.png"
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="src/assets/icons/badge-icon-individual.png"
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="src/assets/icons/verified_arrow.png"
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="src/assets/icons/badge-icon-individual.png"
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="src/assets/icons/verified_arrow.png"
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="src/assets/icons/badge-icon-individual.png"
703
+ src="icons/badge-icon-individual.png"
723
704
  alt="icon"
724
705
  class="badge-feature-icon"
725
706
  /></span>`
@@ -4,6 +4,7 @@ import './pricing-card.js';
4
4
  export default {
5
5
  title: 'Components/Pricing Cards',
6
6
  component: 'bd-pricing-container',
7
+ tags: ["autodocs"],
7
8
  };
8
9
 
9
10
  const Template = () => html`<bd-pricing-container></bd-pricing-container>`;
@@ -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);