mtrl 0.2.6 → 0.2.8

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 (226) hide show
  1. package/demo/build.ts +349 -0
  2. package/demo/index.html +110 -0
  3. package/demo/main.js +448 -0
  4. package/demo/styles.css +239 -0
  5. package/index.ts +18 -0
  6. package/package.json +14 -3
  7. package/server.ts +86 -0
  8. package/src/components/badge/api.ts +70 -63
  9. package/src/components/badge/badge.ts +16 -2
  10. package/src/components/badge/config.ts +66 -13
  11. package/src/components/badge/features.ts +51 -42
  12. package/src/components/badge/index.ts +27 -2
  13. package/src/components/badge/types.ts +62 -30
  14. package/src/components/bottom-app-bar/bottom-app-bar.ts +154 -0
  15. package/src/components/bottom-app-bar/config.ts +29 -0
  16. package/src/components/bottom-app-bar/index.ts +17 -0
  17. package/src/components/bottom-app-bar/types.ts +114 -0
  18. package/src/components/button/api.ts +5 -0
  19. package/src/components/button/button.ts +0 -1
  20. package/src/components/button/config.ts +6 -2
  21. package/src/components/button/index.ts +10 -2
  22. package/src/components/button/types.ts +20 -2
  23. package/src/components/card/card.ts +13 -25
  24. package/src/components/card/config.ts +83 -30
  25. package/src/components/card/content.ts +8 -10
  26. package/src/components/card/features.ts +4 -3
  27. package/src/components/card/index.ts +29 -2
  28. package/src/components/card/types.ts +33 -22
  29. package/src/components/checkbox/config.ts +3 -4
  30. package/src/components/checkbox/index.ts +1 -2
  31. package/src/components/checkbox/types.ts +12 -3
  32. package/src/components/chip/api.ts +170 -221
  33. package/src/components/chip/chip.ts +34 -302
  34. package/src/components/chip/config.ts +1 -2
  35. package/src/components/chip/index.ts +10 -2
  36. package/src/components/chip/types.ts +224 -35
  37. package/src/components/datepicker/api.ts +265 -0
  38. package/src/components/datepicker/config.ts +141 -0
  39. package/src/components/datepicker/datepicker.ts +341 -0
  40. package/src/components/datepicker/index.ts +12 -0
  41. package/src/components/datepicker/render.ts +450 -0
  42. package/src/components/datepicker/types.ts +397 -0
  43. package/src/components/datepicker/utils.ts +289 -0
  44. package/src/components/dialog/api.ts +55 -21
  45. package/src/components/dialog/config.ts +12 -9
  46. package/src/components/dialog/dialog.ts +6 -3
  47. package/src/components/dialog/features.ts +345 -151
  48. package/src/components/dialog/index.ts +38 -8
  49. package/src/components/dialog/types.ts +40 -14
  50. package/src/components/divider/config.ts +81 -0
  51. package/src/components/divider/divider.ts +37 -0
  52. package/src/components/divider/features.ts +207 -0
  53. package/src/components/divider/index.ts +9 -0
  54. package/src/components/divider/types.ts +55 -0
  55. package/src/components/extended-fab/api.ts +141 -0
  56. package/src/components/extended-fab/config.ts +112 -0
  57. package/src/components/extended-fab/extended-fab.ts +125 -0
  58. package/src/components/extended-fab/index.ts +9 -0
  59. package/src/components/extended-fab/types.ts +304 -0
  60. package/src/components/fab/api.ts +97 -0
  61. package/src/components/fab/config.ts +93 -0
  62. package/src/components/fab/fab.ts +67 -0
  63. package/src/components/fab/index.ts +9 -0
  64. package/src/components/fab/types.ts +251 -0
  65. package/src/components/list/config.ts +4 -5
  66. package/src/components/list/features.ts +6 -7
  67. package/src/components/list/index.ts +7 -9
  68. package/src/components/list/list-item.ts +12 -13
  69. package/src/components/list/types.ts +50 -5
  70. package/src/components/list/utils.ts +30 -3
  71. package/src/components/menu/features/items-manager.ts +9 -9
  72. package/src/components/menu/features/positioning.ts +7 -7
  73. package/src/components/menu/features/visibility.ts +7 -7
  74. package/src/components/menu/index.ts +7 -9
  75. package/src/components/menu/menu-item.ts +6 -6
  76. package/src/components/menu/menu.ts +22 -0
  77. package/src/components/menu/types.ts +29 -10
  78. package/src/components/menu/utils.ts +67 -0
  79. package/src/components/navigation/api.ts +78 -50
  80. package/src/components/navigation/config.ts +22 -10
  81. package/src/components/navigation/features/items.ts +284 -0
  82. package/src/components/navigation/index.ts +0 -6
  83. package/src/components/navigation/nav-item.ts +70 -33
  84. package/src/components/navigation/navigation.ts +53 -3
  85. package/src/components/navigation/types.ts +117 -70
  86. package/src/components/progress/api.ts +2 -3
  87. package/src/components/progress/config.ts +2 -3
  88. package/src/components/progress/index.ts +0 -1
  89. package/src/components/progress/progress.ts +1 -2
  90. package/src/components/progress/types.ts +186 -33
  91. package/src/components/radios/config.ts +1 -1
  92. package/src/components/radios/index.ts +0 -1
  93. package/src/components/radios/types.ts +0 -7
  94. package/src/components/search/api.ts +203 -0
  95. package/src/components/search/config.ts +86 -0
  96. package/src/components/search/features/index.ts +4 -0
  97. package/src/components/search/features/search.ts +717 -0
  98. package/src/components/search/features/states.ts +169 -0
  99. package/src/components/search/features/structure.ts +197 -0
  100. package/src/components/search/index.ts +7 -0
  101. package/src/components/search/search.ts +52 -0
  102. package/src/components/search/types.ts +175 -0
  103. package/src/components/segmented-button/config.ts +80 -0
  104. package/src/components/segmented-button/index.ts +4 -0
  105. package/src/components/segmented-button/segment.ts +154 -0
  106. package/src/components/segmented-button/segmented-button.ts +249 -0
  107. package/src/components/segmented-button/types.ts +254 -0
  108. package/src/components/slider/accessibility.md +5 -5
  109. package/src/components/slider/api.ts +41 -120
  110. package/src/components/slider/config.ts +51 -47
  111. package/src/components/slider/features/handlers.ts +495 -0
  112. package/src/components/slider/features/index.ts +1 -2
  113. package/src/components/slider/features/slider.ts +66 -84
  114. package/src/components/slider/features/states.ts +195 -0
  115. package/src/components/slider/features/structure.ts +136 -206
  116. package/src/components/slider/features/ui.ts +145 -206
  117. package/src/components/slider/index.ts +2 -11
  118. package/src/components/slider/slider.ts +9 -12
  119. package/src/components/slider/types.ts +67 -26
  120. package/src/components/snackbar/config.ts +2 -3
  121. package/src/components/snackbar/constants.ts +0 -32
  122. package/src/components/snackbar/index.ts +0 -1
  123. package/src/components/snackbar/position.ts +9 -1
  124. package/src/components/snackbar/types.ts +122 -46
  125. package/src/components/switch/config.ts +2 -3
  126. package/src/components/switch/index.ts +0 -1
  127. package/src/components/switch/types.ts +3 -2
  128. package/src/components/tabs/config.ts +3 -4
  129. package/src/components/tabs/features.ts +4 -2
  130. package/src/components/tabs/index.ts +0 -15
  131. package/src/components/tabs/indicator.ts +73 -13
  132. package/src/components/tabs/tab-api.ts +12 -4
  133. package/src/components/tabs/tab.ts +18 -6
  134. package/src/components/tabs/types.ts +23 -5
  135. package/src/components/textfield/config.ts +2 -3
  136. package/src/components/textfield/index.ts +0 -1
  137. package/src/components/textfield/types.ts +17 -3
  138. package/src/components/timepicker/README.md +277 -0
  139. package/src/components/timepicker/api.ts +632 -0
  140. package/src/components/timepicker/clockdial.ts +482 -0
  141. package/src/components/timepicker/config.ts +228 -0
  142. package/src/components/timepicker/index.ts +3 -0
  143. package/src/components/timepicker/render.ts +613 -0
  144. package/src/components/timepicker/timepicker.ts +117 -0
  145. package/src/components/timepicker/types.ts +336 -0
  146. package/src/components/timepicker/utils.ts +241 -0
  147. package/src/components/tooltip/api.ts +1 -1
  148. package/src/components/tooltip/config.ts +27 -6
  149. package/src/components/tooltip/index.ts +0 -1
  150. package/src/components/tooltip/types.ts +13 -3
  151. package/src/components/top-app-bar/config.ts +83 -0
  152. package/src/components/top-app-bar/index.ts +11 -0
  153. package/src/components/top-app-bar/top-app-bar.ts +316 -0
  154. package/src/components/top-app-bar/types.ts +140 -0
  155. package/src/core/build/_ripple.scss +6 -6
  156. package/src/core/build/ripple.ts +72 -95
  157. package/src/core/compose/features/icon.ts +3 -1
  158. package/src/core/compose/features/ripple.ts +4 -1
  159. package/src/core/compose/features/textlabel.ts +23 -2
  160. package/src/core/dom/create.ts +5 -0
  161. package/src/index.ts +9 -0
  162. package/src/styles/abstract/_theme.scss +9 -1
  163. package/src/styles/components/_badge.scss +182 -0
  164. package/src/styles/components/_bottom-app-bar.scss +103 -0
  165. package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -10
  166. package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -2
  167. package/src/styles/components/_datepicker.scss +358 -0
  168. package/src/styles/components/_dialog.scss +259 -0
  169. package/src/styles/components/_divider.scss +57 -0
  170. package/src/styles/components/_extended-fab.scss +267 -0
  171. package/src/styles/components/_fab.scss +225 -0
  172. package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +1 -0
  173. package/src/styles/components/_search.scss +306 -0
  174. package/src/styles/components/_segmented-button.scss +117 -0
  175. package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +83 -24
  176. package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -2
  177. package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +95 -33
  178. package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +70 -67
  179. package/src/styles/components/_timepicker.scss +451 -0
  180. package/src/styles/components/_top-app-bar.scss +225 -0
  181. package/src/styles/main.scss +98 -49
  182. package/src/styles/themes/_autumn.scss +21 -0
  183. package/src/styles/themes/_base-theme.scss +61 -0
  184. package/src/styles/themes/_baseline.scss +58 -0
  185. package/src/styles/themes/_bluekhaki.scss +125 -0
  186. package/src/styles/themes/_brownbeige.scss +125 -0
  187. package/src/styles/themes/_browngreen.scss +125 -0
  188. package/src/styles/themes/_forest.scss +6 -0
  189. package/src/styles/themes/_greenbeige.scss +125 -0
  190. package/src/styles/themes/_material.scss +125 -0
  191. package/src/styles/themes/_ocean.scss +6 -0
  192. package/src/styles/themes/_sageivory.scss +125 -0
  193. package/src/styles/themes/_spring.scss +6 -0
  194. package/src/styles/themes/_summer.scss +5 -0
  195. package/src/styles/themes/_sunset.scss +5 -0
  196. package/src/styles/themes/_tealcaramel.scss +125 -0
  197. package/src/styles/themes/_winter.scss +6 -0
  198. package/src/components/badge/_styles.scss +0 -174
  199. package/src/components/badge/constants.ts +0 -30
  200. package/src/components/button/constants.ts +0 -11
  201. package/src/components/card/constants.ts +0 -84
  202. package/src/components/dialog/_styles.scss +0 -213
  203. package/src/components/dialog/constants.ts +0 -32
  204. package/src/components/menu/constants.ts +0 -154
  205. package/src/components/navigation/constants.ts +0 -200
  206. package/src/components/navigation/features/items.js +0 -192
  207. package/src/components/progress/constants.ts +0 -29
  208. package/src/components/slider/features/appearance.ts +0 -94
  209. package/src/components/slider/features/disabled.ts +0 -68
  210. package/src/components/slider/features/events.ts +0 -164
  211. package/src/components/slider/features/interactions.ts +0 -396
  212. package/src/components/slider/features/keyboard.ts +0 -233
  213. package/src/components/switch/constants.ts +0 -80
  214. package/src/components/tabs/constants.ts +0 -89
  215. package/src/core/collection/adapters/mongodb.js +0 -232
  216. /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
  217. /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
  218. /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
  219. /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
  220. /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
  221. /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
  222. /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
  223. /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
  224. /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
  225. /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
  226. /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
@@ -4,12 +4,33 @@ import {
4
4
  createElementConfig
5
5
  } from '../../core/config/component-config';
6
6
  import { TooltipConfig } from './types';
7
- import {
8
- TOOLTIP_POSITIONS,
9
- TOOLTIP_VARIANTS,
10
- DEFAULT_SHOW_DELAY,
11
- DEFAULT_HIDE_DELAY
12
- } from './constants';
7
+
8
+
9
+ export const TOOLTIP_POSITIONS = {
10
+ TOP: 'top',
11
+ RIGHT: 'right',
12
+ BOTTOM: 'bottom',
13
+ LEFT: 'left',
14
+ TOP_START: 'top-start',
15
+ TOP_END: 'top-end',
16
+ RIGHT_START: 'right-start',
17
+ RIGHT_END: 'right-end',
18
+ BOTTOM_START: 'bottom-start',
19
+ BOTTOM_END: 'bottom-end',
20
+ LEFT_START: 'left-start',
21
+ LEFT_END: 'left-end'
22
+ }
23
+
24
+ export const TOOLTIP_VARIANTS = {
25
+ DEFAULT: 'default',
26
+ RICH: 'rich',
27
+ PLAIN: 'plain'
28
+ }
29
+
30
+ export const DEFAULT_SHOW_DELAY = 300
31
+ export const DEFAULT_HIDE_DELAY = 100
32
+ export const DEFAULT_OFFSET = 8
33
+ export const DEFAULT_ARROW_SIZE = 8
13
34
 
14
35
  /**
15
36
  * Default configuration for the Tooltip component
@@ -1,4 +1,3 @@
1
1
  // src/components/tooltip/index.ts
2
2
  export { default } from './tooltip';
3
- export { TOOLTIP_POSITIONS, TOOLTIP_VARIANTS } from './constants';
4
3
  export { TooltipConfig, TooltipComponent } from './types';
@@ -1,5 +1,15 @@
1
1
  // src/components/tooltip/types.ts
2
- import { TOOLTIP_POSITIONS, TOOLTIP_VARIANTS } from './constants';
2
+
3
+ /**
4
+ * Available Textfield variants
5
+ */
6
+ export type TooltipVariant = 'default' | 'rich' | 'plain';
7
+
8
+ /**
9
+ * Available Textfield states
10
+ */
11
+ export type TooltipPosition = 'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end';
12
+
3
13
 
4
14
  /**
5
15
  * Configuration interface for the Tooltip component
@@ -22,13 +32,13 @@ export interface TooltipConfig {
22
32
  * Tooltip position relative to the target
23
33
  * @default 'bottom'
24
34
  */
25
- position?: keyof typeof TOOLTIP_POSITIONS | string;
35
+ position?: TooltipPosition | string;
26
36
 
27
37
  /**
28
38
  * Tooltip variant that determines visual styling
29
39
  * @default 'default'
30
40
  */
31
- variant?: keyof typeof TOOLTIP_VARIANTS | string;
41
+ variant?: TooltipVariants | string;
32
42
 
33
43
  /**
34
44
  * Whether the tooltip is initially visible
@@ -0,0 +1,83 @@
1
+ // src/components/top-app-bar/config.ts
2
+ /**
3
+ * @module components/top-app-bar
4
+ * @description Configuration for top app bar component
5
+ */
6
+
7
+ import { createComponentConfig, BaseComponentConfig } from '../../core/config/component-config';
8
+ import { PREFIX } from '../../core/config';
9
+
10
+ /**
11
+ * Top App Bar types
12
+ */
13
+ export type TopAppBarType = 'small' | 'medium' | 'large' | 'center';
14
+
15
+ /**
16
+ * Configuration options for top app bar
17
+ */
18
+ export interface TopAppBarConfig extends BaseComponentConfig {
19
+ /**
20
+ * Element to use for the container
21
+ * @default 'header'
22
+ */
23
+ tag?: string;
24
+
25
+ /**
26
+ * Type of top app bar to display
27
+ * @default 'small'
28
+ */
29
+ type?: TopAppBarType;
30
+
31
+ /**
32
+ * Title text to display in the app bar
33
+ */
34
+ title?: string;
35
+
36
+ /**
37
+ * Whether to enable scrolling behavior
38
+ * @default true
39
+ */
40
+ scrollable?: boolean;
41
+
42
+ /**
43
+ * Whether to compress medium/large variants to small on scroll
44
+ * @default true
45
+ */
46
+ compressible?: boolean;
47
+
48
+ /**
49
+ * Scroll threshold in pixels to trigger the scrolled state
50
+ * @default 4
51
+ */
52
+ scrollThreshold?: number;
53
+
54
+ /**
55
+ * Additional CSS classes to apply
56
+ */
57
+ class?: string;
58
+
59
+ /**
60
+ * Optional callback when scrolling changes the bar appearance
61
+ */
62
+ onScroll?: (scrolled: boolean) => void;
63
+ }
64
+
65
+ /**
66
+ * Default configuration for top app bar
67
+ */
68
+ export const defaultConfig: Partial<TopAppBarConfig> = {
69
+ tag: 'header',
70
+ type: 'small',
71
+ scrollable: true,
72
+ compressible: true,
73
+ scrollThreshold: 4
74
+ };
75
+
76
+ /**
77
+ * Creates the configuration for a top app bar component
78
+ *
79
+ * @param {TopAppBarConfig} config - User provided configuration
80
+ * @returns {TopAppBarConfig} Complete configuration with defaults applied
81
+ */
82
+ export const createConfig = (config: TopAppBarConfig = {} as TopAppBarConfig): TopAppBarConfig =>
83
+ createComponentConfig(defaultConfig, config, 'top-app-bar') as TopAppBarConfig;
@@ -0,0 +1,11 @@
1
+ // src/components/top-app-bar/index.ts
2
+ /**
3
+ * @module components/top-app-bar
4
+ * @description Top app bar component for application headers
5
+ */
6
+
7
+ import { createTopAppBar } from './top-app-bar';
8
+
9
+ export default createTopAppBar;
10
+ export { createTopAppBar };
11
+ export type { TopAppBarConfig, TopAppBarType } from './config';
@@ -0,0 +1,316 @@
1
+ // src/components/top-app-bar/top-app-bar.ts
2
+ /**
3
+ * @module components/top-app-bar
4
+ * @description Top 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, TopAppBarConfig, TopAppBarType } from './config';
17
+
18
+ /**
19
+ * Top app bar component interface
20
+ */
21
+ export interface TopAppBar extends ElementComponent {
22
+ /**
23
+ * Sets the title of the top app bar
24
+ * @param {string} title - Title text
25
+ * @returns {TopAppBar} TopAppBar instance for chaining
26
+ */
27
+ setTitle: (title: string) => TopAppBar;
28
+
29
+ /**
30
+ * Gets the current title
31
+ * @returns {string} Current title text
32
+ */
33
+ getTitle: () => string;
34
+
35
+ /**
36
+ * Adds a leading navigation icon or element
37
+ * @param {HTMLElement} element - Element to add to the leading section
38
+ * @returns {TopAppBar} TopAppBar instance for chaining
39
+ */
40
+ addLeadingElement: (element: HTMLElement) => TopAppBar;
41
+
42
+ /**
43
+ * Adds a trailing action icon or element
44
+ * @param {HTMLElement} element - Element to add to the trailing section
45
+ * @returns {TopAppBar} TopAppBar instance for chaining
46
+ */
47
+ addTrailingElement: (element: HTMLElement) => TopAppBar;
48
+
49
+ /**
50
+ * Changes the top app bar type
51
+ * @param {TopAppBarType} type - New app bar type
52
+ * @returns {TopAppBar} TopAppBar instance for chaining
53
+ */
54
+ setType: (type: TopAppBarType) => TopAppBar;
55
+
56
+ /**
57
+ * Manually sets the scrolled state
58
+ * @param {boolean} scrolled - Whether to show the scrolled state
59
+ * @returns {TopAppBar} TopAppBar instance for chaining
60
+ */
61
+ setScrollState: (scrolled: boolean) => TopAppBar;
62
+
63
+ /**
64
+ * Gets the headline element
65
+ * @returns {HTMLElement} Headline element
66
+ */
67
+ getHeadlineElement: () => HTMLElement;
68
+
69
+ /**
70
+ * Gets the leading container element
71
+ * @returns {HTMLElement} Leading container element
72
+ */
73
+ getLeadingContainer: () => HTMLElement;
74
+
75
+ /**
76
+ * Gets the trailing container element
77
+ * @returns {HTMLElement} Trailing container element
78
+ */
79
+ getTrailingContainer: () => HTMLElement;
80
+ }
81
+
82
+ /**
83
+ * Creates a top app bar component
84
+ *
85
+ * @param {TopAppBarConfig} config - Configuration options
86
+ * @returns {TopAppBar} Top app bar component instance
87
+ */
88
+ export const createTopAppBar = (config: TopAppBarConfig = {}): TopAppBar => {
89
+ // Process configuration with defaults
90
+ const componentConfig = createConfig(config);
91
+
92
+ // Create base component
93
+ const component = createBase(componentConfig);
94
+
95
+ // Create containers for the top app bar structure
96
+ const createContainers = () => {
97
+ // Leading section container
98
+ const leadingContainer = document.createElement('div');
99
+ leadingContainer.className = `${component.getClass('top-app-bar')}-leading`;
100
+
101
+ // Headline element
102
+ const headlineElement = document.createElement('h1');
103
+ headlineElement.className = `${component.getClass('top-app-bar')}-headline`;
104
+ if (componentConfig.title) {
105
+ headlineElement.textContent = componentConfig.title;
106
+ }
107
+
108
+ // Trailing section container
109
+ const trailingContainer = document.createElement('div');
110
+ trailingContainer.className = `${component.getClass('top-app-bar')}-trailing`;
111
+
112
+ return { leadingContainer, headlineElement, trailingContainer };
113
+ };
114
+
115
+ // Create the main containers
116
+ const { leadingContainer, headlineElement, trailingContainer } = createContainers();
117
+
118
+ // Determine initial classes based on type
119
+ const getInitialClasses = () => {
120
+ const classes = [componentConfig.class];
121
+
122
+ // Add type class if not the default 'small' type
123
+ if (componentConfig.type !== 'small') {
124
+ classes.push(`${component.getClass('top-app-bar')}--${componentConfig.type}`);
125
+ }
126
+
127
+ // Add compressible class if enabled and type is medium or large
128
+ if (componentConfig.compressible &&
129
+ (componentConfig.type === 'medium' || componentConfig.type === 'large')) {
130
+ classes.push(`${component.getClass('top-app-bar')}--compressible`);
131
+ }
132
+
133
+ return classes.filter(Boolean);
134
+ };
135
+
136
+ // Apply Element enhancer
137
+ const enhancedComponent = withElement({
138
+ tag: componentConfig.tag,
139
+ componentName: 'top-app-bar',
140
+ className: getInitialClasses(),
141
+ attrs: {
142
+ role: 'banner',
143
+ 'aria-label': 'Top app bar'
144
+ },
145
+ interactive: true
146
+ })(component);
147
+
148
+ // Apply events enhancer for component events
149
+ const withEventsComponent = withEvents()(enhancedComponent);
150
+
151
+ // Apply lifecycle enhancer for cleanup
152
+ const withLifecycleComponent = withLifecycle()(withEventsComponent);
153
+
154
+ // Create the DOM structure based on the type
155
+ const setupDomStructure = () => {
156
+ if (componentConfig.type === 'medium' || componentConfig.type === 'large') {
157
+ // For medium and large, create rows
158
+ const topRow = document.createElement('div');
159
+ topRow.className = `${component.getClass('top-app-bar')}-row`;
160
+ topRow.appendChild(leadingContainer);
161
+ topRow.appendChild(trailingContainer);
162
+
163
+ const bottomRow = document.createElement('div');
164
+ bottomRow.className = `${component.getClass('top-app-bar')}-row`;
165
+ bottomRow.appendChild(headlineElement);
166
+
167
+ withLifecycleComponent.element.appendChild(topRow);
168
+ withLifecycleComponent.element.appendChild(bottomRow);
169
+ } else {
170
+ // For small and center-aligned
171
+ withLifecycleComponent.element.appendChild(leadingContainer);
172
+ withLifecycleComponent.element.appendChild(headlineElement);
173
+ withLifecycleComponent.element.appendChild(trailingContainer);
174
+ }
175
+ };
176
+
177
+ // Set up the initial DOM structure
178
+ setupDomStructure();
179
+
180
+ // Track scrolled state
181
+ let isScrolled = false;
182
+
183
+ // Handle scrolling behavior if enabled
184
+ if (componentConfig.scrollable) {
185
+ const handleScroll = () => {
186
+ const shouldBeScrolled = window.scrollY > componentConfig.scrollThreshold;
187
+
188
+ if (isScrolled !== shouldBeScrolled) {
189
+ isScrolled = shouldBeScrolled;
190
+
191
+ // Toggle scrolled class
192
+ if (isScrolled) {
193
+ withLifecycleComponent.element.classList.add(`${component.getClass('top-app-bar')}--scrolled`);
194
+ } else {
195
+ withLifecycleComponent.element.classList.remove(`${component.getClass('top-app-bar')}--scrolled`);
196
+ }
197
+
198
+ // Call the onScroll callback if provided
199
+ componentConfig.onScroll?.(isScrolled);
200
+ }
201
+ };
202
+
203
+ // Add scroll event listener
204
+ window.addEventListener('scroll', handleScroll, { passive: true });
205
+
206
+ // Initial check
207
+ handleScroll();
208
+
209
+ // Clean up event listener on destroy
210
+ const originalDestroy = withLifecycleComponent.lifecycle.destroy;
211
+ withLifecycleComponent.lifecycle.destroy = () => {
212
+ window.removeEventListener('scroll', handleScroll);
213
+ originalDestroy();
214
+ };
215
+ }
216
+
217
+ // Reorganize the DOM for the given type
218
+ const reorganizeDom = (type: TopAppBarType) => {
219
+ // Clear existing content
220
+ while (withLifecycleComponent.element.firstChild) {
221
+ withLifecycleComponent.element.removeChild(withLifecycleComponent.element.firstChild);
222
+ }
223
+
224
+ // Update component type class
225
+ ['small', 'medium', 'large', 'center'].forEach(t => {
226
+ withLifecycleComponent.element.classList.remove(`${component.getClass('top-app-bar')}--${t}`);
227
+ });
228
+
229
+ if (type !== 'small') {
230
+ withLifecycleComponent.element.classList.add(`${component.getClass('top-app-bar')}--${type}`);
231
+ }
232
+
233
+ // Update compressible class
234
+ withLifecycleComponent.element.classList.toggle(
235
+ `${component.getClass('top-app-bar')}--compressible`,
236
+ componentConfig.compressible && (type === 'medium' || type === 'large')
237
+ );
238
+
239
+ // Rebuild the DOM structure
240
+ if (type === 'medium' || type === 'large') {
241
+ // For medium and large, create rows
242
+ const topRow = document.createElement('div');
243
+ topRow.className = `${component.getClass('top-app-bar')}-row`;
244
+ topRow.appendChild(leadingContainer);
245
+ topRow.appendChild(trailingContainer);
246
+
247
+ const bottomRow = document.createElement('div');
248
+ bottomRow.className = `${component.getClass('top-app-bar')}-row`;
249
+ bottomRow.appendChild(headlineElement);
250
+
251
+ withLifecycleComponent.element.appendChild(topRow);
252
+ withLifecycleComponent.element.appendChild(bottomRow);
253
+ } else {
254
+ // For small and center-aligned
255
+ withLifecycleComponent.element.appendChild(leadingContainer);
256
+ withLifecycleComponent.element.appendChild(headlineElement);
257
+ withLifecycleComponent.element.appendChild(trailingContainer);
258
+ }
259
+ };
260
+
261
+ // Create the top app bar interface
262
+ const topAppBar: TopAppBar = {
263
+ ...withLifecycleComponent,
264
+
265
+ setTitle(title: string) {
266
+ headlineElement.textContent = title;
267
+ return this;
268
+ },
269
+
270
+ getTitle() {
271
+ return headlineElement.textContent || '';
272
+ },
273
+
274
+ addLeadingElement(element: HTMLElement) {
275
+ leadingContainer.appendChild(element);
276
+ return this;
277
+ },
278
+
279
+ addTrailingElement(element: HTMLElement) {
280
+ trailingContainer.appendChild(element);
281
+ return this;
282
+ },
283
+
284
+ setType(type: TopAppBarType) {
285
+ componentConfig.type = type;
286
+ reorganizeDom(type);
287
+ return this;
288
+ },
289
+
290
+ setScrollState(scrolled: boolean) {
291
+ isScrolled = scrolled;
292
+
293
+ if (scrolled) {
294
+ this.element.classList.add(`${component.getClass('top-app-bar')}--scrolled`);
295
+ } else {
296
+ this.element.classList.remove(`${component.getClass('top-app-bar')}--scrolled`);
297
+ }
298
+
299
+ return this;
300
+ },
301
+
302
+ getHeadlineElement() {
303
+ return headlineElement;
304
+ },
305
+
306
+ getLeadingContainer() {
307
+ return leadingContainer;
308
+ },
309
+
310
+ getTrailingContainer() {
311
+ return trailingContainer;
312
+ }
313
+ };
314
+
315
+ return topAppBar;
316
+ };
@@ -0,0 +1,140 @@
1
+ // src/components/top-app-bar/types.ts
2
+ /**
3
+ * @module components/top-app-bar
4
+ * @description Type definitions for Top App Bar component
5
+ */
6
+
7
+ import { ElementComponent } from '../../core/compose';
8
+
9
+ /**
10
+ * Top App Bar types
11
+ * @category Components
12
+ */
13
+ export type TopAppBarType = 'small' | 'medium' | 'large' | 'center';
14
+
15
+ /**
16
+ * Configuration options for Top App Bar component
17
+ * @category Components
18
+ */
19
+ export interface TopAppBarConfig {
20
+ /**
21
+ * Element to use for the container
22
+ * @default 'header'
23
+ */
24
+ tag?: string;
25
+
26
+ /**
27
+ * Type of top app bar to display
28
+ * @default 'small'
29
+ */
30
+ type?: TopAppBarType;
31
+
32
+ /**
33
+ * Title text to display in the app bar
34
+ */
35
+ title?: string;
36
+
37
+ /**
38
+ * Whether to enable scrolling behavior
39
+ * @default true
40
+ */
41
+ scrollable?: boolean;
42
+
43
+ /**
44
+ * Whether to compress medium/large variants to small on scroll
45
+ * @default true
46
+ */
47
+ compressible?: boolean;
48
+
49
+ /**
50
+ * Scroll threshold in pixels to trigger the scrolled state
51
+ * @default 4
52
+ */
53
+ scrollThreshold?: number;
54
+
55
+ /**
56
+ * Additional CSS classes to apply
57
+ */
58
+ class?: string;
59
+
60
+ /**
61
+ * Optional callback when scrolling changes the bar appearance
62
+ */
63
+ onScroll?: (scrolled: boolean) => void;
64
+
65
+ /**
66
+ * Component prefix for class names
67
+ * @default 'mtrl'
68
+ */
69
+ prefix?: string;
70
+
71
+ /**
72
+ * Component name for class generation
73
+ */
74
+ componentName?: string;
75
+ }
76
+
77
+ /**
78
+ * Top App Bar component interface
79
+ * @category Components
80
+ */
81
+ export interface TopAppBar extends ElementComponent {
82
+ /**
83
+ * Sets the title of the top app bar
84
+ * @param {string} title - Title text
85
+ * @returns {TopAppBar} TopAppBar instance for chaining
86
+ */
87
+ setTitle: (title: string) => TopAppBar;
88
+
89
+ /**
90
+ * Gets the current title
91
+ * @returns {string} Current title text
92
+ */
93
+ getTitle: () => string;
94
+
95
+ /**
96
+ * Adds a leading navigation icon or element
97
+ * @param {HTMLElement} element - Element to add to the leading section
98
+ * @returns {TopAppBar} TopAppBar instance for chaining
99
+ */
100
+ addLeadingElement: (element: HTMLElement) => TopAppBar;
101
+
102
+ /**
103
+ * Adds a trailing action icon or element
104
+ * @param {HTMLElement} element - Element to add to the trailing section
105
+ * @returns {TopAppBar} TopAppBar instance for chaining
106
+ */
107
+ addTrailingElement: (element: HTMLElement) => TopAppBar;
108
+
109
+ /**
110
+ * Changes the top app bar type
111
+ * @param {TopAppBarType} type - New app bar type
112
+ * @returns {TopAppBar} TopAppBar instance for chaining
113
+ */
114
+ setType: (type: TopAppBarType) => TopAppBar;
115
+
116
+ /**
117
+ * Manually sets the scrolled state
118
+ * @param {boolean} scrolled - Whether to show the scrolled state
119
+ * @returns {TopAppBar} TopAppBar instance for chaining
120
+ */
121
+ setScrollState: (scrolled: boolean) => TopAppBar;
122
+
123
+ /**
124
+ * Gets the headline element
125
+ * @returns {HTMLElement} Headline element
126
+ */
127
+ getHeadlineElement: () => HTMLElement;
128
+
129
+ /**
130
+ * Gets the leading container element
131
+ * @returns {HTMLElement} Leading container element
132
+ */
133
+ getLeadingContainer: () => HTMLElement;
134
+
135
+ /**
136
+ * Gets the trailing container element
137
+ * @returns {HTMLElement} Trailing container element
138
+ */
139
+ getTrailingContainer: () => HTMLElement;
140
+ }
@@ -19,20 +19,20 @@ $component: '#{base.$prefix}-ripple';
19
19
  pointer-events: none;
20
20
  z-index: 0;
21
21
 
22
- // Ripple element
23
22
  &-wave {
24
23
  position: absolute;
25
24
  border-radius: 50%;
25
+
26
+ // Make the ripple more visible with these changes:
26
27
  background-color: currentColor;
27
- transform: scale(0);
28
- opacity: 0;
28
+ opacity: 0; // Start with 0 opacity
29
+ transform: scale(0); // Start slightly larger for better visibility
29
30
  pointer-events: none;
30
31
  will-change: transform, opacity;
31
32
 
32
33
  // Animation
33
- transition-property: transform, opacity;
34
- transition-duration: v.motion('duration-short4');
35
- transition-timing-function: v.motion('easing-standard');
34
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1),
35
+ opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
36
36
 
37
37
  // Active ripple
38
38
  &.active {