mtrl 0.2.6 → 0.2.8
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/demo/build.ts +349 -0
- package/demo/index.html +110 -0
- package/demo/main.js +448 -0
- package/demo/styles.css +239 -0
- package/index.ts +18 -0
- package/package.json +14 -3
- package/server.ts +86 -0
- package/src/components/badge/api.ts +70 -63
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +66 -13
- package/src/components/badge/features.ts +51 -42
- package/src/components/badge/index.ts +27 -2
- package/src/components/badge/types.ts +62 -30
- package/src/components/bottom-app-bar/bottom-app-bar.ts +154 -0
- package/src/components/bottom-app-bar/config.ts +29 -0
- package/src/components/bottom-app-bar/index.ts +17 -0
- package/src/components/bottom-app-bar/types.ts +114 -0
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -1
- package/src/components/button/config.ts +6 -2
- package/src/components/button/index.ts +10 -2
- package/src/components/button/types.ts +20 -2
- package/src/components/card/card.ts +13 -25
- package/src/components/card/config.ts +83 -30
- package/src/components/card/content.ts +8 -10
- package/src/components/card/features.ts +4 -3
- package/src/components/card/index.ts +29 -2
- package/src/components/card/types.ts +33 -22
- package/src/components/checkbox/config.ts +3 -4
- package/src/components/checkbox/index.ts +1 -2
- package/src/components/checkbox/types.ts +12 -3
- package/src/components/chip/api.ts +170 -221
- package/src/components/chip/chip.ts +34 -302
- package/src/components/chip/config.ts +1 -2
- package/src/components/chip/index.ts +10 -2
- package/src/components/chip/types.ts +224 -35
- package/src/components/datepicker/api.ts +265 -0
- package/src/components/datepicker/config.ts +141 -0
- package/src/components/datepicker/datepicker.ts +341 -0
- package/src/components/datepicker/index.ts +12 -0
- package/src/components/datepicker/render.ts +450 -0
- package/src/components/datepicker/types.ts +397 -0
- package/src/components/datepicker/utils.ts +289 -0
- package/src/components/dialog/api.ts +55 -21
- package/src/components/dialog/config.ts +12 -9
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +345 -151
- package/src/components/dialog/index.ts +38 -8
- package/src/components/dialog/types.ts +40 -14
- package/src/components/divider/config.ts +81 -0
- package/src/components/divider/divider.ts +37 -0
- package/src/components/divider/features.ts +207 -0
- package/src/components/divider/index.ts +9 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +112 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +9 -0
- package/src/components/extended-fab/types.ts +304 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +93 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +9 -0
- package/src/components/fab/types.ts +251 -0
- package/src/components/list/config.ts +4 -5
- package/src/components/list/features.ts +6 -7
- package/src/components/list/index.ts +7 -9
- package/src/components/list/list-item.ts +12 -13
- package/src/components/list/types.ts +50 -5
- package/src/components/list/utils.ts +30 -3
- package/src/components/menu/features/items-manager.ts +9 -9
- package/src/components/menu/features/positioning.ts +7 -7
- package/src/components/menu/features/visibility.ts +7 -7
- package/src/components/menu/index.ts +7 -9
- package/src/components/menu/menu-item.ts +6 -6
- package/src/components/menu/menu.ts +22 -0
- package/src/components/menu/types.ts +29 -10
- package/src/components/menu/utils.ts +67 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/config.ts +22 -10
- package/src/components/navigation/features/items.ts +284 -0
- package/src/components/navigation/index.ts +0 -6
- package/src/components/navigation/nav-item.ts +70 -33
- package/src/components/navigation/navigation.ts +53 -3
- package/src/components/navigation/types.ts +117 -70
- package/src/components/progress/api.ts +2 -3
- package/src/components/progress/config.ts +2 -3
- package/src/components/progress/index.ts +0 -1
- package/src/components/progress/progress.ts +1 -2
- package/src/components/progress/types.ts +186 -33
- package/src/components/radios/config.ts +1 -1
- package/src/components/radios/index.ts +0 -1
- package/src/components/radios/types.ts +0 -7
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +86 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +717 -0
- package/src/components/search/features/states.ts +169 -0
- package/src/components/search/features/structure.ts +197 -0
- package/src/components/search/index.ts +7 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +175 -0
- package/src/components/segmented-button/config.ts +80 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +154 -0
- package/src/components/segmented-button/segmented-button.ts +249 -0
- package/src/components/segmented-button/types.ts +254 -0
- package/src/components/slider/accessibility.md +5 -5
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -47
- package/src/components/slider/features/handlers.ts +495 -0
- package/src/components/slider/features/index.ts +1 -2
- package/src/components/slider/features/slider.ts +66 -84
- package/src/components/slider/features/states.ts +195 -0
- package/src/components/slider/features/structure.ts +136 -206
- package/src/components/slider/features/ui.ts +145 -206
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +67 -26
- package/src/components/snackbar/config.ts +2 -3
- package/src/components/snackbar/constants.ts +0 -32
- package/src/components/snackbar/index.ts +0 -1
- package/src/components/snackbar/position.ts +9 -1
- package/src/components/snackbar/types.ts +122 -46
- package/src/components/switch/config.ts +2 -3
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/types.ts +3 -2
- package/src/components/tabs/config.ts +3 -4
- package/src/components/tabs/features.ts +4 -2
- package/src/components/tabs/index.ts +0 -15
- package/src/components/tabs/indicator.ts +73 -13
- package/src/components/tabs/tab-api.ts +12 -4
- package/src/components/tabs/tab.ts +18 -6
- package/src/components/tabs/types.ts +23 -5
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/index.ts +0 -1
- package/src/components/textfield/types.ts +17 -3
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +228 -0
- package/src/components/timepicker/index.ts +3 -0
- package/src/components/timepicker/render.ts +613 -0
- package/src/components/timepicker/timepicker.ts +117 -0
- package/src/components/timepicker/types.ts +336 -0
- package/src/components/timepicker/utils.ts +241 -0
- package/src/components/tooltip/api.ts +1 -1
- package/src/components/tooltip/config.ts +27 -6
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/types.ts +13 -3
- package/src/components/top-app-bar/config.ts +83 -0
- package/src/components/top-app-bar/index.ts +11 -0
- package/src/components/top-app-bar/top-app-bar.ts +316 -0
- package/src/components/top-app-bar/types.ts +140 -0
- package/src/core/build/_ripple.scss +6 -6
- package/src/core/build/ripple.ts +72 -95
- package/src/core/compose/features/icon.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +23 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +9 -1
- package/src/styles/components/_badge.scss +182 -0
- package/src/styles/components/_bottom-app-bar.scss +103 -0
- package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -10
- package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -2
- package/src/styles/components/_datepicker.scss +358 -0
- package/src/styles/components/_dialog.scss +259 -0
- package/src/styles/components/_divider.scss +57 -0
- package/src/styles/components/_extended-fab.scss +267 -0
- package/src/styles/components/_fab.scss +225 -0
- package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +1 -0
- package/src/styles/components/_search.scss +306 -0
- package/src/styles/components/_segmented-button.scss +117 -0
- package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +83 -24
- package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -2
- package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +95 -33
- package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +70 -67
- package/src/styles/components/_timepicker.scss +451 -0
- package/src/styles/components/_top-app-bar.scss +225 -0
- package/src/styles/main.scss +98 -49
- package/src/styles/themes/_autumn.scss +21 -0
- package/src/styles/themes/_base-theme.scss +61 -0
- package/src/styles/themes/_baseline.scss +58 -0
- package/src/styles/themes/_bluekhaki.scss +125 -0
- package/src/styles/themes/_brownbeige.scss +125 -0
- package/src/styles/themes/_browngreen.scss +125 -0
- package/src/styles/themes/_forest.scss +6 -0
- package/src/styles/themes/_greenbeige.scss +125 -0
- package/src/styles/themes/_material.scss +125 -0
- package/src/styles/themes/_ocean.scss +6 -0
- package/src/styles/themes/_sageivory.scss +125 -0
- package/src/styles/themes/_spring.scss +6 -0
- package/src/styles/themes/_summer.scss +5 -0
- package/src/styles/themes/_sunset.scss +5 -0
- package/src/styles/themes/_tealcaramel.scss +125 -0
- package/src/styles/themes/_winter.scss +6 -0
- package/src/components/badge/_styles.scss +0 -174
- package/src/components/badge/constants.ts +0 -30
- package/src/components/button/constants.ts +0 -11
- package/src/components/card/constants.ts +0 -84
- package/src/components/dialog/_styles.scss +0 -213
- package/src/components/dialog/constants.ts +0 -32
- package/src/components/menu/constants.ts +0 -154
- package/src/components/navigation/constants.ts +0 -200
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/progress/constants.ts +0 -29
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -68
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -396
- package/src/components/slider/features/keyboard.ts +0 -233
- package/src/components/switch/constants.ts +0 -80
- package/src/components/tabs/constants.ts +0 -89
- package/src/core/collection/adapters/mongodb.js +0 -232
- /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
- /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
- /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
- /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
- /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
- /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
- /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
- /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
- /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
- /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
- /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
|
@@ -1,68 +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
|
-
// Apply initial disabled state if needed
|
|
14
|
-
if (isDisabled && component.structure) {
|
|
15
|
-
setTimeout(() => {
|
|
16
|
-
disableComponent();
|
|
17
|
-
}, 0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function disableComponent() {
|
|
21
|
-
component.element.classList.add(`${component.getClass('slider')}--disabled`);
|
|
22
|
-
component.element.setAttribute('aria-disabled', 'true');
|
|
23
|
-
|
|
24
|
-
// Ensure thumbs cannot receive focus when disabled
|
|
25
|
-
if (component.structure.thumb) {
|
|
26
|
-
component.structure.thumb.tabIndex = -1;
|
|
27
|
-
component.structure.thumb.setAttribute('aria-disabled', 'true');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (config.range && component.structure.secondThumb) {
|
|
31
|
-
component.structure.secondThumb.tabIndex = -1;
|
|
32
|
-
component.structure.secondThumb.setAttribute('aria-disabled', 'true');
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function enableComponent() {
|
|
37
|
-
component.element.classList.remove(`${component.getClass('slider')}--disabled`);
|
|
38
|
-
component.element.setAttribute('aria-disabled', 'false');
|
|
39
|
-
|
|
40
|
-
// Re-enable focus on thumbs
|
|
41
|
-
if (component.structure.thumb) {
|
|
42
|
-
component.structure.thumb.tabIndex = 0;
|
|
43
|
-
component.structure.thumb.setAttribute('aria-disabled', 'false');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (config.range && component.structure.secondThumb) {
|
|
47
|
-
component.structure.secondThumb.tabIndex = 0;
|
|
48
|
-
component.structure.secondThumb.setAttribute('aria-disabled', 'false');
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
...component,
|
|
54
|
-
disabled: {
|
|
55
|
-
enable() {
|
|
56
|
-
enableComponent();
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
disable() {
|
|
60
|
-
disableComponent();
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
isDisabled() {
|
|
64
|
-
return component.element.classList.contains(`${component.getClass('slider')}--disabled`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
};
|
|
@@ -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,396 +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
|
-
/**
|
|
46
|
-
* Clear any existing bubble hide timers
|
|
47
|
-
*/
|
|
48
|
-
const clearBubbleHideTimer = () => {
|
|
49
|
-
if (state.valueHideTimer) {
|
|
50
|
-
clearTimeout(state.valueHideTimer);
|
|
51
|
-
state.valueHideTimer = null;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Hide all bubbles immediately
|
|
57
|
-
*/
|
|
58
|
-
const hideAllBubbles = () => {
|
|
59
|
-
// Clear any pending hide timers
|
|
60
|
-
clearBubbleHideTimer();
|
|
61
|
-
|
|
62
|
-
// Hide both bubbles immediately
|
|
63
|
-
if (valueBubble) {
|
|
64
|
-
showValueBubble(valueBubble, false);
|
|
65
|
-
}
|
|
66
|
-
if (secondValueBubble) {
|
|
67
|
-
showValueBubble(secondValueBubble, false);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Clear keyboard focus indicators across all sliders in the document
|
|
73
|
-
* Not just for this instance, but for any slider thumb
|
|
74
|
-
*/
|
|
75
|
-
const clearGlobalKeyboardFocus = () => {
|
|
76
|
-
// First clear local focus indicators
|
|
77
|
-
if (thumb) {
|
|
78
|
-
thumb.classList.remove(`${state.component.getClass('slider-thumb')}--focused`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (secondThumb) {
|
|
82
|
-
secondThumb.classList.remove(`${state.component.getClass('slider-thumb')}--focused`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Now look for all slider thumbs in the document with the focused class
|
|
86
|
-
// This covers cases where we switch between sliders
|
|
87
|
-
try {
|
|
88
|
-
const focusClass = state.component.getClass('slider-thumb--focused');
|
|
89
|
-
const allFocusedThumbs = document.querySelectorAll(`.${focusClass}`);
|
|
90
|
-
|
|
91
|
-
// Remove focus class from all thumbs
|
|
92
|
-
allFocusedThumbs.forEach(element => {
|
|
93
|
-
element.classList.remove(focusClass);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Also blur the active element if it's a thumb
|
|
97
|
-
if (document.activeElement &&
|
|
98
|
-
document.activeElement.classList.contains(state.component.getClass('slider-thumb'))) {
|
|
99
|
-
(document.activeElement as HTMLElement).blur();
|
|
100
|
-
}
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.warn('Error clearing global keyboard focus:', error);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Show the active bubble with consistent behavior
|
|
108
|
-
* @param bubble Bubble element to show
|
|
109
|
-
*/
|
|
110
|
-
const showActiveBubble = (bubble) => {
|
|
111
|
-
// First hide all bubbles
|
|
112
|
-
hideAllBubbles();
|
|
113
|
-
|
|
114
|
-
// Then show the active bubble if allowed by config
|
|
115
|
-
if (bubble && config.showValue) {
|
|
116
|
-
showValueBubble(bubble, true);
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Hide the active bubble with optional delay
|
|
122
|
-
* @param bubble Bubble element to hide
|
|
123
|
-
* @param delay Delay in milliseconds before hiding
|
|
124
|
-
*/
|
|
125
|
-
const hideActiveBubble = (bubble, delay = 0) => {
|
|
126
|
-
// Clear any existing timers first
|
|
127
|
-
clearBubbleHideTimer();
|
|
128
|
-
|
|
129
|
-
if (!bubble || !config.showValue) return;
|
|
130
|
-
|
|
131
|
-
if (delay > 0) {
|
|
132
|
-
// Set delayed hide
|
|
133
|
-
state.valueHideTimer = setTimeout(() => {
|
|
134
|
-
showValueBubble(bubble, false);
|
|
135
|
-
}, delay);
|
|
136
|
-
} else {
|
|
137
|
-
// Hide immediately
|
|
138
|
-
showValueBubble(bubble, false);
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Handle thumb mouse down with improved bubble handling
|
|
144
|
-
*/
|
|
145
|
-
const handleThumbMouseDown = (e, isSecondThumb = false) => {
|
|
146
|
-
// Verify component exists and check if disabled
|
|
147
|
-
if (!state.component || (state.component.disabled && state.component.disabled.isDisabled())) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
e.preventDefault();
|
|
152
|
-
e.stopPropagation();
|
|
153
|
-
|
|
154
|
-
// First hide any existing visible bubbles
|
|
155
|
-
hideAllBubbles();
|
|
156
|
-
|
|
157
|
-
// Clear any keyboard focus indicators globally
|
|
158
|
-
clearGlobalKeyboardFocus();
|
|
159
|
-
|
|
160
|
-
state.dragging = true;
|
|
161
|
-
state.activeThumb = isSecondThumb ? secondThumb : thumb;
|
|
162
|
-
state.activeBubble = isSecondThumb ? secondValueBubble : valueBubble;
|
|
163
|
-
|
|
164
|
-
// Add dragging class to component element to style the thumb differently
|
|
165
|
-
state.component.element.classList.add(`${state.component.getClass('slider')}--dragging`);
|
|
166
|
-
|
|
167
|
-
// Show active bubble
|
|
168
|
-
showActiveBubble(state.activeBubble);
|
|
169
|
-
|
|
170
|
-
// Add global event listeners
|
|
171
|
-
document.addEventListener('mousemove', handleMouseMove);
|
|
172
|
-
document.addEventListener('mouseup', handleMouseUp);
|
|
173
|
-
document.addEventListener('touchmove', handleMouseMove, { passive: false });
|
|
174
|
-
document.addEventListener('touchend', handleMouseUp);
|
|
175
|
-
|
|
176
|
-
// Try to trigger start event (with error handling)
|
|
177
|
-
try {
|
|
178
|
-
triggerEvent(SLIDER_EVENTS.START, e);
|
|
179
|
-
} catch (error) {
|
|
180
|
-
console.warn('Error triggering START event:', error);
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Handle track mouse down with improved bubble handling
|
|
186
|
-
*/
|
|
187
|
-
const handleTrackMouseDown = (e) => {
|
|
188
|
-
// Verify component exists and check if disabled
|
|
189
|
-
if (!state.component || (state.component.disabled && state.component.disabled.isDisabled()) || !track) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
e.preventDefault();
|
|
194
|
-
|
|
195
|
-
// Hide any existing visible bubbles
|
|
196
|
-
hideAllBubbles();
|
|
197
|
-
|
|
198
|
-
// Clear any keyboard focus indicators globally
|
|
199
|
-
clearGlobalKeyboardFocus();
|
|
200
|
-
|
|
201
|
-
// Determine which thumb to move based on click position
|
|
202
|
-
let isSecondThumb = false;
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
// Get track rect for calculating position
|
|
206
|
-
const trackRect = track.getBoundingClientRect();
|
|
207
|
-
|
|
208
|
-
// Get position from mouse or touch event
|
|
209
|
-
const position = e.type.includes('touch')
|
|
210
|
-
? e.touches[0].clientX
|
|
211
|
-
: e.clientX;
|
|
212
|
-
|
|
213
|
-
// Calculate value at click position
|
|
214
|
-
let newValue = getValueFromPosition(position);
|
|
215
|
-
|
|
216
|
-
// Round to step if needed
|
|
217
|
-
if (config.snapToSteps && state.step > 0) {
|
|
218
|
-
newValue = roundToStep(newValue);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Clamp value to min/max
|
|
222
|
-
newValue = clamp(newValue, state.min, state.max);
|
|
223
|
-
|
|
224
|
-
if (config.range && state.secondValue !== null) {
|
|
225
|
-
// For range slider, determine which thumb to move (closest to click position)
|
|
226
|
-
const distToFirst = Math.abs(newValue - state.value);
|
|
227
|
-
const distToSecond = Math.abs(newValue - state.secondValue);
|
|
228
|
-
|
|
229
|
-
isSecondThumb = distToSecond < distToFirst;
|
|
230
|
-
|
|
231
|
-
// Update the appropriate value
|
|
232
|
-
if (isSecondThumb) {
|
|
233
|
-
state.secondValue = newValue;
|
|
234
|
-
} else {
|
|
235
|
-
state.value = newValue;
|
|
236
|
-
}
|
|
237
|
-
} else {
|
|
238
|
-
// Single thumb slider - just update the value
|
|
239
|
-
state.value = newValue;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Update UI immediately
|
|
243
|
-
updateUi();
|
|
244
|
-
|
|
245
|
-
// Trigger events
|
|
246
|
-
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
247
|
-
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.warn('Error handling track click:', error);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Set active elements
|
|
253
|
-
state.activeThumb = isSecondThumb ? secondThumb : thumb;
|
|
254
|
-
state.activeBubble = isSecondThumb ? secondValueBubble : valueBubble;
|
|
255
|
-
|
|
256
|
-
// Call thumb mouse down to start dragging
|
|
257
|
-
handleThumbMouseDown(e, isSecondThumb);
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Handle mouse move with improved thumb and bubble switching
|
|
262
|
-
*/
|
|
263
|
-
const handleMouseMove = (e) => {
|
|
264
|
-
if (!state.dragging || !state.activeThumb) return;
|
|
265
|
-
|
|
266
|
-
e.preventDefault();
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
// Get position
|
|
270
|
-
const position = e.type.includes('touch')
|
|
271
|
-
? e.touches[0].clientX
|
|
272
|
-
: e.clientX;
|
|
273
|
-
|
|
274
|
-
// Calculate new value
|
|
275
|
-
let newValue = getValueFromPosition(position);
|
|
276
|
-
|
|
277
|
-
// Round to step if needed
|
|
278
|
-
if (config.snapToSteps && state.step > 0) {
|
|
279
|
-
newValue = roundToStep(newValue);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Clamp value to min/max
|
|
283
|
-
newValue = clamp(newValue, state.min, state.max);
|
|
284
|
-
|
|
285
|
-
// Check if this is the second thumb
|
|
286
|
-
const isSecondThumb = state.activeThumb === secondThumb;
|
|
287
|
-
|
|
288
|
-
// For range slider, ensure thumbs don't cross
|
|
289
|
-
if (config.range && state.secondValue !== null) {
|
|
290
|
-
if (isSecondThumb) {
|
|
291
|
-
// Second thumb is active
|
|
292
|
-
|
|
293
|
-
// Don't allow second thumb to go below first thumb
|
|
294
|
-
if (newValue >= state.value) {
|
|
295
|
-
state.secondValue = newValue;
|
|
296
|
-
} else {
|
|
297
|
-
// Thumbs are crossed, need to swap them
|
|
298
|
-
|
|
299
|
-
// First hide current bubble
|
|
300
|
-
hideActiveBubble(state.activeBubble, 0);
|
|
301
|
-
|
|
302
|
-
// Swap values
|
|
303
|
-
state.secondValue = state.value;
|
|
304
|
-
state.value = newValue;
|
|
305
|
-
|
|
306
|
-
// Swap active elements
|
|
307
|
-
state.activeThumb = thumb;
|
|
308
|
-
state.activeBubble = valueBubble;
|
|
309
|
-
|
|
310
|
-
// Show new active bubble
|
|
311
|
-
showActiveBubble(state.activeBubble);
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
// First thumb is active
|
|
315
|
-
|
|
316
|
-
// Don't allow first thumb to go above second thumb
|
|
317
|
-
if (newValue <= state.secondValue) {
|
|
318
|
-
state.value = newValue;
|
|
319
|
-
} else {
|
|
320
|
-
// Thumbs are crossed, need to swap them
|
|
321
|
-
|
|
322
|
-
// First hide current bubble
|
|
323
|
-
hideActiveBubble(state.activeBubble, 0);
|
|
324
|
-
|
|
325
|
-
// Swap values
|
|
326
|
-
state.value = state.secondValue;
|
|
327
|
-
state.secondValue = newValue;
|
|
328
|
-
|
|
329
|
-
// Swap active elements
|
|
330
|
-
state.activeThumb = secondThumb;
|
|
331
|
-
state.activeBubble = secondValueBubble;
|
|
332
|
-
|
|
333
|
-
// Show new active bubble
|
|
334
|
-
showActiveBubble(state.activeBubble);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
// Regular slider
|
|
339
|
-
state.value = newValue;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Update UI
|
|
343
|
-
updateUi();
|
|
344
|
-
|
|
345
|
-
// Trigger input event (continuously while dragging)
|
|
346
|
-
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
347
|
-
} catch (error) {
|
|
348
|
-
console.warn('Error during slider drag:', error);
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Handle mouse up with consistent bubble hiding
|
|
354
|
-
*/
|
|
355
|
-
const handleMouseUp = (e) => {
|
|
356
|
-
if (!state.dragging) return;
|
|
357
|
-
|
|
358
|
-
e.preventDefault();
|
|
359
|
-
|
|
360
|
-
state.dragging = false;
|
|
361
|
-
|
|
362
|
-
// Remove dragging class from component element
|
|
363
|
-
state.component.element.classList.remove(`${state.component.getClass('slider')}--dragging`);
|
|
364
|
-
|
|
365
|
-
// Hide bubble with delay
|
|
366
|
-
const currentBubble = state.activeBubble;
|
|
367
|
-
hideActiveBubble(currentBubble, 1000); // Hide after 1 second
|
|
368
|
-
|
|
369
|
-
// Remove global event listeners
|
|
370
|
-
document.removeEventListener('mousemove', handleMouseMove);
|
|
371
|
-
document.removeEventListener('mouseup', handleMouseUp);
|
|
372
|
-
document.removeEventListener('touchmove', handleMouseMove);
|
|
373
|
-
document.removeEventListener('touchend', handleMouseUp);
|
|
374
|
-
|
|
375
|
-
// Reset active thumb
|
|
376
|
-
state.activeThumb = null;
|
|
377
|
-
|
|
378
|
-
try {
|
|
379
|
-
// Trigger change event (only when done dragging)
|
|
380
|
-
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
381
|
-
|
|
382
|
-
// Trigger end event
|
|
383
|
-
triggerEvent(SLIDER_EVENTS.END, e);
|
|
384
|
-
} catch (error) {
|
|
385
|
-
console.warn('Error triggering events on mouse up:', error);
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
// Return handlers
|
|
390
|
-
return {
|
|
391
|
-
handleThumbMouseDown,
|
|
392
|
-
handleTrackMouseDown,
|
|
393
|
-
handleMouseMove,
|
|
394
|
-
handleMouseUp
|
|
395
|
-
};
|
|
396
|
-
};
|