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.
- package/index.ts +18 -0
- package/package.json +1 -1
- package/src/components/badge/_styles.scss +123 -115
- package/src/components/badge/api.ts +57 -59
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +65 -11
- package/src/components/badge/constants.ts +22 -12
- package/src/components/badge/features.ts +44 -40
- package/src/components/badge/types.ts +42 -30
- package/src/components/bottom-app-bar/_styles.scss +103 -0
- package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
- package/src/components/bottom-app-bar/config.ts +73 -0
- package/src/components/bottom-app-bar/index.ts +11 -0
- package/src/components/bottom-app-bar/types.ts +108 -0
- package/src/components/button/_styles.scss +0 -66
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -2
- package/src/components/button/config.ts +5 -0
- package/src/components/button/constants.ts +0 -6
- package/src/components/button/index.ts +2 -2
- package/src/components/button/types.ts +7 -7
- package/src/components/card/_styles.scss +67 -25
- package/src/components/card/api.ts +54 -3
- package/src/components/card/card.ts +25 -6
- package/src/components/card/config.ts +189 -22
- package/src/components/card/constants.ts +20 -19
- package/src/components/card/content.ts +299 -2
- package/src/components/card/features.ts +158 -4
- package/src/components/card/index.ts +31 -9
- package/src/components/card/types.ts +166 -15
- package/src/components/checkbox/_styles.scss +0 -2
- package/src/components/chip/chip.ts +1 -9
- package/src/components/chip/constants.ts +0 -10
- package/src/components/chip/index.ts +1 -1
- package/src/components/chip/types.ts +1 -4
- package/src/components/datepicker/_styles.scss +358 -0
- package/src/components/datepicker/api.ts +272 -0
- package/src/components/datepicker/config.ts +144 -0
- package/src/components/datepicker/constants.ts +98 -0
- package/src/components/datepicker/datepicker.ts +346 -0
- package/src/components/datepicker/index.ts +9 -0
- package/src/components/datepicker/render.ts +452 -0
- package/src/components/datepicker/types.ts +268 -0
- package/src/components/datepicker/utils.ts +290 -0
- package/src/components/dialog/_styles.scss +174 -128
- package/src/components/dialog/api.ts +48 -13
- package/src/components/dialog/config.ts +9 -5
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +290 -130
- package/src/components/dialog/types.ts +7 -4
- package/src/components/divider/_styles.scss +57 -0
- package/src/components/divider/config.ts +81 -0
- package/src/components/divider/divider.ts +37 -0
- package/src/components/divider/features.ts +207 -0
- package/src/components/divider/index.ts +5 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/_styles.scss +267 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +108 -0
- package/src/components/extended-fab/constants.ts +36 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +4 -0
- package/src/components/extended-fab/types.ts +287 -0
- package/src/components/fab/_styles.scss +225 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +94 -0
- package/src/components/fab/constants.ts +41 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +4 -0
- package/src/components/fab/types.ts +234 -0
- package/src/components/navigation/_styles.scss +1 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/features/items.ts +280 -0
- package/src/components/navigation/nav-item.ts +72 -23
- package/src/components/navigation/navigation.ts +54 -2
- package/src/components/navigation/types.ts +210 -188
- package/src/components/progress/_styles.scss +0 -65
- package/src/components/progress/config.ts +1 -2
- package/src/components/progress/constants.ts +0 -14
- package/src/components/progress/index.ts +1 -1
- package/src/components/progress/progress.ts +1 -4
- package/src/components/progress/types.ts +1 -4
- package/src/components/radios/_styles.scss +0 -45
- package/src/components/radios/api.ts +85 -60
- package/src/components/radios/config.ts +1 -2
- package/src/components/radios/constants.ts +0 -9
- package/src/components/radios/index.ts +1 -1
- package/src/components/radios/radio.ts +34 -11
- package/src/components/radios/radios.ts +2 -1
- package/src/components/radios/types.ts +1 -7
- package/src/components/search/_styles.scss +306 -0
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +87 -0
- package/src/components/search/constants.ts +21 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +718 -0
- package/src/components/search/features/states.ts +165 -0
- package/src/components/search/features/structure.ts +198 -0
- package/src/components/search/index.ts +10 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +163 -0
- package/src/components/segmented-button/_styles.scss +117 -0
- package/src/components/segmented-button/config.ts +67 -0
- package/src/components/segmented-button/constants.ts +42 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +155 -0
- package/src/components/segmented-button/segmented-button.ts +250 -0
- package/src/components/segmented-button/types.ts +219 -0
- package/src/components/slider/_styles.scss +221 -168
- package/src/components/slider/accessibility.md +59 -0
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -49
- package/src/components/slider/features/handlers.ts +495 -0
- package/src/components/slider/features/index.ts +1 -2
- package/src/components/slider/features/slider.ts +66 -84
- package/src/components/slider/features/states.ts +195 -0
- package/src/components/slider/features/structure.ts +141 -184
- package/src/components/slider/features/ui.ts +150 -201
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +39 -24
- package/src/components/switch/_styles.scss +0 -2
- package/src/components/tabs/_styles.scss +346 -154
- package/src/components/tabs/api.ts +178 -400
- package/src/components/tabs/config.ts +46 -52
- package/src/components/tabs/constants.ts +85 -8
- package/src/components/tabs/features.ts +403 -0
- package/src/components/tabs/index.ts +60 -3
- package/src/components/tabs/indicator.ts +285 -0
- package/src/components/tabs/responsive.ts +144 -0
- package/src/components/tabs/scroll-indicators.ts +149 -0
- package/src/components/tabs/state.ts +186 -0
- package/src/components/tabs/tab-api.ts +258 -0
- package/src/components/tabs/tab.ts +255 -0
- package/src/components/tabs/tabs.ts +50 -31
- package/src/components/tabs/types.ts +332 -128
- package/src/components/tabs/utils.ts +107 -0
- package/src/components/textfield/_styles.scss +0 -98
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/constants.ts +0 -14
- package/src/components/textfield/index.ts +2 -2
- package/src/components/textfield/textfield.ts +0 -2
- package/src/components/textfield/types.ts +1 -4
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/_styles.scss +451 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +130 -0
- package/src/components/timepicker/constants.ts +138 -0
- package/src/components/timepicker/index.ts +8 -0
- package/src/components/timepicker/render.ts +613 -0
- package/src/components/timepicker/timepicker.ts +117 -0
- package/src/components/timepicker/types.ts +336 -0
- package/src/components/timepicker/utils.ts +241 -0
- package/src/components/top-app-bar/_styles.scss +225 -0
- package/src/components/top-app-bar/config.ts +83 -0
- package/src/components/top-app-bar/index.ts +11 -0
- package/src/components/top-app-bar/top-app-bar.ts +316 -0
- package/src/components/top-app-bar/types.ts +140 -0
- package/src/core/build/_ripple.scss +6 -6
- package/src/core/build/ripple.ts +72 -95
- package/src/core/compose/component.ts +1 -1
- package/src/core/compose/features/badge.ts +79 -0
- package/src/core/compose/features/icon.ts +3 -1
- package/src/core/compose/features/index.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +26 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +115 -3
- package/src/styles/themes/_autumn.scss +21 -0
- package/src/styles/themes/_base-theme.scss +61 -0
- package/src/styles/themes/_baseline.scss +58 -0
- package/src/styles/themes/_bluekhaki.scss +125 -0
- package/src/styles/themes/_brownbeige.scss +125 -0
- package/src/styles/themes/_browngreen.scss +125 -0
- package/src/styles/themes/_forest.scss +6 -0
- package/src/styles/themes/_greenbeige.scss +125 -0
- package/src/styles/themes/_material.scss +125 -0
- package/src/styles/themes/_ocean.scss +6 -0
- package/src/styles/themes/_sageivory.scss +125 -0
- package/src/styles/themes/_spring.scss +6 -0
- package/src/styles/themes/_summer.scss +5 -0
- package/src/styles/themes/_sunset.scss +5 -0
- package/src/styles/themes/_tealcaramel.scss +125 -0
- package/src/styles/themes/_winter.scss +6 -0
- package/src/components/card/actions.ts +0 -48
- package/src/components/card/header.ts +0 -88
- package/src/components/card/media.ts +0 -52
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -43
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -261
- package/src/components/slider/features/keyboard.ts +0 -112
- package/src/core/collection/adapters/mongodb.js +0 -232
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/components/card/
|
|
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:
|
|
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:
|
|
21
|
-
--card-elevation:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
99
|
-
|
|
123
|
+
padding: v.card('padding');
|
|
124
|
+
padding-bottom: 0;
|
|
125
|
+
|
|
100
126
|
&-avatar {
|
|
101
|
-
margin-right:
|
|
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-
|
|
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:
|
|
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:
|
|
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:
|
|
303
|
-
z-index:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
40
|
-
component.element.
|
|
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',
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)}`);
|