mtrl 0.2.6 → 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 (147) hide show
  1. package/index.ts +18 -0
  2. package/package.json +1 -1
  3. package/src/components/badge/_styles.scss +117 -109
  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 -10
  16. package/src/components/button/api.ts +5 -0
  17. package/src/components/button/config.ts +5 -0
  18. package/src/components/button/types.ts +6 -0
  19. package/src/components/card/card.ts +13 -25
  20. package/src/components/card/config.ts +67 -22
  21. package/src/components/card/features.ts +3 -0
  22. package/src/components/card/types.ts +28 -0
  23. package/src/components/checkbox/_styles.scss +0 -2
  24. package/src/components/datepicker/_styles.scss +358 -0
  25. package/src/components/datepicker/api.ts +272 -0
  26. package/src/components/datepicker/config.ts +144 -0
  27. package/src/components/datepicker/constants.ts +98 -0
  28. package/src/components/datepicker/datepicker.ts +346 -0
  29. package/src/components/datepicker/index.ts +9 -0
  30. package/src/components/datepicker/render.ts +452 -0
  31. package/src/components/datepicker/types.ts +268 -0
  32. package/src/components/datepicker/utils.ts +290 -0
  33. package/src/components/dialog/_styles.scss +174 -128
  34. package/src/components/dialog/api.ts +48 -13
  35. package/src/components/dialog/config.ts +9 -5
  36. package/src/components/dialog/dialog.ts +6 -3
  37. package/src/components/dialog/features.ts +290 -130
  38. package/src/components/dialog/types.ts +7 -4
  39. package/src/components/divider/_styles.scss +57 -0
  40. package/src/components/divider/config.ts +81 -0
  41. package/src/components/divider/divider.ts +37 -0
  42. package/src/components/divider/features.ts +207 -0
  43. package/src/components/divider/index.ts +5 -0
  44. package/src/components/divider/types.ts +55 -0
  45. package/src/components/extended-fab/_styles.scss +267 -0
  46. package/src/components/extended-fab/api.ts +141 -0
  47. package/src/components/extended-fab/config.ts +108 -0
  48. package/src/components/extended-fab/constants.ts +36 -0
  49. package/src/components/extended-fab/extended-fab.ts +125 -0
  50. package/src/components/extended-fab/index.ts +4 -0
  51. package/src/components/extended-fab/types.ts +287 -0
  52. package/src/components/fab/_styles.scss +225 -0
  53. package/src/components/fab/api.ts +97 -0
  54. package/src/components/fab/config.ts +94 -0
  55. package/src/components/fab/constants.ts +41 -0
  56. package/src/components/fab/fab.ts +67 -0
  57. package/src/components/fab/index.ts +4 -0
  58. package/src/components/fab/types.ts +234 -0
  59. package/src/components/navigation/_styles.scss +1 -0
  60. package/src/components/navigation/api.ts +78 -50
  61. package/src/components/navigation/features/items.ts +280 -0
  62. package/src/components/navigation/nav-item.ts +72 -23
  63. package/src/components/navigation/navigation.ts +54 -2
  64. package/src/components/navigation/types.ts +210 -188
  65. package/src/components/search/_styles.scss +306 -0
  66. package/src/components/search/api.ts +203 -0
  67. package/src/components/search/config.ts +87 -0
  68. package/src/components/search/constants.ts +21 -0
  69. package/src/components/search/features/index.ts +4 -0
  70. package/src/components/search/features/search.ts +718 -0
  71. package/src/components/search/features/states.ts +165 -0
  72. package/src/components/search/features/structure.ts +198 -0
  73. package/src/components/search/index.ts +10 -0
  74. package/src/components/search/search.ts +52 -0
  75. package/src/components/search/types.ts +163 -0
  76. package/src/components/segmented-button/_styles.scss +117 -0
  77. package/src/components/segmented-button/config.ts +67 -0
  78. package/src/components/segmented-button/constants.ts +42 -0
  79. package/src/components/segmented-button/index.ts +4 -0
  80. package/src/components/segmented-button/segment.ts +155 -0
  81. package/src/components/segmented-button/segmented-button.ts +250 -0
  82. package/src/components/segmented-button/types.ts +219 -0
  83. package/src/components/slider/_styles.scss +83 -24
  84. package/src/components/slider/accessibility.md +5 -5
  85. package/src/components/slider/api.ts +41 -120
  86. package/src/components/slider/config.ts +51 -47
  87. package/src/components/slider/features/handlers.ts +495 -0
  88. package/src/components/slider/features/index.ts +1 -2
  89. package/src/components/slider/features/slider.ts +66 -84
  90. package/src/components/slider/features/states.ts +195 -0
  91. package/src/components/slider/features/structure.ts +136 -206
  92. package/src/components/slider/features/ui.ts +145 -206
  93. package/src/components/slider/index.ts +2 -11
  94. package/src/components/slider/slider.ts +9 -12
  95. package/src/components/slider/types.ts +39 -24
  96. package/src/components/switch/_styles.scss +0 -2
  97. package/src/components/tabs/_styles.scss +94 -32
  98. package/src/components/tabs/features.ts +4 -2
  99. package/src/components/tabs/indicator.ts +73 -13
  100. package/src/components/tabs/types.ts +10 -2
  101. package/src/components/timepicker/README.md +277 -0
  102. package/src/components/timepicker/_styles.scss +451 -0
  103. package/src/components/timepicker/api.ts +632 -0
  104. package/src/components/timepicker/clockdial.ts +482 -0
  105. package/src/components/timepicker/config.ts +130 -0
  106. package/src/components/timepicker/constants.ts +138 -0
  107. package/src/components/timepicker/index.ts +8 -0
  108. package/src/components/timepicker/render.ts +613 -0
  109. package/src/components/timepicker/timepicker.ts +117 -0
  110. package/src/components/timepicker/types.ts +336 -0
  111. package/src/components/timepicker/utils.ts +241 -0
  112. package/src/components/top-app-bar/_styles.scss +225 -0
  113. package/src/components/top-app-bar/config.ts +83 -0
  114. package/src/components/top-app-bar/index.ts +11 -0
  115. package/src/components/top-app-bar/top-app-bar.ts +316 -0
  116. package/src/components/top-app-bar/types.ts +140 -0
  117. package/src/core/build/_ripple.scss +6 -6
  118. package/src/core/build/ripple.ts +72 -95
  119. package/src/core/compose/features/icon.ts +3 -1
  120. package/src/core/compose/features/ripple.ts +4 -1
  121. package/src/core/compose/features/textlabel.ts +26 -2
  122. package/src/core/dom/create.ts +5 -0
  123. package/src/index.ts +9 -0
  124. package/src/styles/abstract/_theme.scss +9 -1
  125. package/src/styles/themes/_autumn.scss +21 -0
  126. package/src/styles/themes/_base-theme.scss +61 -0
  127. package/src/styles/themes/_baseline.scss +58 -0
  128. package/src/styles/themes/_bluekhaki.scss +125 -0
  129. package/src/styles/themes/_brownbeige.scss +125 -0
  130. package/src/styles/themes/_browngreen.scss +125 -0
  131. package/src/styles/themes/_forest.scss +6 -0
  132. package/src/styles/themes/_greenbeige.scss +125 -0
  133. package/src/styles/themes/_material.scss +125 -0
  134. package/src/styles/themes/_ocean.scss +6 -0
  135. package/src/styles/themes/_sageivory.scss +125 -0
  136. package/src/styles/themes/_spring.scss +6 -0
  137. package/src/styles/themes/_summer.scss +5 -0
  138. package/src/styles/themes/_sunset.scss +5 -0
  139. package/src/styles/themes/_tealcaramel.scss +125 -0
  140. package/src/styles/themes/_winter.scss +6 -0
  141. package/src/components/navigation/features/items.js +0 -192
  142. package/src/components/slider/features/appearance.ts +0 -94
  143. package/src/components/slider/features/disabled.ts +0 -68
  144. package/src/components/slider/features/events.ts +0 -164
  145. package/src/components/slider/features/interactions.ts +0 -396
  146. package/src/components/slider/features/keyboard.ts +0 -233
  147. package/src/core/collection/adapters/mongodb.js +0 -232
@@ -0,0 +1,196 @@
1
+ // src/components/bottom-app-bar/bottom-app-bar.ts
2
+ /**
3
+ * @module components/bottom-app-bar
4
+ * @description Bottom app bar implementation
5
+ */
6
+
7
+ import {
8
+ createBase,
9
+ withElement,
10
+ withEvents,
11
+ withLifecycle,
12
+ ElementComponent,
13
+ BaseComponent
14
+ } from '../../core/compose';
15
+
16
+ import { createConfig, BottomAppBarConfig } from './config';
17
+
18
+ /**
19
+ * Bottom app bar component interface
20
+ */
21
+ export interface BottomAppBar extends ElementComponent {
22
+ /**
23
+ * Adds an action button to the bottom bar
24
+ * @param {HTMLElement} button - Button element to add
25
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
26
+ */
27
+ addAction: (button: HTMLElement) => BottomAppBar;
28
+
29
+ /**
30
+ * Adds a floating action button to the bottom bar
31
+ * @param {HTMLElement} fab - FAB element to add
32
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
33
+ */
34
+ addFab: (fab: HTMLElement) => BottomAppBar;
35
+
36
+ /**
37
+ * Shows the bottom bar
38
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
39
+ */
40
+ show: () => BottomAppBar;
41
+
42
+ /**
43
+ * Hides the bottom bar
44
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
45
+ */
46
+ hide: () => BottomAppBar;
47
+
48
+ /**
49
+ * Checks if the bottom bar is visible
50
+ * @returns {boolean} Whether the bottom bar is visible
51
+ */
52
+ isVisible: () => boolean;
53
+
54
+ /**
55
+ * Get the actions container element
56
+ * @returns {HTMLElement} Actions container element
57
+ */
58
+ getActionsContainer: () => HTMLElement;
59
+ }
60
+
61
+ /**
62
+ * Creates a bottom app bar component
63
+ *
64
+ * @param {BottomAppBarConfig} config - Configuration options
65
+ * @returns {BottomAppBar} Bottom app bar component instance
66
+ */
67
+ export const createBottomAppBar = (config: BottomAppBarConfig = {}): BottomAppBar => {
68
+ // Process configuration with defaults
69
+ const componentConfig = createConfig(config);
70
+
71
+ // Create base component
72
+ const component = createBase(componentConfig);
73
+
74
+ // Create actions container
75
+ const actionsContainer = document.createElement('div');
76
+ actionsContainer.className = `${component.getClass('bottom-app-bar')}-actions`;
77
+
78
+ // FAB container for proper positioning
79
+ const fabContainer = document.createElement('div');
80
+ fabContainer.className = `${component.getClass('bottom-app-bar')}-fab-container`;
81
+
82
+ // Apply Element enhancer
83
+ const enhancedComponent = withElement({
84
+ tag: componentConfig.tag,
85
+ componentName: 'bottom-app-bar',
86
+ className: [
87
+ componentConfig.hasFab ? `${component.getClass('bottom-app-bar')}--with-fab` : '',
88
+ componentConfig.fabPosition === 'center' ? `${component.getClass('bottom-app-bar')}--fab-center` : '',
89
+ componentConfig.class
90
+ ],
91
+ attrs: {
92
+ role: 'toolbar',
93
+ 'aria-label': 'Bottom app bar'
94
+ },
95
+ interactive: true
96
+ })(component);
97
+
98
+ // Apply events enhancer for component events
99
+ const withEventsComponent = withEvents()(enhancedComponent);
100
+
101
+ // Apply lifecycle enhancer for cleanup
102
+ const withLifecycleComponent = withLifecycle()(withEventsComponent);
103
+
104
+ // Append actions and FAB containers to the main element
105
+ withLifecycleComponent.element.appendChild(actionsContainer);
106
+ withLifecycleComponent.element.appendChild(fabContainer);
107
+
108
+ // Flag to track visibility
109
+ let isVisible = true;
110
+
111
+ // Previous scroll position for determining scroll direction
112
+ let prevScrollY = window.scrollY;
113
+
114
+ // Handle scrolling behavior if autoHide is enabled
115
+ if (componentConfig.autoHide) {
116
+ const handleScroll = () => {
117
+ const currentScrollY = window.scrollY;
118
+
119
+ // Determine scroll direction
120
+ if (currentScrollY > prevScrollY + 10) {
121
+ // Scrolling down - hide the bottom bar
122
+ if (isVisible) {
123
+ bottomBar.hide();
124
+ componentConfig.onVisibilityChange?.(false);
125
+ }
126
+ } else if (currentScrollY < prevScrollY - 10) {
127
+ // Scrolling up - show the bottom bar
128
+ if (!isVisible) {
129
+ bottomBar.show();
130
+ componentConfig.onVisibilityChange?.(true);
131
+ }
132
+ }
133
+
134
+ prevScrollY = currentScrollY;
135
+ };
136
+
137
+ // Add scroll event listener
138
+ window.addEventListener('scroll', handleScroll, { passive: true });
139
+
140
+ // Clean up event listener on destroy
141
+ const originalDestroy = withLifecycleComponent.lifecycle.destroy;
142
+ withLifecycleComponent.lifecycle.destroy = () => {
143
+ window.removeEventListener('scroll', handleScroll);
144
+ originalDestroy();
145
+ };
146
+ }
147
+
148
+ const bottomBar: BottomAppBar = {
149
+ ...withLifecycleComponent,
150
+
151
+ addAction(button: HTMLElement) {
152
+ actionsContainer.appendChild(button);
153
+ return this;
154
+ },
155
+
156
+ addFab(fab: HTMLElement) {
157
+ // Clear existing FAB if any
158
+ fabContainer.innerHTML = '';
159
+
160
+ // Add the new FAB
161
+ fabContainer.appendChild(fab);
162
+
163
+ // Update component class to indicate it has a FAB
164
+ this.element.classList.add(`${component.getClass('bottom-app-bar')}--with-fab`);
165
+
166
+ return this;
167
+ },
168
+
169
+ show() {
170
+ this.element.classList.remove(`${component.getClass('bottom-app-bar')}--hidden`);
171
+ isVisible = true;
172
+ return this;
173
+ },
174
+
175
+ hide() {
176
+ this.element.classList.add(`${component.getClass('bottom-app-bar')}--hidden`);
177
+ isVisible = false;
178
+ return this;
179
+ },
180
+
181
+ isVisible() {
182
+ return isVisible;
183
+ },
184
+
185
+ getActionsContainer() {
186
+ return actionsContainer;
187
+ }
188
+ };
189
+
190
+ // Set the appropriate styles for transitions if needed
191
+ if (componentConfig.autoHide && componentConfig.transitionDuration) {
192
+ bottomBar.element.style.transition = `transform ${componentConfig.transitionDuration}ms ease-in-out`;
193
+ }
194
+
195
+ return bottomBar;
196
+ };
@@ -0,0 +1,73 @@
1
+ // src/components/bottom-app-bar/config.ts
2
+ /**
3
+ * @module components/bottom-app-bar
4
+ * @description Configuration for bottom app bar component
5
+ */
6
+
7
+ import { createComponentConfig, BaseComponentConfig } from '../../core/config/component-config';
8
+ import { PREFIX } from '../../core/config';
9
+
10
+ /**
11
+ * Configuration options for bottom app bar
12
+ */
13
+ export interface BottomAppBarConfig extends BaseComponentConfig {
14
+ /**
15
+ * Element to use for the container
16
+ * @default 'div'
17
+ */
18
+ tag?: string;
19
+
20
+ /**
21
+ * Whether to show FAB in the bottom bar
22
+ * @default false
23
+ */
24
+ hasFab?: boolean;
25
+
26
+ /**
27
+ * FAB position in bottom bar
28
+ * @default 'end'
29
+ */
30
+ fabPosition?: 'center' | 'end';
31
+
32
+ /**
33
+ * Additional CSS classes to apply
34
+ */
35
+ class?: string;
36
+
37
+ /**
38
+ * Whether to enable auto-hide on scroll
39
+ * @default false
40
+ */
41
+ autoHide?: boolean;
42
+
43
+ /**
44
+ * Transition duration for show/hide in ms
45
+ * @default 300
46
+ */
47
+ transitionDuration?: number;
48
+
49
+ /**
50
+ * Optional callback when scrolling shows/hides the bar
51
+ */
52
+ onVisibilityChange?: (visible: boolean) => void;
53
+ }
54
+
55
+ /**
56
+ * Default configuration for bottom app bar
57
+ */
58
+ export const defaultConfig: Partial<BottomAppBarConfig> = {
59
+ tag: 'div',
60
+ hasFab: false,
61
+ fabPosition: 'end',
62
+ autoHide: false,
63
+ transitionDuration: 300
64
+ };
65
+
66
+ /**
67
+ * Creates the configuration for a bottom app bar component
68
+ *
69
+ * @param {BottomAppBarConfig} config - User provided configuration
70
+ * @returns {BottomAppBarConfig} Complete configuration with defaults applied
71
+ */
72
+ export const createConfig = (config: BottomAppBarConfig = {} as BottomAppBarConfig): BottomAppBarConfig =>
73
+ createComponentConfig(defaultConfig, config, 'bottom-app-bar') as BottomAppBarConfig;
@@ -0,0 +1,11 @@
1
+ // src/components/bottom-app-bar/index.ts
2
+ /**
3
+ * @module components/bottom-app-bar
4
+ * @description Bottom app bar component for mobile interfaces
5
+ */
6
+
7
+ import { createBottomAppBar } from './bottom-app-bar';
8
+
9
+ export default createBottomAppBar;
10
+ export { createBottomAppBar };
11
+ export type { BottomAppBarConfig } from './config';
@@ -0,0 +1,108 @@
1
+ // src/components/bottom-app-bar/types.ts
2
+ /**
3
+ * @module components/bottom-app-bar
4
+ * @description Type definitions for Bottom App Bar component
5
+ */
6
+
7
+ import { ElementComponent } from '../../core/compose';
8
+
9
+ /**
10
+ * Configuration options for Bottom App Bar component
11
+ * @category Components
12
+ */
13
+ export interface BottomAppBarConfig {
14
+ /**
15
+ * Element to use for the container
16
+ * @default 'div'
17
+ */
18
+ tag?: string;
19
+
20
+ /**
21
+ * Whether to show FAB in the bottom bar
22
+ * @default false
23
+ */
24
+ hasFab?: boolean;
25
+
26
+ /**
27
+ * FAB position in bottom bar
28
+ * @default 'end'
29
+ */
30
+ fabPosition?: 'center' | 'end';
31
+
32
+ /**
33
+ * Additional CSS classes to apply
34
+ */
35
+ class?: string;
36
+
37
+ /**
38
+ * Whether to enable auto-hide on scroll
39
+ * @default false
40
+ */
41
+ autoHide?: boolean;
42
+
43
+ /**
44
+ * Transition duration for show/hide in ms
45
+ * @default 300
46
+ */
47
+ transitionDuration?: number;
48
+
49
+ /**
50
+ * Optional callback when scrolling shows/hides the bar
51
+ */
52
+ onVisibilityChange?: (visible: boolean) => void;
53
+
54
+ /**
55
+ * Component prefix for class names
56
+ * @default 'mtrl'
57
+ */
58
+ prefix?: string;
59
+
60
+ /**
61
+ * Component name for class generation
62
+ */
63
+ componentName?: string;
64
+ }
65
+
66
+ /**
67
+ * Bottom App Bar component interface
68
+ * @category Components
69
+ */
70
+ export interface BottomAppBar extends ElementComponent {
71
+ /**
72
+ * Adds an action button to the bottom bar
73
+ * @param {HTMLElement} button - Button element to add
74
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
75
+ */
76
+ addAction: (button: HTMLElement) => BottomAppBar;
77
+
78
+ /**
79
+ * Adds a floating action button to the bottom bar
80
+ * @param {HTMLElement} fab - FAB element to add
81
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
82
+ */
83
+ addFab: (fab: HTMLElement) => BottomAppBar;
84
+
85
+ /**
86
+ * Shows the bottom bar
87
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
88
+ */
89
+ show: () => BottomAppBar;
90
+
91
+ /**
92
+ * Hides the bottom bar
93
+ * @returns {BottomAppBar} BottomAppBar instance for chaining
94
+ */
95
+ hide: () => BottomAppBar;
96
+
97
+ /**
98
+ * Checks if the bottom bar is visible
99
+ * @returns {boolean} Whether the bottom bar is visible
100
+ */
101
+ isVisible: () => boolean;
102
+
103
+ /**
104
+ * Get the actions container element
105
+ * @returns {HTMLElement} Actions container element
106
+ */
107
+ getActionsContainer: () => HTMLElement;
108
+ }
@@ -96,16 +96,6 @@ $component: '#{base.$prefix}-button';
96
96
  }
97
97
  }
98
98
 
99
- // Ripple container
100
- .ripple {
101
- position: absolute;
102
- border-radius: 50%;
103
- transform: scale(0);
104
- pointer-events: none;
105
- background-color: currentColor;
106
- opacity: 0.12;
107
- }
108
-
109
99
  &--disabled {
110
100
  opacity: 0.38
111
101
  }
@@ -73,6 +73,11 @@ export const withAPI = ({ disabled, lifecycle }: ApiOptions) =>
73
73
  getIcon() {
74
74
  return component.icon.getIcon();
75
75
  },
76
+
77
+ setAriaLabel(label: string) {
78
+ component.element.setAttribute('aria-label', label);
79
+ return this;
80
+ },
76
81
 
77
82
  destroy() {
78
83
  lifecycle.destroy();
@@ -45,6 +45,11 @@ export const getElementConfig = (config: ButtonConfig) => {
45
45
  attrs.value = config.value;
46
46
  }
47
47
 
48
+ // Add aria-label attribute for accessibility
49
+ if (config.ariaLabel) {
50
+ attrs['aria-label'] = config.ariaLabel;
51
+ }
52
+
48
53
  return createElementConfig(config, {
49
54
  tag: 'button',
50
55
  attrs,
@@ -81,6 +81,12 @@ export interface ButtonConfig {
81
81
  /** Opacity values for ripple start and end [start, end] */
82
82
  opacity?: [string, string];
83
83
  };
84
+
85
+ /**
86
+ * Accessible name for the button (aria-label)
87
+ * Required for icon-only buttons without text
88
+ */
89
+ ariaLabel?: string;
84
90
  }
85
91
 
86
92
  /**
@@ -13,7 +13,9 @@ import {
13
13
  createBaseConfig,
14
14
  getElementConfig,
15
15
  getApiConfig,
16
- withInteractiveBehavior
16
+ withInteractiveBehavior,
17
+ processInlineConfig,
18
+ applyInlineConfiguration
17
19
  } from './config';
18
20
  import { withElevation } from './features';
19
21
 
@@ -25,44 +27,30 @@ import { withElevation } from './features';
25
27
  *
26
28
  * @param {CardSchema} config - Card configuration object
27
29
  * @returns {CardComponent} Card component instance
28
- *
29
- * @example
30
- * ```typescript
31
- * // Create a basic elevated card
32
- * const card = createCard();
33
- *
34
- * // Create a filled card with content
35
- * const filledCard = createCard({
36
- * variant: CardVariant.FILLED,
37
- * contentConfig: { text: 'Card content' }
38
- * });
39
- *
40
- * // Create an interactive outlined card
41
- * const interactiveCard = createCard({
42
- * variant: CardVariant.OUTLINED,
43
- * interactive: true,
44
- * clickable: true,
45
- * aria: { label: 'Click to view details' }
46
- * });
47
- * ```
48
30
  */
49
31
  const createCard = (config: CardSchema = {}): CardComponent => {
50
- const baseConfig = createBaseConfig(config);
32
+ // Process inline configuration (map shorthand properties)
33
+ const processedConfig = processInlineConfig(config);
34
+ const baseConfig = createBaseConfig(processedConfig);
51
35
 
52
36
  try {
37
+ // Create the core card component
53
38
  const card = pipe(
54
39
  createBase,
55
40
  withEvents(),
56
41
  withElement(getElementConfig(baseConfig)),
57
42
  withVariant(baseConfig),
58
- config.clickable ? withRipple(baseConfig) : (c: BaseComponent) => c,
43
+ baseConfig.clickable ? withRipple(baseConfig) : (c: BaseComponent) => c,
59
44
  withLifecycle(),
60
45
  withInteractiveBehavior,
61
46
  withElevation,
62
47
  comp => withAPI(getApiConfig(comp))(comp)
63
- )(baseConfig);
48
+ )(baseConfig) as CardComponent;
49
+
50
+ // Apply any inline configuration
51
+ applyInlineConfiguration(card, processedConfig);
64
52
 
65
- return card as CardComponent;
53
+ return card;
66
54
  } catch (error) {
67
55
  console.error('Card creation error:', error instanceof Error ? error.message : String(error));
68
56
  throw new Error(`Failed to create card: ${error instanceof Error ? error.message : String(error)}`);
@@ -1,10 +1,17 @@
1
1
  // src/components/card/config.ts
2
+
2
3
  import {
3
4
  createComponentConfig,
4
5
  createElementConfig
5
6
  } from '../../core/config/component-config';
6
- import { BaseComponent, CardSchema } from './types';
7
7
  import { CARD_VARIANTS, CARD_ELEVATIONS } from './constants';
8
+ import {
9
+ createCardHeader,
10
+ createCardContent,
11
+ createCardMedia,
12
+ createCardActions
13
+ } from './content';
14
+ import { CardComponent, CardSchema, ButtonConfig, BaseComponent } from './types';
8
15
 
9
16
  /**
10
17
  * Default configuration for the Card component
@@ -19,57 +26,95 @@ export const defaultConfig: CardSchema = {
19
26
  };
20
27
 
21
28
  /**
22
- * Initializes a card component with its configured elements in the correct order
23
- *
24
- * Creates and adds all configured elements to the card in the following order:
25
- * 1. Top media elements (position='top')
26
- * 2. Header element
27
- * 3. Content elements
28
- * 4. Bottom media elements (position='bottom')
29
- * 5. Actions elements
29
+ * Processes inline configuration options into standard config format
30
+ * Maps shorthand properties to their proper config counterparts
30
31
  *
31
- * This ordering ensures that media appears before header when both are configured,
32
- * maintaining proper visual hierarchy according to Material Design guidelines.
32
+ * @param {CardSchema} config - Raw card configuration
33
+ * @returns {CardSchema} Processed configuration
34
+ */
35
+ export const processInlineConfig = (config: CardSchema): CardSchema => {
36
+ const processedConfig: CardSchema = { ...config };
37
+
38
+ // Map inline properties to their *Config counterparts
39
+ if (config.header) {
40
+ processedConfig.headerConfig = config.header;
41
+ }
42
+
43
+ if (config.content) {
44
+ processedConfig.contentConfig = config.content;
45
+ }
46
+
47
+ if (config.media) {
48
+ processedConfig.mediaConfig = config.media;
49
+ }
50
+
51
+ if (config.actions) {
52
+ processedConfig.actionsConfig = config.actions;
53
+ }
54
+
55
+ return processedConfig;
56
+ };
57
+
58
+ /**
59
+ * Applies inline configuration to a card component
60
+ * Adds configured elements to the card in the correct order
33
61
  *
34
- * @param {CardComponent} card - Card component to initialize
35
- * @param {CardSchema} config - Card configuration
36
- * @returns {CardComponent} Initialized card component
37
- * @internal This is an internal utility for the Card component
62
+ * @param {CardComponent} card - Card component to configure
63
+ * @param {CardSchema} config - Processed configuration
38
64
  */
39
- export const initializeCardElements = (card: CardComponent, config: CardSchema): CardComponent => {
40
- // 1. Add top media first
65
+ export const applyInlineConfiguration = (card: CardComponent, config: CardSchema): void => {
66
+ // Add media (top position) if configured
41
67
  if (config.mediaConfig && (!config.mediaConfig.position || config.mediaConfig.position === 'top')) {
42
68
  const { position, ...mediaConfigWithoutPosition } = config.mediaConfig;
43
69
  const mediaElement = createCardMedia(mediaConfigWithoutPosition);
44
70
  card.addMedia(mediaElement, 'top');
45
71
  }
46
72
 
47
- // 2. Add header AFTER top media
73
+ // Add header if configured
48
74
  if (config.headerConfig) {
49
75
  const headerElement = createCardHeader(config.headerConfig);
50
76
  card.setHeader(headerElement);
51
77
  }
52
78
 
53
- // 3. Add content AFTER header
79
+ // Add content if configured
54
80
  if (config.contentConfig) {
55
81
  const contentElement = createCardContent(config.contentConfig);
56
82
  card.addContent(contentElement);
57
83
  }
58
84
 
59
- // 4. Add bottom media AFTER content
85
+ // Add media (bottom position) if configured
60
86
  if (config.mediaConfig && config.mediaConfig.position === 'bottom') {
61
87
  const { position, ...mediaConfigWithoutPosition } = config.mediaConfig;
62
88
  const mediaElement = createCardMedia(mediaConfigWithoutPosition);
63
89
  card.addMedia(mediaElement, 'bottom');
64
90
  }
65
91
 
66
- // 5. Add actions LAST
92
+ // Add actions if configured
67
93
  if (config.actionsConfig) {
68
94
  const actionsElement = createCardActions(config.actionsConfig);
69
95
  card.setActions(actionsElement);
70
96
  }
71
97
 
72
- return card;
98
+ // Process buttons if provided (asynchronously)
99
+ if (Array.isArray(config.buttons) && config.buttons.length > 0) {
100
+ import('../button').then(({ default: createButton }) => {
101
+ // Create buttons from configuration
102
+ const actionButtons = config.buttons!.map(buttonConfig =>
103
+ createButton(buttonConfig).element
104
+ );
105
+
106
+ // Create actions container
107
+ const actionsElement = createCardActions({
108
+ actions: actionButtons,
109
+ align: config.actionsConfig?.align || 'end'
110
+ });
111
+
112
+ // Add the actions to the card
113
+ card.setActions(actionsElement);
114
+ }).catch(error => {
115
+ console.error('Error processing buttons:', error);
116
+ });
117
+ }
73
118
  };
74
119
 
75
120
  /**
@@ -3,6 +3,9 @@ import { PREFIX } from '../../core/config';
3
3
  import { createElement } from '../../core/dom/create';
4
4
  import { BaseComponent, CardComponent, LoadingFeature, ExpandableFeature, SwipeableFeature } from './types';
5
5
 
6
+ import { createCardHeader, createCardContent, createCardMedia, createCardActions } from './content';
7
+ import { BaseComponent, CardComponent, CardHeaderConfig, CardContentConfig, CardMediaConfig, CardActionsConfig, CardSchema, ButtonConfig } from './types';
8
+
6
9
  interface LoadingConfig {
7
10
  initialState?: boolean;
8
11
  }