@avenue-ticketing/ui 0.7.0 → 0.8.0
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/react/avatar.js.map +1 -1
- package/dist/react/badge.js.map +1 -1
- package/dist/react/button.js.map +1 -1
- package/dist/react/calendar.js.map +1 -1
- package/dist/react/card.js.map +1 -1
- package/dist/react/checkbox.js.map +1 -1
- package/dist/react/datetime-picker.js +73 -52
- package/dist/react/datetime-picker.js.map +1 -1
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.js +36 -26
- package/dist/react/dropdown.js.map +1 -1
- package/dist/react/input.js.map +1 -1
- package/dist/react/pagination.js.map +1 -1
- package/dist/react/popover.js +72 -51
- package/dist/react/popover.js.map +1 -1
- package/dist/react/scroll-header.js.map +1 -1
- package/dist/react/scroll-wheel.js.map +1 -1
- package/dist/react/select.js +32 -24
- package/dist/react/select.js.map +1 -1
- package/dist/react/sheet.js.map +1 -1
- package/dist/react/switch.js.map +1 -1
- package/dist/react/table-pagination.js +32 -24
- package/dist/react/table-pagination.js.map +1 -1
- package/dist/react/table-view/column-menu.js +32 -24
- package/dist/react/table-view/column-menu.js.map +1 -1
- package/dist/react/table-view/index.js +32 -24
- package/dist/react/table-view/index.js.map +1 -1
- package/dist/react/table.js.map +1 -1
- package/dist/react/tabs.js.map +1 -1
- package/dist/react/textarea.js.map +1 -1
- package/dist/react/time-picker.js.map +1 -1
- package/dist/react/tooltip.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/button.tsx","../../src/react/pagination.tsx"],"names":["React","jsx","Pagination"],"mappings":"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","file":"pagination.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst sizeClass = {\n xs: \"h-8 min-h-8 gap-2 px-4 text-sm has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"h-10 min-h-10 gap-2 px-5 text-sm has-[>svg]:px-4 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"h-11 min-h-11 gap-2 px-6 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\n/** Square hit targets for `iconOnly` — same keys as `sizeClass` (`default` | `lg`). */\nconst iconOnlySizeClass = {\n xs: \"size-8 min-h-8 min-w-8 gap-0 p-0 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"size-10 min-h-10 min-w-10 gap-0 p-0 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"size-11 min-h-11 min-w-11 gap-0 p-0 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\nconst roundedClass = {\n full: \"rounded-full\",\n lg: \"rounded-lg\",\n md: \"rounded-md\",\n} as const;\n\nconst variantClass = {\n primary:\n \"bg-primary text-background border border-transparent hover:bg-primary/90 active:bg-primary/85\",\n secondary:\n \"bg-background text-primary border border-primary/10 hover:bg-primary/5\",\n destructive:\n \"bg-background text-red-500 border border-red-500/25 hover:bg-red-500/5\",\n success:\n \"bg-background text-green-500 border border-green-500/25 hover:bg-green-500/5\",\n} as const;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> & {\n /**\n * Visual style: neutral (`secondary`, `primary`), or outline (`destructive`,\n * `success`) using Tailwind `red-500` / `green-500` text and matching borders on\n * `bg-background` (no solid fill).\n */\n variant?: keyof typeof variantClass;\n /**\n * Corner radius. Labeled buttons default to `full` (pill). `iconOnly` buttons\n * default to `md` (square corners) unless you pass `rounded` explicitly.\n */\n rounded?: keyof typeof roundedClass;\n /** Height and horizontal padding: `default` or `lg` only. */\n size?: keyof typeof sizeClass;\n /**\n * Square icon-only control; same `size` presets (`default` | `lg`). Pair with\n * `aria-label` (or `title`) when there is no visible text.\n */\n iconOnly?: boolean;\n};\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n type = \"button\",\n variant = \"secondary\",\n rounded: roundedProp,\n size = \"default\",\n iconOnly = false,\n disabled,\n ...props\n },\n ref,\n ) => {\n const rounded = roundedProp ?? (iconOnly ? \"md\" : \"full\");\n\n return (\n <button\n type={type}\n disabled={disabled}\n data-slot=\"button\"\n data-icon-only={iconOnly ? \"\" : undefined}\n className={cn(\n \"inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap outline-none scale-100 transition-[color,background-color,box-shadow,transform] duration-150 ease-out active:scale-[0.98] active:duration-100 active:ease-linear [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\",\n \"focus-visible:border-ring font-medium lg:tracking-wide focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n iconOnly ? iconOnlySizeClass[size] : sizeClass[size],\n roundedClass[rounded],\n variantClass[variant],\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button };\n","\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button, type ButtonProps } from \"./button\";\n\nexport type PaginationMeta = {\n currentPage: number;\n totalItems: number;\n itemsPerPage: number;\n /** omit to derive `ceil(totalItems / itemsPerPage)` (minimum 1) */\n totalPages?: number;\n};\n\nexport type PaginationProps = {\n meta: PaginationMeta;\n onPageChange?: (page: number) => void;\n className?: string;\n /** max page numbers in the sliding window (excluding first/last when ellipses show; default 3) */\n maxVisibleButtons?: number;\n disabled?: boolean;\n /**\n * density preset → resolved `Button` size for every control (`xs` → `default`;\n * `default` / `lg` → `lg`) so chevrons and page cells share one hit grid.\n */\n size?: ButtonProps[\"size\"];\n /** same as `Button` `rounded`; pagination defaults to `full` */\n rounded?: NonNullable<ButtonProps[\"rounded\"]>;\n};\n\nconst PaginationInner = React.forwardRef<HTMLDivElement, PaginationProps>(\n function Pagination(\n {\n meta,\n onPageChange,\n className,\n maxVisibleButtons = 3,\n disabled = false,\n size = \"default\",\n rounded = \"full\",\n },\n ref,\n ) {\n const handlePageChange = React.useCallback(\n (page: number) => {\n onPageChange?.(page);\n },\n [onPageChange],\n );\n\n const totalPages = React.useMemo(() => {\n const totalItems = Math.max(0, Number(meta.totalItems) || 0);\n const itemsPerPage = Math.max(1, Number(meta.itemsPerPage) || 16);\n if (meta.totalPages != null && Number.isFinite(meta.totalPages)) {\n return Math.max(1, Math.floor(Number(meta.totalPages)));\n }\n return Math.max(1, Math.ceil(totalItems / itemsPerPage));\n }, [meta.totalItems, meta.itemsPerPage, meta.totalPages]);\n\n const currentPage = React.useMemo(\n () => Math.max(1, Number(meta.currentPage) || 1),\n [meta.currentPage],\n );\n\n const { endPage, adjustedStart } = React.useMemo(() => {\n const sp = Math.max(1, currentPage - Math.floor(maxVisibleButtons / 2));\n const ep = Math.min(totalPages, sp + maxVisibleButtons - 1);\n const adj =\n ep - sp + 1 < maxVisibleButtons ? Math.max(1, ep - maxVisibleButtons + 1) : sp;\n return { endPage: ep, adjustedStart: adj };\n }, [currentPage, totalPages, maxVisibleButtons]);\n\n const middlePageNumbers = React.useMemo(\n () =>\n Array.from({ length: endPage - adjustedStart + 1 }, (_, i) => adjustedStart + i),\n [endPage, adjustedStart],\n );\n\n const navButtonSize = React.useMemo(\n (): NonNullable<ButtonProps[\"size\"]> => (size === \"xs\" ? \"default\" : \"lg\"),\n [size],\n );\n\n const ellipsisClassName = React.useMemo(\n () =>\n cn(\n \"inline-flex shrink-0 items-center justify-center\",\n navButtonSize === \"lg\"\n ? \"size-11 min-h-11 min-w-11\"\n : \"size-10 min-h-10 min-w-10\",\n rounded === \"full\"\n ? \"rounded-full\"\n : rounded === \"lg\"\n ? \"rounded-lg\"\n : \"rounded-md\",\n ),\n [navButtonSize, rounded],\n );\n\n const gapIconClassName = React.useMemo(\n () =>\n cn(\n \"mx-auto shrink-0 text-primary/45\",\n navButtonSize === \"lg\" ? \"size-[18px]\" : \"size-4\",\n ),\n [navButtonSize],\n );\n\n if (totalPages <= 1) return null;\n\n return (\n <div ref={ref} className={cn(\"flex w-full justify-center\", className)}>\n <nav\n role=\"navigation\"\n aria-label=\"Pagination\"\n className=\"text-primary flex items-center justify-center gap-0.5 text-base font-medium tabular-nums tracking-tight\"\n >\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage <= 1}\n onClick={() => handlePageChange(currentPage - 1)}\n aria-label=\"Previous page\"\n >\n <ChevronLeft aria-hidden className=\"size-5 shrink-0 mr-0.5\" />\n </Button>\n <div className=\"flex items-center gap-0.5\">\n {adjustedStart > 1 && (\n <>\n {currentPage === 1 ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{1}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(1)}\n aria-label=\"Go to page 1\"\n >\n <span className=\"tabular-nums\">1</span>\n </Button>\n )}\n {adjustedStart > 2 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n </>\n )}\n {middlePageNumbers.map((page) =>\n currentPage === page ? (\n <Button\n key={page}\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ) : (\n <Button\n key={page}\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(page)}\n aria-label={`Go to page ${page}`}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ),\n )}\n {endPage < totalPages && (\n <>\n {endPage < totalPages - 1 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n {currentPage === totalPages ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(totalPages)}\n aria-label={`Go to page ${totalPages}`}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n )}\n </>\n )}\n </div>\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage >= totalPages}\n onClick={() => handlePageChange(currentPage + 1)}\n aria-label=\"Next page\"\n >\n <ChevronRight aria-hidden className=\"size-5 shrink-0 ml-0.5\" />\n </Button>\n </nav>\n </div>\n );\n },\n);\n\nPaginationInner.displayName = \"Pagination\";\n\nexport const Pagination = React.memo(PaginationInner);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/button.tsx","../../src/react/pagination.tsx"],"names":["React","jsx","Pagination"],"mappings":"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","file":"pagination.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\nconst sizeClass = {\n xs: \"h-8 min-h-8 gap-2 px-4 text-sm has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"h-10 min-h-10 gap-2 px-5 text-sm has-[>svg]:px-4 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"h-11 min-h-11 gap-2 px-6 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\n/** Square hit targets for `iconOnly` — same keys as `sizeClass` (`default` | `lg`). */\nconst iconOnlySizeClass = {\n xs: \"size-8 min-h-8 min-w-8 gap-0 p-0 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"size-10 min-h-10 min-w-10 gap-0 p-0 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"size-11 min-h-11 min-w-11 gap-0 p-0 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\nconst roundedClass = {\n full: \"rounded-full\",\n lg: \"rounded-lg\",\n md: \"rounded-md\",\n} as const;\n\nconst variantClass = {\n primary:\n \"bg-primary text-background border border-transparent hover:bg-primary/90 active:bg-primary/85\",\n secondary:\n \"bg-background text-primary border border-primary/10 hover:bg-primary/5\",\n destructive:\n \"bg-background text-red-500 border border-red-500/25 hover:bg-red-500/5\",\n success:\n \"bg-background text-green-500 border border-green-500/25 hover:bg-green-500/5\",\n} as const;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> & {\n /**\n * Visual style: neutral (`secondary`, `primary`), or outline (`destructive`,\n * `success`) using Tailwind `red-500` / `green-500` text and matching borders on\n * `bg-background` (no solid fill).\n */\n variant?: keyof typeof variantClass;\n /**\n * Corner radius. Labeled buttons default to `full` (pill). `iconOnly` buttons\n * default to `md` (square corners) unless you pass `rounded` explicitly.\n */\n rounded?: keyof typeof roundedClass;\n /** Height and horizontal padding: `default` or `lg` only. */\n size?: keyof typeof sizeClass;\n /**\n * Square icon-only control; same `size` presets (`default` | `lg`). Pair with\n * `aria-label` (or `title`) when there is no visible text.\n */\n iconOnly?: boolean;\n};\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n type = \"button\",\n variant = \"secondary\",\n rounded: roundedProp,\n size = \"default\",\n iconOnly = false,\n disabled,\n ...props\n },\n ref,\n ) => {\n const rounded = roundedProp ?? (iconOnly ? \"md\" : \"full\");\n\n return (\n <button\n type={type}\n disabled={disabled}\n data-slot=\"button\"\n data-icon-only={iconOnly ? \"\" : undefined}\n className={cn(\n \"inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap outline-none scale-100 transition-[color,background-color,box-shadow,transform] duration-150 ease-out active:scale-[0.98] active:duration-100 active:ease-linear [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\",\n \"focus-visible:border-ring font-medium lg:tracking-wide focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n iconOnly ? iconOnlySizeClass[size] : sizeClass[size],\n roundedClass[rounded],\n variantClass[variant],\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button };\n","\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { Button, type ButtonProps } from \"./button\";\n\nexport type PaginationMeta = {\n currentPage: number;\n totalItems: number;\n itemsPerPage: number;\n /** omit to derive `ceil(totalItems / itemsPerPage)` (minimum 1) */\n totalPages?: number;\n};\n\nexport type PaginationProps = {\n meta: PaginationMeta;\n onPageChange?: (page: number) => void;\n className?: string;\n /** max page numbers in the sliding window (excluding first/last when ellipses show; default 3) */\n maxVisibleButtons?: number;\n disabled?: boolean;\n /**\n * density preset → resolved `Button` size for every control (`xs` → `default`;\n * `default` / `lg` → `lg`) so chevrons and page cells share one hit grid.\n */\n size?: ButtonProps[\"size\"];\n /** same as `Button` `rounded`; pagination defaults to `full` */\n rounded?: NonNullable<ButtonProps[\"rounded\"]>;\n};\n\nconst PaginationInner = React.forwardRef<HTMLDivElement, PaginationProps>(\n function Pagination(\n {\n meta,\n onPageChange,\n className,\n maxVisibleButtons = 3,\n disabled = false,\n size = \"default\",\n rounded = \"full\",\n },\n ref,\n ) {\n const handlePageChange = React.useCallback(\n (page: number) => {\n onPageChange?.(page);\n },\n [onPageChange],\n );\n\n const totalPages = React.useMemo(() => {\n const totalItems = Math.max(0, Number(meta.totalItems) || 0);\n const itemsPerPage = Math.max(1, Number(meta.itemsPerPage) || 16);\n if (meta.totalPages != null && Number.isFinite(meta.totalPages)) {\n return Math.max(1, Math.floor(Number(meta.totalPages)));\n }\n return Math.max(1, Math.ceil(totalItems / itemsPerPage));\n }, [meta.totalItems, meta.itemsPerPage, meta.totalPages]);\n\n const currentPage = React.useMemo(\n () => Math.max(1, Number(meta.currentPage) || 1),\n [meta.currentPage],\n );\n\n const { endPage, adjustedStart } = React.useMemo(() => {\n const sp = Math.max(1, currentPage - Math.floor(maxVisibleButtons / 2));\n const ep = Math.min(totalPages, sp + maxVisibleButtons - 1);\n const adj =\n ep - sp + 1 < maxVisibleButtons ? Math.max(1, ep - maxVisibleButtons + 1) : sp;\n return { endPage: ep, adjustedStart: adj };\n }, [currentPage, totalPages, maxVisibleButtons]);\n\n const middlePageNumbers = React.useMemo(\n () =>\n Array.from({ length: endPage - adjustedStart + 1 }, (_, i) => adjustedStart + i),\n [endPage, adjustedStart],\n );\n\n const navButtonSize = React.useMemo(\n (): NonNullable<ButtonProps[\"size\"]> => (size === \"xs\" ? \"default\" : \"lg\"),\n [size],\n );\n\n const ellipsisClassName = React.useMemo(\n () =>\n cn(\n \"inline-flex shrink-0 items-center justify-center\",\n navButtonSize === \"lg\"\n ? \"size-11 min-h-11 min-w-11\"\n : \"size-10 min-h-10 min-w-10\",\n rounded === \"full\"\n ? \"rounded-full\"\n : rounded === \"lg\"\n ? \"rounded-lg\"\n : \"rounded-md\",\n ),\n [navButtonSize, rounded],\n );\n\n const gapIconClassName = React.useMemo(\n () =>\n cn(\n \"mx-auto shrink-0 text-primary/45\",\n navButtonSize === \"lg\" ? \"size-[18px]\" : \"size-4\",\n ),\n [navButtonSize],\n );\n\n if (totalPages <= 1) return null;\n\n return (\n <div ref={ref} className={cn(\"flex w-full justify-center\", className)}>\n <nav\n role=\"navigation\"\n aria-label=\"Pagination\"\n className=\"text-primary flex items-center justify-center gap-0.5 text-base font-medium tabular-nums tracking-tight\"\n >\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage <= 1}\n onClick={() => handlePageChange(currentPage - 1)}\n aria-label=\"Previous page\"\n >\n <ChevronLeft aria-hidden className=\"size-5 shrink-0 mr-0.5\" />\n </Button>\n <div className=\"flex items-center gap-0.5\">\n {adjustedStart > 1 && (\n <>\n {currentPage === 1 ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{1}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(1)}\n aria-label=\"Go to page 1\"\n >\n <span className=\"tabular-nums\">1</span>\n </Button>\n )}\n {adjustedStart > 2 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n </>\n )}\n {middlePageNumbers.map((page) =>\n currentPage === page ? (\n <Button\n key={page}\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ) : (\n <Button\n key={page}\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(page)}\n aria-label={`Go to page ${page}`}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ),\n )}\n {endPage < totalPages && (\n <>\n {endPage < totalPages - 1 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n {currentPage === totalPages ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(totalPages)}\n aria-label={`Go to page ${totalPages}`}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n )}\n </>\n )}\n </div>\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage >= totalPages}\n onClick={() => handlePageChange(currentPage + 1)}\n aria-label=\"Next page\"\n >\n <ChevronRight aria-hidden className=\"size-5 shrink-0 ml-0.5\" />\n </Button>\n </nav>\n </div>\n );\n },\n);\n\nPaginationInner.displayName = \"Pagination\";\n\nexport const Pagination = React.memo(PaginationInner);\n"]}
|
package/dist/react/popover.js
CHANGED
|
@@ -13,6 +13,21 @@ var POPOVER_MOBILE_SHEET_MOTION_MS = 175;
|
|
|
13
13
|
var POPOVER_MOBILE_SHEET_ENTRY_EASING = "cubic-bezier(0.85, 0, 0.15, 1)";
|
|
14
14
|
var POPOVER_MOBILE_SHEET_EXIT_EASING = "cubic-bezier(0.85, 0, 1, 0.15)";
|
|
15
15
|
var POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;
|
|
16
|
+
var POPOVER_FLIP_MIN_SPACE_PX = 100;
|
|
17
|
+
function preventPopoverWheelChain(panel, e) {
|
|
18
|
+
let el = e.target;
|
|
19
|
+
while (el && panel.contains(el)) {
|
|
20
|
+
const oy = getComputedStyle(el).overflowY;
|
|
21
|
+
if ((oy === "auto" || oy === "scroll") && el.scrollHeight > el.clientHeight) {
|
|
22
|
+
const atTop = el.scrollTop <= 0;
|
|
23
|
+
const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight;
|
|
24
|
+
if (e.deltaY < 0 && !atTop || e.deltaY > 0 && !atBottom) return;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
el = el.parentElement;
|
|
28
|
+
}
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
}
|
|
16
31
|
function usePopoverIsMobile(breakpoint = 1025) {
|
|
17
32
|
const [isMobile, setIsMobile] = useState(false);
|
|
18
33
|
useEffect(() => {
|
|
@@ -220,74 +235,70 @@ function computePosition(trigger, popover, side, align, offset, viewportPadding)
|
|
|
220
235
|
const triggerRect = trigger.getBoundingClientRect();
|
|
221
236
|
const pw = popover.offsetWidth;
|
|
222
237
|
const ph = popover.offsetHeight;
|
|
238
|
+
const contentHeight = popover.scrollHeight;
|
|
223
239
|
const vw = window.innerWidth;
|
|
224
240
|
const vh = window.innerHeight;
|
|
241
|
+
const pad = viewportPadding;
|
|
225
242
|
let top = 0;
|
|
226
243
|
let left = 0;
|
|
227
244
|
let effectiveSide = side;
|
|
228
|
-
|
|
245
|
+
let maxHeight;
|
|
246
|
+
const placeVertical = (s, height) => {
|
|
247
|
+
if (s === "bottom") top = triggerRect.bottom + offset;
|
|
248
|
+
else top = triggerRect.top - height - offset;
|
|
249
|
+
if (align === "start") left = triggerRect.left;
|
|
250
|
+
else if (align === "end") left = triggerRect.right - pw;
|
|
251
|
+
else left = triggerRect.left + triggerRect.width / 2 - pw / 2;
|
|
252
|
+
};
|
|
253
|
+
const place = (s, height = contentHeight) => {
|
|
229
254
|
switch (s) {
|
|
230
255
|
case "bottom":
|
|
231
|
-
top = triggerRect.bottom + offset;
|
|
232
|
-
break;
|
|
233
256
|
case "top":
|
|
234
|
-
|
|
257
|
+
placeVertical(s, height);
|
|
235
258
|
break;
|
|
236
259
|
case "right":
|
|
237
260
|
left = triggerRect.right + offset;
|
|
238
261
|
top = align === "start" ? triggerRect.top : align === "end" ? triggerRect.bottom - ph : triggerRect.top + triggerRect.height / 2 - ph / 2;
|
|
239
|
-
|
|
262
|
+
break;
|
|
240
263
|
case "left":
|
|
241
264
|
left = triggerRect.left - pw - offset;
|
|
242
265
|
top = align === "start" ? triggerRect.top : align === "end" ? triggerRect.bottom - ph : triggerRect.top + triggerRect.height / 2 - ph / 2;
|
|
243
|
-
|
|
266
|
+
break;
|
|
244
267
|
}
|
|
245
|
-
if (align === "start") left = triggerRect.left;
|
|
246
|
-
else if (align === "end") left = triggerRect.right - pw;
|
|
247
|
-
else left = triggerRect.left + triggerRect.width / 2 - pw / 2;
|
|
248
268
|
};
|
|
249
269
|
place(side);
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const flipped = "bottom";
|
|
260
|
-
const newTop = triggerRect.bottom + offset;
|
|
261
|
-
if (newTop + ph <= vh - viewportPadding) {
|
|
262
|
-
effectiveSide = flipped;
|
|
263
|
-
top = newTop;
|
|
264
|
-
}
|
|
265
|
-
} else if (side === "right" && left + pw > vw - viewportPadding) {
|
|
266
|
-
const flipped = "left";
|
|
267
|
-
const newLeft = triggerRect.left - pw - offset;
|
|
268
|
-
if (newLeft >= viewportPadding) {
|
|
269
|
-
effectiveSide = flipped;
|
|
270
|
-
left = newLeft;
|
|
271
|
-
}
|
|
272
|
-
} else if (side === "left" && left < viewportPadding) {
|
|
273
|
-
const flipped = "right";
|
|
274
|
-
const newLeft = triggerRect.right + offset;
|
|
275
|
-
if (newLeft + pw <= vw - viewportPadding) {
|
|
276
|
-
effectiveSide = flipped;
|
|
277
|
-
left = newLeft;
|
|
278
|
-
}
|
|
270
|
+
const spaceBelow = Math.max(0, vh - pad - triggerRect.bottom - offset);
|
|
271
|
+
const spaceAbove = Math.max(0, triggerRect.top - offset - pad);
|
|
272
|
+
if (side === "bottom" || side === "top") {
|
|
273
|
+
const primarySpace = side === "bottom" ? spaceBelow : spaceAbove;
|
|
274
|
+
const alternateSpace = side === "bottom" ? spaceAbove : spaceBelow;
|
|
275
|
+
const alternateSide = side === "bottom" ? "top" : "bottom";
|
|
276
|
+
if (contentHeight > primarySpace) {
|
|
277
|
+
maxHeight = Math.min(contentHeight, primarySpace);
|
|
278
|
+
place(side, maxHeight);
|
|
279
279
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
280
|
+
if (contentHeight > primarySpace && primarySpace < POPOVER_FLIP_MIN_SPACE_PX && alternateSpace > primarySpace) {
|
|
281
|
+
effectiveSide = alternateSide;
|
|
282
|
+
maxHeight = Math.min(contentHeight, alternateSpace);
|
|
283
|
+
place(alternateSide, maxHeight);
|
|
284
|
+
}
|
|
285
|
+
} else if (side === "right" && left + pw > vw - pad) {
|
|
286
|
+
const flippedLeft = triggerRect.left - pw - offset;
|
|
287
|
+
if (flippedLeft >= pad) {
|
|
288
|
+
effectiveSide = "left";
|
|
289
|
+
left = flippedLeft;
|
|
290
|
+
}
|
|
291
|
+
} else if (side === "left" && left < pad) {
|
|
292
|
+
const flippedLeft = triggerRect.right + offset;
|
|
293
|
+
if (flippedLeft + pw <= vw - pad) {
|
|
294
|
+
effectiveSide = "right";
|
|
295
|
+
left = flippedLeft;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const layoutHeight = maxHeight ?? contentHeight;
|
|
299
|
+
left = Math.max(pad, Math.min(left, vw - pw - pad));
|
|
300
|
+
top = Math.max(pad, Math.min(top, vh - layoutHeight - pad));
|
|
301
|
+
return { top, left, side: effectiveSide, maxHeight };
|
|
291
302
|
}
|
|
292
303
|
var ARROW_SIZE = 6;
|
|
293
304
|
var PopoverContent = ({
|
|
@@ -375,6 +386,14 @@ var PopoverContent = ({
|
|
|
375
386
|
window.removeEventListener("scroll", update, true);
|
|
376
387
|
};
|
|
377
388
|
}, [shouldRender, open, sheetMode, side, align, offset, viewportPadding]);
|
|
389
|
+
useEffect(() => {
|
|
390
|
+
if (!shouldRender || !open || sheetMode || position.maxHeight == null) return;
|
|
391
|
+
const panel = popoverRef.current;
|
|
392
|
+
if (!panel) return;
|
|
393
|
+
const onWheel = (e) => preventPopoverWheelChain(panel, e);
|
|
394
|
+
panel.addEventListener("wheel", onWheel, { passive: false });
|
|
395
|
+
return () => panel.removeEventListener("wheel", onWheel);
|
|
396
|
+
}, [shouldRender, open, sheetMode, position.maxHeight]);
|
|
378
397
|
useEffect(() => {
|
|
379
398
|
if (open && sheetMode) {
|
|
380
399
|
document.body.style.overflow = "hidden";
|
|
@@ -500,8 +519,9 @@ var PopoverContent = ({
|
|
|
500
519
|
...props,
|
|
501
520
|
ref: popoverRef,
|
|
502
521
|
className: cn(
|
|
503
|
-
"bg-background border-primary/10 fixed z-50
|
|
504
|
-
className
|
|
522
|
+
"bg-background border-primary/10 fixed z-50 rounded-xl border shadow-xl outline-none",
|
|
523
|
+
className,
|
|
524
|
+
position.maxHeight != null ? "overflow-y-auto overscroll-contain" : "overflow-hidden"
|
|
505
525
|
),
|
|
506
526
|
"data-slot": "popover-content",
|
|
507
527
|
style: {
|
|
@@ -509,6 +529,7 @@ var PopoverContent = ({
|
|
|
509
529
|
top: position.top,
|
|
510
530
|
left: position.left,
|
|
511
531
|
width: resolvedWidth,
|
|
532
|
+
maxHeight: position.maxHeight,
|
|
512
533
|
transformOrigin: transformOrigin[position.side],
|
|
513
534
|
transform: isAnimating ? "none" : hiddenTransform[position.side],
|
|
514
535
|
opacity: isAnimating ? 1 : 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/popover.tsx"],"names":[],"mappings":"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","file":"popover.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\n/** Mobile popover as bottom sheet — same cutoff and motion as {@link DropdownContent}. */\nconst POPOVER_MOBILE_SHEET_MAX_PX = 1024;\nconst POPOVER_MOBILE_SHEET_MOTION_MS = 175;\nconst POPOVER_MOBILE_SHEET_ENTRY_EASING = \"cubic-bezier(0.85, 0, 0.15, 1)\";\nconst POPOVER_MOBILE_SHEET_EXIT_EASING = \"cubic-bezier(0.85, 0, 1, 0.15)\";\nconst POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;\n\nfunction usePopoverIsMobile(breakpoint = 1025): boolean {\n const [isMobile, setIsMobile] = useState(false);\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mq.matches);\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [breakpoint]);\n return isMobile;\n}\n\n//////////////////////////////////////////////// Context\n\ntype PopoverContextValue = {\n open: boolean;\n setOpen: (open: boolean) => void;\n triggerRef: React.RefObject<HTMLElement | null>;\n};\n\nconst PopoverContext = React.createContext<PopoverContextValue | undefined>(\n undefined,\n);\n\nfunction usePopover() {\n const context = React.useContext(PopoverContext);\n if (!context) {\n throw new Error(\"Popover components must be used within a <Popover />\");\n }\n return context;\n}\n\n//////////////////////////////////////////////// Main\n\nexport const Popover: React.FC<{\n children: React.ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}> = ({ children, open: controlledOpen, onOpenChange }) => {\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const triggerRef = useRef<HTMLElement | null>(null);\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setInternalOpen(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n return (\n <PopoverContext.Provider value={{ open, setOpen, triggerRef }}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\n//////////////////////////////////////////////// Trigger\n\nexport const PopoverTrigger: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { open, setOpen, triggerRef } = usePopover();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n setOpen(!open);\n };\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n ref?: React.Ref<unknown>;\n }>;\n return React.cloneElement(child, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: (el: HTMLElement) => {\n triggerRef.current = el;\n },\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick(e);\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button\n type=\"button\"\n ref={(el) => {\n triggerRef.current = el;\n }}\n onClick={handleClick}\n >\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Close\n\nexport const PopoverClose: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { setOpen } = usePopover();\n const handleClick = () => setOpen(false);\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n }>;\n return React.cloneElement(child, {\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick();\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Mobile sheet (popover-specific; mirrors dropdown behavior)\n\n/**\n * Narrow-viewport (≤1024px) bottom-sheet options for {@link PopoverContent}.\n * `className` merges onto the sheet panel root (after base sheet styles).\n */\nexport interface PopoverMobileSheetOptions {\n /** When `true`, use a bottom sheet on narrow viewports. Default `false`. */\n sheet?: boolean;\n title?: string;\n className?: string;\n contentClassName?: string;\n}\n\nfunction resolvePopoverMobileSheet(\n mobileOptions: PopoverMobileSheetOptions | undefined,\n) {\n return {\n sheet: mobileOptions?.sheet ?? false,\n title: mobileOptions?.title,\n sheetExtraClassName: mobileOptions?.className,\n contentClassName: mobileOptions?.contentClassName,\n };\n}\n\nexport interface PopoverMobileCloseProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\n/**\n * Dismiss control for the mobile bottom-sheet popover. Styling matches\n * {@link DialogCloseButton} (circular hit target, X icon).\n */\nexport const PopoverMobileClose = React.forwardRef<\n HTMLButtonElement,\n PopoverMobileCloseProps\n>(({ className, type = \"button\", ...props }, ref) => {\n return (\n <button\n ref={ref}\n type={type}\n className={cn(\n \"z-100 flex size-12 shrink-0 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]\",\n className,\n )}\n {...props}\n >\n <X className=\"size-5.5\" />\n <span className=\"sr-only\">Close</span>\n </button>\n );\n});\nPopoverMobileClose.displayName = \"PopoverMobileClose\";\n\ninterface PopoverMobileBottomSheetPortalProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"ref\"\n> {\n children: React.ReactNode;\n open: boolean;\n isAnimating: boolean;\n slideEntrance: boolean;\n slideOffsetPx: number;\n sheetTitle?: string;\n sheetExtraClassName?: string;\n contentClassName?: string;\n onRequestClose: () => void;\n menuRef: React.RefObject<HTMLDivElement | null>;\n /** When `false`, scrim taps do not close (matches `closeOnClickOutside={false}`). */\n dismissOnBackdropPress?: boolean;\n}\n\nfunction PopoverMobileBottomSheetPortal({\n open,\n isAnimating,\n slideEntrance,\n slideOffsetPx,\n sheetTitle,\n sheetExtraClassName,\n contentClassName,\n onRequestClose,\n menuRef,\n dismissOnBackdropPress = true,\n children,\n className,\n style,\n ...panelProps\n}: PopoverMobileBottomSheetPortalProps) {\n const sheetMotion = open\n ? POPOVER_MOBILE_SHEET_ENTRY_EASING\n : POPOVER_MOBILE_SHEET_EXIT_EASING;\n const sheetHiddenTransform = slideEntrance\n ? `translateY(${slideOffsetPx}px)`\n : \"translateY(100%)\";\n\n return createPortal(\n <div className=\"fixed inset-0 z-50 flex items-end justify-center p-0\">\n <div\n className={cn(\n \"fixed inset-0 bg-black/40 dark:bg-black/60\",\n isAnimating ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{\n transitionProperty: \"opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n }}\n onClick={dismissOnBackdropPress ? onRequestClose : undefined}\n aria-hidden\n />\n <div\n {...panelProps}\n ref={menuRef}\n className={cn(\n // Panel chrome + padding rhythm matches `DropdownMobileBottomSheetPortal`.\n \"bg-background border-primary/10 relative z-10 flex w-full max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] flex-col overflow-hidden shadow-2xl outline-none\",\n \"rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t\",\n sheetExtraClassName,\n className,\n )}\n style={{\n transform: isAnimating ? \"translateY(0)\" : sheetHiddenTransform,\n opacity: isAnimating ? 1 : 0,\n transitionProperty: \"transform, opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n ...style,\n }}\n >\n <div\n className={cn(\n \"flex w-full shrink-0 items-center py-2 pl-4 pr-2\",\n sheetTitle ? \"justify-between gap-3\" : \"justify-end\",\n )}\n >\n {sheetTitle ? (\n <p className=\"text-foreground min-w-0 flex-1 truncate text-base font-semibold\">\n {sheetTitle}\n </p>\n ) : null}\n <PopoverMobileClose\n onClick={(e) => {\n e.stopPropagation();\n onRequestClose();\n }}\n />\n </div>\n <div\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto px-4 pt-3\",\n contentClassName,\n \"pb-[calc(5rem+env(safe-area-inset-bottom,0px))]\",\n )}\n >\n {children}\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\n//////////////////////////////////////////////// Content\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype Align = \"start\" | \"center\" | \"end\";\n\ninterface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Which side of the trigger to render on */\n side?: Side;\n /** Alignment along the cross-axis */\n align?: Align;\n /** Gap between trigger and popover in px */\n offset?: number;\n /** Show a small arrow pointing to the trigger */\n showArrow?: boolean;\n /** Close when clicking outside */\n closeOnClickOutside?: boolean;\n /** Close when Escape key is pressed */\n closeOnEscape?: boolean;\n /** Animation duration in ms */\n duration?: number;\n /** Minimum distance from the viewport edge in px */\n viewportPadding?: number;\n /** Portal container – defaults to document.body */\n container?: HTMLElement | null;\n /** Width of the popover. 'trigger' matches the trigger width. */\n width?: \"auto\" | \"trigger\" | number;\n /**\n * Narrow-viewport (≤1024px) bottom sheet — same options as dropdown\n * `mobileOptions`, except `sheet` defaults to `false`.\n */\n mobileOptions?: PopoverMobileSheetOptions;\n /**\n * Mobile bottom sheet only. When `true` (default), panel motion matches Dialog\n * `slideEntrance`; when `false`, uses full `translateY(100%)`.\n */\n slideEntrance?: boolean;\n /** Mobile sheet only; defaults to 120px (same as dropdown / dialog full sheet). */\n slideEntranceOffsetPx?: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n side: Side; // actual side after flip\n}\n\nfunction computePosition(\n trigger: HTMLElement,\n popover: HTMLElement,\n side: Side,\n align: Align,\n offset: number,\n viewportPadding: number,\n): Position {\n const triggerRect = trigger.getBoundingClientRect();\n /** Layout box — not affected by exit/enter `transform: scale()`, unlike `getBoundingClientRect()`. */\n const pw = popover.offsetWidth;\n const ph = popover.offsetHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n let top = 0;\n let left = 0;\n let effectiveSide: Side = side;\n\n /** Viewport-space coords — pairs with `position: fixed` on the portal root. */\n const place = (s: Side) => {\n switch (s) {\n case \"bottom\":\n top = triggerRect.bottom + offset;\n break;\n case \"top\":\n top = triggerRect.top - ph - offset;\n break;\n case \"right\":\n left = triggerRect.right + offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n return;\n case \"left\":\n left = triggerRect.left - pw - offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n return;\n }\n // horizontal alignment for top/bottom\n if (align === \"start\") left = triggerRect.left;\n else if (align === \"end\") left = triggerRect.right - pw;\n else left = triggerRect.left + triggerRect.width / 2 - pw / 2;\n };\n\n place(side);\n\n // ----- flip if overflowing viewport -----\n const tryFlip = () => {\n if (side === \"bottom\" && top + ph > vh - viewportPadding) {\n const flipped: Side = \"top\";\n const newTop = triggerRect.top - ph - offset;\n if (newTop >= viewportPadding) {\n effectiveSide = flipped;\n top = newTop;\n }\n } else if (side === \"top\" && top < viewportPadding) {\n const flipped: Side = \"bottom\";\n const newTop = triggerRect.bottom + offset;\n if (newTop + ph <= vh - viewportPadding) {\n effectiveSide = flipped;\n top = newTop;\n }\n } else if (side === \"right\" && left + pw > vw - viewportPadding) {\n const flipped: Side = \"left\";\n const newLeft = triggerRect.left - pw - offset;\n if (newLeft >= viewportPadding) {\n effectiveSide = flipped;\n left = newLeft;\n }\n } else if (side === \"left\" && left < viewportPadding) {\n const flipped: Side = \"right\";\n const newLeft = triggerRect.right + offset;\n if (newLeft + pw <= vw - viewportPadding) {\n effectiveSide = flipped;\n left = newLeft;\n }\n }\n };\n tryFlip();\n\n // ----- clamp to viewport -----\n left = Math.max(\n viewportPadding,\n Math.min(left, vw - pw - viewportPadding),\n );\n top = Math.max(\n viewportPadding,\n Math.min(top, vh - ph - viewportPadding),\n );\n\n return { top, left, side: effectiveSide };\n}\n\nconst ARROW_SIZE = 6;\n\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n side = \"bottom\",\n align = \"center\",\n offset = 10,\n showArrow = false,\n closeOnClickOutside = true,\n closeOnEscape = true,\n duration = 80,\n viewportPadding = 8,\n container,\n width = \"auto\",\n mobileOptions,\n slideEntrance = true,\n slideEntranceOffsetPx: slideEntranceOffsetPxProp,\n className,\n style,\n ...props\n}) => {\n const { open, setOpen, triggerRef } = usePopover();\n const isMobile = usePopoverIsMobile(POPOVER_MOBILE_SHEET_MAX_PX + 1);\n const resolvedMobile = useMemo(\n () => resolvePopoverMobileSheet(mobileOptions),\n [mobileOptions],\n );\n const sheetMode = isMobile && resolvedMobile.sheet;\n const slideOffsetPx = useMemo(\n () =>\n slideEntranceOffsetPxProp ??\n POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX,\n [slideEntranceOffsetPxProp],\n );\n const closeDuration = sheetMode\n ? POPOVER_MOBILE_SHEET_MOTION_MS\n : duration;\n\n const [shouldRender, setShouldRender] = useState(false);\n const [isAnimating, setIsAnimating] = useState(false);\n const [position, setPosition] = useState<Position>({\n top: -9999,\n left: -9999,\n side,\n });\n const [triggerWidth, setTriggerWidth] = useState<number>(0);\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const closePopover = useCallback(() => setOpen(false), [setOpen]);\n\n /** Same open/close sequencing as dropdown mobile sheet / `DialogContent`. */\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n } else {\n setIsAnimating(false);\n const timer = setTimeout(() => setShouldRender(false), closeDuration);\n return () => clearTimeout(timer);\n }\n }, [open, closeDuration]);\n\n useEffect(() => {\n if (!shouldRender || !open) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setIsAnimating(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }, [shouldRender, open]);\n\n // Position calculation – runs after render so the popover has dimensions.\n // Skip while `open` is false: panel still mounts for the exit animation, but\n // `getBoundingClientRect` on the root would reflect `scale()` and re-trigger a jump.\n useLayoutEffect(() => {\n if (\n !shouldRender ||\n !open ||\n sheetMode ||\n !triggerRef.current ||\n !popoverRef.current\n )\n return;\n\n const update = () => {\n if (!triggerRef.current || !popoverRef.current) return;\n setTriggerWidth(triggerRef.current.getBoundingClientRect().width);\n const pos = computePosition(\n triggerRef.current,\n popoverRef.current,\n side,\n align,\n offset,\n viewportPadding,\n );\n setPosition(pos);\n };\n\n update();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n };\n }, [shouldRender, open, sheetMode, side, align, offset, viewportPadding]);\n\n // Body scroll lock (mobile sheet)\n useEffect(() => {\n if (open && sheetMode) {\n document.body.style.overflow = \"hidden\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [open, sheetMode]);\n\n // Close on outside click (floating only — sheet uses scrim `dismissOnBackdropPress`)\n useEffect(() => {\n if (!open || !closeOnClickOutside || sheetMode) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n popoverRef.current?.contains(target) ||\n triggerRef.current?.contains(target)\n )\n return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open, closeOnClickOutside, sheetMode, setOpen, triggerRef]);\n\n // Close on Escape\n useEffect(() => {\n if (!open || !closeOnEscape) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, closeOnEscape, setOpen]);\n\n if (!shouldRender) return null;\n\n if (sheetMode && typeof document !== \"undefined\") {\n return (\n <PopoverMobileBottomSheetPortal\n {...props}\n open={open}\n isAnimating={isAnimating}\n slideEntrance={slideEntrance}\n slideOffsetPx={slideOffsetPx}\n sheetTitle={resolvedMobile.title}\n sheetExtraClassName={resolvedMobile.sheetExtraClassName}\n contentClassName={cn(resolvedMobile.contentClassName, className)}\n onRequestClose={closePopover}\n dismissOnBackdropPress={closeOnClickOutside}\n menuRef={popoverRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n className={undefined}\n style={style}\n data-slot=\"popover-content\"\n >\n {children}\n </PopoverMobileBottomSheetPortal>\n );\n }\n\n // Animation direction by side\n const transformOrigin: Record<Side, string> = {\n bottom: \"top center\",\n top: \"bottom center\",\n left: \"right center\",\n right: \"left center\",\n };\n\n const hiddenTransform: Record<Side, string> = {\n bottom: \"translateY(-6px) scale(0.97)\",\n top: \"translateY(6px) scale(0.97)\",\n left: \"translateX(6px) scale(0.97)\",\n right: \"translateX(-6px) scale(0.97)\",\n };\n\n const resolvedWidth =\n width === \"trigger\" ? triggerWidth : width === \"auto\" ? undefined : width;\n\n // Arrow position relative to popover\n const arrowStyles = (): React.CSSProperties => {\n const base: React.CSSProperties = {\n position: \"absolute\",\n width: 0,\n height: 0,\n pointerEvents: \"none\",\n };\n switch (position.side) {\n case \"bottom\":\n return {\n ...base,\n top: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"top\":\n return {\n ...base,\n bottom: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderTop: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"right\":\n return {\n ...base,\n left: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"left\":\n return {\n ...base,\n right: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderLeft: `${ARROW_SIZE}px solid var(--border)`,\n };\n }\n };\n\n const resolvedContainer =\n container !== undefined\n ? container\n : typeof document !== \"undefined\"\n ? document.body\n : null;\n\n if (!resolvedContainer) return null;\n\n return createPortal(\n <div\n {...props}\n ref={popoverRef}\n className={cn(\n \"bg-background border-primary/10 fixed z-50 overflow-hidden rounded-xl border shadow-xl outline-none\",\n className,\n )}\n data-slot=\"popover-content\"\n style={{\n position: \"fixed\",\n top: position.top,\n left: position.left,\n width: resolvedWidth,\n transformOrigin: transformOrigin[position.side],\n transform: isAnimating ? \"none\" : hiddenTransform[position.side],\n opacity: isAnimating ? 1 : 0,\n transition: `opacity ${duration}ms ease, transform ${duration}ms ease`,\n ...style,\n }}\n >\n {showArrow && <div style={arrowStyles()} />}\n {children}\n </div>,\n resolvedContainer,\n );\n};\n\n//////////////////////////////////////////////// Sub-components\n\nexport const PopoverHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-col space-y-1 border-b px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverFooter: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-row justify-end gap-2 border-t px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverTitle: React.FC<\n React.HTMLAttributes<HTMLHeadingElement>\n> = ({ className, ...props }) => (\n <h4\n className={cn(\"text-primary text-sm leading-none font-semibold\", className)}\n {...props}\n />\n);\n\nexport const PopoverDescription: React.FC<\n React.HTMLAttributes<HTMLParagraphElement>\n> = ({ className, ...props }) => (\n <p className={cn(\"text-muted-foreground text-xs\", className)} {...props} />\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/popover.tsx"],"names":[],"mappings":"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","file":"popover.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../lib/utils\";\n\n/** Mobile popover as bottom sheet — same cutoff and motion as {@link DropdownContent}. */\nconst POPOVER_MOBILE_SHEET_MAX_PX = 1024;\nconst POPOVER_MOBILE_SHEET_MOTION_MS = 175;\nconst POPOVER_MOBILE_SHEET_ENTRY_EASING = \"cubic-bezier(0.85, 0, 0.15, 1)\";\nconst POPOVER_MOBILE_SHEET_EXIT_EASING = \"cubic-bezier(0.85, 0, 1, 0.15)\";\nconst POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;\n/** Shrink on the preferred side until space drops below ~2 rows; then allow flip. */\nconst POPOVER_FLIP_MIN_SPACE_PX = 100;\n\nfunction preventPopoverWheelChain(panel: HTMLElement, e: WheelEvent) {\n let el: HTMLElement | null = e.target as HTMLElement | null;\n while (el && panel.contains(el)) {\n const oy = getComputedStyle(el).overflowY;\n if (\n (oy === \"auto\" || oy === \"scroll\") &&\n el.scrollHeight > el.clientHeight\n ) {\n const atTop = el.scrollTop <= 0;\n const atBottom =\n el.scrollTop + el.clientHeight >= el.scrollHeight;\n if ((e.deltaY < 0 && !atTop) || (e.deltaY > 0 && !atBottom)) return;\n break;\n }\n el = el.parentElement;\n }\n e.preventDefault();\n}\n\nfunction usePopoverIsMobile(breakpoint = 1025): boolean {\n const [isMobile, setIsMobile] = useState(false);\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mq.matches);\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [breakpoint]);\n return isMobile;\n}\n\n//////////////////////////////////////////////// Context\n\ntype PopoverContextValue = {\n open: boolean;\n setOpen: (open: boolean) => void;\n triggerRef: React.RefObject<HTMLElement | null>;\n};\n\nconst PopoverContext = React.createContext<PopoverContextValue | undefined>(\n undefined,\n);\n\nfunction usePopover() {\n const context = React.useContext(PopoverContext);\n if (!context) {\n throw new Error(\"Popover components must be used within a <Popover />\");\n }\n return context;\n}\n\n//////////////////////////////////////////////// Main\n\nexport const Popover: React.FC<{\n children: React.ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}> = ({ children, open: controlledOpen, onOpenChange }) => {\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const triggerRef = useRef<HTMLElement | null>(null);\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setInternalOpen(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n return (\n <PopoverContext.Provider value={{ open, setOpen, triggerRef }}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\n//////////////////////////////////////////////// Trigger\n\nexport const PopoverTrigger: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { open, setOpen, triggerRef } = usePopover();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n setOpen(!open);\n };\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n ref?: React.Ref<unknown>;\n }>;\n return React.cloneElement(child, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: (el: HTMLElement) => {\n triggerRef.current = el;\n },\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick(e);\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button\n type=\"button\"\n ref={(el) => {\n triggerRef.current = el;\n }}\n onClick={handleClick}\n >\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Close\n\nexport const PopoverClose: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { setOpen } = usePopover();\n const handleClick = () => setOpen(false);\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n }>;\n return React.cloneElement(child, {\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick();\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Mobile sheet (popover-specific; mirrors dropdown behavior)\n\n/**\n * Narrow-viewport (≤1024px) bottom-sheet options for {@link PopoverContent}.\n * `className` merges onto the sheet panel root (after base sheet styles).\n */\nexport interface PopoverMobileSheetOptions {\n /** When `true`, use a bottom sheet on narrow viewports. Default `false`. */\n sheet?: boolean;\n title?: string;\n className?: string;\n contentClassName?: string;\n}\n\nfunction resolvePopoverMobileSheet(\n mobileOptions: PopoverMobileSheetOptions | undefined,\n) {\n return {\n sheet: mobileOptions?.sheet ?? false,\n title: mobileOptions?.title,\n sheetExtraClassName: mobileOptions?.className,\n contentClassName: mobileOptions?.contentClassName,\n };\n}\n\nexport interface PopoverMobileCloseProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\n/**\n * Dismiss control for the mobile bottom-sheet popover. Styling matches\n * {@link DialogCloseButton} (circular hit target, X icon).\n */\nexport const PopoverMobileClose = React.forwardRef<\n HTMLButtonElement,\n PopoverMobileCloseProps\n>(({ className, type = \"button\", ...props }, ref) => {\n return (\n <button\n ref={ref}\n type={type}\n className={cn(\n \"z-100 flex size-12 shrink-0 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]\",\n className,\n )}\n {...props}\n >\n <X className=\"size-5.5\" />\n <span className=\"sr-only\">Close</span>\n </button>\n );\n});\nPopoverMobileClose.displayName = \"PopoverMobileClose\";\n\ninterface PopoverMobileBottomSheetPortalProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"ref\"\n> {\n children: React.ReactNode;\n open: boolean;\n isAnimating: boolean;\n slideEntrance: boolean;\n slideOffsetPx: number;\n sheetTitle?: string;\n sheetExtraClassName?: string;\n contentClassName?: string;\n onRequestClose: () => void;\n menuRef: React.RefObject<HTMLDivElement | null>;\n /** When `false`, scrim taps do not close (matches `closeOnClickOutside={false}`). */\n dismissOnBackdropPress?: boolean;\n}\n\nfunction PopoverMobileBottomSheetPortal({\n open,\n isAnimating,\n slideEntrance,\n slideOffsetPx,\n sheetTitle,\n sheetExtraClassName,\n contentClassName,\n onRequestClose,\n menuRef,\n dismissOnBackdropPress = true,\n children,\n className,\n style,\n ...panelProps\n}: PopoverMobileBottomSheetPortalProps) {\n const sheetMotion = open\n ? POPOVER_MOBILE_SHEET_ENTRY_EASING\n : POPOVER_MOBILE_SHEET_EXIT_EASING;\n const sheetHiddenTransform = slideEntrance\n ? `translateY(${slideOffsetPx}px)`\n : \"translateY(100%)\";\n\n return createPortal(\n <div className=\"fixed inset-0 z-50 flex items-end justify-center p-0\">\n <div\n className={cn(\n \"fixed inset-0 bg-black/40 dark:bg-black/60\",\n isAnimating ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{\n transitionProperty: \"opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n }}\n onClick={dismissOnBackdropPress ? onRequestClose : undefined}\n aria-hidden\n />\n <div\n {...panelProps}\n ref={menuRef}\n className={cn(\n // Panel chrome + padding rhythm matches `DropdownMobileBottomSheetPortal`.\n \"bg-background border-primary/10 relative z-10 flex w-full max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] flex-col overflow-hidden shadow-2xl outline-none\",\n \"rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t\",\n sheetExtraClassName,\n className,\n )}\n style={{\n transform: isAnimating ? \"translateY(0)\" : sheetHiddenTransform,\n opacity: isAnimating ? 1 : 0,\n transitionProperty: \"transform, opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n ...style,\n }}\n >\n <div\n className={cn(\n \"flex w-full shrink-0 items-center py-2 pl-4 pr-2\",\n sheetTitle ? \"justify-between gap-3\" : \"justify-end\",\n )}\n >\n {sheetTitle ? (\n <p className=\"text-foreground min-w-0 flex-1 truncate text-base font-semibold\">\n {sheetTitle}\n </p>\n ) : null}\n <PopoverMobileClose\n onClick={(e) => {\n e.stopPropagation();\n onRequestClose();\n }}\n />\n </div>\n <div\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto px-4 pt-3\",\n contentClassName,\n \"pb-[calc(5rem+env(safe-area-inset-bottom,0px))]\",\n )}\n >\n {children}\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\n//////////////////////////////////////////////// Content\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype Align = \"start\" | \"center\" | \"end\";\n\ninterface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Which side of the trigger to render on */\n side?: Side;\n /** Alignment along the cross-axis */\n align?: Align;\n /** Gap between trigger and popover in px */\n offset?: number;\n /** Show a small arrow pointing to the trigger */\n showArrow?: boolean;\n /** Close when clicking outside */\n closeOnClickOutside?: boolean;\n /** Close when Escape key is pressed */\n closeOnEscape?: boolean;\n /** Animation duration in ms */\n duration?: number;\n /** Minimum distance from the viewport edge in px */\n viewportPadding?: number;\n /** Portal container – defaults to document.body */\n container?: HTMLElement | null;\n /** Width of the popover. 'trigger' matches the trigger width. */\n width?: \"auto\" | \"trigger\" | number;\n /**\n * Narrow-viewport (≤1024px) bottom sheet — same options as dropdown\n * `mobileOptions`, except `sheet` defaults to `false`.\n */\n mobileOptions?: PopoverMobileSheetOptions;\n /**\n * Mobile bottom sheet only. When `true` (default), panel motion matches Dialog\n * `slideEntrance`; when `false`, uses full `translateY(100%)`.\n */\n slideEntrance?: boolean;\n /** Mobile sheet only; defaults to 120px (same as dropdown / dialog full sheet). */\n slideEntranceOffsetPx?: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n side: Side;\n maxHeight?: number;\n}\n\nfunction computePosition(\n trigger: HTMLElement,\n popover: HTMLElement,\n side: Side,\n align: Align,\n offset: number,\n viewportPadding: number,\n): Position {\n const triggerRect = trigger.getBoundingClientRect();\n /** Layout box — not affected by exit/enter `transform: scale()`, unlike `getBoundingClientRect()`. */\n const pw = popover.offsetWidth;\n const ph = popover.offsetHeight;\n const contentHeight = popover.scrollHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const pad = viewportPadding;\n\n let top = 0;\n let left = 0;\n let effectiveSide: Side = side;\n let maxHeight: number | undefined;\n\n /** Viewport-space coords — pairs with `position: fixed` on the portal root. */\n const placeVertical = (s: Side, height: number) => {\n if (s === \"bottom\") top = triggerRect.bottom + offset;\n else top = triggerRect.top - height - offset;\n if (align === \"start\") left = triggerRect.left;\n else if (align === \"end\") left = triggerRect.right - pw;\n else left = triggerRect.left + triggerRect.width / 2 - pw / 2;\n };\n\n const place = (s: Side, height = contentHeight) => {\n switch (s) {\n case \"bottom\":\n case \"top\":\n placeVertical(s, height);\n break;\n case \"right\":\n left = triggerRect.right + offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n break;\n case \"left\":\n left = triggerRect.left - pw - offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n break;\n }\n };\n\n place(side);\n\n const spaceBelow = Math.max(0, vh - pad - triggerRect.bottom - offset);\n const spaceAbove = Math.max(0, triggerRect.top - offset - pad);\n\n if (side === \"bottom\" || side === \"top\") {\n const primarySpace = side === \"bottom\" ? spaceBelow : spaceAbove;\n const alternateSpace = side === \"bottom\" ? spaceAbove : spaceBelow;\n const alternateSide: Side = side === \"bottom\" ? \"top\" : \"bottom\";\n\n if (contentHeight > primarySpace) {\n maxHeight = Math.min(contentHeight, primarySpace);\n place(side, maxHeight);\n }\n\n if (\n contentHeight > primarySpace &&\n primarySpace < POPOVER_FLIP_MIN_SPACE_PX &&\n alternateSpace > primarySpace\n ) {\n effectiveSide = alternateSide;\n maxHeight = Math.min(contentHeight, alternateSpace);\n place(alternateSide, maxHeight);\n }\n } else if (side === \"right\" && left + pw > vw - pad) {\n const flippedLeft = triggerRect.left - pw - offset;\n if (flippedLeft >= pad) {\n effectiveSide = \"left\";\n left = flippedLeft;\n }\n } else if (side === \"left\" && left < pad) {\n const flippedLeft = triggerRect.right + offset;\n if (flippedLeft + pw <= vw - pad) {\n effectiveSide = \"right\";\n left = flippedLeft;\n }\n }\n\n const layoutHeight = maxHeight ?? contentHeight;\n left = Math.max(pad, Math.min(left, vw - pw - pad));\n top = Math.max(pad, Math.min(top, vh - layoutHeight - pad));\n\n return { top, left, side: effectiveSide, maxHeight };\n}\n\nconst ARROW_SIZE = 6;\n\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n side = \"bottom\",\n align = \"center\",\n offset = 10,\n showArrow = false,\n closeOnClickOutside = true,\n closeOnEscape = true,\n duration = 80,\n viewportPadding = 8,\n container,\n width = \"auto\",\n mobileOptions,\n slideEntrance = true,\n slideEntranceOffsetPx: slideEntranceOffsetPxProp,\n className,\n style,\n ...props\n}) => {\n const { open, setOpen, triggerRef } = usePopover();\n const isMobile = usePopoverIsMobile(POPOVER_MOBILE_SHEET_MAX_PX + 1);\n const resolvedMobile = useMemo(\n () => resolvePopoverMobileSheet(mobileOptions),\n [mobileOptions],\n );\n const sheetMode = isMobile && resolvedMobile.sheet;\n const slideOffsetPx = useMemo(\n () =>\n slideEntranceOffsetPxProp ??\n POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX,\n [slideEntranceOffsetPxProp],\n );\n const closeDuration = sheetMode\n ? POPOVER_MOBILE_SHEET_MOTION_MS\n : duration;\n\n const [shouldRender, setShouldRender] = useState(false);\n const [isAnimating, setIsAnimating] = useState(false);\n const [position, setPosition] = useState<Position>({\n top: -9999,\n left: -9999,\n side,\n });\n const [triggerWidth, setTriggerWidth] = useState<number>(0);\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const closePopover = useCallback(() => setOpen(false), [setOpen]);\n\n /** Same open/close sequencing as dropdown mobile sheet / `DialogContent`. */\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n } else {\n setIsAnimating(false);\n const timer = setTimeout(() => setShouldRender(false), closeDuration);\n return () => clearTimeout(timer);\n }\n }, [open, closeDuration]);\n\n useEffect(() => {\n if (!shouldRender || !open) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setIsAnimating(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }, [shouldRender, open]);\n\n // Position calculation – runs after render so the popover has dimensions.\n // Skip while `open` is false: panel still mounts for the exit animation, but\n // `getBoundingClientRect` on the root would reflect `scale()` and re-trigger a jump.\n useLayoutEffect(() => {\n if (\n !shouldRender ||\n !open ||\n sheetMode ||\n !triggerRef.current ||\n !popoverRef.current\n )\n return;\n\n const update = () => {\n if (!triggerRef.current || !popoverRef.current) return;\n setTriggerWidth(triggerRef.current.getBoundingClientRect().width);\n const pos = computePosition(\n triggerRef.current,\n popoverRef.current,\n side,\n align,\n offset,\n viewportPadding,\n );\n setPosition(pos);\n };\n\n update();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n };\n }, [shouldRender, open, sheetMode, side, align, offset, viewportPadding]);\n\n useEffect(() => {\n if (!shouldRender || !open || sheetMode || position.maxHeight == null) return;\n const panel = popoverRef.current;\n if (!panel) return;\n const onWheel = (e: WheelEvent) => preventPopoverWheelChain(panel, e);\n panel.addEventListener(\"wheel\", onWheel, { passive: false });\n return () => panel.removeEventListener(\"wheel\", onWheel);\n }, [shouldRender, open, sheetMode, position.maxHeight]);\n\n // Body scroll lock (mobile sheet)\n useEffect(() => {\n if (open && sheetMode) {\n document.body.style.overflow = \"hidden\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [open, sheetMode]);\n\n // Close on outside click (floating only — sheet uses scrim `dismissOnBackdropPress`)\n useEffect(() => {\n if (!open || !closeOnClickOutside || sheetMode) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n popoverRef.current?.contains(target) ||\n triggerRef.current?.contains(target)\n )\n return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open, closeOnClickOutside, sheetMode, setOpen, triggerRef]);\n\n // Close on Escape\n useEffect(() => {\n if (!open || !closeOnEscape) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, closeOnEscape, setOpen]);\n\n if (!shouldRender) return null;\n\n if (sheetMode && typeof document !== \"undefined\") {\n return (\n <PopoverMobileBottomSheetPortal\n {...props}\n open={open}\n isAnimating={isAnimating}\n slideEntrance={slideEntrance}\n slideOffsetPx={slideOffsetPx}\n sheetTitle={resolvedMobile.title}\n sheetExtraClassName={resolvedMobile.sheetExtraClassName}\n contentClassName={cn(resolvedMobile.contentClassName, className)}\n onRequestClose={closePopover}\n dismissOnBackdropPress={closeOnClickOutside}\n menuRef={popoverRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n className={undefined}\n style={style}\n data-slot=\"popover-content\"\n >\n {children}\n </PopoverMobileBottomSheetPortal>\n );\n }\n\n // Animation direction by side\n const transformOrigin: Record<Side, string> = {\n bottom: \"top center\",\n top: \"bottom center\",\n left: \"right center\",\n right: \"left center\",\n };\n\n const hiddenTransform: Record<Side, string> = {\n bottom: \"translateY(-6px) scale(0.97)\",\n top: \"translateY(6px) scale(0.97)\",\n left: \"translateX(6px) scale(0.97)\",\n right: \"translateX(-6px) scale(0.97)\",\n };\n\n const resolvedWidth =\n width === \"trigger\" ? triggerWidth : width === \"auto\" ? undefined : width;\n\n // Arrow position relative to popover\n const arrowStyles = (): React.CSSProperties => {\n const base: React.CSSProperties = {\n position: \"absolute\",\n width: 0,\n height: 0,\n pointerEvents: \"none\",\n };\n switch (position.side) {\n case \"bottom\":\n return {\n ...base,\n top: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"top\":\n return {\n ...base,\n bottom: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderTop: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"right\":\n return {\n ...base,\n left: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"left\":\n return {\n ...base,\n right: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderLeft: `${ARROW_SIZE}px solid var(--border)`,\n };\n }\n };\n\n const resolvedContainer =\n container !== undefined\n ? container\n : typeof document !== \"undefined\"\n ? document.body\n : null;\n\n if (!resolvedContainer) return null;\n\n return createPortal(\n <div\n {...props}\n ref={popoverRef}\n className={cn(\n \"bg-background border-primary/10 fixed z-50 rounded-xl border shadow-xl outline-none\",\n className,\n position.maxHeight != null ? \"overflow-y-auto overscroll-contain\" : \"overflow-hidden\",\n )}\n data-slot=\"popover-content\"\n style={{\n position: \"fixed\",\n top: position.top,\n left: position.left,\n width: resolvedWidth,\n maxHeight: position.maxHeight,\n transformOrigin: transformOrigin[position.side],\n transform: isAnimating ? \"none\" : hiddenTransform[position.side],\n opacity: isAnimating ? 1 : 0,\n transition: `opacity ${duration}ms ease, transform ${duration}ms ease`,\n ...style,\n }}\n >\n {showArrow && <div style={arrowStyles()} />}\n {children}\n </div>,\n resolvedContainer,\n );\n};\n\n//////////////////////////////////////////////// Sub-components\n\nexport const PopoverHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-col space-y-1 border-b px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverFooter: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-row justify-end gap-2 border-t px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverTitle: React.FC<\n React.HTMLAttributes<HTMLHeadingElement>\n> = ({ className, ...props }) => (\n <h4\n className={cn(\"text-primary text-sm leading-none font-semibold\", className)}\n {...props}\n />\n);\n\nexport const PopoverDescription: React.FC<\n React.HTMLAttributes<HTMLParagraphElement>\n> = ({ className, ...props }) => (\n <p className={cn(\"text-muted-foreground text-xs\", className)} {...props} />\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/scroll-header.tsx"],"names":[],"mappings":"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","file":"scroll-header.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n Children,\n createContext,\n isValidElement,\n ReactElement,\n ReactNode,\n useContext,\n useEffect,\n useRef,\n} from \"react\";\n\nconst DATA_ATTR = \"data-scrolled\";\n\nexport type ScrollHeaderRevealAt = \"start\" | \"center\" | \"end\";\n\ninterface ScrollHeaderContextValue {\n revealAt: ScrollHeaderRevealAt;\n slideIn: boolean;\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeaderContext = createContext<ScrollHeaderContextValue>({\n revealAt: \"center\",\n slideIn: true,\n onRevealChange: undefined,\n});\n\nfunction isScrollHeaderStickyEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName ===\n \"ScrollHeaderSticky\"\n );\n}\n\nfunction isScrollHeaderTopEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName === \"ScrollHeaderTop\"\n );\n}\n\n/** Sticky first so `position: sticky; top: 0` pins to the scrollport, not below the hero. */\nfunction reorderScrollHeaderChildren(children: ReactNode): ReactNode[] {\n const sticky: ReactNode[] = [];\n const top: ReactNode[] = [];\n const rest: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n if (child != null && child !== false) rest.push(child);\n return;\n }\n if (isScrollHeaderStickyEl(child)) sticky.push(child);\n else if (isScrollHeaderTopEl(child)) top.push(child);\n else rest.push(child);\n });\n\n return [...sticky, ...top, ...rest];\n}\n\ninterface ScrollHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n /**\n * Which part of `ScrollHeaderTop` must leave the scrollport before the sticky bar shows.\n * `start` — top edge (earliest). `center` — vertical midpoint. `end` — bottom edge (latest).\n * If omitted: defaults to `center` when `slideIn` is true, and `start` when `slideIn` is false (in-flow bar).\n */\n revealAt?: ScrollHeaderRevealAt;\n /**\n * When `true` (default), `ScrollHeaderSticky` overlays without layout height and slides in with opacity.\n * When `false`, the sticky bar stays in document flow (takes vertical space); use `onRevealChange` and\n * your own styles for any fade or toolbar behavior.\n */\n slideIn?: boolean;\n /**\n * Called when the sticky header reveal state changes after scroll.\n * `true` once the top section has crossed the reveal threshold (same moment as `data-scrolled=\"true\"`).\n */\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeader: React.FC<ScrollHeaderProps> = ({\n revealAt,\n slideIn = true,\n onRevealChange,\n children,\n className,\n ...props\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n const resolvedRevealAt = revealAt ?? (slideIn ? \"center\" : \"start\");\n\n return (\n <ScrollHeaderContext.Provider\n value={{\n revealAt: resolvedRevealAt,\n slideIn,\n onRevealChange,\n }}\n >\n <div\n ref={ref}\n data-scrolled=\"false\"\n className={cn(\n \"scroll-header bg-background flex h-full flex-col overflow-y-auto\",\n className,\n )}\n {...props}\n >\n {reorderScrollHeaderChildren(children)}\n </div>\n </ScrollHeaderContext.Provider>\n );\n};\n\nconst sentinelClass = \"pointer-events-none h-px w-full shrink-0\";\n\nconst ScrollHeaderTop: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { revealAt, onRevealChange } = useContext(ScrollHeaderContext);\n const sentinelRef = useRef<HTMLDivElement>(null);\n const onRevealChangeRef = useRef(onRevealChange);\n onRevealChangeRef.current = onRevealChange;\n const lastRevealedRef = useRef<boolean | undefined>(undefined);\n\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n\n const container = sentinel.closest<HTMLElement>(\"[data-scrolled]\");\n if (!container) return;\n\n lastRevealedRef.current = undefined;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry) return;\n const revealed = !entry.isIntersecting;\n container.setAttribute(DATA_ATTR, revealed ? \"true\" : \"false\");\n if (lastRevealedRef.current !== revealed) {\n lastRevealedRef.current = revealed;\n onRevealChangeRef.current?.(revealed);\n }\n },\n { root: container, threshold: 0 },\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [revealAt]);\n\n if (revealAt === \"end\") {\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n {children}\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n </div>\n );\n }\n\n if (revealAt === \"center\") {\n return (\n <div className={cn(\"relative shrink-0\", className)} {...props}>\n <div\n ref={sentinelRef}\n className={cn(\n sentinelClass,\n \"absolute left-0 right-0 top-1/2 z-0 -translate-y-1/2\",\n )}\n aria-hidden\n />\n {children}\n </div>\n );\n }\n\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n {children}\n </div>\n );\n};\n\nScrollHeaderTop.displayName = \"ScrollHeaderTop\";\n\nconst stickyChromeBgClass =\n \"bg-background supports-backdrop-filter:bg-background\";\n\nconst stickyChromeBorderClass = \"border-primary/10 border-b\";\n\nconst stickyChromeClass = cn(stickyChromeBgClass, stickyChromeBorderClass);\n\nconst revealEase =\n \"duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:duration-0 motion-reduce:transition-none\";\n\nconst ScrollHeaderSticky: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { slideIn } = useContext(ScrollHeaderContext);\n\n return (\n <div\n className={cn(\n \"sticky top-0 z-40\",\n slideIn ? \"h-0 overflow-visible\" : \"shrink-0\",\n )}\n >\n {slideIn ? (\n <div\n className={cn(\n stickyChromeClass,\n \"transition-[opacity, transform]\",\n revealEase,\n '[.scroll-header:not([data-scrolled=\"true\"])_&]:pointer-events-none [.scroll-header:not([data-scrolled=\"true\"])_&]:-translate-y-1 [.scroll-header:not([data-scrolled=\"true\"])_&]:opacity-0',\n '[.scroll-header[data-scrolled=\"true\"]_&]:translate-y-0 [.scroll-header[data-scrolled=\"true\"]_&]:opacity-100',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n ) : (\n <div className={stickyChromeBgClass}>\n <div\n className={cn(\n stickyChromeBorderClass,\n \"transition-[border-color] duration-300 motion-reduce:duration-0 motion-reduce:transition-none\",\n '[.scroll-header:not([data-scrolled=\"true\"])_&]:border-b-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nScrollHeaderSticky.displayName = \"ScrollHeaderSticky\";\n\nexport { ScrollHeader, ScrollHeaderSticky, ScrollHeaderTop };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/scroll-header.tsx"],"names":[],"mappings":"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","file":"scroll-header.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { cn } from \"../lib/utils\";\nimport {\n Children,\n createContext,\n isValidElement,\n ReactElement,\n ReactNode,\n useContext,\n useEffect,\n useRef,\n} from \"react\";\n\nconst DATA_ATTR = \"data-scrolled\";\n\nexport type ScrollHeaderRevealAt = \"start\" | \"center\" | \"end\";\n\ninterface ScrollHeaderContextValue {\n revealAt: ScrollHeaderRevealAt;\n slideIn: boolean;\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeaderContext = createContext<ScrollHeaderContextValue>({\n revealAt: \"center\",\n slideIn: true,\n onRevealChange: undefined,\n});\n\nfunction isScrollHeaderStickyEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName ===\n \"ScrollHeaderSticky\"\n );\n}\n\nfunction isScrollHeaderTopEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName === \"ScrollHeaderTop\"\n );\n}\n\n/** Sticky first so `position: sticky; top: 0` pins to the scrollport, not below the hero. */\nfunction reorderScrollHeaderChildren(children: ReactNode): ReactNode[] {\n const sticky: ReactNode[] = [];\n const top: ReactNode[] = [];\n const rest: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n if (child != null && child !== false) rest.push(child);\n return;\n }\n if (isScrollHeaderStickyEl(child)) sticky.push(child);\n else if (isScrollHeaderTopEl(child)) top.push(child);\n else rest.push(child);\n });\n\n return [...sticky, ...top, ...rest];\n}\n\ninterface ScrollHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n /**\n * Which part of `ScrollHeaderTop` must leave the scrollport before the sticky bar shows.\n * `start` — top edge (earliest). `center` — vertical midpoint. `end` — bottom edge (latest).\n * If omitted: defaults to `center` when `slideIn` is true, and `start` when `slideIn` is false (in-flow bar).\n */\n revealAt?: ScrollHeaderRevealAt;\n /**\n * When `true` (default), `ScrollHeaderSticky` overlays without layout height and slides in with opacity.\n * When `false`, the sticky bar stays in document flow (takes vertical space); use `onRevealChange` and\n * your own styles for any fade or toolbar behavior.\n */\n slideIn?: boolean;\n /**\n * Called when the sticky header reveal state changes after scroll.\n * `true` once the top section has crossed the reveal threshold (same moment as `data-scrolled=\"true\"`).\n */\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeader: React.FC<ScrollHeaderProps> = ({\n revealAt,\n slideIn = true,\n onRevealChange,\n children,\n className,\n ...props\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n const resolvedRevealAt = revealAt ?? (slideIn ? \"center\" : \"start\");\n\n return (\n <ScrollHeaderContext.Provider\n value={{\n revealAt: resolvedRevealAt,\n slideIn,\n onRevealChange,\n }}\n >\n <div\n ref={ref}\n data-scrolled=\"false\"\n className={cn(\n \"scroll-header bg-background flex h-full flex-col overflow-y-auto\",\n className,\n )}\n {...props}\n >\n {reorderScrollHeaderChildren(children)}\n </div>\n </ScrollHeaderContext.Provider>\n );\n};\n\nconst sentinelClass = \"pointer-events-none h-px w-full shrink-0\";\n\nconst ScrollHeaderTop: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { revealAt, onRevealChange } = useContext(ScrollHeaderContext);\n const sentinelRef = useRef<HTMLDivElement>(null);\n const onRevealChangeRef = useRef(onRevealChange);\n onRevealChangeRef.current = onRevealChange;\n const lastRevealedRef = useRef<boolean | undefined>(undefined);\n\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n\n const container = sentinel.closest<HTMLElement>(\"[data-scrolled]\");\n if (!container) return;\n\n lastRevealedRef.current = undefined;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry) return;\n const revealed = !entry.isIntersecting;\n container.setAttribute(DATA_ATTR, revealed ? \"true\" : \"false\");\n if (lastRevealedRef.current !== revealed) {\n lastRevealedRef.current = revealed;\n onRevealChangeRef.current?.(revealed);\n }\n },\n { root: container, threshold: 0 },\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [revealAt]);\n\n if (revealAt === \"end\") {\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n {children}\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n </div>\n );\n }\n\n if (revealAt === \"center\") {\n return (\n <div className={cn(\"relative shrink-0\", className)} {...props}>\n <div\n ref={sentinelRef}\n className={cn(\n sentinelClass,\n \"absolute left-0 right-0 top-1/2 z-0 -translate-y-1/2\",\n )}\n aria-hidden\n />\n {children}\n </div>\n );\n }\n\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n {children}\n </div>\n );\n};\n\nScrollHeaderTop.displayName = \"ScrollHeaderTop\";\n\nconst stickyChromeBgClass =\n \"bg-background supports-backdrop-filter:bg-background\";\n\nconst stickyChromeBorderClass = \"border-primary/10 border-b\";\n\nconst stickyChromeClass = cn(stickyChromeBgClass, stickyChromeBorderClass);\n\nconst revealEase =\n \"duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:duration-0 motion-reduce:transition-none\";\n\nconst ScrollHeaderSticky: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { slideIn } = useContext(ScrollHeaderContext);\n\n return (\n <div\n className={cn(\n \"sticky top-0 z-40\",\n slideIn ? \"h-0 overflow-visible\" : \"shrink-0\",\n )}\n >\n {slideIn ? (\n <div\n className={cn(\n stickyChromeClass,\n \"transition-[opacity, transform]\",\n revealEase,\n '[.scroll-header:not([data-scrolled=\"true\"])_&]:pointer-events-none [.scroll-header:not([data-scrolled=\"true\"])_&]:-translate-y-1 [.scroll-header:not([data-scrolled=\"true\"])_&]:opacity-0',\n '[.scroll-header[data-scrolled=\"true\"]_&]:translate-y-0 [.scroll-header[data-scrolled=\"true\"]_&]:opacity-100',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n ) : (\n <div className={stickyChromeBgClass}>\n <div\n className={cn(\n stickyChromeBorderClass,\n \"transition-[border-color] duration-300 motion-reduce:duration-0 motion-reduce:transition-none\",\n '[.scroll-header:not([data-scrolled=\"true\"])_&]:border-b-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nScrollHeaderSticky.displayName = \"ScrollHeaderSticky\";\n\nexport { ScrollHeader, ScrollHeaderSticky, ScrollHeaderTop };\n"]}
|