@tamagui/popover 1.0.1-beta.59 → 1.0.1-beta.60

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/popover",
3
- "version": "1.0.1-beta.59",
3
+ "version": "1.0.1-beta.60",
4
4
  "sideEffects": true,
5
5
  "source": "src/index.ts",
6
6
  "types": "./types/index.d.ts",
@@ -8,6 +8,7 @@
8
8
  "module": "dist/esm",
9
9
  "module:jsx": "dist/jsx",
10
10
  "files": [
11
+ "src",
11
12
  "types",
12
13
  "dist"
13
14
  ],
@@ -19,15 +20,15 @@
19
20
  },
20
21
  "dependencies": {
21
22
  "@floating-ui/react-dom-interactions": "^0.5.0",
22
- "@tamagui/animate-presence": "^1.0.1-beta.59",
23
- "@tamagui/compose-refs": "^1.0.1-beta.59",
24
- "@tamagui/core": "^1.0.1-beta.59",
25
- "@tamagui/create-context": "^1.0.1-beta.59",
26
- "@tamagui/polyfill-dev": "^1.0.1-beta.59",
27
- "@tamagui/popper": "^1.0.1-beta.59",
28
- "@tamagui/portal": "^1.0.1-beta.59",
29
- "@tamagui/stacks": "^1.0.1-beta.59",
30
- "@tamagui/use-controllable-state": "^1.0.1-beta.59"
23
+ "@tamagui/animate-presence": "^1.0.1-beta.60",
24
+ "@tamagui/compose-refs": "^1.0.1-beta.60",
25
+ "@tamagui/core": "^1.0.1-beta.60",
26
+ "@tamagui/create-context": "^1.0.1-beta.60",
27
+ "@tamagui/polyfill-dev": "^1.0.1-beta.60",
28
+ "@tamagui/popper": "^1.0.1-beta.60",
29
+ "@tamagui/portal": "^1.0.1-beta.60",
30
+ "@tamagui/stacks": "^1.0.1-beta.60",
31
+ "@tamagui/use-controllable-state": "^1.0.1-beta.60"
31
32
  },
32
33
  "peerDependencies": {
33
34
  "react": "*",
@@ -35,7 +36,7 @@
35
36
  "react-native": "*"
36
37
  },
37
38
  "devDependencies": {
38
- "@tamagui/build": "^1.0.1-beta.59",
39
+ "@tamagui/build": "^1.0.1-beta.60",
39
40
  "@types/react-dom": "^18.0.3",
40
41
  "@types/react-native": "^0.67.3",
41
42
  "react": "*",
@@ -0,0 +1,552 @@
1
+ // adapted from radix-ui popover
2
+
3
+ import '@tamagui/polyfill-dev'
4
+
5
+ import {
6
+ useDismiss,
7
+ useFloating,
8
+ useFocus,
9
+ useInteractions,
10
+ useRole,
11
+ } from '@floating-ui/react-dom-interactions'
12
+ import { AnimatePresence } from '@tamagui/animate-presence'
13
+ import { useComposedRefs } from '@tamagui/compose-refs'
14
+ import {
15
+ Theme,
16
+ composeEventHandlers,
17
+ useId,
18
+ useThemeName,
19
+ withStaticProperties,
20
+ } from '@tamagui/core'
21
+ import type { Scope } from '@tamagui/create-context'
22
+ import { createContextScope } from '@tamagui/create-context'
23
+ // import { DismissableLayer } from '@tamagui/react-dismissable-layer'
24
+ // import { useFocusGuards } from '@tamagui/react-focus-guards'
25
+ // import { FocusScope } from '@tamagui/react-focus-scope'
26
+ import {
27
+ FloatingOverrideContext,
28
+ Popper,
29
+ PopperAnchor,
30
+ PopperArrow,
31
+ PopperContent,
32
+ PopperContentProps,
33
+ PopperProps,
34
+ UseFloatingFn,
35
+ createPopperScope,
36
+ } from '@tamagui/popper'
37
+ import { Portal } from '@tamagui/portal'
38
+ import { YStack, YStackProps } from '@tamagui/stacks'
39
+ import { useControllableState } from '@tamagui/use-controllable-state'
40
+ // import { hideOthers } from 'aria-hidden'
41
+ import * as React from 'react'
42
+ import { GestureResponderEvent, View } from 'react-native'
43
+
44
+ // import { RemoveScroll } from 'react-remove-scroll'
45
+
46
+ const POPOVER_NAME = 'Popover'
47
+
48
+ type ScopedProps<P> = P & { __scopePopover?: Scope }
49
+ const [createPopoverContext, createPopoverScopeInternal] = createContextScope(POPOVER_NAME, [
50
+ createPopperScope,
51
+ ])
52
+ export const usePopoverScope = createPopperScope()
53
+ export const createPopoverScope = createPopoverScopeInternal
54
+
55
+ type PopoverContextValue = {
56
+ triggerRef: React.RefObject<HTMLButtonElement>
57
+ contentId?: string
58
+ open: boolean
59
+ onOpenChange(open: boolean): void
60
+ onOpenToggle(): void
61
+ hasCustomAnchor: boolean
62
+ onCustomAnchorAdd(): void
63
+ onCustomAnchorRemove(): void
64
+ modal: boolean
65
+ }
66
+
67
+ const [PopoverProviderInternal, usePopoverInternalContext] =
68
+ createPopoverContext<PopoverContextValue>(POPOVER_NAME)
69
+
70
+ export const __PopoverProviderInternal = PopoverProviderInternal
71
+
72
+ /* -------------------------------------------------------------------------------------------------
73
+ * PopoverAnchor
74
+ * -----------------------------------------------------------------------------------------------*/
75
+
76
+ const ANCHOR_NAME = 'PopoverAnchor'
77
+
78
+ type PopoverAnchorElement = HTMLElement | View
79
+ export type PopoverAnchorProps = YStackProps
80
+
81
+ export const PopoverAnchor = React.forwardRef<PopoverAnchorElement, PopoverAnchorProps>(
82
+ (props: ScopedProps<PopoverAnchorProps>, forwardedRef) => {
83
+ const { __scopePopover, ...anchorProps } = props
84
+ const context = usePopoverInternalContext(ANCHOR_NAME, __scopePopover)
85
+ const popperScope = usePopoverScope(__scopePopover)
86
+ const { onCustomAnchorAdd, onCustomAnchorRemove } = context
87
+
88
+ React.useEffect(() => {
89
+ onCustomAnchorAdd()
90
+ return () => onCustomAnchorRemove()
91
+ }, [onCustomAnchorAdd, onCustomAnchorRemove])
92
+
93
+ return <PopperAnchor {...popperScope} {...anchorProps} ref={forwardedRef} />
94
+ }
95
+ )
96
+
97
+ PopoverAnchor.displayName = ANCHOR_NAME
98
+
99
+ /* -------------------------------------------------------------------------------------------------
100
+ * PopoverTrigger
101
+ * -----------------------------------------------------------------------------------------------*/
102
+
103
+ const TRIGGER_NAME = 'PopoverTrigger'
104
+
105
+ type PopoverTriggerElement = HTMLElement | View
106
+ export type PopoverTriggerProps = YStackProps
107
+
108
+ export const PopoverTrigger = React.forwardRef<PopoverTriggerElement, PopoverTriggerProps>(
109
+ (props: ScopedProps<PopoverTriggerProps>, forwardedRef) => {
110
+ const { __scopePopover, ...triggerProps } = props
111
+ const context = usePopoverInternalContext(TRIGGER_NAME, __scopePopover)
112
+ const popperScope = usePopoverScope(__scopePopover)
113
+ const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef)
114
+
115
+ const trigger = (
116
+ <YStack
117
+ aria-haspopup="dialog"
118
+ aria-expanded={context.open}
119
+ aria-controls={context.contentId}
120
+ data-state={getState(context.open)}
121
+ {...triggerProps}
122
+ ref={composedTriggerRef}
123
+ onPress={composeEventHandlers(props.onPress, context.onOpenToggle)}
124
+ />
125
+ )
126
+
127
+ return context.hasCustomAnchor ? (
128
+ trigger
129
+ ) : (
130
+ <PopperAnchor asChild {...popperScope}>
131
+ {trigger}
132
+ </PopperAnchor>
133
+ )
134
+ }
135
+ )
136
+
137
+ PopoverTrigger.displayName = TRIGGER_NAME
138
+
139
+ /* -------------------------------------------------------------------------------------------------
140
+ * PopoverContent
141
+ * -----------------------------------------------------------------------------------------------*/
142
+
143
+ const CONTENT_NAME = 'PopoverContent'
144
+
145
+ export interface PopoverContentTypeProps
146
+ extends Omit<PopoverContentImplProps, 'trapFocus' | 'disableOutsidePointerEvents'> {
147
+ /**
148
+ * @see https://github.com/theKashey/react-remove-scroll#usage
149
+ */
150
+ allowPinchZoom?: RemoveScrollProps['allowPinchZoom']
151
+ }
152
+
153
+ export type PopoverContentProps = PopoverContentTypeProps
154
+
155
+ export const PopoverContent = React.forwardRef<PopoverContentTypeElement, PopoverContentProps>(
156
+ (props: ScopedProps<PopoverContentProps>, forwardedRef) => {
157
+ const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
158
+ return context.modal ? (
159
+ <PopoverContentModal {...props} ref={forwardedRef} />
160
+ ) : (
161
+ <PopoverContentNonModal {...props} ref={forwardedRef} />
162
+ )
163
+ }
164
+ )
165
+
166
+ PopoverContent.displayName = CONTENT_NAME
167
+
168
+ /* -----------------------------------------------------------------------------------------------*/
169
+
170
+ type RemoveScrollProps = any //React.ComponentProps<typeof RemoveScroll>
171
+ type PopoverContentTypeElement = PopoverContentImplElement
172
+
173
+ const PopoverContentModal = React.forwardRef<PopoverContentTypeElement, PopoverContentTypeProps>(
174
+ (props: ScopedProps<PopoverContentTypeProps>, forwardedRef) => {
175
+ const { allowPinchZoom, ...contentModalProps } = props
176
+ const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
177
+ const contentRef = React.useRef<HTMLDivElement>(null)
178
+ const composedRefs = useComposedRefs(forwardedRef, contentRef)
179
+ const isRightClickOutsideRef = React.useRef(false)
180
+ const themeName = useThemeName()
181
+
182
+ // aria-hide everything except the content (better supported equivalent to setting aria-modal)
183
+ // React.useEffect(() => {
184
+ // const content = contentRef.current
185
+ // if (content) return hideOthers(content)
186
+ // }, [])
187
+
188
+ const PortalWrapper = context.modal ? Portal : React.Fragment
189
+
190
+ return (
191
+ <PortalWrapper>
192
+ <Theme name={themeName}>
193
+ {/* <RemoveScroll allowPinchZoom={allowPinchZoom}> */}
194
+ <PopoverContentImpl
195
+ {...contentModalProps}
196
+ ref={composedRefs}
197
+ // we make sure we're not trapping once it's been closed
198
+ // (closed !== unmounted when animating out)
199
+ trapFocus={context.open}
200
+ disableOutsidePointerEvents
201
+ onCloseAutoFocus={composeEventHandlers(props.onCloseAutoFocus, (event) => {
202
+ event.preventDefault()
203
+ if (!isRightClickOutsideRef.current) context.triggerRef.current?.focus()
204
+ })}
205
+ onPointerDownOutside={composeEventHandlers(
206
+ props.onPointerDownOutside,
207
+ (event) => {
208
+ // @ts-expect-error
209
+ const originalEvent = event.detail.originalEvent
210
+ const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true
211
+ const isRightClick = originalEvent.button === 2 || ctrlLeftClick
212
+ isRightClickOutsideRef.current = isRightClick
213
+ },
214
+ { checkDefaultPrevented: false }
215
+ )}
216
+ // When focus is trapped, a `focusout` event may still happen.
217
+ // We make sure we don't trigger our `onDismiss` in such case.
218
+ onFocusOutside={composeEventHandlers(
219
+ props.onFocusOutside,
220
+ (event) => event.preventDefault(),
221
+ { checkDefaultPrevented: false }
222
+ )}
223
+ />
224
+ </Theme>
225
+ {/* </RemoveScroll> */}
226
+ </PortalWrapper>
227
+ )
228
+ }
229
+ )
230
+
231
+ const PopoverContentNonModal = React.forwardRef<PopoverContentTypeElement, PopoverContentTypeProps>(
232
+ (props: ScopedProps<PopoverContentTypeProps>, forwardedRef) => {
233
+ const { ...contentNonModalProps } = props
234
+ const context = usePopoverInternalContext(CONTENT_NAME, props.__scopePopover)
235
+ const hasInteractedOutsideRef = React.useRef(false)
236
+ const PortalWrapper = context.modal ? Portal : React.Fragment
237
+
238
+ return (
239
+ <PortalWrapper>
240
+ <PopoverContentImpl
241
+ {...contentNonModalProps}
242
+ ref={forwardedRef}
243
+ trapFocus={false}
244
+ disableOutsidePointerEvents={false}
245
+ onCloseAutoFocus={(event) => {
246
+ props.onCloseAutoFocus?.(event)
247
+
248
+ if (!event.defaultPrevented) {
249
+ if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus()
250
+ // Always prevent auto focus because we either focus manually or want user agent focus
251
+ event.preventDefault()
252
+ }
253
+
254
+ hasInteractedOutsideRef.current = false
255
+ }}
256
+ onInteractOutside={(event) => {
257
+ props.onInteractOutside?.(event)
258
+
259
+ if (!event.defaultPrevented) hasInteractedOutsideRef.current = true
260
+
261
+ // Prevent dismissing when clicking the trigger.
262
+ // As the trigger is already setup to close, without doing so would
263
+ // cause it to close and immediately open.
264
+ //
265
+ // We use `onInteractOutside` as some browsers also
266
+ // focus on pointer down, creating the same issue.
267
+ // @ts-ignore
268
+ const target = event.target as HTMLElement
269
+ const targetIsTrigger = context.triggerRef.current?.contains(target)
270
+ if (targetIsTrigger) event.preventDefault()
271
+ }}
272
+ />
273
+ </PortalWrapper>
274
+ )
275
+ }
276
+ )
277
+
278
+ /* -----------------------------------------------------------------------------------------------*/
279
+
280
+ type PopoverContentImplElement = React.ElementRef<typeof PopperContent>
281
+
282
+ // TODO
283
+ type FocusScopeProps = {
284
+ /**
285
+ * Whether focus should be trapped within the FocusScope
286
+ * (default: false)
287
+ */
288
+ trapped?: boolean
289
+
290
+ /**
291
+ * Event handler called when auto-focusing on mount.
292
+ * Can be prevented.
293
+ */
294
+ onMountAutoFocus?: (event: GestureResponderEvent) => void
295
+
296
+ /**
297
+ * Event handler called when auto-focusing on unmount.
298
+ * Can be prevented.
299
+ */
300
+ onUnmountAutoFocus?: (event: GestureResponderEvent) => void
301
+ }
302
+
303
+ type DismissableLayerProps = {
304
+ /**
305
+ * When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`.
306
+ * Users will need to click twice on outside elements to interact with them:
307
+ * Once to close the `DismissableLayer`, and again to trigger the element.
308
+ */
309
+ disableOutsidePointerEvents?: boolean
310
+
311
+ /**
312
+ * Event handler called when the escape key is down.
313
+ * Can be prevented.
314
+ */
315
+ onEscapeKeyDown?: (event: KeyboardEvent) => void
316
+
317
+ /**
318
+ * Event handler called when the a pointer event happens outside of the `DismissableLayer`.
319
+ * Can be prevented.
320
+ */
321
+ onPointerDownOutside?: (event: GestureResponderEvent) => void
322
+ // onPointerDownOutside?: (event: MouseEvent | TouchEvent) => void
323
+
324
+ /**
325
+ * Event handler called when the focus moves outside of the `DismissableLayer`.
326
+ * Can be prevented.
327
+ */
328
+ onFocusOutside?: (event: React.FocusEvent) => void
329
+
330
+ /**
331
+ * Event handler called when an interaction happens outside the `DismissableLayer`.
332
+ * Specifically, when a pointer event happens outside of the `DismissableLayer` or focus moves outside of it.
333
+ * Can be prevented.
334
+ */
335
+ onInteractOutside?: (event: GestureResponderEvent) => void
336
+ // onInteractOutside?: (event: MouseEvent | TouchEvent | React.FocusEvent) => void
337
+
338
+ /** Callback called when the `DismissableLayer` should be dismissed */
339
+ onDismiss?: () => void
340
+ }
341
+
342
+ export interface PopoverContentImplProps
343
+ extends PopperContentProps,
344
+ Omit<DismissableLayerProps, 'onDismiss'> {
345
+ /**
346
+ * Whether focus should be trapped within the `Popover`
347
+ * (default: false)
348
+ */
349
+ trapFocus?: FocusScopeProps['trapped']
350
+
351
+ /**
352
+ * Event handler called when auto-focusing on open.
353
+ * Can be prevented.
354
+ */
355
+ onOpenAutoFocus?: FocusScopeProps['onMountAutoFocus']
356
+
357
+ /**
358
+ * Event handler called when auto-focusing on close.
359
+ * Can be prevented.
360
+ */
361
+ onCloseAutoFocus?: FocusScopeProps['onUnmountAutoFocus']
362
+ }
363
+
364
+ const PopoverContentImpl = React.forwardRef<PopoverContentImplElement, PopoverContentImplProps>(
365
+ (props: ScopedProps<PopoverContentImplProps>, forwardedRef) => {
366
+ const {
367
+ __scopePopover,
368
+ trapFocus,
369
+ onOpenAutoFocus,
370
+ onCloseAutoFocus,
371
+ disableOutsidePointerEvents,
372
+ onEscapeKeyDown,
373
+ onPointerDownOutside,
374
+ onFocusOutside,
375
+ onInteractOutside,
376
+ ...contentProps
377
+ } = props
378
+ const context = usePopoverInternalContext(CONTENT_NAME, __scopePopover)
379
+ const popperScope = usePopoverScope(__scopePopover)
380
+
381
+ // Make sure the whole tree has focus guards as our `Popover` may be
382
+ // the last element in the DOM (beacuse of the `Portal`)
383
+ // useFocusGuards()
384
+
385
+ // <FocusScope
386
+ // asChild
387
+ // loop
388
+ // trapped={trapFocus}
389
+ // onMountAutoFocus={onOpenAutoFocus}
390
+ // onUnmountAutoFocus={onCloseAutoFocus}
391
+ // >
392
+ // <DismissableLayer
393
+ // asChild
394
+ // disableOutsidePointerEvents={disableOutsidePointerEvents}
395
+ // onInteractOutside={onInteractOutside}
396
+ // onEscapeKeyDown={onEscapeKeyDown}
397
+ // onPointerDownOutside={onPointerDownOutside}
398
+ // onFocusOutside={onFocusOutside}
399
+ // onDismiss={() => context.onOpenChange(false)}
400
+ // >
401
+ return (
402
+ <AnimatePresence>
403
+ {!!context.open && (
404
+ <PopperContent
405
+ data-state={getState(context.open)}
406
+ // role="dialog"
407
+ id={context.contentId}
408
+ pointerEvents="auto"
409
+ {...popperScope}
410
+ {...contentProps}
411
+ ref={forwardedRef}
412
+ />
413
+ )}
414
+ </AnimatePresence>
415
+ )
416
+ // </DismissableLayer>
417
+ // </FocusScope>
418
+ }
419
+ )
420
+
421
+ /* -------------------------------------------------------------------------------------------------
422
+ * PopoverClose
423
+ * -----------------------------------------------------------------------------------------------*/
424
+
425
+ const CLOSE_NAME = 'PopoverClose'
426
+
427
+ type PopoverCloseElement = HTMLElement | View
428
+ export type PopoverCloseProps = YStackProps
429
+
430
+ export const PopoverClose = React.forwardRef<PopoverCloseElement, PopoverCloseProps>(
431
+ (props: ScopedProps<PopoverCloseProps>, forwardedRef) => {
432
+ const { __scopePopover, ...closeProps } = props
433
+ const context = usePopoverInternalContext(CLOSE_NAME, __scopePopover)
434
+ return (
435
+ <YStack
436
+ {...closeProps}
437
+ ref={forwardedRef}
438
+ onPress={composeEventHandlers(props.onPress, () => context.onOpenChange(false))}
439
+ />
440
+ )
441
+ }
442
+ )
443
+
444
+ PopoverClose.displayName = CLOSE_NAME
445
+
446
+ /* -------------------------------------------------------------------------------------------------
447
+ * PopoverArrow
448
+ * -----------------------------------------------------------------------------------------------*/
449
+
450
+ const ARROW_NAME = 'PopoverArrow'
451
+
452
+ type PopoverArrowElement = HTMLElement | View
453
+ export type PopoverArrowProps = YStackProps
454
+
455
+ export const PopoverArrow = React.forwardRef<PopoverArrowElement, PopoverArrowProps>(
456
+ (props: ScopedProps<PopoverArrowProps>, forwardedRef) => {
457
+ const { __scopePopover, ...arrowProps } = props
458
+ const popperScope = usePopoverScope(__scopePopover)
459
+ return <PopperArrow {...popperScope} {...arrowProps} ref={forwardedRef} />
460
+ }
461
+ )
462
+
463
+ PopoverArrow.displayName = ARROW_NAME
464
+
465
+ /* -------------------------------------------------------------------------------------------------
466
+ * Popover
467
+ * -----------------------------------------------------------------------------------------------*/
468
+
469
+ export type PopoverProps = PopperProps & {
470
+ open?: boolean
471
+ defaultOpen?: boolean
472
+ onOpenChange?: (open: boolean) => void
473
+ modal?: boolean
474
+ }
475
+
476
+ export const Popover = withStaticProperties(
477
+ ((props: ScopedProps<PopoverProps>) => {
478
+ const {
479
+ __scopePopover,
480
+ children,
481
+ open: openProp,
482
+ defaultOpen,
483
+ onOpenChange,
484
+ modal = true,
485
+ ...restProps
486
+ } = props
487
+ const popperScope = usePopoverScope(__scopePopover)
488
+ const triggerRef = React.useRef<HTMLButtonElement>(null)
489
+ const [hasCustomAnchor, setHasCustomAnchor] = React.useState(false)
490
+ const [open, setOpen] = useControllableState({
491
+ prop: openProp,
492
+ defaultProp: defaultOpen || false,
493
+ onChange: onOpenChange,
494
+ })
495
+
496
+ const useFloatingFn: UseFloatingFn = (props) => {
497
+ const floating = useFloating({
498
+ ...props,
499
+ open,
500
+ onOpenChange: setOpen,
501
+ })
502
+ const { getReferenceProps, getFloatingProps } = useInteractions([
503
+ useFocus(floating.context),
504
+ useRole(floating.context, { role: 'dialog' }),
505
+ useDismiss(floating.context),
506
+ ])
507
+ return {
508
+ ...floating,
509
+ getReferenceProps,
510
+ getFloatingProps,
511
+ } as any
512
+ }
513
+
514
+ const useFloatingContext = React.useCallback(useFloatingFn, [open])
515
+
516
+ return (
517
+ <FloatingOverrideContext.Provider value={useFloatingContext}>
518
+ <Popper {...popperScope} {...restProps}>
519
+ <PopoverProviderInternal
520
+ scope={__scopePopover}
521
+ contentId={useId()}
522
+ triggerRef={triggerRef}
523
+ open={open}
524
+ onOpenChange={setOpen}
525
+ onOpenToggle={React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen])}
526
+ hasCustomAnchor={hasCustomAnchor}
527
+ onCustomAnchorAdd={React.useCallback(() => setHasCustomAnchor(true), [])}
528
+ onCustomAnchorRemove={React.useCallback(() => setHasCustomAnchor(false), [])}
529
+ modal={modal}
530
+ >
531
+ {children}
532
+ </PopoverProviderInternal>
533
+ </Popper>
534
+ </FloatingOverrideContext.Provider>
535
+ )
536
+ }) as React.FC<PopoverProps>,
537
+ {
538
+ Anchor: PopoverAnchor,
539
+ Arrow: PopoverArrow,
540
+ Trigger: PopoverTrigger,
541
+ Content: PopoverContent,
542
+ Close: PopoverClose,
543
+ }
544
+ )
545
+
546
+ Popover.displayName = POPOVER_NAME
547
+
548
+ /* -----------------------------------------------------------------------------------------------*/
549
+
550
+ function getState(open: boolean) {
551
+ return open ? 'open' : 'closed'
552
+ }
package/src/index.tsx ADDED
@@ -0,0 +1 @@
1
+ export * from './Popover'