mtrl 0.2.9 → 0.3.1
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/CLAUDE.md +33 -0
- package/package.json +3 -1
- package/src/components/button/button.ts +34 -5
- package/src/components/navigation/index.ts +4 -1
- package/src/components/navigation/system/core.ts +302 -0
- package/src/components/navigation/system/events.ts +240 -0
- package/src/components/navigation/system/index.ts +184 -0
- package/src/components/navigation/system/mobile.ts +278 -0
- package/src/components/navigation/system/state.ts +77 -0
- package/src/components/navigation/system/types.ts +364 -0
- package/src/components/navigation/types.ts +33 -0
- package/src/components/slider/config.ts +2 -2
- package/src/components/slider/features/controller.ts +1 -25
- package/src/components/slider/features/handlers.ts +0 -1
- package/src/components/slider/features/range.ts +7 -7
- package/src/components/slider/{structure.ts → schema.ts} +2 -13
- package/src/components/slider/slider.ts +3 -2
- package/src/components/snackbar/index.ts +7 -1
- package/src/components/snackbar/types.ts +25 -0
- package/src/components/switch/api.ts +16 -0
- package/src/components/switch/config.ts +1 -18
- package/src/components/switch/features.ts +198 -0
- package/src/components/switch/index.ts +6 -1
- package/src/components/switch/switch.ts +3 -3
- package/src/components/switch/types.ts +27 -2
- package/src/components/textfield/index.ts +7 -1
- package/src/components/textfield/types.ts +36 -0
- package/src/core/composition/features/dom.ts +26 -14
- package/src/core/composition/features/icon.ts +18 -18
- package/src/core/composition/features/index.ts +3 -2
- package/src/core/composition/features/label.ts +16 -17
- package/src/core/composition/features/layout.ts +47 -0
- package/src/core/composition/index.ts +4 -4
- package/src/core/layout/README.md +350 -0
- package/src/core/layout/array.ts +181 -0
- package/src/core/layout/create.ts +55 -0
- package/src/core/layout/index.ts +26 -0
- package/src/core/layout/object.ts +124 -0
- package/src/core/layout/processor.ts +58 -0
- package/src/core/layout/result.ts +85 -0
- package/src/core/layout/types.ts +125 -0
- package/src/core/layout/utils.ts +136 -0
- package/src/styles/abstract/_variables.scss +28 -0
- package/src/styles/components/_switch.scss +133 -69
- package/src/styles/components/_textfield.scss +9 -16
- package/test/components/badge.test.ts +545 -0
- package/test/components/bottom-app-bar.test.ts +303 -0
- package/test/components/button.test.ts +233 -0
- package/test/components/card.test.ts +560 -0
- package/test/components/carousel.test.ts +951 -0
- package/test/components/checkbox.test.ts +462 -0
- package/test/components/chip.test.ts +692 -0
- package/test/components/datepicker.test.ts +1124 -0
- package/test/components/dialog.test.ts +990 -0
- package/test/components/divider.test.ts +412 -0
- package/test/components/extended-fab.test.ts +672 -0
- package/test/components/fab.test.ts +561 -0
- package/test/components/list.test.ts +365 -0
- package/test/components/menu.test.ts +718 -0
- package/test/components/navigation.test.ts +186 -0
- package/test/components/progress.test.ts +567 -0
- package/test/components/radios.test.ts +699 -0
- package/test/components/search.test.ts +1135 -0
- package/test/components/segmented-button.test.ts +732 -0
- package/test/components/sheet.test.ts +641 -0
- package/test/components/slider.test.ts +1220 -0
- package/test/components/snackbar.test.ts +461 -0
- package/test/components/switch.test.ts +452 -0
- package/test/components/tabs.test.ts +1369 -0
- package/test/components/textfield.test.ts +400 -0
- package/test/components/timepicker.test.ts +592 -0
- package/test/components/tooltip.test.ts +630 -0
- package/test/components/top-app-bar.test.ts +566 -0
- package/test/core/dom.attributes.test.ts +148 -0
- package/test/core/dom.classes.test.ts +152 -0
- package/test/core/dom.events.test.ts +243 -0
- package/test/core/emitter.test.ts +141 -0
- package/test/core/ripple.test.ts +99 -0
- package/test/core/state.store.test.ts +189 -0
- package/test/core/utils.normalize.test.ts +61 -0
- package/test/core/utils.object.test.ts +120 -0
- package/test/setup.ts +451 -0
- package/tsconfig.json +2 -2
- package/src/components/navigation/system-types.ts +0 -124
- package/src/components/navigation/system.ts +0 -776
- package/src/components/snackbar/constants.ts +0 -26
- package/src/core/composition/features/structure.ts +0 -22
- package/src/core/layout/index.js +0 -95
- package/src/core/structure.ts +0 -288
- package/test/components/button.test.js +0 -170
- package/test/components/checkbox.test.js +0 -238
- package/test/components/list.test.js +0 -105
- package/test/components/menu.test.js +0 -385
- package/test/components/navigation.test.js +0 -227
- package/test/components/snackbar.test.js +0 -234
- package/test/components/switch.test.js +0 -186
- package/test/components/textfield.test.js +0 -314
- package/test/core/emitter.test.js +0 -141
- package/test/core/ripple.test.js +0 -66
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
// src/components/navigation/system/types.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the navigation system
|
|
5
|
+
*/
|
|
6
|
+
export interface NavigationSystemConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Screen width breakpoint for mobile mode (in pixels)
|
|
9
|
+
* @default 960
|
|
10
|
+
*/
|
|
11
|
+
breakpoint?: number;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Prevent body scrolling when mobile drawer is open
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
lockBodyScroll?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Close drawer when clicking outside of it in mobile mode
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
hideOnClickOutside?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Enable swipe gestures for mobile navigation
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
enableSwipeGestures?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Optimize touch targets for mobile devices
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
optimizeForTouch?: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* CSS class for the overlay element
|
|
39
|
+
* @default 'mtrl-nav-overlay'
|
|
40
|
+
*/
|
|
41
|
+
overlayClass?: string;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* CSS class for the close button
|
|
45
|
+
* @default 'mtrl-nav-close-btn'
|
|
46
|
+
*/
|
|
47
|
+
closeButtonClass?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* CSS class applied to body when drawer is open (to prevent scrolling)
|
|
51
|
+
* @default 'mtrl-body-drawer-open'
|
|
52
|
+
*/
|
|
53
|
+
bodyLockClass?: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Display labels on rail navigation items
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
showLabelsOnRail?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Hide drawer when an item is clicked
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
hideDrawerOnClick?: boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Start with drawer expanded
|
|
69
|
+
* @default false
|
|
70
|
+
*/
|
|
71
|
+
expanded?: boolean;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Delay before opening drawer on hover (in ms)
|
|
75
|
+
* @default 200
|
|
76
|
+
*/
|
|
77
|
+
hoverDelay?: number;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Delay before closing drawer after mouseleave (in ms)
|
|
81
|
+
* @default 100
|
|
82
|
+
*/
|
|
83
|
+
closeDelay?: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* ID of the initially active section
|
|
87
|
+
*/
|
|
88
|
+
activeSection?: string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* ID of the initially active subsection
|
|
92
|
+
*/
|
|
93
|
+
activeSubsection?: string;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Navigation items configuration
|
|
97
|
+
*/
|
|
98
|
+
items?: Record<string, NavigationSection>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Additional options for the rail component
|
|
102
|
+
*/
|
|
103
|
+
railOptions?: Record<string, any>;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Additional options for the drawer component
|
|
107
|
+
*/
|
|
108
|
+
drawerOptions?: Record<string, any>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Navigation section configuration
|
|
113
|
+
*/
|
|
114
|
+
export interface NavigationSection {
|
|
115
|
+
/**
|
|
116
|
+
* Display label for the section
|
|
117
|
+
*/
|
|
118
|
+
label: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Icon for the section
|
|
122
|
+
*/
|
|
123
|
+
icon?: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Subsection items
|
|
127
|
+
*/
|
|
128
|
+
items?: NavigationItem[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Navigation item configuration
|
|
133
|
+
*/
|
|
134
|
+
export interface NavigationItem {
|
|
135
|
+
/**
|
|
136
|
+
* Unique identifier for the item
|
|
137
|
+
*/
|
|
138
|
+
id: string;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Display label for the item
|
|
142
|
+
*/
|
|
143
|
+
label: string;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Icon for the item
|
|
147
|
+
*/
|
|
148
|
+
icon?: string;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Whether the item is currently active
|
|
152
|
+
*/
|
|
153
|
+
active?: boolean;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Additional properties
|
|
157
|
+
*/
|
|
158
|
+
[key: string]: any;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Navigation system state interface
|
|
163
|
+
*/
|
|
164
|
+
export interface NavigationSystemState {
|
|
165
|
+
/**
|
|
166
|
+
* Rail navigation component instance
|
|
167
|
+
*/
|
|
168
|
+
rail: any;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Drawer navigation component instance
|
|
172
|
+
*/
|
|
173
|
+
drawer: any;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* ID of the active section
|
|
177
|
+
*/
|
|
178
|
+
activeSection: string | null;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* ID of the active subsection
|
|
182
|
+
*/
|
|
183
|
+
activeSubsection: string | null;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Navigation items configuration
|
|
187
|
+
*/
|
|
188
|
+
items: Record<string, NavigationSection>;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Whether the mouse is currently inside the drawer
|
|
192
|
+
*/
|
|
193
|
+
mouseInDrawer: boolean;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Whether the mouse is currently inside the rail
|
|
197
|
+
*/
|
|
198
|
+
mouseInRail: boolean;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Timer ID for hover delay
|
|
202
|
+
*/
|
|
203
|
+
hoverTimer: number | null;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Timer ID for close delay
|
|
207
|
+
*/
|
|
208
|
+
closeTimer: number | null;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Whether the system is currently processing a change
|
|
212
|
+
*/
|
|
213
|
+
processingChange: boolean;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Whether the system is in mobile mode
|
|
217
|
+
*/
|
|
218
|
+
isMobile: boolean;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Overlay element for mobile mode
|
|
222
|
+
*/
|
|
223
|
+
overlayElement: HTMLElement | null;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Close button element for mobile mode
|
|
227
|
+
*/
|
|
228
|
+
closeButtonElement: HTMLElement | null;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* ResizeObserver instance for responsive behavior
|
|
232
|
+
*/
|
|
233
|
+
resizeObserver: ResizeObserver | null;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Handler function for outside clicks
|
|
237
|
+
*/
|
|
238
|
+
outsideClickHandler: ((event: Event) => void) | null;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Whether outside click handling is set up
|
|
242
|
+
*/
|
|
243
|
+
outsideClickHandlerSet: boolean;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* View change event data
|
|
248
|
+
*/
|
|
249
|
+
export interface ViewChangeEvent {
|
|
250
|
+
/**
|
|
251
|
+
* Whether the system is now in mobile mode
|
|
252
|
+
*/
|
|
253
|
+
mobile: boolean;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Whether the system was previously in mobile mode
|
|
257
|
+
*/
|
|
258
|
+
previousMobile: boolean;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Current window width
|
|
262
|
+
*/
|
|
263
|
+
width: number;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Navigation system API interface
|
|
268
|
+
*/
|
|
269
|
+
export interface NavigationSystem {
|
|
270
|
+
/**
|
|
271
|
+
* Initialize the navigation system
|
|
272
|
+
*/
|
|
273
|
+
initialize(): NavigationSystem;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Clean up resources
|
|
277
|
+
*/
|
|
278
|
+
cleanup(): void;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Navigate to a specific section and subsection
|
|
282
|
+
* @param section - Section ID
|
|
283
|
+
* @param subsection - Subsection ID (optional)
|
|
284
|
+
* @param silent - Whether to suppress change events
|
|
285
|
+
*/
|
|
286
|
+
navigateTo(section: string, subsection?: string, silent?: boolean): void;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Get the rail navigation component
|
|
290
|
+
*/
|
|
291
|
+
getRail(): any;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get the drawer navigation component
|
|
295
|
+
*/
|
|
296
|
+
getDrawer(): any;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get the active section ID
|
|
300
|
+
*/
|
|
301
|
+
getActiveSection(): string | null;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Get the active subsection ID
|
|
305
|
+
*/
|
|
306
|
+
getActiveSubsection(): string | null;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Show the drawer
|
|
310
|
+
*/
|
|
311
|
+
showDrawer(): void;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Hide the drawer
|
|
315
|
+
*/
|
|
316
|
+
hideDrawer(): void;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Check if the drawer is visible
|
|
320
|
+
*/
|
|
321
|
+
isDrawerVisible(): boolean;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Update configuration
|
|
325
|
+
* @param newConfig - New configuration options
|
|
326
|
+
*/
|
|
327
|
+
configure(newConfig: Partial<NavigationSystemConfig>): NavigationSystem;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Set processing change state
|
|
331
|
+
* @param isProcessing - Whether a change is being processed
|
|
332
|
+
*/
|
|
333
|
+
setProcessingChange(isProcessing: boolean): void;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Check if a change is being processed
|
|
337
|
+
*/
|
|
338
|
+
isProcessingChange(): boolean;
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Check if the system is in mobile mode
|
|
342
|
+
*/
|
|
343
|
+
isMobile(): boolean;
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Check and update mobile state
|
|
347
|
+
*/
|
|
348
|
+
checkMobileState(): void;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Handler for section changes
|
|
352
|
+
*/
|
|
353
|
+
onSectionChange?: (sectionId: string, eventData: any) => void;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Handler for item selection
|
|
357
|
+
*/
|
|
358
|
+
onItemSelect?: (event: any) => void;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Handler for view changes (mobile/desktop)
|
|
362
|
+
*/
|
|
363
|
+
onViewChange?: (event: ViewChangeEvent) => void;
|
|
364
|
+
}
|
|
@@ -6,18 +6,51 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export type NavVariant = 'rail' | 'drawer' | 'bar' | 'modal' | 'standard';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Navigation variants enum
|
|
11
|
+
* @category Components
|
|
12
|
+
*/
|
|
13
|
+
export const NAV_VARIANTS: Record<string, NavVariant> = {
|
|
14
|
+
RAIL: 'rail',
|
|
15
|
+
DRAWER: 'drawer',
|
|
16
|
+
BAR: 'bar',
|
|
17
|
+
MODAL: 'modal',
|
|
18
|
+
STANDARD: 'standard'
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
9
21
|
/**
|
|
10
22
|
* Navigation positions
|
|
11
23
|
* @category Components
|
|
12
24
|
*/
|
|
13
25
|
export type NavPosition = 'left' | 'right' | 'top' | 'bottom';
|
|
14
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Navigation positions enum
|
|
29
|
+
* @category Components
|
|
30
|
+
*/
|
|
31
|
+
export const NAV_POSITIONS: Record<string, NavPosition> = {
|
|
32
|
+
LEFT: 'left',
|
|
33
|
+
RIGHT: 'right',
|
|
34
|
+
TOP: 'top',
|
|
35
|
+
BOTTOM: 'bottom'
|
|
36
|
+
} as const;
|
|
37
|
+
|
|
15
38
|
/**
|
|
16
39
|
* Navigation behaviors
|
|
17
40
|
* @category Components
|
|
18
41
|
*/
|
|
19
42
|
export type NavBehavior = 'fixed' | 'dismissible' | 'modal';
|
|
20
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Navigation behaviors enum
|
|
46
|
+
* @category Components
|
|
47
|
+
*/
|
|
48
|
+
export const NAV_BEHAVIORS: Record<string, NavBehavior> = {
|
|
49
|
+
FIXED: 'fixed',
|
|
50
|
+
DISMISSIBLE: 'dismissible',
|
|
51
|
+
MODAL: 'modal'
|
|
52
|
+
} as const;
|
|
53
|
+
|
|
21
54
|
/**
|
|
22
55
|
* Navigation item state
|
|
23
56
|
* @category Components
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from '../../core/config/component-config';
|
|
6
6
|
import { SliderConfig } from './types';
|
|
7
7
|
import { SLIDER_COLORS, SLIDER_SIZES } from './constants';
|
|
8
|
-
import {
|
|
8
|
+
import { createSliderSchema } from './schema';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Default configuration for the Slider component
|
|
@@ -47,7 +47,7 @@ export const createBaseConfig = (config: SliderConfig = {}): SliderConfig => {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
// Add the structure definition to the config
|
|
50
|
-
baseConfig.
|
|
50
|
+
baseConfig.schema = createSliderSchema(baseComponent, baseConfig);
|
|
51
51
|
|
|
52
52
|
return baseConfig;
|
|
53
53
|
};
|
|
@@ -16,30 +16,6 @@ export const withController = (config: SliderConfig) => component => {
|
|
|
16
16
|
console.warn('Cannot initialize slider controller: missing element or components');
|
|
17
17
|
return component;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
// Ensure component has events
|
|
21
|
-
if (!component.events) {
|
|
22
|
-
component.events = {
|
|
23
|
-
listeners: {},
|
|
24
|
-
on(event, handler) {
|
|
25
|
-
if (!this.listeners[event]) this.listeners[event] = [];
|
|
26
|
-
this.listeners[event].push(handler);
|
|
27
|
-
return this;
|
|
28
|
-
},
|
|
29
|
-
off(event, handler) {
|
|
30
|
-
if (this.listeners[event]) {
|
|
31
|
-
this.listeners[event] = this.listeners[event].filter(h => h !== handler);
|
|
32
|
-
}
|
|
33
|
-
return this;
|
|
34
|
-
},
|
|
35
|
-
trigger(event, data) {
|
|
36
|
-
if (this.listeners[event]) {
|
|
37
|
-
this.listeners[event].forEach(handler => handler(data));
|
|
38
|
-
}
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
19
|
|
|
44
20
|
// Initialize state
|
|
45
21
|
const state = {
|
|
@@ -68,7 +44,7 @@ export const withController = (config: SliderConfig) => component => {
|
|
|
68
44
|
defaultPrevented: false
|
|
69
45
|
};
|
|
70
46
|
|
|
71
|
-
state.component.
|
|
47
|
+
state.component.emit(eventName, eventData);
|
|
72
48
|
return eventData;
|
|
73
49
|
}
|
|
74
50
|
};
|
|
@@ -174,7 +174,6 @@ export const createHandlers = (config: SliderConfig, state, uiRenderer, eventHel
|
|
|
174
174
|
// Update UI and trigger events
|
|
175
175
|
render();
|
|
176
176
|
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
177
|
-
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
178
177
|
} catch (error) {
|
|
179
178
|
console.warn('Error handling track click:', error);
|
|
180
179
|
}
|
|
@@ -10,7 +10,7 @@ import { createElement } from '../../../core/dom/create';
|
|
|
10
10
|
*/
|
|
11
11
|
export const withRange = (config: SliderConfig) => component => {
|
|
12
12
|
// If not a range slider or missing structure definition, return unmodified
|
|
13
|
-
if (!config.range || !config.secondValue || !component.
|
|
13
|
+
if (!config.range || !config.secondValue || !component.schema) {
|
|
14
14
|
return component;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -25,18 +25,18 @@ export const withRange = (config: SliderConfig) => component => {
|
|
|
25
25
|
const getClass = component.getClass;
|
|
26
26
|
|
|
27
27
|
// Clone the structure definition (deep copy)
|
|
28
|
-
const
|
|
28
|
+
const schema = JSON.parse(JSON.stringify(component.schema));
|
|
29
29
|
|
|
30
30
|
// Add range class to root element
|
|
31
|
-
const rootClasses =
|
|
31
|
+
const rootClasses = schema.element.options.className || [];
|
|
32
32
|
if (Array.isArray(rootClasses)) {
|
|
33
33
|
rootClasses.push(getClass('slider--range'));
|
|
34
34
|
} else {
|
|
35
|
-
|
|
35
|
+
schema.element.options.className = `${rootClasses} ${getClass('slider--range')}`.trim();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Add start track segment to track children
|
|
39
|
-
const trackChildren =
|
|
39
|
+
const trackChildren = schema.element.children.container.children.track.children;
|
|
40
40
|
trackChildren.startTrack = {
|
|
41
41
|
name: 'startTrack',
|
|
42
42
|
creator: createElement,
|
|
@@ -50,7 +50,7 @@ export const withRange = (config: SliderConfig) => component => {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
// Add second handle to container children
|
|
53
|
-
const containerChildren =
|
|
53
|
+
const containerChildren = schema.element.children.container.children;
|
|
54
54
|
containerChildren.secondHandle = {
|
|
55
55
|
name: 'secondHandle',
|
|
56
56
|
creator: createElement,
|
|
@@ -95,7 +95,7 @@ export const withRange = (config: SliderConfig) => component => {
|
|
|
95
95
|
// Return component with updated structure definition
|
|
96
96
|
return {
|
|
97
97
|
...component,
|
|
98
|
-
|
|
98
|
+
schema
|
|
99
99
|
};
|
|
100
100
|
} catch (error) {
|
|
101
101
|
console.warn('Error enhancing structure with range functionality:', error);
|
|
@@ -6,9 +6,9 @@ import { SliderConfig } from './types';
|
|
|
6
6
|
*
|
|
7
7
|
* @param component Component for class name generation
|
|
8
8
|
* @param config Slider configuration
|
|
9
|
-
* @returns Structure
|
|
9
|
+
* @returns Structure schema object
|
|
10
10
|
*/
|
|
11
|
-
export function
|
|
11
|
+
export function createSliderSchema(component, config: SliderConfig) {
|
|
12
12
|
// Get prefixed class names
|
|
13
13
|
const getClass = (className) => component.getClass(className);
|
|
14
14
|
|
|
@@ -26,7 +26,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
26
26
|
return {
|
|
27
27
|
element: {
|
|
28
28
|
options: {
|
|
29
|
-
tag: 'div',
|
|
30
29
|
className: [getClass('slider'), config.class].filter(Boolean),
|
|
31
30
|
attrs: {
|
|
32
31
|
tabindex: '-1',
|
|
@@ -38,20 +37,17 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
38
37
|
// Container with all slider elements
|
|
39
38
|
container: {
|
|
40
39
|
options: {
|
|
41
|
-
tag: 'div',
|
|
42
40
|
className: getClass('slider-container')
|
|
43
41
|
},
|
|
44
42
|
children: {
|
|
45
43
|
// Track with segments
|
|
46
44
|
track: {
|
|
47
45
|
options: {
|
|
48
|
-
tag: 'div',
|
|
49
46
|
className: getClass('slider-track')
|
|
50
47
|
},
|
|
51
48
|
children: {
|
|
52
49
|
activeTrack: {
|
|
53
50
|
options: {
|
|
54
|
-
tag: 'div',
|
|
55
51
|
className: getClass('slider-active-track'),
|
|
56
52
|
style: {
|
|
57
53
|
width: `${valuePercent}%`
|
|
@@ -60,7 +56,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
60
56
|
},
|
|
61
57
|
startTrack: {
|
|
62
58
|
options: {
|
|
63
|
-
tag: 'div',
|
|
64
59
|
className: getClass('slider-start-track'),
|
|
65
60
|
style: {
|
|
66
61
|
display: 'none', // Initially hidden for single slider
|
|
@@ -70,7 +65,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
70
65
|
},
|
|
71
66
|
remainingTrack: {
|
|
72
67
|
options: {
|
|
73
|
-
tag: 'div',
|
|
74
68
|
className: getClass('slider-remaining-track'),
|
|
75
69
|
style: {
|
|
76
70
|
width: `${100 - valuePercent}%`
|
|
@@ -83,7 +77,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
83
77
|
// Ticks container
|
|
84
78
|
ticksContainer: {
|
|
85
79
|
options: {
|
|
86
|
-
tag: 'div',
|
|
87
80
|
className: getClass('slider-ticks-container')
|
|
88
81
|
}
|
|
89
82
|
},
|
|
@@ -91,7 +84,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
91
84
|
// Dots for ends
|
|
92
85
|
startDot: {
|
|
93
86
|
options: {
|
|
94
|
-
tag: 'div',
|
|
95
87
|
className: [
|
|
96
88
|
getClass('slider-dot'),
|
|
97
89
|
getClass('slider-dot--start')
|
|
@@ -100,7 +92,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
100
92
|
},
|
|
101
93
|
endDot: {
|
|
102
94
|
options: {
|
|
103
|
-
tag: 'div',
|
|
104
95
|
className: [
|
|
105
96
|
getClass('slider-dot'),
|
|
106
97
|
getClass('slider-dot--end')
|
|
@@ -111,7 +102,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
111
102
|
// Main handle
|
|
112
103
|
handle: {
|
|
113
104
|
options: {
|
|
114
|
-
tag: 'div',
|
|
115
105
|
className: getClass('slider-handle'),
|
|
116
106
|
attrs: {
|
|
117
107
|
role: 'slider',
|
|
@@ -132,7 +122,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
|
|
|
132
122
|
// Main value bubble
|
|
133
123
|
valueBubble: {
|
|
134
124
|
options: {
|
|
135
|
-
tag: 'div',
|
|
136
125
|
className: getClass('slider-value'),
|
|
137
126
|
attrs: {
|
|
138
127
|
'aria-hidden': 'true',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { pipe } from '../../core/compose/pipe';
|
|
3
3
|
import { createBase } from '../../core/compose/component';
|
|
4
4
|
import { withEvents, withLifecycle } from '../../core/compose/features';
|
|
5
|
-
import {
|
|
5
|
+
import { withLayout, withIcon, withLabel, withDom } from '../../core/composition/features';
|
|
6
6
|
import {
|
|
7
7
|
withRange,
|
|
8
8
|
withStates,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { withAPI } from './api';
|
|
12
12
|
import { SliderConfig, SliderComponent } from './types';
|
|
13
13
|
import { createBaseConfig, getApiConfig } from './config';
|
|
14
|
+
|
|
14
15
|
/**
|
|
15
16
|
* Creates a new Slider component
|
|
16
17
|
*
|
|
@@ -36,7 +37,7 @@ const createSlider = (config: SliderConfig = {}): SliderComponent => {
|
|
|
36
37
|
// Base component with event system
|
|
37
38
|
createBase,
|
|
38
39
|
withEvents(),
|
|
39
|
-
|
|
40
|
+
withLayout(baseConfig),
|
|
40
41
|
withIcon(baseConfig),
|
|
41
42
|
withLabel(baseConfig),
|
|
42
43
|
withRange(baseConfig),
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
// src/components/snackbar/index.ts
|
|
2
2
|
export { default } from './snackbar'
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
SnackbarConfig,
|
|
5
|
+
SnackbarComponent,
|
|
6
|
+
SNACKBAR_VARIANTS,
|
|
7
|
+
SNACKBAR_POSITIONS,
|
|
8
|
+
SNACKBAR_STATES
|
|
9
|
+
} from './types'
|
|
@@ -5,16 +5,41 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type SnackbarVariant = 'basic' | 'action';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Snackbar visual variants
|
|
10
|
+
*/
|
|
11
|
+
export const SNACKBAR_VARIANTS = {
|
|
12
|
+
BASIC: 'basic',
|
|
13
|
+
ACTION: 'action' // With action button
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* Available snackbar positions
|
|
10
18
|
*/
|
|
11
19
|
export type SnackbarPosition = 'center' | 'start' | 'end';
|
|
12
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Snackbar display positions
|
|
23
|
+
*/
|
|
24
|
+
export const SNACKBAR_POSITIONS = {
|
|
25
|
+
CENTER: 'center',
|
|
26
|
+
START: 'start',
|
|
27
|
+
END: 'end'
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
13
30
|
/**
|
|
14
31
|
* Snackbar visibility states
|
|
15
32
|
*/
|
|
16
33
|
export type SnackbarState = 'visible' | 'hidden';
|
|
17
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Snackbar state classes
|
|
37
|
+
*/
|
|
38
|
+
export const SNACKBAR_STATES = {
|
|
39
|
+
VISIBLE: 'visible',
|
|
40
|
+
HIDDEN: 'hidden'
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
18
43
|
/**
|
|
19
44
|
* Available snackbar event types
|
|
20
45
|
*/
|