@tamagui/select 2.0.0-rc.3 → 2.0.0-rc.30
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 +63 -55
- package/dist/cjs/Select.native.js +65 -57
- package/dist/cjs/Select.native.js.map +1 -1
- package/dist/cjs/SelectContent.cjs +41 -47
- package/dist/cjs/SelectImpl.cjs +42 -24
- package/dist/cjs/SelectItem.cjs +10 -3
- package/dist/cjs/SelectItem.native.js +9 -7
- package/dist/cjs/SelectItem.native.js.map +1 -1
- package/dist/cjs/SelectScrollButton.cjs +4 -4
- package/dist/cjs/SelectTrigger.cjs +1 -1
- package/dist/cjs/SelectViewport.cjs +44 -29
- package/dist/cjs/context.cjs +4 -1
- package/dist/cjs/context.native.js +3 -0
- package/dist/cjs/context.native.js.map +1 -1
- package/dist/cjs/index.js +12 -9
- package/dist/esm/Select.mjs +64 -56
- package/dist/esm/Select.mjs.map +1 -1
- package/dist/esm/Select.native.js +66 -58
- package/dist/esm/Select.native.js.map +1 -1
- package/dist/esm/SelectContent.mjs +38 -33
- package/dist/esm/SelectContent.mjs.map +1 -1
- package/dist/esm/SelectImpl.mjs +38 -20
- package/dist/esm/SelectImpl.mjs.map +1 -1
- package/dist/esm/SelectItem.mjs +10 -3
- package/dist/esm/SelectItem.mjs.map +1 -1
- package/dist/esm/SelectItem.native.js +9 -7
- package/dist/esm/SelectItem.native.js.map +1 -1
- package/dist/esm/SelectScrollButton.mjs +1 -1
- package/dist/esm/SelectScrollButton.mjs.map +1 -1
- package/dist/esm/SelectTrigger.mjs +1 -1
- package/dist/esm/SelectTrigger.mjs.map +1 -1
- package/dist/esm/SelectViewport.mjs +28 -24
- package/dist/esm/SelectViewport.mjs.map +1 -1
- package/dist/esm/context.mjs +4 -2
- package/dist/esm/context.mjs.map +1 -1
- package/dist/esm/context.native.js +4 -2
- package/dist/esm/context.native.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -6
- package/dist/jsx/Select.mjs +64 -56
- package/dist/jsx/Select.mjs.map +1 -1
- package/dist/jsx/Select.native.js +65 -57
- package/dist/jsx/Select.native.js.map +1 -1
- package/dist/jsx/SelectContent.mjs +38 -33
- package/dist/jsx/SelectContent.mjs.map +1 -1
- package/dist/jsx/SelectImpl.mjs +38 -20
- package/dist/jsx/SelectImpl.mjs.map +1 -1
- package/dist/jsx/SelectItem.mjs +10 -3
- package/dist/jsx/SelectItem.mjs.map +1 -1
- package/dist/jsx/SelectItem.native.js +9 -7
- package/dist/jsx/SelectItem.native.js.map +1 -1
- package/dist/jsx/SelectScrollButton.mjs +1 -1
- package/dist/jsx/SelectScrollButton.mjs.map +1 -1
- package/dist/jsx/SelectTrigger.mjs +1 -1
- package/dist/jsx/SelectTrigger.mjs.map +1 -1
- package/dist/jsx/SelectViewport.mjs +28 -24
- package/dist/jsx/SelectViewport.mjs.map +1 -1
- package/dist/jsx/context.mjs +4 -2
- package/dist/jsx/context.mjs.map +1 -1
- package/dist/jsx/context.native.js +3 -0
- package/dist/jsx/context.native.js.map +1 -1
- package/dist/jsx/index.js +2 -2
- package/dist/jsx/index.js.map +1 -6
- package/package.json +31 -35
- package/src/Select.tsx +16 -1
- package/src/SelectContent.tsx +47 -36
- package/src/SelectImpl.tsx +51 -49
- package/src/SelectItem.tsx +17 -7
- package/src/SelectScrollButton.tsx +1 -1
- package/src/SelectTrigger.tsx +1 -1
- package/src/SelectViewport.tsx +42 -22
- package/src/context.tsx +4 -0
- package/src/types.tsx +44 -4
- package/types/Select.d.ts +2 -2
- 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/SelectImpl.d.ts.map +1 -1
- package/types/SelectItem.d.ts.map +1 -1
- package/types/SelectTrigger.d.ts +1 -1
- package/types/SelectViewport.d.ts.map +1 -1
- package/types/context.d.ts +1 -0
- package/types/context.d.ts.map +1 -1
- package/types/types.d.ts +33 -3
- package/types/types.d.ts.map +1 -1
- package/dist/cjs/BubbleSelect.js +0 -34
- package/dist/cjs/BubbleSelect.js.map +0 -6
- package/dist/cjs/Select.js +0 -402
- package/dist/cjs/Select.js.map +0 -6
- package/dist/cjs/SelectContent.js +0 -57
- package/dist/cjs/SelectContent.js.map +0 -6
- package/dist/cjs/SelectImpl.js +0 -222
- package/dist/cjs/SelectImpl.js.map +0 -6
- package/dist/cjs/SelectItem.js +0 -166
- package/dist/cjs/SelectItem.js.map +0 -6
- package/dist/cjs/SelectItemText.js +0 -64
- package/dist/cjs/SelectItemText.js.map +0 -6
- package/dist/cjs/SelectScrollButton.js +0 -105
- package/dist/cjs/SelectScrollButton.js.map +0 -6
- package/dist/cjs/SelectTrigger.js +0 -81
- package/dist/cjs/SelectTrigger.js.map +0 -6
- package/dist/cjs/SelectViewport.js +0 -114
- package/dist/cjs/SelectViewport.js.map +0 -6
- package/dist/cjs/constants.js +0 -27
- package/dist/cjs/constants.js.map +0 -6
- package/dist/cjs/context.js +0 -33
- package/dist/cjs/context.js.map +0 -6
- package/dist/cjs/types.js +0 -14
- package/dist/cjs/types.js.map +0 -6
- package/dist/cjs/useSelectBreakpointActive.js +0 -25
- package/dist/cjs/useSelectBreakpointActive.js.map +0 -6
- package/dist/esm/BubbleSelect.js +0 -17
- package/dist/esm/BubbleSelect.js.map +0 -6
- package/dist/esm/Select.js +0 -412
- package/dist/esm/Select.js.map +0 -6
- package/dist/esm/SelectContent.js +0 -39
- package/dist/esm/SelectContent.js.map +0 -6
- package/dist/esm/SelectImpl.js +0 -223
- package/dist/esm/SelectImpl.js.map +0 -6
- package/dist/esm/SelectItem.js +0 -148
- package/dist/esm/SelectItem.js.map +0 -6
- package/dist/esm/SelectItemText.js +0 -46
- package/dist/esm/SelectItemText.js.map +0 -6
- package/dist/esm/SelectScrollButton.js +0 -87
- package/dist/esm/SelectScrollButton.js.map +0 -6
- package/dist/esm/SelectTrigger.js +0 -61
- package/dist/esm/SelectTrigger.js.map +0 -6
- package/dist/esm/SelectViewport.js +0 -112
- package/dist/esm/SelectViewport.js.map +0 -6
- package/dist/esm/constants.js +0 -11
- package/dist/esm/constants.js.map +0 -6
- package/dist/esm/context.js +0 -19
- package/dist/esm/context.js.map +0 -6
- package/dist/esm/types.js +0 -1
- package/dist/esm/types.js.map +0 -6
- package/dist/esm/useSelectBreakpointActive.js +0 -9
- package/dist/esm/useSelectBreakpointActive.js.map +0 -6
- package/dist/jsx/BubbleSelect.js +0 -17
- package/dist/jsx/BubbleSelect.js.map +0 -6
- package/dist/jsx/Select.js +0 -412
- package/dist/jsx/Select.js.map +0 -6
- package/dist/jsx/SelectContent.js +0 -39
- package/dist/jsx/SelectContent.js.map +0 -6
- package/dist/jsx/SelectImpl.js +0 -223
- package/dist/jsx/SelectImpl.js.map +0 -6
- package/dist/jsx/SelectItem.js +0 -148
- package/dist/jsx/SelectItem.js.map +0 -6
- package/dist/jsx/SelectItemText.js +0 -46
- package/dist/jsx/SelectItemText.js.map +0 -6
- package/dist/jsx/SelectScrollButton.js +0 -87
- package/dist/jsx/SelectScrollButton.js.map +0 -6
- package/dist/jsx/SelectTrigger.js +0 -61
- package/dist/jsx/SelectTrigger.js.map +0 -6
- package/dist/jsx/SelectViewport.js +0 -112
- package/dist/jsx/SelectViewport.js.map +0 -6
- package/dist/jsx/constants.js +0 -11
- package/dist/jsx/constants.js.map +0 -6
- package/dist/jsx/context.js +0 -19
- package/dist/jsx/context.js.map +0 -6
- package/dist/jsx/types.js +0 -1
- package/dist/jsx/types.js.map +0 -6
- package/dist/jsx/useSelectBreakpointActive.js +0 -9
- package/dist/jsx/useSelectBreakpointActive.js.map +0 -6
package/src/SelectImpl.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { SideObject } from '@floating-ui/react'
|
|
2
1
|
import {
|
|
3
2
|
autoUpdate,
|
|
4
3
|
flip,
|
|
@@ -7,14 +6,15 @@ import {
|
|
|
7
6
|
shift,
|
|
8
7
|
size,
|
|
9
8
|
useClick,
|
|
10
|
-
|
|
11
|
-
useFloating,
|
|
12
|
-
useInnerOffset,
|
|
9
|
+
useFloatingRaw as useFloatingDom,
|
|
13
10
|
useInteractions,
|
|
11
|
+
useInnerOffset,
|
|
14
12
|
useListNavigation,
|
|
15
13
|
useRole,
|
|
16
14
|
useTypeahead,
|
|
17
|
-
|
|
15
|
+
type FloatingInteractionContext,
|
|
16
|
+
type SideObject,
|
|
17
|
+
} from '@tamagui/floating'
|
|
18
18
|
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
19
19
|
import { useEvent, useIsTouchDevice } from '@tamagui/core'
|
|
20
20
|
import * as React from 'react'
|
|
@@ -60,13 +60,10 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
60
60
|
const floatingStyle = React.useRef({})
|
|
61
61
|
|
|
62
62
|
// sync activeIndex on open/close
|
|
63
|
-
// use useEffect (not layout effect) so this runs AFTER SelectItem children have subscribed
|
|
64
63
|
React.useEffect(() => {
|
|
65
64
|
if (open) {
|
|
66
|
-
// use fast setter for initial focus - doesn't trigger re-render
|
|
67
65
|
setActiveIndexFast(selectedIndex ?? 0)
|
|
68
66
|
} else {
|
|
69
|
-
// reset state when closed
|
|
70
67
|
setScrollTop(0)
|
|
71
68
|
setFallback(false)
|
|
72
69
|
setActiveIndexFast(null)
|
|
@@ -90,9 +87,15 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
90
87
|
}, [open])
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
const {
|
|
90
|
+
const {
|
|
91
|
+
x,
|
|
92
|
+
y,
|
|
93
|
+
strategy,
|
|
94
|
+
refs,
|
|
95
|
+
update,
|
|
96
|
+
placement: computedPlacement,
|
|
97
|
+
} = useFloatingDom({
|
|
94
98
|
open,
|
|
95
|
-
onOpenChange: setOpen,
|
|
96
99
|
placement: 'bottom-start',
|
|
97
100
|
whileElementsMounted: autoUpdate,
|
|
98
101
|
// eslint-disable-next-line no-constant-condition
|
|
@@ -145,7 +148,7 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
145
148
|
}),
|
|
146
149
|
offset({ crossAxis: -5 }),
|
|
147
150
|
],
|
|
148
|
-
})
|
|
151
|
+
} as any)
|
|
149
152
|
|
|
150
153
|
const floatingRef = refs.floating
|
|
151
154
|
|
|
@@ -174,21 +177,39 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
174
177
|
return fn(index)
|
|
175
178
|
})
|
|
176
179
|
|
|
180
|
+
// construct interaction context for our custom hooks
|
|
181
|
+
const dataRef = React.useRef<{ openEvent?: Event; placement?: string }>({})
|
|
182
|
+
dataRef.current.placement = computedPlacement
|
|
183
|
+
const interactionContext: FloatingInteractionContext = {
|
|
184
|
+
open,
|
|
185
|
+
onOpenChange: (val) => setOpen(val),
|
|
186
|
+
refs: {
|
|
187
|
+
reference: refs.reference as any,
|
|
188
|
+
floating: refs.floating,
|
|
189
|
+
domReference: refs.reference as any,
|
|
190
|
+
},
|
|
191
|
+
elements: {
|
|
192
|
+
reference: (refs.reference?.current as Element) || null,
|
|
193
|
+
floating: refs.floating?.current || null,
|
|
194
|
+
domReference: (refs.reference?.current as Element) || null,
|
|
195
|
+
},
|
|
196
|
+
dataRef,
|
|
197
|
+
}
|
|
198
|
+
|
|
177
199
|
const interactionsProps = [
|
|
178
|
-
useClick(
|
|
179
|
-
useDismiss
|
|
180
|
-
useRole(
|
|
181
|
-
useInnerOffset(
|
|
200
|
+
useClick(interactionContext, { event: 'mousedown', keyboardHandlers: false }),
|
|
201
|
+
// useDismiss removed - already handled by Dismissable in SelectContent
|
|
202
|
+
useRole(interactionContext, { role: 'listbox' }),
|
|
203
|
+
useInnerOffset(interactionContext, {
|
|
182
204
|
enabled: !fallback && isScrollable,
|
|
183
205
|
onChange: setInnerOffset,
|
|
184
206
|
overflowRef,
|
|
185
207
|
scrollRef: refs.floating,
|
|
186
208
|
}),
|
|
187
|
-
useListNavigation(
|
|
209
|
+
useListNavigation(interactionContext, {
|
|
188
210
|
listRef: listItemsRef,
|
|
189
211
|
activeIndex: selectContext.activeIndex ?? 0,
|
|
190
212
|
selectedIndex,
|
|
191
|
-
// wrap onNavigate to prevent floating-ui from resetting activeIndex to null on focus loss
|
|
192
213
|
onNavigate: (index) => {
|
|
193
214
|
if (index !== null) {
|
|
194
215
|
setActiveIndex(index)
|
|
@@ -196,7 +217,7 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
196
217
|
},
|
|
197
218
|
scrollItemIntoView: false,
|
|
198
219
|
}),
|
|
199
|
-
useTypeahead(
|
|
220
|
+
useTypeahead(interactionContext, {
|
|
200
221
|
listRef: listContentRef,
|
|
201
222
|
onMatch,
|
|
202
223
|
selectedIndex,
|
|
@@ -208,7 +229,6 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
208
229
|
]
|
|
209
230
|
|
|
210
231
|
const interactions = useInteractions(
|
|
211
|
-
// unfortunately these memos will just always break due to floating-ui context always changing :/
|
|
212
232
|
React.useMemo(() => {
|
|
213
233
|
return interactionsProps
|
|
214
234
|
}, interactionsProps)
|
|
@@ -278,13 +298,10 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
278
298
|
|
|
279
299
|
useIsomorphicLayoutEffect(() => {
|
|
280
300
|
if (open) {
|
|
281
|
-
// Prevent the initial mouseup from selecting an item
|
|
282
|
-
// (the mouseup from the click that opened the menu)
|
|
283
301
|
allowMouseUpRef.current = false
|
|
284
302
|
|
|
285
303
|
selectTimeoutRef.current = setTimeout(() => {
|
|
286
304
|
allowSelectRef.current = true
|
|
287
|
-
// Re-enable mouseup after delay for click-and-hold-to-select behavior
|
|
288
305
|
allowMouseUpRef.current = true
|
|
289
306
|
}, 300)
|
|
290
307
|
|
|
@@ -305,8 +322,7 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
305
322
|
}
|
|
306
323
|
}, [open])
|
|
307
324
|
|
|
308
|
-
//
|
|
309
|
-
// element DOM tree.
|
|
325
|
+
// dismiss on outside pointer down (arrows are outside the floating DOM tree)
|
|
310
326
|
useIsomorphicLayoutEffect(() => {
|
|
311
327
|
function onPointerDown(e: PointerEvent) {
|
|
312
328
|
const target = e.target as Node
|
|
@@ -330,8 +346,7 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
330
346
|
}
|
|
331
347
|
}, [open, refs, setOpen])
|
|
332
348
|
|
|
333
|
-
//
|
|
334
|
-
// (keyboard nav) mode. Use subscription to avoid re-renders on every activeIndex change.
|
|
349
|
+
// scroll activeIndex into view during keyboard nav
|
|
335
350
|
React.useEffect(() => {
|
|
336
351
|
if (!open) return
|
|
337
352
|
|
|
@@ -342,14 +357,11 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
342
357
|
setScrollTop(refs.floating.current?.scrollTop ?? 0)
|
|
343
358
|
}
|
|
344
359
|
|
|
345
|
-
// initial scroll
|
|
346
360
|
scrollActiveIntoView(activeIndexRef.current)
|
|
347
361
|
|
|
348
|
-
// subscribe to future changes
|
|
349
362
|
return selectItemParentContext.activeIndexSubscribe(scrollActiveIntoView)
|
|
350
363
|
}, [open, refs, controlledScrolling, selectItemParentContext.activeIndexSubscribe])
|
|
351
364
|
|
|
352
|
-
// Scroll the `selectedIndex` into view upon opening the floating element.
|
|
353
365
|
React.useEffect(() => {
|
|
354
366
|
if (open && fallback) {
|
|
355
367
|
if (selectedIndex != null) {
|
|
@@ -358,18 +370,20 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
358
370
|
}
|
|
359
371
|
}, [open, fallback, selectedIndex])
|
|
360
372
|
|
|
361
|
-
// Unset the height limiting for fallback mode. This gets executed prior to
|
|
362
|
-
// the positioning call.
|
|
363
373
|
useIsomorphicLayoutEffect(() => {
|
|
364
374
|
if (refs.floating.current && fallback) {
|
|
365
375
|
refs.floating.current.style.maxHeight = ''
|
|
366
376
|
}
|
|
367
377
|
}, [refs, fallback])
|
|
368
378
|
|
|
369
|
-
//
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
379
|
+
// build a minimal floating context for SelectViewport/SelectScrollButton
|
|
380
|
+
const floatingContext = React.useMemo(
|
|
381
|
+
() => ({
|
|
382
|
+
refs,
|
|
383
|
+
dataRef,
|
|
384
|
+
}),
|
|
385
|
+
[refs]
|
|
386
|
+
)
|
|
373
387
|
|
|
374
388
|
return (
|
|
375
389
|
<SelectProvider
|
|
@@ -378,7 +392,7 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
378
392
|
setScrollTop={setScrollTop}
|
|
379
393
|
setInnerOffset={setInnerOffset}
|
|
380
394
|
fallback={fallback}
|
|
381
|
-
floatingContext={
|
|
395
|
+
floatingContext={floatingContext as any}
|
|
382
396
|
canScrollDown={!!showDownArrow}
|
|
383
397
|
canScrollUp={!!showUpArrow}
|
|
384
398
|
controlledScrolling={controlledScrolling}
|
|
@@ -392,25 +406,13 @@ export const SelectInlineImpl = (props: SelectImplProps) => {
|
|
|
392
406
|
{...selectItemParentContext}
|
|
393
407
|
allowMouseUpRef={allowMouseUpRef}
|
|
394
408
|
allowSelectRef={allowSelectRef}
|
|
395
|
-
dataRef={
|
|
409
|
+
dataRef={dataRef as any}
|
|
396
410
|
interactions={interactionsContext}
|
|
397
411
|
listRef={listItemsRef}
|
|
398
412
|
selectTimeoutRef={selectTimeoutRef}
|
|
399
413
|
>
|
|
400
414
|
{children}
|
|
401
415
|
</SelectItemParentProvider>
|
|
402
|
-
{/* {isFormControl ? (
|
|
403
|
-
<BubbleSelect
|
|
404
|
-
ref={setBubbleSelect}
|
|
405
|
-
aria-hidden
|
|
406
|
-
tabIndex={-1}
|
|
407
|
-
name={name}
|
|
408
|
-
autoComplete={autoComplete}
|
|
409
|
-
value={value}
|
|
410
|
-
// enable form autofill
|
|
411
|
-
onChange={(event) => setValue(event.target.value)}
|
|
412
|
-
/>
|
|
413
|
-
) : null} */}
|
|
414
416
|
</SelectProvider>
|
|
415
417
|
)
|
|
416
418
|
}
|
package/src/SelectItem.tsx
CHANGED
|
@@ -53,6 +53,7 @@ export const SelectItem = ListItem.Frame.styleable<SelectItemExtraProps>(
|
|
|
53
53
|
setOpen,
|
|
54
54
|
onChange,
|
|
55
55
|
activeIndexSubscribe,
|
|
56
|
+
activeIndexRef,
|
|
56
57
|
valueSubscribe,
|
|
57
58
|
allowMouseUpRef,
|
|
58
59
|
allowSelectRef,
|
|
@@ -77,17 +78,26 @@ export const SelectItem = ListItem.Frame.styleable<SelectItemExtraProps>(
|
|
|
77
78
|
}, [])
|
|
78
79
|
|
|
79
80
|
React.useEffect(() => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (isActive) {
|
|
81
|
+
const handleActiveIndex = (i: number) => {
|
|
82
|
+
if (index === i) {
|
|
84
83
|
onActiveChange(value, index)
|
|
85
|
-
|
|
86
84
|
if (isWeb) {
|
|
87
|
-
|
|
85
|
+
// use rAF to focus after browser's click handling completes
|
|
86
|
+
// this prevents the trigger from stealing focus after we set it
|
|
87
|
+
requestAnimationFrame(() => {
|
|
88
|
+
listRef?.current[index]?.focus()
|
|
89
|
+
})
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
|
-
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// check initial value (parent effect may have set it before we subscribed)
|
|
95
|
+
const currentActiveIndex = activeIndexRef?.current
|
|
96
|
+
if (currentActiveIndex !== null && currentActiveIndex !== undefined) {
|
|
97
|
+
handleActiveIndex(currentActiveIndex)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return activeIndexSubscribe(handleActiveIndex)
|
|
91
101
|
}, [index])
|
|
92
102
|
|
|
93
103
|
React.useEffect(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { autoUpdate, offset, useFloating } from '@floating
|
|
1
|
+
import { autoUpdate, offset, useFloatingRaw as useFloating } from '@tamagui/floating'
|
|
2
2
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
3
3
|
import type { TamaguiElement } from '@tamagui/core'
|
|
4
4
|
import { YStack } from '@tamagui/stacks'
|
package/src/SelectTrigger.tsx
CHANGED
package/src/SelectViewport.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FloatingFocusManager } from '@floating-ui/react'
|
|
2
1
|
import { AdaptPortalContents, useAdaptIsActive } from '@tamagui/adapt'
|
|
3
2
|
import { AnimatePresence } from '@tamagui/animate-presence'
|
|
4
3
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
@@ -6,6 +5,8 @@ import { isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
|
6
5
|
import { styled } from '@tamagui/core'
|
|
7
6
|
import { needsPortalRepropagation } from '@tamagui/portal'
|
|
8
7
|
import { YStack } from '@tamagui/stacks'
|
|
8
|
+
import { startTransition } from '@tamagui/start-transition'
|
|
9
|
+
import * as React from 'react'
|
|
9
10
|
import { VIEWPORT_NAME } from './constants'
|
|
10
11
|
import {
|
|
11
12
|
ForwardSelectContext,
|
|
@@ -56,6 +57,18 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
56
57
|
const itemContext = useSelectItemParentContext(scope)
|
|
57
58
|
const isAdapted = useAdaptIsActive(context.adaptScope)
|
|
58
59
|
|
|
60
|
+
// lazy mount: defer mounting children until first open using startTransition
|
|
61
|
+
const [lazyMounted, setLazyMounted] = React.useState(context.lazyMount ? false : true)
|
|
62
|
+
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (!context.lazyMount) return
|
|
65
|
+
if (!context.open) return
|
|
66
|
+
if (lazyMounted) return
|
|
67
|
+
startTransition(() => {
|
|
68
|
+
setLazyMounted(true)
|
|
69
|
+
})
|
|
70
|
+
}, [context.lazyMount, context.open, lazyMounted])
|
|
71
|
+
|
|
59
72
|
const composedRefs = useComposedRefs(
|
|
60
73
|
// @ts-ignore TODO react 19 type needs fix
|
|
61
74
|
forwardedRef,
|
|
@@ -68,6 +81,14 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
68
81
|
}
|
|
69
82
|
}, [isAdapted])
|
|
70
83
|
|
|
84
|
+
// after lazy children mount, force floating-ui to recompute so inner middleware
|
|
85
|
+
// can position using the now-present list items
|
|
86
|
+
useIsomorphicLayoutEffect(() => {
|
|
87
|
+
if (context.lazyMount && lazyMounted && context.open && context.update) {
|
|
88
|
+
context.update()
|
|
89
|
+
}
|
|
90
|
+
}, [lazyMounted])
|
|
91
|
+
|
|
71
92
|
if (itemContext.shouldRenderWebNative) {
|
|
72
93
|
return <YStack position="relative">{children}</YStack>
|
|
73
94
|
}
|
|
@@ -103,6 +124,8 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
103
124
|
...floatingProps
|
|
104
125
|
} = itemContext.interactions.getFloatingProps()
|
|
105
126
|
|
|
127
|
+
// FloatingFocusManager removed — SelectContent already wraps with FocusScope
|
|
128
|
+
// that handles focus trapping and auto-focus
|
|
106
129
|
return (
|
|
107
130
|
<>
|
|
108
131
|
{!disableScroll && !props.unstyled && (
|
|
@@ -114,31 +137,28 @@ export const SelectViewport = SelectViewportFrame.styleable<SelectViewportExtraP
|
|
|
114
137
|
)}
|
|
115
138
|
<AnimatePresence>
|
|
116
139
|
{context.open ? (
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
140
|
+
<SelectViewportFrame
|
|
141
|
+
key="select-viewport"
|
|
142
|
+
size={itemContext.size}
|
|
143
|
+
role="presentation"
|
|
144
|
+
{...viewportProps}
|
|
145
|
+
{...style}
|
|
146
|
+
{...floatingProps}
|
|
147
|
+
{...(!props.unstyled && {
|
|
148
|
+
overflowY: disableScroll ? undefined : (style.overflow ?? 'auto'),
|
|
149
|
+
})}
|
|
150
|
+
ref={composedRefs}
|
|
121
151
|
>
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
size={itemContext.size}
|
|
125
|
-
role="presentation"
|
|
126
|
-
{...viewportProps}
|
|
127
|
-
{...style}
|
|
128
|
-
{...floatingProps}
|
|
129
|
-
{...(!props.unstyled && {
|
|
130
|
-
overflowY: disableScroll ? undefined : (style.overflow ?? 'auto'),
|
|
131
|
-
})}
|
|
132
|
-
ref={composedRefs}
|
|
133
|
-
>
|
|
134
|
-
{children}
|
|
135
|
-
</SelectViewportFrame>
|
|
136
|
-
</FloatingFocusManager>
|
|
152
|
+
{lazyMounted ? children : null}
|
|
153
|
+
</SelectViewportFrame>
|
|
137
154
|
) : null}
|
|
138
155
|
</AnimatePresence>
|
|
139
156
|
|
|
140
|
-
{/* keep in dom to allow for portal to the trigger
|
|
141
|
-
{
|
|
157
|
+
{/* keep in dom to allow for portal to the trigger when renderValue isn't provided */}
|
|
158
|
+
{/* when lazyMount is enabled and renderValue is provided, skip this entirely for performance */}
|
|
159
|
+
{!context.open && !(context.lazyMount && context.renderValue) && lazyMounted && (
|
|
160
|
+
<div style={{ display: 'none' }}>{children}</div>
|
|
161
|
+
)}
|
|
142
162
|
</>
|
|
143
163
|
)
|
|
144
164
|
}
|
package/src/context.tsx
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { createStyledContext } from '@tamagui/core'
|
|
2
2
|
import { getPortal } from '@tamagui/native'
|
|
3
|
+
import { createContext } from 'react'
|
|
3
4
|
import type { SelectContextValue, SelectItemParentContextValue } from './types'
|
|
4
5
|
|
|
6
|
+
// zIndex flows from root Select prop to SelectContent portal
|
|
7
|
+
export const SelectZIndexContext = createContext<number | undefined>(undefined)
|
|
8
|
+
|
|
5
9
|
export const { Provider: SelectProvider, useStyledContext: useSelectContext } =
|
|
6
10
|
createStyledContext<SelectContextValue>(null as any, 'Select')
|
|
7
11
|
|
package/src/types.tsx
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
import type { ContextData, FloatingContext, ReferenceType } from '@floating-ui/react'
|
|
2
1
|
import type { NativeValue, SizeTokens } from '@tamagui/core'
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import type { YStackProps } from '@tamagui/stacks'
|
|
3
|
+
import type {
|
|
4
|
+
DispatchWithoutAction,
|
|
5
|
+
HTMLProps,
|
|
6
|
+
MutableRefObject,
|
|
7
|
+
ReactNode,
|
|
8
|
+
RefObject,
|
|
9
|
+
} from 'react'
|
|
10
|
+
|
|
11
|
+
// minimal types replacing @floating-ui/react imports
|
|
12
|
+
type ContextData = Record<string, any>
|
|
13
|
+
type ReferenceType = Element
|
|
14
|
+
type FloatingContext<RT = ReferenceType> = {
|
|
15
|
+
refs: {
|
|
16
|
+
reference: RefObject<RT | null>
|
|
17
|
+
floating: RefObject<HTMLElement | null>
|
|
18
|
+
setFloating: (el: HTMLElement | null) => void
|
|
19
|
+
setReference: (el: RT | null) => void
|
|
20
|
+
[key: string]: any
|
|
21
|
+
}
|
|
22
|
+
dataRef: RefObject<ContextData>
|
|
23
|
+
update?: () => void
|
|
24
|
+
[key: string]: any
|
|
25
|
+
}
|
|
5
26
|
|
|
6
27
|
export type SelectDirection = 'ltr' | 'rtl'
|
|
7
28
|
|
|
@@ -59,6 +80,23 @@ export interface SelectProps<Value extends string = string> {
|
|
|
59
80
|
* ```
|
|
60
81
|
*/
|
|
61
82
|
renderValue?(value: Value): ReactNode
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* When true, defers mounting Select items until opened using startTransition.
|
|
86
|
+
* This significantly improves initial render performance for pages with many Selects.
|
|
87
|
+
*
|
|
88
|
+
* Should be combined with `renderValue` to display the selected value during SSR
|
|
89
|
+
* and before items are mounted.
|
|
90
|
+
*
|
|
91
|
+
* @default false
|
|
92
|
+
*/
|
|
93
|
+
lazyMount?: boolean
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* z-index for the select portal. Use this when select dropdowns need to appear
|
|
97
|
+
* above other portaled content like dialogs or fixed headers.
|
|
98
|
+
*/
|
|
99
|
+
zIndex?: number
|
|
62
100
|
}
|
|
63
101
|
|
|
64
102
|
type DisposeFn = () => void
|
|
@@ -75,6 +113,7 @@ export interface SelectItemParentContextValue {
|
|
|
75
113
|
onChange: (value: string) => void
|
|
76
114
|
onActiveChange: (value: string, index: number) => void
|
|
77
115
|
activeIndexSubscribe: EmitterSubscriber<number>
|
|
116
|
+
activeIndexRef?: MutableRefObject<number | null>
|
|
78
117
|
valueSubscribe: EmitterSubscriber<any>
|
|
79
118
|
allowSelectRef?: MutableRefObject<boolean>
|
|
80
119
|
allowMouseUpRef?: MutableRefObject<boolean>
|
|
@@ -131,6 +170,8 @@ export interface SelectContextValue {
|
|
|
131
170
|
update?: () => void
|
|
132
171
|
/** Render function for the selected value (SSR support) */
|
|
133
172
|
renderValue?: (value: any) => ReactNode
|
|
173
|
+
/** When true, defers mounting items until opened */
|
|
174
|
+
lazyMount?: boolean
|
|
134
175
|
}
|
|
135
176
|
|
|
136
177
|
export type SelectViewportExtraProps = SelectScopedProps<{
|
|
@@ -143,7 +184,6 @@ export type SelectViewportProps = YStackProps & SelectViewportExtraProps
|
|
|
143
184
|
|
|
144
185
|
export type SelectContentProps = SelectScopedProps<{
|
|
145
186
|
children?: React.ReactNode
|
|
146
|
-
zIndex?: number
|
|
147
187
|
}>
|
|
148
188
|
|
|
149
189
|
export type SelectScrollButtonImplProps = YStackProps &
|
package/types/Select.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare const Select: (<Value extends string = string>(props: SelectScope
|
|
|
41
41
|
shouldForwardSpace: boolean;
|
|
42
42
|
};
|
|
43
43
|
};
|
|
44
|
-
Content: ({ children, scope,
|
|
44
|
+
Content: ({ children, scope, ...focusScopeProps }: import("./types").SelectContentProps & import("@tamagui/focus-scope").FocusScopeProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
45
45
|
Group: React.ForwardRefExoticComponent<Omit<import("@tamagui/core").RNTamaguiViewNonStyleProps, "elevation" | keyof import("@tamagui/core").StackStyleBase | "fullscreen"> & import("@tamagui/core").WithThemeValues<import("@tamagui/core").StackStyleBase> & {
|
|
46
46
|
elevation?: number | SizeTokens | undefined;
|
|
47
47
|
fullscreen?: boolean | undefined;
|
|
@@ -107,7 +107,7 @@ export declare const Select: (<Value extends string = string>(props: SelectScope
|
|
|
107
107
|
}, import("@tamagui/core").StaticConfigPublic>;
|
|
108
108
|
ScrollDownButton: React.ForwardRefExoticComponent<import("./types").SelectScrollButtonProps & React.RefAttributes<TamaguiElement>>;
|
|
109
109
|
ScrollUpButton: React.ForwardRefExoticComponent<import("./types").SelectScrollButtonProps & React.RefAttributes<TamaguiElement>>;
|
|
110
|
-
Trigger: React.ForwardRefExoticComponent<Omit<import("@tamagui/core").StackNonStyleProps, "disabled" | "size" | "unstyled" | keyof import("@tamagui/core").StackStyleBase | "
|
|
110
|
+
Trigger: React.ForwardRefExoticComponent<Omit<import("@tamagui/core").StackNonStyleProps, "disabled" | "size" | "unstyled" | keyof import("@tamagui/core").StackStyleBase | "variant" | "active"> & import("@tamagui/core").WithThemeValues<import("@tamagui/core").StackStyleBase> & {
|
|
111
111
|
size?: SizeTokens | undefined;
|
|
112
112
|
variant?: "outlined" | undefined;
|
|
113
113
|
disabled?: boolean | undefined;
|
package/types/Select.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAiBzF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAiBzF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,OAAO,KAAK,EAAmB,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAS9E,QAAA,MAAM,gBAAgB;;;8CAGpB,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;IACpD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC9B,CAAC,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,GAAG,qBAAqB,CAAA;AA6DxF,eAAO,MAAM,UAAU;;;8CAKrB,CAAA;AAkCF,QAAA,MAAM,oBAAoB;;;;8CAoBxB,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC,OAAO,oBAAoB,CAAC,CAAA;AA6DxE,eAAO,MAAM,gBAAgB;;;8CAG3B,CAAA;AAoHF,QAAA,MAAM,gBAAgB;;;8CA4BpB,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAA;AA4BnF,eAAO,MAAM,eAAe;;;8CAE1B,CAAA;AAoCF,eAAO,MAAM,MAAM,IACD,KAAK,SAAS,MAAM,kBAC3B,iBAAiB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;;;sBA7ZsB,GAAI;qBAE1E,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAyVyD,GAAG;;gBAAH,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAjV5C,KAAK,CAAC,SAAS;;;;sBAAf,KAAK,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8a9B,CAAA"}
|
package/types/SelectContent.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { FocusScopeProps } from '@tamagui/focus-scope';
|
|
2
2
|
import type { SelectContentProps } from './types';
|
|
3
|
-
export declare const SelectContent: ({ children, scope,
|
|
3
|
+
export declare const SelectContent: ({ children, scope, ...focusScopeProps }: SelectContentProps & FocusScopeProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
4
4
|
//# sourceMappingURL=SelectContent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectContent.d.ts","sourceRoot":"","sources":["../src/SelectContent.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"SelectContent.d.ts","sourceRoot":"","sources":["../src/SelectContent.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAW3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAOjD,eAAO,MAAM,aAAa,GAAI,yCAI3B,kBAAkB,GAAG,eAAe,mDAyDtC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectImpl.d.ts","sourceRoot":"","sources":["../src/SelectImpl.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAG9C,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,
|
|
1
|
+
{"version":3,"file":"SelectImpl.d.ts","sourceRoot":"","sources":["../src/SelectImpl.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAG9C,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,4CAkYtD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectItem.d.ts","sourceRoot":"","sources":["../src/SelectItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,KAAK,sBAAsB,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,eAAO,MACK,yBAAyB;;;IACjB,oBAAoB,4CAC+B,CAAA;AAEvE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,aAAa,EAAE,MAAM,oBAAoB,CAAC,EAAE,oBAAoB;CAAG;AAElF,eAAO,MAAM,UAAU;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"SelectItem.d.ts","sourceRoot":"","sources":["../src/SelectItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,KAAK,sBAAsB,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,eAAO,MACK,yBAAyB;;;IACjB,oBAAoB,4CAC+B,CAAA;AAEvE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,aAAa,EAAE,MAAM,oBAAoB,CAAC,EAAE,oBAAoB;CAAG;AAElF,eAAO,MAAM,UAAU;;;;;;;;;;;;8CA8NtB,CAAA"}
|
package/types/SelectTrigger.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ListItemProps } from '@tamagui/list-item';
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import type { SelectScopedProps } from './types';
|
|
5
5
|
export type SelectTriggerProps = SelectScopedProps<ListItemProps>;
|
|
6
|
-
export declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<import("@tamagui/core").StackNonStyleProps, "disabled" | "size" | "unstyled" | keyof import("@tamagui/core").StackStyleBase | "
|
|
6
|
+
export declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<import("@tamagui/core").StackNonStyleProps, "disabled" | "size" | "unstyled" | keyof import("@tamagui/core").StackStyleBase | "variant" | "active"> & import("@tamagui/core").WithThemeValues<import("@tamagui/core").StackStyleBase> & {
|
|
7
7
|
size?: import("@tamagui/core").SizeTokens | undefined;
|
|
8
8
|
variant?: "outlined" | undefined;
|
|
9
9
|
disabled?: boolean | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectViewport.d.ts","sourceRoot":"","sources":["../src/SelectViewport.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SelectViewport.d.ts","sourceRoot":"","sources":["../src/SelectViewport.tsx"],"names":[],"mappings":"AAqBA,eAAO,MAAM,mBAAmB;;;;;8CA2B9B,CAAA;AAIF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;8CAgH1B,CAAA"}
|
package/types/context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SelectContextValue, SelectItemParentContextValue } from './types';
|
|
2
|
+
export declare const SelectZIndexContext: import("react").Context<number | undefined>;
|
|
2
3
|
export declare const SelectProvider: import("react").Provider<SelectContextValue> & import("react").ProviderExoticComponent<Partial<SelectContextValue> & {
|
|
3
4
|
children?: import("react").ReactNode;
|
|
4
5
|
scope?: string;
|
package/types/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAA;AAG/E,eAAO,MAAM,mBAAmB,6CAA+C,CAAA;AAE/E,eAAO,MAAkB,cAAc;;;IAAoB,gBAAgB,wCACX,CAAA;AAIhE,eAAO,MACK,wBAAwB;;;IAChB,0BAA0B,kDACkC,CAAA;AAEhF,eAAO,MAAM,oBAAoB,GAAI,qCAIlC;IACD,QAAQ,CAAC,EAAE,GAAG,CAAA;IACd,OAAO,EAAE,kBAAkB,CAAA;IAC3B,WAAW,EAAE,4BAA4B,CAAA;CAC1C,QAgBA,CAAA"}
|
package/types/types.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import type { ContextData, FloatingContext, ReferenceType } from '@floating-ui/react';
|
|
2
1
|
import type { NativeValue, SizeTokens } from '@tamagui/core';
|
|
3
2
|
import type { YStackProps } from '@tamagui/stacks';
|
|
4
|
-
import type { DispatchWithoutAction, HTMLProps, MutableRefObject, ReactNode } from 'react';
|
|
3
|
+
import type { DispatchWithoutAction, HTMLProps, MutableRefObject, ReactNode, RefObject } from 'react';
|
|
4
|
+
type ContextData = Record<string, any>;
|
|
5
|
+
type ReferenceType = Element;
|
|
6
|
+
type FloatingContext<RT = ReferenceType> = {
|
|
7
|
+
refs: {
|
|
8
|
+
reference: RefObject<RT | null>;
|
|
9
|
+
floating: RefObject<HTMLElement | null>;
|
|
10
|
+
setFloating: (el: HTMLElement | null) => void;
|
|
11
|
+
setReference: (el: RT | null) => void;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
};
|
|
14
|
+
dataRef: RefObject<ContextData>;
|
|
15
|
+
update?: () => void;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
5
18
|
export type SelectDirection = 'ltr' | 'rtl';
|
|
6
19
|
export type SelectScopes = string;
|
|
7
20
|
export type SelectScopedProps<P> = P & {
|
|
@@ -53,6 +66,21 @@ export interface SelectProps<Value extends string = string> {
|
|
|
53
66
|
* ```
|
|
54
67
|
*/
|
|
55
68
|
renderValue?(value: Value): ReactNode;
|
|
69
|
+
/**
|
|
70
|
+
* When true, defers mounting Select items until opened using startTransition.
|
|
71
|
+
* This significantly improves initial render performance for pages with many Selects.
|
|
72
|
+
*
|
|
73
|
+
* Should be combined with `renderValue` to display the selected value during SSR
|
|
74
|
+
* and before items are mounted.
|
|
75
|
+
*
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
lazyMount?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* z-index for the select portal. Use this when select dropdowns need to appear
|
|
81
|
+
* above other portaled content like dialogs or fixed headers.
|
|
82
|
+
*/
|
|
83
|
+
zIndex?: number;
|
|
56
84
|
}
|
|
57
85
|
type DisposeFn = () => void;
|
|
58
86
|
export type EmitterSubscriber<Val> = (cb: (val: Val) => void) => DisposeFn;
|
|
@@ -67,6 +95,7 @@ export interface SelectItemParentContextValue {
|
|
|
67
95
|
onChange: (value: string) => void;
|
|
68
96
|
onActiveChange: (value: string, index: number) => void;
|
|
69
97
|
activeIndexSubscribe: EmitterSubscriber<number>;
|
|
98
|
+
activeIndexRef?: MutableRefObject<number | null>;
|
|
70
99
|
valueSubscribe: EmitterSubscriber<any>;
|
|
71
100
|
allowSelectRef?: MutableRefObject<boolean>;
|
|
72
101
|
allowMouseUpRef?: MutableRefObject<boolean>;
|
|
@@ -120,6 +149,8 @@ export interface SelectContextValue {
|
|
|
120
149
|
update?: () => void;
|
|
121
150
|
/** Render function for the selected value (SSR support) */
|
|
122
151
|
renderValue?: (value: any) => ReactNode;
|
|
152
|
+
/** When true, defers mounting items until opened */
|
|
153
|
+
lazyMount?: boolean;
|
|
123
154
|
}
|
|
124
155
|
export type SelectViewportExtraProps = SelectScopedProps<{
|
|
125
156
|
size?: SizeTokens;
|
|
@@ -129,7 +160,6 @@ export type SelectViewportExtraProps = SelectScopedProps<{
|
|
|
129
160
|
export type SelectViewportProps = YStackProps & SelectViewportExtraProps;
|
|
130
161
|
export type SelectContentProps = SelectScopedProps<{
|
|
131
162
|
children?: React.ReactNode;
|
|
132
|
-
zIndex?: number;
|
|
133
163
|
}>;
|
|
134
164
|
export type SelectScrollButtonImplProps = YStackProps & SelectScopedProps<{
|
|
135
165
|
dir: 'up' | 'down';
|