@tamagui/popover 1.1.7 → 1.1.8
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/Popover.js +46 -40
- package/dist/cjs/Popover.js.map +2 -2
- package/dist/esm/Popover.js +53 -39
- package/dist/esm/Popover.js.map +2 -2
- package/dist/jsx/Popover.js +28 -20
- package/dist/jsx/Popover.js.map +2 -2
- package/package.json +17 -17
- package/src/Popover.tsx +66 -40
- package/types/Popover.d.ts +4 -3
- package/types/useFloating.d.ts +23 -0
- package/src/floating.native.ts +0 -18
- package/src/floating.ts +0 -8
package/src/Popover.tsx
CHANGED
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import '@tamagui/polyfill-dev'
|
|
4
4
|
|
|
5
|
+
import type { UseFloatingProps } from '@floating-ui/react-dom-interactions'
|
|
6
|
+
import {
|
|
7
|
+
useDismiss,
|
|
8
|
+
useFloating,
|
|
9
|
+
useInteractions,
|
|
10
|
+
useRole,
|
|
11
|
+
} from '@floating-ui/react-dom-interactions'
|
|
5
12
|
import { Adapt, useAdaptParent } from '@tamagui/adapt'
|
|
6
13
|
import { AnimatePresence } from '@tamagui/animate-presence'
|
|
7
14
|
import { hideOthers } from '@tamagui/aria-hidden'
|
|
8
15
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
9
16
|
import {
|
|
17
|
+
GestureReponderEvent,
|
|
10
18
|
MediaQueryKey,
|
|
11
19
|
SizeTokens,
|
|
20
|
+
Stack,
|
|
21
|
+
TamaguiElement,
|
|
12
22
|
Theme,
|
|
13
23
|
composeEventHandlers,
|
|
14
24
|
isWeb,
|
|
@@ -22,9 +32,9 @@ import {
|
|
|
22
32
|
import type { Scope } from '@tamagui/create-context'
|
|
23
33
|
import { createContextScope } from '@tamagui/create-context'
|
|
24
34
|
import { DismissableProps } from '@tamagui/dismissable'
|
|
35
|
+
import { FloatingOverrideContext } from '@tamagui/floating'
|
|
25
36
|
import { FocusScope, FocusScopeProps } from '@tamagui/focus-scope'
|
|
26
37
|
import {
|
|
27
|
-
FloatingOverrideContext,
|
|
28
38
|
Popper,
|
|
29
39
|
PopperAnchor,
|
|
30
40
|
PopperArrow,
|
|
@@ -39,13 +49,17 @@ import {
|
|
|
39
49
|
import { Portal, PortalHost, PortalItem } from '@tamagui/portal'
|
|
40
50
|
import { RemoveScroll, RemoveScrollProps } from '@tamagui/remove-scroll'
|
|
41
51
|
import { ControlledSheet, SheetController } from '@tamagui/sheet'
|
|
42
|
-
import { YStack, YStackProps } from '@tamagui/stacks'
|
|
52
|
+
import { SizableStack, XStack, YStack, YStackProps, ZStack } from '@tamagui/stacks'
|
|
43
53
|
import { useControllableState } from '@tamagui/use-controllable-state'
|
|
44
54
|
import * as React from 'react'
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
import { useEffect } from 'react'
|
|
56
|
+
import {
|
|
57
|
+
GestureResponderEvent,
|
|
58
|
+
Platform,
|
|
59
|
+
ScrollView,
|
|
60
|
+
ScrollViewProps,
|
|
61
|
+
View,
|
|
62
|
+
} from 'react-native'
|
|
49
63
|
|
|
50
64
|
const POPOVER_NAME = 'Popover'
|
|
51
65
|
|
|
@@ -58,7 +72,7 @@ export type PopoverProps = PopperProps & {
|
|
|
58
72
|
}
|
|
59
73
|
|
|
60
74
|
type PopoverContextValue = {
|
|
61
|
-
triggerRef: React.RefObject<
|
|
75
|
+
triggerRef: React.RefObject<any>
|
|
62
76
|
contentId?: string
|
|
63
77
|
open: boolean
|
|
64
78
|
onOpenChange(open: boolean): void
|
|
@@ -70,6 +84,7 @@ type PopoverContextValue = {
|
|
|
70
84
|
sheetBreakpoint: any
|
|
71
85
|
scopeKey: string
|
|
72
86
|
popperScope: any
|
|
87
|
+
breakpointActive?: boolean
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
const [createPopoverContext, createPopoverScopeInternal] = createContextScope(
|
|
@@ -183,7 +198,7 @@ export const PopoverContent = React.forwardRef<
|
|
|
183
198
|
...contentModalProps
|
|
184
199
|
} = props
|
|
185
200
|
const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
|
|
186
|
-
const contentRef = React.useRef<
|
|
201
|
+
const contentRef = React.useRef<any>(null)
|
|
187
202
|
const composedRefs = useComposedRefs(forwardedRef, contentRef)
|
|
188
203
|
const isRightClickOutsideRef = React.useRef(false)
|
|
189
204
|
|
|
@@ -233,13 +248,13 @@ export const PopoverContent = React.forwardRef<
|
|
|
233
248
|
|
|
234
249
|
function PopoverContentPortal(props: ScopedProps<PopoverContentTypeProps>) {
|
|
235
250
|
const themeName = useThemeName()
|
|
251
|
+
const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
|
|
236
252
|
|
|
237
253
|
// on android we have to re-pass context
|
|
238
254
|
let contents = props.children
|
|
239
255
|
|
|
240
256
|
if (Platform.OS === 'android') {
|
|
241
257
|
// ok conditional hooks by platform
|
|
242
|
-
const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
|
|
243
258
|
const popperContext = usePopperContext(CONTENT_NAME, context.popperScope)
|
|
244
259
|
|
|
245
260
|
contents = (
|
|
@@ -252,10 +267,19 @@ function PopoverContentPortal(props: ScopedProps<PopoverContentTypeProps>) {
|
|
|
252
267
|
)
|
|
253
268
|
}
|
|
254
269
|
|
|
270
|
+
const zIndex = props.zIndex ?? 1000
|
|
271
|
+
|
|
272
|
+
// Portal the contents and add a transparent bg overlay to handle dismiss on native
|
|
255
273
|
return (
|
|
256
|
-
<Portal zIndex={
|
|
274
|
+
<Portal zIndex={zIndex}>
|
|
257
275
|
<Theme forceClassName name={themeName}>
|
|
258
|
-
{
|
|
276
|
+
{!!context.open && !context.breakpointActive && (
|
|
277
|
+
<YStack
|
|
278
|
+
fullscreen
|
|
279
|
+
onPress={composeEventHandlers(props.onPress as any, context.onOpenToggle)}
|
|
280
|
+
/>
|
|
281
|
+
)}
|
|
282
|
+
<Stack zIndex={(zIndex as number) + 1}>{contents}</Stack>
|
|
259
283
|
</Theme>
|
|
260
284
|
</Portal>
|
|
261
285
|
)
|
|
@@ -309,9 +333,8 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
309
333
|
} = props
|
|
310
334
|
const popperScope = usePopoverScope(__scopePopover)
|
|
311
335
|
const context = usePopoverInternalContext(CONTENT_NAME, popperScope.__scopePopover)
|
|
312
|
-
const showSheet = useShowPopoverSheet(context)
|
|
313
336
|
|
|
314
|
-
if (
|
|
337
|
+
if (context.breakpointActive) {
|
|
315
338
|
// unwrap the PopoverScrollView if used, as it will use the SheetScrollView if that exists
|
|
316
339
|
const childrenWithoutScrollView = React.Children.toArray(children).map((child) => {
|
|
317
340
|
if (React.isValidElement(child)) {
|
|
@@ -330,7 +353,9 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
330
353
|
)
|
|
331
354
|
}
|
|
332
355
|
|
|
333
|
-
// const handleDismiss = React.useCallback(() =>
|
|
356
|
+
// const handleDismiss = React.useCallback((event: GestureResponderEvent) =>{
|
|
357
|
+
// context.onOpenChange(false);
|
|
358
|
+
// }, [])
|
|
334
359
|
// <Dismissable
|
|
335
360
|
// disableOutsidePointerEvents={disableOutsidePointerEvents}
|
|
336
361
|
// // onInteractOutside={onInteractOutside}
|
|
@@ -344,13 +369,13 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
344
369
|
<AnimatePresence>
|
|
345
370
|
{!!context.open && (
|
|
346
371
|
<PopperContent
|
|
347
|
-
key=
|
|
372
|
+
key={context.contentId}
|
|
348
373
|
data-state={getState(context.open)}
|
|
349
374
|
id={context.contentId}
|
|
350
375
|
pointerEvents="auto"
|
|
376
|
+
ref={forwardedRef}
|
|
351
377
|
{...popperScope}
|
|
352
378
|
{...contentProps}
|
|
353
|
-
ref={forwardedRef}
|
|
354
379
|
>
|
|
355
380
|
<RemoveScroll
|
|
356
381
|
enabled={disableRemoveScroll ? false : context.open}
|
|
@@ -370,7 +395,7 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
370
395
|
onMountAutoFocus={onOpenAutoFocus}
|
|
371
396
|
onUnmountAutoFocus={onCloseAutoFocus}
|
|
372
397
|
>
|
|
373
|
-
<div style={{ display: 'contents' }}>{children}</div>
|
|
398
|
+
{isWeb ? <div style={{ display: 'contents' }}>{children}</div> : children}
|
|
374
399
|
</FocusScope>
|
|
375
400
|
)}
|
|
376
401
|
</RemoveScroll>
|
|
@@ -418,11 +443,6 @@ export type PopoverArrowProps = PopperArrowProps
|
|
|
418
443
|
|
|
419
444
|
export const PopoverArrow = React.forwardRef<PopoverArrowElement, PopoverArrowProps>(
|
|
420
445
|
(props: ScopedProps<PopoverArrowProps>, forwardedRef) => {
|
|
421
|
-
// we dont show on native and i'm getting an err
|
|
422
|
-
if (!isWeb) {
|
|
423
|
-
return null
|
|
424
|
-
}
|
|
425
|
-
|
|
426
446
|
const { __scopePopover, ...arrowProps } = props
|
|
427
447
|
const popperScope = usePopoverScope(__scopePopover)
|
|
428
448
|
return <PopperArrow {...popperScope} {...arrowProps} ref={forwardedRef} />
|
|
@@ -465,7 +485,7 @@ export const Popover = withStaticProperties(
|
|
|
465
485
|
|
|
466
486
|
const sheetBreakpoint = when
|
|
467
487
|
const popperScope = usePopoverScope(__scopePopover)
|
|
468
|
-
const triggerRef = React.useRef<
|
|
488
|
+
const triggerRef = React.useRef<TamaguiElement>(null)
|
|
469
489
|
const [hasCustomAnchor, setHasCustomAnchor] = React.useState(false)
|
|
470
490
|
const [open, setOpen] = useControllableState({
|
|
471
491
|
prop: openProp,
|
|
@@ -476,6 +496,7 @@ export const Popover = withStaticProperties(
|
|
|
476
496
|
|
|
477
497
|
const breakpointActive = useSheetBreakpointActive(sheetBreakpoint)
|
|
478
498
|
|
|
499
|
+
// Custom floating context to override the Popper on web
|
|
479
500
|
const useFloatingContext = React.useCallback(
|
|
480
501
|
(props: UseFloatingProps) => {
|
|
481
502
|
const floating = useFloating({
|
|
@@ -510,6 +531,7 @@ export const Popover = withStaticProperties(
|
|
|
510
531
|
contentId: useId(),
|
|
511
532
|
triggerRef,
|
|
512
533
|
open,
|
|
534
|
+
breakpointActive,
|
|
513
535
|
onOpenChange: setOpen,
|
|
514
536
|
onOpenToggle: useEvent(() => {
|
|
515
537
|
if (open && breakpointActive) {
|
|
@@ -529,20 +551,25 @@ export const Popover = withStaticProperties(
|
|
|
529
551
|
// })
|
|
530
552
|
// }
|
|
531
553
|
|
|
554
|
+
const contents = (
|
|
555
|
+
<Popper {...popperScope} stayInFrame {...restProps}>
|
|
556
|
+
<PopoverProviderInternal {...popoverContext}>
|
|
557
|
+
<PopoverSheetController onOpenChange={setOpen} __scopePopover={__scopePopover}>
|
|
558
|
+
{children}
|
|
559
|
+
</PopoverSheetController>
|
|
560
|
+
</PopoverProviderInternal>
|
|
561
|
+
</Popper>
|
|
562
|
+
)
|
|
563
|
+
|
|
532
564
|
return (
|
|
533
565
|
<AdaptProvider>
|
|
534
|
-
|
|
535
|
-
<
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
{children}
|
|
542
|
-
</PopoverSheetController>
|
|
543
|
-
</PopoverProviderInternal>
|
|
544
|
-
</Popper>
|
|
545
|
-
</FloatingOverrideContext.Provider>
|
|
566
|
+
{isWeb ? (
|
|
567
|
+
<FloatingOverrideContext.Provider value={useFloatingContext as any}>
|
|
568
|
+
{contents}
|
|
569
|
+
</FloatingOverrideContext.Provider>
|
|
570
|
+
) : (
|
|
571
|
+
contents
|
|
572
|
+
)}
|
|
546
573
|
</AdaptProvider>
|
|
547
574
|
)
|
|
548
575
|
}) as React.FC<PopoverProps>,
|
|
@@ -577,7 +604,7 @@ const PopoverSheetController = (
|
|
|
577
604
|
props.__scopePopover
|
|
578
605
|
)
|
|
579
606
|
const showSheet = useShowPopoverSheet(context)
|
|
580
|
-
const breakpointActive =
|
|
607
|
+
const breakpointActive = context.breakpointActive
|
|
581
608
|
const getShowSheet = useGet(showSheet)
|
|
582
609
|
return (
|
|
583
610
|
<SheetController
|
|
@@ -596,14 +623,13 @@ const PopoverSheetController = (
|
|
|
596
623
|
|
|
597
624
|
const useSheetBreakpointActive = (breakpoint?: MediaQueryKey | null | boolean) => {
|
|
598
625
|
const media = useMedia()
|
|
599
|
-
if (!breakpoint)
|
|
600
|
-
|
|
626
|
+
if (typeof breakpoint === 'boolean' || !breakpoint) {
|
|
627
|
+
return !!breakpoint
|
|
628
|
+
}
|
|
601
629
|
return media[breakpoint]
|
|
602
630
|
}
|
|
603
631
|
|
|
604
632
|
const useShowPopoverSheet = (context: PopoverContextValue) => {
|
|
605
|
-
// for now always show as sheet on native
|
|
606
|
-
if (!isWeb) return true
|
|
607
633
|
const breakpointActive = useSheetBreakpointActive(context.sheetBreakpoint)
|
|
608
634
|
return context.open === false ? false : breakpointActive
|
|
609
635
|
}
|
package/types/Popover.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '@tamagui/polyfill-dev';
|
|
2
|
-
import { SizeTokens } from '@tamagui/core';
|
|
2
|
+
import { SizeTokens, TamaguiElement } from '@tamagui/core';
|
|
3
3
|
import type { Scope } from '@tamagui/create-context';
|
|
4
4
|
import { DismissableProps } from '@tamagui/dismissable';
|
|
5
5
|
import { FocusScopeProps } from '@tamagui/focus-scope';
|
|
@@ -14,7 +14,7 @@ export type PopoverProps = PopperProps & {
|
|
|
14
14
|
onOpenChange?: (open: boolean) => void;
|
|
15
15
|
};
|
|
16
16
|
type PopoverContextValue = {
|
|
17
|
-
triggerRef: React.RefObject<
|
|
17
|
+
triggerRef: React.RefObject<any>;
|
|
18
18
|
contentId?: string;
|
|
19
19
|
open: boolean;
|
|
20
20
|
onOpenChange(open: boolean): void;
|
|
@@ -26,6 +26,7 @@ type PopoverContextValue = {
|
|
|
26
26
|
sheetBreakpoint: any;
|
|
27
27
|
scopeKey: string;
|
|
28
28
|
popperScope: any;
|
|
29
|
+
breakpointActive?: boolean;
|
|
29
30
|
};
|
|
30
31
|
export declare const usePopoverScope: (scope: Scope<any>) => {
|
|
31
32
|
[__scopeProp: string]: Scope<any>;
|
|
@@ -212,7 +213,7 @@ export declare const Popover: React.FC<PopoverProps> & {
|
|
|
212
213
|
[x: string]: undefined;
|
|
213
214
|
}>> & import("@tamagui/core").PseudoProps<Partial<ScrollViewProps & Omit<import("@tamagui/core").StackProps, keyof ScrollViewProps> & Omit<{}, string | number> & {
|
|
214
215
|
[x: string]: undefined;
|
|
215
|
-
}>>, string | number>) & React.RefAttributes<
|
|
216
|
+
}>>, string | number>) & React.RefAttributes<TamaguiElement>>;
|
|
216
217
|
};
|
|
217
218
|
};
|
|
218
219
|
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import * as Floating from './floating';
|
|
3
|
+
export type UseFloatingFn = typeof Floating.useFloating;
|
|
4
|
+
type InferFloatingProps = UseFloatingFn extends (props: infer Props) => any ? Props : never;
|
|
5
|
+
export type UseFloatingProps = InferFloatingProps & {
|
|
6
|
+
sameScrollView?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type InferUseFloatingReturn = ReturnType<UseFloatingFn>;
|
|
9
|
+
export type UseFloatingReturn = InferUseFloatingReturn & {
|
|
10
|
+
context?: any;
|
|
11
|
+
getFloatingProps?: (props: {
|
|
12
|
+
ref: any;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
}) => any;
|
|
15
|
+
getReferenceProps?: (props: {
|
|
16
|
+
ref: any;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}) => any;
|
|
19
|
+
};
|
|
20
|
+
export declare const FloatingOverrideContext: import("react").Context<typeof Floating.useFloating | null>;
|
|
21
|
+
export declare const useFloating: (props: UseFloatingProps) => UseFloatingReturn;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=useFloating.d.ts.map
|
package/src/floating.native.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const useDismiss = () => {}
|
|
2
|
-
export const useFloating = () => {
|
|
3
|
-
return {
|
|
4
|
-
context: {},
|
|
5
|
-
reference: () => {},
|
|
6
|
-
floating: () => {},
|
|
7
|
-
refs: {
|
|
8
|
-
floating: {},
|
|
9
|
-
reference: {},
|
|
10
|
-
},
|
|
11
|
-
middlewareData: {},
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export const useFocus = () => {}
|
|
15
|
-
export const useInteractions = () => {
|
|
16
|
-
return {}
|
|
17
|
-
}
|
|
18
|
-
export const useRole = () => {}
|