mtrl 0.2.5 → 0.2.7

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 (196) hide show
  1. package/index.ts +18 -0
  2. package/package.json +1 -1
  3. package/src/components/badge/_styles.scss +123 -115
  4. package/src/components/badge/api.ts +57 -59
  5. package/src/components/badge/badge.ts +16 -2
  6. package/src/components/badge/config.ts +65 -11
  7. package/src/components/badge/constants.ts +22 -12
  8. package/src/components/badge/features.ts +44 -40
  9. package/src/components/badge/types.ts +42 -30
  10. package/src/components/bottom-app-bar/_styles.scss +103 -0
  11. package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
  12. package/src/components/bottom-app-bar/config.ts +73 -0
  13. package/src/components/bottom-app-bar/index.ts +11 -0
  14. package/src/components/bottom-app-bar/types.ts +108 -0
  15. package/src/components/button/_styles.scss +0 -66
  16. package/src/components/button/api.ts +5 -0
  17. package/src/components/button/button.ts +0 -2
  18. package/src/components/button/config.ts +5 -0
  19. package/src/components/button/constants.ts +0 -6
  20. package/src/components/button/index.ts +2 -2
  21. package/src/components/button/types.ts +7 -7
  22. package/src/components/card/_styles.scss +67 -25
  23. package/src/components/card/api.ts +54 -3
  24. package/src/components/card/card.ts +25 -6
  25. package/src/components/card/config.ts +189 -22
  26. package/src/components/card/constants.ts +20 -19
  27. package/src/components/card/content.ts +299 -2
  28. package/src/components/card/features.ts +158 -4
  29. package/src/components/card/index.ts +31 -9
  30. package/src/components/card/types.ts +166 -15
  31. package/src/components/checkbox/_styles.scss +0 -2
  32. package/src/components/chip/chip.ts +1 -9
  33. package/src/components/chip/constants.ts +0 -10
  34. package/src/components/chip/index.ts +1 -1
  35. package/src/components/chip/types.ts +1 -4
  36. package/src/components/datepicker/_styles.scss +358 -0
  37. package/src/components/datepicker/api.ts +272 -0
  38. package/src/components/datepicker/config.ts +144 -0
  39. package/src/components/datepicker/constants.ts +98 -0
  40. package/src/components/datepicker/datepicker.ts +346 -0
  41. package/src/components/datepicker/index.ts +9 -0
  42. package/src/components/datepicker/render.ts +452 -0
  43. package/src/components/datepicker/types.ts +268 -0
  44. package/src/components/datepicker/utils.ts +290 -0
  45. package/src/components/dialog/_styles.scss +174 -128
  46. package/src/components/dialog/api.ts +48 -13
  47. package/src/components/dialog/config.ts +9 -5
  48. package/src/components/dialog/dialog.ts +6 -3
  49. package/src/components/dialog/features.ts +290 -130
  50. package/src/components/dialog/types.ts +7 -4
  51. package/src/components/divider/_styles.scss +57 -0
  52. package/src/components/divider/config.ts +81 -0
  53. package/src/components/divider/divider.ts +37 -0
  54. package/src/components/divider/features.ts +207 -0
  55. package/src/components/divider/index.ts +5 -0
  56. package/src/components/divider/types.ts +55 -0
  57. package/src/components/extended-fab/_styles.scss +267 -0
  58. package/src/components/extended-fab/api.ts +141 -0
  59. package/src/components/extended-fab/config.ts +108 -0
  60. package/src/components/extended-fab/constants.ts +36 -0
  61. package/src/components/extended-fab/extended-fab.ts +125 -0
  62. package/src/components/extended-fab/index.ts +4 -0
  63. package/src/components/extended-fab/types.ts +287 -0
  64. package/src/components/fab/_styles.scss +225 -0
  65. package/src/components/fab/api.ts +97 -0
  66. package/src/components/fab/config.ts +94 -0
  67. package/src/components/fab/constants.ts +41 -0
  68. package/src/components/fab/fab.ts +67 -0
  69. package/src/components/fab/index.ts +4 -0
  70. package/src/components/fab/types.ts +234 -0
  71. package/src/components/navigation/_styles.scss +1 -0
  72. package/src/components/navigation/api.ts +78 -50
  73. package/src/components/navigation/features/items.ts +280 -0
  74. package/src/components/navigation/nav-item.ts +72 -23
  75. package/src/components/navigation/navigation.ts +54 -2
  76. package/src/components/navigation/types.ts +210 -188
  77. package/src/components/progress/_styles.scss +0 -65
  78. package/src/components/progress/config.ts +1 -2
  79. package/src/components/progress/constants.ts +0 -14
  80. package/src/components/progress/index.ts +1 -1
  81. package/src/components/progress/progress.ts +1 -4
  82. package/src/components/progress/types.ts +1 -4
  83. package/src/components/radios/_styles.scss +0 -45
  84. package/src/components/radios/api.ts +85 -60
  85. package/src/components/radios/config.ts +1 -2
  86. package/src/components/radios/constants.ts +0 -9
  87. package/src/components/radios/index.ts +1 -1
  88. package/src/components/radios/radio.ts +34 -11
  89. package/src/components/radios/radios.ts +2 -1
  90. package/src/components/radios/types.ts +1 -7
  91. package/src/components/search/_styles.scss +306 -0
  92. package/src/components/search/api.ts +203 -0
  93. package/src/components/search/config.ts +87 -0
  94. package/src/components/search/constants.ts +21 -0
  95. package/src/components/search/features/index.ts +4 -0
  96. package/src/components/search/features/search.ts +718 -0
  97. package/src/components/search/features/states.ts +165 -0
  98. package/src/components/search/features/structure.ts +198 -0
  99. package/src/components/search/index.ts +10 -0
  100. package/src/components/search/search.ts +52 -0
  101. package/src/components/search/types.ts +163 -0
  102. package/src/components/segmented-button/_styles.scss +117 -0
  103. package/src/components/segmented-button/config.ts +67 -0
  104. package/src/components/segmented-button/constants.ts +42 -0
  105. package/src/components/segmented-button/index.ts +4 -0
  106. package/src/components/segmented-button/segment.ts +155 -0
  107. package/src/components/segmented-button/segmented-button.ts +250 -0
  108. package/src/components/segmented-button/types.ts +219 -0
  109. package/src/components/slider/_styles.scss +221 -168
  110. package/src/components/slider/accessibility.md +59 -0
  111. package/src/components/slider/api.ts +41 -120
  112. package/src/components/slider/config.ts +51 -49
  113. package/src/components/slider/features/handlers.ts +495 -0
  114. package/src/components/slider/features/index.ts +1 -2
  115. package/src/components/slider/features/slider.ts +66 -84
  116. package/src/components/slider/features/states.ts +195 -0
  117. package/src/components/slider/features/structure.ts +141 -184
  118. package/src/components/slider/features/ui.ts +150 -201
  119. package/src/components/slider/index.ts +2 -11
  120. package/src/components/slider/slider.ts +9 -12
  121. package/src/components/slider/types.ts +39 -24
  122. package/src/components/switch/_styles.scss +0 -2
  123. package/src/components/tabs/_styles.scss +346 -154
  124. package/src/components/tabs/api.ts +178 -400
  125. package/src/components/tabs/config.ts +46 -52
  126. package/src/components/tabs/constants.ts +85 -8
  127. package/src/components/tabs/features.ts +403 -0
  128. package/src/components/tabs/index.ts +60 -3
  129. package/src/components/tabs/indicator.ts +285 -0
  130. package/src/components/tabs/responsive.ts +144 -0
  131. package/src/components/tabs/scroll-indicators.ts +149 -0
  132. package/src/components/tabs/state.ts +186 -0
  133. package/src/components/tabs/tab-api.ts +258 -0
  134. package/src/components/tabs/tab.ts +255 -0
  135. package/src/components/tabs/tabs.ts +50 -31
  136. package/src/components/tabs/types.ts +332 -128
  137. package/src/components/tabs/utils.ts +107 -0
  138. package/src/components/textfield/_styles.scss +0 -98
  139. package/src/components/textfield/config.ts +2 -3
  140. package/src/components/textfield/constants.ts +0 -14
  141. package/src/components/textfield/index.ts +2 -2
  142. package/src/components/textfield/textfield.ts +0 -2
  143. package/src/components/textfield/types.ts +1 -4
  144. package/src/components/timepicker/README.md +277 -0
  145. package/src/components/timepicker/_styles.scss +451 -0
  146. package/src/components/timepicker/api.ts +632 -0
  147. package/src/components/timepicker/clockdial.ts +482 -0
  148. package/src/components/timepicker/config.ts +130 -0
  149. package/src/components/timepicker/constants.ts +138 -0
  150. package/src/components/timepicker/index.ts +8 -0
  151. package/src/components/timepicker/render.ts +613 -0
  152. package/src/components/timepicker/timepicker.ts +117 -0
  153. package/src/components/timepicker/types.ts +336 -0
  154. package/src/components/timepicker/utils.ts +241 -0
  155. package/src/components/top-app-bar/_styles.scss +225 -0
  156. package/src/components/top-app-bar/config.ts +83 -0
  157. package/src/components/top-app-bar/index.ts +11 -0
  158. package/src/components/top-app-bar/top-app-bar.ts +316 -0
  159. package/src/components/top-app-bar/types.ts +140 -0
  160. package/src/core/build/_ripple.scss +6 -6
  161. package/src/core/build/ripple.ts +72 -95
  162. package/src/core/compose/component.ts +1 -1
  163. package/src/core/compose/features/badge.ts +79 -0
  164. package/src/core/compose/features/icon.ts +3 -1
  165. package/src/core/compose/features/index.ts +3 -1
  166. package/src/core/compose/features/ripple.ts +4 -1
  167. package/src/core/compose/features/textlabel.ts +26 -2
  168. package/src/core/dom/create.ts +5 -0
  169. package/src/index.ts +9 -0
  170. package/src/styles/abstract/_theme.scss +115 -3
  171. package/src/styles/themes/_autumn.scss +21 -0
  172. package/src/styles/themes/_base-theme.scss +61 -0
  173. package/src/styles/themes/_baseline.scss +58 -0
  174. package/src/styles/themes/_bluekhaki.scss +125 -0
  175. package/src/styles/themes/_brownbeige.scss +125 -0
  176. package/src/styles/themes/_browngreen.scss +125 -0
  177. package/src/styles/themes/_forest.scss +6 -0
  178. package/src/styles/themes/_greenbeige.scss +125 -0
  179. package/src/styles/themes/_material.scss +125 -0
  180. package/src/styles/themes/_ocean.scss +6 -0
  181. package/src/styles/themes/_sageivory.scss +125 -0
  182. package/src/styles/themes/_spring.scss +6 -0
  183. package/src/styles/themes/_summer.scss +5 -0
  184. package/src/styles/themes/_sunset.scss +5 -0
  185. package/src/styles/themes/_tealcaramel.scss +125 -0
  186. package/src/styles/themes/_winter.scss +6 -0
  187. package/src/components/card/actions.ts +0 -48
  188. package/src/components/card/header.ts +0 -88
  189. package/src/components/card/media.ts +0 -52
  190. package/src/components/navigation/features/items.js +0 -192
  191. package/src/components/slider/features/appearance.ts +0 -94
  192. package/src/components/slider/features/disabled.ts +0 -43
  193. package/src/components/slider/features/events.ts +0 -164
  194. package/src/components/slider/features/interactions.ts +0 -261
  195. package/src/components/slider/features/keyboard.ts +0 -112
  196. package/src/core/collection/adapters/mongodb.js +0 -232
package/index.ts CHANGED
@@ -3,23 +3,32 @@ import {
3
3
  createLayout,
4
4
  createElement,
5
5
  createBadge,
6
+ createBottomAppBar,
6
7
  createButton,
8
+ createDatePicker,
9
+ createFab,
10
+ createExtendedFab,
11
+ createSegmentedButton,
7
12
  createCard,
8
13
  createCarousel,
9
14
  createCheckbox,
10
15
  createChip,
11
16
  createDialog,
17
+ createDivider,
12
18
  createList,
13
19
  createMenu,
14
20
  createNavigation,
15
21
  createProgress,
16
22
  createRadios,
23
+ createSearch,
17
24
  createSheet,
18
25
  createSlider,
19
26
  createSnackbar,
20
27
  createTabs,
21
28
  createTextfield,
29
+ createTimePicker,
22
30
  createTooltip,
31
+ createTopAppBar,
23
32
  createSwitch
24
33
  } from './src/index.js'
25
34
 
@@ -27,22 +36,31 @@ export {
27
36
  createLayout,
28
37
  createElement,
29
38
  createBadge,
39
+ createBottomAppBar,
30
40
  createButton,
41
+ createDatePicker,
42
+ createFab,
43
+ createExtendedFab,
44
+ createSegmentedButton,
31
45
  createCard,
32
46
  createCarousel,
33
47
  createCheckbox,
34
48
  createChip,
35
49
  createDialog,
50
+ createDivider,
36
51
  createList,
37
52
  createMenu,
38
53
  createNavigation,
39
54
  createProgress,
40
55
  createRadios,
56
+ createSearch,
41
57
  createSheet,
42
58
  createSlider,
43
59
  createSnackbar,
44
60
  createTabs,
45
61
  createTextfield,
62
+ createTimePicker,
46
63
  createTooltip,
64
+ createTopAppBar,
47
65
  createSwitch
48
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtrl",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A functional TypeScript/JavaScript component library with composable architecture based on Material Design 3",
5
5
  "keywords": [
6
6
  "component",
@@ -1,96 +1,130 @@
1
- // src/components/badge/_styles.scss
1
+ // src/components/badge/_badge.scss
2
2
  @use '../../styles/abstract/base' as base;
3
3
  @use '../../styles/abstract/variables' as v;
4
4
  @use '../../styles/abstract/functions' as f;
5
5
  @use '../../styles/abstract/mixins' as m;
6
6
  @use '../../styles/abstract/theme' as t;
7
7
 
8
+ /**
9
+ * Badge component styles
10
+ *
11
+ * Badge specifications:
12
+ * - Small badge size: 6dp
13
+ * - Large badge height: 16dp
14
+ * - Small badge corner radius: 3dp
15
+ * - Large badge corner radius: 8dp
16
+ * - Small badge: positioned 6dp from container edge
17
+ * - Large badge: positioned 14dp (height) x 12dp (width) from container edge
18
+ */
8
19
  $component: '#{base.$prefix}-badge';
20
+ $wrapper: '#{base.$prefix}-badge-wrapper';
9
21
 
10
- .#{$component} {
11
- // Base styles
22
+ // Wrapper styles to establish positioning context
23
+ .#{$wrapper} {
12
24
  position: relative;
13
25
  display: inline-flex;
26
+ flex-shrink: 0;
27
+ }
28
+
29
+ .#{$component} {
30
+ // Base badge styles
31
+ position: absolute;
32
+ display: flex;
14
33
  align-items: center;
15
34
  justify-content: center;
16
- box-sizing: border-box;
17
- min-width: 20px;
18
- height: 20px;
19
- padding: 0 6px;
20
- border-radius: 10px;
21
- background-color: t.color('error');
22
- color: t.color('on-error');
23
- font-size: 11px;
24
35
  font-weight: 500;
25
- line-height: 1;
26
- letter-spacing: 0.5px;
27
- white-space: nowrap;
28
- text-align: center;
29
-
30
- // Badge parent wrapper
31
- &-wrapper {
32
- position: relative;
33
- display: inline-flex;
34
- }
36
+ box-sizing: border-box;
37
+ overflow: hidden;
38
+ transition: all 200ms ease;
39
+ text-overflow: ellipsis;
35
40
 
36
- // Default positioning (top-right)
37
- &--positioned {
38
- position: absolute;
39
- top: -8px;
40
- right: -8px;
41
- transform: translate(50%, -50%);
41
+ // Hide for visibility: false
42
+ &--invisible {
43
+ display: none;
42
44
  }
43
45
 
44
- // Dot variant
45
- &--dot {
46
- min-width: 8px;
47
- height: 8px;
46
+ // Small badge (dot)
47
+ &--small {
48
+ width: 6px;
49
+ height: 6px;
50
+ min-width: 6px;
51
+ border-radius: 3px; // 3dp corner radius
52
+ font-size: 0;
48
53
  padding: 0;
49
- border-radius: 50%;
50
54
  }
51
55
 
52
- // Small size
53
- &--small {
54
- min-width: 16px;
56
+ // Large badge
57
+ &--large {
55
58
  height: 16px;
56
- font-size: 10px;
59
+ min-width: 16px;
60
+ border-radius: 8px; // 8dp corner radius
57
61
  padding: 0 4px;
62
+ font-size: 11px;
63
+ line-height: 16px;
64
+
65
+ // Handle max character count container (16dp x 34dp)
66
+ &.#{$component}--overflow {
67
+ min-width: auto;
68
+ max-width: 34px; // max width is 34dp for overflow badges
69
+ padding: 0 4px;
70
+ }
58
71
  }
59
72
 
60
- // Large size
61
- &--large {
62
- min-width: 24px;
63
- height: 24px;
64
- font-size: 12px;
65
- padding: 0 8px;
66
- }
67
-
68
- // Position variants
69
- &--top-left {
70
- top: 0;
71
- left: 0;
72
- transform: translate(-50%, -50%);
73
- }
74
-
75
- &--top-right {
76
- top: 0;
77
- right: 0;
78
- transform: translate(50%, -50%);
79
- }
80
-
81
- &--bottom-left {
82
- bottom: 0;
83
- left: 0;
84
- transform: translate(-50%, 50%);
73
+ // Position specs
74
+ &--positioned {
75
+ // Small badge placement (6dp from container edge)
76
+ &.#{$component}--small {
77
+ &.#{$component}--top-right {
78
+ top: -3px;
79
+ right: -3px;
80
+ }
81
+
82
+ &.#{$component}--top-left {
83
+ top: -3px;
84
+ left: -3px;
85
+ }
86
+
87
+ &.#{$component}--bottom-right {
88
+ bottom: -3px;
89
+ right: -3px;
90
+ }
91
+
92
+ &.#{$component}--bottom-left {
93
+ bottom: -3px;
94
+ left: -3px;
95
+ }
96
+ }
97
+
98
+ // Large badge placement (14dp x 12dp from container edge)
99
+ &.#{$component}--large {
100
+ &.#{$component}--top-right {
101
+ top: -8px;
102
+ right: -8px;
103
+ }
104
+
105
+ &.#{$component}--top-left {
106
+ top: -8px;
107
+ left: -8px;
108
+ }
109
+
110
+ &.#{$component}--bottom-right {
111
+ bottom: -8px;
112
+ right: -8px;
113
+ }
114
+
115
+ &.#{$component}--bottom-left {
116
+ bottom: -8px;
117
+ left: -8px;
118
+ }
119
+ }
85
120
  }
86
121
 
87
- &--bottom-right {
88
- bottom: 0;
89
- right: 0;
90
- transform: translate(50%, 50%);
122
+ // badge color system
123
+ &--error {
124
+ background-color: t.color('error');
125
+ color: t.color('on-error');
91
126
  }
92
127
 
93
- // Color variants
94
128
  &--primary {
95
129
  background-color: t.color('primary');
96
130
  color: t.color('on-primary');
@@ -106,69 +140,43 @@ $component: '#{base.$prefix}-badge';
106
140
  color: t.color('on-tertiary');
107
141
  }
108
142
 
109
- &--error {
110
- background-color: t.color('error');
111
- color: t.color('on-error');
112
- }
113
-
114
143
  &--success {
115
- background-color: t.color('success', t.color('primary'));
116
- color: t.color('on-success', t.color('on-primary'));
144
+ background-color: t.color('success');
145
+ color: t.color('on-success');
117
146
  }
118
147
 
119
148
  &--warning {
120
- background-color: t.color('warning', t.color('tertiary'));
121
- color: t.color('on-warning', t.color('on-tertiary'));
149
+ background-color: t.color('warning');
150
+ color: t.color('on-warning');
122
151
  }
123
152
 
124
153
  &--info {
125
- background-color: t.color('info', t.color('secondary'));
126
- color: t.color('on-info', t.color('on-secondary'));
154
+ background-color: t.color('info');
155
+ color: t.color('on-info');
127
156
  }
128
-
129
- // Outline variant
130
- &--outlined {
131
- background-color: transparent;
132
- border: 1px solid currentColor;
133
-
134
- &.#{$component}--primary {
135
- color: t.color('primary');
136
- }
137
-
138
- &.#{$component}--secondary {
139
- color: t.color('secondary');
140
- }
141
-
142
- &.#{$component}--tertiary {
143
- color: t.color('tertiary');
144
- }
145
-
146
- &.#{$component}--error {
147
- color: t.color('error');
157
+ }
158
+
159
+ // RTL support
160
+ [dir="rtl"] {
161
+ .#{$component}--positioned {
162
+ &.#{$component}--top-right {
163
+ right: auto;
164
+ left: -8px;
148
165
  }
149
166
 
150
- &.#{$component}--success {
151
- color: t.color('success', t.color('primary'));
167
+ &.#{$component}--top-left {
168
+ left: auto;
169
+ right: -8px;
152
170
  }
153
171
 
154
- &.#{$component}--warning {
155
- color: t.color('warning', t.color('tertiary'));
172
+ &.#{$component}--bottom-right {
173
+ right: auto;
174
+ left: -8px;
156
175
  }
157
176
 
158
- &.#{$component}--info {
159
- color: t.color('info', t.color('secondary'));
177
+ &.#{$component}--bottom-left {
178
+ left: auto;
179
+ right: -8px;
160
180
  }
161
181
  }
162
-
163
- // Max value handling
164
- &--max {
165
- &::after {
166
- content: '+';
167
- }
168
- }
169
-
170
- // Invisible
171
- &--invisible {
172
- display: none;
173
- }
174
182
  }
@@ -1,6 +1,11 @@
1
1
  // src/components/badge/api.ts
2
2
  import { BadgeComponent } from './types';
3
- import { BADGE_VARIANTS, BADGE_SIZES, BADGE_COLORS, BADGE_POSITIONS } from './constants';
3
+ import {
4
+ BADGE_VARIANTS,
5
+ BADGE_COLORS,
6
+ BADGE_POSITIONS
7
+ } from './constants';
8
+ import { formatBadgeLabel } from './config';
4
9
 
5
10
  interface ApiOptions {
6
11
  visibility: {
@@ -19,7 +24,8 @@ interface ComponentWithElements {
19
24
  wrapper?: HTMLElement;
20
25
  config: {
21
26
  max?: number;
22
- content?: string | number;
27
+ label?: string | number;
28
+ variant?: string;
23
29
  };
24
30
  getClass: (name: string) => string;
25
31
  addClass: (...classes: string[]) => any;
@@ -39,27 +45,33 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
39
45
  ...component as any,
40
46
 
41
47
  /**
42
- * Sets the badge content
43
- * @param {string|number} content - Content to display in the badge
48
+ * Sets the badge label
49
+ * @param {string|number} label - Label to display in the badge
44
50
  * @returns {BadgeComponent} Badge component instance for chaining
45
51
  */
46
- setContent(content: string | number) {
47
- const stringContent = String(content);
48
- component.config.content = content;
52
+ setLabel(label: string | number) {
53
+ component.config.label = label;
49
54
 
50
- // If max is defined and content is a number greater than max, show max+
51
- if (component.config.max !== undefined &&
52
- typeof content === 'number' &&
53
- content > component.config.max) {
54
- component.element.textContent = String(component.config.max);
55
- component.element.classList.add(`${component.getClass('badge')}--max`);
56
- } else {
57
- component.element.textContent = stringContent;
58
- component.element.classList.remove(`${component.getClass('badge')}--max`);
55
+ // Small badges (dot variant) don't have text
56
+ if (component.config.variant === BADGE_VARIANTS.SMALL) {
57
+ component.element.textContent = '';
58
+ return this;
59
+ }
60
+
61
+ // Format the label
62
+ const formattedLabel = formatBadgeLabel(label, component.config.max);
63
+ component.element.textContent = formattedLabel;
64
+
65
+ // Add overflow class if label was truncated
66
+ component.element.classList.remove(`${component.getClass('badge')}--overflow`);
67
+ if (typeof label === 'number' &&
68
+ component.config.max !== undefined &&
69
+ label > component.config.max) {
70
+ component.element.classList.add(`${component.getClass('badge')}--overflow`);
59
71
  }
60
72
 
61
- // Toggle the dot variant based on whether content is empty
62
- if (stringContent === '' || stringContent === '0') {
73
+ // Toggle visibility based on whether label is empty
74
+ if (formattedLabel === '' || formattedLabel === '0') {
63
75
  this.hide();
64
76
  } else {
65
77
  this.show();
@@ -69,10 +81,10 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
69
81
  },
70
82
 
71
83
  /**
72
- * Gets the badge content
73
- * @returns {string} Current badge content
84
+ * Gets the badge label
85
+ * @returns {string} Current badge label
74
86
  */
75
- getContent() {
87
+ getLabel() {
76
88
  return component.element.textContent || '';
77
89
  },
78
90
 
@@ -114,19 +126,16 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
114
126
 
115
127
  /**
116
128
  * Sets maximum value (after which badge shows max+)
129
+ *
117
130
  * @param {number} max - Maximum value to display
118
131
  * @returns {BadgeComponent} Badge component instance for chaining
119
132
  */
120
133
  setMax(max: number) {
121
134
  component.config.max = max;
122
135
 
123
- // Apply max formatting if current content exceeds max
124
- if (typeof component.config.content === 'number' &&
125
- component.config.content > max) {
126
- component.element.textContent = String(max);
127
- component.element.classList.add(`${component.getClass('badge')}--max`);
128
- } else {
129
- component.element.classList.remove(`${component.getClass('badge')}--max`);
136
+ // Apply max formatting if current label exceeds max
137
+ if (component.config.label !== undefined) {
138
+ this.setLabel(component.config.label);
130
139
  }
131
140
 
132
141
  return this;
@@ -137,7 +146,7 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
137
146
  * @param {string} color - Color variant to apply
138
147
  * @returns {BadgeComponent} Badge component instance for chaining
139
148
  */
140
- setColor(color: keyof typeof BADGE_COLORS | BADGE_COLORS) {
149
+ setColor(color: keyof typeof BADGE_COLORS | (typeof BADGE_COLORS)[keyof typeof BADGE_COLORS]) {
141
150
  // Remove existing color classes
142
151
  Object.values(BADGE_COLORS).forEach(colorName => {
143
152
  component.element.classList.remove(`${component.getClass('badge')}--${colorName}`);
@@ -150,44 +159,32 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
150
159
 
151
160
  /**
152
161
  * Sets badge variant
153
- * @param {string} variant - Variant to apply
162
+ * @param {string} variant - Variant to apply (small or large)
154
163
  * @returns {BadgeComponent} Badge component instance for chaining
155
164
  */
156
- setVariant(variant: keyof typeof BADGE_VARIANTS | BADGE_VARIANTS) {
165
+ setVariant(variant: keyof typeof BADGE_VARIANTS | (typeof BADGE_VARIANTS)[keyof typeof BADGE_VARIANTS]) {
157
166
  // Remove existing variant classes
158
167
  Object.values(BADGE_VARIANTS).forEach(variantName => {
159
168
  component.element.classList.remove(`${component.getClass('badge')}--${variantName}`);
160
169
  });
161
170
 
162
- // Add new variant class if not standard
163
- if (variant !== BADGE_VARIANTS.STANDARD) {
164
- component.element.classList.add(`${component.getClass('badge')}--${variant}`);
165
- }
171
+ // Add new variant class
172
+ component.element.classList.add(`${component.getClass('badge')}--${variant}`);
166
173
 
167
- // Clear content if dot variant
168
- if (variant === BADGE_VARIANTS.DOT) {
169
- component.element.textContent = '';
170
- } else if (component.config.content !== undefined) {
171
- this.setContent(component.config.content);
172
- }
174
+ // Update component config
175
+ component.config.variant = variant;
173
176
 
174
- return this;
175
- },
176
-
177
- /**
178
- * Sets badge size
179
- * @param {string} size - Size variant to apply
180
- * @returns {BadgeComponent} Badge component instance for chaining
181
- */
182
- setSize(size: keyof typeof BADGE_SIZES | BADGE_SIZES) {
183
- // Remove existing size classes
184
- Object.values(BADGE_SIZES).forEach(sizeName => {
185
- component.element.classList.remove(`${component.getClass('badge')}--${sizeName}`);
186
- });
187
-
188
- // Add new size class if not medium (default)
189
- if (size !== BADGE_SIZES.MEDIUM) {
190
- component.element.classList.add(`${component.getClass('badge')}--${size}`);
177
+ // Update accessibility attributes
178
+ if (variant === BADGE_VARIANTS.SMALL) {
179
+ component.element.textContent = '';
180
+ component.element.setAttribute('aria-hidden', 'true');
181
+ } else {
182
+ component.element.setAttribute('role', 'status');
183
+
184
+ // Restore label for large badges
185
+ if (component.config.label !== undefined) {
186
+ this.setLabel(component.config.label);
187
+ }
191
188
  }
192
189
 
193
190
  return this;
@@ -198,7 +195,7 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
198
195
  * @param {string} position - Position variant to apply
199
196
  * @returns {BadgeComponent} Badge component instance for chaining
200
197
  */
201
- setPosition(position: keyof typeof BADGE_POSITIONS | BADGE_POSITIONS) {
198
+ setPosition(position: keyof typeof BADGE_POSITIONS | (typeof BADGE_POSITIONS)[keyof typeof BADGE_POSITIONS]) {
202
199
  // Remove existing position classes
203
200
  Object.values(BADGE_POSITIONS).forEach(posName => {
204
201
  component.element.classList.remove(`${component.getClass('badge')}--${posName}`);
@@ -224,6 +221,7 @@ export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
224
221
  // Create a new wrapper to hold the target and badge
225
222
  const wrapper = document.createElement('div');
226
223
  wrapper.classList.add(component.getClass('badge-wrapper'));
224
+ wrapper.style.position = 'relative';
227
225
 
228
226
  // Replace the target with the wrapper
229
227
  const parent = target.parentNode;
@@ -9,7 +9,6 @@ import {
9
9
  withVisibility,
10
10
  withVariant,
11
11
  withColor,
12
- withSize,
13
12
  withPosition,
14
13
  withMax,
15
14
  withAttachment
@@ -22,18 +21,33 @@ import { createBaseConfig, getElementConfig, getApiConfig } from './config';
22
21
  * Creates a new Badge component
23
22
  * @param {BadgeConfig} config - Badge configuration object
24
23
  * @returns {BadgeComponent} Badge component instance
24
+ *
25
+ * @example
26
+ * // Create a small dot badge
27
+ * const notificationBadge = createBadge({
28
+ * variant: BADGE_VARIANTS.SMALL,
29
+ * target: document.querySelector('.icon-button')
30
+ * });
31
+ *
32
+ * @example
33
+ * // Create a large badge with a count
34
+ * const countBadge = createBadge({
35
+ * variant: BADGE_VARIANTS.LARGE,
36
+ * label: 5,
37
+ * target: document.querySelector('.notification-icon')
38
+ * });
25
39
  */
26
40
  const createBadge = (config: BadgeConfig = {}): BadgeComponent => {
27
41
  const baseConfig = createBaseConfig(config);
28
42
 
29
43
  try {
44
+ // Compose the badge component from multiple feature enhancers
30
45
  const badge = pipe(
31
46
  createBase,
32
47
  withEvents(),
33
48
  withElement(getElementConfig(baseConfig)),
34
49
  withVariant(baseConfig),
35
50
  withColor(baseConfig),
36
- withSize(baseConfig),
37
51
  withPosition(baseConfig),
38
52
  withMax(baseConfig),
39
53
  withVisibility(),