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
@@ -1,4 +1,4 @@
1
- // src/components/card/_card.scss
1
+ // src/components/card/_styles.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;
@@ -13,23 +13,33 @@ $component: '#{base.$prefix}-card';
13
13
  display: flex;
14
14
  flex-direction: column;
15
15
  box-sizing: border-box;
16
- border-radius: v.shape('medium');
16
+ border-radius: f.get-shape('medium'); // Use function for MD3 standard shape
17
17
  background-color: t.color('surface');
18
18
  color: t.color('on-surface');
19
19
  overflow: hidden;
20
- width: 320px; // Fixed width since v.card() isn't available
21
- --card-elevation: 1;
20
+ width: v.card('width'); // Use card width variable
21
+ --card-elevation: 0;
22
22
 
23
- // Typography
23
+ // Typography - use mixin
24
24
  @include m.typography('body-medium');
25
25
 
26
- // Transition for elevation and hover states
26
+ // Transition for elevation and hover states - use motion-transition mixin
27
27
  @include m.motion-transition(
28
28
  box-shadow,
29
29
  background-color,
30
30
  border-color
31
31
  );
32
32
 
33
+ // Focus outline for accessibility - use focus-ring mixin
34
+ &:focus-visible {
35
+ @include m.focus-ring(t.color('secondary'));
36
+ }
37
+
38
+ // Focus state class
39
+ &--focused {
40
+ @include m.focus-ring(t.color('secondary'));
41
+ }
42
+
33
43
  // Ripple styles for clickable cards
34
44
  .ripple {
35
45
  position: absolute;
@@ -37,7 +47,7 @@ $component: '#{base.$prefix}-card';
37
47
  transform: scale(0);
38
48
  pointer-events: none;
39
49
  background-color: currentColor;
40
- opacity: 0.08;
50
+ opacity: f.get-state-opacity('hover'); // Use function for standard opacity
41
51
  }
42
52
 
43
53
  // Ensure proper stacking for inner components
@@ -45,35 +55,50 @@ $component: '#{base.$prefix}-card';
45
55
  margin-bottom: 0;
46
56
  }
47
57
 
48
- // === Variants ===
58
+ // === Variants - use proper theme colors ===
49
59
 
50
60
  // Elevated variant
51
61
  &--elevated {
52
- @include m.elevation(1);
62
+ background-color: t.color('surface-container-low');
63
+ @include m.elevation(1); // Use elevation mixin
53
64
 
54
65
  &:hover.#{$component}--interactive {
55
- @include m.elevation(2);
66
+ @include m.elevation(2); // Use elevation mixin for hover state
67
+ }
68
+
69
+ &:active.#{$component}--interactive {
70
+ @include m.state-layer(t.color('on-surface'), 'pressed'); // Use state-layer mixin
56
71
  }
57
72
  }
58
73
 
59
74
  // Filled variant
60
75
  &--filled {
61
76
  background-color: t.color('surface-container-highest');
77
+ @include m.elevation(0); // No elevation
62
78
 
63
79
  &:hover.#{$component}--interactive {
64
80
  @include m.state-layer(t.color('on-surface'), 'hover');
65
81
  }
82
+
83
+ &:active.#{$component}--interactive {
84
+ @include m.state-layer(t.color('on-surface'), 'pressed');
85
+ }
66
86
  }
67
87
 
68
88
  // Outlined variant
69
89
  &--outlined {
70
90
  border: 1px solid t.color('outline');
71
91
  background-color: t.color('surface');
92
+ @include m.elevation(0); // No elevation
72
93
 
73
94
  &:hover.#{$component}--interactive {
74
95
  @include m.state-layer(t.color('on-surface'), 'hover');
75
96
  border-color: t.color('outline-variant');
76
97
  }
98
+
99
+ &:active.#{$component}--interactive {
100
+ @include m.state-layer(t.color('on-surface'), 'pressed');
101
+ }
77
102
  }
78
103
 
79
104
  // === Modifiers ===
@@ -95,10 +120,11 @@ $component: '#{base.$prefix}-card';
95
120
  &-header {
96
121
  display: flex;
97
122
  align-items: center;
98
- padding: 16px;
99
-
123
+ padding: v.card('padding');
124
+ padding-bottom: 0;
125
+
100
126
  &-avatar {
101
- margin-right: 16px;
127
+ margin-right: v.card('padding');
102
128
  flex-shrink: 0;
103
129
  display: flex;
104
130
  align-items: center;
@@ -119,7 +145,7 @@ $component: '#{base.$prefix}-card';
119
145
 
120
146
  &-title {
121
147
  margin: 0;
122
- @include m.typography('title-medium');
148
+ @include m.typography('title-large');
123
149
  @include m.truncate;
124
150
  color: t.color('on-surface');
125
151
  }
@@ -141,7 +167,7 @@ $component: '#{base.$prefix}-card';
141
167
  &-media {
142
168
  position: relative;
143
169
  overflow: hidden;
144
-
170
+ border-radius: f.get-shape('medium');
145
171
  &-img {
146
172
  display: block;
147
173
  width: 100%;
@@ -182,7 +208,7 @@ $component: '#{base.$prefix}-card';
182
208
 
183
209
  // Card Content
184
210
  &-content {
185
- padding: 16px;
211
+ padding: v.card('padding');
186
212
  flex: 1 1 auto;
187
213
 
188
214
  > *:first-child {
@@ -195,7 +221,7 @@ $component: '#{base.$prefix}-card';
195
221
 
196
222
  // When content follows media without padding
197
223
  .#{$component}-media + &:not(.#{$component}-content--no-padding) {
198
- padding-top: 16px;
224
+ padding-top: v.card('padding');
199
225
  }
200
226
 
201
227
  // No padding modifier
@@ -276,7 +302,7 @@ $component: '#{base.$prefix}-card';
276
302
 
277
303
  // State classes
278
304
  &--state-disabled {
279
- opacity: 0.38;
305
+ opacity: 0.38; // Use MTRL standard opacity
280
306
  pointer-events: none;
281
307
  }
282
308
 
@@ -285,7 +311,7 @@ $component: '#{base.$prefix}-card';
285
311
  }
286
312
 
287
313
  &--dragging {
288
- @include m.elevation(4);
314
+ @include m.elevation(4); // Use elevation mixin
289
315
  opacity: 0.9;
290
316
  }
291
317
 
@@ -299,15 +325,15 @@ $component: '#{base.$prefix}-card';
299
325
  display: flex;
300
326
  align-items: center;
301
327
  justify-content: center;
302
- background-color: rgba(t.color('surface'), 0.7);
303
- z-index: 1;
328
+ background-color: t.alpha('surface', 0.7);
329
+ z-index: f.get-z-index('default');
304
330
  }
305
331
 
306
332
  &-loading-spinner {
307
333
  width: 40px;
308
334
  height: 40px;
309
335
  border-radius: 50%;
310
- border: 3px solid rgba(t.color('primary'), 0.2);
336
+ border: 3px solid t.alpha('primary', 0.2);
311
337
  border-top-color: t.color('primary');
312
338
  animation: card-spinner 1s infinite linear;
313
339
  }
@@ -315,7 +341,7 @@ $component: '#{base.$prefix}-card';
315
341
  // Expandable content
316
342
  &-expandable-content {
317
343
  overflow: hidden;
318
- transition: max-height 0.3s ease;
344
+ transition: max-height f.get-motion-duration('medium1') f.get-motion-easing('standard');
319
345
  }
320
346
 
321
347
  &-expand-button {
@@ -324,6 +350,9 @@ $component: '#{base.$prefix}-card';
324
350
  padding: 8px;
325
351
  cursor: pointer;
326
352
  color: t.color('primary');
353
+ display: inline-flex;
354
+ align-items: center;
355
+ justify-content: center;
327
356
 
328
357
  &::before {
329
358
  content: '';
@@ -333,7 +362,7 @@ $component: '#{base.$prefix}-card';
333
362
  border-right: 2px solid currentColor;
334
363
  border-bottom: 2px solid currentColor;
335
364
  transform: rotate(45deg);
336
- transition: transform 0.3s ease;
365
+ transition: transform f.get-motion-duration('short2') f.get-motion-easing('standard');
337
366
  }
338
367
 
339
368
  &[aria-expanded="true"]::before {
@@ -344,7 +373,13 @@ $component: '#{base.$prefix}-card';
344
373
  // Swipeable card
345
374
  &--swipeable {
346
375
  touch-action: pan-y;
347
- transition: transform 0.3s ease;
376
+ transition: transform f.get-motion-duration('medium1') f.get-motion-easing('standard');
377
+ }
378
+
379
+ // Hidden buttons for accessibility
380
+ &-swipe-left-action,
381
+ &-swipe-right-action {
382
+ @include m.visually-hidden; // Use visually-hidden mixin
348
383
  }
349
384
  }
350
385
 
@@ -356,4 +391,11 @@ $component: '#{base.$prefix}-card';
356
391
  100% {
357
392
  transform: rotate(360deg);
358
393
  }
394
+ }
395
+
396
+ // Media query for responsive adjustments
397
+ @include m.breakpoint-down('sm') {
398
+ .#{$component} {
399
+ width: 100%; // Full width on small screens
400
+ }
359
401
  }
@@ -3,6 +3,7 @@ import { BaseComponent, CardComponent, ApiOptions } from './types';
3
3
 
4
4
  /**
5
5
  * Enhances a card component with API methods
6
+ *
6
7
  * @param {ApiOptions} options - API configuration options
7
8
  * @returns {Function} Higher-order function that adds API methods to component
8
9
  * @internal This is an internal utility for the Card component
@@ -13,6 +14,7 @@ export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent)
13
14
 
14
15
  /**
15
16
  * Adds content to the card
17
+ *
16
18
  * @param {HTMLElement} contentElement - The content element to add
17
19
  * @returns {CardComponent} The card instance for chaining
18
20
  */
@@ -25,8 +27,18 @@ export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent)
25
27
 
26
28
  /**
27
29
  * Sets the card header
30
+ *
31
+ * Places the header element in the card. When media elements exist,
32
+ * the header is placed after the last media element to ensure proper
33
+ * visual hierarchy following Material Design guidelines.
34
+ *
28
35
  * @param {HTMLElement} headerElement - The header element to add
29
36
  * @returns {CardComponent} The card instance for chaining
37
+ * @example
38
+ * ```typescript
39
+ * // Add a header after media
40
+ * card.setHeader(headerElement);
41
+ * ```
30
42
  */
31
43
  setHeader(headerElement: HTMLElement): CardComponent {
32
44
  if (headerElement && headerElement.classList.contains(`${component.getClass('card')}-header`)) {
@@ -36,14 +48,32 @@ export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent)
36
48
  existingHeader.remove();
37
49
  }
38
50
 
39
- // Insert at the beginning of the card
40
- component.element.insertBefore(headerElement, component.element.firstChild);
51
+ // Look for media element
52
+ const mediaElement = component.element.querySelector(`.${component.getClass('card')}-media`);
53
+
54
+ if (mediaElement) {
55
+ // If media exists, insert after the LAST media element
56
+ // Find all media elements
57
+ const mediaElements = component.element.querySelectorAll(`.${component.getClass('card')}-media`);
58
+ const lastMedia = mediaElements[mediaElements.length - 1];
59
+
60
+ // Insert after the last media element
61
+ if (lastMedia.nextSibling) {
62
+ component.element.insertBefore(headerElement, lastMedia.nextSibling);
63
+ } else {
64
+ component.element.appendChild(headerElement);
65
+ }
66
+ } else {
67
+ // No media, insert at the beginning
68
+ component.element.insertBefore(headerElement, component.element.firstChild);
69
+ }
41
70
  }
42
71
  return this;
43
72
  },
44
73
 
45
74
  /**
46
75
  * Adds media to the card
76
+ *
47
77
  * @param {HTMLElement} mediaElement - The media element to add
48
78
  * @param {string} [position='top'] - Position to place media ('top', 'bottom')
49
79
  * @returns {CardComponent} The card instance for chaining
@@ -61,6 +91,7 @@ export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent)
61
91
 
62
92
  /**
63
93
  * Sets the card actions section
94
+ *
64
95
  * @param {HTMLElement} actionsElement - The actions element to add
65
96
  * @returns {CardComponent} The card instance for chaining
66
97
  */
@@ -80,19 +111,39 @@ export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent)
80
111
 
81
112
  /**
82
113
  * Makes the card draggable
114
+ *
83
115
  * @param {Function} [dragStartCallback] - Callback for drag start event
84
116
  * @returns {CardComponent} The card instance for chaining
85
117
  */
86
118
  makeDraggable(dragStartCallback?: (event: DragEvent) => void): CardComponent {
87
119
  component.element.setAttribute('draggable', 'true');
120
+ component.element.setAttribute('aria-grabbed', 'false');
88
121
 
89
122
  if (typeof dragStartCallback === 'function') {
90
- component.element.addEventListener('dragstart', dragStartCallback as EventListener);
123
+ component.element.addEventListener('dragstart', (e: DragEvent) => {
124
+ component.element.setAttribute('aria-grabbed', 'true');
125
+ dragStartCallback(e);
126
+ });
127
+
128
+ component.element.addEventListener('dragend', () => {
129
+ component.element.setAttribute('aria-grabbed', 'false');
130
+ });
91
131
  }
92
132
 
93
133
  return this;
94
134
  },
95
135
 
136
+ /**
137
+ * Sets focus to the card
138
+ * Useful for programmatic focus management
139
+ *
140
+ * @returns {CardComponent} The card instance for chaining
141
+ */
142
+ focus(): CardComponent {
143
+ component.element.focus();
144
+ return this;
145
+ },
146
+
96
147
  /**
97
148
  * Destroys the card component and removes event listeners
98
149
  */
@@ -9,29 +9,48 @@ import {
9
9
  } from '../../core/compose/features';
10
10
  import { withAPI } from './api';
11
11
  import { CardComponent, BaseComponent, CardSchema } from './types';
12
- import { createBaseConfig, getElementConfig, getApiConfig, withInteractiveBehavior } from './config';
12
+ import {
13
+ createBaseConfig,
14
+ getElementConfig,
15
+ getApiConfig,
16
+ withInteractiveBehavior,
17
+ processInlineConfig,
18
+ applyInlineConfiguration
19
+ } from './config';
20
+ import { withElevation } from './features';
13
21
 
14
22
  /**
15
23
  * Creates a new Card component following Material Design 3 principles
24
+ *
25
+ * Material Design 3 Cards are surfaces that display content and actions about a single topic.
26
+ * Cards can contain text, media, and UI controls.
27
+ *
16
28
  * @param {CardSchema} config - Card configuration object
17
29
  * @returns {CardComponent} Card component instance
18
30
  */
19
31
  const createCard = (config: CardSchema = {}): CardComponent => {
20
- const baseConfig = createBaseConfig(config);
32
+ // Process inline configuration (map shorthand properties)
33
+ const processedConfig = processInlineConfig(config);
34
+ const baseConfig = createBaseConfig(processedConfig);
21
35
 
22
36
  try {
37
+ // Create the core card component
23
38
  const card = pipe(
24
39
  createBase,
25
40
  withEvents(),
26
41
  withElement(getElementConfig(baseConfig)),
27
42
  withVariant(baseConfig),
28
- config.clickable ? withRipple(baseConfig) : (c: BaseComponent) => c,
43
+ baseConfig.clickable ? withRipple(baseConfig) : (c: BaseComponent) => c,
29
44
  withLifecycle(),
30
45
  withInteractiveBehavior,
46
+ withElevation,
31
47
  comp => withAPI(getApiConfig(comp))(comp)
32
- )(baseConfig);
33
-
34
- return card as CardComponent;
48
+ )(baseConfig) as CardComponent;
49
+
50
+ // Apply any inline configuration
51
+ applyInlineConfiguration(card, processedConfig);
52
+
53
+ return card;
35
54
  } catch (error) {
36
55
  console.error('Card creation error:', error instanceof Error ? error.message : String(error));
37
56
  throw new Error(`Failed to create card: ${error instanceof Error ? error.message : String(error)}`);