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.
- package/index.ts +18 -0
- package/package.json +1 -1
- package/src/components/badge/_styles.scss +123 -115
- package/src/components/badge/api.ts +57 -59
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +65 -11
- package/src/components/badge/constants.ts +22 -12
- package/src/components/badge/features.ts +44 -40
- package/src/components/badge/types.ts +42 -30
- package/src/components/bottom-app-bar/_styles.scss +103 -0
- package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
- package/src/components/bottom-app-bar/config.ts +73 -0
- package/src/components/bottom-app-bar/index.ts +11 -0
- package/src/components/bottom-app-bar/types.ts +108 -0
- package/src/components/button/_styles.scss +0 -66
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -2
- package/src/components/button/config.ts +5 -0
- package/src/components/button/constants.ts +0 -6
- package/src/components/button/index.ts +2 -2
- package/src/components/button/types.ts +7 -7
- package/src/components/card/_styles.scss +67 -25
- package/src/components/card/api.ts +54 -3
- package/src/components/card/card.ts +25 -6
- package/src/components/card/config.ts +189 -22
- package/src/components/card/constants.ts +20 -19
- package/src/components/card/content.ts +299 -2
- package/src/components/card/features.ts +158 -4
- package/src/components/card/index.ts +31 -9
- package/src/components/card/types.ts +166 -15
- package/src/components/checkbox/_styles.scss +0 -2
- package/src/components/chip/chip.ts +1 -9
- package/src/components/chip/constants.ts +0 -10
- package/src/components/chip/index.ts +1 -1
- package/src/components/chip/types.ts +1 -4
- package/src/components/datepicker/_styles.scss +358 -0
- package/src/components/datepicker/api.ts +272 -0
- package/src/components/datepicker/config.ts +144 -0
- package/src/components/datepicker/constants.ts +98 -0
- package/src/components/datepicker/datepicker.ts +346 -0
- package/src/components/datepicker/index.ts +9 -0
- package/src/components/datepicker/render.ts +452 -0
- package/src/components/datepicker/types.ts +268 -0
- package/src/components/datepicker/utils.ts +290 -0
- package/src/components/dialog/_styles.scss +174 -128
- package/src/components/dialog/api.ts +48 -13
- package/src/components/dialog/config.ts +9 -5
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +290 -130
- package/src/components/dialog/types.ts +7 -4
- package/src/components/divider/_styles.scss +57 -0
- 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 +5 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/_styles.scss +267 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +108 -0
- package/src/components/extended-fab/constants.ts +36 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +4 -0
- package/src/components/extended-fab/types.ts +287 -0
- package/src/components/fab/_styles.scss +225 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +94 -0
- package/src/components/fab/constants.ts +41 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +4 -0
- package/src/components/fab/types.ts +234 -0
- package/src/components/navigation/_styles.scss +1 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/features/items.ts +280 -0
- package/src/components/navigation/nav-item.ts +72 -23
- package/src/components/navigation/navigation.ts +54 -2
- package/src/components/navigation/types.ts +210 -188
- package/src/components/progress/_styles.scss +0 -65
- package/src/components/progress/config.ts +1 -2
- package/src/components/progress/constants.ts +0 -14
- package/src/components/progress/index.ts +1 -1
- package/src/components/progress/progress.ts +1 -4
- package/src/components/progress/types.ts +1 -4
- package/src/components/radios/_styles.scss +0 -45
- package/src/components/radios/api.ts +85 -60
- package/src/components/radios/config.ts +1 -2
- package/src/components/radios/constants.ts +0 -9
- package/src/components/radios/index.ts +1 -1
- package/src/components/radios/radio.ts +34 -11
- package/src/components/radios/radios.ts +2 -1
- package/src/components/radios/types.ts +1 -7
- package/src/components/search/_styles.scss +306 -0
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +87 -0
- package/src/components/search/constants.ts +21 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +718 -0
- package/src/components/search/features/states.ts +165 -0
- package/src/components/search/features/structure.ts +198 -0
- package/src/components/search/index.ts +10 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +163 -0
- package/src/components/segmented-button/_styles.scss +117 -0
- package/src/components/segmented-button/config.ts +67 -0
- package/src/components/segmented-button/constants.ts +42 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +155 -0
- package/src/components/segmented-button/segmented-button.ts +250 -0
- package/src/components/segmented-button/types.ts +219 -0
- package/src/components/slider/_styles.scss +221 -168
- package/src/components/slider/accessibility.md +59 -0
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -49
- 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 +141 -184
- package/src/components/slider/features/ui.ts +150 -201
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +39 -24
- package/src/components/switch/_styles.scss +0 -2
- package/src/components/tabs/_styles.scss +346 -154
- package/src/components/tabs/api.ts +178 -400
- package/src/components/tabs/config.ts +46 -52
- package/src/components/tabs/constants.ts +85 -8
- package/src/components/tabs/features.ts +403 -0
- package/src/components/tabs/index.ts +60 -3
- package/src/components/tabs/indicator.ts +285 -0
- package/src/components/tabs/responsive.ts +144 -0
- package/src/components/tabs/scroll-indicators.ts +149 -0
- package/src/components/tabs/state.ts +186 -0
- package/src/components/tabs/tab-api.ts +258 -0
- package/src/components/tabs/tab.ts +255 -0
- package/src/components/tabs/tabs.ts +50 -31
- package/src/components/tabs/types.ts +332 -128
- package/src/components/tabs/utils.ts +107 -0
- package/src/components/textfield/_styles.scss +0 -98
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/constants.ts +0 -14
- package/src/components/textfield/index.ts +2 -2
- package/src/components/textfield/textfield.ts +0 -2
- package/src/components/textfield/types.ts +1 -4
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/_styles.scss +451 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +130 -0
- package/src/components/timepicker/constants.ts +138 -0
- package/src/components/timepicker/index.ts +8 -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/top-app-bar/_styles.scss +225 -0
- 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/component.ts +1 -1
- package/src/core/compose/features/badge.ts +79 -0
- package/src/core/compose/features/icon.ts +3 -1
- package/src/core/compose/features/index.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +26 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +115 -3
- 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/card/actions.ts +0 -48
- package/src/components/card/header.ts +0 -88
- package/src/components/card/media.ts +0 -52
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -43
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -261
- package/src/components/slider/features/keyboard.ts +0 -112
- package/src/core/collection/adapters/mongodb.js +0 -232
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { SliderConfig } from '../types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Create UI update helpers for slider component
|
|
5
|
+
* Create optimized UI update helpers for slider component
|
|
6
6
|
*
|
|
7
7
|
* @param config Slider configuration
|
|
8
8
|
* @param state Slider state object
|
|
@@ -12,19 +12,29 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
12
12
|
// Return empty implementations if component structure is missing
|
|
13
13
|
if (!state.component?.structure) {
|
|
14
14
|
console.error('Cannot create UI helpers: component structure is missing');
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
return {
|
|
16
|
+
getPercentage: () => 0,
|
|
17
|
+
getValueFromPosition: () => 0,
|
|
18
|
+
roundToStep: v => v,
|
|
19
|
+
clamp: (v, min, max) => Math.min(Math.max(v, min), max),
|
|
20
|
+
updateUi: () => {},
|
|
21
|
+
showValueBubble: () => {},
|
|
22
|
+
generateTicks: () => {},
|
|
23
|
+
updateTicks: () => {}
|
|
24
|
+
};
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
const {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
container = null,
|
|
29
|
+
track = null,
|
|
30
|
+
activeTrack = null,
|
|
31
|
+
startTrack = null,
|
|
32
|
+
remainingTrack = null,
|
|
33
|
+
handle = null,
|
|
34
|
+
valueBubble = null,
|
|
35
|
+
secondHandle = null,
|
|
36
|
+
secondValueBubble = null,
|
|
37
|
+
ticksContainer = null
|
|
28
38
|
} = state.component.structure;
|
|
29
39
|
|
|
30
40
|
/**
|
|
@@ -39,21 +49,22 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
39
49
|
* Gets track dimensions and constraints for positioning calculations
|
|
40
50
|
*/
|
|
41
51
|
const getTrackDimensions = () => {
|
|
42
|
-
if (!track || !
|
|
52
|
+
if (!track || !handle || !container) return null;
|
|
43
53
|
|
|
44
|
-
const
|
|
45
|
-
const trackRect =
|
|
46
|
-
const
|
|
54
|
+
const handleRect = handle.getBoundingClientRect();
|
|
55
|
+
const trackRect = container.getBoundingClientRect();
|
|
56
|
+
const handleSize = handleRect.width || 20;
|
|
47
57
|
const trackSize = trackRect.width;
|
|
48
58
|
|
|
49
|
-
const edgeConstraint = (
|
|
50
|
-
const
|
|
59
|
+
const edgeConstraint = (handleSize / 2) / trackSize * 100;
|
|
60
|
+
const paddingPixels = state.activeHandle ? 6 : 8;
|
|
61
|
+
const paddingPercent = (paddingPixels / trackSize) * 100;
|
|
51
62
|
|
|
52
|
-
return {
|
|
63
|
+
return { handleSize, trackSize, edgeConstraint, paddingPercent };
|
|
53
64
|
};
|
|
54
65
|
|
|
55
66
|
/**
|
|
56
|
-
*
|
|
67
|
+
* Maps value percentage to visual position with edge constraints
|
|
57
68
|
*/
|
|
58
69
|
const mapValueToVisualPercent = (valuePercent, edgeConstraint) => {
|
|
59
70
|
const minEdge = edgeConstraint;
|
|
@@ -69,17 +80,15 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
69
80
|
* Gets slider value from a position on the track
|
|
70
81
|
*/
|
|
71
82
|
const getValueFromPosition = (position) => {
|
|
72
|
-
if (!track) return state.min;
|
|
83
|
+
if (!track || !container) return state.min;
|
|
73
84
|
|
|
74
85
|
try {
|
|
75
|
-
const
|
|
86
|
+
const containerRect = container.getBoundingClientRect();
|
|
76
87
|
const range = state.max - state.min;
|
|
88
|
+
const handleWidth = handle.getBoundingClientRect().width || 20;
|
|
77
89
|
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
const leftEdge = trackRect.left + (thumbWidth / 2);
|
|
82
|
-
const rightEdge = trackRect.right - (thumbWidth / 2);
|
|
90
|
+
const leftEdge = containerRect.left + (handleWidth / 2);
|
|
91
|
+
const rightEdge = containerRect.right - (handleWidth / 2);
|
|
83
92
|
const effectiveWidth = rightEdge - leftEdge;
|
|
84
93
|
|
|
85
94
|
const adjustedPosition = Math.max(leftEdge, Math.min(rightEdge, position));
|
|
@@ -109,147 +118,116 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
109
118
|
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
110
119
|
|
|
111
120
|
/**
|
|
112
|
-
*
|
|
121
|
+
* Updates handle and bubble positions and transforms
|
|
113
122
|
*/
|
|
114
|
-
const
|
|
115
|
-
if (!
|
|
123
|
+
const updateHandlePositions = () => {
|
|
124
|
+
if (!handle || !container) return;
|
|
116
125
|
|
|
117
126
|
const dims = getTrackDimensions();
|
|
118
127
|
if (!dims) return;
|
|
119
128
|
|
|
120
|
-
const {
|
|
121
|
-
const edgeConstraint = (thumbSize / 2) / trackSize * 100;
|
|
122
|
-
const adjustedPercent = mapValueToVisualPercent(valuePercent, edgeConstraint);
|
|
129
|
+
const { edgeConstraint } = dims;
|
|
123
130
|
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
// Update main handle position
|
|
132
|
+
const percent = getPercentage(state.value);
|
|
133
|
+
const adjustedPercent = mapValueToVisualPercent(percent, edgeConstraint);
|
|
126
134
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
135
|
+
handle.style.left = `${adjustedPercent}%`;
|
|
136
|
+
handle.style.transform = 'translate(-50%, -50%)';
|
|
137
|
+
if (valueBubble) {
|
|
138
|
+
valueBubble.style.left = `${adjustedPercent}%`;
|
|
139
|
+
valueBubble.style.transform = 'translateX(-50%)';
|
|
130
140
|
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Updates start track styles
|
|
135
|
-
*/
|
|
136
|
-
const updateStartTrack = () => {
|
|
137
|
-
if (!startTrack || !track || !thumb) return;
|
|
138
|
-
|
|
139
|
-
const dims = getTrackDimensions();
|
|
140
|
-
if (!dims) return;
|
|
141
|
-
|
|
142
|
-
const { thumbSize, trackSize, paddingPercent } = dims;
|
|
143
141
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
const edgeConstraint = (thumbSize / 2) / trackSize * 100;
|
|
149
|
-
const adjustedPercent = mapValueToVisualPercent(lowerPercent, edgeConstraint);
|
|
150
|
-
const finalPercent = Math.max(0, adjustedPercent - paddingPercent);
|
|
142
|
+
// Update second handle if range slider
|
|
143
|
+
if (config.range && secondHandle && state.secondValue !== null) {
|
|
144
|
+
const secondPercent = getPercentage(state.secondValue);
|
|
145
|
+
const adjustedSecondPercent = mapValueToVisualPercent(secondPercent, edgeConstraint);
|
|
151
146
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
147
|
+
secondHandle.style.left = `${adjustedSecondPercent}%`;
|
|
148
|
+
secondHandle.style.transform = 'translate(-50%, -50%)';
|
|
149
|
+
if (secondValueBubble) {
|
|
150
|
+
secondValueBubble.style.left = `${adjustedSecondPercent}%`;
|
|
151
|
+
secondValueBubble.style.transform = 'translateX(-50%)';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Update ARIA attributes
|
|
156
|
+
handle.setAttribute('aria-valuenow', String(state.value));
|
|
157
|
+
if (config.range && secondHandle && state.secondValue !== null) {
|
|
158
|
+
secondHandle.setAttribute('aria-valuenow', String(state.secondValue));
|
|
158
159
|
}
|
|
159
160
|
};
|
|
160
|
-
|
|
161
|
+
|
|
161
162
|
/**
|
|
162
|
-
* Updates
|
|
163
|
+
* Updates all track segments at once with optimized positioning
|
|
163
164
|
*/
|
|
164
|
-
const
|
|
165
|
-
if (!
|
|
165
|
+
const updateTrackSegments = () => {
|
|
166
|
+
if (!track || !container || !handle) return;
|
|
166
167
|
|
|
167
168
|
const dims = getTrackDimensions();
|
|
168
169
|
if (!dims) return;
|
|
169
170
|
|
|
170
|
-
const {
|
|
171
|
-
const edgeConstraint = (
|
|
171
|
+
const { handleSize, trackSize, paddingPercent } = dims;
|
|
172
|
+
const edgeConstraint = (handleSize / 2) / trackSize * 100;
|
|
172
173
|
|
|
173
174
|
if (config.range && state.secondValue !== null) {
|
|
174
|
-
// Range slider
|
|
175
|
+
// Range slider setup
|
|
175
176
|
const lowerValue = Math.min(state.value, state.secondValue);
|
|
176
177
|
const higherValue = Math.max(state.value, state.secondValue);
|
|
177
178
|
const lowerPercent = getPercentage(lowerValue);
|
|
178
179
|
const higherPercent = getPercentage(higherValue);
|
|
179
180
|
|
|
180
|
-
const adjustedLower = mapValueToVisualPercent(lowerPercent, edgeConstraint)
|
|
181
|
-
const adjustedHigher = mapValueToVisualPercent(higherPercent, edgeConstraint)
|
|
181
|
+
const adjustedLower = mapValueToVisualPercent(lowerPercent, edgeConstraint);
|
|
182
|
+
const adjustedHigher = mapValueToVisualPercent(higherPercent, edgeConstraint);
|
|
182
183
|
|
|
183
|
-
|
|
184
|
-
if (
|
|
185
|
-
|
|
184
|
+
// Start track (before first handle)
|
|
185
|
+
if (lowerPercent > 1) {
|
|
186
|
+
startTrack.style.display = 'block';
|
|
187
|
+
startTrack.style.left = '0';
|
|
188
|
+
startTrack.style.right = `${100 - (adjustedLower - paddingPercent)}%`;
|
|
189
|
+
startTrack.style.width = 'auto';
|
|
190
|
+
} else {
|
|
191
|
+
startTrack.style.display = 'none';
|
|
186
192
|
}
|
|
187
193
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
194
|
+
// Active track (between handles)
|
|
195
|
+
const valueDiffPercent = Math.abs(higherPercent - lowerPercent);
|
|
196
|
+
const hideThreshold = (handleSize / trackSize) * 100;
|
|
197
|
+
|
|
198
|
+
if (valueDiffPercent <= hideThreshold) {
|
|
199
|
+
activeTrack.style.display = 'none';
|
|
200
|
+
} else {
|
|
201
|
+
activeTrack.style.display = 'block';
|
|
202
|
+
activeTrack.style.left = `${adjustedLower + paddingPercent}%`;
|
|
203
|
+
activeTrack.style.right = `${100 - (adjustedHigher - paddingPercent)}%`;
|
|
204
|
+
activeTrack.style.width = 'auto';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Remaining track (after second handle)
|
|
208
|
+
remainingTrack.style.display = 'block';
|
|
209
|
+
remainingTrack.style.left = `${adjustedHigher + paddingPercent}%`;
|
|
210
|
+
remainingTrack.style.right = '0';
|
|
211
|
+
remainingTrack.style.width = 'auto';
|
|
192
212
|
} else {
|
|
193
|
-
// Single
|
|
213
|
+
// Single handle slider
|
|
194
214
|
const valuePercent = getPercentage(state.value);
|
|
195
215
|
const adjustedPercent = mapValueToVisualPercent(valuePercent, edgeConstraint);
|
|
196
|
-
const adjustedWidth = Math.max(0, adjustedPercent - paddingPercent);
|
|
197
216
|
|
|
217
|
+
// Hide start track for single slider
|
|
218
|
+
startTrack.style.display = 'none';
|
|
219
|
+
|
|
220
|
+
// Active track (filled part)
|
|
198
221
|
activeTrack.style.display = 'block';
|
|
199
|
-
activeTrack.style.width = `${adjustedWidth}%`;
|
|
200
222
|
activeTrack.style.left = '0';
|
|
201
|
-
activeTrack.style.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (!remainingTrack || !track || !thumb) return;
|
|
210
|
-
|
|
211
|
-
const dims = getTrackDimensions();
|
|
212
|
-
if (!dims) return;
|
|
213
|
-
|
|
214
|
-
const { thumbSize, trackSize, paddingPercent } = dims;
|
|
215
|
-
const edgeConstraint = (thumbSize / 2) / trackSize * 100;
|
|
216
|
-
|
|
217
|
-
// Find the highest thumb value
|
|
218
|
-
const highValue = config.range && state.secondValue !== null ?
|
|
219
|
-
Math.max(state.value, state.secondValue) : state.value;
|
|
220
|
-
|
|
221
|
-
const valuePercent = getPercentage(highValue);
|
|
222
|
-
|
|
223
|
-
// Map percentage to visual range
|
|
224
|
-
const adjustedPercent = mapValueToVisualPercent(valuePercent, edgeConstraint) + paddingPercent;
|
|
225
|
-
const remainingSize = Math.max(0, 100 - adjustedPercent);
|
|
226
|
-
|
|
227
|
-
remainingTrack.style.display = 'block';
|
|
228
|
-
remainingTrack.style.width = `${remainingSize}%`;
|
|
229
|
-
remainingTrack.style.left = `${adjustedPercent}%`;
|
|
230
|
-
remainingTrack.style.height = '100%';
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Updates thumb positions
|
|
235
|
-
*/
|
|
236
|
-
const updateThumbPositions = () => {
|
|
237
|
-
if (!thumb) return;
|
|
238
|
-
|
|
239
|
-
// Update main thumb
|
|
240
|
-
const percent = getPercentage(state.value);
|
|
241
|
-
setThumbPosition(thumb, valueBubble, percent);
|
|
242
|
-
|
|
243
|
-
// Update second thumb if range slider
|
|
244
|
-
if (config.range && secondThumb && secondValueBubble && state.secondValue !== null) {
|
|
245
|
-
const secondPercent = getPercentage(state.secondValue);
|
|
246
|
-
setThumbPosition(secondThumb, secondValueBubble, secondPercent);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Update ARIA attributes
|
|
250
|
-
thumb.setAttribute('aria-valuenow', String(state.value));
|
|
251
|
-
if (config.range && secondThumb && state.secondValue !== null) {
|
|
252
|
-
secondThumb.setAttribute('aria-valuenow', String(state.secondValue));
|
|
223
|
+
activeTrack.style.right = `${100 - (adjustedPercent - paddingPercent)}%`;
|
|
224
|
+
activeTrack.style.width = 'auto';
|
|
225
|
+
|
|
226
|
+
// Remaining track (unfilled part)
|
|
227
|
+
remainingTrack.style.display = 'block';
|
|
228
|
+
remainingTrack.style.left = `${adjustedPercent + paddingPercent}%`;
|
|
229
|
+
remainingTrack.style.right = '0';
|
|
230
|
+
remainingTrack.style.width = 'auto';
|
|
253
231
|
}
|
|
254
232
|
};
|
|
255
233
|
|
|
@@ -259,11 +237,9 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
259
237
|
const updateValueBubbles = () => {
|
|
260
238
|
if (!valueBubble) return;
|
|
261
239
|
|
|
262
|
-
// Format the values
|
|
263
240
|
const formatter = config.valueFormatter || (value => value.toString());
|
|
264
|
-
|
|
265
|
-
// Update main and second value bubble if needed
|
|
266
241
|
valueBubble.textContent = formatter(state.value);
|
|
242
|
+
|
|
267
243
|
if (config.range && secondValueBubble && state.secondValue !== null) {
|
|
268
244
|
secondValueBubble.textContent = formatter(state.secondValue);
|
|
269
245
|
}
|
|
@@ -275,42 +251,30 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
275
251
|
const showValueBubble = (bubbleElement, show) => {
|
|
276
252
|
if (!bubbleElement || !config.showValue) return;
|
|
277
253
|
|
|
278
|
-
|
|
279
|
-
bubbleElement.classList[show ? 'add' : 'remove'](visibleClass);
|
|
254
|
+
bubbleElement.classList[show ? 'add' : 'remove'](`${state.component.getClass('slider-value')}--visible`);
|
|
280
255
|
};
|
|
281
256
|
|
|
282
257
|
/**
|
|
283
258
|
* Generates tick marks
|
|
284
259
|
*/
|
|
285
260
|
const generateTicks = () => {
|
|
286
|
-
if (!ticksContainer)
|
|
287
|
-
console.warn('Ticks container not found in component structure');
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
261
|
+
if (!ticksContainer || !container) return;
|
|
290
262
|
|
|
291
263
|
// Clear existing ticks
|
|
292
|
-
const sliderElement = state.component.element;
|
|
293
|
-
sliderElement.querySelectorAll(`.${state.component.getClass('slider-tick')}`)
|
|
294
|
-
.forEach(tick => tick.parentNode.removeChild(tick));
|
|
295
|
-
|
|
296
264
|
while (ticksContainer.firstChild) {
|
|
297
265
|
ticksContainer.removeChild(ticksContainer.firstChild);
|
|
298
266
|
}
|
|
299
267
|
|
|
300
|
-
// Reset ticks array
|
|
301
268
|
state.ticks = [];
|
|
302
|
-
|
|
303
269
|
if (!config.ticks) return;
|
|
304
270
|
|
|
305
|
-
// Generate tick values
|
|
306
271
|
const numSteps = Math.floor((state.max - state.min) / state.step);
|
|
307
272
|
const tickValues = [];
|
|
308
273
|
|
|
274
|
+
// Generate tick values
|
|
309
275
|
for (let i = 0; i <= numSteps; i++) {
|
|
310
276
|
const value = state.min + (i * state.step);
|
|
311
|
-
if (value <= state.max)
|
|
312
|
-
tickValues.push(value);
|
|
313
|
-
}
|
|
277
|
+
if (value <= state.max) tickValues.push(value);
|
|
314
278
|
}
|
|
315
279
|
|
|
316
280
|
// Ensure max value is included
|
|
@@ -319,41 +283,35 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
319
283
|
}
|
|
320
284
|
|
|
321
285
|
// CSS classes
|
|
322
|
-
const activeClass = `${state.component.getClass('slider-tick')}--active`;
|
|
323
|
-
const inactiveClass = `${state.component.getClass('slider-tick')}--inactive`;
|
|
324
|
-
const hiddenClass = `${state.component.getClass('slider-tick')}--hidden`;
|
|
325
286
|
const tickClass = state.component.getClass('slider-tick');
|
|
287
|
+
const activeClass = `${tickClass}--active`;
|
|
288
|
+
const inactiveClass = `${tickClass}--inactive`;
|
|
289
|
+
const hiddenClass = `${tickClass}--hidden`;
|
|
326
290
|
|
|
327
|
-
// Create
|
|
291
|
+
// Create tick elements
|
|
328
292
|
tickValues.forEach(value => {
|
|
329
293
|
const percent = getPercentage(value);
|
|
294
|
+
const tick = document.createElement('div');
|
|
295
|
+
tick.classList.add(tickClass);
|
|
296
|
+
tick.style.left = `${percent}%`;
|
|
330
297
|
|
|
331
|
-
//
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const isExactlySelected = value === state.value ||
|
|
341
|
-
(config.range && state.secondValue !== null && value === state.secondValue);
|
|
342
|
-
|
|
343
|
-
if (isExactlySelected) {
|
|
344
|
-
tick.classList.add(hiddenClass);
|
|
345
|
-
} else if (config.range && state.secondValue !== null) {
|
|
346
|
-
const lowerValue = Math.min(state.value, state.secondValue);
|
|
347
|
-
const higherValue = Math.max(state.value, state.secondValue);
|
|
348
|
-
|
|
349
|
-
tick.classList.add(value >= lowerValue && value <= higherValue ? activeClass : inactiveClass);
|
|
350
|
-
} else {
|
|
351
|
-
tick.classList.add(value <= state.value ? activeClass : inactiveClass);
|
|
352
|
-
}
|
|
298
|
+
// Determine tick active state
|
|
299
|
+
const isExactlySelected = (value === state.value ||
|
|
300
|
+
(config.range && state.secondValue !== null && value === state.secondValue));
|
|
301
|
+
|
|
302
|
+
if (isExactlySelected) {
|
|
303
|
+
tick.classList.add(hiddenClass);
|
|
304
|
+
} else if (config.range && state.secondValue !== null) {
|
|
305
|
+
const lowerValue = Math.min(state.value, state.secondValue);
|
|
306
|
+
const higherValue = Math.max(state.value, state.secondValue);
|
|
353
307
|
|
|
354
|
-
|
|
355
|
-
|
|
308
|
+
tick.classList.add(value >= lowerValue && value <= higherValue ? activeClass : inactiveClass);
|
|
309
|
+
} else {
|
|
310
|
+
tick.classList.add(value <= state.value ? activeClass : inactiveClass);
|
|
356
311
|
}
|
|
312
|
+
|
|
313
|
+
ticksContainer.appendChild(tick);
|
|
314
|
+
state.ticks.push(tick);
|
|
357
315
|
});
|
|
358
316
|
};
|
|
359
317
|
|
|
@@ -363,24 +321,23 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
363
321
|
const updateTicks = () => {
|
|
364
322
|
if (!state.ticks || state.ticks.length === 0) return;
|
|
365
323
|
|
|
366
|
-
const
|
|
367
|
-
const
|
|
368
|
-
const
|
|
324
|
+
const tickClass = state.component.getClass('slider-tick');
|
|
325
|
+
const activeClass = `${tickClass}--active`;
|
|
326
|
+
const inactiveClass = `${tickClass}--inactive`;
|
|
327
|
+
const hiddenClass = `${tickClass}--hidden`;
|
|
369
328
|
|
|
370
|
-
// Update active ticks based on current value
|
|
371
329
|
state.ticks.forEach((tick, index) => {
|
|
372
|
-
// Calculate the value for this tick
|
|
330
|
+
// Calculate the value for this tick
|
|
373
331
|
const tickValue = state.min + (index * state.step);
|
|
374
332
|
|
|
375
|
-
//
|
|
333
|
+
// Reset visibility first
|
|
376
334
|
tick.classList.remove(hiddenClass);
|
|
377
335
|
|
|
378
336
|
// Check if this tick should be hidden (matches exactly a selected value)
|
|
379
|
-
const isExactlySelected = tickValue === state.value ||
|
|
380
|
-
|
|
337
|
+
const isExactlySelected = (tickValue === state.value ||
|
|
338
|
+
(config.range && state.secondValue !== null && tickValue === state.secondValue));
|
|
381
339
|
|
|
382
340
|
if (isExactlySelected) {
|
|
383
|
-
// Hide this tick as it exactly matches a selected value
|
|
384
341
|
tick.classList.add(hiddenClass);
|
|
385
342
|
} else if (config.range && state.secondValue !== null) {
|
|
386
343
|
// Range slider - ticks between values should be active
|
|
@@ -411,29 +368,21 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
411
368
|
* Updates all UI elements
|
|
412
369
|
*/
|
|
413
370
|
const updateUi = () => {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
updateActiveTrack();
|
|
417
|
-
updateRemainingTrack();
|
|
371
|
+
updateHandlePositions();
|
|
372
|
+
updateTrackSegments();
|
|
418
373
|
updateValueBubbles();
|
|
419
374
|
updateTicks();
|
|
420
375
|
};
|
|
421
376
|
|
|
422
|
-
// Return helper methods
|
|
377
|
+
// Return consolidated helper methods
|
|
423
378
|
return {
|
|
424
379
|
getPercentage,
|
|
425
380
|
getValueFromPosition,
|
|
426
381
|
roundToStep,
|
|
427
382
|
clamp,
|
|
428
|
-
setThumbPosition,
|
|
429
|
-
updateActiveTrack,
|
|
430
|
-
updateStartTrack,
|
|
431
|
-
updateRemainingTrack,
|
|
432
|
-
updateThumbPositions,
|
|
433
|
-
updateValueBubbles,
|
|
434
383
|
showValueBubble,
|
|
435
384
|
generateTicks,
|
|
436
385
|
updateTicks,
|
|
437
386
|
updateUi
|
|
438
387
|
};
|
|
439
|
-
}
|
|
388
|
+
}
|
|
@@ -4,16 +4,7 @@
|
|
|
4
4
|
export { default } from './slider';
|
|
5
5
|
|
|
6
6
|
// Export constants
|
|
7
|
-
export {
|
|
8
|
-
SLIDER_COLORS,
|
|
9
|
-
SLIDER_SIZES,
|
|
10
|
-
SLIDER_ORIENTATIONS,
|
|
11
|
-
SLIDER_EVENTS
|
|
12
|
-
} from './constants';
|
|
7
|
+
export { SLIDER_COLORS, SLIDER_SIZES, SLIDER_EVENTS } from './constants';
|
|
13
8
|
|
|
14
9
|
// Export types for TypeScript users
|
|
15
|
-
export type {
|
|
16
|
-
SliderConfig,
|
|
17
|
-
SliderComponent,
|
|
18
|
-
SliderEvent
|
|
19
|
-
} from './types';
|
|
10
|
+
export type { SliderConfig, SliderComponent, SliderEvent } from './types';
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
// src/components/slider/slider.ts
|
|
2
2
|
import { pipe } from '../../core/compose/pipe';
|
|
3
3
|
import { createBase, withElement } from '../../core/compose/component';
|
|
4
|
-
import { withEvents, withLifecycle } from '../../core/compose/features';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
withDisabled,
|
|
8
|
-
withAppearance,
|
|
9
|
-
withSlider
|
|
10
|
-
} from './features';
|
|
4
|
+
import { withEvents, withLifecycle, withTextLabel, withIcon } from '../../core/compose/features';
|
|
5
|
+
import { withStructure, withSlider } from './features';
|
|
6
|
+
import { withStates } from './features/states';
|
|
11
7
|
import { withAPI } from './api';
|
|
12
8
|
import { SliderConfig, SliderComponent } from './types';
|
|
13
9
|
import { createBaseConfig, getElementConfig, getApiConfig } from './config';
|
|
@@ -21,22 +17,23 @@ const createSlider = (config: SliderConfig = {}): SliderComponent => {
|
|
|
21
17
|
const baseConfig = createBaseConfig(config);
|
|
22
18
|
|
|
23
19
|
try {
|
|
24
|
-
//
|
|
20
|
+
// Create the component with all required features
|
|
25
21
|
const component = pipe(
|
|
26
22
|
createBase,
|
|
27
23
|
withEvents(),
|
|
28
24
|
withElement(getElementConfig(baseConfig)),
|
|
25
|
+
withIcon(baseConfig),
|
|
26
|
+
withTextLabel(baseConfig),
|
|
29
27
|
withStructure(baseConfig),
|
|
30
|
-
|
|
31
|
-
withAppearance(baseConfig),
|
|
28
|
+
withStates(baseConfig),
|
|
32
29
|
withSlider(baseConfig),
|
|
33
30
|
withLifecycle()
|
|
34
31
|
)(baseConfig);
|
|
35
32
|
|
|
36
|
-
//
|
|
33
|
+
// Generate the API configuration
|
|
37
34
|
const apiOptions = getApiConfig(component);
|
|
38
35
|
|
|
39
|
-
//
|
|
36
|
+
// Apply the API layer
|
|
40
37
|
const slider = withAPI(apiOptions)(component);
|
|
41
38
|
|
|
42
39
|
// Register event handlers from config
|