@hanzogui/tabs-headless 2.0.0
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/dist/cjs/index.cjs +18 -0
- package/dist/cjs/index.native.js +21 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/useTabs.cjs +258 -0
- package/dist/cjs/useTabs.native.js +276 -0
- package/dist/cjs/useTabs.native.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +2 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +2 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/useTabs.mjs +220 -0
- package/dist/esm/useTabs.mjs.map +1 -0
- package/dist/esm/useTabs.native.js +235 -0
- package/dist/esm/useTabs.native.js.map +1 -0
- package/dist/jsx/index.js +2 -0
- package/dist/jsx/index.js.map +1 -0
- package/dist/jsx/index.mjs +2 -0
- package/dist/jsx/index.mjs.map +1 -0
- package/dist/jsx/index.native.js +21 -0
- package/dist/jsx/index.native.js.map +1 -0
- package/dist/jsx/useTabs.mjs +220 -0
- package/dist/jsx/useTabs.mjs.map +1 -0
- package/dist/jsx/useTabs.native.js +276 -0
- package/dist/jsx/useTabs.native.js.map +1 -0
- package/package.json +49 -0
- package/src/index.ts +1 -0
- package/src/useTabs.tsx +406 -0
- package/types/index.d.ts +2 -0
- package/types/useTabs.d.ts +132 -0
package/src/useTabs.tsx
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { composeEventHandlers } from '@hanzogui/helpers'
|
|
2
|
+
import { useControllableState } from '@hanzogui/use-controllable-state'
|
|
3
|
+
import { useDirection } from '@hanzogui/use-direction'
|
|
4
|
+
import * as React from 'react'
|
|
5
|
+
import { useCallback, useId, useRef, useState } from 'react'
|
|
6
|
+
|
|
7
|
+
export type TabsActivationMode = 'automatic' | 'manual'
|
|
8
|
+
export type TabsOrientation = 'horizontal' | 'vertical'
|
|
9
|
+
export type Direction = 'ltr' | 'rtl'
|
|
10
|
+
|
|
11
|
+
// -------------------------------------------------------------------------------------------------
|
|
12
|
+
// useTabs
|
|
13
|
+
// -------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface UseTabsProps {
|
|
16
|
+
/** The value for the selected tab, if controlled */
|
|
17
|
+
value?: string
|
|
18
|
+
/** The value of the tab to select by default, if uncontrolled */
|
|
19
|
+
defaultValue?: string
|
|
20
|
+
/** A function called when a new tab is selected */
|
|
21
|
+
onValueChange?: (value: string) => void
|
|
22
|
+
/**
|
|
23
|
+
* The orientation the tabs are layed out.
|
|
24
|
+
* Mainly so arrow navigation is done accordingly (left & right vs. up & down)
|
|
25
|
+
* @defaultValue horizontal
|
|
26
|
+
*/
|
|
27
|
+
orientation?: TabsOrientation
|
|
28
|
+
/**
|
|
29
|
+
* The direction of navigation between toolbar items.
|
|
30
|
+
*/
|
|
31
|
+
dir?: Direction
|
|
32
|
+
/**
|
|
33
|
+
* Whether a tab is activated automatically (on focus) or manually (on click/enter).
|
|
34
|
+
* @defaultValue automatic
|
|
35
|
+
*/
|
|
36
|
+
activationMode?: TabsActivationMode
|
|
37
|
+
/**
|
|
38
|
+
* Whether keyboard navigation should loop from last to first and vice versa.
|
|
39
|
+
* @defaultValue true
|
|
40
|
+
*/
|
|
41
|
+
loop?: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface UseTabsReturn {
|
|
45
|
+
/** The currently selected tab value */
|
|
46
|
+
value: string
|
|
47
|
+
/** Function to change the selected tab */
|
|
48
|
+
setValue: (value: string) => void
|
|
49
|
+
/** The resolved text direction */
|
|
50
|
+
direction: Direction
|
|
51
|
+
/** Props to spread on the tabs container element */
|
|
52
|
+
tabsProps: {
|
|
53
|
+
'data-orientation': TabsOrientation
|
|
54
|
+
dir: Direction
|
|
55
|
+
}
|
|
56
|
+
/** Props to spread on the tab list element */
|
|
57
|
+
listProps: {
|
|
58
|
+
role: 'tablist'
|
|
59
|
+
'aria-orientation': TabsOrientation
|
|
60
|
+
}
|
|
61
|
+
/** Function to get props for a tab trigger */
|
|
62
|
+
getTabProps: (tabValue: string, disabled?: boolean) => TabTriggerProps
|
|
63
|
+
/** Function to get props for a tab content panel */
|
|
64
|
+
getContentProps: (tabValue: string) => TabContentProps
|
|
65
|
+
/** Context value to provide to child components */
|
|
66
|
+
contextValue: TabsContextValue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface TabTriggerProps {
|
|
70
|
+
role: 'tab'
|
|
71
|
+
id: string
|
|
72
|
+
'aria-selected': boolean
|
|
73
|
+
'aria-controls': string
|
|
74
|
+
'data-state': 'active' | 'inactive'
|
|
75
|
+
'data-disabled'?: ''
|
|
76
|
+
disabled?: boolean
|
|
77
|
+
tabIndex: number
|
|
78
|
+
onKeyDown: (event: React.KeyboardEvent) => void
|
|
79
|
+
onClick: (event: React.MouseEvent) => void
|
|
80
|
+
onFocus: (event: React.FocusEvent) => void
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface TabContentProps {
|
|
84
|
+
role: 'tabpanel'
|
|
85
|
+
id: string
|
|
86
|
+
'aria-labelledby': string
|
|
87
|
+
'data-state': 'active' | 'inactive'
|
|
88
|
+
'data-orientation': TabsOrientation
|
|
89
|
+
hidden: boolean
|
|
90
|
+
tabIndex: 0
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface TabsContextValue {
|
|
94
|
+
baseId: string
|
|
95
|
+
value: string
|
|
96
|
+
setValue: (value: string) => void
|
|
97
|
+
orientation: TabsOrientation
|
|
98
|
+
direction: Direction
|
|
99
|
+
activationMode: TabsActivationMode
|
|
100
|
+
loop: boolean
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function useTabs(props: UseTabsProps = {}): UseTabsReturn {
|
|
104
|
+
const {
|
|
105
|
+
value: valueProp,
|
|
106
|
+
onValueChange,
|
|
107
|
+
defaultValue = '',
|
|
108
|
+
orientation = 'horizontal',
|
|
109
|
+
dir,
|
|
110
|
+
activationMode = 'automatic',
|
|
111
|
+
loop = true,
|
|
112
|
+
} = props
|
|
113
|
+
|
|
114
|
+
const direction = useDirection(dir)
|
|
115
|
+
const baseId = useId()
|
|
116
|
+
|
|
117
|
+
const [value, setValue] = useControllableState({
|
|
118
|
+
prop: valueProp,
|
|
119
|
+
onChange: onValueChange,
|
|
120
|
+
defaultProp: defaultValue,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const tabRefs = useRef<Map<string, HTMLElement>>(new Map())
|
|
124
|
+
const [tabValues, setTabValues] = useState<string[]>([])
|
|
125
|
+
|
|
126
|
+
const registerTab = useCallback((tabValue: string, element: HTMLElement | null) => {
|
|
127
|
+
if (element) {
|
|
128
|
+
tabRefs.current.set(tabValue, element)
|
|
129
|
+
setTabValues((prev) => (prev.includes(tabValue) ? prev : [...prev, tabValue]))
|
|
130
|
+
} else {
|
|
131
|
+
tabRefs.current.delete(tabValue)
|
|
132
|
+
setTabValues((prev) => prev.filter((v) => v !== tabValue))
|
|
133
|
+
}
|
|
134
|
+
}, [])
|
|
135
|
+
|
|
136
|
+
const focusTab = useCallback((tabValue: string) => {
|
|
137
|
+
const element = tabRefs.current.get(tabValue)
|
|
138
|
+
element?.focus()
|
|
139
|
+
}, [])
|
|
140
|
+
|
|
141
|
+
const getNextTab = useCallback(
|
|
142
|
+
(currentValue: string, direction: 1 | -1): string | null => {
|
|
143
|
+
const currentIndex = tabValues.indexOf(currentValue)
|
|
144
|
+
if (currentIndex === -1) return null
|
|
145
|
+
|
|
146
|
+
let nextIndex = currentIndex + direction
|
|
147
|
+
if (loop) {
|
|
148
|
+
nextIndex = (nextIndex + tabValues.length) % tabValues.length
|
|
149
|
+
} else {
|
|
150
|
+
if (nextIndex < 0 || nextIndex >= tabValues.length) return null
|
|
151
|
+
}
|
|
152
|
+
return tabValues[nextIndex] ?? null
|
|
153
|
+
},
|
|
154
|
+
[tabValues, loop]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const handleKeyDown = useCallback(
|
|
158
|
+
(tabValue: string) => (event: React.KeyboardEvent) => {
|
|
159
|
+
const isHorizontal = orientation === 'horizontal'
|
|
160
|
+
const isRtl = direction === 'rtl'
|
|
161
|
+
|
|
162
|
+
let nextTab: string | null = null
|
|
163
|
+
|
|
164
|
+
switch (event.key) {
|
|
165
|
+
case 'ArrowRight':
|
|
166
|
+
if (isHorizontal) {
|
|
167
|
+
nextTab = getNextTab(tabValue, isRtl ? -1 : 1)
|
|
168
|
+
}
|
|
169
|
+
break
|
|
170
|
+
case 'ArrowLeft':
|
|
171
|
+
if (isHorizontal) {
|
|
172
|
+
nextTab = getNextTab(tabValue, isRtl ? 1 : -1)
|
|
173
|
+
}
|
|
174
|
+
break
|
|
175
|
+
case 'ArrowDown':
|
|
176
|
+
if (!isHorizontal) {
|
|
177
|
+
nextTab = getNextTab(tabValue, 1)
|
|
178
|
+
}
|
|
179
|
+
break
|
|
180
|
+
case 'ArrowUp':
|
|
181
|
+
if (!isHorizontal) {
|
|
182
|
+
nextTab = getNextTab(tabValue, -1)
|
|
183
|
+
}
|
|
184
|
+
break
|
|
185
|
+
case 'Home':
|
|
186
|
+
nextTab = tabValues[0] ?? null
|
|
187
|
+
break
|
|
188
|
+
case 'End':
|
|
189
|
+
nextTab = tabValues[tabValues.length - 1] ?? null
|
|
190
|
+
break
|
|
191
|
+
case ' ':
|
|
192
|
+
case 'Enter':
|
|
193
|
+
if (activationMode === 'manual') {
|
|
194
|
+
setValue(tabValue)
|
|
195
|
+
event.preventDefault()
|
|
196
|
+
}
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (nextTab) {
|
|
201
|
+
event.preventDefault()
|
|
202
|
+
focusTab(nextTab)
|
|
203
|
+
if (activationMode === 'automatic') {
|
|
204
|
+
setValue(nextTab)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
[orientation, direction, getNextTab, tabValues, activationMode, setValue, focusTab]
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
const getTabProps = useCallback(
|
|
212
|
+
(tabValue: string, disabled?: boolean): TabTriggerProps => {
|
|
213
|
+
const isSelected = value === tabValue
|
|
214
|
+
const triggerId = makeTriggerId(baseId, tabValue)
|
|
215
|
+
const contentId = makeContentId(baseId, tabValue)
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
role: 'tab',
|
|
219
|
+
id: triggerId,
|
|
220
|
+
'aria-selected': isSelected,
|
|
221
|
+
'aria-controls': contentId,
|
|
222
|
+
'data-state': isSelected ? 'active' : 'inactive',
|
|
223
|
+
...(disabled && { 'data-disabled': '' as const }),
|
|
224
|
+
disabled,
|
|
225
|
+
tabIndex: isSelected ? 0 : -1,
|
|
226
|
+
onKeyDown: disabled ? () => {} : handleKeyDown(tabValue),
|
|
227
|
+
onClick: (event: React.MouseEvent) => {
|
|
228
|
+
if (!disabled && !isSelected) {
|
|
229
|
+
setValue(tabValue)
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
onFocus: (event: React.FocusEvent) => {
|
|
233
|
+
registerTab(tabValue, event.currentTarget as HTMLElement)
|
|
234
|
+
if (!disabled && !isSelected && activationMode === 'automatic') {
|
|
235
|
+
setValue(tabValue)
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
[value, baseId, handleKeyDown, setValue, activationMode, registerTab]
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
const getContentProps = useCallback(
|
|
244
|
+
(tabValue: string): TabContentProps => {
|
|
245
|
+
const isSelected = value === tabValue
|
|
246
|
+
const triggerId = makeTriggerId(baseId, tabValue)
|
|
247
|
+
const contentId = makeContentId(baseId, tabValue)
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
role: 'tabpanel',
|
|
251
|
+
id: contentId,
|
|
252
|
+
'aria-labelledby': triggerId,
|
|
253
|
+
'data-state': isSelected ? 'active' : 'inactive',
|
|
254
|
+
'data-orientation': orientation,
|
|
255
|
+
hidden: !isSelected,
|
|
256
|
+
tabIndex: 0,
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
[value, baseId, orientation]
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
const contextValue: TabsContextValue = {
|
|
263
|
+
baseId,
|
|
264
|
+
value,
|
|
265
|
+
setValue,
|
|
266
|
+
orientation,
|
|
267
|
+
direction,
|
|
268
|
+
activationMode,
|
|
269
|
+
loop,
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
value,
|
|
274
|
+
setValue,
|
|
275
|
+
direction,
|
|
276
|
+
tabsProps: {
|
|
277
|
+
'data-orientation': orientation,
|
|
278
|
+
dir: direction,
|
|
279
|
+
},
|
|
280
|
+
listProps: {
|
|
281
|
+
role: 'tablist',
|
|
282
|
+
'aria-orientation': orientation,
|
|
283
|
+
},
|
|
284
|
+
getTabProps,
|
|
285
|
+
getContentProps,
|
|
286
|
+
contextValue,
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// -------------------------------------------------------------------------------------------------
|
|
291
|
+
// useTabsContext - for component-based APIs
|
|
292
|
+
// -------------------------------------------------------------------------------------------------
|
|
293
|
+
|
|
294
|
+
const TabsContext = React.createContext<TabsContextValue | null>(null)
|
|
295
|
+
|
|
296
|
+
export const TabsProvider = TabsContext.Provider
|
|
297
|
+
|
|
298
|
+
export function useTabsContext(): TabsContextValue {
|
|
299
|
+
const context = React.useContext(TabsContext)
|
|
300
|
+
if (!context) {
|
|
301
|
+
throw new Error('useTabsContext must be used within a TabsProvider')
|
|
302
|
+
}
|
|
303
|
+
return context
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// -------------------------------------------------------------------------------------------------
|
|
307
|
+
// useTab - hook for individual tab triggers
|
|
308
|
+
// -------------------------------------------------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
export interface UseTabProps {
|
|
311
|
+
value: string
|
|
312
|
+
disabled?: boolean
|
|
313
|
+
onPress?: (event: any) => void
|
|
314
|
+
onKeyDown?: (event: React.KeyboardEvent) => void
|
|
315
|
+
onFocus?: (event: React.FocusEvent) => void
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function useTab(props: UseTabProps) {
|
|
319
|
+
const { value: tabValue, disabled, onPress, onKeyDown, onFocus } = props
|
|
320
|
+
const context = useTabsContext()
|
|
321
|
+
const { value, setValue, baseId, activationMode, orientation, direction, loop } =
|
|
322
|
+
context
|
|
323
|
+
|
|
324
|
+
const isSelected = value === tabValue
|
|
325
|
+
const triggerId = makeTriggerId(baseId, tabValue)
|
|
326
|
+
const contentId = makeContentId(baseId, tabValue)
|
|
327
|
+
|
|
328
|
+
const ref = useRef<HTMLElement>(null)
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
isSelected,
|
|
332
|
+
tabProps: {
|
|
333
|
+
ref,
|
|
334
|
+
role: 'tab' as const,
|
|
335
|
+
id: triggerId,
|
|
336
|
+
'aria-selected': isSelected,
|
|
337
|
+
'aria-controls': contentId,
|
|
338
|
+
'data-state': isSelected ? 'active' : 'inactive',
|
|
339
|
+
...(disabled && { 'data-disabled': '' as const }),
|
|
340
|
+
disabled,
|
|
341
|
+
tabIndex: isSelected ? 0 : -1,
|
|
342
|
+
onKeyDown: composeEventHandlers(onKeyDown, (event: React.KeyboardEvent) => {
|
|
343
|
+
if (disabled) return
|
|
344
|
+
if ([' ', 'Enter'].includes(event.key)) {
|
|
345
|
+
setValue(tabValue)
|
|
346
|
+
event.preventDefault()
|
|
347
|
+
}
|
|
348
|
+
}),
|
|
349
|
+
onPress: composeEventHandlers(onPress, () => {
|
|
350
|
+
if (!disabled && !isSelected) {
|
|
351
|
+
setValue(tabValue)
|
|
352
|
+
}
|
|
353
|
+
}),
|
|
354
|
+
onFocus: composeEventHandlers(onFocus, () => {
|
|
355
|
+
if (!disabled && !isSelected && activationMode === 'automatic') {
|
|
356
|
+
setValue(tabValue)
|
|
357
|
+
}
|
|
358
|
+
}),
|
|
359
|
+
},
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// -------------------------------------------------------------------------------------------------
|
|
364
|
+
// useTabContent - hook for tab content panels
|
|
365
|
+
// -------------------------------------------------------------------------------------------------
|
|
366
|
+
|
|
367
|
+
export interface UseTabContentProps {
|
|
368
|
+
value: string
|
|
369
|
+
forceMount?: boolean
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function useTabContent(props: UseTabContentProps) {
|
|
373
|
+
const { value: tabValue, forceMount } = props
|
|
374
|
+
const context = useTabsContext()
|
|
375
|
+
const { value, baseId, orientation } = context
|
|
376
|
+
|
|
377
|
+
const isSelected = value === tabValue
|
|
378
|
+
const triggerId = makeTriggerId(baseId, tabValue)
|
|
379
|
+
const contentId = makeContentId(baseId, tabValue)
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
isSelected,
|
|
383
|
+
shouldMount: forceMount || isSelected,
|
|
384
|
+
contentProps: {
|
|
385
|
+
role: 'tabpanel' as const,
|
|
386
|
+
id: contentId,
|
|
387
|
+
'aria-labelledby': triggerId,
|
|
388
|
+
'data-state': isSelected ? 'active' : 'inactive',
|
|
389
|
+
'data-orientation': orientation,
|
|
390
|
+
hidden: !isSelected,
|
|
391
|
+
tabIndex: 0,
|
|
392
|
+
},
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// -------------------------------------------------------------------------------------------------
|
|
397
|
+
// Helpers
|
|
398
|
+
// -------------------------------------------------------------------------------------------------
|
|
399
|
+
|
|
400
|
+
function makeTriggerId(baseId: string, value: string) {
|
|
401
|
+
return `${baseId}-trigger-${value}`
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function makeContentId(baseId: string, value: string) {
|
|
405
|
+
return `${baseId}-content-${value}`
|
|
406
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type TabsActivationMode = 'automatic' | 'manual';
|
|
3
|
+
export type TabsOrientation = 'horizontal' | 'vertical';
|
|
4
|
+
export type Direction = 'ltr' | 'rtl';
|
|
5
|
+
export interface UseTabsProps {
|
|
6
|
+
/** The value for the selected tab, if controlled */
|
|
7
|
+
value?: string;
|
|
8
|
+
/** The value of the tab to select by default, if uncontrolled */
|
|
9
|
+
defaultValue?: string;
|
|
10
|
+
/** A function called when a new tab is selected */
|
|
11
|
+
onValueChange?: (value: string) => void;
|
|
12
|
+
/**
|
|
13
|
+
* The orientation the tabs are layed out.
|
|
14
|
+
* Mainly so arrow navigation is done accordingly (left & right vs. up & down)
|
|
15
|
+
* @defaultValue horizontal
|
|
16
|
+
*/
|
|
17
|
+
orientation?: TabsOrientation;
|
|
18
|
+
/**
|
|
19
|
+
* The direction of navigation between toolbar items.
|
|
20
|
+
*/
|
|
21
|
+
dir?: Direction;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a tab is activated automatically (on focus) or manually (on click/enter).
|
|
24
|
+
* @defaultValue automatic
|
|
25
|
+
*/
|
|
26
|
+
activationMode?: TabsActivationMode;
|
|
27
|
+
/**
|
|
28
|
+
* Whether keyboard navigation should loop from last to first and vice versa.
|
|
29
|
+
* @defaultValue true
|
|
30
|
+
*/
|
|
31
|
+
loop?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface UseTabsReturn {
|
|
34
|
+
/** The currently selected tab value */
|
|
35
|
+
value: string;
|
|
36
|
+
/** Function to change the selected tab */
|
|
37
|
+
setValue: (value: string) => void;
|
|
38
|
+
/** The resolved text direction */
|
|
39
|
+
direction: Direction;
|
|
40
|
+
/** Props to spread on the tabs container element */
|
|
41
|
+
tabsProps: {
|
|
42
|
+
'data-orientation': TabsOrientation;
|
|
43
|
+
dir: Direction;
|
|
44
|
+
};
|
|
45
|
+
/** Props to spread on the tab list element */
|
|
46
|
+
listProps: {
|
|
47
|
+
role: 'tablist';
|
|
48
|
+
'aria-orientation': TabsOrientation;
|
|
49
|
+
};
|
|
50
|
+
/** Function to get props for a tab trigger */
|
|
51
|
+
getTabProps: (tabValue: string, disabled?: boolean) => TabTriggerProps;
|
|
52
|
+
/** Function to get props for a tab content panel */
|
|
53
|
+
getContentProps: (tabValue: string) => TabContentProps;
|
|
54
|
+
/** Context value to provide to child components */
|
|
55
|
+
contextValue: TabsContextValue;
|
|
56
|
+
}
|
|
57
|
+
export interface TabTriggerProps {
|
|
58
|
+
role: 'tab';
|
|
59
|
+
id: string;
|
|
60
|
+
'aria-selected': boolean;
|
|
61
|
+
'aria-controls': string;
|
|
62
|
+
'data-state': 'active' | 'inactive';
|
|
63
|
+
'data-disabled'?: '';
|
|
64
|
+
disabled?: boolean;
|
|
65
|
+
tabIndex: number;
|
|
66
|
+
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
67
|
+
onClick: (event: React.MouseEvent) => void;
|
|
68
|
+
onFocus: (event: React.FocusEvent) => void;
|
|
69
|
+
}
|
|
70
|
+
export interface TabContentProps {
|
|
71
|
+
role: 'tabpanel';
|
|
72
|
+
id: string;
|
|
73
|
+
'aria-labelledby': string;
|
|
74
|
+
'data-state': 'active' | 'inactive';
|
|
75
|
+
'data-orientation': TabsOrientation;
|
|
76
|
+
hidden: boolean;
|
|
77
|
+
tabIndex: 0;
|
|
78
|
+
}
|
|
79
|
+
export interface TabsContextValue {
|
|
80
|
+
baseId: string;
|
|
81
|
+
value: string;
|
|
82
|
+
setValue: (value: string) => void;
|
|
83
|
+
orientation: TabsOrientation;
|
|
84
|
+
direction: Direction;
|
|
85
|
+
activationMode: TabsActivationMode;
|
|
86
|
+
loop: boolean;
|
|
87
|
+
}
|
|
88
|
+
export declare function useTabs(props?: UseTabsProps): UseTabsReturn;
|
|
89
|
+
export declare const TabsProvider: React.Provider<TabsContextValue | null>;
|
|
90
|
+
export declare function useTabsContext(): TabsContextValue;
|
|
91
|
+
export interface UseTabProps {
|
|
92
|
+
value: string;
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
onPress?: (event: any) => void;
|
|
95
|
+
onKeyDown?: (event: React.KeyboardEvent) => void;
|
|
96
|
+
onFocus?: (event: React.FocusEvent) => void;
|
|
97
|
+
}
|
|
98
|
+
export declare function useTab(props: UseTabProps): {
|
|
99
|
+
isSelected: boolean;
|
|
100
|
+
tabProps: {
|
|
101
|
+
disabled: boolean | undefined;
|
|
102
|
+
tabIndex: number;
|
|
103
|
+
onKeyDown: import("@gui/helpers").EventHandler<React.KeyboardEvent<Element>> | undefined;
|
|
104
|
+
onPress: import("@gui/helpers").EventHandler<any> | undefined;
|
|
105
|
+
onFocus: import("@gui/helpers").EventHandler<React.FocusEvent<Element, Element>> | undefined;
|
|
106
|
+
'data-disabled'?: "" | undefined;
|
|
107
|
+
ref: React.RefObject<HTMLElement | null>;
|
|
108
|
+
role: "tab";
|
|
109
|
+
id: string;
|
|
110
|
+
'aria-selected': boolean;
|
|
111
|
+
'aria-controls': string;
|
|
112
|
+
'data-state': string;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
export interface UseTabContentProps {
|
|
116
|
+
value: string;
|
|
117
|
+
forceMount?: boolean;
|
|
118
|
+
}
|
|
119
|
+
export declare function useTabContent(props: UseTabContentProps): {
|
|
120
|
+
isSelected: boolean;
|
|
121
|
+
shouldMount: boolean;
|
|
122
|
+
contentProps: {
|
|
123
|
+
role: "tabpanel";
|
|
124
|
+
id: string;
|
|
125
|
+
'aria-labelledby': string;
|
|
126
|
+
'data-state': string;
|
|
127
|
+
'data-orientation': TabsOrientation;
|
|
128
|
+
hidden: boolean;
|
|
129
|
+
tabIndex: number;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=useTabs.d.ts.map
|