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.
Files changed (159) hide show
  1. package/.env +15 -0
  2. package/CONTRIBUTING.md +8 -8
  3. package/DOCS.md +3 -3
  4. package/README.md +43 -20
  5. package/TESTING.md +128 -18
  6. package/dist/index.js +14865 -0
  7. package/git-user-stats.js +545 -0
  8. package/index.ts +9 -67
  9. package/package.json +8 -3
  10. package/src/components/badge/api.ts +15 -1
  11. package/src/components/badge/badge.ts +43 -4
  12. package/src/components/badge/config.ts +40 -8
  13. package/src/components/badge/index.ts +64 -3
  14. package/src/components/badge/types.ts +175 -33
  15. package/src/components/button/api.ts +63 -1
  16. package/src/components/button/button.ts +39 -3
  17. package/src/components/button/config.ts +21 -4
  18. package/src/components/button/index.ts +26 -1
  19. package/src/components/button/types.ts +7 -1
  20. package/src/components/card/api.ts +78 -9
  21. package/src/components/card/card.ts +58 -3
  22. package/src/components/card/config.ts +41 -11
  23. package/src/components/card/features.ts +39 -12
  24. package/src/components/card/index.ts +84 -19
  25. package/src/components/card/types.ts +218 -29
  26. package/src/components/carousel/carousel.ts +92 -28
  27. package/src/components/carousel/constants.ts +107 -21
  28. package/src/components/carousel/index.ts +31 -13
  29. package/src/components/checkbox/checkbox.ts +83 -16
  30. package/src/components/checkbox/index.ts +43 -1
  31. package/src/components/checkbox/types.ts +219 -32
  32. package/src/components/chips/api.ts +194 -0
  33. package/src/components/{chip → chips/chip}/api.ts +42 -2
  34. package/src/components/chips/chip/chip.ts +131 -0
  35. package/src/components/{chip → chips/chip}/config.ts +3 -3
  36. package/src/components/chips/chip/index.ts +3 -0
  37. package/src/components/chips/chips.md +481 -0
  38. package/src/components/chips/chips.ts +75 -0
  39. package/src/components/chips/config.ts +109 -0
  40. package/src/components/chips/constants.ts +61 -0
  41. package/src/components/chips/features/chip-items.ts +33 -0
  42. package/src/components/chips/features/container.ts +77 -0
  43. package/src/components/chips/features/controller.ts +448 -0
  44. package/src/components/chips/features/index.ts +5 -0
  45. package/src/components/chips/features/label.ts +108 -0
  46. package/src/components/chips/index.ts +11 -0
  47. package/src/components/chips/schema.ts +61 -0
  48. package/src/components/{chip → chips}/types.ts +203 -92
  49. package/src/components/dialog/dialog.ts +99 -16
  50. package/src/components/dialog/index.ts +97 -1
  51. package/src/components/dialog/types.ts +375 -69
  52. package/src/components/divider/config.ts +90 -6
  53. package/src/components/divider/divider.ts +32 -2
  54. package/src/components/divider/features.ts +26 -0
  55. package/src/components/divider/index.ts +30 -0
  56. package/src/components/divider/types.ts +86 -9
  57. package/src/components/extended-fab/api.ts +53 -1
  58. package/src/components/extended-fab/config.ts +29 -1
  59. package/src/components/extended-fab/extended-fab.ts +28 -0
  60. package/src/components/extended-fab/index.ts +36 -0
  61. package/src/components/extended-fab/types.ts +458 -13
  62. package/src/components/fab/api.ts +42 -2
  63. package/src/components/fab/config.ts +29 -1
  64. package/src/components/fab/fab.ts +16 -2
  65. package/src/components/fab/index.ts +35 -0
  66. package/src/components/fab/types.ts +374 -10
  67. package/src/components/list/api.ts +12 -2
  68. package/src/components/list/config.ts +21 -0
  69. package/src/components/list/features.ts +6 -0
  70. package/src/components/list/index.ts +56 -1
  71. package/src/components/list/list-item.ts +46 -2
  72. package/src/components/list/list.ts +73 -2
  73. package/src/components/list/types.ts +172 -0
  74. package/src/components/list/utils.ts +26 -2
  75. package/src/components/menu/api.ts +217 -20
  76. package/src/components/menu/config.ts +27 -0
  77. package/src/components/menu/features/visibility.ts +55 -6
  78. package/src/components/menu/index.ts +64 -0
  79. package/src/components/menu/menu-item.ts +46 -3
  80. package/src/components/menu/menu.ts +77 -1
  81. package/src/components/menu/types.ts +404 -39
  82. package/src/components/sheet/config.ts +1 -2
  83. package/src/components/sheet/features/gestures.ts +1 -1
  84. package/src/components/sheet/features/position.ts +1 -2
  85. package/src/components/sheet/features/state.ts +1 -1
  86. package/src/components/sheet/index.ts +10 -2
  87. package/src/components/sheet/sheet.ts +1 -2
  88. package/src/components/sheet/types.ts +29 -1
  89. package/src/components/slider/api.ts +1 -1
  90. package/src/components/slider/config.ts +1 -1
  91. package/src/components/slider/features/controller.ts +1 -1
  92. package/src/components/slider/features/handlers.ts +1 -1
  93. package/src/components/slider/features/states.ts +1 -1
  94. package/src/components/slider/index.ts +12 -5
  95. package/src/components/slider/schema.ts +1 -1
  96. package/src/components/slider/types.ts +31 -0
  97. package/src/components/tabs/tab-api.ts +1 -1
  98. package/src/components/tabs/types.ts +1 -1
  99. package/src/components/tooltip/api.ts +6 -2
  100. package/src/components/tooltip/config.ts +9 -28
  101. package/src/components/tooltip/index.ts +10 -1
  102. package/src/components/tooltip/types.ts +38 -3
  103. package/src/index.ts +129 -31
  104. package/src/styles/abstract/_mixins.scss +23 -9
  105. package/src/styles/abstract/_variables.scss +14 -4
  106. package/src/styles/components/_card.scss +1 -1
  107. package/src/styles/components/_chip.scss +323 -113
  108. package/src/styles/components/_tabs.scss +1 -1
  109. package/CLAUDE.md +0 -33
  110. package/src/components/checkbox/constants.ts +0 -37
  111. package/src/components/chip/chip-set.ts +0 -225
  112. package/src/components/chip/chip.ts +0 -118
  113. package/src/components/chip/constants.ts +0 -28
  114. package/src/components/chip/index.ts +0 -12
  115. package/src/components/list/constants.ts +0 -116
  116. package/src/components/sheet/constants.ts +0 -20
  117. package/src/components/slider/constants.ts +0 -32
  118. package/src/components/tooltip/constants.ts +0 -27
  119. package/test/components/badge.test.ts +0 -545
  120. package/test/components/bottom-app-bar.test.ts +0 -303
  121. package/test/components/button.test.ts +0 -233
  122. package/test/components/card.test.ts +0 -560
  123. package/test/components/carousel.test.ts +0 -951
  124. package/test/components/checkbox.test.ts +0 -462
  125. package/test/components/chip.test.ts +0 -692
  126. package/test/components/datepicker.test.ts +0 -1124
  127. package/test/components/dialog.test.ts +0 -990
  128. package/test/components/divider.test.ts +0 -412
  129. package/test/components/extended-fab.test.ts +0 -672
  130. package/test/components/fab.test.ts +0 -561
  131. package/test/components/list.test.ts +0 -365
  132. package/test/components/menu.test.ts +0 -718
  133. package/test/components/navigation.test.ts +0 -186
  134. package/test/components/progress.test.ts +0 -567
  135. package/test/components/radios.test.ts +0 -699
  136. package/test/components/search.test.ts +0 -1135
  137. package/test/components/segmented-button.test.ts +0 -732
  138. package/test/components/sheet.test.ts +0 -641
  139. package/test/components/slider.test.ts +0 -1220
  140. package/test/components/snackbar.test.ts +0 -461
  141. package/test/components/switch.test.ts +0 -452
  142. package/test/components/tabs.test.ts +0 -1369
  143. package/test/components/textfield.test.ts +0 -400
  144. package/test/components/timepicker.test.ts +0 -592
  145. package/test/components/tooltip.test.ts +0 -630
  146. package/test/components/top-app-bar.test.ts +0 -566
  147. package/test/core/dom.attributes.test.ts +0 -148
  148. package/test/core/dom.classes.test.ts +0 -152
  149. package/test/core/dom.events.test.ts +0 -243
  150. package/test/core/emitter.test.ts +0 -141
  151. package/test/core/ripple.test.ts +0 -99
  152. package/test/core/state.store.test.ts +0 -189
  153. package/test/core/utils.normalize.test.ts +0 -61
  154. package/test/core/utils.object.test.ts +0 -120
  155. package/test/setup.js +0 -371
  156. package/test/setup.ts +0 -451
  157. package/tsconfig.json +0 -22
  158. package/typedoc.json +0 -28
  159. package/typedoc.simple.json +0 -14
package/.env ADDED
@@ -0,0 +1,15 @@
1
+ # Application settings
2
+ NODE_ENV=development
3
+ PORT=4000
4
+ # Compression settings
5
+ COMPRESSION_ENABLED=false
6
+ # Cache settings (shorter for development)
7
+ CACHE_STATIC_FILES=0 # No caching in development
8
+ CACHE_CSS_FILES=0
9
+ CACHE_PUBLIC_FILES=0
10
+ # Security settings
11
+ ENABLE_CORS=true
12
+ CORS_ORIGIN=*
13
+ # Application specific settings
14
+ APP_TITLE=MTRL Playground (DEV)
15
+ DEBUG_LEVEL=debug
package/CONTRIBUTING.md CHANGED
@@ -1,10 +1,10 @@
1
- # Contributing to MTRL
1
+ # Contributing to mtrl
2
2
 
3
- Thank you for your interest in contributing to MTRL! This document provides guidelines and instructions for contributing to this lightweight, ES6-focused JavaScript UI component library.
3
+ Thank you for your interest in contributing to mtrl! This document provides guidelines and instructions for contributing to this lightweight, ES6-focused JavaScript UI component library.
4
4
 
5
5
  ## Why Contribute?
6
6
 
7
- MTRL aims to be a modern, flexible UI component library with:
7
+ mtrl aims to be a modern, flexible UI component library with:
8
8
 
9
9
  - Zero dependencies (except Bun for development)
10
10
  - ES6+ focused codebase
@@ -12,7 +12,7 @@ MTRL aims to be a modern, flexible UI component library with:
12
12
  - Simple and extensible API
13
13
  - Excellent documentation
14
14
 
15
- By contributing to MTRL, you'll help create a lean alternative to heavier frameworks while gaining experience with modern JavaScript patterns and component design.
15
+ By contributing to mtrl, you'll help create a lean alternative to heavier frameworks while gaining experience with modern JavaScript patterns and component design.
16
16
 
17
17
  ## Getting Started
18
18
 
@@ -31,7 +31,7 @@ By contributing to MTRL, you'll help create a lean alternative to heavier framew
31
31
 
32
32
  ### Testing Your Components with mtrl.app
33
33
 
34
- MTRL uses a separate repository called mtrl.app (https://mtrl.app) for showcasing and testing components. There are two ways to test your components:
34
+ mtrl uses a separate repository called mtrl.app (https://mtrl.app) for showcasing and testing components. There are two ways to test your components:
35
35
 
36
36
  1. **Build and link locally**:
37
37
  ```bash
@@ -74,7 +74,7 @@ MTRL uses a separate repository called mtrl.app (https://mtrl.app) for showcasin
74
74
 
75
75
  ### Component Structure
76
76
 
77
- MTRL components follow a consistent pattern:
77
+ mtrl components follow a consistent pattern:
78
78
 
79
79
  ```javascript
80
80
  // src/components/mycomponent/index.js
@@ -172,8 +172,8 @@ For any new feature or component:
172
172
 
173
173
  ## License
174
174
 
175
- By contributing to MTRL, you agree that your contributions will be licensed under the project's MIT License.
175
+ By contributing to mtrl, you agree that your contributions will be licensed under the project's MIT License.
176
176
 
177
177
  ---
178
178
 
179
- Thank you for contributing to MTRL! Your efforts help make this library better for everyone.
179
+ Thank you for contributing to mtrl! Your efforts help make this library better for everyone.
package/DOCS.md CHANGED
@@ -1,6 +1,6 @@
1
- # TypeDoc Installation and Usage Guide for MTRL
1
+ # TypeDoc Installation and Usage Guide for mtrl
2
2
 
3
- This guide will help you set up and use TypeDoc with your MTRL library.
3
+ This guide will help you set up and use TypeDoc with your mtrl library.
4
4
 
5
5
  ## Installation
6
6
 
@@ -86,7 +86,7 @@ function myFunction(paramName: string): number {
86
86
 
87
87
  ### Categories
88
88
 
89
- Use the `@category` tag to organize your MTRL components and utilities:
89
+ Use the `@category` tag to organize your mtrl components and utilities:
90
90
 
91
91
  ```typescript
92
92
  /**
package/README.md CHANGED
@@ -1,26 +1,26 @@
1
- # MTRL Library
1
+ # mtrl Library
2
2
 
3
- > **Project Status:** MTRL is in active development with TypeScript support! The core architecture and components are established, with more features on the roadmap. We welcome early adopters and contributors who want to help shape MTRL's future!
3
+ > **Project Status:** mtrl is in active development with TypeScript support! The core architecture and components are established, with more features on the roadmap. We welcome early adopters and contributors who want to help shape mtrl's future!
4
4
 
5
- MTRL is a lightweight, composable TypeScript/JavaScript component library inspired by Material Design principles. Built with zero dependencies, MTRL provides a robust foundation for creating modern web interfaces with an emphasis on performance, type safety, and accessibility.
5
+ mtrl is a lightweight, composable TypeScript/JavaScript component library inspired by Material Design principles. Built with zero dependencies, mtrl provides a robust foundation for creating modern web interfaces with an emphasis on performance, type safety, and accessibility.
6
6
 
7
- ## Understanding MTRL
7
+ ## Understanding mtrl
8
8
 
9
- MTRL (pronounced "material") takes its inspiration from Material Design while providing a flexible, framework-agnostic implementation. The library's name is reflected in its component prefix `mtrl-`, which you'll see used consistently throughout the codebase.
9
+ mtrl (pronounced "material") takes its inspiration from Material Design while providing a flexible, framework-agnostic implementation. The library's name is reflected in its component prefix `mtrl-`, which you'll see used consistently throughout the codebase.
10
10
 
11
11
  ### Design Philosophy
12
12
 
13
- MTRL is built on several core principles:
13
+ mtrl is built on several core principles:
14
14
 
15
15
  1. **Composition Over Inheritance**: Components are constructed through functional composition with full type safety.
16
16
  2. **Zero Dependencies**: The entire library is built with vanilla TypeScript, ensuring minimal bundle size and maximum compatibility.
17
- 3. **Material Design Inspiration**: While inspired by Material Design, MTRL provides flexibility in styling and behavior.
17
+ 3. **Material Design Inspiration**: While inspired by Material Design, mtrl provides flexibility in styling and behavior.
18
18
  4. **Accessibility First**: Built-in accessibility features ensure your applications are usable by everyone.
19
19
  5. **TypeScript First**: Comprehensive type definitions for better developer experience and code reliability.
20
20
 
21
21
  ## Core Components
22
22
 
23
- MTRL provides a comprehensive set of components, each following Material Design principles:
23
+ mtrl provides a comprehensive set of components, each following Material Design principles:
24
24
 
25
25
  ```typescript
26
26
  import { createButton, createTextField } from 'mtrl'
@@ -63,7 +63,7 @@ bun add mtrl
63
63
 
64
64
  ## Component Architecture
65
65
 
66
- Let's look at how MTRL components are constructed:
66
+ Let's look at how mtrl components are constructed:
67
67
 
68
68
  ```typescript
69
69
  // Example of a button component creation
@@ -78,7 +78,7 @@ const button = createButton({
78
78
 
79
79
  ### The Composition System
80
80
 
81
- MTRL uses a pipe-based composition system with full type safety for building components:
81
+ mtrl uses a pipe-based composition system with full type safety for building components:
82
82
 
83
83
  ```typescript
84
84
  // Internal component creation
@@ -101,7 +101,7 @@ const createButton = (config: ButtonConfig): ButtonComponent => {
101
101
 
102
102
  ### TypeScript Integration
103
103
 
104
- MTRL provides comprehensive TypeScript definitions:
104
+ mtrl provides comprehensive TypeScript definitions:
105
105
 
106
106
  ```typescript
107
107
  // Component interfaces for better developer experience
@@ -129,7 +129,7 @@ export interface ButtonComponent extends
129
129
 
130
130
  ### CSS Classes
131
131
 
132
- MTRL follows a consistent class naming convention:
132
+ mtrl follows a consistent class naming convention:
133
133
 
134
134
  ```css
135
135
  .mtrl-component /* Base component class */
@@ -140,7 +140,7 @@ MTRL follows a consistent class naming convention:
140
140
 
141
141
  ## State Management
142
142
 
143
- MTRL provides several approaches to state management:
143
+ mtrl provides several approaches to state management:
144
144
 
145
145
  ### Local Component State
146
146
 
@@ -175,7 +175,7 @@ collection.subscribe(({ event, data }) => {
175
175
 
176
176
  ## Data Integration
177
177
 
178
- MTRL provides adapters for different data sources:
178
+ mtrl provides adapters for different data sources:
179
179
 
180
180
  ```typescript
181
181
  // MongoDB adapter
@@ -199,7 +199,7 @@ const routeAdapter = createRouteAdapter({
199
199
 
200
200
  ### Creating Custom Components
201
201
 
202
- Extend MTRL by creating custom components with full type safety:
202
+ Extend mtrl by creating custom components with full type safety:
203
203
 
204
204
  ```typescript
205
205
  interface CustomCardConfig {
@@ -234,7 +234,7 @@ const createCustomCard = (config: CustomCardConfig): CustomCardComponent => {
234
234
 
235
235
  ### Styling
236
236
 
237
- MTRL components can be styled through CSS custom properties:
237
+ mtrl components can be styled through CSS custom properties:
238
238
 
239
239
  ```css
240
240
  :root {
@@ -249,7 +249,7 @@ MTRL components can be styled through CSS custom properties:
249
249
 
250
250
  ### Performance
251
251
 
252
- MTRL is designed with performance in mind:
252
+ mtrl is designed with performance in mind:
253
253
 
254
254
  - Minimal DOM operations
255
255
  - Efficient event handling
@@ -258,7 +258,7 @@ MTRL is designed with performance in mind:
258
258
 
259
259
  ### Type Safety
260
260
 
261
- MTRL leverages TypeScript for better developer experience:
261
+ mtrl leverages TypeScript for better developer experience:
262
262
 
263
263
  - Clear component interfaces
264
264
  - Type-safe method chaining
@@ -277,7 +277,7 @@ Built-in accessibility features include:
277
277
 
278
278
  ## Browser Support
279
279
 
280
- MTRL supports modern browsers:
280
+ mtrl supports modern browsers:
281
281
 
282
282
  - Chrome (latest)
283
283
  - Firefox (latest)
@@ -290,7 +290,30 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
290
290
 
291
291
  ## License
292
292
 
293
- MTRL is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
293
+ mtrl is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
294
+
295
+ ## Testing
296
+
297
+ mtrl comes with a comprehensive test suite using Bun's test runner. The tests are written in TypeScript and use JSDOM for DOM testing.
298
+
299
+ ```bash
300
+ # Run all tests
301
+ bun test
302
+
303
+ # Run tests in watch mode
304
+ bun test --watch
305
+
306
+ # Run tests with coverage report
307
+ bun test --coverage
308
+
309
+ # Run tests with UI
310
+ bun test --watch --ui
311
+
312
+ # Run a specific test file
313
+ bun test test/components/button.test.ts
314
+ ```
315
+
316
+ For more details on writing and running tests, see our [Testing Guide](TESTING.md).
294
317
 
295
318
  ## Documentation
296
319
 
package/TESTING.md CHANGED
@@ -1,6 +1,6 @@
1
- # Testing MTRL Components
1
+ # Testing mtrl Components
2
2
 
3
- This document provides guidelines for writing and running tests for the MTRL library. We use Bun's built-in test runner for fast, efficient testing.
3
+ This document provides guidelines for writing and running tests for the mtrl library. We use Bun's built-in test runner for fast, efficient testing.
4
4
 
5
5
  ## Running Tests
6
6
 
@@ -18,7 +18,7 @@ bun test --coverage
18
18
  bun test --watch --ui
19
19
 
20
20
  # Run specific test file or pattern
21
- bun test test/components/button.test.js
21
+ bun test test/components/button.test.ts
22
22
  ```
23
23
 
24
24
  ## Test Structure
@@ -27,29 +27,31 @@ Tests are organized to mirror the source code structure:
27
27
 
28
28
  ```
29
29
  test/
30
- ├── setup.js # Global test setup and DOM mocking
30
+ ├── setup.ts # Global test setup and DOM mocking
31
31
  ├── components/ # Component tests
32
- │ ├── button.test.js
33
- │ ├── textfield.test.js
32
+ │ ├── button.test.ts
33
+ │ ├── textfield.test.ts
34
34
  │ └── ...
35
35
  └── core/ # Core functionality tests
36
- ├── build/
37
- │ └── ripple.test.js
38
- ├── dom/
39
- │ └── ...
40
- └── state/
41
- └── emitter.test.js
36
+ ├── dom.classes.test.ts
37
+ ├── dom.attributes.test.ts
38
+ ├── dom.events.test.ts
39
+ ├── utils.normalize.test.ts
40
+ ├── utils.object.test.ts
41
+ ├── emitter.test.ts
42
+ ├── ripple.test.ts
43
+ └── state.store.test.ts
42
44
  ```
43
45
 
44
46
  ## Writing Tests
45
47
 
46
- When writing tests for MTRL components, follow these guidelines:
48
+ When writing tests for mtrl components, follow these guidelines:
47
49
 
48
50
  ### 1. Test Component Creation
49
51
 
50
52
  Always verify that components are created correctly with default options:
51
53
 
52
- ```javascript
54
+ ```typescript
53
55
  test('should create a component element', () => {
54
56
  const component = createComponent();
55
57
  expect(component.element).toBeDefined();
@@ -62,7 +64,7 @@ test('should create a component element', () => {
62
64
 
63
65
  Test that configuration options properly affect the component:
64
66
 
65
- ```javascript
67
+ ```typescript
66
68
  test('should apply variant class', () => {
67
69
  const variant = 'filled';
68
70
  const component = createComponent({
@@ -77,7 +79,7 @@ test('should apply variant class', () => {
77
79
 
78
80
  Verify that events are properly emitted and handled:
79
81
 
80
- ```javascript
82
+ ```typescript
81
83
  test('should handle click events', () => {
82
84
  const component = createComponent();
83
85
  const handleClick = mock(() => {});
@@ -96,9 +98,117 @@ test('should handle click events', () => {
96
98
 
97
99
  Test component state changes through its API:
98
100
 
99
- ```javascript
101
+ ```typescript
100
102
  test('should support disabled state', () => {
101
103
  const component = createComponent();
102
104
 
103
105
  // Initially not disabled
104
- expect(component.element.has
106
+ expect(component.disabled.isDisabled()).toBe(false);
107
+
108
+ // Disable
109
+ component.disable();
110
+ expect(component.disabled.isDisabled()).toBe(true);
111
+ expect(component.element.classList.contains('mtrl-component--disabled')).toBe(true);
112
+
113
+ // Enable
114
+ component.enable();
115
+ expect(component.disabled.isDisabled()).toBe(false);
116
+ expect(component.element.classList.contains('mtrl-component--disabled')).toBe(false);
117
+ });
118
+ ```
119
+
120
+ ## JSDOM Setup
121
+
122
+ We use JSDOM to create a DOM environment for component tests. Each test file that requires DOM manipulation should include the proper JSDOM setup:
123
+
124
+ ```typescript
125
+ // Setup jsdom environment
126
+ let dom: JSDOM;
127
+ let window: Window;
128
+ let document: Document;
129
+ let originalGlobalDocument: any;
130
+ let originalGlobalWindow: any;
131
+
132
+ beforeAll(() => {
133
+ // Create a new JSDOM instance
134
+ dom = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
135
+ url: 'http://localhost/',
136
+ pretendToBeVisual: true
137
+ });
138
+
139
+ // Get window and document from jsdom
140
+ window = dom.window;
141
+ document = window.document;
142
+
143
+ // Store original globals
144
+ originalGlobalDocument = global.document;
145
+ originalGlobalWindow = global.window;
146
+
147
+ // Set globals to use jsdom
148
+ global.document = document;
149
+ global.window = window;
150
+ global.Element = window.Element;
151
+ global.HTMLElement = window.HTMLElement;
152
+ global.Event = window.Event;
153
+ });
154
+
155
+ afterAll(() => {
156
+ // Restore original globals
157
+ global.document = originalGlobalDocument;
158
+ global.window = originalGlobalWindow;
159
+
160
+ // Clean up jsdom
161
+ window.close();
162
+ });
163
+ ```
164
+
165
+ ## Component Testing Approach
166
+
167
+ For most component tests, we use a mock implementation approach that creates components with the same interface as the real components, but with simplified internals. This approach:
168
+
169
+ 1. Avoids circular dependency issues in tests
170
+ 2. Makes tests faster and more isolated
171
+ 3. Allows testing component interfaces without implementation details
172
+ 4. Provides better control over the test environment
173
+
174
+ A typical mock component setup might look like:
175
+
176
+ ```typescript
177
+ const createMockComponent = (config: ComponentConfig = {}): ComponentInterface => {
178
+ // Create base elements
179
+ const element = document.createElement('div');
180
+ element.className = 'mtrl-component';
181
+
182
+ // Apply configuration
183
+ if (config.variant) {
184
+ element.classList.add(`mtrl-component--${config.variant}`);
185
+ }
186
+
187
+ // Event tracking
188
+ const eventHandlers: Record<string, Function[]> = {};
189
+
190
+ // Return component interface
191
+ return {
192
+ element,
193
+
194
+ // Component methods matching the real component API
195
+ setValue(value: string) {
196
+ element.setAttribute('value', value);
197
+ return this;
198
+ },
199
+
200
+ getValue() {
201
+ return element.getAttribute('value') || '';
202
+ },
203
+
204
+ on(event: string, handler: Function) {
205
+ if (!eventHandlers[event]) eventHandlers[event] = [];
206
+ eventHandlers[event].push(handler);
207
+ element.addEventListener(event, handler as EventListener);
208
+ return this;
209
+ },
210
+
211
+ // Additional methods as needed...
212
+ };
213
+ };
214
+ ```