mtrl 0.2.6 → 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 +117 -109
- 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 -10
- package/src/components/button/api.ts +5 -0
- package/src/components/button/config.ts +5 -0
- package/src/components/button/types.ts +6 -0
- package/src/components/card/card.ts +13 -25
- package/src/components/card/config.ts +67 -22
- package/src/components/card/features.ts +3 -0
- package/src/components/card/types.ts +28 -0
- package/src/components/checkbox/_styles.scss +0 -2
- 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/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 +83 -24
- 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 +39 -24
- package/src/components/switch/_styles.scss +0 -2
- package/src/components/tabs/_styles.scss +94 -32
- package/src/components/tabs/features.ts +4 -2
- package/src/components/tabs/indicator.ts +73 -13
- package/src/components/tabs/types.ts +10 -2
- 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/features/icon.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 +9 -1
- 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/navigation/features/items.js +0 -192
- 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/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,157 +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
|
-
|
|
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';
|
|
192
|
+
}
|
|
185
193
|
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
const hideThreshold = (
|
|
194
|
+
// Active track (between handles)
|
|
195
|
+
const valueDiffPercent = Math.abs(higherPercent - lowerPercent);
|
|
196
|
+
const hideThreshold = (handleSize / trackSize) * 100;
|
|
189
197
|
|
|
190
198
|
if (valueDiffPercent <= hideThreshold) {
|
|
191
|
-
// Thumbs are too close together, hide the active track
|
|
192
199
|
activeTrack.style.display = 'none';
|
|
193
200
|
} else {
|
|
194
|
-
// Normal display of active track
|
|
195
|
-
let trackLength = Math.max(0, adjustedHigher - adjustedLower);
|
|
196
|
-
|
|
197
201
|
activeTrack.style.display = 'block';
|
|
198
|
-
activeTrack.style.
|
|
199
|
-
activeTrack.style.
|
|
200
|
-
activeTrack.style.
|
|
202
|
+
activeTrack.style.left = `${adjustedLower + paddingPercent}%`;
|
|
203
|
+
activeTrack.style.right = `${100 - (adjustedHigher - paddingPercent)}%`;
|
|
204
|
+
activeTrack.style.width = 'auto';
|
|
201
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';
|
|
202
212
|
} else {
|
|
203
|
-
// Single
|
|
213
|
+
// Single handle slider
|
|
204
214
|
const valuePercent = getPercentage(state.value);
|
|
205
215
|
const adjustedPercent = mapValueToVisualPercent(valuePercent, edgeConstraint);
|
|
206
|
-
const adjustedWidth = Math.max(0, adjustedPercent - paddingPercent);
|
|
207
216
|
|
|
217
|
+
// Hide start track for single slider
|
|
218
|
+
startTrack.style.display = 'none';
|
|
219
|
+
|
|
220
|
+
// Active track (filled part)
|
|
208
221
|
activeTrack.style.display = 'block';
|
|
209
|
-
activeTrack.style.width = `${adjustedWidth}%`;
|
|
210
222
|
activeTrack.style.left = '0';
|
|
211
|
-
activeTrack.style.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!remainingTrack || !track || !thumb) return;
|
|
220
|
-
|
|
221
|
-
const dims = getTrackDimensions();
|
|
222
|
-
if (!dims) return;
|
|
223
|
-
|
|
224
|
-
const { thumbSize, trackSize, paddingPercent } = dims;
|
|
225
|
-
const edgeConstraint = (thumbSize / 2) / trackSize * 100;
|
|
226
|
-
|
|
227
|
-
// Find the highest thumb value
|
|
228
|
-
const highValue = config.range && state.secondValue !== null ?
|
|
229
|
-
Math.max(state.value, state.secondValue) : state.value;
|
|
230
|
-
|
|
231
|
-
const valuePercent = getPercentage(highValue);
|
|
232
|
-
|
|
233
|
-
// Map percentage to visual range
|
|
234
|
-
const adjustedPercent = mapValueToVisualPercent(valuePercent, edgeConstraint) + paddingPercent;
|
|
235
|
-
const remainingSize = Math.max(0, 100 - adjustedPercent);
|
|
236
|
-
|
|
237
|
-
remainingTrack.style.display = 'block';
|
|
238
|
-
remainingTrack.style.width = `${remainingSize}%`;
|
|
239
|
-
remainingTrack.style.left = `${adjustedPercent}%`;
|
|
240
|
-
remainingTrack.style.height = '100%';
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Updates thumb positions
|
|
245
|
-
*/
|
|
246
|
-
const updateThumbPositions = () => {
|
|
247
|
-
if (!thumb) return;
|
|
248
|
-
|
|
249
|
-
// Update main thumb
|
|
250
|
-
const percent = getPercentage(state.value);
|
|
251
|
-
setThumbPosition(thumb, valueBubble, percent);
|
|
252
|
-
|
|
253
|
-
// Update second thumb if range slider
|
|
254
|
-
if (config.range && secondThumb && secondValueBubble && state.secondValue !== null) {
|
|
255
|
-
const secondPercent = getPercentage(state.secondValue);
|
|
256
|
-
setThumbPosition(secondThumb, secondValueBubble, secondPercent);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Update ARIA attributes
|
|
260
|
-
thumb.setAttribute('aria-valuenow', String(state.value));
|
|
261
|
-
if (config.range && secondThumb && state.secondValue !== null) {
|
|
262
|
-
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';
|
|
263
231
|
}
|
|
264
232
|
};
|
|
265
233
|
|
|
@@ -269,11 +237,9 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
269
237
|
const updateValueBubbles = () => {
|
|
270
238
|
if (!valueBubble) return;
|
|
271
239
|
|
|
272
|
-
// Format the values
|
|
273
240
|
const formatter = config.valueFormatter || (value => value.toString());
|
|
274
|
-
|
|
275
|
-
// Update main and second value bubble if needed
|
|
276
241
|
valueBubble.textContent = formatter(state.value);
|
|
242
|
+
|
|
277
243
|
if (config.range && secondValueBubble && state.secondValue !== null) {
|
|
278
244
|
secondValueBubble.textContent = formatter(state.secondValue);
|
|
279
245
|
}
|
|
@@ -285,42 +251,30 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
285
251
|
const showValueBubble = (bubbleElement, show) => {
|
|
286
252
|
if (!bubbleElement || !config.showValue) return;
|
|
287
253
|
|
|
288
|
-
|
|
289
|
-
bubbleElement.classList[show ? 'add' : 'remove'](visibleClass);
|
|
254
|
+
bubbleElement.classList[show ? 'add' : 'remove'](`${state.component.getClass('slider-value')}--visible`);
|
|
290
255
|
};
|
|
291
256
|
|
|
292
257
|
/**
|
|
293
258
|
* Generates tick marks
|
|
294
259
|
*/
|
|
295
260
|
const generateTicks = () => {
|
|
296
|
-
if (!ticksContainer)
|
|
297
|
-
console.warn('Ticks container not found in component structure');
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
261
|
+
if (!ticksContainer || !container) return;
|
|
300
262
|
|
|
301
263
|
// Clear existing ticks
|
|
302
|
-
const sliderElement = state.component.element;
|
|
303
|
-
sliderElement.querySelectorAll(`.${state.component.getClass('slider-tick')}`)
|
|
304
|
-
.forEach(tick => tick.parentNode.removeChild(tick));
|
|
305
|
-
|
|
306
264
|
while (ticksContainer.firstChild) {
|
|
307
265
|
ticksContainer.removeChild(ticksContainer.firstChild);
|
|
308
266
|
}
|
|
309
267
|
|
|
310
|
-
// Reset ticks array
|
|
311
268
|
state.ticks = [];
|
|
312
|
-
|
|
313
269
|
if (!config.ticks) return;
|
|
314
270
|
|
|
315
|
-
// Generate tick values
|
|
316
271
|
const numSteps = Math.floor((state.max - state.min) / state.step);
|
|
317
272
|
const tickValues = [];
|
|
318
273
|
|
|
274
|
+
// Generate tick values
|
|
319
275
|
for (let i = 0; i <= numSteps; i++) {
|
|
320
276
|
const value = state.min + (i * state.step);
|
|
321
|
-
if (value <= state.max)
|
|
322
|
-
tickValues.push(value);
|
|
323
|
-
}
|
|
277
|
+
if (value <= state.max) tickValues.push(value);
|
|
324
278
|
}
|
|
325
279
|
|
|
326
280
|
// Ensure max value is included
|
|
@@ -329,41 +283,35 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
329
283
|
}
|
|
330
284
|
|
|
331
285
|
// CSS classes
|
|
332
|
-
const activeClass = `${state.component.getClass('slider-tick')}--active`;
|
|
333
|
-
const inactiveClass = `${state.component.getClass('slider-tick')}--inactive`;
|
|
334
|
-
const hiddenClass = `${state.component.getClass('slider-tick')}--hidden`;
|
|
335
286
|
const tickClass = state.component.getClass('slider-tick');
|
|
287
|
+
const activeClass = `${tickClass}--active`;
|
|
288
|
+
const inactiveClass = `${tickClass}--inactive`;
|
|
289
|
+
const hiddenClass = `${tickClass}--hidden`;
|
|
336
290
|
|
|
337
|
-
// Create
|
|
291
|
+
// Create tick elements
|
|
338
292
|
tickValues.forEach(value => {
|
|
339
293
|
const percent = getPercentage(value);
|
|
294
|
+
const tick = document.createElement('div');
|
|
295
|
+
tick.classList.add(tickClass);
|
|
296
|
+
tick.style.left = `${percent}%`;
|
|
340
297
|
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const isExactlySelected = value === state.value ||
|
|
351
|
-
(config.range && state.secondValue !== null && value === state.secondValue);
|
|
352
|
-
|
|
353
|
-
if (isExactlySelected) {
|
|
354
|
-
tick.classList.add(hiddenClass);
|
|
355
|
-
} else if (config.range && state.secondValue !== null) {
|
|
356
|
-
const lowerValue = Math.min(state.value, state.secondValue);
|
|
357
|
-
const higherValue = Math.max(state.value, state.secondValue);
|
|
358
|
-
|
|
359
|
-
tick.classList.add(value >= lowerValue && value <= higherValue ? activeClass : inactiveClass);
|
|
360
|
-
} else {
|
|
361
|
-
tick.classList.add(value <= state.value ? activeClass : inactiveClass);
|
|
362
|
-
}
|
|
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);
|
|
363
307
|
|
|
364
|
-
|
|
365
|
-
|
|
308
|
+
tick.classList.add(value >= lowerValue && value <= higherValue ? activeClass : inactiveClass);
|
|
309
|
+
} else {
|
|
310
|
+
tick.classList.add(value <= state.value ? activeClass : inactiveClass);
|
|
366
311
|
}
|
|
312
|
+
|
|
313
|
+
ticksContainer.appendChild(tick);
|
|
314
|
+
state.ticks.push(tick);
|
|
367
315
|
});
|
|
368
316
|
};
|
|
369
317
|
|
|
@@ -373,24 +321,23 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
373
321
|
const updateTicks = () => {
|
|
374
322
|
if (!state.ticks || state.ticks.length === 0) return;
|
|
375
323
|
|
|
376
|
-
const
|
|
377
|
-
const
|
|
378
|
-
const
|
|
324
|
+
const tickClass = state.component.getClass('slider-tick');
|
|
325
|
+
const activeClass = `${tickClass}--active`;
|
|
326
|
+
const inactiveClass = `${tickClass}--inactive`;
|
|
327
|
+
const hiddenClass = `${tickClass}--hidden`;
|
|
379
328
|
|
|
380
|
-
// Update active ticks based on current value
|
|
381
329
|
state.ticks.forEach((tick, index) => {
|
|
382
|
-
// Calculate the value for this tick
|
|
330
|
+
// Calculate the value for this tick
|
|
383
331
|
const tickValue = state.min + (index * state.step);
|
|
384
332
|
|
|
385
|
-
//
|
|
333
|
+
// Reset visibility first
|
|
386
334
|
tick.classList.remove(hiddenClass);
|
|
387
335
|
|
|
388
336
|
// Check if this tick should be hidden (matches exactly a selected value)
|
|
389
|
-
const isExactlySelected = tickValue === state.value ||
|
|
390
|
-
|
|
337
|
+
const isExactlySelected = (tickValue === state.value ||
|
|
338
|
+
(config.range && state.secondValue !== null && tickValue === state.secondValue));
|
|
391
339
|
|
|
392
340
|
if (isExactlySelected) {
|
|
393
|
-
// Hide this tick as it exactly matches a selected value
|
|
394
341
|
tick.classList.add(hiddenClass);
|
|
395
342
|
} else if (config.range && state.secondValue !== null) {
|
|
396
343
|
// Range slider - ticks between values should be active
|
|
@@ -421,29 +368,21 @@ export const createUiHelpers = (config: SliderConfig, state) => {
|
|
|
421
368
|
* Updates all UI elements
|
|
422
369
|
*/
|
|
423
370
|
const updateUi = () => {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
updateActiveTrack();
|
|
427
|
-
updateRemainingTrack();
|
|
371
|
+
updateHandlePositions();
|
|
372
|
+
updateTrackSegments();
|
|
428
373
|
updateValueBubbles();
|
|
429
374
|
updateTicks();
|
|
430
375
|
};
|
|
431
376
|
|
|
432
|
-
// Return helper methods
|
|
377
|
+
// Return consolidated helper methods
|
|
433
378
|
return {
|
|
434
379
|
getPercentage,
|
|
435
380
|
getValueFromPosition,
|
|
436
381
|
roundToStep,
|
|
437
382
|
clamp,
|
|
438
|
-
setThumbPosition,
|
|
439
|
-
updateActiveTrack,
|
|
440
|
-
updateStartTrack,
|
|
441
|
-
updateRemainingTrack,
|
|
442
|
-
updateThumbPositions,
|
|
443
|
-
updateValueBubbles,
|
|
444
383
|
showValueBubble,
|
|
445
384
|
generateTicks,
|
|
446
385
|
updateTicks,
|
|
447
386
|
updateUi
|
|
448
387
|
};
|
|
449
|
-
}
|
|
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
|