mtrl 0.2.5 → 0.2.7

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 (196) hide show
  1. package/index.ts +18 -0
  2. package/package.json +1 -1
  3. package/src/components/badge/_styles.scss +123 -115
  4. package/src/components/badge/api.ts +57 -59
  5. package/src/components/badge/badge.ts +16 -2
  6. package/src/components/badge/config.ts +65 -11
  7. package/src/components/badge/constants.ts +22 -12
  8. package/src/components/badge/features.ts +44 -40
  9. package/src/components/badge/types.ts +42 -30
  10. package/src/components/bottom-app-bar/_styles.scss +103 -0
  11. package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
  12. package/src/components/bottom-app-bar/config.ts +73 -0
  13. package/src/components/bottom-app-bar/index.ts +11 -0
  14. package/src/components/bottom-app-bar/types.ts +108 -0
  15. package/src/components/button/_styles.scss +0 -66
  16. package/src/components/button/api.ts +5 -0
  17. package/src/components/button/button.ts +0 -2
  18. package/src/components/button/config.ts +5 -0
  19. package/src/components/button/constants.ts +0 -6
  20. package/src/components/button/index.ts +2 -2
  21. package/src/components/button/types.ts +7 -7
  22. package/src/components/card/_styles.scss +67 -25
  23. package/src/components/card/api.ts +54 -3
  24. package/src/components/card/card.ts +25 -6
  25. package/src/components/card/config.ts +189 -22
  26. package/src/components/card/constants.ts +20 -19
  27. package/src/components/card/content.ts +299 -2
  28. package/src/components/card/features.ts +158 -4
  29. package/src/components/card/index.ts +31 -9
  30. package/src/components/card/types.ts +166 -15
  31. package/src/components/checkbox/_styles.scss +0 -2
  32. package/src/components/chip/chip.ts +1 -9
  33. package/src/components/chip/constants.ts +0 -10
  34. package/src/components/chip/index.ts +1 -1
  35. package/src/components/chip/types.ts +1 -4
  36. package/src/components/datepicker/_styles.scss +358 -0
  37. package/src/components/datepicker/api.ts +272 -0
  38. package/src/components/datepicker/config.ts +144 -0
  39. package/src/components/datepicker/constants.ts +98 -0
  40. package/src/components/datepicker/datepicker.ts +346 -0
  41. package/src/components/datepicker/index.ts +9 -0
  42. package/src/components/datepicker/render.ts +452 -0
  43. package/src/components/datepicker/types.ts +268 -0
  44. package/src/components/datepicker/utils.ts +290 -0
  45. package/src/components/dialog/_styles.scss +174 -128
  46. package/src/components/dialog/api.ts +48 -13
  47. package/src/components/dialog/config.ts +9 -5
  48. package/src/components/dialog/dialog.ts +6 -3
  49. package/src/components/dialog/features.ts +290 -130
  50. package/src/components/dialog/types.ts +7 -4
  51. package/src/components/divider/_styles.scss +57 -0
  52. package/src/components/divider/config.ts +81 -0
  53. package/src/components/divider/divider.ts +37 -0
  54. package/src/components/divider/features.ts +207 -0
  55. package/src/components/divider/index.ts +5 -0
  56. package/src/components/divider/types.ts +55 -0
  57. package/src/components/extended-fab/_styles.scss +267 -0
  58. package/src/components/extended-fab/api.ts +141 -0
  59. package/src/components/extended-fab/config.ts +108 -0
  60. package/src/components/extended-fab/constants.ts +36 -0
  61. package/src/components/extended-fab/extended-fab.ts +125 -0
  62. package/src/components/extended-fab/index.ts +4 -0
  63. package/src/components/extended-fab/types.ts +287 -0
  64. package/src/components/fab/_styles.scss +225 -0
  65. package/src/components/fab/api.ts +97 -0
  66. package/src/components/fab/config.ts +94 -0
  67. package/src/components/fab/constants.ts +41 -0
  68. package/src/components/fab/fab.ts +67 -0
  69. package/src/components/fab/index.ts +4 -0
  70. package/src/components/fab/types.ts +234 -0
  71. package/src/components/navigation/_styles.scss +1 -0
  72. package/src/components/navigation/api.ts +78 -50
  73. package/src/components/navigation/features/items.ts +280 -0
  74. package/src/components/navigation/nav-item.ts +72 -23
  75. package/src/components/navigation/navigation.ts +54 -2
  76. package/src/components/navigation/types.ts +210 -188
  77. package/src/components/progress/_styles.scss +0 -65
  78. package/src/components/progress/config.ts +1 -2
  79. package/src/components/progress/constants.ts +0 -14
  80. package/src/components/progress/index.ts +1 -1
  81. package/src/components/progress/progress.ts +1 -4
  82. package/src/components/progress/types.ts +1 -4
  83. package/src/components/radios/_styles.scss +0 -45
  84. package/src/components/radios/api.ts +85 -60
  85. package/src/components/radios/config.ts +1 -2
  86. package/src/components/radios/constants.ts +0 -9
  87. package/src/components/radios/index.ts +1 -1
  88. package/src/components/radios/radio.ts +34 -11
  89. package/src/components/radios/radios.ts +2 -1
  90. package/src/components/radios/types.ts +1 -7
  91. package/src/components/search/_styles.scss +306 -0
  92. package/src/components/search/api.ts +203 -0
  93. package/src/components/search/config.ts +87 -0
  94. package/src/components/search/constants.ts +21 -0
  95. package/src/components/search/features/index.ts +4 -0
  96. package/src/components/search/features/search.ts +718 -0
  97. package/src/components/search/features/states.ts +165 -0
  98. package/src/components/search/features/structure.ts +198 -0
  99. package/src/components/search/index.ts +10 -0
  100. package/src/components/search/search.ts +52 -0
  101. package/src/components/search/types.ts +163 -0
  102. package/src/components/segmented-button/_styles.scss +117 -0
  103. package/src/components/segmented-button/config.ts +67 -0
  104. package/src/components/segmented-button/constants.ts +42 -0
  105. package/src/components/segmented-button/index.ts +4 -0
  106. package/src/components/segmented-button/segment.ts +155 -0
  107. package/src/components/segmented-button/segmented-button.ts +250 -0
  108. package/src/components/segmented-button/types.ts +219 -0
  109. package/src/components/slider/_styles.scss +221 -168
  110. package/src/components/slider/accessibility.md +59 -0
  111. package/src/components/slider/api.ts +41 -120
  112. package/src/components/slider/config.ts +51 -49
  113. package/src/components/slider/features/handlers.ts +495 -0
  114. package/src/components/slider/features/index.ts +1 -2
  115. package/src/components/slider/features/slider.ts +66 -84
  116. package/src/components/slider/features/states.ts +195 -0
  117. package/src/components/slider/features/structure.ts +141 -184
  118. package/src/components/slider/features/ui.ts +150 -201
  119. package/src/components/slider/index.ts +2 -11
  120. package/src/components/slider/slider.ts +9 -12
  121. package/src/components/slider/types.ts +39 -24
  122. package/src/components/switch/_styles.scss +0 -2
  123. package/src/components/tabs/_styles.scss +346 -154
  124. package/src/components/tabs/api.ts +178 -400
  125. package/src/components/tabs/config.ts +46 -52
  126. package/src/components/tabs/constants.ts +85 -8
  127. package/src/components/tabs/features.ts +403 -0
  128. package/src/components/tabs/index.ts +60 -3
  129. package/src/components/tabs/indicator.ts +285 -0
  130. package/src/components/tabs/responsive.ts +144 -0
  131. package/src/components/tabs/scroll-indicators.ts +149 -0
  132. package/src/components/tabs/state.ts +186 -0
  133. package/src/components/tabs/tab-api.ts +258 -0
  134. package/src/components/tabs/tab.ts +255 -0
  135. package/src/components/tabs/tabs.ts +50 -31
  136. package/src/components/tabs/types.ts +332 -128
  137. package/src/components/tabs/utils.ts +107 -0
  138. package/src/components/textfield/_styles.scss +0 -98
  139. package/src/components/textfield/config.ts +2 -3
  140. package/src/components/textfield/constants.ts +0 -14
  141. package/src/components/textfield/index.ts +2 -2
  142. package/src/components/textfield/textfield.ts +0 -2
  143. package/src/components/textfield/types.ts +1 -4
  144. package/src/components/timepicker/README.md +277 -0
  145. package/src/components/timepicker/_styles.scss +451 -0
  146. package/src/components/timepicker/api.ts +632 -0
  147. package/src/components/timepicker/clockdial.ts +482 -0
  148. package/src/components/timepicker/config.ts +130 -0
  149. package/src/components/timepicker/constants.ts +138 -0
  150. package/src/components/timepicker/index.ts +8 -0
  151. package/src/components/timepicker/render.ts +613 -0
  152. package/src/components/timepicker/timepicker.ts +117 -0
  153. package/src/components/timepicker/types.ts +336 -0
  154. package/src/components/timepicker/utils.ts +241 -0
  155. package/src/components/top-app-bar/_styles.scss +225 -0
  156. package/src/components/top-app-bar/config.ts +83 -0
  157. package/src/components/top-app-bar/index.ts +11 -0
  158. package/src/components/top-app-bar/top-app-bar.ts +316 -0
  159. package/src/components/top-app-bar/types.ts +140 -0
  160. package/src/core/build/_ripple.scss +6 -6
  161. package/src/core/build/ripple.ts +72 -95
  162. package/src/core/compose/component.ts +1 -1
  163. package/src/core/compose/features/badge.ts +79 -0
  164. package/src/core/compose/features/icon.ts +3 -1
  165. package/src/core/compose/features/index.ts +3 -1
  166. package/src/core/compose/features/ripple.ts +4 -1
  167. package/src/core/compose/features/textlabel.ts +26 -2
  168. package/src/core/dom/create.ts +5 -0
  169. package/src/index.ts +9 -0
  170. package/src/styles/abstract/_theme.scss +115 -3
  171. package/src/styles/themes/_autumn.scss +21 -0
  172. package/src/styles/themes/_base-theme.scss +61 -0
  173. package/src/styles/themes/_baseline.scss +58 -0
  174. package/src/styles/themes/_bluekhaki.scss +125 -0
  175. package/src/styles/themes/_brownbeige.scss +125 -0
  176. package/src/styles/themes/_browngreen.scss +125 -0
  177. package/src/styles/themes/_forest.scss +6 -0
  178. package/src/styles/themes/_greenbeige.scss +125 -0
  179. package/src/styles/themes/_material.scss +125 -0
  180. package/src/styles/themes/_ocean.scss +6 -0
  181. package/src/styles/themes/_sageivory.scss +125 -0
  182. package/src/styles/themes/_spring.scss +6 -0
  183. package/src/styles/themes/_summer.scss +5 -0
  184. package/src/styles/themes/_sunset.scss +5 -0
  185. package/src/styles/themes/_tealcaramel.scss +125 -0
  186. package/src/styles/themes/_winter.scss +6 -0
  187. package/src/components/card/actions.ts +0 -48
  188. package/src/components/card/header.ts +0 -88
  189. package/src/components/card/media.ts +0 -52
  190. package/src/components/navigation/features/items.js +0 -192
  191. package/src/components/slider/features/appearance.ts +0 -94
  192. package/src/components/slider/features/disabled.ts +0 -43
  193. package/src/components/slider/features/events.ts +0 -164
  194. package/src/components/slider/features/interactions.ts +0 -261
  195. package/src/components/slider/features/keyboard.ts +0 -112
  196. package/src/core/collection/adapters/mongodb.js +0 -232
@@ -1,43 +0,0 @@
1
- // src/components/slider/features/disabled.ts
2
- import { SliderConfig } from '../types';
3
-
4
- /**
5
- * Add disabled state functionality to component
6
- * @param config Slider configuration
7
- * @returns Component enhancer with disabled functionality
8
- */
9
- export const withDisabled = (config: SliderConfig) => component => {
10
- // Initial disabled state
11
- const isDisabled = config.disabled === true;
12
-
13
- return {
14
- ...component,
15
- disabled: {
16
- enable() {
17
- component.element.classList.remove(`${component.getClass('slider')}--disabled`);
18
- component.element.setAttribute('aria-disabled', 'false');
19
- component.element.tabIndex = 0;
20
- component.structure.thumb.tabIndex = 0;
21
-
22
- if (config.range && component.structure.secondThumb) {
23
- component.structure.secondThumb.tabIndex = 0;
24
- }
25
- },
26
-
27
- disable() {
28
- component.element.classList.add(`${component.getClass('slider')}--disabled`);
29
- component.element.setAttribute('aria-disabled', 'true');
30
- component.element.tabIndex = -1;
31
- component.structure.thumb.tabIndex = -1;
32
-
33
- if (config.range && component.structure.secondThumb) {
34
- component.structure.secondThumb.tabIndex = -1;
35
- }
36
- },
37
-
38
- isDisabled() {
39
- return component.element.classList.contains(`${component.getClass('slider')}--disabled`);
40
- }
41
- }
42
- };
43
- };
@@ -1,164 +0,0 @@
1
- // src/components/slider/features/events.ts
2
- import { SliderEvent } from '../types';
3
-
4
- /**
5
- * Create event helper functions for the slider component
6
- *
7
- * @param state Slider state object
8
- * @returns Event helper methods
9
- */
10
- export const createEventHelpers = (state) => {
11
- /**
12
- * Triggers a slider event
13
- * @param eventName Name of the event to trigger
14
- * @param originalEvent Original DOM event if applicable
15
- * @returns Event data object
16
- */
17
- const triggerEvent = (eventName, originalEvent = null) => {
18
- // Create event data object
19
- const eventData: SliderEvent = {
20
- slider: state.component,
21
- value: state.value,
22
- secondValue: state.secondValue,
23
- originalEvent,
24
- preventDefault: () => { eventData.defaultPrevented = true; },
25
- defaultPrevented: false
26
- };
27
-
28
- // Add a component events facade if it doesn't exist
29
- if (!state.component.events) {
30
- state.component.events = {
31
- trigger: () => {},
32
- on: () => {},
33
- off: () => {}
34
- };
35
- }
36
-
37
- // Now we can safely trigger the event
38
- state.component.events.trigger(eventName, eventData);
39
-
40
- return eventData;
41
- };
42
-
43
- /**
44
- * Set up event listeners for slider elements
45
- * @param interactionHandlers Mouse/touch interaction handlers
46
- * @param keyboardHandlers Keyboard interaction handlers
47
- */
48
- const setupEventListeners = (interactionHandlers, keyboardHandlers) => {
49
- // Ensure needed component parts exist
50
- if (!state.component || !state.component.structure) {
51
- console.warn('Cannot set up event listeners: component structure is missing');
52
- return;
53
- }
54
-
55
- const {
56
- track = null,
57
- thumb = null,
58
- secondThumb = null
59
- } = state.component.structure;
60
-
61
- if (!track || !thumb) {
62
- console.warn('Cannot set up event listeners: track or thumb is missing');
63
- return;
64
- }
65
-
66
- const {
67
- handleThumbMouseDown,
68
- handleTrackMouseDown
69
- } = interactionHandlers;
70
-
71
- const {
72
- handleKeyDown,
73
- handleFocus,
74
- handleBlur
75
- } = keyboardHandlers;
76
-
77
- // Track events
78
- track.addEventListener('mousedown', handleTrackMouseDown);
79
- track.addEventListener('touchstart', handleTrackMouseDown, { passive: false });
80
-
81
- // Thumb events
82
- thumb.addEventListener('mousedown', (e) => handleThumbMouseDown(e, false));
83
- thumb.addEventListener('touchstart', (e) => handleThumbMouseDown(e, false), { passive: false });
84
- thumb.addEventListener('keydown', (e) => handleKeyDown(e, false));
85
- thumb.addEventListener('focus', (e) => handleFocus(e, false));
86
- thumb.addEventListener('blur', (e) => handleBlur(e, false));
87
-
88
- // Second thumb events for range slider
89
- if (state.component.config && state.component.config.range && secondThumb) {
90
- secondThumb.addEventListener('mousedown', (e) => handleThumbMouseDown(e, true));
91
- secondThumb.addEventListener('touchstart', (e) => handleThumbMouseDown(e, true), { passive: false });
92
- secondThumb.addEventListener('keydown', (e) => handleKeyDown(e, true));
93
- secondThumb.addEventListener('focus', (e) => handleFocus(e, true));
94
- secondThumb.addEventListener('blur', (e) => handleBlur(e, true));
95
- }
96
- };
97
-
98
- /**
99
- * Clean up event listeners
100
- * @param interactionHandlers Mouse/touch interaction handlers
101
- * @param keyboardHandlers Keyboard interaction handlers
102
- */
103
- const cleanupEventListeners = (interactionHandlers, keyboardHandlers) => {
104
- // Ensure needed component parts exist
105
- if (!state.component || !state.component.structure) {
106
- return;
107
- }
108
-
109
- const {
110
- track = null,
111
- thumb = null,
112
- secondThumb = null
113
- } = state.component.structure;
114
-
115
- if (!track || !thumb) {
116
- return;
117
- }
118
-
119
- const {
120
- handleThumbMouseDown,
121
- handleTrackMouseDown,
122
- handleMouseMove,
123
- handleMouseUp
124
- } = interactionHandlers;
125
-
126
- const {
127
- handleKeyDown,
128
- handleFocus,
129
- handleBlur
130
- } = keyboardHandlers;
131
-
132
- // Track events
133
- track.removeEventListener('mousedown', handleTrackMouseDown);
134
- track.removeEventListener('touchstart', handleTrackMouseDown);
135
-
136
- // Thumb events
137
- thumb.removeEventListener('mousedown', (e) => handleThumbMouseDown(e, false));
138
- thumb.removeEventListener('touchstart', (e) => handleThumbMouseDown(e, false));
139
- thumb.removeEventListener('keydown', (e) => handleKeyDown(e, false));
140
- thumb.removeEventListener('focus', (e) => handleFocus(e, false));
141
- thumb.removeEventListener('blur', (e) => handleBlur(e, false));
142
-
143
- // Second thumb events
144
- if (state.component.config && state.component.config.range && secondThumb) {
145
- secondThumb.removeEventListener('mousedown', (e) => handleThumbMouseDown(e, true));
146
- secondThumb.removeEventListener('touchstart', (e) => handleThumbMouseDown(e, true));
147
- secondThumb.removeEventListener('keydown', (e) => handleKeyDown(e, true));
148
- secondThumb.removeEventListener('focus', (e) => handleFocus(e, true));
149
- secondThumb.removeEventListener('blur', (e) => handleBlur(e, true));
150
- }
151
-
152
- // Global events
153
- document.removeEventListener('mousemove', handleMouseMove);
154
- document.removeEventListener('mouseup', handleMouseUp);
155
- document.removeEventListener('touchmove', handleMouseMove);
156
- document.removeEventListener('touchend', handleMouseUp);
157
- };
158
-
159
- return {
160
- triggerEvent,
161
- setupEventListeners,
162
- cleanupEventListeners
163
- };
164
- };
@@ -1,261 +0,0 @@
1
- // src/components/slider/features/interactions.ts
2
- import { SLIDER_EVENTS } from '../constants';
3
- import { SliderConfig, SliderEvent } from '../types';
4
-
5
- /**
6
- * Add interaction event handlers to slider component
7
- * This function contains the core event handlers for mouse/touch interactions
8
- *
9
- * @param config Slider configuration
10
- * @param state Slider state object
11
- * @param handlers Object containing handler methods
12
- * @returns Event handlers for slider interactions
13
- */
14
- export const createInteractionHandlers = (config: SliderConfig, state, handlers) => {
15
- // Ensure state and handlers exist
16
- if (!state || !handlers) {
17
- console.error('Cannot create interaction handlers: state or handlers missing');
18
- return {
19
- handleThumbMouseDown: () => {},
20
- handleTrackMouseDown: () => {},
21
- handleMouseMove: () => {},
22
- handleMouseUp: () => {}
23
- };
24
- }
25
-
26
- // Get required elements from structure (with fallbacks)
27
- const {
28
- track = null,
29
- thumb = null,
30
- valueBubble = null,
31
- secondThumb = null,
32
- secondValueBubble = null
33
- } = state.component?.structure || {};
34
-
35
- // Get required handler methods (with fallbacks)
36
- const {
37
- getValueFromPosition = () => 0,
38
- roundToStep = value => value,
39
- clamp = (value, min, max) => value,
40
- showValueBubble = () => {},
41
- updateUi = () => {},
42
- triggerEvent = () => ({ defaultPrevented: false })
43
- } = handlers;
44
-
45
- // Event handlers
46
- const handleThumbMouseDown = (e, isSecondThumb = false) => {
47
- console.log('handleThumbMouseDown', e)
48
- // Verify component exists and check if disabled
49
- if (!state.component || (state.component.disabled && state.component.disabled.isDisabled())) {
50
- return;
51
- }
52
-
53
- e.preventDefault();
54
- e.stopPropagation();
55
-
56
- state.dragging = true;
57
- state.activeThumb = isSecondThumb ? secondThumb : thumb;
58
- state.activeBubble = isSecondThumb ? secondValueBubble : valueBubble;
59
-
60
- // Add dragging class to component element to style the thumb differently
61
- state.component.element.classList.add(`${state.component.getClass('slider')}--dragging`);
62
-
63
- // Show value bubble if it exists
64
- if (state.activeBubble) {
65
- showValueBubble(state.activeBubble, true);
66
- }
67
-
68
- // Add global event listeners
69
- document.addEventListener('mousemove', handleMouseMove);
70
- document.addEventListener('mouseup', handleMouseUp);
71
- document.addEventListener('touchmove', handleMouseMove, { passive: false });
72
- document.addEventListener('touchend', handleMouseUp);
73
-
74
- // Try to trigger start event (with error handling)
75
- try {
76
- triggerEvent(SLIDER_EVENTS.START, e);
77
- } catch (error) {
78
- console.warn('Error triggering START event:', error);
79
- }
80
- };
81
-
82
- const handleTrackMouseDown = (e) => {
83
- // Verify component exists and check if disabled
84
- if (!state.component || (state.component.disabled && state.component.disabled.isDisabled()) || !track) {
85
- return;
86
- }
87
-
88
- e.preventDefault();
89
-
90
- // Determine which thumb to move based on click position
91
- let isSecondThumb = false;
92
-
93
- try {
94
- // Get track rect for calculating position
95
- const trackRect = track.getBoundingClientRect();
96
-
97
- // Get position from mouse or touch event
98
- const position = e.type.includes('touch')
99
- ? e.touches[0].clientX
100
- : e.clientX;
101
-
102
- // Calculate value at click position
103
- let newValue = getValueFromPosition(position);
104
-
105
- // Round to step if needed
106
- if (config.snapToSteps && state.step > 0) {
107
- newValue = roundToStep(newValue);
108
- }
109
-
110
- // Clamp value to min/max
111
- newValue = clamp(newValue, state.min, state.max);
112
-
113
- if (config.range && state.secondValue !== null) {
114
- // For range slider, determine which thumb to move (closest to click position)
115
- const distToFirst = Math.abs(newValue - state.value);
116
- const distToSecond = Math.abs(newValue - state.secondValue);
117
-
118
- isSecondThumb = distToSecond < distToFirst;
119
-
120
- // Update the appropriate value
121
- if (isSecondThumb) {
122
- state.secondValue = newValue;
123
- } else {
124
- state.value = newValue;
125
- }
126
- } else {
127
- // Single thumb slider - just update the value
128
- state.value = newValue;
129
- }
130
-
131
- // Update UI immediately
132
- updateUi();
133
-
134
- // Trigger events
135
- triggerEvent(SLIDER_EVENTS.INPUT, e);
136
- triggerEvent(SLIDER_EVENTS.CHANGE, e);
137
- } catch (error) {
138
- console.warn('Error handling track click:', error);
139
- }
140
-
141
- // Set active elements
142
- state.activeThumb = isSecondThumb ? secondThumb : thumb;
143
- state.activeBubble = isSecondThumb ? secondValueBubble : valueBubble;
144
-
145
- // Call thumb mouse down to start dragging
146
- handleThumbMouseDown(e, isSecondThumb);
147
- };
148
-
149
- const handleMouseMove = (e) => {
150
- if (!state.dragging || !state.activeThumb) return;
151
-
152
- e.preventDefault();
153
-
154
- try {
155
- // Get position
156
- const position = e.type.includes('touch')
157
- ? e.touches[0].clientX
158
- : e.clientX;
159
-
160
- // Calculate new value
161
- let newValue = getValueFromPosition(position);
162
-
163
- // Round to step if needed
164
- if (config.snapToSteps && state.step > 0) {
165
- newValue = roundToStep(newValue);
166
- }
167
-
168
- // Clamp value to min/max
169
- newValue = clamp(newValue, state.min, state.max);
170
-
171
- // Check if this is the second thumb
172
- const isSecondThumb = state.activeThumb === secondThumb;
173
-
174
- // For range slider, ensure thumbs don't cross
175
- if (config.range && state.secondValue !== null) {
176
- if (isSecondThumb) {
177
- // Don't allow second thumb to go below first thumb
178
- if (newValue < state.value) {
179
- state.secondValue = newValue;
180
- } else {
181
- // Thumbs are crossed, swap them
182
- state.secondValue = state.value;
183
- state.value = newValue;
184
-
185
- // Swap active thumb and bubble
186
- state.activeThumb = thumb;
187
- state.activeBubble = valueBubble;
188
- }
189
- } else {
190
- // Don't allow first thumb to go above second thumb
191
- if (newValue > state.secondValue) {
192
- state.value = newValue;
193
- } else {
194
- // Thumbs are crossed, swap them
195
- state.value = state.secondValue;
196
- state.secondValue = newValue;
197
-
198
- // Swap active thumb and bubble
199
- state.activeThumb = secondThumb;
200
- state.activeBubble = secondValueBubble;
201
- }
202
- }
203
- } else {
204
- // Regular slider
205
- state.value = newValue;
206
- }
207
-
208
- // Update UI
209
- updateUi();
210
-
211
- // Trigger input event (continuously while dragging)
212
- triggerEvent(SLIDER_EVENTS.INPUT, e);
213
- } catch (error) {
214
- console.warn('Error during slider drag:', error);
215
- }
216
- };
217
-
218
- const handleMouseUp = (e) => {
219
- if (!state.dragging) return;
220
-
221
- e.preventDefault();
222
-
223
- state.dragging = false;
224
-
225
- // Remove dragging class from component element
226
- state.component.element.classList.remove(`${state.component.getClass('slider')}--dragging`);
227
-
228
- // Hide value bubble
229
- if (state.activeBubble) {
230
- showValueBubble(state.activeBubble, false);
231
- }
232
-
233
- // Remove global event listeners
234
- document.removeEventListener('mousemove', handleMouseMove);
235
- document.removeEventListener('mouseup', handleMouseUp);
236
- document.removeEventListener('touchmove', handleMouseMove);
237
- document.removeEventListener('touchend', handleMouseUp);
238
-
239
- // Reset active elements
240
- state.activeThumb = null;
241
- state.activeBubble = null;
242
-
243
- try {
244
- // Trigger change event (only when done dragging)
245
- triggerEvent(SLIDER_EVENTS.CHANGE, e);
246
-
247
- // Trigger end event
248
- triggerEvent(SLIDER_EVENTS.END, e);
249
- } catch (error) {
250
- console.warn('Error triggering events on mouse up:', error);
251
- }
252
- };
253
-
254
- // Return handlers
255
- return {
256
- handleThumbMouseDown,
257
- handleTrackMouseDown,
258
- handleMouseMove,
259
- handleMouseUp
260
- };
261
- };
@@ -1,112 +0,0 @@
1
- // src/components/slider/features/keyboard.ts
2
- import { SLIDER_EVENTS } from '../constants';
3
-
4
- /**
5
- * Add keyboard interaction handlers to slider component
6
- *
7
- * @param state Slider state object
8
- * @param handlers Object containing handler methods
9
- * @returns Event handlers for keyboard interactions
10
- */
11
- export const createKeyboardHandlers = (state, handlers) => {
12
- const {
13
- secondThumb,
14
- secondValueBubble,
15
- valueBubble
16
- } = state.component.structure;
17
-
18
- const {
19
- showValueBubble,
20
- updateUi,
21
- triggerEvent
22
- } = handlers;
23
-
24
- // Event handlers
25
- const handleKeyDown = (e, isSecondThumb = false) => {
26
- if (state.component.disabled && state.component.disabled.isDisabled()) return;
27
-
28
- const step = state.step || 1;
29
- let newValue;
30
-
31
- // Determine which value to modify
32
- if (isSecondThumb) {
33
- newValue = state.secondValue;
34
- } else {
35
- newValue = state.value;
36
- }
37
-
38
- switch (e.key) {
39
- case 'ArrowRight':
40
- e.preventDefault();
41
- newValue = Math.min(newValue + step, state.max);
42
- break;
43
-
44
- case 'ArrowLeft':
45
- e.preventDefault();
46
- newValue = Math.max(newValue - step, state.min);
47
- break;
48
-
49
- case 'Home':
50
- e.preventDefault();
51
- newValue = state.min;
52
- break;
53
-
54
- case 'End':
55
- e.preventDefault();
56
- newValue = state.max;
57
- break;
58
-
59
- case 'PageUp':
60
- e.preventDefault();
61
- newValue = Math.min(newValue + (step * 10), state.max);
62
- break;
63
-
64
- case 'PageDown':
65
- e.preventDefault();
66
- newValue = Math.max(newValue - (step * 10), state.min);
67
- break;
68
-
69
- default:
70
- return; // Exit if not a handled key
71
- }
72
-
73
- // Update the value
74
- if (isSecondThumb) {
75
- state.secondValue = newValue;
76
- } else {
77
- state.value = newValue;
78
- }
79
-
80
- // Update UI
81
- updateUi();
82
-
83
- // Trigger events
84
- triggerEvent(SLIDER_EVENTS.INPUT, e);
85
- triggerEvent(SLIDER_EVENTS.CHANGE, e);
86
- };
87
-
88
- const handleFocus = (e, isSecondThumb = false) => {
89
- if (state.component.disabled && state.component.disabled.isDisabled()) return;
90
-
91
- // Show value bubble
92
- showValueBubble(isSecondThumb ? secondValueBubble : valueBubble, true);
93
-
94
- // Trigger focus event
95
- triggerEvent(SLIDER_EVENTS.FOCUS, e);
96
- };
97
-
98
- const handleBlur = (e, isSecondThumb = false) => {
99
- // Hide value bubble
100
- showValueBubble(isSecondThumb ? secondValueBubble : valueBubble, false);
101
-
102
- // Trigger blur event
103
- triggerEvent(SLIDER_EVENTS.BLUR, e);
104
- };
105
-
106
- // Return handlers
107
- return {
108
- handleKeyDown,
109
- handleFocus,
110
- handleBlur
111
- };
112
- };