mtrl 0.0.0 → 0.0.1
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/CONTRIBUTING.md +179 -0
- package/README.md +2 -0
- package/index.js +3 -2
- package/package.json +1 -1
- package/src/components/menu/api.js +117 -0
- package/src/components/menu/constants.js +42 -0
- package/src/components/menu/features/items-manager.js +371 -0
- package/src/components/menu/features/keyboard-navigation.js +129 -0
- package/src/components/menu/features/positioning.js +125 -0
- package/src/components/menu/features/visibility.js +179 -0
- package/src/components/menu/index.js +2 -0
- package/src/components/menu/menu-item.js +41 -0
- package/src/components/menu/menu.js +54 -0
- package/src/components/menu/styles.scss +150 -0
- package/src/index.js +4 -3
- package/src/styles/abstract/_config.scss +1 -1
- package/src/styles/abstract/_mixins.scss +75 -0
- package/src/styles/abstract/_variables.scss +1 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Contributing to MTRL
|
|
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.
|
|
4
|
+
|
|
5
|
+
## Why Contribute?
|
|
6
|
+
|
|
7
|
+
MTRL aims to be a modern, flexible UI component library with:
|
|
8
|
+
|
|
9
|
+
- Zero dependencies (except Bun for development)
|
|
10
|
+
- ES6+ focused codebase
|
|
11
|
+
- Lightweight, tree-shakable components
|
|
12
|
+
- Simple and extensible API
|
|
13
|
+
- Excellent documentation
|
|
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.
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
### Development Environment
|
|
20
|
+
|
|
21
|
+
1. **Fork and clone the repository**:
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/YOUR-USERNAME/mtrl.git
|
|
24
|
+
cd mtrl
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. **Install dependencies**:
|
|
28
|
+
```bash
|
|
29
|
+
bun install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Testing Your Components with mtrl.app
|
|
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:
|
|
35
|
+
|
|
36
|
+
1. **Build and link locally**:
|
|
37
|
+
```bash
|
|
38
|
+
# In the mtrl repository
|
|
39
|
+
bun run build
|
|
40
|
+
|
|
41
|
+
# Clone the mtrl.app repository
|
|
42
|
+
git clone https://github.com/YOUR-USERNAME/mtrl.app.git
|
|
43
|
+
cd mtrl.app
|
|
44
|
+
|
|
45
|
+
# Install dependencies and link to your local mtrl build
|
|
46
|
+
bun install
|
|
47
|
+
bun link ../path/to/your/mtrl
|
|
48
|
+
|
|
49
|
+
# Start the showcase server
|
|
50
|
+
bun run dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. **Use the official showcase site**:
|
|
54
|
+
Visit https://mtrl.app to see official examples and documentation.
|
|
55
|
+
|
|
56
|
+
## Contribution Workflow
|
|
57
|
+
|
|
58
|
+
1. **Pick an issue or feature** - Start with issues labeled `good-first-issue` or `help-wanted`.
|
|
59
|
+
|
|
60
|
+
2. **Create a branch** - Name your branch based on what you're working on:
|
|
61
|
+
```bash
|
|
62
|
+
git checkout -b feature/button-improvements
|
|
63
|
+
# or
|
|
64
|
+
git checkout -b fix/textfield-validation
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
3. **Make your changes** - Follow the coding standards and guidelines below.
|
|
68
|
+
|
|
69
|
+
4. **Test your changes** - Use the playground app to test your components in real-time.
|
|
70
|
+
|
|
71
|
+
5. **Submit a pull request** - Include a detailed description of your changes and reference any related issues.
|
|
72
|
+
|
|
73
|
+
## Development Guidelines
|
|
74
|
+
|
|
75
|
+
### Component Structure
|
|
76
|
+
|
|
77
|
+
MTRL components follow a consistent pattern:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// src/components/mycomponent/index.js
|
|
81
|
+
export { createMyComponent } from './mycomponent';
|
|
82
|
+
|
|
83
|
+
// src/components/mycomponent/mycomponent.js
|
|
84
|
+
import { createElement } from '../../core/dom/create';
|
|
85
|
+
import { createLifecycle } from '../../core/state/lifecycle';
|
|
86
|
+
// etc...
|
|
87
|
+
|
|
88
|
+
export const createMyComponent = (options = {}) => {
|
|
89
|
+
// Create DOM elements
|
|
90
|
+
const element = createElement({...});
|
|
91
|
+
|
|
92
|
+
// Setup state and features
|
|
93
|
+
const lifecycle = createLifecycle(element);
|
|
94
|
+
|
|
95
|
+
// Return component API
|
|
96
|
+
return {
|
|
97
|
+
element,
|
|
98
|
+
// Other public methods...
|
|
99
|
+
destroy() {
|
|
100
|
+
lifecycle.destroy();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Using mtrl.app for Development
|
|
107
|
+
|
|
108
|
+
The mtrl.app showcase application is the best way to develop and test your components:
|
|
109
|
+
|
|
110
|
+
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.
|
|
113
|
+
4. Implement different variants and states for testing.
|
|
114
|
+
5. Run the showcase server with `bun run dev` in the mtrl.app directory.
|
|
115
|
+
|
|
116
|
+
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
|
+
|
|
118
|
+
### Coding Standards
|
|
119
|
+
|
|
120
|
+
- Use ES6+ features but maintain browser compatibility
|
|
121
|
+
- Follow functional programming principles when possible
|
|
122
|
+
- Use consistent naming conventions:
|
|
123
|
+
- Factory functions should be named `createXyz`
|
|
124
|
+
- Utilities should use clear, descriptive names
|
|
125
|
+
- Write JSDoc comments for all public functions
|
|
126
|
+
|
|
127
|
+
### CSS/SCSS Guidelines
|
|
128
|
+
|
|
129
|
+
- Use BEM-style naming: `mtrl-component__element--modifier`
|
|
130
|
+
- Keep specificity low
|
|
131
|
+
- Use CSS variables for theming
|
|
132
|
+
- Organize styles in the `src/components/*/styles.scss` file
|
|
133
|
+
|
|
134
|
+
## Pull Request Process
|
|
135
|
+
|
|
136
|
+
1. Ensure your code follows the style guidelines
|
|
137
|
+
2. Update documentation as needed
|
|
138
|
+
3. Include a clear description of the changes
|
|
139
|
+
4. Reference any issues that are being addressed
|
|
140
|
+
5. Wait for review and address any feedback
|
|
141
|
+
|
|
142
|
+
## Testing
|
|
143
|
+
|
|
144
|
+
Please add appropriate tests for your changes:
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Example test structure
|
|
148
|
+
describe('myComponent', () => {
|
|
149
|
+
it('should render correctly', () => {
|
|
150
|
+
// Test code
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should handle user interaction', () => {
|
|
154
|
+
// Test code
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Documentation
|
|
160
|
+
|
|
161
|
+
For any new feature or component:
|
|
162
|
+
|
|
163
|
+
- Add JSDoc comments for API methods
|
|
164
|
+
- Update the component's README.md (if applicable)
|
|
165
|
+
- Consider adding example code in the playground
|
|
166
|
+
|
|
167
|
+
## Community and Communication
|
|
168
|
+
|
|
169
|
+
- Submit issues for bugs or feature requests
|
|
170
|
+
- Join the discussion on existing issues
|
|
171
|
+
- Be respectful and constructive in communications
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
By contributing to MTRL, you agree that your contributions will be licensed under the project's MIT License.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
Thank you for contributing to MTRL! Your efforts help make this library better for everyone.
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# MTRL Library
|
|
2
2
|
|
|
3
|
+
> **Project Status:** MTRL is in active early development. The core architecture and initial components are being established, with more features on the roadmap. While we're making rapid progress, the API may evolve as we refine the library. We welcome early adopters and contributors who want to help shape MTRL's future!
|
|
4
|
+
|
|
3
5
|
MTRL is a lightweight, composable JavaScript component library inspired by Material Design principles. Built with vanilla JavaScript and zero dependencies, MTRL provides a robust foundation for creating modern web interfaces with an emphasis on performance and accessibility.
|
|
4
6
|
|
|
5
7
|
## Understanding MTRL
|
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// index.js
|
|
2
2
|
import {
|
|
3
3
|
createLayout,
|
|
4
|
-
createElement,
|
|
4
|
+
createElement,
|
|
5
|
+
createButton, createCheckbox, createTextfield, createSwitch, createContainer, createList, createSnackbar, createNavigation, createMenu
|
|
5
6
|
} from './src/index.js'
|
|
6
7
|
|
|
7
8
|
export {
|
|
8
9
|
createLayout,
|
|
9
|
-
createElement, createButton, createCheckbox, createTextfield, createSwitch, createContainer, createList, createSnackbar, createNavigation
|
|
10
|
+
createElement, createButton, createCheckbox, createTextfield, createSwitch, createContainer, createList, createSnackbar, createNavigation, createMenu
|
|
10
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mtrl",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"description": "A functional JavaScript component library with composable architecture based on Material Design 3",
|
|
5
5
|
"keywords": ["component", "library", "ui", "user interface", "functional", "composable"],
|
|
6
6
|
"main": "index.js",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// src/components/menu/api.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Enhances menu component with API methods
|
|
5
|
+
* @param {Object} options - API configuration
|
|
6
|
+
* @param {Object} options.lifecycle - Lifecycle handlers
|
|
7
|
+
*/
|
|
8
|
+
export const withAPI = ({ lifecycle }) => (component) => ({
|
|
9
|
+
...component,
|
|
10
|
+
element: component.element,
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Shows the menu
|
|
14
|
+
* @returns {Object} Component instance
|
|
15
|
+
*/
|
|
16
|
+
show () {
|
|
17
|
+
component.show()
|
|
18
|
+
return this
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hides the menu
|
|
23
|
+
* @returns {Object} Component instance
|
|
24
|
+
*/
|
|
25
|
+
hide () {
|
|
26
|
+
component.hide()
|
|
27
|
+
return this
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Positions the menu relative to a target
|
|
32
|
+
* @param {HTMLElement} target - Target element
|
|
33
|
+
* @param {Object} options - Position options
|
|
34
|
+
* @returns {Object} Component instance
|
|
35
|
+
*/
|
|
36
|
+
position (target, options) {
|
|
37
|
+
component.position(target, options)
|
|
38
|
+
return this
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Adds an item to the menu
|
|
43
|
+
* @param {Object} config - Item configuration
|
|
44
|
+
* @returns {Object} Component instance
|
|
45
|
+
*/
|
|
46
|
+
addItem (config) {
|
|
47
|
+
component.addItem?.(config)
|
|
48
|
+
return this
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Removes an item by name
|
|
53
|
+
* @param {string} name - Item name to remove
|
|
54
|
+
* @returns {Object} Component instance
|
|
55
|
+
*/
|
|
56
|
+
removeItem (name) {
|
|
57
|
+
component.removeItem?.(name)
|
|
58
|
+
return this
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Gets all registered items
|
|
63
|
+
* @returns {Map} Map of item names to configurations
|
|
64
|
+
*/
|
|
65
|
+
getItems () {
|
|
66
|
+
return component.getItems?.()
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Checks if the menu is currently visible
|
|
71
|
+
* @returns {boolean} Whether the menu is visible
|
|
72
|
+
*/
|
|
73
|
+
isVisible () {
|
|
74
|
+
return component.isVisible?.()
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Registers an event handler
|
|
79
|
+
* @param {string} event - Event name
|
|
80
|
+
* @param {Function} handler - Event handler
|
|
81
|
+
* @returns {Object} Component instance
|
|
82
|
+
*/
|
|
83
|
+
on (event, handler) {
|
|
84
|
+
component.on(event, handler)
|
|
85
|
+
return this
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Unregisters an event handler
|
|
90
|
+
* @param {string} event - Event name
|
|
91
|
+
* @param {Function} handler - Event handler
|
|
92
|
+
* @returns {Object} Component instance
|
|
93
|
+
*/
|
|
94
|
+
off (event, handler) {
|
|
95
|
+
component.off(event, handler)
|
|
96
|
+
return this
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Destroys the menu component and cleans up resources
|
|
101
|
+
* @returns {Object} Component instance
|
|
102
|
+
*/
|
|
103
|
+
destroy () {
|
|
104
|
+
// First close any open submenus
|
|
105
|
+
component.hide?.()
|
|
106
|
+
|
|
107
|
+
// Then destroy the component
|
|
108
|
+
lifecycle.destroy?.()
|
|
109
|
+
|
|
110
|
+
// Final cleanup - forcibly remove from DOM if still attached
|
|
111
|
+
if (component.element && component.element.parentNode) {
|
|
112
|
+
component.element.remove()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return this
|
|
116
|
+
}
|
|
117
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/components/menu/constants.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Menu alignment options
|
|
5
|
+
* @enum {string}
|
|
6
|
+
*/
|
|
7
|
+
export const MENU_ALIGN = {
|
|
8
|
+
LEFT: 'left',
|
|
9
|
+
RIGHT: 'right',
|
|
10
|
+
CENTER: 'center'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Menu vertical alignment options
|
|
15
|
+
* @enum {string}
|
|
16
|
+
*/
|
|
17
|
+
export const MENU_VERTICAL_ALIGN = {
|
|
18
|
+
TOP: 'top',
|
|
19
|
+
BOTTOM: 'bottom',
|
|
20
|
+
MIDDLE: 'middle'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Menu item types
|
|
25
|
+
* @enum {string}
|
|
26
|
+
*/
|
|
27
|
+
export const MENU_ITEM_TYPES = {
|
|
28
|
+
ITEM: 'item',
|
|
29
|
+
DIVIDER: 'divider'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Menu events
|
|
34
|
+
* @enum {string}
|
|
35
|
+
*/
|
|
36
|
+
export const MENU_EVENTS = {
|
|
37
|
+
SELECT: 'select',
|
|
38
|
+
OPEN: 'open',
|
|
39
|
+
CLOSE: 'close',
|
|
40
|
+
SUBMENU_OPEN: 'submenuOpen',
|
|
41
|
+
SUBMENU_CLOSE: 'submenuClose'
|
|
42
|
+
}
|