@tamagui/popover 1.43.1 → 1.43.3
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 +80 -49
- package/dist/cjs/Popover.js.map +1 -1
- package/dist/esm/Popover.js +80 -49
- package/dist/esm/Popover.js.map +1 -1
- package/dist/jsx/Popover.js +58 -31
- package/dist/jsx/Popover.js.map +1 -1
- package/dist/jsx/Popover.mjs +58 -31
- package/dist/jsx/Popover.mjs.map +1 -1
- package/package.json +19 -18
- package/src/Popover.tsx +128 -95
- package/types/Popover.d.ts +1 -1
- package/types/Popover.d.ts.map +1 -1
package/src/Popover.tsx
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// adapted from radix-ui popover
|
|
2
|
-
|
|
3
1
|
import '@tamagui/polyfill-dev'
|
|
4
2
|
|
|
5
3
|
import { Adapt, useAdaptParent } from '@tamagui/adapt'
|
|
@@ -45,10 +43,13 @@ import { Sheet, SheetController } from '@tamagui/sheet'
|
|
|
45
43
|
import { YStack, YStackProps } from '@tamagui/stacks'
|
|
46
44
|
import { useControllableState } from '@tamagui/use-controllable-state'
|
|
47
45
|
import * as React from 'react'
|
|
46
|
+
import { Freeze } from 'react-freeze'
|
|
48
47
|
import { Platform, ScrollView, ScrollViewProps } from 'react-native'
|
|
49
48
|
|
|
50
49
|
import { useFloatingContext } from './useFloatingContext'
|
|
51
50
|
|
|
51
|
+
// adapted from radix-ui popover
|
|
52
|
+
|
|
52
53
|
export type PopoverProps = PopperProps & {
|
|
53
54
|
open?: boolean
|
|
54
55
|
defaultOpen?: boolean
|
|
@@ -148,6 +149,18 @@ export interface PopoverContentTypeProps
|
|
|
148
149
|
export const PopoverContent = PopperContentFrame.extractable(
|
|
149
150
|
React.forwardRef<PopoverContentTypeElement, PopoverContentTypeProps>(
|
|
150
151
|
function PopoverContent(props: PopoverContentTypeProps, forwardedRef) {
|
|
152
|
+
return (
|
|
153
|
+
<PopoverContentPortal zIndex={props.zIndex}>
|
|
154
|
+
<PopoverContentInner {...props} ref={forwardedRef} />
|
|
155
|
+
</PopoverContentPortal>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
const PopoverContentInner = React.memo(
|
|
162
|
+
React.forwardRef<PopoverContentTypeElement, PopoverContentTypeProps>(
|
|
163
|
+
(props, forwardedRef) => {
|
|
151
164
|
const {
|
|
152
165
|
allowPinchZoom,
|
|
153
166
|
trapFocus,
|
|
@@ -159,6 +172,7 @@ export const PopoverContent = PopperContentFrame.extractable(
|
|
|
159
172
|
const contentRef = React.useRef<any>(null)
|
|
160
173
|
const composedRefs = useComposedRefs(forwardedRef, contentRef)
|
|
161
174
|
const isRightClickOutsideRef = React.useRef(false)
|
|
175
|
+
const themeName = useThemeName()
|
|
162
176
|
|
|
163
177
|
// aria-hide everything except the content (better supported equivalent to setting aria-modal)
|
|
164
178
|
React.useEffect(() => {
|
|
@@ -167,49 +181,42 @@ export const PopoverContent = PopperContentFrame.extractable(
|
|
|
167
181
|
if (content) return hideOthers(content)
|
|
168
182
|
}, [context.open])
|
|
169
183
|
|
|
170
|
-
const themeName = useThemeName()
|
|
171
184
|
return (
|
|
172
|
-
<
|
|
173
|
-
<
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
{ checkDefaultPrevented: false }
|
|
208
|
-
)}
|
|
209
|
-
/>
|
|
210
|
-
</Theme>
|
|
211
|
-
</Stack>
|
|
212
|
-
</PopoverContentPortal>
|
|
185
|
+
<Stack pointerEvents={context.open ? 'auto' : 'none'}>
|
|
186
|
+
<Theme name={themeName}>
|
|
187
|
+
<PopoverContentImpl
|
|
188
|
+
{...contentImplProps}
|
|
189
|
+
disableRemoveScroll={disableRemoveScroll}
|
|
190
|
+
ref={composedRefs}
|
|
191
|
+
// we make sure we're not trapping once it's been closed
|
|
192
|
+
// (closed !== unmounted when animating out)
|
|
193
|
+
trapFocus={trapFocus ?? context.open}
|
|
194
|
+
disableOutsidePointerEvents
|
|
195
|
+
onCloseAutoFocus={composeEventHandlers(props.onCloseAutoFocus, (event) => {
|
|
196
|
+
event.preventDefault()
|
|
197
|
+
if (!isRightClickOutsideRef.current) context.triggerRef.current?.focus()
|
|
198
|
+
})}
|
|
199
|
+
onPointerDownOutside={composeEventHandlers(
|
|
200
|
+
props.onPointerDownOutside,
|
|
201
|
+
(event) => {
|
|
202
|
+
const originalEvent = event.detail.originalEvent
|
|
203
|
+
const ctrlLeftClick =
|
|
204
|
+
originalEvent.button === 0 && originalEvent.ctrlKey === true
|
|
205
|
+
const isRightClick = originalEvent.button === 2 || ctrlLeftClick
|
|
206
|
+
isRightClickOutsideRef.current = isRightClick
|
|
207
|
+
},
|
|
208
|
+
{ checkDefaultPrevented: false }
|
|
209
|
+
)}
|
|
210
|
+
// When focus is trapped, a `focusout` event may still happen.
|
|
211
|
+
// We make sure we don't trigger our `onDismiss` in such case.
|
|
212
|
+
onFocusOutside={composeEventHandlers(
|
|
213
|
+
props.onFocusOutside,
|
|
214
|
+
(event) => event.preventDefault(),
|
|
215
|
+
{ checkDefaultPrevented: false }
|
|
216
|
+
)}
|
|
217
|
+
/>
|
|
218
|
+
</Theme>
|
|
219
|
+
</Stack>
|
|
213
220
|
)
|
|
214
221
|
}
|
|
215
222
|
)
|
|
@@ -230,9 +237,22 @@ function PopoverRepropagateContext(props: {
|
|
|
230
237
|
}
|
|
231
238
|
|
|
232
239
|
function PopoverContentPortal(props: PopoverContentTypeProps) {
|
|
240
|
+
const zIndex = props.zIndex ?? 150_000
|
|
241
|
+
|
|
242
|
+
// Portal the contents and add a transparent bg overlay to handle dismiss on native
|
|
243
|
+
return (
|
|
244
|
+
<Portal zIndex={zIndex}>
|
|
245
|
+
{React.useMemo(() => {
|
|
246
|
+
return <PopoverContentPortalContents {...props} />
|
|
247
|
+
}, [props])}
|
|
248
|
+
</Portal>
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const PopoverContentPortalContents = (props: PopoverContentTypeProps) => {
|
|
233
253
|
const themeName = useThemeName()
|
|
234
|
-
const context = usePopoverContext()
|
|
235
254
|
const popperContext = usePopperContext()
|
|
255
|
+
const context = usePopoverContext()
|
|
236
256
|
|
|
237
257
|
// on android we have to re-pass context
|
|
238
258
|
let contents = props.children
|
|
@@ -245,21 +265,16 @@ function PopoverContentPortal(props: PopoverContentTypeProps) {
|
|
|
245
265
|
)
|
|
246
266
|
}
|
|
247
267
|
|
|
248
|
-
const zIndex = props.zIndex ?? 150_000
|
|
249
|
-
|
|
250
|
-
// Portal the contents and add a transparent bg overlay to handle dismiss on native
|
|
251
268
|
return (
|
|
252
|
-
<
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
</Theme>
|
|
262
|
-
</Portal>
|
|
269
|
+
<Theme forceClassName name={themeName}>
|
|
270
|
+
{!!context.open && !context.breakpointActive && (
|
|
271
|
+
<YStack
|
|
272
|
+
fullscreen
|
|
273
|
+
onPress={composeEventHandlers(props.onPress as any, context.onOpenToggle)}
|
|
274
|
+
/>
|
|
275
|
+
)}
|
|
276
|
+
{contents}
|
|
277
|
+
</Theme>
|
|
263
278
|
)
|
|
264
279
|
}
|
|
265
280
|
|
|
@@ -309,14 +324,22 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
309
324
|
...contentProps
|
|
310
325
|
} = props
|
|
311
326
|
const context = usePopoverContext()
|
|
327
|
+
const { open, keepChildrenMounted } = context
|
|
312
328
|
const popperContext = usePopperContext()
|
|
313
329
|
const [isFullyHidden, setIsFullyHidden] = React.useState(!context.open)
|
|
330
|
+
const [hasShownOnce, setHasShownOnce] = React.useState(false)
|
|
331
|
+
|
|
332
|
+
React.useEffect(() => {
|
|
333
|
+
if (!open) {
|
|
334
|
+
setHasShownOnce(true)
|
|
335
|
+
}
|
|
336
|
+
}, [open])
|
|
314
337
|
|
|
315
|
-
if (
|
|
338
|
+
if (open && isFullyHidden) {
|
|
316
339
|
setIsFullyHidden(false)
|
|
317
340
|
}
|
|
318
341
|
|
|
319
|
-
if (!
|
|
342
|
+
if (!keepChildrenMounted) {
|
|
320
343
|
if (isFullyHidden) {
|
|
321
344
|
return null
|
|
322
345
|
}
|
|
@@ -327,7 +350,7 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
327
350
|
// TODO this should be disabled through context
|
|
328
351
|
const childrenWithoutScrollView = React.Children.toArray(children).map((child) => {
|
|
329
352
|
if (React.isValidElement(child)) {
|
|
330
|
-
if (child.type ===
|
|
353
|
+
if (child.type === ScrollView) {
|
|
331
354
|
return child.props.children
|
|
332
355
|
}
|
|
333
356
|
}
|
|
@@ -360,49 +383,67 @@ const PopoverContentImpl = React.forwardRef<
|
|
|
360
383
|
// onDismiss={handleDismiss}
|
|
361
384
|
// >
|
|
362
385
|
|
|
386
|
+
const contents = React.useMemo(() => {
|
|
387
|
+
return isWeb ? <div style={{ display: 'contents' }}>{children}</div> : children
|
|
388
|
+
}, [children])
|
|
389
|
+
|
|
390
|
+
const freeze = isFullyHidden && (hasShownOnce || !keepChildrenMounted)
|
|
391
|
+
|
|
363
392
|
return (
|
|
364
393
|
<Animate
|
|
365
394
|
type="presence"
|
|
366
|
-
present={Boolean(
|
|
367
|
-
keepChildrenMounted={
|
|
395
|
+
present={Boolean(open)}
|
|
396
|
+
keepChildrenMounted={keepChildrenMounted}
|
|
368
397
|
onExitComplete={() => {
|
|
369
398
|
setIsFullyHidden(true)
|
|
370
399
|
}}
|
|
371
400
|
>
|
|
372
|
-
<
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
ref={forwardedRef}
|
|
377
|
-
{...contentProps}
|
|
401
|
+
<FreezeToLastContents
|
|
402
|
+
// freeze if fully hidden but fallback to last contents
|
|
403
|
+
// if keepChildrenMounted then mount it on the first
|
|
404
|
+
freeze={freeze}
|
|
378
405
|
>
|
|
379
|
-
<
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
display: 'contents',
|
|
386
|
-
}}
|
|
406
|
+
<PopperContent
|
|
407
|
+
key={context.contentId}
|
|
408
|
+
data-state={getState(open)}
|
|
409
|
+
id={context.contentId}
|
|
410
|
+
ref={forwardedRef}
|
|
411
|
+
{...contentProps}
|
|
387
412
|
>
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
413
|
+
<RemoveScroll
|
|
414
|
+
enabled={disableRemoveScroll ? false : open}
|
|
415
|
+
allowPinchZoom
|
|
416
|
+
// causes lots of bugs on touch web on site
|
|
417
|
+
removeScrollBar={false}
|
|
418
|
+
style={{
|
|
419
|
+
display: 'contents',
|
|
420
|
+
}}
|
|
421
|
+
>
|
|
391
422
|
<FocusScope
|
|
392
423
|
loop
|
|
393
|
-
trapped={trapFocus ??
|
|
424
|
+
trapped={trapFocus ?? open}
|
|
394
425
|
onMountAutoFocus={onOpenAutoFocus}
|
|
395
426
|
onUnmountAutoFocus={onCloseAutoFocus}
|
|
396
427
|
>
|
|
397
|
-
{
|
|
428
|
+
{contents}
|
|
398
429
|
</FocusScope>
|
|
399
|
-
|
|
400
|
-
</
|
|
401
|
-
</
|
|
430
|
+
</RemoveScroll>
|
|
431
|
+
</PopperContent>
|
|
432
|
+
</FreezeToLastContents>
|
|
402
433
|
</Animate>
|
|
403
434
|
)
|
|
404
435
|
})
|
|
405
436
|
|
|
437
|
+
const FreezeToLastContents = (props: { freeze: boolean; children: any }) => {
|
|
438
|
+
const last = React.useRef()
|
|
439
|
+
|
|
440
|
+
if (!props.freeze) {
|
|
441
|
+
last.current = props.children
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return <Freeze placeholder={last.current} {...props} />
|
|
445
|
+
}
|
|
446
|
+
|
|
406
447
|
/* -------------------------------------------------------------------------------------------------
|
|
407
448
|
* PopoverClose
|
|
408
449
|
* -----------------------------------------------------------------------------------------------*/
|
|
@@ -437,14 +478,6 @@ export const PopoverArrow = React.forwardRef<TamaguiElement, PopoverArrowProps>(
|
|
|
437
478
|
}
|
|
438
479
|
)
|
|
439
480
|
|
|
440
|
-
/* -------------------------------------------------------------------------------------------------
|
|
441
|
-
* PopoverScrollView
|
|
442
|
-
* -----------------------------------------------------------------------------------------------*/
|
|
443
|
-
|
|
444
|
-
const PopoverScrollView = React.forwardRef<ScrollView, ScrollViewProps>((props, ref) => {
|
|
445
|
-
return <ScrollView ref={ref} {...props} />
|
|
446
|
-
})
|
|
447
|
-
|
|
448
481
|
/* -------------------------------------------------------------------------------------------------
|
|
449
482
|
* Popover
|
|
450
483
|
* -----------------------------------------------------------------------------------------------*/
|
|
@@ -537,7 +570,7 @@ export const Popover = withStaticProperties(
|
|
|
537
570
|
Content: PopoverContent,
|
|
538
571
|
Close: PopoverClose,
|
|
539
572
|
Adapt,
|
|
540
|
-
ScrollView:
|
|
573
|
+
ScrollView: ScrollView,
|
|
541
574
|
Sheet: Sheet.Controlled,
|
|
542
575
|
}
|
|
543
576
|
)
|
package/types/Popover.d.ts
CHANGED
|
@@ -206,7 +206,7 @@ export declare const Popover: React.FC<PopoverProps> & {
|
|
|
206
206
|
shouldForwardSpace: boolean;
|
|
207
207
|
};
|
|
208
208
|
};
|
|
209
|
-
ScrollView:
|
|
209
|
+
ScrollView: typeof ScrollView;
|
|
210
210
|
Sheet: React.FunctionComponent<Omit<import("@tamagui/sheet").SheetProps, "open" | "onOpenChange"> & React.RefAttributes<import("react-native").View>> & {
|
|
211
211
|
Frame: React.ForwardRefExoticComponent<Omit<import("react-native").ViewProps, "display" | "children" | "onLayout" | keyof import("react-native").GestureResponderHandlers | "style"> & import("@tamagui/core").ExtendBaseStackProps & import("@tamagui/core").TamaguiComponentPropsBase & {
|
|
212
212
|
style?: import("@tamagui/core").StyleProp<React.CSSProperties | import("react-native").ViewStyle | (React.CSSProperties & import("react-native").ViewStyle)>;
|
package/types/Popover.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../src/Popover.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../src/Popover.tsx"],"names":[],"mappings":"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"}
|