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.
- package/demo/build.ts +349 -0
- package/demo/index.html +110 -0
- package/demo/main.js +448 -0
- package/demo/styles.css +239 -0
- package/index.ts +18 -0
- package/package.json +14 -3
- package/server.ts +86 -0
- package/src/components/badge/api.ts +70 -63
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +66 -13
- package/src/components/badge/features.ts +51 -42
- package/src/components/badge/index.ts +27 -2
- package/src/components/badge/types.ts +62 -30
- package/src/components/bottom-app-bar/bottom-app-bar.ts +154 -0
- package/src/components/bottom-app-bar/config.ts +29 -0
- package/src/components/bottom-app-bar/index.ts +17 -0
- package/src/components/bottom-app-bar/types.ts +114 -0
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -1
- package/src/components/button/config.ts +6 -2
- package/src/components/button/index.ts +10 -2
- package/src/components/button/types.ts +20 -2
- package/src/components/card/card.ts +13 -25
- package/src/components/card/config.ts +83 -30
- package/src/components/card/content.ts +8 -10
- package/src/components/card/features.ts +4 -3
- package/src/components/card/index.ts +29 -2
- package/src/components/card/types.ts +33 -22
- package/src/components/checkbox/config.ts +3 -4
- package/src/components/checkbox/index.ts +1 -2
- package/src/components/checkbox/types.ts +12 -3
- package/src/components/chip/api.ts +170 -221
- package/src/components/chip/chip.ts +34 -302
- package/src/components/chip/config.ts +1 -2
- package/src/components/chip/index.ts +10 -2
- package/src/components/chip/types.ts +224 -35
- package/src/components/datepicker/api.ts +265 -0
- package/src/components/datepicker/config.ts +141 -0
- package/src/components/datepicker/datepicker.ts +341 -0
- package/src/components/datepicker/index.ts +12 -0
- package/src/components/datepicker/render.ts +450 -0
- package/src/components/datepicker/types.ts +397 -0
- package/src/components/datepicker/utils.ts +289 -0
- package/src/components/dialog/api.ts +55 -21
- package/src/components/dialog/config.ts +12 -9
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +345 -151
- package/src/components/dialog/index.ts +38 -8
- package/src/components/dialog/types.ts +40 -14
- 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 +9 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +112 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +9 -0
- package/src/components/extended-fab/types.ts +304 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +93 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +9 -0
- package/src/components/fab/types.ts +251 -0
- package/src/components/list/config.ts +4 -5
- package/src/components/list/features.ts +6 -7
- package/src/components/list/index.ts +7 -9
- package/src/components/list/list-item.ts +12 -13
- package/src/components/list/types.ts +50 -5
- package/src/components/list/utils.ts +30 -3
- package/src/components/menu/features/items-manager.ts +9 -9
- package/src/components/menu/features/positioning.ts +7 -7
- package/src/components/menu/features/visibility.ts +7 -7
- package/src/components/menu/index.ts +7 -9
- package/src/components/menu/menu-item.ts +6 -6
- package/src/components/menu/menu.ts +22 -0
- package/src/components/menu/types.ts +29 -10
- package/src/components/menu/utils.ts +67 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/config.ts +22 -10
- package/src/components/navigation/features/items.ts +284 -0
- package/src/components/navigation/index.ts +0 -6
- package/src/components/navigation/nav-item.ts +70 -33
- package/src/components/navigation/navigation.ts +53 -3
- package/src/components/navigation/types.ts +117 -70
- package/src/components/progress/api.ts +2 -3
- package/src/components/progress/config.ts +2 -3
- package/src/components/progress/index.ts +0 -1
- package/src/components/progress/progress.ts +1 -2
- package/src/components/progress/types.ts +186 -33
- package/src/components/radios/config.ts +1 -1
- package/src/components/radios/index.ts +0 -1
- package/src/components/radios/types.ts +0 -7
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +86 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +717 -0
- package/src/components/search/features/states.ts +169 -0
- package/src/components/search/features/structure.ts +197 -0
- package/src/components/search/index.ts +7 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +175 -0
- package/src/components/segmented-button/config.ts +80 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +154 -0
- package/src/components/segmented-button/segmented-button.ts +249 -0
- package/src/components/segmented-button/types.ts +254 -0
- package/src/components/slider/accessibility.md +5 -5
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -47
- 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 +136 -206
- package/src/components/slider/features/ui.ts +145 -206
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +67 -26
- package/src/components/snackbar/config.ts +2 -3
- package/src/components/snackbar/constants.ts +0 -32
- package/src/components/snackbar/index.ts +0 -1
- package/src/components/snackbar/position.ts +9 -1
- package/src/components/snackbar/types.ts +122 -46
- package/src/components/switch/config.ts +2 -3
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/types.ts +3 -2
- package/src/components/tabs/config.ts +3 -4
- package/src/components/tabs/features.ts +4 -2
- package/src/components/tabs/index.ts +0 -15
- package/src/components/tabs/indicator.ts +73 -13
- package/src/components/tabs/tab-api.ts +12 -4
- package/src/components/tabs/tab.ts +18 -6
- package/src/components/tabs/types.ts +23 -5
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/index.ts +0 -1
- package/src/components/textfield/types.ts +17 -3
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +228 -0
- package/src/components/timepicker/index.ts +3 -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/tooltip/api.ts +1 -1
- package/src/components/tooltip/config.ts +27 -6
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/types.ts +13 -3
- 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/features/icon.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +23 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +9 -1
- package/src/styles/components/_badge.scss +182 -0
- package/src/styles/components/_bottom-app-bar.scss +103 -0
- package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -10
- package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -2
- package/src/styles/components/_datepicker.scss +358 -0
- package/src/styles/components/_dialog.scss +259 -0
- package/src/styles/components/_divider.scss +57 -0
- package/src/styles/components/_extended-fab.scss +267 -0
- package/src/styles/components/_fab.scss +225 -0
- package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +1 -0
- package/src/styles/components/_search.scss +306 -0
- package/src/styles/components/_segmented-button.scss +117 -0
- package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +83 -24
- package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -2
- package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +95 -33
- package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +70 -67
- package/src/styles/components/_timepicker.scss +451 -0
- package/src/styles/components/_top-app-bar.scss +225 -0
- package/src/styles/main.scss +98 -49
- 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/badge/_styles.scss +0 -174
- package/src/components/badge/constants.ts +0 -30
- package/src/components/button/constants.ts +0 -11
- package/src/components/card/constants.ts +0 -84
- package/src/components/dialog/_styles.scss +0 -213
- package/src/components/dialog/constants.ts +0 -32
- package/src/components/menu/constants.ts +0 -154
- package/src/components/navigation/constants.ts +0 -200
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/progress/constants.ts +0 -29
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -68
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -396
- package/src/components/slider/features/keyboard.ts +0 -233
- package/src/components/switch/constants.ts +0 -80
- package/src/components/tabs/constants.ts +0 -89
- package/src/core/collection/adapters/mongodb.js +0 -232
- /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
- /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
- /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
- /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
- /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
- /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
- /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
- /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
- /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
- /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
- /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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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,5 +1,15 @@
|
|
|
1
1
|
// src/components/tooltip/types.ts
|
|
2
|
-
|
|
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?:
|
|
35
|
+
position?: TooltipPosition | string;
|
|
26
36
|
|
|
27
37
|
/**
|
|
28
38
|
* Tooltip variant that determines visual styling
|
|
29
39
|
* @default 'default'
|
|
30
40
|
*/
|
|
31
|
-
variant?:
|
|
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
|
-
|
|
28
|
-
|
|
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
|
|
34
|
-
|
|
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 {
|