mtrl 0.1.3 → 0.2.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.
Files changed (225) hide show
  1. package/README.md +70 -22
  2. package/index.ts +33 -0
  3. package/package.json +14 -5
  4. package/src/components/button/{styles.scss → _styles.scss} +2 -2
  5. package/src/components/button/api.ts +89 -0
  6. package/src/components/button/button.ts +50 -0
  7. package/src/components/button/config.ts +75 -0
  8. package/src/components/button/constants.ts +17 -0
  9. package/src/components/button/index.ts +4 -0
  10. package/src/components/button/types.ts +118 -0
  11. package/src/components/card/{styles.scss → _styles.scss} +79 -7
  12. package/src/components/card/{actions.js → actions.ts} +15 -18
  13. package/src/components/card/{api.js → api.ts} +33 -33
  14. package/src/components/card/card.ts +41 -0
  15. package/src/components/card/config.ts +99 -0
  16. package/src/components/card/{constants.js → constants.ts} +11 -10
  17. package/src/components/card/{content.js → content.ts} +15 -18
  18. package/src/components/card/{features.js → features.ts} +104 -94
  19. package/src/components/card/{header.js → header.ts} +21 -25
  20. package/src/components/card/index.ts +19 -0
  21. package/src/components/card/media.ts +52 -0
  22. package/src/components/card/types.ts +174 -0
  23. package/src/components/checkbox/api.ts +82 -0
  24. package/src/components/checkbox/checkbox.ts +75 -0
  25. package/src/components/checkbox/config.ts +90 -0
  26. package/src/components/checkbox/constants.ts +37 -0
  27. package/src/components/checkbox/index.ts +4 -0
  28. package/src/components/checkbox/types.ts +146 -0
  29. package/src/components/chip/_styles.scss +372 -0
  30. package/src/components/chip/api.ts +115 -0
  31. package/src/components/chip/chip-set.ts +225 -0
  32. package/src/components/chip/chip.ts +82 -0
  33. package/src/components/chip/config.ts +92 -0
  34. package/src/components/chip/constants.ts +38 -0
  35. package/src/components/chip/index.ts +4 -0
  36. package/src/components/chip/types.ts +172 -0
  37. package/src/components/list/api.ts +72 -0
  38. package/src/components/list/config.ts +43 -0
  39. package/src/components/list/{constants.js → constants.ts} +34 -7
  40. package/src/components/list/features.ts +224 -0
  41. package/src/components/list/index.ts +14 -0
  42. package/src/components/list/list-item.ts +120 -0
  43. package/src/components/list/list.ts +37 -0
  44. package/src/components/list/types.ts +179 -0
  45. package/src/components/list/utils.ts +47 -0
  46. package/src/components/menu/api.ts +119 -0
  47. package/src/components/menu/config.ts +54 -0
  48. package/src/components/menu/constants.ts +154 -0
  49. package/src/components/menu/features/items-manager.ts +457 -0
  50. package/src/components/menu/features/keyboard-navigation.ts +133 -0
  51. package/src/components/menu/features/positioning.ts +127 -0
  52. package/src/components/menu/features/{visibility.js → visibility.ts} +66 -64
  53. package/src/components/menu/index.ts +14 -0
  54. package/src/components/menu/menu-item.ts +43 -0
  55. package/src/components/menu/menu.ts +53 -0
  56. package/src/components/menu/types.ts +178 -0
  57. package/src/components/navigation/api.ts +79 -0
  58. package/src/components/navigation/config.ts +61 -0
  59. package/src/components/navigation/{constants.js → constants.ts} +10 -10
  60. package/src/components/navigation/index.ts +14 -0
  61. package/src/components/navigation/nav-item.ts +148 -0
  62. package/src/components/navigation/navigation.ts +50 -0
  63. package/src/components/navigation/types.ts +212 -0
  64. package/src/components/progress/_styles.scss +204 -0
  65. package/src/components/progress/api.ts +179 -0
  66. package/src/components/progress/config.ts +124 -0
  67. package/src/components/progress/constants.ts +43 -0
  68. package/src/components/progress/index.ts +5 -0
  69. package/src/components/progress/progress.ts +163 -0
  70. package/src/components/progress/types.ts +102 -0
  71. package/src/components/snackbar/api.ts +162 -0
  72. package/src/components/snackbar/config.ts +62 -0
  73. package/src/components/snackbar/{constants.js → constants.ts} +21 -4
  74. package/src/components/snackbar/features.ts +76 -0
  75. package/src/components/snackbar/index.ts +4 -0
  76. package/src/components/snackbar/position.ts +71 -0
  77. package/src/components/snackbar/queue.ts +76 -0
  78. package/src/components/snackbar/snackbar.ts +60 -0
  79. package/src/components/snackbar/types.ts +58 -0
  80. package/src/components/switch/api.ts +77 -0
  81. package/src/components/switch/config.ts +74 -0
  82. package/src/components/switch/{constants.js → constants.ts} +5 -5
  83. package/src/components/switch/index.ts +4 -0
  84. package/src/components/switch/switch.ts +52 -0
  85. package/src/components/switch/types.ts +142 -0
  86. package/src/components/textfield/api.ts +72 -0
  87. package/src/components/textfield/config.ts +54 -0
  88. package/src/components/textfield/{constants.js → constants.ts} +38 -5
  89. package/src/components/textfield/index.ts +4 -0
  90. package/src/components/textfield/textfield.ts +50 -0
  91. package/src/components/textfield/types.ts +139 -0
  92. package/src/core/compose/base.ts +43 -0
  93. package/src/core/compose/component.ts +255 -0
  94. package/src/core/compose/features/checkable.ts +155 -0
  95. package/src/core/compose/features/disabled.ts +116 -0
  96. package/src/core/compose/features/events.ts +65 -0
  97. package/src/core/compose/features/icon.ts +67 -0
  98. package/src/core/compose/features/index.ts +35 -0
  99. package/src/core/compose/features/input.ts +174 -0
  100. package/src/core/compose/features/lifecycle.ts +139 -0
  101. package/src/core/compose/features/position.ts +94 -0
  102. package/src/core/compose/features/ripple.ts +55 -0
  103. package/src/core/compose/features/size.ts +29 -0
  104. package/src/core/compose/features/style.ts +31 -0
  105. package/src/core/compose/features/text.ts +44 -0
  106. package/src/core/compose/features/textinput.ts +225 -0
  107. package/src/core/compose/features/textlabel.ts +92 -0
  108. package/src/core/compose/features/track.ts +84 -0
  109. package/src/core/compose/features/variant.ts +29 -0
  110. package/src/core/compose/features/withEvents.ts +137 -0
  111. package/src/core/compose/index.ts +54 -0
  112. package/src/core/compose/{pipe.js → pipe.ts} +16 -11
  113. package/src/core/config/component-config.ts +136 -0
  114. package/src/core/config.ts +211 -0
  115. package/src/core/dom/{attributes.js → attributes.ts} +11 -11
  116. package/src/core/dom/classes.ts +60 -0
  117. package/src/core/dom/create.ts +251 -0
  118. package/src/core/dom/events.ts +209 -0
  119. package/src/core/dom/index.ts +10 -0
  120. package/src/core/dom/utils.ts +97 -0
  121. package/src/core/index.ts +111 -0
  122. package/src/core/state/disabled.ts +81 -0
  123. package/src/core/state/emitter.ts +94 -0
  124. package/src/core/state/events.ts +88 -0
  125. package/src/core/state/index.ts +16 -0
  126. package/src/core/state/lifecycle.ts +131 -0
  127. package/src/core/state/store.ts +197 -0
  128. package/src/core/utils/index.ts +45 -0
  129. package/src/core/utils/{mobile.js → mobile.ts} +48 -24
  130. package/src/core/utils/object.ts +41 -0
  131. package/src/core/utils/validate.ts +234 -0
  132. package/src/{index.js → index.ts} +3 -2
  133. package/index.js +0 -11
  134. package/src/components/button/api.js +0 -54
  135. package/src/components/button/button.js +0 -81
  136. package/src/components/button/config.js +0 -10
  137. package/src/components/button/constants.js +0 -63
  138. package/src/components/button/index.js +0 -2
  139. package/src/components/card/card.js +0 -102
  140. package/src/components/card/config.js +0 -16
  141. package/src/components/card/index.js +0 -7
  142. package/src/components/card/media.js +0 -56
  143. package/src/components/checkbox/api.js +0 -45
  144. package/src/components/checkbox/checkbox.js +0 -96
  145. package/src/components/checkbox/constants.js +0 -88
  146. package/src/components/checkbox/index.js +0 -2
  147. package/src/components/container/api.js +0 -42
  148. package/src/components/container/container.js +0 -45
  149. package/src/components/container/index.js +0 -2
  150. package/src/components/container/styles.scss +0 -66
  151. package/src/components/list/index.js +0 -2
  152. package/src/components/list/list-item.js +0 -147
  153. package/src/components/list/list.js +0 -267
  154. package/src/components/menu/api.js +0 -117
  155. package/src/components/menu/constants.js +0 -42
  156. package/src/components/menu/features/items-manager.js +0 -375
  157. package/src/components/menu/features/keyboard-navigation.js +0 -129
  158. package/src/components/menu/features/positioning.js +0 -125
  159. package/src/components/menu/index.js +0 -2
  160. package/src/components/menu/menu-item.js +0 -41
  161. package/src/components/menu/menu.js +0 -54
  162. package/src/components/navigation/api.js +0 -43
  163. package/src/components/navigation/index.js +0 -2
  164. package/src/components/navigation/nav-item.js +0 -137
  165. package/src/components/navigation/navigation.js +0 -55
  166. package/src/components/snackbar/api.js +0 -125
  167. package/src/components/snackbar/features.js +0 -69
  168. package/src/components/snackbar/index.js +0 -2
  169. package/src/components/snackbar/position.js +0 -63
  170. package/src/components/snackbar/queue.js +0 -74
  171. package/src/components/snackbar/snackbar.js +0 -70
  172. package/src/components/switch/api.js +0 -44
  173. package/src/components/switch/index.js +0 -2
  174. package/src/components/switch/switch.js +0 -71
  175. package/src/components/textfield/api.js +0 -49
  176. package/src/components/textfield/index.js +0 -2
  177. package/src/components/textfield/textfield.js +0 -68
  178. package/src/core/build/_ripple.scss +0 -79
  179. package/src/core/build/constants.js +0 -51
  180. package/src/core/build/icon.js +0 -78
  181. package/src/core/build/ripple.js +0 -159
  182. package/src/core/build/text.js +0 -54
  183. package/src/core/compose/base.js +0 -8
  184. package/src/core/compose/component.js +0 -225
  185. package/src/core/compose/features/checkable.js +0 -114
  186. package/src/core/compose/features/disabled.js +0 -64
  187. package/src/core/compose/features/events.js +0 -48
  188. package/src/core/compose/features/icon.js +0 -33
  189. package/src/core/compose/features/index.js +0 -20
  190. package/src/core/compose/features/input.js +0 -100
  191. package/src/core/compose/features/lifecycle.js +0 -69
  192. package/src/core/compose/features/position.js +0 -60
  193. package/src/core/compose/features/ripple.js +0 -32
  194. package/src/core/compose/features/size.js +0 -9
  195. package/src/core/compose/features/style.js +0 -12
  196. package/src/core/compose/features/text.js +0 -17
  197. package/src/core/compose/features/textinput.js +0 -114
  198. package/src/core/compose/features/textlabel.js +0 -28
  199. package/src/core/compose/features/track.js +0 -49
  200. package/src/core/compose/features/variant.js +0 -9
  201. package/src/core/compose/features/withEvents.js +0 -67
  202. package/src/core/compose/index.js +0 -16
  203. package/src/core/config.js +0 -140
  204. package/src/core/dom/classes.js +0 -70
  205. package/src/core/dom/create.js +0 -132
  206. package/src/core/dom/events.js +0 -175
  207. package/src/core/dom/index.js +0 -5
  208. package/src/core/dom/utils.js +0 -22
  209. package/src/core/index.js +0 -23
  210. package/src/core/state/disabled.js +0 -51
  211. package/src/core/state/emitter.js +0 -63
  212. package/src/core/state/events.js +0 -29
  213. package/src/core/state/index.js +0 -6
  214. package/src/core/state/lifecycle.js +0 -64
  215. package/src/core/state/store.js +0 -112
  216. package/src/core/utils/index.js +0 -39
  217. package/src/core/utils/object.js +0 -22
  218. package/src/core/utils/validate.js +0 -37
  219. /package/src/components/checkbox/{styles.scss → _styles.scss} +0 -0
  220. /package/src/components/list/{styles.scss → _styles.scss} +0 -0
  221. /package/src/components/menu/{styles.scss → _styles.scss} +0 -0
  222. /package/src/components/navigation/{styles.scss → _styles.scss} +0 -0
  223. /package/src/components/snackbar/{styles.scss → _styles.scss} +0 -0
  224. /package/src/components/switch/{styles.scss → _styles.scss} +0 -0
  225. /package/src/components/textfield/{styles.scss → _styles.scss} +0 -0
@@ -1,132 +0,0 @@
1
- // src/core/dom/create.js
2
- /**
3
- * @module core/dom
4
- * @description DOM manipulation utilities
5
- */
6
-
7
- import { setAttributes } from './attributes'
8
- import { normalizeClasses } from '../utils'
9
-
10
- /**
11
- * Creates a DOM element with the specified options
12
- * @memberof module:core/dom
13
- * @param {Object} options - Element creation options
14
- * @param {string} [options.tag='div'] - HTML tag name
15
- * @param {HTMLElement} [options.container] - Container to append element to
16
- * @param {string} [options.html] - Inner HTML content
17
- * @param {string} [options.text] - Text content
18
- * @param {string} [options.id] - Element ID
19
- * @param {Object} [options.data] - Dataset attributes
20
- * @param {string|string[]} [options.className] - CSS classes
21
- * @param {Object} [options.attrs] - HTML attributes
22
- * @param {Object} [options.forwardEvents] - Events to forward when component has emit method
23
- * @param {Function} [options.onCreate] - Callback after element creation
24
- * @returns {HTMLElement} Created element
25
- */
26
- export const createElement = (options = {}) => {
27
- const {
28
- tag = 'div',
29
- container = null,
30
- html = '',
31
- text = '',
32
- id = '',
33
- data = {},
34
- className,
35
- attrs = {},
36
- forwardEvents = {},
37
- onCreate,
38
- context,
39
- ...rest
40
- } = options
41
-
42
- const element = document.createElement(tag)
43
-
44
- // Handle content
45
- if (html) element.innerHTML = html
46
- if (text) element.textContent = text
47
- if (id) element.id = id
48
-
49
- // Handle classes
50
- if (className) {
51
- const normalizedClasses = normalizeClasses(className)
52
- if (normalizedClasses.length) {
53
- element.classList.add(...normalizedClasses)
54
- }
55
- }
56
-
57
- // Handle data attributes
58
- Object.entries(data).forEach(([key, value]) => {
59
- element.dataset[key] = value
60
- })
61
-
62
- // Handle all other attributes
63
- const allAttrs = { ...attrs, ...rest }
64
- Object.entries(allAttrs).forEach(([key, value]) => {
65
- if (value != null) element.setAttribute(key, value)
66
- })
67
-
68
- // Handle event forwarding if context has emit method
69
- if (context?.emit && forwardEvents) {
70
- Object.entries(forwardEvents).forEach(([nativeEvent, eventConfig]) => {
71
- const shouldForward = typeof eventConfig === 'function'
72
- ? eventConfig
73
- : () => true
74
-
75
- element.addEventListener(nativeEvent, (event) => {
76
- if (shouldForward({ ...context, element }, event)) {
77
- context.emit(nativeEvent, { event })
78
- }
79
- })
80
- })
81
- }
82
-
83
- // Append to container if provided
84
- if (container) {
85
- container.appendChild(element)
86
- }
87
-
88
- if (typeof onCreate === 'function') {
89
- onCreate(element, context)
90
- }
91
-
92
- return element
93
- }
94
-
95
- /**
96
- * Higher-order function to add attributes to an element
97
- * @param {Object} attrs - Attributes to add
98
- * @returns {Function} Element transformer
99
- */
100
- export const withAttributes = (attrs) => (element) => {
101
- setAttributes(element, attrs)
102
- return element
103
- }
104
-
105
- /**
106
- * Higher-order function to add classes to an element
107
- * @memberof module:core/dom
108
- * @param {...string} classes - Classes to add
109
- * @returns {Function} Element transformer
110
- */
111
- export const withClasses = (...classes) => (element) => {
112
- const normalizedClasses = normalizeClasses(...classes)
113
- if (normalizedClasses.length) {
114
- element.classList.add(...normalizedClasses)
115
- }
116
- return element
117
- }
118
-
119
- /**
120
- * Higher-order function to add content to an element
121
- * @memberof module:core/dom
122
- * @param {Node|string} content - Content to add
123
- * @returns {Function} Element transformer
124
- */
125
- export const withContent = (content) => (element) => {
126
- if (content instanceof Node) {
127
- element.appendChild(content)
128
- } else {
129
- element.textContent = content
130
- }
131
- return element
132
- }
@@ -1,175 +0,0 @@
1
- // src/core/state/events.js
2
- /**
3
- * @module core/dom
4
- * @description DOM manipulation utilities
5
- */
6
-
7
- /**
8
- * Creates an event manager to handle DOM events with enhanced functionality.
9
- * Provides a robust interface for managing event listeners with error handling,
10
- * cleanup, and lifecycle management.
11
- *
12
- * @param {HTMLElement} element - DOM element to attach events to
13
- * @returns {Object} Event manager interface with the following methods:
14
- *
15
- * @property {Function} on - Adds an event listener with options
16
- * @property {Function} off - Removes an event listener
17
- * @property {Function} pause - Temporarily disables all event listeners
18
- * @property {Function} resume - Re-enables all event listeners
19
- * @property {Function} destroy - Removes all event listeners and cleans up
20
- * @property {Function} getHandlers - Gets all active handlers
21
- * @property {Function} hasHandler - Checks if a specific handler exists
22
- *
23
- * @example
24
- * const manager = createEventManager(myElement);
25
- *
26
- * // Add a listener
27
- * manager.on('click', (e) => console.log('clicked'), { capture: true });
28
- *
29
- * // Remove a listener
30
- * manager.off('click', myHandler);
31
- *
32
- * // Pause all events
33
- * manager.pause();
34
- *
35
- * // Resume all events
36
- * manager.resume();
37
- *
38
- * // Cleanup
39
- * manager.destroy();
40
- */
41
- export const createEventManager = (element) => {
42
- // Store handlers with their metadata
43
- const handlers = new Map()
44
-
45
- /**
46
- * Private helper to create a unique handler identifier
47
- * @memberof module:core/dom
48
- * @private
49
- * @param {string} event - Event name
50
- * @param {Function} handler - Event handler
51
- * @returns {string} Unique identifier
52
- */
53
- const createHandlerId = (event, handler) =>
54
- `${event}_${handler.toString()}`
55
-
56
- /**
57
- * Wraps an event handler with error boundary and logging
58
- * @memberof module:core/dom
59
- * @private
60
- * @param {Function} handler - Original event handler
61
- * @param {string} event - Event name for error context
62
- * @returns {Function} Enhanced handler with error boundary
63
- */
64
- const enhanceHandler = (handler, event) => (e) => {
65
- try {
66
- handler(e)
67
- } catch (error) {
68
- console.error(`Error in ${event} handler:`, error)
69
- }
70
- }
71
-
72
- /**
73
- * Safely removes event listener
74
- * @memberof module:core/dom
75
- * @param {string} event - Event name
76
- * @param {Function} handler - Event handler
77
- */
78
- const safeRemoveListener = (event, handler) => {
79
- try {
80
- element.removeEventListener(event, handler)
81
- } catch (error) {
82
- console.warn(`Failed to remove ${event} listener:`, error)
83
- }
84
- }
85
-
86
- return {
87
- /**
88
- * Adds an event listener with options
89
- * @memberof module:core/dom
90
- * @param {string} event - Event name
91
- * @param {Function} handler - Event handler
92
- * @param {Object} [options] - addEventListener options
93
- */
94
- on (event, handler, options = {}) {
95
- const enhanced = enhanceHandler(handler, event)
96
- const id = createHandlerId(event, handler)
97
-
98
- handlers.set(id, {
99
- original: handler,
100
- enhanced,
101
- event,
102
- options
103
- })
104
-
105
- element.addEventListener(event, enhanced, options)
106
- return this
107
- },
108
-
109
- /**
110
- * Removes an event listener
111
- * @memberof module:core/dom
112
- * @param {string} event - Event name
113
- * @param {Function} handler - Event handler
114
- */
115
- off (event, handler) {
116
- const id = createHandlerId(event, handler)
117
- const stored = handlers.get(id)
118
-
119
- if (stored) {
120
- safeRemoveListener(event, stored.enhanced)
121
- handlers.delete(id)
122
- }
123
- return this
124
- },
125
-
126
- /**
127
- * Temporarily disables all event listeners
128
- */
129
- pause () {
130
- handlers.forEach(({ enhanced, event, options }) => {
131
- safeRemoveListener(event, enhanced)
132
- })
133
- return this
134
- },
135
-
136
- /**
137
- * Re-enables all event listeners
138
- */
139
- resume () {
140
- handlers.forEach(({ enhanced, event, options }) => {
141
- element.addEventListener(event, enhanced, options)
142
- })
143
- return this
144
- },
145
-
146
- /**
147
- * Removes all event listeners and cleans up
148
- */
149
- destroy () {
150
- handlers.forEach(({ enhanced, event }) => {
151
- safeRemoveListener(event, enhanced)
152
- })
153
- handlers.clear()
154
- },
155
-
156
- /**
157
- * Gets all active handlers
158
- * @returns {Map} Map of active handlers
159
- */
160
- getHandlers () {
161
- return new Map(handlers)
162
- },
163
-
164
- /**
165
- * Checks if a specific handler exists
166
- * @param {string} event - Event name
167
- * @param {Function} handler - Event handler
168
- * @returns {boolean} Whether handler exists
169
- */
170
- hasHandler (event, handler) {
171
- const id = createHandlerId(event, handler)
172
- return handlers.has(id)
173
- }
174
- }
175
- }
@@ -1,5 +0,0 @@
1
- // src/core/dom/index.js
2
- export { createElement } from './create'
3
- export { setAttributes, removeAttributes } from './attributes'
4
- export { addClass, removeClass } from './classes'
5
- // export { attachEvents } from './events'
@@ -1,22 +0,0 @@
1
- /**
2
- * Normalizes class names input by handling various formats:
3
- * - String with space-separated classes
4
- * - Array of strings
5
- * - Mixed array of strings and space-separated classes
6
- * @param {...(string|string[])} classes - Classes to normalize
7
- * @returns {string[]} Array of unique, non-empty class names
8
- */
9
- export const normalizeClasses = (...classes) => {
10
- return [...new Set(
11
- classes
12
- .flat()
13
- .reduce((acc, cls) => {
14
- if (typeof cls === 'string') {
15
- // Split space-separated classes and add them individually
16
- acc.push(...cls.split(/\s+/))
17
- }
18
- return acc
19
- }, [])
20
- .filter(Boolean) // Remove empty strings
21
- )]
22
- }
package/src/core/index.js DELETED
@@ -1,23 +0,0 @@
1
- // src/core/index.js
2
- /**
3
- * @module core
4
- * @description Core utilities and building blocks for the component system
5
- */
6
- // Build
7
- export { createText } from './build/text'
8
- export { createIcon } from './build/icon'
9
-
10
- // Classes management
11
- export { addClass, removeClass } from './dom/classes'
12
-
13
- // State Management
14
- export { createDisabled } from './state/disabled'
15
- export { createEventManager } from './state/events'
16
- export { createLifecycle } from './state/lifecycle'
17
- export { createEmitter } from './state/emitter'
18
-
19
- // Composition Utilities
20
- export { pipe, compose, transform } from './compose'
21
-
22
- // General Utilities
23
- export { classNames } from './utils'
@@ -1,51 +0,0 @@
1
- // src/core/state/disabled.js
2
-
3
- /**
4
- * Creates a controller for managing the disabled state of an element
5
- * @param {HTMLElement} element - The element to control
6
- * @returns {Object} Disabled state controller
7
- */
8
- export const createDisabled = (element) => {
9
- return {
10
- /**
11
- * Enables the element
12
- * @returns {Object} The controller instance for chaining
13
- */
14
- enable () {
15
- element.disabled = false
16
- element.removeAttribute('disabled')
17
- return this
18
- },
19
-
20
- /**
21
- * Disables the element
22
- * @returns {Object} The controller instance for chaining
23
- */
24
- disable () {
25
- element.disabled = true
26
- element.setAttribute('disabled', 'true')
27
- return this
28
- },
29
-
30
- /**
31
- * Toggles the disabled state
32
- * @returns {Object} The controller instance for chaining
33
- */
34
- toggle () {
35
- if (element.disabled) {
36
- this.enable()
37
- } else {
38
- this.disable()
39
- }
40
- return this
41
- },
42
-
43
- /**
44
- * Checks if the element is disabled
45
- * @returns {boolean} True if the element is disabled
46
- */
47
- isDisabled () {
48
- return element.disabled === true
49
- }
50
- }
51
- }
@@ -1,63 +0,0 @@
1
- // src/core/state/emitter.js
2
- /**
3
- * @module core/state
4
- */
5
-
6
- /**
7
- * Creates an event emitter with subscription management
8
- * @memberof module:core/state
9
- * @function createEmitter
10
- * @returns {Object} Event emitter interface
11
- * @property {Function} on - Subscribe to an event
12
- * @property {Function} off - Unsubscribe from an event
13
- * @property {Function} emit - Emit an event
14
- * @property {Function} clear - Clear all subscriptions
15
- * @example
16
- * const emitter = createEmitter()
17
- * const unsubscribe = emitter.on('change', (data) => console.log(data))
18
- * emitter.emit('change', { value: 42 })
19
- * unsubscribe()
20
- */
21
- export const createEmitter = () => {
22
- const events = new Map()
23
-
24
- return {
25
- /**
26
- * Subscribe to an event
27
- * @param {string} event - Event name
28
- * @param {Function} callback - Event handler
29
- * @returns {Function} Unsubscribe function
30
- */
31
- on: (event, callback) => {
32
- const callbacks = events.get(event) || []
33
- events.set(event, [...callbacks, callback])
34
-
35
- return () => {
36
- const callbacks = events.get(event) || []
37
- events.set(event, callbacks.filter(cb => cb !== callback))
38
- }
39
- },
40
-
41
- off (event, callback) {
42
- const callbacks = events.get(event) || []
43
- events.set(event, callbacks.filter(cb => cb !== callback))
44
- },
45
-
46
- /**
47
- * Emit an event
48
- * @param {string} event - Event name
49
- * @param {...any} args - Event arguments
50
- */
51
- emit: (event, ...args) => {
52
- const callbacks = events.get(event) || []
53
- callbacks.forEach(cb => cb(...args))
54
- },
55
-
56
- /**
57
- * Clear all event listeners
58
- */
59
- clear: () => {
60
- events.clear()
61
- }
62
- }
63
- }
@@ -1,29 +0,0 @@
1
- // src/core/state/events.js
2
- export const createEventManager = (element) => {
3
- const handlers = new Map()
4
-
5
- return {
6
- on (event, handler) {
7
- element.addEventListener(event, handler)
8
- handlers.set(handler, event)
9
- return this
10
- },
11
-
12
- off (event, handler) {
13
- element.removeEventListener(event, handler)
14
- handlers.delete(handler)
15
- return this
16
- },
17
-
18
- destroy () {
19
- handlers.forEach((event, handler) => {
20
- element.removeEventListener(event, handler)
21
- })
22
- handlers.clear()
23
- },
24
-
25
- getHandlers () {
26
- return handlers
27
- }
28
- }
29
- }
@@ -1,6 +0,0 @@
1
- // src/core/state/index.js
2
- export { createEmitter } from './state/emitter'
3
- export { createStore } from './store'
4
- export { createLifecycle } from './lifecycle'
5
- export { createDisabled } from './disabled'
6
- export { createEventManager } from './events'
@@ -1,64 +0,0 @@
1
- // src/core/state/lifecycle.js
2
- import { createEmitter } from './emitter'
3
-
4
- export const createLifecycle = (element, managers = {}) => {
5
- let mounted = false
6
- const emitter = createEmitter()
7
-
8
- return {
9
- // Mount/Unmount state management
10
- onMount: (handler) => emitter.on('mount', handler),
11
- onUnmount: (handler) => emitter.on('unmount', handler),
12
-
13
- mount: () => {
14
- if (!mounted) {
15
- mounted = true
16
- emitter.emit('mount')
17
- }
18
- },
19
-
20
- unmount: () => {
21
- if (mounted) {
22
- mounted = false
23
- emitter.emit('unmount')
24
- emitter.clear()
25
- }
26
- },
27
-
28
- isMounted: () => mounted,
29
-
30
- // Cleanup and destruction
31
- destroy() {
32
- // First trigger unmount
33
- if (mounted) {
34
- this.unmount()
35
- }
36
-
37
- // Clean up all event listeners
38
- if (managers.events) {
39
- managers.events.destroy()
40
- }
41
-
42
- // Clean up text element
43
- if (managers.text) {
44
- const textElement = managers.text.getElement()
45
- if (textElement) {
46
- textElement.remove()
47
- }
48
- }
49
-
50
- // Clean up icon element
51
- if (managers.icon) {
52
- const iconElement = managers.icon.getElement()
53
- if (iconElement) {
54
- iconElement.remove()
55
- }
56
- }
57
-
58
- // Remove the main element
59
- if (element) {
60
- element.remove()
61
- }
62
- }
63
- }
64
- }
@@ -1,112 +0,0 @@
1
- // src/core/state/store.js
2
- import { createEmitter } from './emitter'
3
-
4
- /**
5
- * Creates a state store with support for derived state and middleware
6
- * @template T
7
- * @param {T} initialState - Initial state object
8
- * @param {Object} [options] - Store options
9
- * @param {Function[]} [options.middleware] - Middleware functions
10
- * @returns {Object} State store interface
11
- */
12
- export const createStore = (initialState = {}, options = {}) => {
13
- let state = { ...initialState }
14
- const emitter = createEmitter()
15
- const derivedStates = new Map()
16
- const middleware = options.middleware || []
17
-
18
- const notifyListeners = (newState, oldState) => {
19
- emitter.emit('change', newState, oldState)
20
- }
21
-
22
- const applyMiddleware = (newState, oldState) => {
23
- return middleware.reduce((state, fn) => fn(state, oldState), newState)
24
- }
25
-
26
- return {
27
- /**
28
- * Get current state including derived values
29
- * @returns {T} Current state
30
- */
31
- getState: () => {
32
- const derivedValues = {}
33
- derivedStates.forEach((compute, key) => {
34
- derivedValues[key] = compute(state)
35
- })
36
- return { ...state, ...derivedValues }
37
- },
38
-
39
- /**
40
- * Update state
41
- * @param {Object|Function} update - State update or updater function
42
- */
43
- setState: (update) => {
44
- const oldState = { ...state }
45
- const newState = typeof update === 'function'
46
- ? update(state)
47
- : { ...state, ...update }
48
-
49
- state = applyMiddleware(newState, oldState)
50
- notifyListeners(state, oldState)
51
- },
52
-
53
- /**
54
- * Subscribe to state changes
55
- * @param {Function} listener - Change listener
56
- * @returns {Function} Unsubscribe function
57
- */
58
- subscribe: (listener) => emitter.on('change', listener),
59
-
60
- /**
61
- * Create a derived state value
62
- * @param {string} key - Derived state key
63
- * @param {Function} computation - Function to compute derived value
64
- * @returns {Function} Function to remove derived state
65
- */
66
- derive: (key, computation) => {
67
- derivedStates.set(key, computation)
68
- return () => {
69
- derivedStates.delete(key)
70
- }
71
- },
72
-
73
- /**
74
- * Select a specific slice of state
75
- * @param {Function} selector - State selector function
76
- * @returns {any} Selected state
77
- */
78
- select: (selector) => selector(state),
79
-
80
- /**
81
- * Reset state to initial values
82
- */
83
- reset: () => {
84
- state = { ...initialState }
85
- notifyListeners(state, null)
86
- }
87
- }
88
- }
89
-
90
- // Example middleware
91
- export const loggingMiddleware = (newState, oldState) => {
92
- console.log('State change:', {
93
- old: oldState,
94
- new: newState,
95
- diff: Object.keys(newState).reduce((acc, key) => {
96
- if (newState[key] !== oldState[key]) {
97
- acc[key] = { from: oldState[key], to: newState[key] }
98
- }
99
- return acc
100
- }, {})
101
- })
102
- return newState
103
- }
104
-
105
- // Example derived state
106
- export const deriveFiltered = (predicate) => (state) =>
107
- Object.keys(state).reduce((acc, key) => {
108
- if (predicate(state[key], key)) {
109
- acc[key] = state[key]
110
- }
111
- return acc
112
- }, {})