mtrl 0.2.2 → 0.2.3
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/.typedocignore +11 -0
- package/DOCS.md +153 -0
- package/index.ts +18 -3
- package/package.json +7 -2
- package/src/components/badge/_styles.scss +174 -0
- package/src/components/badge/api.ts +292 -0
- package/src/components/badge/badge.ts +52 -0
- package/src/components/badge/config.ts +68 -0
- package/src/components/badge/constants.ts +30 -0
- package/src/components/badge/features.ts +185 -0
- package/src/components/badge/index.ts +4 -0
- package/src/components/badge/types.ts +105 -0
- package/src/components/button/types.ts +174 -29
- package/src/components/carousel/_styles.scss +645 -0
- package/src/components/carousel/api.ts +147 -0
- package/src/components/carousel/carousel.ts +178 -0
- package/src/components/carousel/config.ts +91 -0
- package/src/components/carousel/constants.ts +95 -0
- package/src/components/carousel/features/drag.ts +388 -0
- package/src/components/carousel/features/index.ts +8 -0
- package/src/components/carousel/features/slides.ts +682 -0
- package/src/components/carousel/index.ts +38 -0
- package/src/components/carousel/types.ts +327 -0
- package/src/components/dialog/_styles.scss +213 -0
- package/src/components/dialog/api.ts +283 -0
- package/src/components/dialog/config.ts +113 -0
- package/src/components/dialog/constants.ts +32 -0
- package/src/components/dialog/dialog.ts +56 -0
- package/src/components/dialog/features.ts +713 -0
- package/src/components/dialog/index.ts +15 -0
- package/src/components/dialog/types.ts +221 -0
- package/src/components/progress/_styles.scss +13 -1
- package/src/components/progress/api.ts +2 -2
- package/src/components/progress/progress.ts +2 -2
- package/src/components/progress/types.ts +3 -0
- package/src/components/radios/_styles.scss +232 -0
- package/src/components/radios/api.ts +100 -0
- package/src/components/radios/config.ts +60 -0
- package/src/components/radios/constants.ts +28 -0
- package/src/components/radios/index.ts +4 -0
- package/src/components/radios/radio.ts +269 -0
- package/src/components/radios/radios.ts +42 -0
- package/src/components/radios/types.ts +232 -0
- package/src/components/sheet/_styles.scss +236 -0
- package/src/components/sheet/api.ts +96 -0
- package/src/components/sheet/config.ts +66 -0
- package/src/components/sheet/constants.ts +20 -0
- package/src/components/sheet/features/content.ts +51 -0
- package/src/components/sheet/features/gestures.ts +177 -0
- package/src/components/sheet/features/index.ts +6 -0
- package/src/components/sheet/features/position.ts +42 -0
- package/src/components/sheet/features/state.ts +116 -0
- package/src/components/sheet/features/title.ts +86 -0
- package/src/components/sheet/index.ts +4 -0
- package/src/components/sheet/sheet.ts +57 -0
- package/src/components/sheet/types.ts +266 -0
- package/src/components/slider/_styles.scss +518 -0
- package/src/components/slider/api.ts +336 -0
- package/src/components/slider/config.ts +145 -0
- package/src/components/slider/constants.ts +28 -0
- package/src/components/slider/features/appearance.ts +140 -0
- package/src/components/slider/features/disabled.ts +43 -0
- package/src/components/slider/features/events.ts +164 -0
- package/src/components/slider/features/index.ts +5 -0
- package/src/components/slider/features/interactions.ts +256 -0
- package/src/components/slider/features/keyboard.ts +114 -0
- package/src/components/slider/features/slider.ts +336 -0
- package/src/components/slider/features/structure.ts +264 -0
- package/src/components/slider/features/ui.ts +518 -0
- package/src/components/slider/index.ts +9 -0
- package/src/components/slider/slider.ts +58 -0
- package/src/components/slider/types.ts +166 -0
- package/src/components/tabs/_styles.scss +224 -0
- package/src/components/tabs/api.ts +443 -0
- package/src/components/tabs/config.ts +80 -0
- package/src/components/tabs/constants.ts +12 -0
- package/src/components/tabs/index.ts +4 -0
- package/src/components/tabs/tabs.ts +52 -0
- package/src/components/tabs/types.ts +247 -0
- package/src/components/textfield/_styles.scss +97 -4
- package/src/components/tooltip/_styles.scss +241 -0
- package/src/components/tooltip/api.ts +411 -0
- package/src/components/tooltip/config.ts +78 -0
- package/src/components/tooltip/constants.ts +27 -0
- package/src/components/tooltip/index.ts +4 -0
- package/src/components/tooltip/tooltip.ts +60 -0
- package/src/components/tooltip/types.ts +178 -0
- package/src/index.ts +9 -1
- package/src/styles/abstract/_variables.scss +24 -12
- package/tsconfig.json +22 -0
- package/typedoc.json +28 -0
- package/typedoc.simple.json +14 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
// src/components/slider/api.ts
|
|
2
|
+
import { SliderComponent, SliderEvent } from './types';
|
|
3
|
+
import { SLIDER_COLORS, SLIDER_SIZES, SLIDER_ORIENTATIONS, SLIDER_EVENTS } from './constants';
|
|
4
|
+
|
|
5
|
+
interface ApiOptions {
|
|
6
|
+
slider: {
|
|
7
|
+
setValue: (value: number, triggerEvent?: boolean) => any;
|
|
8
|
+
getValue: () => number;
|
|
9
|
+
setSecondValue: (value: number, triggerEvent?: boolean) => any;
|
|
10
|
+
getSecondValue: () => number | null;
|
|
11
|
+
setMin: (min: number) => any;
|
|
12
|
+
getMin: () => number;
|
|
13
|
+
setMax: (max: number) => any;
|
|
14
|
+
getMax: () => number;
|
|
15
|
+
setStep: (step: number) => any;
|
|
16
|
+
getStep: () => number;
|
|
17
|
+
regenerateTicks: () => any;
|
|
18
|
+
};
|
|
19
|
+
disabled: {
|
|
20
|
+
enable: () => void;
|
|
21
|
+
disable: () => void;
|
|
22
|
+
isDisabled: () => boolean;
|
|
23
|
+
};
|
|
24
|
+
appearance: {
|
|
25
|
+
setColor: (color: string) => void;
|
|
26
|
+
getColor: () => string;
|
|
27
|
+
setSize: (size: string) => void;
|
|
28
|
+
getSize: () => string;
|
|
29
|
+
setOrientation: (orientation: string) => void;
|
|
30
|
+
getOrientation: () => string;
|
|
31
|
+
showTicks: (show: boolean) => void;
|
|
32
|
+
showTickLabels: (show: boolean | string[]) => void;
|
|
33
|
+
showCurrentValue: (show: boolean) => void;
|
|
34
|
+
};
|
|
35
|
+
events: {
|
|
36
|
+
on: (event: string, handler: Function) => void;
|
|
37
|
+
off: (event: string, handler: Function) => void;
|
|
38
|
+
};
|
|
39
|
+
lifecycle: {
|
|
40
|
+
destroy: () => void;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ComponentWithElements {
|
|
45
|
+
element: HTMLElement;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Enhances a slider component with API methods
|
|
50
|
+
* @param {ApiOptions} options - API configuration options
|
|
51
|
+
* @returns {Function} Higher-order function that adds API methods to component
|
|
52
|
+
* @internal This is an internal utility for the Slider component
|
|
53
|
+
*/
|
|
54
|
+
export const withAPI = (options: ApiOptions) =>
|
|
55
|
+
(component: ComponentWithElements): SliderComponent => {
|
|
56
|
+
// Make sure options is defined with fallbacks
|
|
57
|
+
const safeOptions: ApiOptions = options || {
|
|
58
|
+
slider: {
|
|
59
|
+
setValue: () => {},
|
|
60
|
+
getValue: () => 0,
|
|
61
|
+
setSecondValue: () => {},
|
|
62
|
+
getSecondValue: () => null,
|
|
63
|
+
setMin: () => {},
|
|
64
|
+
getMin: () => 0,
|
|
65
|
+
setMax: () => {},
|
|
66
|
+
getMax: () => 100,
|
|
67
|
+
setStep: () => {},
|
|
68
|
+
getStep: () => 1,
|
|
69
|
+
regenerateTicks: () => {}
|
|
70
|
+
},
|
|
71
|
+
disabled: {
|
|
72
|
+
enable: () => {},
|
|
73
|
+
disable: () => {},
|
|
74
|
+
isDisabled: () => false
|
|
75
|
+
},
|
|
76
|
+
appearance: {
|
|
77
|
+
setColor: () => {},
|
|
78
|
+
getColor: () => 'primary',
|
|
79
|
+
setSize: () => {},
|
|
80
|
+
getSize: () => 'medium',
|
|
81
|
+
setOrientation: () => {},
|
|
82
|
+
getOrientation: () => 'horizontal',
|
|
83
|
+
showTicks: () => {},
|
|
84
|
+
showTickLabels: () => {},
|
|
85
|
+
showCurrentValue: () => {}
|
|
86
|
+
},
|
|
87
|
+
events: {
|
|
88
|
+
on: () => {},
|
|
89
|
+
off: () => {}
|
|
90
|
+
},
|
|
91
|
+
lifecycle: {
|
|
92
|
+
destroy: () => {}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
...component as any,
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Sets slider value
|
|
101
|
+
* @param {number} value - New slider value
|
|
102
|
+
* @param {boolean} [triggerEvent=true] - Whether to trigger change event
|
|
103
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
104
|
+
*/
|
|
105
|
+
setValue(value: number, triggerEvent: boolean = true) {
|
|
106
|
+
safeOptions.slider.setValue(value, triggerEvent);
|
|
107
|
+
return this;
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Gets slider value
|
|
112
|
+
* @returns {number} Current slider value
|
|
113
|
+
*/
|
|
114
|
+
getValue() {
|
|
115
|
+
return safeOptions.slider.getValue();
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sets secondary slider value (for range slider)
|
|
120
|
+
* @param {number} value - New secondary value
|
|
121
|
+
* @param {boolean} [triggerEvent=true] - Whether to trigger change event
|
|
122
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
123
|
+
*/
|
|
124
|
+
setSecondValue(value: number, triggerEvent: boolean = true) {
|
|
125
|
+
safeOptions.slider.setSecondValue(value, triggerEvent);
|
|
126
|
+
return this;
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Gets secondary slider value
|
|
131
|
+
* @returns {number|null} Current secondary value or null
|
|
132
|
+
*/
|
|
133
|
+
getSecondValue() {
|
|
134
|
+
return safeOptions.slider.getSecondValue();
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Sets slider minimum value
|
|
139
|
+
* @param {number} min - New minimum value
|
|
140
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
141
|
+
*/
|
|
142
|
+
setMin(min: number) {
|
|
143
|
+
safeOptions.slider.setMin(min);
|
|
144
|
+
return this;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Gets slider minimum value
|
|
149
|
+
* @returns {number} Current minimum value
|
|
150
|
+
*/
|
|
151
|
+
getMin() {
|
|
152
|
+
return safeOptions.slider.getMin();
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sets slider maximum value
|
|
157
|
+
* @param {number} max - New maximum value
|
|
158
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
159
|
+
*/
|
|
160
|
+
setMax(max: number) {
|
|
161
|
+
safeOptions.slider.setMax(max);
|
|
162
|
+
return this;
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Gets slider maximum value
|
|
167
|
+
* @returns {number} Current maximum value
|
|
168
|
+
*/
|
|
169
|
+
getMax() {
|
|
170
|
+
return safeOptions.slider.getMax();
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Sets slider step size
|
|
175
|
+
* @param {number} step - New step size
|
|
176
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
177
|
+
*/
|
|
178
|
+
setStep(step: number) {
|
|
179
|
+
safeOptions.slider.setStep(step);
|
|
180
|
+
return this;
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Gets slider step size
|
|
185
|
+
* @returns {number} Current step size
|
|
186
|
+
*/
|
|
187
|
+
getStep() {
|
|
188
|
+
return safeOptions.slider.getStep();
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Enables the slider
|
|
193
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
194
|
+
*/
|
|
195
|
+
enable() {
|
|
196
|
+
safeOptions.disabled.enable();
|
|
197
|
+
return this;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Disables the slider
|
|
202
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
203
|
+
*/
|
|
204
|
+
disable() {
|
|
205
|
+
safeOptions.disabled.disable();
|
|
206
|
+
return this;
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Checks if slider is disabled
|
|
211
|
+
* @returns {boolean} True if slider is disabled
|
|
212
|
+
*/
|
|
213
|
+
isDisabled() {
|
|
214
|
+
return safeOptions.disabled.isDisabled();
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Sets slider color
|
|
219
|
+
* @param {string} color - Color variant
|
|
220
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
221
|
+
*/
|
|
222
|
+
setColor(color: keyof typeof SLIDER_COLORS | SLIDER_COLORS) {
|
|
223
|
+
safeOptions.appearance.setColor(color);
|
|
224
|
+
return this;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Gets slider color
|
|
229
|
+
* @returns {string} Current color name
|
|
230
|
+
*/
|
|
231
|
+
getColor() {
|
|
232
|
+
return safeOptions.appearance.getColor();
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Sets slider size
|
|
237
|
+
* @param {string} size - Size variant
|
|
238
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
239
|
+
*/
|
|
240
|
+
setSize(size: keyof typeof SLIDER_SIZES | SLIDER_SIZES) {
|
|
241
|
+
safeOptions.appearance.setSize(size);
|
|
242
|
+
return this;
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Gets slider size
|
|
247
|
+
* @returns {string} Current size name
|
|
248
|
+
*/
|
|
249
|
+
getSize() {
|
|
250
|
+
return safeOptions.appearance.getSize();
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Sets slider orientation
|
|
255
|
+
* @param {string} orientation - Orientation variant
|
|
256
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
257
|
+
*/
|
|
258
|
+
setOrientation(orientation: keyof typeof SLIDER_ORIENTATIONS | SLIDER_ORIENTATIONS) {
|
|
259
|
+
safeOptions.appearance.setOrientation(orientation);
|
|
260
|
+
return this;
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Gets slider orientation
|
|
265
|
+
* @returns {string} Current orientation name
|
|
266
|
+
*/
|
|
267
|
+
getOrientation() {
|
|
268
|
+
return safeOptions.appearance.getOrientation();
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Shows or hides tick marks
|
|
273
|
+
* @param {boolean} show - Whether to show ticks
|
|
274
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
275
|
+
*/
|
|
276
|
+
showTicks(show: boolean) {
|
|
277
|
+
safeOptions.appearance.showTicks(show);
|
|
278
|
+
return this;
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Shows or hides tick labels
|
|
283
|
+
* @param {boolean|string[]} show - Whether to show labels or array of label texts
|
|
284
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
285
|
+
*/
|
|
286
|
+
showTickLabels(show: boolean | string[]) {
|
|
287
|
+
safeOptions.appearance.showTickLabels(show);
|
|
288
|
+
return this;
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Shows or hides current value while dragging
|
|
293
|
+
* @param {boolean} show - Whether to show value bubble
|
|
294
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
295
|
+
*/
|
|
296
|
+
showCurrentValue(show: boolean) {
|
|
297
|
+
safeOptions.appearance.showCurrentValue(show);
|
|
298
|
+
return this;
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Adds event listener
|
|
303
|
+
* @param {string} event - Event name
|
|
304
|
+
* @param {Function} handler - Event handler
|
|
305
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
306
|
+
*/
|
|
307
|
+
on(event: keyof typeof SLIDER_EVENTS | SLIDER_EVENTS, handler: (event: SliderEvent) => void) {
|
|
308
|
+
if (safeOptions.events && typeof safeOptions.events.on === 'function') {
|
|
309
|
+
safeOptions.events.on(event, handler);
|
|
310
|
+
}
|
|
311
|
+
return this;
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Removes event listener
|
|
316
|
+
* @param {string} event - Event name
|
|
317
|
+
* @param {Function} handler - Event handler
|
|
318
|
+
* @returns {SliderComponent} Slider component instance for chaining
|
|
319
|
+
*/
|
|
320
|
+
off(event: keyof typeof SLIDER_EVENTS | SLIDER_EVENTS, handler: (event: SliderEvent) => void) {
|
|
321
|
+
if (safeOptions.events && typeof safeOptions.events.off === 'function') {
|
|
322
|
+
safeOptions.events.off(event, handler);
|
|
323
|
+
}
|
|
324
|
+
return this;
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Destroys the slider component and cleans up resources
|
|
329
|
+
*/
|
|
330
|
+
destroy() {
|
|
331
|
+
if (safeOptions.lifecycle && typeof safeOptions.lifecycle.destroy === 'function') {
|
|
332
|
+
safeOptions.lifecycle.destroy();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// src/components/slider/config.ts
|
|
2
|
+
import {
|
|
3
|
+
createComponentConfig,
|
|
4
|
+
createElementConfig
|
|
5
|
+
} from '../../core/config/component-config';
|
|
6
|
+
import { SliderConfig } from './types';
|
|
7
|
+
import { SLIDER_COLORS, SLIDER_SIZES, SLIDER_ORIENTATIONS } from './constants';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default configuration for the Slider component
|
|
11
|
+
*/
|
|
12
|
+
export const defaultConfig: SliderConfig = {
|
|
13
|
+
min: 0,
|
|
14
|
+
max: 100,
|
|
15
|
+
value: 0,
|
|
16
|
+
step: 1,
|
|
17
|
+
disabled: false,
|
|
18
|
+
color: SLIDER_COLORS.PRIMARY,
|
|
19
|
+
size: SLIDER_SIZES.MEDIUM,
|
|
20
|
+
orientation: SLIDER_ORIENTATIONS.HORIZONTAL,
|
|
21
|
+
ticks: false,
|
|
22
|
+
tickLabels: false,
|
|
23
|
+
showValue: true,
|
|
24
|
+
snapToSteps: true,
|
|
25
|
+
range: false,
|
|
26
|
+
valueFormatter: (value: number) => value.toString()
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates the base configuration for Slider component
|
|
31
|
+
* @param {SliderConfig} config - User provided configuration
|
|
32
|
+
* @returns {SliderConfig} Complete configuration with defaults applied
|
|
33
|
+
*/
|
|
34
|
+
export const createBaseConfig = (config: SliderConfig = {}): SliderConfig =>
|
|
35
|
+
createComponentConfig(defaultConfig, config, 'slider') as SliderConfig;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Generates element configuration for the Slider component
|
|
39
|
+
* @param {SliderConfig} config - Slider configuration
|
|
40
|
+
* @returns {Object} Element configuration object for withElement
|
|
41
|
+
*/
|
|
42
|
+
export const getElementConfig = (config: SliderConfig) => {
|
|
43
|
+
return createElementConfig(config, {
|
|
44
|
+
tag: 'div',
|
|
45
|
+
attrs: {
|
|
46
|
+
'role': 'slider',
|
|
47
|
+
'tabindex': config.disabled ? -1 : 0,
|
|
48
|
+
'aria-disabled': config.disabled === true ? true : false,
|
|
49
|
+
'aria-valuemin': config.min,
|
|
50
|
+
'aria-valuemax': config.max,
|
|
51
|
+
'aria-valuenow': config.value,
|
|
52
|
+
'aria-orientation': config.orientation
|
|
53
|
+
},
|
|
54
|
+
className: config.class
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates API configuration for the Slider component
|
|
60
|
+
* @param {Object} comp - Component with slider features
|
|
61
|
+
* @returns {Object} API configuration object
|
|
62
|
+
*/
|
|
63
|
+
export const getApiConfig = (comp) => {
|
|
64
|
+
// Create safe accessor functions to avoid undefined errors
|
|
65
|
+
const safeCall = (obj, path, fallback = () => {}) => {
|
|
66
|
+
try {
|
|
67
|
+
const parts = path.split('.');
|
|
68
|
+
let current = obj;
|
|
69
|
+
|
|
70
|
+
for (const part of parts) {
|
|
71
|
+
if (current === undefined || current === null) return fallback;
|
|
72
|
+
current = current[part];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return typeof current === 'function' ? current : fallback;
|
|
76
|
+
} catch {
|
|
77
|
+
return fallback;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const safeGetter = (obj, path, defaultValue = null) => {
|
|
82
|
+
try {
|
|
83
|
+
const parts = path.split('.');
|
|
84
|
+
let current = obj;
|
|
85
|
+
|
|
86
|
+
for (const part of parts) {
|
|
87
|
+
if (current === undefined || current === null) return defaultValue;
|
|
88
|
+
current = current[part];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return current === undefined ? defaultValue : current;
|
|
92
|
+
} catch {
|
|
93
|
+
return defaultValue;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Create API configuration using safe accessors
|
|
98
|
+
return {
|
|
99
|
+
slider: {
|
|
100
|
+
setValue: (value, triggerEvent) => safeCall(comp, 'slider.setValue')(value, triggerEvent),
|
|
101
|
+
getValue: () => safeGetter(comp, 'slider.getValue', 0)(),
|
|
102
|
+
setSecondValue: (value, triggerEvent) => safeCall(comp, 'slider.setSecondValue')(value, triggerEvent),
|
|
103
|
+
getSecondValue: () => safeGetter(comp, 'slider.getSecondValue', null)(),
|
|
104
|
+
setMin: (min) => safeCall(comp, 'slider.setMin')(min),
|
|
105
|
+
getMin: () => safeGetter(comp, 'slider.getMin', 0)(),
|
|
106
|
+
setMax: (max) => safeCall(comp, 'slider.setMax')(max),
|
|
107
|
+
getMax: () => safeGetter(comp, 'slider.getMax', 100)(),
|
|
108
|
+
setStep: (step) => safeCall(comp, 'slider.setStep')(step),
|
|
109
|
+
getStep: () => safeGetter(comp, 'slider.getStep', 1)()
|
|
110
|
+
},
|
|
111
|
+
disabled: {
|
|
112
|
+
enable: () => safeCall(comp, 'disabled.enable')(),
|
|
113
|
+
disable: () => safeCall(comp, 'disabled.disable')(),
|
|
114
|
+
isDisabled: () => safeGetter(comp, 'disabled.isDisabled', false)()
|
|
115
|
+
},
|
|
116
|
+
appearance: {
|
|
117
|
+
setColor: (color) => safeCall(comp, 'appearance.setColor')(color),
|
|
118
|
+
getColor: () => safeGetter(comp, 'appearance.getColor', 'primary')(),
|
|
119
|
+
setSize: (size) => safeCall(comp, 'appearance.setSize')(size),
|
|
120
|
+
getSize: () => safeGetter(comp, 'appearance.getSize', 'medium')(),
|
|
121
|
+
setOrientation: (orientation) => safeCall(comp, 'appearance.setOrientation')(orientation),
|
|
122
|
+
getOrientation: () => safeGetter(comp, 'appearance.getOrientation', 'horizontal')(),
|
|
123
|
+
showTicks: (show) => safeCall(comp, 'appearance.showTicks')(show),
|
|
124
|
+
showTickLabels: (show) => safeCall(comp, 'appearance.showTickLabels')(show),
|
|
125
|
+
showCurrentValue: (show) => safeCall(comp, 'appearance.showCurrentValue')(show)
|
|
126
|
+
},
|
|
127
|
+
events: {
|
|
128
|
+
on: (event, handler) => {
|
|
129
|
+
if (comp && comp.events && typeof comp.events.on === 'function') {
|
|
130
|
+
return comp.events.on(event, handler);
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
},
|
|
134
|
+
off: (event, handler) => {
|
|
135
|
+
if (comp && comp.events && typeof comp.events.off === 'function') {
|
|
136
|
+
return comp.events.off(event, handler);
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
lifecycle: {
|
|
142
|
+
destroy: () => safeCall(comp, 'lifecycle.destroy')()
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/components/slider/constants.ts
|
|
2
|
+
|
|
3
|
+
export const SLIDER_COLORS = {
|
|
4
|
+
PRIMARY: 'primary',
|
|
5
|
+
SECONDARY: 'secondary',
|
|
6
|
+
TERTIARY: 'tertiary',
|
|
7
|
+
ERROR: 'error'
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const SLIDER_SIZES = {
|
|
11
|
+
SMALL: 'small',
|
|
12
|
+
MEDIUM: 'medium',
|
|
13
|
+
LARGE: 'large'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const SLIDER_ORIENTATIONS = {
|
|
17
|
+
HORIZONTAL: 'horizontal',
|
|
18
|
+
VERTICAL: 'vertical'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const SLIDER_EVENTS = {
|
|
22
|
+
CHANGE: 'change',
|
|
23
|
+
INPUT: 'input',
|
|
24
|
+
FOCUS: 'focus',
|
|
25
|
+
BLUR: 'blur',
|
|
26
|
+
START: 'start',
|
|
27
|
+
END: 'end'
|
|
28
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// src/components/slider/features/appearance.ts
|
|
2
|
+
import { SLIDER_COLORS, SLIDER_SIZES, SLIDER_ORIENTATIONS } from '../constants';
|
|
3
|
+
import { SliderConfig } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Add appearance management features to slider component
|
|
7
|
+
* @param config Slider configuration
|
|
8
|
+
* @returns Component enhancer with appearance features
|
|
9
|
+
*/
|
|
10
|
+
export const withAppearance = (config: SliderConfig) => component => {
|
|
11
|
+
return {
|
|
12
|
+
...component,
|
|
13
|
+
appearance: {
|
|
14
|
+
/**
|
|
15
|
+
* Sets slider color
|
|
16
|
+
* @param color Color variant
|
|
17
|
+
*/
|
|
18
|
+
setColor(color: keyof typeof SLIDER_COLORS | SLIDER_COLORS) {
|
|
19
|
+
// Remove existing color classes
|
|
20
|
+
Object.values(SLIDER_COLORS).forEach(colorName => {
|
|
21
|
+
component.element.classList.remove(`${component.getClass('slider')}--${colorName}`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Add new color class if not primary (default)
|
|
25
|
+
if (color !== SLIDER_COLORS.PRIMARY) {
|
|
26
|
+
component.element.classList.add(`${component.getClass('slider')}--${color}`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Gets slider color
|
|
32
|
+
* @returns Current color name
|
|
33
|
+
*/
|
|
34
|
+
getColor() {
|
|
35
|
+
// Find which color class is active
|
|
36
|
+
const colorClass = Object.values(SLIDER_COLORS).find(colorName =>
|
|
37
|
+
component.element.classList.contains(`${component.getClass('slider')}--${colorName}`)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return colorClass || SLIDER_COLORS.PRIMARY;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sets slider size
|
|
45
|
+
* @param size Size variant
|
|
46
|
+
*/
|
|
47
|
+
setSize(size: keyof typeof SLIDER_SIZES | SLIDER_SIZES) {
|
|
48
|
+
// Remove existing size classes
|
|
49
|
+
Object.values(SLIDER_SIZES).forEach(sizeName => {
|
|
50
|
+
component.element.classList.remove(`${component.getClass('slider')}--${sizeName}`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Add new size class if not medium (default)
|
|
54
|
+
if (size !== SLIDER_SIZES.MEDIUM) {
|
|
55
|
+
component.element.classList.add(`${component.getClass('slider')}--${size}`);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets slider size
|
|
61
|
+
* @returns Current size name
|
|
62
|
+
*/
|
|
63
|
+
getSize() {
|
|
64
|
+
// Find which size class is active
|
|
65
|
+
const sizeClass = Object.values(SLIDER_SIZES).find(sizeName =>
|
|
66
|
+
component.element.classList.contains(`${component.getClass('slider')}--${sizeName}`)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return sizeClass || SLIDER_SIZES.MEDIUM;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sets slider orientation
|
|
74
|
+
* @param orientation Orientation variant
|
|
75
|
+
*/
|
|
76
|
+
setOrientation(orientation: keyof typeof SLIDER_ORIENTATIONS | SLIDER_ORIENTATIONS) {
|
|
77
|
+
// Clear existing orientation class
|
|
78
|
+
component.element.classList.remove(`${component.getClass('slider')}--${SLIDER_ORIENTATIONS.VERTICAL}`);
|
|
79
|
+
|
|
80
|
+
// Add orientation class if vertical
|
|
81
|
+
if (orientation === SLIDER_ORIENTATIONS.VERTICAL) {
|
|
82
|
+
component.element.classList.add(`${component.getClass('slider')}--${SLIDER_ORIENTATIONS.VERTICAL}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Update ARIA attribute
|
|
86
|
+
component.element.setAttribute('aria-orientation', orientation);
|
|
87
|
+
|
|
88
|
+
// Update visual elements
|
|
89
|
+
if (component.slider) {
|
|
90
|
+
const eventData = { slider: component, value: component.slider.getValue() };
|
|
91
|
+
component.events.trigger('change', eventData);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Gets slider orientation
|
|
97
|
+
* @returns Current orientation name
|
|
98
|
+
*/
|
|
99
|
+
getOrientation() {
|
|
100
|
+
return component.element.classList.contains(`${component.getClass('slider')}--${SLIDER_ORIENTATIONS.VERTICAL}`)
|
|
101
|
+
? SLIDER_ORIENTATIONS.VERTICAL
|
|
102
|
+
: SLIDER_ORIENTATIONS.HORIZONTAL;
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Shows or hides tick marks
|
|
107
|
+
* @param show Whether to show ticks
|
|
108
|
+
*/
|
|
109
|
+
showTicks(show: boolean) {
|
|
110
|
+
config.ticks = show;
|
|
111
|
+
|
|
112
|
+
// Regenerate ticks if slider is initialized
|
|
113
|
+
if (component.slider) {
|
|
114
|
+
component.slider.regenerateTicks();
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Shows or hides tick labels
|
|
120
|
+
* @param show Whether to show labels or array of label texts
|
|
121
|
+
*/
|
|
122
|
+
showTickLabels(show: boolean | string[]) {
|
|
123
|
+
config.tickLabels = show;
|
|
124
|
+
|
|
125
|
+
// Regenerate ticks if slider is initialized
|
|
126
|
+
if (component.slider) {
|
|
127
|
+
component.slider.regenerateTicks();
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Shows or hides current value bubble while dragging
|
|
133
|
+
* @param show Whether to show value bubble
|
|
134
|
+
*/
|
|
135
|
+
showCurrentValue(show: boolean) {
|
|
136
|
+
config.showValue = show;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/components/slider/features/disabled.ts
|
|
2
|
+
import { SliderConfig } from '../types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Add disabled state functionality to component
|
|
6
|
+
* @param config Slider configuration
|
|
7
|
+
* @returns Component enhancer with disabled functionality
|
|
8
|
+
*/
|
|
9
|
+
export const withDisabled = (config: SliderConfig) => component => {
|
|
10
|
+
// Initial disabled state
|
|
11
|
+
const isDisabled = config.disabled === true;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
...component,
|
|
15
|
+
disabled: {
|
|
16
|
+
enable() {
|
|
17
|
+
component.element.classList.remove(`${component.getClass('slider')}--disabled`);
|
|
18
|
+
component.element.setAttribute('aria-disabled', 'false');
|
|
19
|
+
component.element.tabIndex = 0;
|
|
20
|
+
component.structure.thumb.tabIndex = 0;
|
|
21
|
+
|
|
22
|
+
if (config.range && component.structure.secondThumb) {
|
|
23
|
+
component.structure.secondThumb.tabIndex = 0;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
disable() {
|
|
28
|
+
component.element.classList.add(`${component.getClass('slider')}--disabled`);
|
|
29
|
+
component.element.setAttribute('aria-disabled', 'true');
|
|
30
|
+
component.element.tabIndex = -1;
|
|
31
|
+
component.structure.thumb.tabIndex = -1;
|
|
32
|
+
|
|
33
|
+
if (config.range && component.structure.secondThumb) {
|
|
34
|
+
component.structure.secondThumb.tabIndex = -1;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
isDisabled() {
|
|
39
|
+
return component.element.classList.contains(`${component.getClass('slider')}--disabled`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
};
|