mtrl 0.0.0

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 (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +251 -0
  3. package/index.js +10 -0
  4. package/package.json +17 -0
  5. package/src/components/button/api.js +54 -0
  6. package/src/components/button/button.js +81 -0
  7. package/src/components/button/config.js +8 -0
  8. package/src/components/button/constants.js +63 -0
  9. package/src/components/button/index.js +2 -0
  10. package/src/components/button/styles.scss +231 -0
  11. package/src/components/checkbox/api.js +45 -0
  12. package/src/components/checkbox/checkbox.js +95 -0
  13. package/src/components/checkbox/constants.js +88 -0
  14. package/src/components/checkbox/index.js +2 -0
  15. package/src/components/checkbox/styles.scss +183 -0
  16. package/src/components/container/api.js +42 -0
  17. package/src/components/container/container.js +45 -0
  18. package/src/components/container/index.js +2 -0
  19. package/src/components/container/styles.scss +59 -0
  20. package/src/components/list/constants.js +89 -0
  21. package/src/components/list/index.js +2 -0
  22. package/src/components/list/list-item.js +147 -0
  23. package/src/components/list/list.js +267 -0
  24. package/src/components/list/styles/_list-item.scss +142 -0
  25. package/src/components/list/styles/_list.scss +89 -0
  26. package/src/components/list/styles/_variables.scss +13 -0
  27. package/src/components/list/styles.scss +19 -0
  28. package/src/components/navigation/api.js +43 -0
  29. package/src/components/navigation/constants.js +235 -0
  30. package/src/components/navigation/features/items.js +192 -0
  31. package/src/components/navigation/index.js +2 -0
  32. package/src/components/navigation/nav-item.js +137 -0
  33. package/src/components/navigation/navigation.js +55 -0
  34. package/src/components/navigation/styles/_bar.scss +51 -0
  35. package/src/components/navigation/styles/_base.scss +129 -0
  36. package/src/components/navigation/styles/_drawer.scss +169 -0
  37. package/src/components/navigation/styles/_rail.scss +65 -0
  38. package/src/components/navigation/styles.scss +6 -0
  39. package/src/components/snackbar/api.js +125 -0
  40. package/src/components/snackbar/constants.js +41 -0
  41. package/src/components/snackbar/features.js +69 -0
  42. package/src/components/snackbar/index.js +2 -0
  43. package/src/components/snackbar/position.js +63 -0
  44. package/src/components/snackbar/queue.js +74 -0
  45. package/src/components/snackbar/snackbar.js +70 -0
  46. package/src/components/snackbar/styles.scss +182 -0
  47. package/src/components/switch/api.js +44 -0
  48. package/src/components/switch/constants.js +80 -0
  49. package/src/components/switch/index.js +2 -0
  50. package/src/components/switch/styles.scss +172 -0
  51. package/src/components/switch/switch.js +71 -0
  52. package/src/components/textfield/api.js +49 -0
  53. package/src/components/textfield/constants.js +81 -0
  54. package/src/components/textfield/index.js +2 -0
  55. package/src/components/textfield/styles/base.scss +107 -0
  56. package/src/components/textfield/styles/filled.scss +58 -0
  57. package/src/components/textfield/styles/outlined.scss +66 -0
  58. package/src/components/textfield/styles.scss +6 -0
  59. package/src/components/textfield/textfield.js +68 -0
  60. package/src/core/build/constants.js +51 -0
  61. package/src/core/build/icon.js +78 -0
  62. package/src/core/build/ripple.js +92 -0
  63. package/src/core/build/text.js +54 -0
  64. package/src/core/collection/adapters/base.js +26 -0
  65. package/src/core/collection/adapters/mongodb.js +232 -0
  66. package/src/core/collection/adapters/route.js +201 -0
  67. package/src/core/collection/collection.js +259 -0
  68. package/src/core/collection/list-manager.js +157 -0
  69. package/src/core/compose/base.js +8 -0
  70. package/src/core/compose/component.js +225 -0
  71. package/src/core/compose/features/checkable.js +114 -0
  72. package/src/core/compose/features/disabled.js +25 -0
  73. package/src/core/compose/features/events.js +48 -0
  74. package/src/core/compose/features/icon.js +33 -0
  75. package/src/core/compose/features/index.js +20 -0
  76. package/src/core/compose/features/input.js +92 -0
  77. package/src/core/compose/features/lifecycle.js +69 -0
  78. package/src/core/compose/features/position.js +60 -0
  79. package/src/core/compose/features/ripple.js +32 -0
  80. package/src/core/compose/features/size.js +9 -0
  81. package/src/core/compose/features/style.js +12 -0
  82. package/src/core/compose/features/text.js +17 -0
  83. package/src/core/compose/features/textinput.js +118 -0
  84. package/src/core/compose/features/textlabel.js +28 -0
  85. package/src/core/compose/features/track.js +49 -0
  86. package/src/core/compose/features/variant.js +9 -0
  87. package/src/core/compose/features/withEvents.js +67 -0
  88. package/src/core/compose/index.js +16 -0
  89. package/src/core/compose/pipe.js +69 -0
  90. package/src/core/config.js +140 -0
  91. package/src/core/dom/attributes.js +33 -0
  92. package/src/core/dom/classes.js +70 -0
  93. package/src/core/dom/create.js +133 -0
  94. package/src/core/dom/events.js +175 -0
  95. package/src/core/dom/index.js +5 -0
  96. package/src/core/dom/utils.js +22 -0
  97. package/src/core/index.js +23 -0
  98. package/src/core/layout/index.js +93 -0
  99. package/src/core/state/disabled.js +14 -0
  100. package/src/core/state/emitter.js +63 -0
  101. package/src/core/state/events.js +29 -0
  102. package/src/core/state/index.js +6 -0
  103. package/src/core/state/lifecycle.js +64 -0
  104. package/src/core/state/store.js +112 -0
  105. package/src/core/utils/index.js +39 -0
  106. package/src/core/utils/mobile.js +74 -0
  107. package/src/core/utils/object.js +22 -0
  108. package/src/core/utils/validate.js +37 -0
  109. package/src/index.js +11 -0
  110. package/src/styles/abstract/_base.scss +2 -0
  111. package/src/styles/abstract/_config.scss +28 -0
  112. package/src/styles/abstract/_functions.scss +124 -0
  113. package/src/styles/abstract/_mixins.scss +261 -0
  114. package/src/styles/abstract/_variables.scss +158 -0
  115. package/src/styles/main.scss +78 -0
  116. package/src/styles/themes/_base-theme.scss +49 -0
  117. package/src/styles/themes/_baseline.scss +90 -0
  118. package/src/styles/themes/_forest.scss +71 -0
  119. package/src/styles/themes/_index.scss +6 -0
  120. package/src/styles/themes/_ocean.scss +71 -0
  121. package/src/styles/themes/_sunset.scss +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 floor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,251 @@
1
+ # MTRL Library
2
+
3
+ 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
+
5
+ ## Understanding MTRL
6
+
7
+ 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.
8
+
9
+ ### Design Philosophy
10
+
11
+ MTRL is built on several core principles:
12
+
13
+ 1. **Composition Over Inheritance**: Components are constructed through functional composition, making them flexible and maintainable.
14
+ 2. **Zero Dependencies**: The entire library is built with vanilla JavaScript, ensuring minimal bundle size and maximum compatibility.
15
+ 3. **Material Design Inspiration**: While inspired by Material Design, MTRL provides flexibility in styling and behavior.
16
+ 4. **Accessibility First**: Built-in accessibility features ensure your applications are usable by everyone.
17
+
18
+ ## Core Components
19
+
20
+ MTRL provides a comprehensive set of components, each following Material Design principles:
21
+
22
+ ```javascript
23
+ import { createButton, createTextField } from 'mtrl'
24
+
25
+ // Create a material button with ripple effect
26
+ const button = createButton({
27
+ text: 'Submit',
28
+ variant: 'filled',
29
+ ripple: true,
30
+ class: 'custom-button'
31
+ })
32
+
33
+ // className will be: mtrl-button mtrl-button--filled custom-button
34
+ ```
35
+
36
+ ### Component List
37
+
38
+ Each component follows the `mtrl-` prefix convention:
39
+
40
+ - `mtrl-button` - Material buttons with ripple effects
41
+ - `mtrl-textfield` - Text input components
42
+ - `mtrl-switch` - Toggle switches
43
+ - `mtrl-navigation` - Navigation components
44
+ - `mtrl-list` - List components with selection
45
+ - `mtrl-snackbar` - Toast notifications
46
+ - `mtrl-container` - Layout containers
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ # Using npm
52
+ npm install mtrl
53
+
54
+ # Using yarn
55
+ yarn add mtrl
56
+
57
+ # Using bun
58
+ bun add mtrl
59
+ ```
60
+
61
+ ## Component Architecture
62
+
63
+ Let's look at how MTRL components are constructed:
64
+
65
+ ```javascript
66
+ // Example of a button component creation
67
+ const button = createButton({
68
+ prefix: 'mtrl', // The library's prefix
69
+ componentName: 'button', // Component identifier
70
+ variant: 'filled', // Visual variant
71
+ text: 'Click me', // Button text
72
+ ripple: true // Enable ripple effect
73
+ })
74
+ ```
75
+
76
+ ### The Composition System
77
+
78
+ MTRL uses a pipe-based composition system for building components:
79
+
80
+ ```javascript
81
+ // Internal component creation
82
+ const createButton = (config) => {
83
+ return pipe(
84
+ createBase, // Base component structure
85
+ withEvents(), // Event handling capability
86
+ withElement({ // DOM element creation
87
+ tag: 'button',
88
+ componentName: 'button',
89
+ prefix: 'mtrl'
90
+ }),
91
+ withVariant(config), // Visual variant support
92
+ withText(config), // Text content management
93
+ withIcon(config), // Icon support
94
+ withRipple(config) // Ripple animation
95
+ )(config)
96
+ }
97
+ ```
98
+
99
+ ### CSS Classes
100
+
101
+ MTRL follows a consistent class naming convention:
102
+
103
+ ```css
104
+ .mtrl-component /* Base component class */
105
+ .mtrl-component--variant /* Variant modifier */
106
+ .mtrl-component--state /* State modifier (disabled, focused) */
107
+ .mtrl-component-element /* Child element */
108
+ ```
109
+
110
+ ## State Management
111
+
112
+ MTRL provides several approaches to state management:
113
+
114
+ ### Local Component State
115
+
116
+ ```javascript
117
+ const textField = createTextField({
118
+ label: 'Username'
119
+ })
120
+
121
+ textField.on('input', ({ value }) => {
122
+ console.log('Current value:', value)
123
+ })
124
+
125
+ textField.setValue('New value')
126
+ ```
127
+
128
+ ### Collection Management
129
+
130
+ For managing lists and datasets:
131
+
132
+ ```javascript
133
+ const collection = new Collection({
134
+ transform: (item) => ({
135
+ ...item,
136
+ displayName: `${item.firstName} ${item.lastName}`
137
+ })
138
+ })
139
+
140
+ collection.subscribe(({ event, data }) => {
141
+ console.log(`Collection ${event}:`, data)
142
+ })
143
+ ```
144
+
145
+ ## Data Integration
146
+
147
+ MTRL provides adapters for different data sources:
148
+
149
+ ```javascript
150
+ // MongoDB adapter
151
+ const mongoAdapter = createMongoAdapter({
152
+ uri: 'mongodb://localhost:27017',
153
+ dbName: 'mtrl-app',
154
+ collection: 'users'
155
+ })
156
+
157
+ // Route adapter for REST APIs
158
+ const routeAdapter = createRouteAdapter({
159
+ base: '/api',
160
+ endpoints: {
161
+ list: '/users',
162
+ create: '/users'
163
+ }
164
+ })
165
+ ```
166
+
167
+ ## Customization
168
+
169
+ ### Creating Custom Components
170
+
171
+ Extend MTRL by creating custom components:
172
+
173
+ ```javascript
174
+ const createCustomCard = (config) => {
175
+ return pipe(
176
+ createBase,
177
+ withEvents(),
178
+ withElement({
179
+ tag: 'div',
180
+ componentName: 'card',
181
+ prefix: 'mtrl'
182
+ }),
183
+ // Add custom features
184
+ (component) => ({
185
+ ...component,
186
+ setContent(content) {
187
+ component.element.innerHTML = content
188
+ return this
189
+ }
190
+ })
191
+ )(config)
192
+ }
193
+ ```
194
+
195
+ ### Styling
196
+
197
+ MTRL components can be styled through CSS custom properties:
198
+
199
+ ```css
200
+ :root {
201
+ --mtrl-primary: #6200ee;
202
+ --mtrl-surface: #ffffff;
203
+ --mtrl-on-surface: #000000;
204
+ --mtrl-elevation-1: 0 2px 4px rgba(0,0,0,0.2);
205
+ }
206
+ ```
207
+
208
+ ## Best Practices
209
+
210
+ ### Performance
211
+
212
+ MTRL is designed with performance in mind:
213
+
214
+ - Minimal DOM operations
215
+ - Efficient event handling
216
+ - Automatic cleanup of resources
217
+ - Lazy initialization of features
218
+
219
+ ### Accessibility
220
+
221
+ Built-in accessibility features include:
222
+
223
+ - ARIA attributes management
224
+ - Keyboard navigation
225
+ - Focus management
226
+ - Screen reader support
227
+
228
+ ## Browser Support
229
+
230
+ MTRL supports modern browsers:
231
+
232
+ - Chrome (latest)
233
+ - Firefox (latest)
234
+ - Safari (latest)
235
+ - Edge (latest)
236
+
237
+ ## Contributing
238
+
239
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
240
+
241
+ ## License
242
+
243
+ MTRL is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
244
+
245
+ ## Documentation
246
+
247
+ For detailed API documentation, examples, and guides, visit our [documentation site](https://mtrl.app).
248
+
249
+ ---
250
+
251
+ This library is designed to provide a solid foundation for building modern web interfaces while maintaining flexibility for custom implementations. For questions, issues, or contributions, please visit our GitHub repository.
package/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // index.js
2
+ import {
3
+ createLayout,
4
+ createElement, createButton, createCheckbox, createTextfield, createSwitch, createContainer, createList, createSnackbar, createNavigation
5
+ } from './src/index.js'
6
+
7
+ export {
8
+ createLayout,
9
+ createElement, createButton, createCheckbox, createTextfield, createSwitch, createContainer, createList, createSnackbar, createNavigation
10
+ }
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "mtrl",
3
+ "version": "0.0.0",
4
+ "description": "A functional JavaScript component library with composable architecture based on Material Design 3",
5
+ "keywords": ["component", "library", "ui", "user interface", "functional", "composable"],
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/floor/mtrl.git"
13
+ },
14
+
15
+ "author": "floor",
16
+ "license": "GPL-3.0"
17
+ }
@@ -0,0 +1,54 @@
1
+ // src/components/button/api.js
2
+
3
+ /**
4
+ * Enhances a button component with API methods
5
+ * @param {Object} options - API configuration options
6
+ * @param {Object} options.disabled - Object containing enable/disable methods
7
+ * @param {Object} options.lifecycle - Object containing lifecycle methods
8
+ * @returns {Function} Higher-order function that adds API methods to component
9
+ * @internal This is an internal utility for the Button component
10
+ */
11
+ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
12
+ ...component,
13
+ element: component.element,
14
+ getValue: () => component.element.value,
15
+ setValue (value) {
16
+ component.element.value = value
17
+ return this
18
+ },
19
+ enable () {
20
+ disabled.enable()
21
+ return this
22
+ },
23
+ disable () {
24
+ disabled.disable()
25
+ return this
26
+ },
27
+ setText (content) {
28
+ component.text.setText(content)
29
+ this.updateCircularStyle()
30
+ return this
31
+ },
32
+ getText () {
33
+ return component.text.getText()
34
+ },
35
+ setIcon (icon) {
36
+ component.icon.setIcon(icon)
37
+ this.updateCircularStyle()
38
+ return this
39
+ },
40
+ getIcon () {
41
+ return component.icon.getIcon()
42
+ },
43
+ destroy () {
44
+ lifecycle.destroy()
45
+ },
46
+ updateCircularStyle () {
47
+ const hasText = component.text.getElement()
48
+ if (!hasText && component.icon.getElement()) {
49
+ component.element.classList.add(`${component.getClass('button')}--circular`)
50
+ } else {
51
+ component.element.classList.remove(`${component.getClass('button')}--circular`)
52
+ }
53
+ }
54
+ })
@@ -0,0 +1,81 @@
1
+ // src/components/button/button.js
2
+ import { PREFIX } from '../../core/config'
3
+ import { pipe } from '../../core/compose'
4
+ import { createBase, withElement } from '../../core/compose/component'
5
+ import {
6
+ withEvents,
7
+ withText,
8
+ withIcon,
9
+ withVariant,
10
+ withSize,
11
+ withRipple,
12
+ withDisabled,
13
+ withLifecycle
14
+ } from '../../core/compose/features'
15
+ import { withAPI } from './api'
16
+ import { BUTTON_VARIANTS } from './constants'
17
+
18
+ /**
19
+ * Creates a new Button component
20
+ * @param {Object} config - Button configuration object
21
+ * @param {string} [config.variant='filled'] - Button variant (filled, tonal, outlined, elevated, text)
22
+ * @param {string} [config.size] - Button size (small, medium, large)
23
+ * @param {boolean} [config.disabled] - Whether the button is initially disabled
24
+ * @param {string} [config.text] - Initial button text content
25
+ * @param {string} [config.icon] - Initial button icon HTML content
26
+ * @param {string} [config.class] - Additional CSS classes
27
+ * @param {string} [config.value] - Button value attribute
28
+ */
29
+ const createButton = (config = {}) => {
30
+ const baseConfig = {
31
+ ...config,
32
+ variant: config.variant || BUTTON_VARIANTS.FILLED,
33
+ componentName: 'button',
34
+ prefix: PREFIX
35
+ }
36
+
37
+ try {
38
+ const button = pipe(
39
+ createBase,
40
+ withEvents(),
41
+ withElement({
42
+ tag: 'button',
43
+ componentName: 'button',
44
+ attrs: {
45
+ type: config.type || 'button',
46
+ disabled: config.disabled,
47
+ value: config.value
48
+ },
49
+ className: config.class,
50
+ forwardEvents: {
51
+ click: (component) => !component.element.disabled,
52
+ focus: true,
53
+ blur: true
54
+ }
55
+ }),
56
+ withVariant(baseConfig),
57
+ withSize(baseConfig),
58
+ withText(baseConfig),
59
+ withIcon(baseConfig),
60
+ withDisabled(baseConfig),
61
+ withRipple(baseConfig),
62
+ withLifecycle(),
63
+ comp => withAPI({
64
+ disabled: {
65
+ enable: () => comp.disabled.enable(),
66
+ disable: () => comp.disabled.disable()
67
+ },
68
+ lifecycle: {
69
+ destroy: () => comp.lifecycle.destroy()
70
+ }
71
+ })(comp)
72
+ )(baseConfig)
73
+
74
+ return button
75
+ } catch (error) {
76
+ console.error('Button creation error:', error)
77
+ throw new Error(`Failed to create button: ${error.message}`)
78
+ }
79
+ }
80
+
81
+ export default createButton
@@ -0,0 +1,8 @@
1
+ import PREFIX from '../../core/config'
2
+
3
+ const defaultConfig = {
4
+ componentName: 'button',
5
+ prefix: PREFIX
6
+ }
7
+
8
+ export default defaultConfig
@@ -0,0 +1,63 @@
1
+ // src/components/button/constants.js
2
+
3
+ import { RIPPLE_SCHEMA } from '../../core/build/constants'
4
+
5
+ export const BUTTON_VARIANTS = {
6
+ FILLED: 'filled',
7
+ TONAL: 'tonal',
8
+ OUTLINED: 'outlined',
9
+ ELEVATED: 'elevated',
10
+ TEXT: 'text'
11
+ }
12
+
13
+ export const BUTTON_SIZES = {
14
+ SMALL: 'small',
15
+ MEDIUM: 'medium',
16
+ LARGE: 'large'
17
+ }
18
+
19
+ /**
20
+ * Validation schema for button configuration
21
+ */
22
+ export const BUTTON_SCHEMA = {
23
+ variant: {
24
+ type: 'string',
25
+ enum: Object.values(BUTTON_VARIANTS),
26
+ required: false
27
+ },
28
+ size: {
29
+ type: 'string',
30
+ enum: Object.values(BUTTON_SIZES),
31
+ required: false
32
+ },
33
+ disabled: {
34
+ type: 'boolean',
35
+ required: false
36
+ },
37
+ text: {
38
+ type: 'string',
39
+ required: false
40
+ },
41
+ icon: {
42
+ type: 'string',
43
+ required: false
44
+ },
45
+ class: {
46
+ type: 'string',
47
+ required: false
48
+ },
49
+ value: {
50
+ type: 'string',
51
+ required: false
52
+ },
53
+ ripple: {
54
+ type: 'boolean',
55
+ required: false,
56
+ default: true
57
+ },
58
+ rippleConfig: {
59
+ type: 'object',
60
+ required: false,
61
+ properties: RIPPLE_SCHEMA
62
+ }
63
+ }
@@ -0,0 +1,2 @@
1
+ // src/components/button/index.js
2
+ export { default } from './button.js'