mtrl 0.3.1 → 0.3.3

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 (162) hide show
  1. package/.env +15 -0
  2. package/CONTRIBUTING.md +62 -23
  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/navigation/nav-item.ts +13 -2
  83. package/src/components/sheet/config.ts +1 -2
  84. package/src/components/sheet/features/gestures.ts +1 -1
  85. package/src/components/sheet/features/position.ts +1 -2
  86. package/src/components/sheet/features/state.ts +1 -1
  87. package/src/components/sheet/index.ts +10 -2
  88. package/src/components/sheet/sheet.ts +1 -2
  89. package/src/components/sheet/types.ts +29 -1
  90. package/src/components/slider/api.ts +1 -1
  91. package/src/components/slider/config.ts +1 -1
  92. package/src/components/slider/features/controller.ts +1 -1
  93. package/src/components/slider/features/handlers.ts +1 -1
  94. package/src/components/slider/features/states.ts +1 -1
  95. package/src/components/slider/index.ts +12 -5
  96. package/src/components/slider/schema.ts +1 -1
  97. package/src/components/slider/types.ts +31 -0
  98. package/src/components/tabs/tab-api.ts +1 -1
  99. package/src/components/tabs/types.ts +1 -1
  100. package/src/components/tooltip/api.ts +6 -2
  101. package/src/components/tooltip/config.ts +9 -28
  102. package/src/components/tooltip/index.ts +10 -1
  103. package/src/components/tooltip/types.ts +38 -3
  104. package/src/core/dom/create.ts +57 -51
  105. package/src/index.ts +129 -31
  106. package/src/styles/abstract/_mixins.scss +23 -9
  107. package/src/styles/abstract/_variables.scss +14 -4
  108. package/src/styles/components/_card.scss +1 -1
  109. package/src/styles/components/_chip.scss +323 -113
  110. package/src/styles/components/_tabs.scss +1 -1
  111. package/src/styles/themes/_autumn.scss +3 -0
  112. package/CLAUDE.md +0 -33
  113. package/src/components/checkbox/constants.ts +0 -37
  114. package/src/components/chip/chip-set.ts +0 -225
  115. package/src/components/chip/chip.ts +0 -118
  116. package/src/components/chip/constants.ts +0 -28
  117. package/src/components/chip/index.ts +0 -12
  118. package/src/components/list/constants.ts +0 -116
  119. package/src/components/sheet/constants.ts +0 -20
  120. package/src/components/slider/constants.ts +0 -32
  121. package/src/components/tooltip/constants.ts +0 -27
  122. package/test/components/badge.test.ts +0 -545
  123. package/test/components/bottom-app-bar.test.ts +0 -303
  124. package/test/components/button.test.ts +0 -233
  125. package/test/components/card.test.ts +0 -560
  126. package/test/components/carousel.test.ts +0 -951
  127. package/test/components/checkbox.test.ts +0 -462
  128. package/test/components/chip.test.ts +0 -692
  129. package/test/components/datepicker.test.ts +0 -1124
  130. package/test/components/dialog.test.ts +0 -990
  131. package/test/components/divider.test.ts +0 -412
  132. package/test/components/extended-fab.test.ts +0 -672
  133. package/test/components/fab.test.ts +0 -561
  134. package/test/components/list.test.ts +0 -365
  135. package/test/components/menu.test.ts +0 -718
  136. package/test/components/navigation.test.ts +0 -186
  137. package/test/components/progress.test.ts +0 -567
  138. package/test/components/radios.test.ts +0 -699
  139. package/test/components/search.test.ts +0 -1135
  140. package/test/components/segmented-button.test.ts +0 -732
  141. package/test/components/sheet.test.ts +0 -641
  142. package/test/components/slider.test.ts +0 -1220
  143. package/test/components/snackbar.test.ts +0 -461
  144. package/test/components/switch.test.ts +0 -452
  145. package/test/components/tabs.test.ts +0 -1369
  146. package/test/components/textfield.test.ts +0 -400
  147. package/test/components/timepicker.test.ts +0 -592
  148. package/test/components/tooltip.test.ts +0 -630
  149. package/test/components/top-app-bar.test.ts +0 -566
  150. package/test/core/dom.attributes.test.ts +0 -148
  151. package/test/core/dom.classes.test.ts +0 -152
  152. package/test/core/dom.events.test.ts +0 -243
  153. package/test/core/emitter.test.ts +0 -141
  154. package/test/core/ripple.test.ts +0 -99
  155. package/test/core/state.store.test.ts +0 -189
  156. package/test/core/utils.normalize.test.ts +0 -61
  157. package/test/core/utils.object.test.ts +0 -120
  158. package/test/setup.js +0 -371
  159. package/test/setup.ts +0 -451
  160. package/tsconfig.json +0 -22
  161. package/typedoc.json +0 -28
  162. 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,18 +1,18 @@
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, TypeScript-focused 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
- - ES6+ focused codebase
10
+ - TypeScript-first codebase
11
11
  - Lightweight, tree-shakable components
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 TypeScript 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,18 +74,31 @@ 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
- ```javascript
80
- // src/components/mycomponent/index.js
79
+ ```typescript
80
+ // src/components/mycomponent/index.ts
81
81
  export { createMyComponent } from './mycomponent';
82
+ export type { MyComponentOptions } from './types';
82
83
 
83
- // src/components/mycomponent/mycomponent.js
84
+ // src/components/mycomponent/types.ts
85
+ export interface MyComponentOptions {
86
+ text?: string;
87
+ onClick?: (event: MouseEvent) => void;
88
+ // other options...
89
+ }
90
+
91
+ // src/components/mycomponent/mycomponent.ts
84
92
  import { createElement } from '../../core/dom/create';
85
93
  import { createLifecycle } from '../../core/state/lifecycle';
86
- // etc...
87
-
88
- export const createMyComponent = (options = {}) => {
94
+ import type { MyComponentOptions } from './types';
95
+
96
+ /**
97
+ * Creates a new MyComponent instance
98
+ * @param options - Configuration options for MyComponent
99
+ * @returns The MyComponent instance
100
+ */
101
+ export const createMyComponent = (options: MyComponentOptions = {}) => {
89
102
  // Create DOM elements
90
103
  const element = createElement({...});
91
104
 
@@ -108,21 +121,30 @@ export const createMyComponent = (options = {}) => {
108
121
  The mtrl.app showcase application is the best way to develop and test your components:
109
122
 
110
123
  1. Clone the mtrl.app repository alongside your mtrl clone.
111
- 2. Create a new view file in `src/client/views/components/` for your component.
112
- 3. Add the route in `src/client/core/navigation.js` of the mtrl.app repository.
124
+ 2. Create a new view file in `src/client/content/components/` for your component.
125
+ 3. Add the route in `src/client/core/navigation.ts` of the mtrl.app repository.
113
126
  4. Implement different variants and states for testing.
114
127
  5. Run the showcase server with `bun run dev` in the mtrl.app directory.
115
128
 
116
129
  This separation of the library code (mtrl) and the showcase app (mtrl.app) keeps the core library clean while providing a rich development environment.
117
130
 
131
+ ### TypeScript Standards
132
+
133
+ - Use TypeScript's type system to create clear interfaces and types
134
+ - Export types and interfaces separately from implementations
135
+ - Use strict typing and avoid `any` when possible
136
+ - Prefer interfaces for public APIs and type aliases for complex types
137
+ - Add proper return types to all functions
138
+
118
139
  ### Coding Standards
119
140
 
120
- - Use ES6+ features but maintain browser compatibility
121
- - Follow functional programming principles when possible
141
+ - Add file path as a comment on the first line of each file
142
+ - Use functional programming principles when possible
122
143
  - Use consistent naming conventions:
123
144
  - Factory functions should be named `createXyz`
124
145
  - Utilities should use clear, descriptive names
125
- - Write JSDoc comments for all public functions
146
+ - Interfaces should be named in PascalCase (e.g., `ButtonOptions`)
147
+ - Write TypeDoc comments for all public functions and types
126
148
 
127
149
  ### CSS/SCSS Guidelines
128
150
 
@@ -143,7 +165,7 @@ This separation of the library code (mtrl) and the showcase app (mtrl.app) keeps
143
165
 
144
166
  Please add appropriate tests for your changes:
145
167
 
146
- ```javascript
168
+ ```typescript
147
169
  // Example test structure
148
170
  describe('myComponent', () => {
149
171
  it('should render correctly', () => {
@@ -158,12 +180,29 @@ describe('myComponent', () => {
158
180
 
159
181
  ## Documentation
160
182
 
161
- For any new feature or component:
183
+ Documentation is crucial for this project:
162
184
 
163
- - Add JSDoc comments for API methods
185
+ - Add TypeDoc comments for all public API methods and types
186
+ - Comment the file path at the top of each file
164
187
  - Update the component's README.md (if applicable)
165
188
  - Consider adding example code in the playground
166
189
 
190
+ Example of proper TypeDoc:
191
+
192
+ ```typescript
193
+ /**
194
+ * Creates a button element with specified options
195
+ *
196
+ * @param options - The button configuration options
197
+ * @returns A button component instance
198
+ * @example
199
+ * ```ts
200
+ * const button = createButton({ text: 'Click me', variant: 'primary' });
201
+ * document.body.appendChild(button.element);
202
+ * ```
203
+ */
204
+ ```
205
+
167
206
  ## Community and Communication
168
207
 
169
208
  - Submit issues for bugs or feature requests
@@ -172,8 +211,8 @@ For any new feature or component:
172
211
 
173
212
  ## License
174
213
 
175
- By contributing to MTRL, you agree that your contributions will be licensed under the project's MIT License.
214
+ By contributing to mtrl, you agree that your contributions will be licensed under the project's MIT License.
176
215
 
177
216
  ---
178
217
 
179
- Thank you for contributing to MTRL! Your efforts help make this library better for everyone.
218
+ 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
+ ```