mtrl 0.2.7 → 0.2.9
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 +2 -0
- package/package.json +14 -3
- package/src/components/badge/api.ts +23 -14
- package/src/components/badge/badge.ts +2 -2
- package/src/components/badge/config.ts +10 -11
- package/src/components/badge/features.ts +15 -10
- package/src/components/badge/index.ts +27 -2
- package/src/components/badge/types.ts +28 -8
- package/src/components/bottom-app-bar/bottom-app-bar.ts +2 -44
- package/src/components/bottom-app-bar/config.ts +1 -45
- package/src/components/bottom-app-bar/index.ts +7 -1
- package/src/components/bottom-app-bar/types.ts +7 -1
- package/src/components/button/button.ts +0 -1
- package/src/components/button/config.ts +1 -2
- package/src/components/button/index.ts +10 -2
- package/src/components/button/types.ts +14 -2
- package/src/components/card/config.ts +17 -9
- package/src/components/card/content.ts +8 -10
- package/src/components/card/features.ts +4 -6
- package/src/components/card/index.ts +29 -2
- package/src/components/card/types.ts +6 -23
- package/src/components/checkbox/config.ts +3 -4
- package/src/components/checkbox/index.ts +1 -2
- package/src/components/checkbox/types.ts +12 -3
- package/src/components/chip/api.ts +170 -221
- package/src/components/chip/chip.ts +34 -302
- package/src/components/chip/config.ts +1 -2
- package/src/components/chip/index.ts +10 -2
- package/src/components/chip/types.ts +224 -35
- package/src/components/datepicker/api.ts +18 -25
- package/src/components/datepicker/config.ts +9 -12
- package/src/components/datepicker/datepicker.ts +7 -12
- package/src/components/datepicker/index.ts +10 -7
- package/src/components/datepicker/render.ts +16 -18
- package/src/components/datepicker/types.ts +164 -35
- package/src/components/datepicker/utils.ts +1 -2
- package/src/components/dialog/api.ts +7 -8
- package/src/components/dialog/config.ts +3 -4
- package/src/components/dialog/features.ts +56 -22
- package/src/components/dialog/index.ts +38 -8
- package/src/components/dialog/types.ts +33 -10
- package/src/components/divider/index.ts +5 -1
- package/src/components/extended-fab/config.ts +6 -2
- package/src/components/extended-fab/index.ts +7 -2
- package/src/components/extended-fab/types.ts +21 -4
- package/src/components/fab/config.ts +3 -4
- package/src/components/fab/fab.ts +1 -1
- package/src/components/fab/index.ts +7 -2
- package/src/components/fab/types.ts +21 -4
- package/src/components/list/config.ts +4 -5
- package/src/components/list/features.ts +6 -7
- package/src/components/list/index.ts +7 -9
- package/src/components/list/list-item.ts +12 -13
- package/src/components/list/types.ts +50 -5
- package/src/components/list/utils.ts +30 -3
- package/src/components/menu/features/items-manager.ts +9 -9
- package/src/components/menu/features/positioning.ts +7 -7
- package/src/components/menu/features/visibility.ts +7 -7
- package/src/components/menu/index.ts +7 -9
- package/src/components/menu/menu-item.ts +6 -6
- package/src/components/menu/menu.ts +22 -0
- package/src/components/menu/types.ts +29 -10
- package/src/components/menu/utils.ts +67 -0
- package/src/components/navigation/api.ts +131 -96
- package/src/components/navigation/config.ts +22 -10
- package/src/components/navigation/features/controller.ts +273 -0
- package/src/components/navigation/features/items.ts +160 -87
- package/src/components/navigation/index.ts +0 -6
- package/src/components/navigation/nav-item.ts +12 -24
- package/src/components/navigation/navigation.ts +21 -8
- package/src/components/navigation/system-types.ts +124 -0
- package/src/components/navigation/system.ts +776 -0
- package/src/components/navigation/types.ts +228 -203
- package/src/components/progress/api.ts +2 -3
- package/src/components/progress/config.ts +2 -3
- package/src/components/progress/index.ts +0 -1
- package/src/components/progress/progress.ts +1 -2
- package/src/components/progress/types.ts +186 -33
- package/src/components/radios/config.ts +1 -1
- package/src/components/radios/index.ts +0 -1
- package/src/components/radios/types.ts +0 -7
- package/src/components/search/config.ts +1 -2
- package/src/components/search/features/search.ts +14 -15
- package/src/components/search/features/states.ts +5 -1
- package/src/components/search/features/structure.ts +3 -4
- package/src/components/search/index.ts +0 -3
- package/src/components/search/types.ts +18 -6
- package/src/components/segmented-button/config.ts +20 -7
- package/src/components/segmented-button/segment.ts +6 -7
- package/src/components/segmented-button/segmented-button.ts +4 -5
- package/src/components/segmented-button/types.ts +37 -2
- package/src/components/slider/config.ts +20 -2
- package/src/components/slider/features/controller.ts +761 -0
- package/src/components/slider/features/handlers.ts +18 -15
- package/src/components/slider/features/index.ts +3 -2
- package/src/components/slider/features/range.ts +104 -0
- package/src/components/slider/slider.ts +34 -14
- package/src/components/slider/structure.ts +152 -0
- package/src/components/slider/types.ts +34 -8
- package/src/components/snackbar/config.ts +2 -3
- package/src/components/snackbar/constants.ts +0 -32
- package/src/components/snackbar/index.ts +0 -1
- package/src/components/snackbar/position.ts +9 -1
- package/src/components/snackbar/types.ts +122 -46
- package/src/components/switch/config.ts +2 -3
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/types.ts +3 -2
- package/src/components/tabs/config.ts +3 -4
- package/src/components/tabs/index.ts +0 -15
- package/src/components/tabs/tab-api.ts +12 -4
- package/src/components/tabs/tab.ts +18 -6
- package/src/components/tabs/types.ts +13 -3
- package/src/components/textfield/api.ts +53 -0
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/features.ts +322 -0
- package/src/components/textfield/index.ts +0 -1
- package/src/components/textfield/textfield.ts +8 -0
- package/src/components/textfield/types.ts +29 -6
- package/src/components/timepicker/api.ts +1 -1
- package/src/components/timepicker/clockdial.ts +2 -5
- package/src/components/timepicker/config.ts +102 -4
- package/src/components/timepicker/index.ts +1 -6
- package/src/components/timepicker/render.ts +1 -1
- package/src/components/timepicker/timepicker.ts +1 -1
- package/src/components/tooltip/api.ts +1 -1
- package/src/components/tooltip/config.ts +27 -6
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/types.ts +13 -3
- package/src/core/compose/features/textinput.ts +15 -2
- package/src/core/compose/features/textlabel.ts +0 -3
- package/src/core/composition/features/dom.ts +33 -0
- package/src/core/composition/features/icon.ts +131 -0
- package/src/core/composition/features/index.ts +11 -0
- package/src/core/composition/features/label.ts +156 -0
- package/src/core/composition/features/structure.ts +22 -0
- package/src/core/composition/index.ts +26 -0
- package/src/core/index.ts +1 -1
- package/src/core/structure.ts +288 -0
- package/src/index.ts +1 -0
- package/src/styles/components/_navigation-mobile.scss +244 -0
- package/src/styles/components/_navigation-system.scss +151 -0
- package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +1 -1
- package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +314 -72
- package/src/styles/main.scss +98 -49
- package/src/components/badge/constants.ts +0 -40
- package/src/components/button/constants.ts +0 -11
- package/src/components/card/constants.ts +0 -84
- package/src/components/datepicker/constants.ts +0 -98
- package/src/components/dialog/constants.ts +0 -32
- package/src/components/extended-fab/constants.ts +0 -36
- package/src/components/fab/constants.ts +0 -41
- package/src/components/menu/constants.ts +0 -154
- package/src/components/navigation/constants.ts +0 -200
- package/src/components/progress/constants.ts +0 -29
- package/src/components/search/constants.ts +0 -21
- package/src/components/segmented-button/constants.ts +0 -42
- package/src/components/slider/features/slider.ts +0 -318
- package/src/components/slider/features/structure.ts +0 -181
- package/src/components/slider/features/ui.ts +0 -388
- package/src/components/switch/constants.ts +0 -80
- package/src/components/tabs/constants.ts +0 -89
- package/src/components/textfield/constants.ts +0 -100
- package/src/components/timepicker/constants.ts +0 -138
- /package/src/{components/badge/_styles.scss → styles/components/_badge.scss} +0 -0
- /package/src/{components/bottom-app-bar/_styles.scss → styles/components/_bottom-app-bar.scss} +0 -0
- /package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -0
- /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
- /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
- /package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -0
- /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
- /package/src/{components/datepicker/_styles.scss → styles/components/_datepicker.scss} +0 -0
- /package/src/{components/dialog/_styles.scss → styles/components/_dialog.scss} +0 -0
- /package/src/{components/divider/_styles.scss → styles/components/_divider.scss} +0 -0
- /package/src/{components/extended-fab/_styles.scss → styles/components/_extended-fab.scss} +0 -0
- /package/src/{components/fab/_styles.scss → styles/components/_fab.scss} +0 -0
- /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
- /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
- /package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +0 -0
- /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
- /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
- /package/src/{components/search/_styles.scss → styles/components/_search.scss} +0 -0
- /package/src/{components/segmented-button/_styles.scss → styles/components/_segmented-button.scss} +0 -0
- /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
- /package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +0 -0
- /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
- /package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -0
- /package/src/{components/timepicker/_styles.scss → styles/components/_timepicker.scss} +0 -0
- /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
- /package/src/{components/top-app-bar/_styles.scss → styles/components/_top-app-bar.scss} +0 -0
- /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
// src/components/navigation/constants.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Navigation variants following Material Design 3
|
|
5
|
-
*/
|
|
6
|
-
export const NAV_VARIANTS = {
|
|
7
|
-
RAIL: 'rail', // Vertical slim navigation
|
|
8
|
-
DRAWER: 'drawer', // Expandable side navigation
|
|
9
|
-
BAR: 'bar', // Bottom or top navigation bar
|
|
10
|
-
DRAWER_MODAL: 'modal', // Modal drawer overlay
|
|
11
|
-
DRAWER_STANDARD: 'standard' // Standard permanent drawer
|
|
12
|
-
} as const;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Navigation positions
|
|
16
|
-
*/
|
|
17
|
-
export const NAV_POSITIONS = {
|
|
18
|
-
LEFT: 'left',
|
|
19
|
-
RIGHT: 'right',
|
|
20
|
-
TOP: 'top',
|
|
21
|
-
BOTTOM: 'bottom'
|
|
22
|
-
} as const;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Navigation behaviors
|
|
26
|
-
*/
|
|
27
|
-
export const NAV_BEHAVIORS = {
|
|
28
|
-
FIXED: 'fixed', // Always visible
|
|
29
|
-
DISMISSIBLE: 'dismissible', // Can be dismissed/hidden
|
|
30
|
-
MODAL: 'modal' // Overlays content with scrim
|
|
31
|
-
} as const;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Navigation state classes
|
|
35
|
-
*/
|
|
36
|
-
export const NAV_STATES = {
|
|
37
|
-
ACTIVE: 'active', // Currently selected item
|
|
38
|
-
DISABLED: 'disabled', // Disabled state
|
|
39
|
-
EXPANDED: 'expanded', // Drawer expanded state
|
|
40
|
-
COLLAPSED: 'collapsed', // Drawer collapsed state
|
|
41
|
-
HOVERED: 'hovered', // Hover state
|
|
42
|
-
FOCUSED: 'focused', // Keyboard focus state
|
|
43
|
-
PRESSED: 'pressed' // Press/click state
|
|
44
|
-
} as const;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Navigation element classes
|
|
48
|
-
*/
|
|
49
|
-
export const NAV_CLASSES = {
|
|
50
|
-
ROOT: 'nav',
|
|
51
|
-
ITEM: 'nav-item',
|
|
52
|
-
ITEM_CONTAINER: 'nav-item-container',
|
|
53
|
-
ICON: 'nav-item-icon',
|
|
54
|
-
LABEL: 'nav-item-label',
|
|
55
|
-
BADGE: 'nav-item-badge',
|
|
56
|
-
DIVIDER: 'nav-divider',
|
|
57
|
-
SCRIM: 'nav-scrim',
|
|
58
|
-
GROUP: 'nav-group',
|
|
59
|
-
GROUP_TITLE: 'nav-group-title',
|
|
60
|
-
SUBTITLE: 'nav-subtitle',
|
|
61
|
-
NESTED_CONTAINER: 'nav-nested-container',
|
|
62
|
-
NESTED_ITEM: 'nav-nested-item',
|
|
63
|
-
EXPAND_ICON: 'nav-expand-icon'
|
|
64
|
-
} as const;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Validation schema for navigation configuration
|
|
68
|
-
*/
|
|
69
|
-
export const NAV_SCHEMA = {
|
|
70
|
-
type: 'object',
|
|
71
|
-
properties: {
|
|
72
|
-
variant: {
|
|
73
|
-
type: 'string',
|
|
74
|
-
enum: Object.values(NAV_VARIANTS),
|
|
75
|
-
optional: true,
|
|
76
|
-
default: NAV_VARIANTS.RAIL
|
|
77
|
-
},
|
|
78
|
-
position: {
|
|
79
|
-
type: 'string',
|
|
80
|
-
enum: Object.values(NAV_POSITIONS),
|
|
81
|
-
optional: true,
|
|
82
|
-
default: NAV_POSITIONS.LEFT
|
|
83
|
-
},
|
|
84
|
-
behavior: {
|
|
85
|
-
type: 'string',
|
|
86
|
-
enum: Object.values(NAV_BEHAVIORS),
|
|
87
|
-
optional: true,
|
|
88
|
-
default: NAV_BEHAVIORS.FIXED
|
|
89
|
-
},
|
|
90
|
-
items: {
|
|
91
|
-
type: 'array',
|
|
92
|
-
optional: true,
|
|
93
|
-
default: []
|
|
94
|
-
},
|
|
95
|
-
groups: {
|
|
96
|
-
type: 'array',
|
|
97
|
-
optional: true
|
|
98
|
-
},
|
|
99
|
-
disabled: {
|
|
100
|
-
type: 'boolean',
|
|
101
|
-
optional: true
|
|
102
|
-
},
|
|
103
|
-
expanded: {
|
|
104
|
-
type: 'boolean',
|
|
105
|
-
optional: true
|
|
106
|
-
},
|
|
107
|
-
showLabels: {
|
|
108
|
-
type: 'boolean',
|
|
109
|
-
optional: true,
|
|
110
|
-
default: true
|
|
111
|
-
},
|
|
112
|
-
scrimEnabled: {
|
|
113
|
-
type: 'boolean',
|
|
114
|
-
optional: true,
|
|
115
|
-
default: false
|
|
116
|
-
},
|
|
117
|
-
class: {
|
|
118
|
-
type: 'string',
|
|
119
|
-
optional: true
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} as const;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Navigation item states
|
|
126
|
-
*/
|
|
127
|
-
export const NAV_ITEM_STATES = {
|
|
128
|
-
EXPANDED: 'expanded',
|
|
129
|
-
COLLAPSED: 'collapsed'
|
|
130
|
-
} as const;
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Navigation item schema
|
|
134
|
-
* Enhanced with support for nested items
|
|
135
|
-
*/
|
|
136
|
-
export const NAV_ITEM_SCHEMA = {
|
|
137
|
-
type: 'object',
|
|
138
|
-
properties: {
|
|
139
|
-
id: {
|
|
140
|
-
type: 'string',
|
|
141
|
-
required: true
|
|
142
|
-
},
|
|
143
|
-
icon: {
|
|
144
|
-
type: 'string',
|
|
145
|
-
required: true
|
|
146
|
-
},
|
|
147
|
-
label: {
|
|
148
|
-
type: 'string',
|
|
149
|
-
required: true
|
|
150
|
-
},
|
|
151
|
-
badge: {
|
|
152
|
-
type: 'string',
|
|
153
|
-
optional: true
|
|
154
|
-
},
|
|
155
|
-
disabled: {
|
|
156
|
-
type: 'boolean',
|
|
157
|
-
optional: true
|
|
158
|
-
},
|
|
159
|
-
subtitle: {
|
|
160
|
-
type: 'string',
|
|
161
|
-
optional: true
|
|
162
|
-
},
|
|
163
|
-
groupId: {
|
|
164
|
-
type: 'string',
|
|
165
|
-
optional: true
|
|
166
|
-
},
|
|
167
|
-
items: {
|
|
168
|
-
type: 'array',
|
|
169
|
-
optional: true,
|
|
170
|
-
description: 'Nested navigation items'
|
|
171
|
-
},
|
|
172
|
-
expanded: {
|
|
173
|
-
type: 'boolean',
|
|
174
|
-
optional: true,
|
|
175
|
-
default: false
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
} as const;
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Navigation group schema
|
|
182
|
-
*/
|
|
183
|
-
export const NAV_GROUP_SCHEMA = {
|
|
184
|
-
type: 'object',
|
|
185
|
-
properties: {
|
|
186
|
-
id: {
|
|
187
|
-
type: 'string',
|
|
188
|
-
required: true
|
|
189
|
-
},
|
|
190
|
-
title: {
|
|
191
|
-
type: 'string',
|
|
192
|
-
required: true
|
|
193
|
-
},
|
|
194
|
-
expanded: {
|
|
195
|
-
type: 'boolean',
|
|
196
|
-
optional: true,
|
|
197
|
-
default: true
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
} as const;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// src/components/progress/constants.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Progress component variants
|
|
5
|
-
*/
|
|
6
|
-
export const PROGRESS_VARIANTS = {
|
|
7
|
-
/** Standard linear progress bar */
|
|
8
|
-
LINEAR: 'linear',
|
|
9
|
-
|
|
10
|
-
/** Circular progress indicator */
|
|
11
|
-
CIRCULAR: 'circular',
|
|
12
|
-
|
|
13
|
-
/** Progress with known value */
|
|
14
|
-
DETERMINATE: 'determinate',
|
|
15
|
-
|
|
16
|
-
/** Indeterminate progress animation */
|
|
17
|
-
INDETERMINATE: 'indeterminate'
|
|
18
|
-
} as const;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Progress component events
|
|
22
|
-
*/
|
|
23
|
-
export const PROGRESS_EVENTS = {
|
|
24
|
-
/** Fired when value changes */
|
|
25
|
-
VALUE_CHANGE: 'valueChange',
|
|
26
|
-
|
|
27
|
-
/** Fired when component becomes determinate/indeterminate */
|
|
28
|
-
STATE_CHANGE: 'stateChange'
|
|
29
|
-
} as const;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// src/components/search/constants.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Available search component variants
|
|
5
|
-
*/
|
|
6
|
-
export const SEARCH_VARIANTS = {
|
|
7
|
-
BAR: 'bar',
|
|
8
|
-
VIEW: 'view'
|
|
9
|
-
} as const;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Available search component events
|
|
13
|
-
*/
|
|
14
|
-
export const SEARCH_EVENTS = {
|
|
15
|
-
FOCUS: 'focus',
|
|
16
|
-
BLUR: 'blur',
|
|
17
|
-
INPUT: 'input',
|
|
18
|
-
SUBMIT: 'submit',
|
|
19
|
-
CLEAR: 'clear',
|
|
20
|
-
ICON_CLICK: 'iconClick'
|
|
21
|
-
} as const;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// src/components/segmented-button/constants.ts
|
|
2
|
-
import { SelectionMode } from './types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Default checkbox icon SVG used for selected state
|
|
6
|
-
* @internal
|
|
7
|
-
*/
|
|
8
|
-
export const DEFAULT_CHECKMARK_ICON = `
|
|
9
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
10
|
-
<polyline points="20 6 9 17 4 12"></polyline>
|
|
11
|
-
</svg>`;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Default configuration values for segmented buttons
|
|
15
|
-
* @internal
|
|
16
|
-
*/
|
|
17
|
-
export const DEFAULT_CONFIG = {
|
|
18
|
-
mode: SelectionMode.SINGLE,
|
|
19
|
-
ripple: true
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Event names used by the segmented button component
|
|
24
|
-
* @internal
|
|
25
|
-
*/
|
|
26
|
-
export const EVENTS = {
|
|
27
|
-
CHANGE: 'change'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* CSS classes used by the segmented button component
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
export const CLASSES = {
|
|
35
|
-
CONTAINER: 'segmented-button',
|
|
36
|
-
SEGMENT: 'segmented-button-segment',
|
|
37
|
-
SELECTED: 'selected',
|
|
38
|
-
DISABLED: 'disabled',
|
|
39
|
-
ICON: 'icon',
|
|
40
|
-
CHECKMARK: 'checkmark',
|
|
41
|
-
TEXT: 'text'
|
|
42
|
-
};
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
// src/components/slider/features/slider.ts
|
|
2
|
-
import { SLIDER_EVENTS } from '../constants';
|
|
3
|
-
import { SliderConfig } from '../types';
|
|
4
|
-
import { createUiHelpers } from './ui';
|
|
5
|
-
import { createHandlers } from './handlers';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Add main slider functionality to component
|
|
9
|
-
* @param config Slider configuration
|
|
10
|
-
* @returns Component enhancer with slider functionality
|
|
11
|
-
*/
|
|
12
|
-
export const withSlider = (config: SliderConfig) => component => {
|
|
13
|
-
// Ensure component has events
|
|
14
|
-
if (!component.events) {
|
|
15
|
-
component.events = {
|
|
16
|
-
listeners: {},
|
|
17
|
-
on(event, handler) {
|
|
18
|
-
if (!this.listeners[event]) this.listeners[event] = [];
|
|
19
|
-
this.listeners[event].push(handler);
|
|
20
|
-
return this;
|
|
21
|
-
},
|
|
22
|
-
off(event, handler) {
|
|
23
|
-
if (this.listeners[event]) {
|
|
24
|
-
this.listeners[event] = this.listeners[event].filter(h => h !== handler);
|
|
25
|
-
}
|
|
26
|
-
return this;
|
|
27
|
-
},
|
|
28
|
-
trigger(event, data) {
|
|
29
|
-
if (this.listeners[event]) {
|
|
30
|
-
this.listeners[event].forEach(handler => handler(data));
|
|
31
|
-
}
|
|
32
|
-
return this;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Initialize state
|
|
38
|
-
const state = {
|
|
39
|
-
value: config.value !== undefined ? config.value : 0,
|
|
40
|
-
secondValue: config.secondValue !== undefined ? config.secondValue : null,
|
|
41
|
-
min: config.min !== undefined ? config.min : 0,
|
|
42
|
-
max: config.max !== undefined ? config.max : 100,
|
|
43
|
-
step: config.step !== undefined ? config.step : 1,
|
|
44
|
-
dragging: false,
|
|
45
|
-
activeBubble: null,
|
|
46
|
-
activeHandle: null,
|
|
47
|
-
ticks: [],
|
|
48
|
-
valueHideTimer: null,
|
|
49
|
-
component
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// Create event helpers
|
|
53
|
-
const eventHelpers = {
|
|
54
|
-
triggerEvent(eventName, originalEvent = null) {
|
|
55
|
-
const eventData = {
|
|
56
|
-
slider: state.component,
|
|
57
|
-
value: state.value,
|
|
58
|
-
secondValue: state.secondValue,
|
|
59
|
-
originalEvent,
|
|
60
|
-
preventDefault: () => { eventData.defaultPrevented = true; },
|
|
61
|
-
defaultPrevented: false
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
state.component.events.trigger(eventName, eventData);
|
|
65
|
-
return eventData;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// Create UI helpers and handlers
|
|
70
|
-
const uiHelpers = createUiHelpers(config, state);
|
|
71
|
-
const handlers = createHandlers(config, state, uiHelpers, eventHelpers);
|
|
72
|
-
|
|
73
|
-
// Initialize slider
|
|
74
|
-
const initSlider = () => {
|
|
75
|
-
// Set ARIA attributes
|
|
76
|
-
component.element.setAttribute('aria-valuemin', String(state.min));
|
|
77
|
-
component.element.setAttribute('aria-valuemax', String(state.max));
|
|
78
|
-
component.element.setAttribute('aria-valuenow', String(state.value));
|
|
79
|
-
|
|
80
|
-
if (!component.structure) {
|
|
81
|
-
console.warn('Cannot initialize slider: missing structure');
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const { handle, secondHandle } = component.structure;
|
|
86
|
-
|
|
87
|
-
if (handle) {
|
|
88
|
-
handle.setAttribute('aria-valuemin', String(state.min));
|
|
89
|
-
handle.setAttribute('aria-valuemax', String(state.max));
|
|
90
|
-
handle.setAttribute('aria-valuenow', String(state.value));
|
|
91
|
-
|
|
92
|
-
if (config.range && secondHandle && state.secondValue !== null) {
|
|
93
|
-
secondHandle.setAttribute('aria-valuemin', String(state.min));
|
|
94
|
-
secondHandle.setAttribute('aria-valuemax', String(state.max));
|
|
95
|
-
secondHandle.setAttribute('aria-valuenow', String(state.secondValue));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Initial UI update
|
|
100
|
-
uiHelpers.updateUi();
|
|
101
|
-
|
|
102
|
-
// Generate ticks if needed
|
|
103
|
-
if (config.ticks || config.tickLabels) {
|
|
104
|
-
uiHelpers.generateTicks();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Setup event listeners
|
|
108
|
-
handlers.setupEventListeners();
|
|
109
|
-
|
|
110
|
-
// Force one more UI update after a delay to ensure proper positioning
|
|
111
|
-
setTimeout(() => {
|
|
112
|
-
uiHelpers.updateUi();
|
|
113
|
-
}, 50);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// Register with lifecycle if available
|
|
117
|
-
if (component.lifecycle) {
|
|
118
|
-
const originalDestroy = component.lifecycle.destroy || (() => {});
|
|
119
|
-
component.lifecycle.destroy = () => {
|
|
120
|
-
handlers.cleanupEventListeners();
|
|
121
|
-
originalDestroy();
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Initialize slider
|
|
126
|
-
initSlider();
|
|
127
|
-
|
|
128
|
-
// Return enhanced component
|
|
129
|
-
return {
|
|
130
|
-
...component,
|
|
131
|
-
slider: {
|
|
132
|
-
/**
|
|
133
|
-
* Sets slider value
|
|
134
|
-
* @param value New value
|
|
135
|
-
* @param triggerEvent Whether to trigger change event
|
|
136
|
-
* @returns Slider controller for chaining
|
|
137
|
-
*/
|
|
138
|
-
setValue(value, triggerEvent = true) {
|
|
139
|
-
const newValue = uiHelpers.clamp(value, state.min, state.max);
|
|
140
|
-
state.value = newValue;
|
|
141
|
-
uiHelpers.updateUi();
|
|
142
|
-
|
|
143
|
-
if (triggerEvent) {
|
|
144
|
-
eventHelpers.triggerEvent(SLIDER_EVENTS.CHANGE);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return this;
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Gets slider value
|
|
152
|
-
* @returns Current value
|
|
153
|
-
*/
|
|
154
|
-
getValue() {
|
|
155
|
-
return state.value;
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Sets secondary slider value (for range slider)
|
|
160
|
-
* @param value New secondary value
|
|
161
|
-
* @param triggerEvent Whether to trigger change event
|
|
162
|
-
* @returns Slider controller for chaining
|
|
163
|
-
*/
|
|
164
|
-
setSecondValue(value, triggerEvent = true) {
|
|
165
|
-
if (!config.range) return this;
|
|
166
|
-
|
|
167
|
-
const newValue = uiHelpers.clamp(value, state.min, state.max);
|
|
168
|
-
state.secondValue = newValue;
|
|
169
|
-
uiHelpers.updateUi();
|
|
170
|
-
|
|
171
|
-
if (triggerEvent) {
|
|
172
|
-
eventHelpers.triggerEvent(SLIDER_EVENTS.CHANGE);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return this;
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Gets secondary slider value
|
|
180
|
-
* @returns Current secondary value or null
|
|
181
|
-
*/
|
|
182
|
-
getSecondValue() {
|
|
183
|
-
return config.range ? state.secondValue : null;
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Sets slider minimum value
|
|
188
|
-
* @param min New minimum value
|
|
189
|
-
* @returns Slider controller for chaining
|
|
190
|
-
*/
|
|
191
|
-
setMin(min) {
|
|
192
|
-
state.min = min;
|
|
193
|
-
|
|
194
|
-
// Update ARIA attributes
|
|
195
|
-
component.element.setAttribute('aria-valuemin', String(min));
|
|
196
|
-
if (component.structure.handle) {
|
|
197
|
-
component.structure.handle.setAttribute('aria-valuemin', String(min));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (config.range && component.structure.secondHandle) {
|
|
201
|
-
component.structure.secondHandle.setAttribute('aria-valuemin', String(min));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Clamp values to new min
|
|
205
|
-
if (state.value < min) state.value = min;
|
|
206
|
-
if (config.range && state.secondValue !== null && state.secondValue < min) {
|
|
207
|
-
state.secondValue = min;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Regenerate ticks if needed
|
|
211
|
-
if (config.ticks || config.tickLabels) {
|
|
212
|
-
uiHelpers.generateTicks();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
uiHelpers.updateUi();
|
|
216
|
-
return this;
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Gets slider minimum value
|
|
221
|
-
* @returns Current minimum value
|
|
222
|
-
*/
|
|
223
|
-
getMin() {
|
|
224
|
-
return state.min;
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Sets slider maximum value
|
|
229
|
-
* @param max New maximum value
|
|
230
|
-
* @returns Slider controller for chaining
|
|
231
|
-
*/
|
|
232
|
-
setMax(max) {
|
|
233
|
-
state.max = max;
|
|
234
|
-
|
|
235
|
-
// Update ARIA attributes
|
|
236
|
-
component.element.setAttribute('aria-valuemax', String(max));
|
|
237
|
-
if (component.structure.handle) {
|
|
238
|
-
component.structure.handle.setAttribute('aria-valuemax', String(max));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (config.range && component.structure.secondHandle) {
|
|
242
|
-
component.structure.secondHandle.setAttribute('aria-valuemax', String(max));
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Clamp values to new max
|
|
246
|
-
if (state.value > max) state.value = max;
|
|
247
|
-
if (config.range && state.secondValue !== null && state.secondValue > max) {
|
|
248
|
-
state.secondValue = max;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Regenerate ticks if needed
|
|
252
|
-
if (config.ticks || config.tickLabels) {
|
|
253
|
-
uiHelpers.generateTicks();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
uiHelpers.updateUi();
|
|
257
|
-
return this;
|
|
258
|
-
},
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Gets slider maximum value
|
|
262
|
-
* @returns Current maximum value
|
|
263
|
-
*/
|
|
264
|
-
getMax() {
|
|
265
|
-
return state.max;
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Sets slider step size
|
|
270
|
-
* @param step New step size
|
|
271
|
-
* @returns Slider controller for chaining
|
|
272
|
-
*/
|
|
273
|
-
setStep(step) {
|
|
274
|
-
state.step = step;
|
|
275
|
-
|
|
276
|
-
// Add or remove discrete class
|
|
277
|
-
component.element.classList[step > 0 ? 'add' : 'remove'](
|
|
278
|
-
`${component.getClass('slider')}--discrete`
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
// Regenerate ticks if needed
|
|
282
|
-
if (config.ticks || config.tickLabels) {
|
|
283
|
-
uiHelpers.generateTicks();
|
|
284
|
-
uiHelpers.updateTicks();
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return this;
|
|
288
|
-
},
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Gets slider step size
|
|
292
|
-
* @returns Current step size
|
|
293
|
-
*/
|
|
294
|
-
getStep() {
|
|
295
|
-
return state.step;
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Regenerate tick marks and labels
|
|
300
|
-
* @returns Slider controller for chaining
|
|
301
|
-
*/
|
|
302
|
-
regenerateTicks() {
|
|
303
|
-
uiHelpers.generateTicks();
|
|
304
|
-
uiHelpers.updateTicks();
|
|
305
|
-
return this;
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Update all UI elements
|
|
310
|
-
* @returns Slider controller for chaining
|
|
311
|
-
*/
|
|
312
|
-
updateUi() {
|
|
313
|
-
uiHelpers.updateUi();
|
|
314
|
-
return this;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
};
|