@tamagui/select 2.7.6 → 3.0.0-beta.637.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/dist/cjs/Select.cjs +409 -467
- package/dist/cjs/Select.native.cjs +495 -0
- package/dist/cjs/Select.native.js +445 -492
- package/dist/cjs/Select.native.js.map +1 -1
- package/dist/cjs/SelectContent.cjs +80 -79
- package/dist/cjs/SelectContent.native.cjs +30 -0
- package/dist/cjs/SelectContent.native.js +18 -22
- package/dist/cjs/SelectContent.native.js.map +1 -1
- package/dist/cjs/SelectImpl.cjs +299 -319
- package/dist/cjs/SelectImpl.native.cjs +30 -0
- package/dist/cjs/SelectImpl.native.js +17 -24
- package/dist/cjs/SelectImpl.native.js.map +1 -1
- package/dist/cjs/SelectItem.cjs +268 -205
- package/dist/cjs/SelectItem.native.cjs +317 -0
- package/dist/cjs/SelectItem.native.js +291 -211
- package/dist/cjs/SelectItem.native.js.map +1 -1
- package/dist/cjs/SelectItemText.cjs +49 -79
- package/dist/cjs/SelectItemText.native.cjs +74 -0
- package/dist/cjs/SelectItemText.native.js +50 -79
- package/dist/cjs/SelectItemText.native.js.map +1 -1
- package/dist/cjs/SelectScrollButton.cjs +111 -130
- package/dist/cjs/SelectScrollButton.native.cjs +38 -0
- package/dist/cjs/SelectScrollButton.native.js +25 -22
- package/dist/cjs/SelectScrollButton.native.js.map +1 -1
- package/dist/cjs/SelectTrigger.cjs +69 -84
- package/dist/cjs/SelectTrigger.native.cjs +91 -0
- package/dist/cjs/SelectTrigger.native.js +71 -66
- package/dist/cjs/SelectTrigger.native.js.map +1 -1
- package/dist/cjs/SelectViewport.cjs +119 -142
- package/dist/cjs/SelectViewport.native.cjs +73 -0
- package/dist/cjs/SelectViewport.native.js +54 -50
- package/dist/cjs/SelectViewport.native.js.map +1 -1
- package/dist/cjs/constants.cjs +21 -22
- package/dist/cjs/constants.native.cjs +41 -0
- package/dist/cjs/constants.native.js +21 -21
- package/dist/cjs/constants.native.js.map +1 -1
- package/dist/cjs/context.cjs +38 -48
- package/dist/cjs/context.native.cjs +58 -0
- package/dist/cjs/context.native.js +40 -49
- package/dist/cjs/context.native.js.map +1 -1
- package/dist/cjs/index.cjs +15 -11
- package/dist/cjs/index.native.cjs +27 -0
- package/dist/cjs/index.native.js +15 -10
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/selectionController.cjs +334 -0
- package/dist/cjs/selectionController.native.cjs +403 -0
- package/dist/cjs/selectionController.native.js +405 -0
- package/dist/cjs/selectionController.native.js.map +1 -0
- package/dist/cjs/types.cjs +10 -11
- package/dist/cjs/types.native.cjs +19 -0
- package/dist/cjs/types.native.js +10 -10
- package/dist/cjs/types.native.js.map +1 -1
- package/dist/esm/Select.mjs +382 -443
- package/dist/esm/Select.mjs.map +1 -1
- package/dist/esm/Select.native.js +418 -469
- package/dist/esm/Select.native.js.map +1 -1
- package/dist/esm/SelectContent.mjs +67 -61
- package/dist/esm/SelectContent.mjs.map +1 -1
- package/dist/esm/SelectContent.native.js +4 -5
- package/dist/esm/SelectContent.native.js.map +1 -1
- package/dist/esm/SelectImpl.mjs +284 -294
- package/dist/esm/SelectImpl.mjs.map +1 -1
- package/dist/esm/SelectImpl.native.js +5 -8
- package/dist/esm/SelectImpl.native.js.map +1 -1
- package/dist/esm/SelectItem.mjs +252 -182
- package/dist/esm/SelectItem.mjs.map +1 -1
- package/dist/esm/SelectItem.native.js +276 -190
- package/dist/esm/SelectItem.native.js.map +1 -1
- package/dist/esm/SelectItemText.mjs +33 -55
- package/dist/esm/SelectItemText.mjs.map +1 -1
- package/dist/esm/SelectItemText.native.js +34 -56
- package/dist/esm/SelectItemText.native.js.map +1 -1
- package/dist/esm/SelectScrollButton.mjs +95 -107
- package/dist/esm/SelectScrollButton.mjs.map +1 -1
- package/dist/esm/SelectScrollButton.native.js +11 -7
- package/dist/esm/SelectScrollButton.native.js.map +1 -1
- package/dist/esm/SelectTrigger.mjs +56 -58
- package/dist/esm/SelectTrigger.mjs.map +1 -1
- package/dist/esm/SelectTrigger.native.js +54 -44
- package/dist/esm/SelectTrigger.native.js.map +1 -1
- package/dist/esm/SelectViewport.mjs +104 -119
- package/dist/esm/SelectViewport.mjs.map +1 -1
- package/dist/esm/SelectViewport.native.js +44 -39
- package/dist/esm/SelectViewport.native.js.map +1 -1
- package/dist/esm/constants.mjs +1 -0
- package/dist/esm/constants.mjs.map +1 -1
- package/dist/esm/constants.native.js +1 -0
- package/dist/esm/constants.native.js.map +1 -1
- package/dist/esm/context.mjs +20 -28
- package/dist/esm/context.mjs.map +1 -1
- package/dist/esm/context.native.js +23 -31
- package/dist/esm/context.native.js.map +1 -1
- package/dist/esm/index.js +13 -3
- package/dist/esm/index.mjs +13 -3
- package/dist/esm/index.native.js +13 -3
- package/dist/esm/selectionController.mjs +305 -0
- package/dist/esm/selectionController.mjs.map +1 -0
- package/dist/esm/selectionController.native.js +372 -0
- package/dist/esm/selectionController.native.js.map +1 -0
- package/dist/esm/types.mjs +0 -2
- package/dist/esm/types.native.js +0 -2
- package/dist/jsx/Select.mjs +382 -443
- package/dist/jsx/Select.mjs.map +1 -1
- package/dist/jsx/Select.native.cjs +495 -0
- package/dist/jsx/Select.native.js +445 -492
- package/dist/jsx/Select.native.js.map +1 -1
- package/dist/jsx/SelectContent.mjs +67 -61
- package/dist/jsx/SelectContent.mjs.map +1 -1
- package/dist/jsx/SelectContent.native.cjs +30 -0
- package/dist/jsx/SelectContent.native.js +18 -22
- package/dist/jsx/SelectContent.native.js.map +1 -1
- package/dist/jsx/SelectImpl.mjs +284 -294
- package/dist/jsx/SelectImpl.mjs.map +1 -1
- package/dist/jsx/SelectImpl.native.cjs +30 -0
- package/dist/jsx/SelectImpl.native.js +17 -24
- package/dist/jsx/SelectImpl.native.js.map +1 -1
- package/dist/jsx/SelectItem.mjs +252 -182
- package/dist/jsx/SelectItem.mjs.map +1 -1
- package/dist/jsx/SelectItem.native.cjs +317 -0
- package/dist/jsx/SelectItem.native.js +291 -211
- package/dist/jsx/SelectItem.native.js.map +1 -1
- package/dist/jsx/SelectItemText.mjs +33 -55
- package/dist/jsx/SelectItemText.mjs.map +1 -1
- package/dist/jsx/SelectItemText.native.cjs +74 -0
- package/dist/jsx/SelectItemText.native.js +50 -79
- package/dist/jsx/SelectItemText.native.js.map +1 -1
- package/dist/jsx/SelectScrollButton.mjs +95 -107
- package/dist/jsx/SelectScrollButton.mjs.map +1 -1
- package/dist/jsx/SelectScrollButton.native.cjs +38 -0
- package/dist/jsx/SelectScrollButton.native.js +25 -22
- package/dist/jsx/SelectScrollButton.native.js.map +1 -1
- package/dist/jsx/SelectTrigger.mjs +56 -58
- package/dist/jsx/SelectTrigger.mjs.map +1 -1
- package/dist/jsx/SelectTrigger.native.cjs +91 -0
- package/dist/jsx/SelectTrigger.native.js +71 -66
- package/dist/jsx/SelectTrigger.native.js.map +1 -1
- package/dist/jsx/SelectViewport.mjs +104 -119
- package/dist/jsx/SelectViewport.mjs.map +1 -1
- package/dist/jsx/SelectViewport.native.cjs +73 -0
- package/dist/jsx/SelectViewport.native.js +54 -50
- package/dist/jsx/SelectViewport.native.js.map +1 -1
- package/dist/jsx/constants.mjs +1 -0
- package/dist/jsx/constants.mjs.map +1 -1
- package/dist/jsx/constants.native.cjs +41 -0
- package/dist/jsx/constants.native.js +21 -21
- package/dist/jsx/constants.native.js.map +1 -1
- package/dist/jsx/context.mjs +20 -28
- package/dist/jsx/context.mjs.map +1 -1
- package/dist/jsx/context.native.cjs +58 -0
- package/dist/jsx/context.native.js +40 -49
- package/dist/jsx/context.native.js.map +1 -1
- package/dist/jsx/index.js +13 -3
- package/dist/jsx/index.mjs +13 -3
- package/dist/jsx/index.native.cjs +27 -0
- package/dist/jsx/index.native.js +15 -10
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/selectionController.mjs +305 -0
- package/dist/jsx/selectionController.mjs.map +1 -0
- package/dist/jsx/selectionController.native.cjs +403 -0
- package/dist/jsx/selectionController.native.js +405 -0
- package/dist/jsx/selectionController.native.js.map +1 -0
- package/dist/jsx/types.mjs +0 -2
- package/dist/jsx/types.native.cjs +19 -0
- package/dist/jsx/types.native.js +10 -10
- package/dist/jsx/types.native.js.map +1 -1
- package/package.json +28 -28
- package/src/Select.tsx +457 -357
- package/src/SelectContent.tsx +46 -16
- package/src/SelectImpl.native.tsx +0 -8
- package/src/SelectImpl.tsx +87 -100
- package/src/SelectItem.tsx +282 -136
- package/src/SelectItemText.tsx +16 -33
- package/src/SelectScrollButton.native.tsx +13 -4
- package/src/SelectScrollButton.tsx +56 -41
- package/src/SelectTrigger.tsx +77 -53
- package/src/SelectViewport.native.tsx +42 -25
- package/src/SelectViewport.tsx +52 -51
- package/src/context.tsx +6 -2
- package/src/index.tsx +5 -2
- package/src/selectionController.ts +389 -0
- package/src/types.tsx +88 -45
- package/types/Select.d.ts +139 -201
- package/types/Select.d.ts.map +1 -1
- package/types/SelectContent.d.ts +1 -1
- package/types/SelectContent.d.ts.map +1 -1
- package/types/SelectContent.native.d.ts.map +1 -1
- package/types/SelectImpl.d.ts +2 -1
- package/types/SelectImpl.d.ts.map +1 -1
- package/types/SelectImpl.native.d.ts +1 -5
- package/types/SelectImpl.native.d.ts.map +1 -1
- package/types/SelectItem.d.ts +13 -16
- package/types/SelectItem.d.ts.map +1 -1
- package/types/SelectItemText.d.ts +9 -13
- package/types/SelectItemText.d.ts.map +1 -1
- package/types/SelectScrollButton.d.ts +15 -2
- package/types/SelectScrollButton.d.ts.map +1 -1
- package/types/SelectScrollButton.native.d.ts +16 -3
- package/types/SelectScrollButton.native.d.ts.map +1 -1
- package/types/SelectTrigger.d.ts +11 -23
- package/types/SelectTrigger.d.ts.map +1 -1
- package/types/SelectViewport.d.ts +11 -38
- package/types/SelectViewport.d.ts.map +1 -1
- package/types/SelectViewport.native.d.ts +15 -4
- package/types/SelectViewport.native.d.ts.map +1 -1
- package/types/context.d.ts +2 -0
- package/types/context.d.ts.map +1 -1
- package/types/index.d.ts +5 -2
- package/types/index.d.ts.map +1 -1
- package/types/selectionController.d.ts +88 -0
- package/types/selectionController.d.ts.map +1 -0
- package/types/types.d.ts +47 -37
- package/types/types.d.ts.map +1 -1
- package/dist/cjs/BubbleSelect.cjs +0 -50
- package/dist/cjs/BubbleSelect.native.js +0 -30
- package/dist/cjs/BubbleSelect.native.js.map +0 -1
- package/dist/cjs/useSelectBreakpointActive.cjs +0 -32
- package/dist/cjs/useSelectBreakpointActive.native.js +0 -35
- package/dist/cjs/useSelectBreakpointActive.native.js.map +0 -1
- package/dist/esm/BubbleSelect.mjs +0 -27
- package/dist/esm/BubbleSelect.mjs.map +0 -1
- package/dist/esm/BubbleSelect.native.js +0 -4
- package/dist/esm/BubbleSelect.native.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/index.native.js.map +0 -1
- package/dist/esm/types.mjs.map +0 -1
- package/dist/esm/types.native.js.map +0 -1
- package/dist/esm/useSelectBreakpointActive.mjs +0 -7
- package/dist/esm/useSelectBreakpointActive.mjs.map +0 -1
- package/dist/esm/useSelectBreakpointActive.native.js +0 -7
- package/dist/esm/useSelectBreakpointActive.native.js.map +0 -1
- package/dist/jsx/BubbleSelect.mjs +0 -27
- package/dist/jsx/BubbleSelect.mjs.map +0 -1
- package/dist/jsx/BubbleSelect.native.js +0 -30
- package/dist/jsx/BubbleSelect.native.js.map +0 -1
- package/dist/jsx/index.js.map +0 -1
- package/dist/jsx/index.mjs.map +0 -1
- package/dist/jsx/types.mjs.map +0 -1
- package/dist/jsx/useSelectBreakpointActive.mjs +0 -7
- package/dist/jsx/useSelectBreakpointActive.mjs.map +0 -1
- package/dist/jsx/useSelectBreakpointActive.native.js +0 -35
- package/dist/jsx/useSelectBreakpointActive.native.js.map +0 -1
- package/src/BubbleSelect.tsx +0 -50
- package/src/useSelectBreakpointActive.tsx +0 -7
- package/types/BubbleSelect.d.ts +0 -2
- package/types/BubbleSelect.d.ts.map +0 -1
- package/types/useSelectBreakpointActive.d.ts +0 -3
- package/types/useSelectBreakpointActive.d.ts.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { createStyledHOC, styled, View } from '@tamagui/core'
|
|
1
2
|
import { autoUpdate, offset, useFloatingRaw as useFloating } from '@tamagui/floating'
|
|
2
3
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
3
4
|
import type { TamaguiElement } from '@tamagui/core'
|
|
4
|
-
import {
|
|
5
|
+
import { composeEventHandlers } from '@tamagui/helpers'
|
|
5
6
|
import * as React from 'react'
|
|
6
7
|
import { flushSync } from 'react-dom'
|
|
7
8
|
|
|
@@ -18,20 +19,24 @@ import type {
|
|
|
18
19
|
|
|
19
20
|
const SCROLL_UP_BUTTON_NAME = 'SelectScrollUpButton'
|
|
20
21
|
|
|
21
|
-
export const
|
|
22
|
-
|
|
23
|
-
SelectScrollButtonProps
|
|
24
|
-
>((props: SelectScopedProps<SelectScrollButtonProps>, forwardedRef) => {
|
|
25
|
-
return (
|
|
26
|
-
<SelectScrollButtonImpl
|
|
27
|
-
componentName={SCROLL_UP_BUTTON_NAME}
|
|
28
|
-
{...props}
|
|
29
|
-
dir="up"
|
|
30
|
-
ref={forwardedRef}
|
|
31
|
-
/>
|
|
32
|
-
)
|
|
22
|
+
export const SelectScrollButtonFrame = styled(View, {
|
|
23
|
+
displayName: 'SelectScrollButton',
|
|
33
24
|
})
|
|
34
25
|
|
|
26
|
+
export const SelectScrollUpButton = createStyledHOC(
|
|
27
|
+
SelectScrollButtonFrame,
|
|
28
|
+
(props: SelectScopedProps<SelectScrollButtonProps>, forwardedRef) => {
|
|
29
|
+
return (
|
|
30
|
+
<SelectScrollButtonImpl
|
|
31
|
+
partClassName={`is_${SCROLL_UP_BUTTON_NAME}`}
|
|
32
|
+
{...props}
|
|
33
|
+
dir="up"
|
|
34
|
+
ref={forwardedRef}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
35
40
|
SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME
|
|
36
41
|
|
|
37
42
|
/* -------------------------------------------------------------------------------------------------
|
|
@@ -40,29 +45,30 @@ SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME
|
|
|
40
45
|
|
|
41
46
|
const SCROLL_DOWN_BUTTON_NAME = 'SelectScrollDownButton'
|
|
42
47
|
|
|
43
|
-
export const SelectScrollDownButton =
|
|
44
|
-
|
|
45
|
-
SelectScrollButtonProps
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
export const SelectScrollDownButton = createStyledHOC(
|
|
49
|
+
SelectScrollButtonFrame,
|
|
50
|
+
(props: SelectScopedProps<SelectScrollButtonProps>, forwardedRef) => {
|
|
51
|
+
return (
|
|
52
|
+
<SelectScrollButtonImpl
|
|
53
|
+
partClassName={`is_${SCROLL_DOWN_BUTTON_NAME}`}
|
|
54
|
+
{...props}
|
|
55
|
+
dir="down"
|
|
56
|
+
ref={forwardedRef}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
56
61
|
|
|
57
62
|
SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME
|
|
58
63
|
|
|
59
|
-
type SelectScrollButtonImplElement = TamaguiElement
|
|
60
|
-
|
|
61
64
|
const SelectScrollButtonImpl = React.memo(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const {
|
|
65
|
+
createStyledHOC(
|
|
66
|
+
SelectScrollButtonFrame,
|
|
67
|
+
(props: SelectScrollButtonImplProps, forwardedRef) => {
|
|
68
|
+
const { scope, dir, partClassName, ...scrollIndicatorProps } = props
|
|
69
|
+
const { className, onPointerEnter, onPointerLeave, ...frameProps } =
|
|
70
|
+
scrollIndicatorProps
|
|
71
|
+
const { open, fallback, setScrollTop, setInnerOffset, ...context } =
|
|
66
72
|
useSelectContext(scope)
|
|
67
73
|
const floatingRef = context.floatingContext?.refs.floating
|
|
68
74
|
|
|
@@ -81,8 +87,17 @@ const SelectScrollButtonImpl = React.memo(
|
|
|
81
87
|
whileElementsMounted: (...args) => autoUpdate(...args, { animationFrame: true }),
|
|
82
88
|
})
|
|
83
89
|
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
const setFloatingRef = React.useCallback(
|
|
91
|
+
(node: TamaguiElement | null) => {
|
|
92
|
+
refs.setFloating(node as HTMLElement | null)
|
|
93
|
+
},
|
|
94
|
+
[refs.setFloating]
|
|
95
|
+
)
|
|
96
|
+
const composedRef = useComposedRefs(forwardedRef, setFloatingRef)
|
|
97
|
+
|
|
98
|
+
React.useEffect(() => {
|
|
99
|
+
return () => cancelAnimationFrame(frameRef.current)
|
|
100
|
+
}, [])
|
|
86
101
|
|
|
87
102
|
if (!isVisible) {
|
|
88
103
|
return null
|
|
@@ -102,17 +117,17 @@ const SelectScrollButtonImpl = React.memo(
|
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
return (
|
|
105
|
-
<
|
|
120
|
+
<SelectScrollButtonFrame
|
|
106
121
|
ref={composedRef}
|
|
107
|
-
|
|
122
|
+
className={`${partClassName} ${className || ''}`.trim()}
|
|
108
123
|
aria-hidden
|
|
109
|
-
{...
|
|
124
|
+
{...frameProps}
|
|
110
125
|
zIndex={1000}
|
|
111
126
|
position={strategy}
|
|
112
127
|
left={x || 0}
|
|
113
128
|
top={y || 0}
|
|
114
129
|
width={`calc(${(floatingRef?.current?.offsetWidth ?? 0) - 2}px)`}
|
|
115
|
-
onPointerEnter={() => {
|
|
130
|
+
onPointerEnter={composeEventHandlers(onPointerEnter as any, () => {
|
|
116
131
|
statusRef.current = 'active'
|
|
117
132
|
let prevNow = Date.now()
|
|
118
133
|
|
|
@@ -150,11 +165,11 @@ const SelectScrollButtonImpl = React.memo(
|
|
|
150
165
|
|
|
151
166
|
cancelAnimationFrame(frameRef.current)
|
|
152
167
|
frameRef.current = requestAnimationFrame(frame)
|
|
153
|
-
}}
|
|
154
|
-
onPointerLeave={() => {
|
|
168
|
+
})}
|
|
169
|
+
onPointerLeave={composeEventHandlers(onPointerLeave as any, () => {
|
|
155
170
|
statusRef.current = 'idle'
|
|
156
171
|
cancelAnimationFrame(frameRef.current)
|
|
157
|
-
}}
|
|
172
|
+
})}
|
|
158
173
|
/>
|
|
159
174
|
)
|
|
160
175
|
}
|
package/src/SelectTrigger.tsx
CHANGED
|
@@ -1,87 +1,111 @@
|
|
|
1
1
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
2
|
+
import { isWeb } from '@tamagui/constants'
|
|
3
|
+
import {
|
|
4
|
+
createChangeEventDetails,
|
|
5
|
+
createStyledHOC,
|
|
6
|
+
styled,
|
|
7
|
+
View,
|
|
8
|
+
type GetProps,
|
|
9
|
+
} from '@tamagui/core'
|
|
10
|
+
import { composeEventHandlers } from '@tamagui/helpers'
|
|
5
11
|
import * as React from 'react'
|
|
6
12
|
|
|
7
13
|
import { useSelectContext, useSelectItemParentContext } from './context'
|
|
8
|
-
import type { SelectScopedProps } from './types'
|
|
14
|
+
import type { SelectOpenChangeDetails, SelectScopedProps } from './types'
|
|
9
15
|
|
|
10
|
-
/* -------------------------------------------------------------------------------------------------
|
|
11
|
-
* SelectTrigger
|
|
12
|
-
* -----------------------------------------------------------------------------------------------*/
|
|
13
16
|
const TRIGGER_NAME = 'SelectTrigger'
|
|
14
17
|
|
|
15
|
-
export
|
|
18
|
+
export const SelectTriggerFrame = styled(View, {
|
|
19
|
+
displayName: TRIGGER_NAME,
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
flexDirection: 'row',
|
|
22
|
+
render: <button type="button" />,
|
|
23
|
+
})
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
typeof window !== 'undefined' && process.env.TAMAGUI_TARGET === 'web'
|
|
19
|
-
? window.matchMedia('(pointer:coarse)').matches
|
|
20
|
-
: true
|
|
25
|
+
export type SelectTriggerProps = SelectScopedProps<GetProps<typeof SelectTriggerFrame>>
|
|
21
26
|
|
|
22
|
-
export const SelectTrigger =
|
|
27
|
+
export const SelectTrigger = createStyledHOC(
|
|
28
|
+
SelectTriggerFrame,
|
|
23
29
|
function SelectTrigger(props: SelectTriggerProps, forwardedRef) {
|
|
24
|
-
const { scope, disabled = false,
|
|
25
|
-
|
|
30
|
+
const { scope, disabled = false, ...triggerProps } = props
|
|
26
31
|
const context = useSelectContext(scope)
|
|
27
32
|
const itemParentContext = useSelectItemParentContext(scope)
|
|
28
33
|
const composedRefs = useComposedRefs(
|
|
29
34
|
forwardedRef,
|
|
30
35
|
context.floatingContext?.refs.setReference as any
|
|
31
36
|
)
|
|
32
|
-
|
|
33
|
-
// const labelId = useLabelContext(context.trigger)
|
|
34
|
-
// const labelledBy = ariaLabelledby || labelId
|
|
37
|
+
|
|
35
38
|
if (itemParentContext.shouldRenderWebNative) {
|
|
36
39
|
return null
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
const toggleOpen = (
|
|
43
|
+
event?: any,
|
|
44
|
+
reason: 'trigger-press' | 'keyboard' = 'trigger-press'
|
|
45
|
+
) => {
|
|
46
|
+
if (!disabled) {
|
|
47
|
+
itemParentContext.requestOpenChange(
|
|
48
|
+
!context.open,
|
|
49
|
+
createChangeEventDetails(
|
|
50
|
+
reason,
|
|
51
|
+
event?.nativeEvent || event,
|
|
52
|
+
event?.currentTarget
|
|
53
|
+
) as SelectOpenChangeDetails
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const interactionProps =
|
|
58
|
+
process.env.TAMAGUI_TARGET === 'web' && itemParentContext.interactions
|
|
59
|
+
? itemParentContext.interactions.getReferenceProps({
|
|
60
|
+
...triggerProps,
|
|
61
|
+
onMouseDown: composeEventHandlers(triggerProps.onMouseDown as any, () =>
|
|
62
|
+
context.floatingContext?.update?.()
|
|
63
|
+
),
|
|
64
|
+
} as any)
|
|
65
|
+
: {
|
|
66
|
+
...triggerProps,
|
|
67
|
+
...(isWeb
|
|
68
|
+
? {
|
|
69
|
+
onMouseDown: composeEventHandlers(
|
|
70
|
+
triggerProps.onMouseDown as any,
|
|
71
|
+
(event: any) => {
|
|
72
|
+
event.preventDefault()
|
|
73
|
+
toggleOpen(event)
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
}
|
|
77
|
+
: {
|
|
78
|
+
onPress: composeEventHandlers(triggerProps.onPress as any, toggleOpen),
|
|
79
|
+
}),
|
|
80
|
+
onKeyDown: composeEventHandlers(
|
|
81
|
+
triggerProps.onKeyDown as any,
|
|
82
|
+
(event: any) => {
|
|
83
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
84
|
+
event.preventDefault()
|
|
85
|
+
toggleOpen(event, 'keyboard')
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
}
|
|
90
|
+
|
|
39
91
|
return (
|
|
40
|
-
<
|
|
41
|
-
componentName={TRIGGER_NAME}
|
|
42
|
-
unstyled={unstyled}
|
|
43
|
-
render="button"
|
|
92
|
+
<SelectTriggerFrame
|
|
44
93
|
type="button"
|
|
45
94
|
id={itemParentContext.id}
|
|
46
|
-
{...(!unstyled && {
|
|
47
|
-
focusVisibleStyle: {
|
|
48
|
-
outlineStyle: 'solid',
|
|
49
|
-
outlineWidth: 2,
|
|
50
|
-
outlineColor: '$outlineColor',
|
|
51
|
-
},
|
|
52
|
-
borderWidth: 1,
|
|
53
|
-
size: itemParentContext.size,
|
|
54
|
-
})}
|
|
55
95
|
role="combobox"
|
|
56
96
|
aria-haspopup="listbox"
|
|
57
97
|
aria-expanded={context.open}
|
|
98
|
+
{...(process.env.TAMAGUI_TARGET === 'web' && {
|
|
99
|
+
'data-state': context.open ? 'open' : 'closed',
|
|
100
|
+
})}
|
|
58
101
|
aria-autocomplete="none"
|
|
102
|
+
accessibilityRole={isWeb ? undefined : 'button'}
|
|
103
|
+
accessibilityState={isWeb ? undefined : { expanded: context.open, disabled }}
|
|
59
104
|
dir={context.dir}
|
|
60
105
|
disabled={disabled}
|
|
61
106
|
data-disabled={disabled ? '' : undefined}
|
|
62
|
-
{...
|
|
107
|
+
{...interactionProps}
|
|
63
108
|
ref={composedRefs}
|
|
64
|
-
{...(process.env.TAMAGUI_TARGET === 'web' && itemParentContext.interactions
|
|
65
|
-
? {
|
|
66
|
-
...itemParentContext.interactions.getReferenceProps(),
|
|
67
|
-
...(isPointerCoarse
|
|
68
|
-
? {
|
|
69
|
-
onPress() {
|
|
70
|
-
itemParentContext.setOpen(!context.open)
|
|
71
|
-
},
|
|
72
|
-
}
|
|
73
|
-
: {
|
|
74
|
-
onMouseDown() {
|
|
75
|
-
context.floatingContext?.update?.()
|
|
76
|
-
itemParentContext.setOpen(!context.open)
|
|
77
|
-
},
|
|
78
|
-
}),
|
|
79
|
-
}
|
|
80
|
-
: {
|
|
81
|
-
onPress() {
|
|
82
|
-
itemParentContext.setOpen(!context.open)
|
|
83
|
-
},
|
|
84
|
-
})}
|
|
85
109
|
/>
|
|
86
110
|
)
|
|
87
111
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
AdaptContext,
|
|
3
|
+
AdaptPortalContents,
|
|
4
|
+
useAdaptContext,
|
|
5
|
+
useAdaptIsActive,
|
|
6
|
+
} from '@tamagui/adapt'
|
|
7
|
+
import { createStyledHOC, styled, Theme, useThemeName, View } from '@tamagui/core'
|
|
4
8
|
|
|
5
9
|
import { VIEWPORT_NAME } from './constants'
|
|
6
10
|
import {
|
|
@@ -8,33 +12,46 @@ import {
|
|
|
8
12
|
useSelectContext,
|
|
9
13
|
useSelectItemParentContext,
|
|
10
14
|
} from './context'
|
|
11
|
-
import type { SelectViewportProps } from './types'
|
|
15
|
+
import type { SelectViewportExtraProps, SelectViewportProps } from './types'
|
|
16
|
+
|
|
17
|
+
export const SelectViewportFrame = styled(View, {
|
|
18
|
+
displayName: VIEWPORT_NAME,
|
|
19
|
+
position: 'relative',
|
|
20
|
+
})
|
|
12
21
|
|
|
13
|
-
export const SelectViewport = (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
export const SelectViewport = createStyledHOC(
|
|
23
|
+
SelectViewportFrame,
|
|
24
|
+
function SelectViewport(props: SelectViewportProps, forwardedRef) {
|
|
25
|
+
const { scope, children, disableScroll: _disableScroll, ...viewportProps } = props
|
|
26
|
+
const context = useSelectContext(scope)
|
|
27
|
+
const itemParentContext = useSelectItemParentContext(scope)
|
|
28
|
+
const themeName = useThemeName()
|
|
29
|
+
const adaptContext = useAdaptContext()
|
|
30
|
+
const isAdapted = useAdaptIsActive(context.adaptScope)
|
|
18
31
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
const contents = (
|
|
33
|
+
<Theme name={themeName}>
|
|
34
|
+
<ForwardSelectContext itemContext={itemParentContext} context={context}>
|
|
35
|
+
<AdaptContext.Provider {...adaptContext}>
|
|
36
|
+
<SelectViewportFrame {...viewportProps} ref={forwardedRef}>
|
|
37
|
+
{children}
|
|
38
|
+
</SelectViewportFrame>
|
|
39
|
+
</AdaptContext.Provider>
|
|
40
|
+
</ForwardSelectContext>
|
|
41
|
+
</Theme>
|
|
42
|
+
)
|
|
28
43
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
44
|
+
if (!context.open) {
|
|
45
|
+
if (context.lazyMount && context.renderValue) return null
|
|
46
|
+
return <SelectViewportFrame display="none">{contents}</SelectViewportFrame>
|
|
32
47
|
}
|
|
33
48
|
|
|
34
|
-
return
|
|
49
|
+
return isAdapted ? (
|
|
50
|
+
<AdaptPortalContents scope={context.adaptScope}>{contents}</AdaptPortalContents>
|
|
51
|
+
) : (
|
|
52
|
+
contents
|
|
53
|
+
)
|
|
35
54
|
}
|
|
36
|
-
|
|
37
|
-
return <AdaptPortalContents scope={context.adaptScope}>{contents}</AdaptPortalContents>
|
|
38
|
-
}
|
|
55
|
+
)
|
|
39
56
|
|
|
40
57
|
SelectViewport.displayName = VIEWPORT_NAME
|
package/src/SelectViewport.tsx
CHANGED
|
@@ -2,9 +2,9 @@ import { AdaptPortalContents, useAdaptIsActive } from '@tamagui/adapt'
|
|
|
2
2
|
import { AnimatePresence } from '@tamagui/animate-presence'
|
|
3
3
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
4
4
|
import { isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
5
|
-
import { styled } from '@tamagui/core'
|
|
5
|
+
import { createStyledHOC, styled, View } from '@tamagui/core'
|
|
6
6
|
import { needsPortalRepropagation } from '@tamagui/portal'
|
|
7
|
-
import {
|
|
7
|
+
import { YStack } from '@tamagui/stacks'
|
|
8
8
|
import { startTransition } from '@tamagui/start-transition'
|
|
9
9
|
import * as React from 'react'
|
|
10
10
|
import { VIEWPORT_NAME } from './constants'
|
|
@@ -13,51 +13,29 @@ import {
|
|
|
13
13
|
useSelectContext,
|
|
14
14
|
useSelectItemParentContext,
|
|
15
15
|
} from './context'
|
|
16
|
-
import type {
|
|
16
|
+
import type { SelectViewportProps } from './types'
|
|
17
|
+
import { getSelectListboxProps } from './selectionController'
|
|
17
18
|
|
|
18
19
|
/* -------------------------------------------------------------------------------------------------
|
|
19
20
|
* SelectViewport
|
|
20
21
|
* -----------------------------------------------------------------------------------------------*/
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
name: VIEWPORT_NAME,
|
|
26
|
-
|
|
27
|
-
variants: {
|
|
28
|
-
unstyled: {
|
|
29
|
-
false: {
|
|
30
|
-
size: '$2',
|
|
31
|
-
backgroundColor: '$background',
|
|
32
|
-
elevate: true,
|
|
33
|
-
bordered: true,
|
|
34
|
-
userSelect: 'none',
|
|
35
|
-
outlineWidth: 0,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
size: {
|
|
40
|
-
'...size': (val, { tokens }) => {
|
|
41
|
-
return {
|
|
42
|
-
borderRadius: tokens.radius[val] ?? val,
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
} as const,
|
|
47
|
-
|
|
48
|
-
defaultVariants: {
|
|
49
|
-
unstyled: process.env.TAMAGUI_HEADLESS === '1',
|
|
50
|
-
},
|
|
23
|
+
export const SelectViewportFrame = styled(View, {
|
|
24
|
+
displayName: VIEWPORT_NAME,
|
|
25
|
+
position: 'relative',
|
|
51
26
|
})
|
|
52
27
|
|
|
53
28
|
const needsRepropagation = needsPortalRepropagation()
|
|
54
29
|
|
|
55
|
-
export const SelectViewport =
|
|
56
|
-
|
|
30
|
+
export const SelectViewport = createStyledHOC(
|
|
31
|
+
SelectViewportFrame,
|
|
32
|
+
function SelectViewport(props: SelectViewportProps, forwardedRef) {
|
|
57
33
|
const { scope, children, disableScroll, ...viewportProps } = props
|
|
58
34
|
const context = useSelectContext(scope)
|
|
59
35
|
const itemContext = useSelectItemParentContext(scope)
|
|
60
36
|
const isAdapted = useAdaptIsActive(context.adaptScope)
|
|
37
|
+
const viewportRef = React.useRef<any>(null)
|
|
38
|
+
const registeredItemCount = itemContext.registry.getItems().length
|
|
61
39
|
|
|
62
40
|
// lazy mount: defer mounting children until first open using startTransition
|
|
63
41
|
const [lazyMounted, setLazyMounted] = React.useState(context.lazyMount ? false : true)
|
|
@@ -71,9 +49,25 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
71
49
|
})
|
|
72
50
|
}, [context.lazyMount, context.open, lazyMounted])
|
|
73
51
|
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
if (!isWeb || !isAdapted || !context.open) return
|
|
54
|
+
const frame = requestAnimationFrame(() => {
|
|
55
|
+
const index =
|
|
56
|
+
context.activeIndexRef.current ?? itemContext.registry.firstEnabledIndex()
|
|
57
|
+
const activeItem =
|
|
58
|
+
(viewportRef.current?.querySelector(
|
|
59
|
+
'[role="option"][tabindex="0"]'
|
|
60
|
+
) as HTMLElement | null) ??
|
|
61
|
+
(index >= 0 ? itemContext.listRef?.current[index] : null)
|
|
62
|
+
activeItem?.focus()
|
|
63
|
+
})
|
|
64
|
+
return () => cancelAnimationFrame(frame)
|
|
65
|
+
}, [context.activeIndex, context.open, isAdapted, registeredItemCount])
|
|
66
|
+
|
|
74
67
|
const composedRefs = useComposedRefs(
|
|
75
|
-
// @ts-ignore
|
|
68
|
+
// @ts-ignore react 19 ref type mismatch
|
|
76
69
|
forwardedRef,
|
|
70
|
+
viewportRef,
|
|
77
71
|
context.floatingContext?.refs.setFloating as any
|
|
78
72
|
)
|
|
79
73
|
|
|
@@ -85,18 +79,28 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
85
79
|
|
|
86
80
|
// after lazy children mount, force floating-ui to recompute so inner middleware
|
|
87
81
|
// can position using the now-present list items
|
|
88
|
-
|
|
82
|
+
React.useEffect(() => {
|
|
89
83
|
if (context.lazyMount && lazyMounted && context.open && context.update) {
|
|
90
|
-
context.update
|
|
84
|
+
const frame = requestAnimationFrame(context.update)
|
|
85
|
+
return () => cancelAnimationFrame(frame)
|
|
91
86
|
}
|
|
92
|
-
}, [lazyMounted])
|
|
87
|
+
}, [lazyMounted, registeredItemCount])
|
|
93
88
|
|
|
94
89
|
if (itemContext.shouldRenderWebNative) {
|
|
95
90
|
return <YStack position="relative">{children}</YStack>
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
if (isAdapted || !isWeb) {
|
|
99
|
-
let content =
|
|
94
|
+
let content = (
|
|
95
|
+
<SelectViewportFrame
|
|
96
|
+
{...viewportProps}
|
|
97
|
+
{...(isWeb ? (getSelectListboxProps(itemContext.mode) as any) : {})}
|
|
98
|
+
data-select-viewport=""
|
|
99
|
+
ref={composedRefs}
|
|
100
|
+
>
|
|
101
|
+
{lazyMounted ? children : null}
|
|
102
|
+
</SelectViewportFrame>
|
|
103
|
+
)
|
|
100
104
|
|
|
101
105
|
if (needsRepropagation) {
|
|
102
106
|
content = (
|
|
@@ -112,10 +116,6 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
if (!itemContext.interactions) {
|
|
115
|
-
if (process.env.NODE_ENV === 'development') {
|
|
116
|
-
console.warn(`No interactions provided to Select, potentially missing Adapt`)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
119
|
return null
|
|
120
120
|
}
|
|
121
121
|
|
|
@@ -130,7 +130,7 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
130
130
|
// that handles focus trapping and auto-focus
|
|
131
131
|
return (
|
|
132
132
|
<>
|
|
133
|
-
{!disableScroll &&
|
|
133
|
+
{!disableScroll && (
|
|
134
134
|
<style
|
|
135
135
|
dangerouslySetInnerHTML={{
|
|
136
136
|
__html: selectViewportCSS,
|
|
@@ -141,14 +141,15 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
141
141
|
{context.open ? (
|
|
142
142
|
<SelectViewportFrame
|
|
143
143
|
key="select-viewport"
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
data-select-viewport=""
|
|
145
|
+
{...(isWeb && {
|
|
146
|
+
'data-state': context.open ? 'open' : 'closed',
|
|
147
|
+
})}
|
|
146
148
|
{...viewportProps}
|
|
147
149
|
{...style}
|
|
148
150
|
{...floatingProps}
|
|
149
|
-
{...(
|
|
150
|
-
|
|
151
|
-
})}
|
|
151
|
+
{...getSelectListboxProps(itemContext.mode)}
|
|
152
|
+
overflowY={disableScroll ? undefined : (style.overflow ?? 'auto')}
|
|
152
153
|
ref={composedRefs}
|
|
153
154
|
>
|
|
154
155
|
{lazyMounted ? children : null}
|
|
@@ -167,13 +168,13 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
167
168
|
)
|
|
168
169
|
|
|
169
170
|
const selectViewportCSS = `
|
|
170
|
-
|
|
171
|
+
[data-select-viewport] {
|
|
171
172
|
scrollbar-width: none;
|
|
172
173
|
-webkit-overflow-scrolling: touch;
|
|
173
174
|
overscroll-behavior: contain;
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
|
|
177
|
+
[data-select-viewport]::-webkit-scrollbar{
|
|
177
178
|
display:none
|
|
178
179
|
}
|
|
179
180
|
`
|
package/src/context.tsx
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { createStyledContext } from '@tamagui/core'
|
|
2
2
|
import { getPortal } from '@tamagui/native'
|
|
3
|
-
import { createContext } from 'react'
|
|
3
|
+
import { createContext, type ComponentType } from 'react'
|
|
4
4
|
import type { SelectContextValue, SelectItemParentContextValue } from './types'
|
|
5
5
|
|
|
6
6
|
// zIndex flows from root Select prop to SelectContent portal
|
|
7
7
|
export const SelectZIndexContext = createContext<number | undefined>(undefined)
|
|
8
8
|
|
|
9
|
+
// the behavior surface renders a raw native select. the styled tamagui surface
|
|
10
|
+
// supplies its native-select skin through this slot.
|
|
11
|
+
export const SelectNativeComponentContext = createContext<ComponentType<any> | null>(null)
|
|
12
|
+
|
|
9
13
|
export const { Provider: SelectProvider, useStyledContext: useSelectContext } =
|
|
10
14
|
createStyledContext<SelectContextValue>(null as any, 'Select')
|
|
11
15
|
|
|
@@ -34,7 +38,7 @@ export const ForwardSelectContext = ({
|
|
|
34
38
|
|
|
35
39
|
// fall back to context forwarding for legacy portal implementations
|
|
36
40
|
return (
|
|
37
|
-
<SelectProvider
|
|
41
|
+
<SelectProvider scope={context.scopeName} {...context}>
|
|
38
42
|
<SelectItemParentProvider scope={context.scopeName} {...itemContext}>
|
|
39
43
|
{children}
|
|
40
44
|
</SelectItemParentProvider>
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export * from './Select'
|
|
2
|
+
export * from './SelectItem'
|
|
3
|
+
export * from './SelectItemText'
|
|
4
|
+
export * from './SelectScrollButton'
|
|
5
|
+
export * from './SelectTrigger'
|
|
6
|
+
export * from './SelectViewport'
|
|
2
7
|
export type * from './types'
|
|
3
8
|
export * from './context'
|
|
4
|
-
export type { SelectItemProps, SelectItemExtraProps } from './SelectItem'
|
|
5
|
-
export type { SelectTriggerProps } from './SelectTrigger'
|