mtrl 0.2.4 → 0.2.6
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/package.json +6 -3
- package/src/components/badge/_styles.scss +9 -9
- package/src/components/button/_styles.scss +0 -56
- package/src/components/button/button.ts +0 -2
- package/src/components/button/constants.ts +0 -6
- package/src/components/button/index.ts +2 -2
- package/src/components/button/types.ts +1 -7
- package/src/components/card/_styles.scss +67 -25
- package/src/components/card/api.ts +54 -3
- package/src/components/card/card.ts +33 -2
- package/src/components/card/config.ts +143 -21
- package/src/components/card/constants.ts +20 -19
- package/src/components/card/content.ts +299 -2
- package/src/components/card/features.ts +155 -4
- package/src/components/card/index.ts +31 -9
- package/src/components/card/types.ts +138 -15
- package/src/components/chip/chip.ts +1 -9
- package/src/components/chip/constants.ts +0 -10
- package/src/components/chip/index.ts +1 -1
- package/src/components/chip/types.ts +1 -4
- package/src/components/progress/_styles.scss +0 -65
- package/src/components/progress/config.ts +1 -2
- package/src/components/progress/constants.ts +0 -14
- package/src/components/progress/index.ts +1 -1
- package/src/components/progress/progress.ts +1 -4
- package/src/components/progress/types.ts +1 -4
- package/src/components/radios/_styles.scss +0 -45
- package/src/components/radios/api.ts +85 -60
- package/src/components/radios/config.ts +1 -2
- package/src/components/radios/constants.ts +0 -9
- package/src/components/radios/index.ts +1 -1
- package/src/components/radios/radio.ts +34 -11
- package/src/components/radios/radios.ts +2 -1
- package/src/components/radios/types.ts +1 -7
- package/src/components/slider/_styles.scss +193 -281
- package/src/components/slider/accessibility.md +59 -0
- package/src/components/slider/api.ts +36 -101
- package/src/components/slider/config.ts +29 -78
- package/src/components/slider/constants.ts +12 -8
- package/src/components/slider/features/appearance.ts +1 -47
- package/src/components/slider/features/disabled.ts +41 -16
- package/src/components/slider/features/interactions.ts +166 -26
- package/src/components/slider/features/keyboard.ts +125 -6
- package/src/components/slider/features/structure.ts +182 -195
- package/src/components/slider/features/ui.ts +234 -303
- package/src/components/slider/index.ts +11 -1
- package/src/components/slider/slider.ts +1 -1
- package/src/components/slider/types.ts +10 -25
- package/src/components/tabs/_styles.scss +285 -155
- package/src/components/tabs/api.ts +178 -400
- package/src/components/tabs/config.ts +46 -52
- package/src/components/tabs/constants.ts +85 -8
- package/src/components/tabs/features.ts +401 -0
- package/src/components/tabs/index.ts +60 -3
- package/src/components/tabs/indicator.ts +225 -0
- package/src/components/tabs/responsive.ts +144 -0
- package/src/components/tabs/scroll-indicators.ts +149 -0
- package/src/components/tabs/state.ts +186 -0
- package/src/components/tabs/tab-api.ts +258 -0
- package/src/components/tabs/tab.ts +255 -0
- package/src/components/tabs/tabs.ts +50 -31
- package/src/components/tabs/types.ts +324 -128
- package/src/components/tabs/utils.ts +107 -0
- package/src/components/textfield/_styles.scss +0 -98
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/constants.ts +0 -14
- package/src/components/textfield/index.ts +2 -2
- package/src/components/textfield/textfield.ts +0 -2
- package/src/components/textfield/types.ts +1 -4
- package/src/core/compose/component.ts +1 -1
- package/src/core/compose/features/badge.ts +79 -0
- package/src/core/compose/features/index.ts +3 -1
- package/src/styles/abstract/_theme.scss +106 -2
- package/src/components/card/actions.ts +0 -48
- package/src/components/card/header.ts +0 -88
- package/src/components/card/media.ts +0 -52
|
@@ -1,36 +1,140 @@
|
|
|
1
1
|
// src/components/tabs/types.ts
|
|
2
|
-
import { TABS_VARIANTS } from './constants';
|
|
2
|
+
import { TABS_VARIANTS, TAB_STATES, TAB_LAYOUT } from './constants';
|
|
3
|
+
import { BadgeComponent } from '../badge/types';
|
|
4
|
+
import { TabIndicator } from './indicator';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
7
|
+
* Configuration for the tab indicator
|
|
6
8
|
* @category Components
|
|
7
9
|
*/
|
|
8
|
-
export interface
|
|
10
|
+
export interface IndicatorConfig {
|
|
11
|
+
/** Height of the indicator in pixels */
|
|
12
|
+
height?: number;
|
|
13
|
+
/** Width strategy for the indicator */
|
|
14
|
+
widthStrategy?: 'fixed' | 'dynamic' | 'content';
|
|
15
|
+
/** Fixed width in pixels (when using fixed strategy) */
|
|
16
|
+
fixedWidth?: number;
|
|
17
|
+
/** Animation duration in milliseconds */
|
|
18
|
+
animationDuration?: number;
|
|
19
|
+
/** Animation timing function */
|
|
20
|
+
animationTiming?: string;
|
|
21
|
+
/** Custom color for the indicator */
|
|
22
|
+
color?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Tab change event data interface
|
|
27
|
+
* @category Events
|
|
28
|
+
*/
|
|
29
|
+
export interface TabChangeEventData {
|
|
9
30
|
/**
|
|
10
|
-
*
|
|
31
|
+
* The tab component that was activated
|
|
11
32
|
*/
|
|
12
|
-
|
|
33
|
+
tab: TabComponent;
|
|
13
34
|
|
|
14
35
|
/**
|
|
15
|
-
*
|
|
36
|
+
* The value of the activated tab
|
|
16
37
|
*/
|
|
17
|
-
|
|
38
|
+
value: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Configuration interface for a single Tab
|
|
43
|
+
* @category Components
|
|
44
|
+
*/
|
|
45
|
+
export interface TabConfig {
|
|
46
|
+
/**
|
|
47
|
+
* Tab state that determines if it's the active destination
|
|
48
|
+
* @default 'inactive'
|
|
49
|
+
*/
|
|
50
|
+
state?: keyof typeof TAB_STATES | string;
|
|
18
51
|
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
52
|
+
/**
|
|
53
|
+
* Whether the tab is initially disabled
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Initial tab text content (label)
|
|
60
|
+
* @example 'Home'
|
|
61
|
+
*/
|
|
62
|
+
text?: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Initial tab icon HTML content
|
|
66
|
+
* @example '<svg>...</svg>'
|
|
21
67
|
*/
|
|
22
68
|
icon?: string;
|
|
23
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Badge text or value to display (if applicable)
|
|
72
|
+
* @example '5'
|
|
73
|
+
*/
|
|
74
|
+
badge?: string | number;
|
|
75
|
+
|
|
24
76
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
77
|
+
* Badge configuration object
|
|
78
|
+
* Pass additional options for the badge component
|
|
27
79
|
*/
|
|
28
|
-
|
|
80
|
+
badgeConfig?: {
|
|
81
|
+
variant?: string;
|
|
82
|
+
color?: string;
|
|
83
|
+
size?: string;
|
|
84
|
+
position?: string;
|
|
85
|
+
max?: number;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Icon size in pixels or other CSS units
|
|
90
|
+
* @default '24px'
|
|
91
|
+
*/
|
|
92
|
+
iconSize?: string;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Additional CSS classes to add to the tab
|
|
96
|
+
* @example 'home-tab main-navigation'
|
|
97
|
+
*/
|
|
98
|
+
class?: string;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Tab value attribute for identifying the selected tab
|
|
102
|
+
*/
|
|
103
|
+
value?: string;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Whether to enable ripple effect
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
ripple?: boolean;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Component prefix for class names
|
|
113
|
+
* @default 'mtrl'
|
|
114
|
+
*/
|
|
115
|
+
prefix?: string;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Component name used in class generation
|
|
119
|
+
*/
|
|
120
|
+
componentName?: string;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Ripple effect configuration
|
|
124
|
+
*/
|
|
125
|
+
rippleConfig?: {
|
|
126
|
+
/** Duration of the ripple animation in milliseconds */
|
|
127
|
+
duration?: number;
|
|
128
|
+
/** Timing function for the ripple animation */
|
|
129
|
+
timing?: string;
|
|
130
|
+
/** Opacity values for ripple start and end [start, end] */
|
|
131
|
+
opacity?: [string, string];
|
|
132
|
+
};
|
|
29
133
|
|
|
30
134
|
/**
|
|
31
|
-
*
|
|
135
|
+
* Variant of the tab
|
|
32
136
|
*/
|
|
33
|
-
|
|
137
|
+
variant?: string;
|
|
34
138
|
}
|
|
35
139
|
|
|
36
140
|
/**
|
|
@@ -39,209 +143,301 @@ export interface TabItem {
|
|
|
39
143
|
*/
|
|
40
144
|
export interface TabsConfig {
|
|
41
145
|
/**
|
|
42
|
-
* Tabs variant
|
|
146
|
+
* Tabs variant (primary or secondary)
|
|
43
147
|
* @default 'primary'
|
|
44
148
|
*/
|
|
45
149
|
variant?: keyof typeof TABS_VARIANTS | string;
|
|
46
150
|
|
|
47
151
|
/**
|
|
48
|
-
* Initial
|
|
152
|
+
* Initial tabs to create
|
|
49
153
|
*/
|
|
50
|
-
|
|
154
|
+
tabs?: TabConfig[];
|
|
51
155
|
|
|
52
156
|
/**
|
|
53
|
-
*
|
|
54
|
-
* @default
|
|
157
|
+
* Whether to show the divider
|
|
158
|
+
* @default true
|
|
55
159
|
*/
|
|
56
|
-
|
|
160
|
+
showDivider?: boolean;
|
|
57
161
|
|
|
58
162
|
/**
|
|
59
|
-
* Whether
|
|
60
|
-
* @default
|
|
163
|
+
* Whether to enable horizontal scrolling
|
|
164
|
+
* @default true
|
|
61
165
|
*/
|
|
62
|
-
|
|
166
|
+
scrollable?: boolean;
|
|
63
167
|
|
|
64
168
|
/**
|
|
65
|
-
*
|
|
66
|
-
* @default true
|
|
169
|
+
* Additional CSS classes for the container
|
|
67
170
|
*/
|
|
68
|
-
|
|
171
|
+
class?: string;
|
|
69
172
|
|
|
70
173
|
/**
|
|
71
|
-
*
|
|
72
|
-
* @default
|
|
174
|
+
* Component prefix for class names
|
|
175
|
+
* @default 'mtrl'
|
|
73
176
|
*/
|
|
74
|
-
|
|
177
|
+
prefix?: string;
|
|
75
178
|
|
|
76
179
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @default true
|
|
180
|
+
* Event handlers configuration
|
|
79
181
|
*/
|
|
80
|
-
|
|
182
|
+
on?: {
|
|
183
|
+
/**
|
|
184
|
+
* Tab change event handler
|
|
185
|
+
*/
|
|
186
|
+
change?: (event: TabChangeEventData) => void;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Event handlers for other events
|
|
190
|
+
*/
|
|
191
|
+
[key: string]: Function | undefined;
|
|
192
|
+
};
|
|
81
193
|
|
|
82
194
|
/**
|
|
83
|
-
*
|
|
195
|
+
* Tab indicator configuration
|
|
84
196
|
*/
|
|
85
|
-
|
|
197
|
+
indicator?: IndicatorConfig;
|
|
86
198
|
|
|
87
199
|
/**
|
|
88
|
-
*
|
|
89
|
-
* @
|
|
200
|
+
* Tab indicator height in pixels
|
|
201
|
+
* @deprecated Use indicator.height instead
|
|
90
202
|
*/
|
|
91
|
-
|
|
203
|
+
indicatorHeight?: number;
|
|
92
204
|
|
|
93
205
|
/**
|
|
94
|
-
*
|
|
206
|
+
* Tab indicator width strategy
|
|
207
|
+
* @deprecated Use indicator.widthStrategy instead
|
|
95
208
|
*/
|
|
96
|
-
|
|
209
|
+
indicatorWidthStrategy?: 'fixed' | 'dynamic' | 'content';
|
|
97
210
|
}
|
|
98
211
|
|
|
99
212
|
/**
|
|
100
|
-
*
|
|
213
|
+
* Icon API interface for managing tab icons
|
|
101
214
|
* @category Components
|
|
102
215
|
*/
|
|
103
|
-
export interface
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
/** The tab indicator DOM element */
|
|
111
|
-
indicatorElement: HTMLElement;
|
|
112
|
-
|
|
113
|
-
/** API for managing disabled state */
|
|
114
|
-
disabled: {
|
|
115
|
-
/** Enables the tabs component */
|
|
116
|
-
enable: () => void;
|
|
117
|
-
/** Disables the tabs component */
|
|
118
|
-
disable: () => void;
|
|
119
|
-
/** Checks if the tabs component is disabled */
|
|
120
|
-
isDisabled: () => boolean;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/** API for managing component lifecycle */
|
|
124
|
-
lifecycle: {
|
|
125
|
-
/** Destroys the component and cleans up resources */
|
|
126
|
-
destroy: () => void;
|
|
127
|
-
};
|
|
216
|
+
export interface IconAPI {
|
|
217
|
+
/**
|
|
218
|
+
* Sets the icon HTML content
|
|
219
|
+
* @param html - HTML string for the icon
|
|
220
|
+
* @returns The icon API for chaining
|
|
221
|
+
*/
|
|
222
|
+
setIcon: (html: string) => IconAPI;
|
|
128
223
|
|
|
129
224
|
/**
|
|
130
|
-
* Gets
|
|
131
|
-
* @
|
|
132
|
-
* @returns Prefixed class name
|
|
225
|
+
* Gets the current icon HTML content
|
|
226
|
+
* @returns HTML string for the icon
|
|
133
227
|
*/
|
|
134
|
-
|
|
228
|
+
getIcon: () => string;
|
|
135
229
|
|
|
136
230
|
/**
|
|
137
|
-
*
|
|
138
|
-
* @returns The
|
|
231
|
+
* Gets the icon DOM element
|
|
232
|
+
* @returns The icon element or null if not present
|
|
139
233
|
*/
|
|
140
|
-
|
|
234
|
+
getElement: () => HTMLElement | null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Text API interface for managing tab text
|
|
239
|
+
* @category Components
|
|
240
|
+
*/
|
|
241
|
+
export interface TextAPI {
|
|
242
|
+
/**
|
|
243
|
+
* Sets the text content
|
|
244
|
+
* @param content - Text content
|
|
245
|
+
* @returns The text API for chaining
|
|
246
|
+
*/
|
|
247
|
+
setText: (content: string) => TextAPI;
|
|
141
248
|
|
|
142
249
|
/**
|
|
143
|
-
*
|
|
144
|
-
* @returns
|
|
250
|
+
* Gets the current text content
|
|
251
|
+
* @returns Tab text content
|
|
145
252
|
*/
|
|
146
|
-
|
|
253
|
+
getText: () => string;
|
|
147
254
|
|
|
148
255
|
/**
|
|
149
|
-
* Gets
|
|
150
|
-
* @returns
|
|
256
|
+
* Gets the text DOM element
|
|
257
|
+
* @returns The text element or null if not present
|
|
151
258
|
*/
|
|
152
|
-
|
|
259
|
+
getElement: () => HTMLElement | null;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Tab component interface
|
|
264
|
+
* @category Components
|
|
265
|
+
*/
|
|
266
|
+
export interface TabComponent {
|
|
267
|
+
/** The tab's DOM element */
|
|
268
|
+
element: HTMLElement;
|
|
269
|
+
|
|
270
|
+
/** The tab's badge component (if any) */
|
|
271
|
+
badge?: BadgeComponent;
|
|
272
|
+
|
|
273
|
+
/** Gets a class name with the component's prefix */
|
|
274
|
+
getClass: (name: string) => string;
|
|
275
|
+
|
|
276
|
+
/** Gets the tab's value attribute */
|
|
277
|
+
getValue: () => string;
|
|
278
|
+
|
|
279
|
+
/** Sets the tab's value attribute */
|
|
280
|
+
setValue: (value: string) => TabComponent;
|
|
281
|
+
|
|
282
|
+
/** Activates the tab (sets active state) */
|
|
283
|
+
activate: () => TabComponent;
|
|
284
|
+
|
|
285
|
+
/** Deactivates the tab (sets inactive state) */
|
|
286
|
+
deactivate: () => TabComponent;
|
|
287
|
+
|
|
288
|
+
/** Checks if the tab is active */
|
|
289
|
+
isActive: () => boolean;
|
|
290
|
+
|
|
291
|
+
/** Enables the tab (removes disabled attribute) */
|
|
292
|
+
enable: () => TabComponent;
|
|
293
|
+
|
|
294
|
+
/** Disables the tab (adds disabled attribute) */
|
|
295
|
+
disable: () => TabComponent;
|
|
296
|
+
|
|
297
|
+
/** Sets the tab's text content */
|
|
298
|
+
setText: (content: string) => TabComponent;
|
|
299
|
+
|
|
300
|
+
/** Gets the tab's text content */
|
|
301
|
+
getText: () => string;
|
|
302
|
+
|
|
303
|
+
/** Sets the tab's icon */
|
|
304
|
+
setIcon: (icon: string) => TabComponent;
|
|
305
|
+
|
|
306
|
+
/** Gets the tab's icon HTML content */
|
|
307
|
+
getIcon: () => string;
|
|
153
308
|
|
|
309
|
+
/** Sets the tab's badge */
|
|
310
|
+
setBadge: (content: string | number) => TabComponent;
|
|
311
|
+
|
|
312
|
+
/** Gets the tab's badge content */
|
|
313
|
+
getBadge: () => string;
|
|
314
|
+
|
|
315
|
+
/** Shows the tab's badge */
|
|
316
|
+
showBadge: () => TabComponent;
|
|
317
|
+
|
|
318
|
+
/** Hides the tab's badge */
|
|
319
|
+
hideBadge: () => TabComponent;
|
|
320
|
+
|
|
321
|
+
/** Gets the badge component instance */
|
|
322
|
+
getBadgeComponent: () => BadgeComponent | undefined;
|
|
323
|
+
|
|
324
|
+
/** Updates the tab's layout style based on content */
|
|
325
|
+
updateLayoutStyle: () => void;
|
|
326
|
+
|
|
327
|
+
/** Adds an event listener to the tab */
|
|
328
|
+
on: (event: string, handler: Function) => TabComponent;
|
|
329
|
+
|
|
330
|
+
/** Removes an event listener from the tab */
|
|
331
|
+
off: (event: string, handler: Function) => TabComponent;
|
|
332
|
+
|
|
333
|
+
/** Destroys the tab component and cleans up resources */
|
|
334
|
+
destroy: () => void;
|
|
335
|
+
|
|
336
|
+
/** API for managing disabled state */
|
|
337
|
+
disabled?: {
|
|
338
|
+
enable: () => void;
|
|
339
|
+
disable: () => void;
|
|
340
|
+
isDisabled: () => boolean;
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
/** API for managing component lifecycle */
|
|
344
|
+
lifecycle?: {
|
|
345
|
+
destroy: () => void;
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Tabs component interface
|
|
351
|
+
* @category Components
|
|
352
|
+
*/
|
|
353
|
+
export interface TabsComponent {
|
|
154
354
|
/**
|
|
155
|
-
*
|
|
156
|
-
* @param items - Array of tab items
|
|
157
|
-
* @returns The tabs component for chaining
|
|
355
|
+
* Container element
|
|
158
356
|
*/
|
|
159
|
-
|
|
357
|
+
element: HTMLElement;
|
|
160
358
|
|
|
161
359
|
/**
|
|
162
|
-
*
|
|
163
|
-
* @param
|
|
164
|
-
* @
|
|
165
|
-
* @returns The tabs component for chaining
|
|
360
|
+
* Creates and adds a new tab to the tabs component
|
|
361
|
+
* @param config - Tab configuration
|
|
362
|
+
* @returns The created tab component
|
|
166
363
|
*/
|
|
167
|
-
addTab: (
|
|
364
|
+
addTab: (config: TabConfig) => TabComponent;
|
|
168
365
|
|
|
169
366
|
/**
|
|
170
|
-
*
|
|
171
|
-
* @param
|
|
172
|
-
* @returns
|
|
367
|
+
* Adds a pre-created tab to the tabs component
|
|
368
|
+
* @param tab - Tab component to add
|
|
369
|
+
* @returns Tabs component for chaining
|
|
173
370
|
*/
|
|
174
|
-
|
|
371
|
+
add: (tab: TabComponent) => TabsComponent;
|
|
175
372
|
|
|
176
373
|
/**
|
|
177
|
-
* Gets
|
|
178
|
-
* @returns
|
|
374
|
+
* Gets all tabs in the container
|
|
375
|
+
* @returns Array of tab components
|
|
179
376
|
*/
|
|
180
|
-
|
|
377
|
+
getTabs: () => TabComponent[];
|
|
181
378
|
|
|
182
379
|
/**
|
|
183
|
-
* Gets the
|
|
184
|
-
* @returns
|
|
380
|
+
* Gets the active tab
|
|
381
|
+
* @returns Active tab or null if none
|
|
185
382
|
*/
|
|
186
|
-
|
|
383
|
+
getActiveTab: () => TabComponent | null;
|
|
187
384
|
|
|
188
385
|
/**
|
|
189
|
-
*
|
|
190
|
-
* @
|
|
191
|
-
* @returns The tabs component for chaining
|
|
386
|
+
* Gets the indicator component
|
|
387
|
+
* @returns Tab indicator component
|
|
192
388
|
*/
|
|
193
|
-
|
|
389
|
+
getIndicator?: () => TabIndicator;
|
|
194
390
|
|
|
195
391
|
/**
|
|
196
|
-
* Sets
|
|
197
|
-
* @param
|
|
198
|
-
* @returns
|
|
392
|
+
* Sets a tab as active
|
|
393
|
+
* @param tabOrValue - Tab component or tab value
|
|
394
|
+
* @returns Tabs component for chaining
|
|
199
395
|
*/
|
|
200
|
-
|
|
396
|
+
setActiveTab: (tabOrValue: TabComponent | string) => TabsComponent;
|
|
201
397
|
|
|
202
398
|
/**
|
|
203
|
-
*
|
|
399
|
+
* Removes a tab from the container
|
|
400
|
+
* @param tabOrValue - Tab component or tab value
|
|
401
|
+
* @returns Tabs component for chaining
|
|
204
402
|
*/
|
|
205
|
-
|
|
403
|
+
removeTab: (tabOrValue: TabComponent | string) => TabsComponent;
|
|
206
404
|
|
|
207
405
|
/**
|
|
208
|
-
* Adds an event listener
|
|
209
|
-
* @param event - Event name
|
|
210
|
-
* @param handler - Event handler
|
|
211
|
-
* @returns
|
|
406
|
+
* Adds an event listener
|
|
407
|
+
* @param event - Event name
|
|
408
|
+
* @param handler - Event handler
|
|
409
|
+
* @returns Tabs component for chaining
|
|
212
410
|
*/
|
|
213
411
|
on: (event: string, handler: Function) => TabsComponent;
|
|
214
412
|
|
|
215
413
|
/**
|
|
216
|
-
* Removes an event listener
|
|
414
|
+
* Removes an event listener
|
|
217
415
|
* @param event - Event name
|
|
218
|
-
* @param handler - Event handler
|
|
219
|
-
* @returns
|
|
416
|
+
* @param handler - Event handler
|
|
417
|
+
* @returns Tabs component for chaining
|
|
220
418
|
*/
|
|
221
419
|
off: (event: string, handler: Function) => TabsComponent;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Event data for tab change events
|
|
226
|
-
*/
|
|
227
|
-
export interface TabChangeEventData {
|
|
420
|
+
|
|
228
421
|
/**
|
|
229
|
-
*
|
|
422
|
+
* Emit an event
|
|
423
|
+
* @param event - Event name
|
|
424
|
+
* @param data - Event data
|
|
425
|
+
* @returns Tabs component for chaining
|
|
230
426
|
*/
|
|
231
|
-
|
|
427
|
+
emit?: (event: string, data: any) => TabsComponent;
|
|
232
428
|
|
|
233
429
|
/**
|
|
234
|
-
*
|
|
430
|
+
* Destroys the tabs component and all tabs
|
|
235
431
|
*/
|
|
236
|
-
|
|
432
|
+
destroy: () => void;
|
|
237
433
|
|
|
238
434
|
/**
|
|
239
|
-
*
|
|
435
|
+
* Tab click event handler
|
|
240
436
|
*/
|
|
241
|
-
|
|
437
|
+
handleTabClick: (event: any, tab: TabComponent) => void;
|
|
242
438
|
|
|
243
439
|
/**
|
|
244
|
-
*
|
|
440
|
+
* Scroll container for scrollable tabs
|
|
245
441
|
*/
|
|
246
|
-
|
|
442
|
+
scrollContainer?: HTMLElement;
|
|
247
443
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/components/tabs/utils.ts
|
|
2
|
+
import { TabsComponent, TabComponent } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Gets the active tab from a component
|
|
6
|
+
* @param component - Component with tabs
|
|
7
|
+
* @returns Active tab or null
|
|
8
|
+
*/
|
|
9
|
+
export function getActiveTab(component: any): TabComponent | null {
|
|
10
|
+
// First try the standard method
|
|
11
|
+
if (typeof component.getActiveTab === 'function') {
|
|
12
|
+
return component.getActiveTab();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Fallback: check if component has tabs array
|
|
16
|
+
if (Array.isArray(component.tabs)) {
|
|
17
|
+
return component.tabs.find(tab => tab.isActive && tab.isActive());
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If all else fails, return null
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Updates tab panels based on active tab
|
|
26
|
+
* @param component - Component with tabs
|
|
27
|
+
*/
|
|
28
|
+
export function updateTabPanels(component: any): void {
|
|
29
|
+
// Get active tab using our helper function
|
|
30
|
+
const activeTab = getActiveTab(component);
|
|
31
|
+
if (!activeTab) return;
|
|
32
|
+
|
|
33
|
+
// Make sure getValue exists
|
|
34
|
+
if (typeof activeTab.getValue !== 'function') return;
|
|
35
|
+
|
|
36
|
+
const activeValue = activeTab.getValue();
|
|
37
|
+
|
|
38
|
+
// Find all tab panels in the document
|
|
39
|
+
const tabPanels = document.querySelectorAll(`[role="tabpanel"]`);
|
|
40
|
+
|
|
41
|
+
tabPanels.forEach(panel => {
|
|
42
|
+
// Get the associated tab value
|
|
43
|
+
const forTab = panel.getAttribute('aria-labelledby')?.replace('tab-', '');
|
|
44
|
+
|
|
45
|
+
if (forTab === activeValue) {
|
|
46
|
+
panel.removeAttribute('hidden');
|
|
47
|
+
panel.setAttribute('tabindex', '0');
|
|
48
|
+
} else {
|
|
49
|
+
panel.setAttribute('hidden', 'true');
|
|
50
|
+
panel.setAttribute('tabindex', '-1');
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Sets up keyboard navigation for tabs
|
|
57
|
+
* @param component - Tabs component
|
|
58
|
+
*/
|
|
59
|
+
export function setupKeyboardNavigation(component: any): void {
|
|
60
|
+
// Skip if element is missing
|
|
61
|
+
if (!component.element) return;
|
|
62
|
+
|
|
63
|
+
component.element.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
64
|
+
// Only handle arrow keys when tabs container has focus
|
|
65
|
+
if (event.target !== event.currentTarget) return;
|
|
66
|
+
|
|
67
|
+
// Skip if getTabs or setActiveTab don't exist
|
|
68
|
+
if (typeof component.getTabs !== 'function' ||
|
|
69
|
+
typeof component.setActiveTab !== 'function') return;
|
|
70
|
+
|
|
71
|
+
const tabs = component.getTabs();
|
|
72
|
+
const currentTab = getActiveTab(component);
|
|
73
|
+
const currentIndex = currentTab ? tabs.indexOf(currentTab) : -1;
|
|
74
|
+
|
|
75
|
+
let newIndex = currentIndex;
|
|
76
|
+
|
|
77
|
+
switch (event.key) {
|
|
78
|
+
case 'ArrowRight':
|
|
79
|
+
case 'ArrowDown':
|
|
80
|
+
newIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
|
|
81
|
+
break;
|
|
82
|
+
|
|
83
|
+
case 'ArrowLeft':
|
|
84
|
+
case 'ArrowUp':
|
|
85
|
+
newIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
|
|
86
|
+
break;
|
|
87
|
+
|
|
88
|
+
case 'Home':
|
|
89
|
+
newIndex = 0;
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
case 'End':
|
|
93
|
+
newIndex = tabs.length - 1;
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
default:
|
|
97
|
+
return; // Don't handle other keys
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// If a new tab should be focused
|
|
101
|
+
if (newIndex !== currentIndex && tabs[newIndex]) {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
tabs[newIndex].element.focus();
|
|
104
|
+
component.setActiveTab(tabs[newIndex]);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|