feat: upgrade Popover to latest version

This commit is contained in:
p-sw 2024-06-30 15:03:06 +09:00
parent 8c7f9bd257
commit df29b38c35
2 changed files with 123 additions and 28 deletions

View File

@ -43,7 +43,7 @@ import { Popover, PopoverTrigger, PopoverContent } from "@components/popover"
<PopoverContent> <PopoverContent>
{/* content of popover */} {/* content of popover */}
</PopoverContent> </PopoverContent>
</Popover </Popover>
``` ```
> Note: > Note:
@ -69,10 +69,13 @@ import { Popover, PopoverTrigger, PopoverContent } from "@components/popover"
#### Variants #### Variants
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
|:---------|:-------------------------------------------------------------------------|:-----------------|:--------------------------------| |:------------|:-------------------------------|:-----------|:------------------------------------|
| `anchor` | `` `${"top" \| "middle" \| "bottom"}${"Left" \| "Center" \| "Right"}` `` | `"bottomCenter"` | Position of Popover content | | `direction` | `"row" \| "col"` | `"col"` | Main axis of aligning popover |
| `offset` | `"sm" \| "md" \| "lg"` | `"md"` | Gap between trigger and popover | | `position` | `"start" \| "end"` | `"end"` | Position of popover |
| `anchor` | `"start" \| "middle" \| "end"` | `"middle"` | Reference point of aligning popover |
| `align` | `"start" \| "middle" \| "end"` | `"middle"` | Position of reference point |
| `offset` | `"sm" \| "md" \| "lg"` | `"md"` | Gap between trigger and popover |
#### Special #### Special

View File

@ -1,5 +1,5 @@
import { type AsChild, Slot, type VariantProps, vcn } from "@pswui-lib";
import React, { useContext, useEffect, useRef } from "react"; import React, { useContext, useEffect, useRef } from "react";
import { AsChild, Slot, VariantProps, vcn } from "@pswui-lib";
interface IPopoverContext { interface IPopoverContext {
opened: boolean; opened: boolean;
@ -56,24 +56,23 @@ const popoverColors = {
const [popoverContentVariant, resolvePopoverContentVariantProps] = vcn({ const [popoverContentVariant, resolvePopoverContentVariantProps] = vcn({
base: `absolute transition-all duration-150 border rounded-lg p-0.5 [&>*]:w-full ${popoverColors.background} ${popoverColors.border}`, base: `absolute transition-all duration-150 border rounded-lg p-0.5 [&>*]:w-full ${popoverColors.background} ${popoverColors.border}`,
variants: { variants: {
direction: {
row: "",
col: "",
},
anchor: { anchor: {
topLeft: start: "",
"bottom-[calc(100%+var(--popover-offset))] right-[calc(100%+var(--popover-offset))] origin-bottom-right", middle: "",
topCenter: end: "",
"bottom-[calc(100%+var(--popover-offset))] left-1/2 -translate-x-1/2 origin-bottom-center", },
topRight: align: {
"bottom-[calc(100%+var(--popover-offset))] left-[calc(100%+var(--popover-offset))] origin-bottom-left", start: "",
middleLeft: "top-1/2 translate-y-1/2 right-full origin-right", middle: "",
middleCenter: end: "",
"top-1/2 translate-y-1/2 left-1/2 -translate-x-1/2 origin-center", },
middleRight: position: {
"top-1/2 translate-y-1/2 left-[calc(100%+var(--popover-offset))] origin-left", start: "",
bottomLeft: end: "",
"top-[calc(100%+var(--popover-offset))] right-[calc(100%+var(--popover-offset))] origin-top-right",
bottomCenter:
"top-[calc(100%+var(--popover-offset))] left-1/2 -translate-x-1/2 origin-top-center",
bottomRight:
"top-[calc(100%+var(--popover-offset))] left-[calc(100%+var(--popover-offset))] origin-top-left",
}, },
offset: { offset: {
sm: "[--popover-offset:2px]", sm: "[--popover-offset:2px]",
@ -81,15 +80,104 @@ const [popoverContentVariant, resolvePopoverContentVariantProps] = vcn({
lg: "[--popover-offset:8px]", lg: "[--popover-offset:8px]",
}, },
opened: { opened: {
true: "opacity-1 scale-100", true: "opacity-1 scale-100 pointer-events-auto select-auto touch-auto",
false: "opacity-0 scale-75", false: "opacity-0 scale-75 pointer-events-none select-none touch-none",
}, },
}, },
defaults: { defaults: {
anchor: "bottomCenter", direction: "col",
anchor: "middle",
align: "middle",
position: "end",
opened: false, opened: false,
offset: "md", offset: "md",
}, },
dynamics: [
function originClass({ direction, anchor, position }) {
switch (`${direction} ${position} ${anchor}` as const) {
// left
case "row start start":
return "origin-top-right";
case "row start middle":
return "origin-right";
case "row start end":
return "origin-bottom-right";
// right
case "row end start":
return "origin-top-left";
case "row end middle":
return "origin-left";
case "row end end":
return "origin-bottom-left";
// top
case "col start start":
return "origin-bottom-left";
case "col start middle":
return "origin-bottom";
case "col start end":
return "origin-bottom-right";
// bottom
case "col end start":
return "origin-top-left";
case "col end middle":
return "origin-top";
case "col end end":
return "origin-top-right";
}
},
function basePositionClass({ position, direction }) {
switch (`${direction} ${position}` as const) {
case "col start":
return "bottom-[calc(100%+var(--popover-offset))]";
case "col end":
return "top-[calc(100%+var(--popover-offset))]";
case "row start":
return "right-[calc(100%+var(--popover-offset))]";
case "row end":
return "left-[calc(100%+var(--popover-offset))]";
}
},
function directionPositionClass({ direction, anchor, align }) {
switch (`${direction} ${anchor} ${align}` as const) {
case "col start start":
return "left-0";
case "col start middle":
return "left-1/2";
case "col start end":
return "left-full";
case "col middle start":
return "left-0 -translate-x-1/2";
case "col middle middle":
return "left-1/2 -translate-x-1/2";
case "col middle end":
return "right-0 translate-x-1/2";
case "col end start":
return "right-full";
case "col end middle":
return "right-1/2";
case "col end end":
return "right-0";
case "row start start":
return "top-0";
case "row start middle":
return "top-1/2";
case "row start end":
return "top-full";
case "row middle start":
return "top-0 -translate-y-1/2";
case "row middle middle":
return "top-1/2 -translate-y-1/2";
case "row middle end":
return "bottom-0 translate-y-1/2";
case "row end start":
return "bottom-full";
case "row end middle":
return "bottom-1/2";
case "row end end":
return "bottom-0";
}
},
],
}); });
interface PopoverContentProps interface PopoverContentProps
@ -119,7 +207,7 @@ const PopoverContent = React.forwardRef<HTMLDivElement, PopoverContentProps>(
return () => { return () => {
document.removeEventListener("mousedown", handleOutsideClick); document.removeEventListener("mousedown", handleOutsideClick);
}; };
}, [internalRef, setState]); }, [setState]);
return ( return (
<div <div
@ -130,7 +218,11 @@ const PopoverContent = React.forwardRef<HTMLDivElement, PopoverContentProps>(
})} })}
ref={(el) => { ref={(el) => {
internalRef.current = el; internalRef.current = el;
typeof ref === "function" ? ref(el) : ref && (ref.current = el); if (typeof ref === "function") {
ref(el);
} else if (ref) {
ref.current = el;
}
}} }}
> >
{children} {children}