reka-ui
Version:
Vue port for Radix UI Primitives.
1 lines • 15.6 kB
Source Map (JSON)
{"version":3,"file":"PopperContent.cjs","sources":["../../src/Popper/PopperContent.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Ref } from 'vue'\nimport type {\n Middleware,\n Placement,\n ReferenceElement,\n} from '@floating-ui/vue'\nimport type { PrimitiveProps } from '@/Primitive'\nimport { createContext, useForwardExpose, useSize } from '@/shared'\nimport type {\n Align,\n Side,\n} from './utils'\n\nexport const PopperContentPropsDefaultValue = {\n side: 'bottom' as Side,\n sideOffset: 0,\n align: 'center' as Align,\n alignOffset: 0,\n arrowPadding: 0,\n avoidCollisions: true,\n collisionBoundary: () => [],\n collisionPadding: 0,\n sticky: 'partial' as 'partial' | 'always',\n hideWhenDetached: false,\n positionStrategy: 'fixed' as 'absolute' | 'fixed',\n updatePositionStrategy: 'optimized' as 'optimized' | 'always',\n prioritizePosition: false,\n}\n\nexport interface PopperContentProps extends PrimitiveProps {\n /**\n * The preferred side of the trigger to render against when open.\n * Will be reversed when collisions occur and avoidCollisions\n * is enabled.\n *\n * @defaultValue \"top\"\n */\n side?: Side\n\n /**\n * The distance in pixels from the trigger.\n *\n * @defaultValue 0\n */\n sideOffset?: number\n\n /**\n * The preferred alignment against the trigger.\n * May change when collisions occur.\n *\n * @defaultValue \"center\"\n */\n align?: Align\n\n /**\n * An offset in pixels from the `start` or `end` alignment options.\n *\n * @defaultValue 0\n */\n alignOffset?: number\n\n /**\n * When `true`, overrides the side and align preferences\n * to prevent collisions with boundary edges.\n *\n * @defaultValue true\n */\n avoidCollisions?: boolean\n\n /**\n * The element used as the collision boundary. By default\n * this is the viewport, though you can provide additional\n * element(s) to be included in this check.\n *\n * @defaultValue []\n */\n collisionBoundary?: Element | null | Array<Element | null>\n\n /**\n * The distance in pixels from the boundary edges where collision\n * detection should occur. Accepts a number (same for all sides),\n * or a partial padding object, for example: { top: 20, left: 20 }.\n *\n * @defaultValue 0\n */\n collisionPadding?: number | Partial<Record<Side, number>>\n\n /**\n * The padding between the arrow and the edges of the content.\n * If your content has border-radius, this will prevent it from\n * overflowing the corners.\n *\n * @defaultValue 0\n */\n arrowPadding?: number\n\n /**\n * The sticky behavior on the align axis. `partial` will keep the\n * content in the boundary as long as the trigger is at least partially\n * in the boundary whilst \"always\" will keep the content in the boundary\n * regardless.\n *\n * @defaultValue \"partial\"\n */\n sticky?: 'partial' | 'always'\n\n /**\n * Whether to hide the content when the trigger becomes fully occluded.\n *\n * @defaultValue false\n */\n hideWhenDetached?: boolean\n\n /**\n * The type of CSS position property to use.\n */\n positionStrategy?: 'absolute' | 'fixed'\n\n /**\n * Strategy to update the position of the floating element on every animation frame.\n *\n * @defaultValue 'optimized'\n */\n updatePositionStrategy?: 'optimized' | 'always'\n\n /**\n * Whether to disable the update position for the content when the layout shifted.\n *\n * @defaultValue false\n */\n disableUpdateOnLayoutShift?: boolean\n\n /**\n * Force content to be position within the viewport.\n *\n * Might overlap the reference element, which may not be desired.\n *\n * @defaultValue false\n */\n prioritizePosition?: boolean\n\n /**\n * The custom element or virtual element that will be set as the reference\n * to position the floating element.\n *\n * If provided, it will replace the default anchor element.\n */\n reference?: ReferenceElement\n}\n\nexport interface PopperContentContext {\n placedSide: Ref<Side>\n onArrowChange: (arrow: HTMLElement | undefined) => void\n arrowX?: Ref<number>\n arrowY?: Ref<number>\n shouldHideArrow: Ref<boolean>\n}\n\nexport const [injectPopperContentContext, providePopperContentContext]\n = createContext<PopperContentContext>('PopperContent')\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watchEffect, watchPostEffect } from 'vue'\nimport { computedEager } from '@vueuse/core'\nimport {\n autoUpdate,\n flip,\n arrow as floatingUIarrow,\n hide,\n limitShift,\n offset,\n shift,\n size,\n useFloating,\n} from '@floating-ui/vue'\nimport { injectPopperRootContext } from './PopperRoot.vue'\nimport {\n getSideAndAlignFromPlacement,\n isNotNull,\n transformOrigin,\n} from './utils'\nimport {\n Primitive,\n} from '@/Primitive'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<PopperContentProps>(), {\n ...PopperContentPropsDefaultValue,\n})\nconst emits = defineEmits<{\n placed: [void]\n}>()\n\nconst rootContext = injectPopperRootContext()\nconst { forwardRef, currentElement: contentElement } = useForwardExpose()\n\nconst floatingRef = ref<HTMLElement>()\n\nconst arrow = ref<HTMLElement>()\nconst { width: arrowWidth, height: arrowHeight } = useSize(arrow)\n\nconst desiredPlacement = computed(\n () =>\n (props.side\n + (props.align !== 'center' ? `-${props.align}` : '')) as Placement,\n)\n\nconst collisionPadding = computed(() => {\n return typeof props.collisionPadding === 'number'\n ? props.collisionPadding\n : { top: 0, right: 0, bottom: 0, left: 0, ...props.collisionPadding }\n})\n\nconst boundary = computed(() => {\n return Array.isArray(props.collisionBoundary)\n ? props.collisionBoundary\n : [props.collisionBoundary]\n})\n\nconst detectOverflowOptions = computed(() => {\n return {\n padding: collisionPadding.value,\n boundary: boundary.value.filter(isNotNull),\n // with `strategy: 'fixed'`, this is the only way to get it to respect boundaries\n altBoundary: boundary.value.length > 0,\n }\n})\n\nconst computedMiddleware = computedEager(() => {\n return [\n offset({\n mainAxis: props.sideOffset + arrowHeight.value,\n alignmentAxis: props.alignOffset,\n }),\n props.prioritizePosition\n && props.avoidCollisions\n && flip({\n ...detectOverflowOptions.value,\n }),\n props.avoidCollisions\n && shift({\n mainAxis: true,\n crossAxis: !!props.prioritizePosition,\n limiter: props.sticky === 'partial' ? limitShift() : undefined,\n ...detectOverflowOptions.value,\n }),\n !props.prioritizePosition\n && props.avoidCollisions\n && flip({\n ...detectOverflowOptions.value,\n }),\n size({\n ...detectOverflowOptions.value,\n apply: ({ elements, rects, availableWidth, availableHeight }) => {\n const { width: anchorWidth, height: anchorHeight } = rects.reference\n const contentStyle = elements.floating.style\n contentStyle.setProperty(\n '--reka-popper-available-width',\n `${availableWidth}px`,\n )\n contentStyle.setProperty(\n '--reka-popper-available-height',\n `${availableHeight}px`,\n )\n contentStyle.setProperty(\n '--reka-popper-anchor-width',\n `${anchorWidth}px`,\n )\n contentStyle.setProperty(\n '--reka-popper-anchor-height',\n `${anchorHeight}px`,\n )\n },\n }),\n arrow.value\n && floatingUIarrow({ element: arrow.value, padding: props.arrowPadding }),\n transformOrigin({\n arrowWidth: arrowWidth.value,\n arrowHeight: arrowHeight.value,\n }),\n props.hideWhenDetached\n && hide({ strategy: 'referenceHidden', ...detectOverflowOptions.value }),\n ] as Middleware[]\n})\n\n// If provided custom reference, it will overwrite the default anchor element\nconst reference = computed(() => props.reference ?? rootContext.anchor.value)\n\nconst { floatingStyles, placement, isPositioned, middlewareData, update } = useFloating(\n reference,\n floatingRef,\n {\n strategy: props.positionStrategy,\n placement: desiredPlacement,\n whileElementsMounted: (...args) => {\n const cleanup = autoUpdate(...args, {\n layoutShift: !props.disableUpdateOnLayoutShift,\n animationFrame: props.updatePositionStrategy === 'always',\n })\n return cleanup\n },\n middleware: computedMiddleware,\n },\n)\n\nconst placedSide = computed(\n () => getSideAndAlignFromPlacement(placement.value)[0],\n)\nconst placedAlign = computed(\n () => getSideAndAlignFromPlacement(placement.value)[1],\n)\n\nwatchPostEffect(() => {\n if (isPositioned.value)\n emits('placed')\n})\n\nconst cannotCenterArrow = computed(\n () => middlewareData.value.arrow?.centerOffset !== 0,\n)\n\nconst contentZIndex = ref('')\nwatchEffect(() => {\n if (contentElement.value)\n contentZIndex.value = window.getComputedStyle(contentElement.value).zIndex\n})\n\nconst arrowX = computed(() => middlewareData.value.arrow?.x ?? 0)\nconst arrowY = computed(() => middlewareData.value.arrow?.y ?? 0)\n\nprovidePopperContentContext({\n placedSide,\n onArrowChange: element => arrow.value = element,\n arrowX,\n arrowY,\n shouldHideArrow: cannotCenterArrow,\n})\n</script>\n\n<template>\n <div\n ref=\"floatingRef\"\n data-reka-popper-content-wrapper=\"\"\n :style=\"{\n ...floatingStyles,\n transform: isPositioned ? floatingStyles.transform : 'translate(0, -200%)', // keep off the page when measuring\n minWidth: 'max-content',\n zIndex: contentZIndex,\n ['--reka-popper-transform-origin' as any]: [\n middlewareData.transformOrigin?.x,\n middlewareData.transformOrigin?.y,\n ].join(' '),\n\n // hide the content if using the hide middleware and should be hidden\n // set visibility to hidden and disable pointer events so the UI behaves\n // as if the PopperContent isn't there at all\n ...(middlewareData.hide?.referenceHidden && {\n visibility: 'hidden',\n pointerEvents: 'none',\n }),\n }\"\n >\n <Primitive\n :ref=\"forwardRef\"\n v-bind=\"$attrs\"\n :as-child=\"props.asChild\"\n :as=\"as\"\n :data-side=\"placedSide\"\n :data-align=\"placedAlign\"\n :style=\"{\n // if the PopperContent hasn't been placed yet (not all measurements done)\n // we prevent animations so that users's animation don't kick in too early referring wrong sides\n animation: !isPositioned ? 'none' : undefined,\n }\"\n >\n <slot />\n </Primitive>\n </div>\n</template>\n"],"names":["createContext","injectPopperRootContext","useForwardExpose","ref","useSize","computed","isNotNull","computedEager","offset","flip","shift","limitShift","size","floatingUIarrow","transformOrigin","hide","useFloating","autoUpdate","getSideAndAlignFromPlacement","watchPostEffect","watchEffect"],"mappings":"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"}