@tamagui/popover 1.43.2 → 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/src/Popover.tsx CHANGED
@@ -47,6 +47,7 @@ import { Freeze } from 'react-freeze'
47
47
  import { Platform, ScrollView, ScrollViewProps } from 'react-native'
48
48
 
49
49
  import { useFloatingContext } from './useFloatingContext'
50
+
50
51
  // adapted from radix-ui popover
51
52
 
52
53
  export type PopoverProps = PopperProps & {
@@ -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
- <PopoverContentPortal zIndex={zIndex}>
173
- <Stack pointerEvents={context.open ? 'auto' : 'none'}>
174
- <Theme name={themeName}>
175
- <PopoverContentImpl
176
- {...contentImplProps}
177
- disableRemoveScroll={disableRemoveScroll}
178
- ref={composedRefs}
179
- // we make sure we're not trapping once it's been closed
180
- // (closed !== unmounted when animating out)
181
- trapFocus={trapFocus ?? context.open}
182
- disableOutsidePointerEvents
183
- onCloseAutoFocus={composeEventHandlers(
184
- props.onCloseAutoFocus,
185
- (event) => {
186
- event.preventDefault()
187
- if (!isRightClickOutsideRef.current)
188
- context.triggerRef.current?.focus()
189
- }
190
- )}
191
- onPointerDownOutside={composeEventHandlers(
192
- props.onPointerDownOutside,
193
- (event) => {
194
- const originalEvent = event.detail.originalEvent
195
- const ctrlLeftClick =
196
- originalEvent.button === 0 && originalEvent.ctrlKey === true
197
- const isRightClick = originalEvent.button === 2 || ctrlLeftClick
198
- isRightClickOutsideRef.current = isRightClick
199
- },
200
- { checkDefaultPrevented: false }
201
- )}
202
- // When focus is trapped, a `focusout` event may still happen.
203
- // We make sure we don't trigger our `onDismiss` in such case.
204
- onFocusOutside={composeEventHandlers(
205
- props.onFocusOutside,
206
- (event) => event.preventDefault(),
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
- <Portal zIndex={zIndex}>
253
- <Theme forceClassName name={themeName}>
254
- {!!context.open && !context.breakpointActive && (
255
- <YStack
256
- fullscreen
257
- onPress={composeEventHandlers(props.onPress as any, context.onOpenToggle)}
258
- />
259
- )}
260
- <Stack zIndex={(zIndex as number) + 1}>{contents}</Stack>
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 (context.open && isFullyHidden) {
338
+ if (open && isFullyHidden) {
316
339
  setIsFullyHidden(false)
317
340
  }
318
341
 
319
- if (!context.keepChildrenMounted) {
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 === PopoverScrollView) {
353
+ if (child.type === ScrollView) {
331
354
  return child.props.children
332
355
  }
333
356
  }
@@ -360,25 +383,35 @@ 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(context.open)}
367
- keepChildrenMounted={context.keepChildrenMounted}
395
+ present={Boolean(open)}
396
+ keepChildrenMounted={keepChildrenMounted}
368
397
  onExitComplete={() => {
369
398
  setIsFullyHidden(true)
370
399
  }}
371
400
  >
372
- <Freeze freeze={isFullyHidden}>
401
+ <FreezeToLastContents
402
+ // freeze if fully hidden but fallback to last contents
403
+ // if keepChildrenMounted then mount it on the first
404
+ freeze={freeze}
405
+ >
373
406
  <PopperContent
374
407
  key={context.contentId}
375
- data-state={getState(context.open)}
408
+ data-state={getState(open)}
376
409
  id={context.contentId}
377
410
  ref={forwardedRef}
378
411
  {...contentProps}
379
412
  >
380
413
  <RemoveScroll
381
- enabled={disableRemoveScroll ? false : context.open}
414
+ enabled={disableRemoveScroll ? false : open}
382
415
  allowPinchZoom
383
416
  // causes lots of bugs on touch web on site
384
417
  removeScrollBar={false}
@@ -386,25 +419,31 @@ const PopoverContentImpl = React.forwardRef<
386
419
  display: 'contents',
387
420
  }}
388
421
  >
389
- {trapFocus === false ? (
390
- children
391
- ) : (
392
- <FocusScope
393
- loop
394
- trapped={trapFocus ?? context.open}
395
- onMountAutoFocus={onOpenAutoFocus}
396
- onUnmountAutoFocus={onCloseAutoFocus}
397
- >
398
- {isWeb ? <div style={{ display: 'contents' }}>{children}</div> : children}
399
- </FocusScope>
400
- )}
422
+ <FocusScope
423
+ loop
424
+ trapped={trapFocus ?? open}
425
+ onMountAutoFocus={onOpenAutoFocus}
426
+ onUnmountAutoFocus={onCloseAutoFocus}
427
+ >
428
+ {contents}
429
+ </FocusScope>
401
430
  </RemoveScroll>
402
431
  </PopperContent>
403
- </Freeze>
432
+ </FreezeToLastContents>
404
433
  </Animate>
405
434
  )
406
435
  })
407
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
+
408
447
  /* -------------------------------------------------------------------------------------------------
409
448
  * PopoverClose
410
449
  * -----------------------------------------------------------------------------------------------*/
@@ -439,14 +478,6 @@ export const PopoverArrow = React.forwardRef<TamaguiElement, PopoverArrowProps>(
439
478
  }
440
479
  )
441
480
 
442
- /* -------------------------------------------------------------------------------------------------
443
- * PopoverScrollView
444
- * -----------------------------------------------------------------------------------------------*/
445
-
446
- const PopoverScrollView = React.forwardRef<ScrollView, ScrollViewProps>((props, ref) => {
447
- return <ScrollView ref={ref} {...props} />
448
- })
449
-
450
481
  /* -------------------------------------------------------------------------------------------------
451
482
  * Popover
452
483
  * -----------------------------------------------------------------------------------------------*/
@@ -539,7 +570,7 @@ export const Popover = withStaticProperties(
539
570
  Content: PopoverContent,
540
571
  Close: PopoverClose,
541
572
  Adapt,
542
- ScrollView: PopoverScrollView,
573
+ ScrollView: ScrollView,
543
574
  Sheet: Sheet.Controlled,
544
575
  }
545
576
  )
@@ -206,7 +206,7 @@ export declare const Popover: React.FC<PopoverProps> & {
206
206
  shouldForwardSpace: boolean;
207
207
  };
208
208
  };
209
- ScrollView: React.ForwardRefExoticComponent<ScrollViewProps & React.RefAttributes<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)>;
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../src/Popover.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../src/Popover.tsx"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAA;AAM9B,OAAO,EAEL,UAAU,EAEV,UAAU,EACV,cAAc,EAYf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,OAAO,EAAc,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAClE,OAAO,EAIL,gBAAgB,EAGhB,kBAAkB,EAElB,WAAW,EAEZ,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAgB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAExE,OAAO,EAAU,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMpE,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,KAAK,mBAAmB,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACjC,YAAY,IAAI,IAAI,CAAA;IACpB,eAAe,EAAE,OAAO,CAAA;IACxB,iBAAiB,IAAI,IAAI,CAAA;IACzB,oBAAoB,IAAI,IAAI,CAAA;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,eAAe,EAAE,GAAG,CAAA;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,eAAO,MAAM,cAAc,4DAAsD,CAAA;AAEjF,eAAO,MAAM,iBAAiB,2BAAyC,CAAA;AAMvE,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAA;AAE5C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;4CAYzB,CAAA;AAMD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAA;AAE5C,eAAO,MAAM,cAAc;;8+BAyB1B,CAAA;AAMD,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,CAAA;AAIzD,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,uBAAuB,EAAE,6BAA6B,CAAC;IACpE;;OAEG;IACH,cAAc,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,CAAA;CACrD;AAED,eAAO,MAAM,cAAc,2HAU1B,CAAA;AA8HD,MAAM,WAAW,uBACf,SAAQ,kBAAkB,EACxB,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,UAAU,CAAC;IAClD;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAA;IAEtC;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC,kBAAkB,CAAC,CAAA;IAErD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAExD,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAgJD,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;4CAcxB,CAAA;AAMD,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAA;AAEhD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;wCAIxB,CAAA;AAMD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2FnB,CAAA"}