mtrl 0.3.1 → 0.3.2
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/.env +15 -0
- package/CONTRIBUTING.md +8 -8
- package/DOCS.md +3 -3
- package/README.md +43 -20
- package/TESTING.md +128 -18
- package/dist/index.js +14865 -0
- package/git-user-stats.js +545 -0
- package/index.ts +9 -67
- package/package.json +8 -3
- package/src/components/badge/api.ts +15 -1
- package/src/components/badge/badge.ts +43 -4
- package/src/components/badge/config.ts +40 -8
- package/src/components/badge/index.ts +64 -3
- package/src/components/badge/types.ts +175 -33
- package/src/components/button/api.ts +63 -1
- package/src/components/button/button.ts +39 -3
- package/src/components/button/config.ts +21 -4
- package/src/components/button/index.ts +26 -1
- package/src/components/button/types.ts +7 -1
- package/src/components/card/api.ts +78 -9
- package/src/components/card/card.ts +58 -3
- package/src/components/card/config.ts +41 -11
- package/src/components/card/features.ts +39 -12
- package/src/components/card/index.ts +84 -19
- package/src/components/card/types.ts +218 -29
- package/src/components/carousel/carousel.ts +92 -28
- package/src/components/carousel/constants.ts +107 -21
- package/src/components/carousel/index.ts +31 -13
- package/src/components/checkbox/checkbox.ts +83 -16
- package/src/components/checkbox/index.ts +43 -1
- package/src/components/checkbox/types.ts +219 -32
- package/src/components/chips/api.ts +194 -0
- package/src/components/{chip → chips/chip}/api.ts +42 -2
- package/src/components/chips/chip/chip.ts +131 -0
- package/src/components/{chip → chips/chip}/config.ts +3 -3
- package/src/components/chips/chip/index.ts +3 -0
- package/src/components/chips/chips.md +481 -0
- package/src/components/chips/chips.ts +75 -0
- package/src/components/chips/config.ts +109 -0
- package/src/components/chips/constants.ts +61 -0
- package/src/components/chips/features/chip-items.ts +33 -0
- package/src/components/chips/features/container.ts +77 -0
- package/src/components/chips/features/controller.ts +448 -0
- package/src/components/chips/features/index.ts +5 -0
- package/src/components/chips/features/label.ts +108 -0
- package/src/components/chips/index.ts +11 -0
- package/src/components/chips/schema.ts +61 -0
- package/src/components/{chip → chips}/types.ts +203 -92
- package/src/components/dialog/dialog.ts +99 -16
- package/src/components/dialog/index.ts +97 -1
- package/src/components/dialog/types.ts +375 -69
- package/src/components/divider/config.ts +90 -6
- package/src/components/divider/divider.ts +32 -2
- package/src/components/divider/features.ts +26 -0
- package/src/components/divider/index.ts +30 -0
- package/src/components/divider/types.ts +86 -9
- package/src/components/extended-fab/api.ts +53 -1
- package/src/components/extended-fab/config.ts +29 -1
- package/src/components/extended-fab/extended-fab.ts +28 -0
- package/src/components/extended-fab/index.ts +36 -0
- package/src/components/extended-fab/types.ts +458 -13
- package/src/components/fab/api.ts +42 -2
- package/src/components/fab/config.ts +29 -1
- package/src/components/fab/fab.ts +16 -2
- package/src/components/fab/index.ts +35 -0
- package/src/components/fab/types.ts +374 -10
- package/src/components/list/api.ts +12 -2
- package/src/components/list/config.ts +21 -0
- package/src/components/list/features.ts +6 -0
- package/src/components/list/index.ts +56 -1
- package/src/components/list/list-item.ts +46 -2
- package/src/components/list/list.ts +73 -2
- package/src/components/list/types.ts +172 -0
- package/src/components/list/utils.ts +26 -2
- package/src/components/menu/api.ts +217 -20
- package/src/components/menu/config.ts +27 -0
- package/src/components/menu/features/visibility.ts +55 -6
- package/src/components/menu/index.ts +64 -0
- package/src/components/menu/menu-item.ts +46 -3
- package/src/components/menu/menu.ts +77 -1
- package/src/components/menu/types.ts +404 -39
- package/src/components/sheet/config.ts +1 -2
- package/src/components/sheet/features/gestures.ts +1 -1
- package/src/components/sheet/features/position.ts +1 -2
- package/src/components/sheet/features/state.ts +1 -1
- package/src/components/sheet/index.ts +10 -2
- package/src/components/sheet/sheet.ts +1 -2
- package/src/components/sheet/types.ts +29 -1
- package/src/components/slider/api.ts +1 -1
- package/src/components/slider/config.ts +1 -1
- package/src/components/slider/features/controller.ts +1 -1
- package/src/components/slider/features/handlers.ts +1 -1
- package/src/components/slider/features/states.ts +1 -1
- package/src/components/slider/index.ts +12 -5
- package/src/components/slider/schema.ts +1 -1
- package/src/components/slider/types.ts +31 -0
- package/src/components/tabs/tab-api.ts +1 -1
- package/src/components/tabs/types.ts +1 -1
- package/src/components/tooltip/api.ts +6 -2
- package/src/components/tooltip/config.ts +9 -28
- package/src/components/tooltip/index.ts +10 -1
- package/src/components/tooltip/types.ts +38 -3
- package/src/index.ts +129 -31
- package/src/styles/abstract/_mixins.scss +23 -9
- package/src/styles/abstract/_variables.scss +14 -4
- package/src/styles/components/_card.scss +1 -1
- package/src/styles/components/_chip.scss +323 -113
- package/src/styles/components/_tabs.scss +1 -1
- package/CLAUDE.md +0 -33
- package/src/components/checkbox/constants.ts +0 -37
- package/src/components/chip/chip-set.ts +0 -225
- package/src/components/chip/chip.ts +0 -118
- package/src/components/chip/constants.ts +0 -28
- package/src/components/chip/index.ts +0 -12
- package/src/components/list/constants.ts +0 -116
- package/src/components/sheet/constants.ts +0 -20
- package/src/components/slider/constants.ts +0 -32
- package/src/components/tooltip/constants.ts +0 -27
- package/test/components/badge.test.ts +0 -545
- package/test/components/bottom-app-bar.test.ts +0 -303
- package/test/components/button.test.ts +0 -233
- package/test/components/card.test.ts +0 -560
- package/test/components/carousel.test.ts +0 -951
- package/test/components/checkbox.test.ts +0 -462
- package/test/components/chip.test.ts +0 -692
- package/test/components/datepicker.test.ts +0 -1124
- package/test/components/dialog.test.ts +0 -990
- package/test/components/divider.test.ts +0 -412
- package/test/components/extended-fab.test.ts +0 -672
- package/test/components/fab.test.ts +0 -561
- package/test/components/list.test.ts +0 -365
- package/test/components/menu.test.ts +0 -718
- package/test/components/navigation.test.ts +0 -186
- package/test/components/progress.test.ts +0 -567
- package/test/components/radios.test.ts +0 -699
- package/test/components/search.test.ts +0 -1135
- package/test/components/segmented-button.test.ts +0 -732
- package/test/components/sheet.test.ts +0 -641
- package/test/components/slider.test.ts +0 -1220
- package/test/components/snackbar.test.ts +0 -461
- package/test/components/switch.test.ts +0 -452
- package/test/components/tabs.test.ts +0 -1369
- package/test/components/textfield.test.ts +0 -400
- package/test/components/timepicker.test.ts +0 -592
- package/test/components/tooltip.test.ts +0 -630
- package/test/components/top-app-bar.test.ts +0 -566
- package/test/core/dom.attributes.test.ts +0 -148
- package/test/core/dom.classes.test.ts +0 -152
- package/test/core/dom.events.test.ts +0 -243
- package/test/core/emitter.test.ts +0 -141
- package/test/core/ripple.test.ts +0 -99
- package/test/core/state.store.test.ts +0 -189
- package/test/core/utils.normalize.test.ts +0 -61
- package/test/core/utils.object.test.ts +0 -120
- package/test/setup.js +0 -371
- package/test/setup.ts +0 -451
- package/tsconfig.json +0 -22
- package/typedoc.json +0 -28
- package/typedoc.simple.json +0 -14
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
// src/components/carousel/
|
|
1
|
+
// src/components/carousel/carousel.ts
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Creates carousels with different layouts based on Material Design 3 guidelines.
|
|
4
4
|
*
|
|
5
|
-
* This
|
|
6
|
-
* - Multi-browse: For browsing many visual items at once (photos,
|
|
7
|
-
* - Uncontained: For
|
|
8
|
-
* - Hero: For spotlighting
|
|
5
|
+
* This module implements a carousel component that supports four layout types:
|
|
6
|
+
* - Multi-browse: For browsing many visual items at once (photos, feeds)
|
|
7
|
+
* - Uncontained: For customized or text-heavy carousels (traditional)
|
|
8
|
+
* - Hero: For spotlighting large visual items (featured content)
|
|
9
9
|
* - Full-screen: For immersive vertical-scrolling experiences
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Each layout is optimized for different content types and presentation needs,
|
|
12
|
+
* following the Material Design 3 component guidelines.
|
|
13
|
+
*
|
|
14
|
+
* @module components/carousel
|
|
15
|
+
* @category Components
|
|
12
16
|
*/
|
|
13
17
|
|
|
14
18
|
import { pipe } from '../../core/compose';
|
|
@@ -26,15 +30,22 @@ import { createBaseConfig, getElementConfig } from './config';
|
|
|
26
30
|
import { CAROUSEL_DEFAULTS } from './constants';
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
|
-
* Creates a new carousel with specified
|
|
33
|
+
* Creates a new carousel component with the specified configuration.
|
|
30
34
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
35
|
+
* The carousel supports different layout types for various content
|
|
36
|
+
* presentation needs, from image galleries to full-screen experiences.
|
|
37
|
+
* It handles gesture interactions, keyboard navigation, and responsive
|
|
38
|
+
* behavior following Material Design 3 guidelines.
|
|
39
|
+
*
|
|
40
|
+
* @param {CarouselConfig} config - Configuration options for the carousel
|
|
41
|
+
* @returns {CarouselComponent} A fully configured carousel component instance
|
|
42
|
+
* @throws {Error} Throws an error if carousel creation fails
|
|
43
|
+
*
|
|
44
|
+
* @category Components
|
|
33
45
|
*
|
|
34
46
|
* @example
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* const carousel = createCarousel({
|
|
47
|
+
* // Create a multi-browse carousel for a photo gallery
|
|
48
|
+
* const photoGallery = createCarousel({
|
|
38
49
|
* layout: 'multi-browse',
|
|
39
50
|
* scrollBehavior: 'snap',
|
|
40
51
|
* slides: [
|
|
@@ -44,9 +55,36 @@ import { CAROUSEL_DEFAULTS } from './constants';
|
|
|
44
55
|
* showAllLink: true
|
|
45
56
|
* });
|
|
46
57
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
58
|
+
* document.getElementById('gallery-container').appendChild(photoGallery.element);
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Create a hero carousel for featured content
|
|
62
|
+
* const featuredContent = createCarousel({
|
|
63
|
+
* layout: 'hero',
|
|
64
|
+
* centered: true,
|
|
65
|
+
* gap: 16,
|
|
66
|
+
* slides: [
|
|
67
|
+
* { image: 'hero1.jpg', title: 'Featured Story', buttonText: 'Read More' },
|
|
68
|
+
* { image: 'hero2.jpg', title: 'Special Offer', buttonText: 'Shop Now' }
|
|
69
|
+
* ]
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* // Listen for slide changes
|
|
73
|
+
* featuredContent.on('slide-changed', (index) => {
|
|
74
|
+
* console.log(`Now showing featured item ${index}`);
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Create a full-screen immersive carousel
|
|
79
|
+
* const storyViewer = createCarousel({
|
|
80
|
+
* layout: 'full-screen',
|
|
81
|
+
* loop: false,
|
|
82
|
+
* transition: 'fade',
|
|
83
|
+
* slides: [
|
|
84
|
+
* { image: 'story1.jpg', description: 'Chapter 1' },
|
|
85
|
+
* { image: 'story2.jpg', description: 'Chapter 2' }
|
|
86
|
+
* ]
|
|
87
|
+
* });
|
|
50
88
|
*/
|
|
51
89
|
export const createCarousel = (config: CarouselConfig = {}): CarouselComponent => {
|
|
52
90
|
// Ensure layout and scrollBehavior have defaults
|
|
@@ -106,72 +144,98 @@ export const createCarousel = (config: CarouselConfig = {}): CarouselComponent =
|
|
|
106
144
|
};
|
|
107
145
|
|
|
108
146
|
/**
|
|
109
|
-
*
|
|
147
|
+
* Determines the optimal scroll behavior based on the selected layout type.
|
|
148
|
+
*
|
|
149
|
+
* Material Design 3 recommendations suggest different scroll behaviors
|
|
150
|
+
* for each layout type to provide the best user experience.
|
|
110
151
|
*
|
|
111
152
|
* @param {CarouselLayout} layout - Carousel layout type
|
|
112
|
-
* @returns {CarouselScrollBehavior}
|
|
153
|
+
* @returns {CarouselScrollBehavior} The recommended scroll behavior
|
|
154
|
+
* @category Components
|
|
155
|
+
* @internal
|
|
113
156
|
*/
|
|
114
157
|
function getDefaultScrollBehavior(layout: CarouselLayout): CarouselScrollBehavior {
|
|
115
158
|
switch (layout) {
|
|
159
|
+
// These layouts work best with snap scrolling for defined stops
|
|
116
160
|
case 'multi-browse':
|
|
117
161
|
case 'hero':
|
|
118
162
|
case 'full-screen':
|
|
119
163
|
return 'snap';
|
|
164
|
+
|
|
165
|
+
// Uncontained layout works best with standard scrolling
|
|
120
166
|
case 'uncontained':
|
|
121
167
|
return 'default';
|
|
168
|
+
|
|
169
|
+
// Default to standard scrolling for unknown layouts
|
|
122
170
|
default:
|
|
123
171
|
return 'default';
|
|
124
172
|
}
|
|
125
173
|
}
|
|
126
174
|
|
|
127
175
|
/**
|
|
128
|
-
*
|
|
176
|
+
* Applies layout-specific configurations and styling to the carousel component.
|
|
177
|
+
*
|
|
178
|
+
* Each carousel layout has specific CSS properties, data attributes,
|
|
179
|
+
* and behaviors that optimize it for different content types.
|
|
180
|
+
* This function sets up those properties based on the selected layout.
|
|
129
181
|
*
|
|
130
182
|
* @param {any} component - The component to configure
|
|
131
183
|
* @param {CarouselConfig} config - Carousel configuration
|
|
184
|
+
* @category Components
|
|
185
|
+
* @internal
|
|
132
186
|
*/
|
|
133
187
|
function applyLayoutConfig(component: any, config: CarouselConfig): void {
|
|
134
|
-
// Add layout-specific class
|
|
188
|
+
// Add layout-specific class for CSS targeting
|
|
135
189
|
component.element.classList.add(`${component.getClass('carousel')}-layout--${config.layout}`);
|
|
136
190
|
|
|
137
|
-
// Apply
|
|
191
|
+
// Apply layout-specific configurations
|
|
138
192
|
switch (config.layout) {
|
|
139
193
|
case 'multi-browse':
|
|
140
|
-
//
|
|
194
|
+
// Multi-browse layout: For browsing many visual items at once
|
|
195
|
+
// Shows items of varying sizes with parallax scrolling effect
|
|
141
196
|
component.element.dataset.enableParallax = 'true';
|
|
197
|
+
component.element.dataset.layout = 'multi-browse';
|
|
142
198
|
break;
|
|
143
199
|
|
|
144
200
|
case 'uncontained':
|
|
145
|
-
//
|
|
201
|
+
// Uncontained layout: For text-heavy or consistent-sized items
|
|
202
|
+
// Allows content to flow past the viewport edges
|
|
146
203
|
component.element.style.overflow = 'visible';
|
|
204
|
+
component.element.dataset.layout = 'uncontained';
|
|
147
205
|
break;
|
|
148
206
|
|
|
149
207
|
case 'hero':
|
|
150
|
-
//
|
|
208
|
+
// Hero layout: For spotlighting featured content
|
|
209
|
+
// Large central item with preview of adjacent items
|
|
151
210
|
component.element.dataset.largeItemFocus = 'true';
|
|
211
|
+
component.element.dataset.layout = 'hero';
|
|
152
212
|
|
|
153
|
-
//
|
|
213
|
+
// Optionally center items for balanced presentation
|
|
154
214
|
if (config.centered) {
|
|
155
215
|
component.element.dataset.centered = 'true';
|
|
156
216
|
}
|
|
157
217
|
break;
|
|
158
218
|
|
|
159
219
|
case 'full-screen':
|
|
160
|
-
//
|
|
220
|
+
// Full-screen layout: For immersive experiences
|
|
221
|
+
// Takes up entire viewport and supports vertical scrolling
|
|
161
222
|
component.element.style.width = '100%';
|
|
162
223
|
component.element.style.height = '100%';
|
|
163
224
|
component.element.style.maxWidth = '100vw';
|
|
164
225
|
component.element.style.maxHeight = '100vh';
|
|
165
226
|
component.element.dataset.verticalScroll = 'true';
|
|
227
|
+
component.element.dataset.layout = 'full-screen';
|
|
166
228
|
|
|
167
|
-
//
|
|
229
|
+
// Full-screen layout always uses snap scrolling for controlled navigation
|
|
168
230
|
config.scrollBehavior = 'snap';
|
|
169
231
|
break;
|
|
170
232
|
}
|
|
171
233
|
|
|
172
|
-
// Apply scroll behavior
|
|
234
|
+
// Apply scroll behavior data attribute for CSS targeting
|
|
173
235
|
if (config.scrollBehavior === 'snap') {
|
|
174
236
|
component.element.dataset.snapScroll = 'true';
|
|
237
|
+
} else {
|
|
238
|
+
component.element.dataset.snapScroll = 'false';
|
|
175
239
|
}
|
|
176
240
|
}
|
|
177
241
|
|
|
@@ -2,94 +2,180 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Carousel layout types as defined by Material Design 3
|
|
5
|
+
*
|
|
6
|
+
* Material Design 3 defines specific layout patterns for carousels
|
|
7
|
+
* to accommodate different content presentation needs.
|
|
8
|
+
*
|
|
9
|
+
* @category Components
|
|
10
|
+
* @see https://material.io/components/carousel
|
|
5
11
|
*/
|
|
6
12
|
export const CAROUSEL_LAYOUTS = {
|
|
7
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Multi-browse layout: Best for browsing many visual items at once
|
|
15
|
+
* Ideal for photo galleries, product collections, or event feeds
|
|
16
|
+
* Shows multiple items in a single view with varying sizes
|
|
17
|
+
*/
|
|
8
18
|
MULTI_BROWSE: 'multi-browse',
|
|
9
19
|
|
|
10
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Uncontained layout: For highly customized or text-heavy carousels
|
|
22
|
+
* Traditional horizontal scrolling behavior without special styling
|
|
23
|
+
* Content can extend beyond viewport edges with consistent sizing
|
|
24
|
+
*/
|
|
11
25
|
UNCONTAINED: 'uncontained',
|
|
12
26
|
|
|
13
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Hero layout: For spotlighting very large visual items
|
|
29
|
+
* Highlights featured content with a large central item
|
|
30
|
+
* Shows a partial preview of the next/previous items
|
|
31
|
+
*/
|
|
14
32
|
HERO: 'hero',
|
|
15
33
|
|
|
16
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Full-screen layout: For immersive vertical-scrolling experiences
|
|
36
|
+
* Takes up entire viewport with snap scrolling between items
|
|
37
|
+
* Suited for immersive content or focused presentations
|
|
38
|
+
*/
|
|
17
39
|
FULL_SCREEN: 'full-screen'
|
|
18
40
|
} as const;
|
|
19
41
|
|
|
20
42
|
/**
|
|
21
43
|
* Carousel scroll behaviors
|
|
44
|
+
*
|
|
45
|
+
* Controls how scrolling behaves when moving between items.
|
|
46
|
+
* Each layout type has a recommended default behavior.
|
|
47
|
+
*
|
|
48
|
+
* @category Components
|
|
22
49
|
*/
|
|
23
50
|
export const CAROUSEL_SCROLL_BEHAVIORS = {
|
|
24
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Default: Standard smooth scrolling without snapping
|
|
53
|
+
* Users can stop at any position between items
|
|
54
|
+
* Recommended for uncontained layouts and content browsing
|
|
55
|
+
*/
|
|
25
56
|
DEFAULT: 'default',
|
|
26
57
|
|
|
27
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Snap: Items snap to predefined positions when scrolling
|
|
60
|
+
* Ensures items are properly aligned for viewing
|
|
61
|
+
* Recommended for multi-browse, hero, and full-screen layouts
|
|
62
|
+
*/
|
|
28
63
|
SNAP: 'snap'
|
|
29
64
|
} as const;
|
|
30
65
|
|
|
31
66
|
/**
|
|
32
|
-
* Carousel item
|
|
67
|
+
* Carousel item size constants
|
|
68
|
+
*
|
|
69
|
+
* Defines the available sizes for carousel items.
|
|
70
|
+
* These are used to control the relative sizing of
|
|
71
|
+
* items within different carousel layouts.
|
|
72
|
+
*
|
|
73
|
+
* @category Components
|
|
33
74
|
*/
|
|
34
75
|
export const CAROUSEL_ITEM_SIZES = {
|
|
76
|
+
/** Large featured items (primary content) */
|
|
35
77
|
LARGE: 'large',
|
|
78
|
+
/** Medium-sized items (secondary content) */
|
|
36
79
|
MEDIUM: 'medium',
|
|
80
|
+
/** Small items (tertiary content or thumbnails) */
|
|
37
81
|
SMALL: 'small'
|
|
38
82
|
} as const;
|
|
39
83
|
|
|
40
84
|
/**
|
|
41
85
|
* Transition effects for carousel slides
|
|
86
|
+
*
|
|
87
|
+
* Controls the visual transition when moving between slides.
|
|
88
|
+
*
|
|
89
|
+
* @category Components
|
|
42
90
|
*/
|
|
43
91
|
export const CAROUSEL_TRANSITIONS = {
|
|
92
|
+
/** Horizontal sliding animation (default) */
|
|
44
93
|
SLIDE: 'slide',
|
|
94
|
+
/** Fade in/out transition between slides */
|
|
45
95
|
FADE: 'fade',
|
|
96
|
+
/** No animation, immediate change */
|
|
46
97
|
NONE: 'none'
|
|
47
98
|
} as const;
|
|
48
99
|
|
|
49
100
|
/**
|
|
50
101
|
* Event names for the carousel component
|
|
102
|
+
*
|
|
103
|
+
* These events can be listened to using the carousel's
|
|
104
|
+
* `on()` method for custom behavior.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* carousel.on(CAROUSEL_EVENTS.SLIDE_CHANGED, (index) => {
|
|
108
|
+
* console.log(`Now showing slide ${index}`);
|
|
109
|
+
* });
|
|
110
|
+
*
|
|
111
|
+
* @category Components
|
|
51
112
|
*/
|
|
52
113
|
export const CAROUSEL_EVENTS = {
|
|
114
|
+
/** Fired when a slide change begins */
|
|
53
115
|
SLIDE_CHANGE: 'slide-change',
|
|
116
|
+
/** Fired when a slide change completes */
|
|
54
117
|
SLIDE_CHANGED: 'slide-changed',
|
|
118
|
+
/** Fired when the carousel is resized */
|
|
55
119
|
RESIZE: 'resize'
|
|
56
120
|
} as const;
|
|
57
121
|
|
|
58
122
|
/**
|
|
59
123
|
* Default values for carousel configuration
|
|
124
|
+
*
|
|
125
|
+
* These values will be used when not explicitly specified
|
|
126
|
+
* in the configuration object passed to createCarousel().
|
|
127
|
+
*
|
|
128
|
+
* @category Components
|
|
60
129
|
*/
|
|
61
130
|
export const CAROUSEL_DEFAULTS = {
|
|
131
|
+
/** Start displaying from the first slide (index 0) */
|
|
62
132
|
INITIAL_SLIDE: 0,
|
|
133
|
+
/** Enable infinite looping by default */
|
|
63
134
|
LOOP: true,
|
|
135
|
+
/** Default transition effect is sliding */
|
|
64
136
|
TRANSITION: CAROUSEL_TRANSITIONS.SLIDE,
|
|
137
|
+
/** Transition duration in milliseconds */
|
|
65
138
|
TRANSITION_DURATION: 300,
|
|
139
|
+
/** Border radius for slides following Material Design 3 */
|
|
66
140
|
BORDER_RADIUS: 16,
|
|
141
|
+
/** Gap between slides in pixels */
|
|
67
142
|
GAP: 8,
|
|
143
|
+
/** Default layout is multi-browse for browsing visual content */
|
|
68
144
|
LAYOUT: CAROUSEL_LAYOUTS.MULTI_BROWSE,
|
|
145
|
+
/** Default scroll behavior is snap for controlled movement */
|
|
69
146
|
SCROLL_BEHAVIOR: CAROUSEL_SCROLL_BEHAVIORS.SNAP,
|
|
70
|
-
|
|
147
|
+
/** Small item width in pixels (40-56dp range per MD3 guidelines) */
|
|
148
|
+
SMALL_ITEM_WIDTH: 48,
|
|
71
149
|
|
|
72
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Item widths for different layouts in pixels
|
|
152
|
+
* These values are optimized for each layout type
|
|
153
|
+
* based on Material Design 3 guidelines
|
|
154
|
+
*/
|
|
73
155
|
ITEM_WIDTHS: {
|
|
156
|
+
// Multi-browse layout uses varying sizes
|
|
74
157
|
[CAROUSEL_LAYOUTS.MULTI_BROWSE]: {
|
|
75
|
-
LARGE: 240,
|
|
76
|
-
MEDIUM: 180,
|
|
77
|
-
SMALL: 48
|
|
158
|
+
LARGE: 240, // Large featured items
|
|
159
|
+
MEDIUM: 180, // Medium secondary items
|
|
160
|
+
SMALL: 48 // Small thumbnail/preview items
|
|
78
161
|
},
|
|
162
|
+
// Uncontained layout uses consistent sizing
|
|
79
163
|
[CAROUSEL_LAYOUTS.UNCONTAINED]: {
|
|
80
|
-
LARGE: 240,
|
|
81
|
-
MEDIUM: 240,
|
|
82
|
-
SMALL: 240
|
|
164
|
+
LARGE: 240, // All items same size
|
|
165
|
+
MEDIUM: 240, // for consistent scrolling
|
|
166
|
+
SMALL: 240 // experience
|
|
83
167
|
},
|
|
168
|
+
// Hero layout emphasizes the main item
|
|
84
169
|
[CAROUSEL_LAYOUTS.HERO]: {
|
|
85
|
-
LARGE: 300,
|
|
86
|
-
MEDIUM: 240,
|
|
87
|
-
SMALL: 48
|
|
170
|
+
LARGE: 300, // Very large for hero spotlight
|
|
171
|
+
MEDIUM: 240, // Medium for preview items
|
|
172
|
+
SMALL: 48 // Small for navigation thumbnails
|
|
88
173
|
},
|
|
174
|
+
// Full-screen takes entire viewport width
|
|
89
175
|
[CAROUSEL_LAYOUTS.FULL_SCREEN]: {
|
|
90
|
-
LARGE: '100%',
|
|
91
|
-
MEDIUM: '100%',
|
|
92
|
-
SMALL: '100%'
|
|
176
|
+
LARGE: '100%', // Full width immersive
|
|
177
|
+
MEDIUM: '100%', // experience with all
|
|
178
|
+
SMALL: '100%' // items filling viewport
|
|
93
179
|
}
|
|
94
180
|
}
|
|
95
181
|
} as const;
|
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
// src/components/carousel/index.ts
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
|
-
* Carousel Component
|
|
4
|
-
*
|
|
5
|
-
* This module exports a carousel component with four layout types:
|
|
6
|
-
* - Multi-browse: For browsing many visual items at once (photos, event feeds)
|
|
7
|
-
* - Uncontained: For highly customized or text-heavy carousels (traditional behavior)
|
|
8
|
-
* - Hero: For spotlighting very large visual items (featured content)
|
|
9
|
-
* - Full-screen: For immersive vertical-scrolling experiences
|
|
4
|
+
* Carousel Component Module
|
|
10
5
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* A Material Design 3 compatible carousel implementation that supports
|
|
7
|
+
* various layout types and scroll behaviors to accommodate different
|
|
8
|
+
* content presentation needs.
|
|
14
9
|
*
|
|
15
|
-
* @module
|
|
10
|
+
* @module components/carousel
|
|
11
|
+
* @category Components
|
|
16
12
|
*/
|
|
17
13
|
|
|
18
14
|
// Main factory function
|
|
19
15
|
export { default } from './carousel';
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Constants for carousel configuration
|
|
19
|
+
*
|
|
20
|
+
* Use these constants instead of string literals for better
|
|
21
|
+
* code completion, type safety, and to follow best practices.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import { createCarousel, CAROUSEL_LAYOUTS } from 'mtrl';
|
|
25
|
+
*
|
|
26
|
+
* const carousel = createCarousel({
|
|
27
|
+
* layout: CAROUSEL_LAYOUTS.MULTI_BROWSE,
|
|
28
|
+
* // Other configuration options...
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* @category Components
|
|
32
|
+
*/
|
|
22
33
|
export {
|
|
23
34
|
CAROUSEL_LAYOUTS,
|
|
24
35
|
CAROUSEL_SCROLL_BEHAVIORS,
|
|
@@ -28,7 +39,14 @@ export {
|
|
|
28
39
|
CAROUSEL_ITEM_SIZES
|
|
29
40
|
} from './constants';
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
/**
|
|
43
|
+
* TypeScript types and interfaces for the Carousel component
|
|
44
|
+
*
|
|
45
|
+
* These provide proper type checking and IntelliSense support
|
|
46
|
+
* when using the carousel component in TypeScript projects.
|
|
47
|
+
*
|
|
48
|
+
* @category Components
|
|
49
|
+
*/
|
|
32
50
|
export {
|
|
33
51
|
CarouselConfig,
|
|
34
52
|
CarouselComponent,
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
// src/components/checkbox/checkbox.ts
|
|
2
|
+
/**
|
|
3
|
+
* Checkbox Component Implementation
|
|
4
|
+
*
|
|
5
|
+
* This module implements a Material Design 3 checkbox component
|
|
6
|
+
* with support for different visual variants, indeterminate state,
|
|
7
|
+
* and configurable label positioning.
|
|
8
|
+
*
|
|
9
|
+
* @module components/checkbox
|
|
10
|
+
* @category Components
|
|
11
|
+
*/
|
|
12
|
+
|
|
2
13
|
import { pipe } from '../../core/compose';
|
|
3
14
|
import { createBase, withElement } from '../../core/compose/component';
|
|
4
15
|
import {
|
|
@@ -20,19 +31,26 @@ import {
|
|
|
20
31
|
} from './config';
|
|
21
32
|
|
|
22
33
|
/**
|
|
23
|
-
* Enhances a component with checkable features and indeterminate state
|
|
34
|
+
* Enhances a component with checkable features and indeterminate state support
|
|
35
|
+
*
|
|
36
|
+
* The indeterminate state is a third visual state for checkboxes that represents
|
|
37
|
+
* a mixed or partial selection (neither fully checked nor unchecked).
|
|
38
|
+
*
|
|
24
39
|
* @param {BaseComponent} component - The component to enhance
|
|
25
40
|
* @param {CheckboxConfig} config - Configuration options
|
|
26
41
|
* @returns {BaseComponent} The enhanced component
|
|
42
|
+
* @category Components
|
|
43
|
+
* @internal
|
|
27
44
|
*/
|
|
28
45
|
const enhanceWithCheckable = (component: BaseComponent, config: CheckboxConfig): BaseComponent => {
|
|
29
46
|
const enhanced = withCheckable(config)(component);
|
|
30
47
|
|
|
31
|
-
//
|
|
48
|
+
// Set initial indeterminate state if specified in config
|
|
32
49
|
if (config.indeterminate) {
|
|
33
50
|
enhanced.input.indeterminate = true;
|
|
34
51
|
}
|
|
35
52
|
|
|
53
|
+
// Add method to control indeterminate state
|
|
36
54
|
enhanced.setIndeterminate = (state: boolean) => {
|
|
37
55
|
enhanced.input.indeterminate = state;
|
|
38
56
|
enhanced.element.classList.toggle(`${config.prefix}-checkbox--indeterminate`, state);
|
|
@@ -43,26 +61,75 @@ const enhanceWithCheckable = (component: BaseComponent, config: CheckboxConfig):
|
|
|
43
61
|
};
|
|
44
62
|
|
|
45
63
|
/**
|
|
46
|
-
* Creates a new Checkbox component
|
|
47
|
-
*
|
|
48
|
-
*
|
|
64
|
+
* Creates a new Checkbox component with the specified configuration.
|
|
65
|
+
*
|
|
66
|
+
* Checkboxes allow users to select one or more items from a set,
|
|
67
|
+
* or to toggle a single option on or off. This implementation follows
|
|
68
|
+
* Material Design 3 guidelines for accessible, customizable checkboxes.
|
|
69
|
+
*
|
|
70
|
+
* @param {CheckboxConfig} config - Configuration options for the checkbox
|
|
71
|
+
* @returns {CheckboxComponent} A fully configured checkbox component instance
|
|
72
|
+
* @throws {Error} Throws an error if checkbox creation fails
|
|
73
|
+
*
|
|
74
|
+
* @category Components
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // Create a basic checkbox
|
|
78
|
+
* const checkbox = createCheckbox({
|
|
79
|
+
* label: 'Accept terms and conditions',
|
|
80
|
+
* name: 'accept-terms'
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* document.querySelector('.form').appendChild(checkbox.element);
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Create a pre-checked checkbox with custom styling
|
|
87
|
+
* const checkbox = createCheckbox({
|
|
88
|
+
* label: 'Remember me',
|
|
89
|
+
* checked: true,
|
|
90
|
+
* variant: 'outlined',
|
|
91
|
+
* labelPosition: 'start'
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* // Add event listener
|
|
95
|
+
* checkbox.on('change', (e) => {
|
|
96
|
+
* console.log('Checkbox changed:', e.target.checked);
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // Create an indeterminate checkbox for "select all" functionality
|
|
101
|
+
* const selectAll = createCheckbox({
|
|
102
|
+
* label: 'Select All',
|
|
103
|
+
* indeterminate: true
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* // Later, based on selections:
|
|
107
|
+
* if (allSelected) {
|
|
108
|
+
* selectAll.check();
|
|
109
|
+
* } else if (noneSelected) {
|
|
110
|
+
* selectAll.uncheck();
|
|
111
|
+
* } else {
|
|
112
|
+
* selectAll.setIndeterminate(true);
|
|
113
|
+
* }
|
|
49
114
|
*/
|
|
50
115
|
const createCheckbox = (config: CheckboxConfig = {}): CheckboxComponent => {
|
|
51
116
|
const baseConfig = createBaseConfig(config);
|
|
52
117
|
|
|
53
118
|
try {
|
|
119
|
+
// Create the checkbox through functional composition
|
|
120
|
+
// Each function in the pipe adds specific features to the component
|
|
54
121
|
const checkbox = pipe(
|
|
55
|
-
createBase,
|
|
56
|
-
withEvents(),
|
|
57
|
-
withElement(getElementConfig(baseConfig)),
|
|
58
|
-
withInput(baseConfig),
|
|
59
|
-
withCheckIcon(baseConfig),
|
|
60
|
-
withTextLabel(baseConfig),
|
|
61
|
-
withLabelPosition(baseConfig),
|
|
62
|
-
component => enhanceWithCheckable(component, baseConfig),
|
|
63
|
-
withDisabled(baseConfig),
|
|
64
|
-
withLifecycle(),
|
|
65
|
-
comp => withAPI(getApiConfig(comp))(comp)
|
|
122
|
+
createBase, // Base component
|
|
123
|
+
withEvents(), // Event handling
|
|
124
|
+
withElement(getElementConfig(baseConfig)), // DOM element
|
|
125
|
+
withInput(baseConfig), // Input element
|
|
126
|
+
withCheckIcon(baseConfig), // Checkbox icon
|
|
127
|
+
withTextLabel(baseConfig), // Text label
|
|
128
|
+
withLabelPosition(baseConfig), // Label positioning
|
|
129
|
+
component => enhanceWithCheckable(component, baseConfig), // Checkable state
|
|
130
|
+
withDisabled(baseConfig), // Disabled state
|
|
131
|
+
withLifecycle(), // Lifecycle management
|
|
132
|
+
comp => withAPI(getApiConfig(comp))(comp) // Public API
|
|
66
133
|
)(baseConfig);
|
|
67
134
|
|
|
68
135
|
return checkbox as CheckboxComponent;
|
|
@@ -1,3 +1,45 @@
|
|
|
1
1
|
// src/components/checkbox/index.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checkbox Component Module
|
|
5
|
+
*
|
|
6
|
+
* A Material Design 3 checkbox implementation with support
|
|
7
|
+
* for different variants, indeterminate state, and label positioning.
|
|
8
|
+
*
|
|
9
|
+
* @module components/checkbox
|
|
10
|
+
* @category Components
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Main factory function
|
|
2
14
|
export { default } from './checkbox';
|
|
3
|
-
|
|
15
|
+
|
|
16
|
+
// TypeScript types and interfaces
|
|
17
|
+
export type {
|
|
18
|
+
CheckboxConfig,
|
|
19
|
+
CheckboxComponent,
|
|
20
|
+
CheckboxVariant,
|
|
21
|
+
CheckboxLabelPosition
|
|
22
|
+
} from './types';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Constants for checkbox configuration
|
|
26
|
+
*
|
|
27
|
+
* Use these constants instead of string literals for better
|
|
28
|
+
* code completion, type safety, and to follow best practices.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* import { createCheckbox, CHECKBOX_VARIANTS } from 'mtrl';
|
|
32
|
+
*
|
|
33
|
+
* const checkbox = createCheckbox({
|
|
34
|
+
* variant: CHECKBOX_VARIANTS.OUTLINED,
|
|
35
|
+
* label: 'Accept terms'
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* @category Components
|
|
39
|
+
*/
|
|
40
|
+
export {
|
|
41
|
+
CHECKBOX_VARIANTS,
|
|
42
|
+
CHECKBOX_LABEL_POSITION,
|
|
43
|
+
CHECKBOX_STATES,
|
|
44
|
+
CHECKBOX_CLASSES
|
|
45
|
+
} from './types';
|