@evolve.ui/core-components 1.1.0 → 1.2.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/{BottomSheet-ZV_eq3xt.mjs → BottomSheet-CNVLnEoD.mjs} +3 -3
- package/BottomSheet-CNVLnEoD.mjs.map +1 -0
- package/{BottomSheet-emWP9Fct.cjs → BottomSheet-D5w0WZDl.cjs} +3 -3
- package/BottomSheet-D5w0WZDl.cjs.map +1 -0
- package/Button.cjs +1 -1
- package/Button.mjs +1 -1
- package/{CookieConsent-CIwm0bTz.mjs → CookieConsent-B9dg9WdC.mjs} +2 -2
- package/{CookieConsent-CIwm0bTz.mjs.map → CookieConsent-B9dg9WdC.mjs.map} +1 -1
- package/{CookieConsent-PIglB_bb.cjs → CookieConsent-BSXJHMwX.cjs} +2 -2
- package/{CookieConsent-PIglB_bb.cjs.map → CookieConsent-BSXJHMwX.cjs.map} +1 -1
- package/{Drawer-9HFG45OA.cjs → Drawer-3rA9dGCl.cjs} +2 -2
- package/{Drawer-9HFG45OA.cjs.map → Drawer-3rA9dGCl.cjs.map} +1 -1
- package/Drawer-CFZbwg0R.d.cts.map +1 -1
- package/Drawer-CFZbwg0R.d.mts.map +1 -1
- package/{Drawer-BkCPfK6P.mjs → Drawer-DzKEmewj.mjs} +2 -2
- package/{Drawer-BkCPfK6P.mjs.map → Drawer-DzKEmewj.mjs.map} +1 -1
- package/{FavoriteButton-CC3qL0lR.mjs → FavoriteButton-7nK77lQP.mjs} +6 -6
- package/FavoriteButton-7nK77lQP.mjs.map +1 -0
- package/{FavoriteButton-BGF-3dze.d.cts → FavoriteButton-B8r_qtlj.d.cts} +2 -2
- package/{FavoriteButton-BGF-3dze.d.cts.map → FavoriteButton-B8r_qtlj.d.cts.map} +1 -1
- package/{FavoriteButton-DliYzkfu.cjs → FavoriteButton-BkIaWfgD.cjs} +6 -6
- package/FavoriteButton-BkIaWfgD.cjs.map +1 -0
- package/{FavoriteButton-BZEGWrRo.d.mts → FavoriteButton-hIkGjcKH.d.mts} +2 -2
- package/{FavoriteButton-BZEGWrRo.d.mts.map → FavoriteButton-hIkGjcKH.d.mts.map} +1 -1
- package/{FileUpload-p_pl9NXr.mjs → FileUpload-BfZOMsLs.mjs} +6 -6
- package/FileUpload-BfZOMsLs.mjs.map +1 -0
- package/{FileUpload--e_UJ_ek.cjs → FileUpload-gjRbkgrL.cjs} +6 -6
- package/FileUpload-gjRbkgrL.cjs.map +1 -0
- package/IconButton.cjs +1 -1
- package/IconButton.mjs +1 -1
- package/{ImageSlider-BidXfnLj.cjs → ImageSlider-CAgxQffP.cjs} +3 -3
- package/ImageSlider-CAgxQffP.cjs.map +1 -0
- package/{ImageSlider-CDrg_TbL.mjs → ImageSlider-fdrJ6lIJ.mjs} +3 -3
- package/ImageSlider-fdrJ6lIJ.mjs.map +1 -0
- package/InfoIconTooltip.cjs +1 -1
- package/InfoIconTooltip.cjs.map +1 -1
- package/InfoIconTooltip.mjs +1 -1
- package/InfoIconTooltip.mjs.map +1 -1
- package/InlineButton-CRLbNJZ3.d.mts.map +1 -1
- package/InlineButton-DoXGLiSE.d.cts.map +1 -1
- package/Input.cjs +1 -1
- package/Input.cjs.map +1 -1
- package/Input.mjs +1 -1
- package/Input.mjs.map +1 -1
- package/JumpMenu-BXYZnPIH.cjs.map +1 -1
- package/JumpMenu-DcZjAiej.mjs.map +1 -1
- package/{Menu-Cxu8CaX1.mjs → Menu-Bn4smlEe.mjs} +2 -2
- package/Menu-Bn4smlEe.mjs.map +1 -0
- package/{Menu-ClUogmwE.cjs → Menu-DuDhtoNP.cjs} +2 -2
- package/Menu-DuDhtoNP.cjs.map +1 -0
- package/Modal-DM0aXJZ5.d.cts.map +1 -1
- package/Modal-DM0aXJZ5.d.mts.map +1 -1
- package/{Modal-C6gatdtT.mjs → Modal-DtxWd7Le.mjs} +3 -2
- package/{Modal-C6gatdtT.mjs.map → Modal-DtxWd7Le.mjs.map} +1 -1
- package/{Modal-CiBqXyiK.cjs → Modal-q4HhBAQU.cjs} +3 -2
- package/Modal-q4HhBAQU.cjs.map +1 -0
- package/{Pagination-bAtbN478.cjs → Pagination-Denb9_zB.cjs} +2 -2
- package/{Pagination-bAtbN478.cjs.map → Pagination-Denb9_zB.cjs.map} +1 -1
- package/{Pagination-DIpGKMLz.mjs → Pagination-Dyfeys4B.mjs} +2 -2
- package/{Pagination-DIpGKMLz.mjs.map → Pagination-Dyfeys4B.mjs.map} +1 -1
- package/PhoneInput-B5pkpkdt.mjs.map +1 -1
- package/PhoneInput-BXnkBME4.d.mts.map +1 -1
- package/PhoneInput-Bkrbrins.d.cts.map +1 -1
- package/PhoneInput-CUMPOSxJ.cjs.map +1 -1
- package/{ProgressCircle-BC81D9sU.cjs → ProgressCircle-B6R4dxoV.cjs} +2 -2
- package/{ProgressCircle-BC81D9sU.cjs.map → ProgressCircle-B6R4dxoV.cjs.map} +1 -1
- package/{ProgressCircle-ae8cvZhe.mjs → ProgressCircle-zSai1HTT.mjs} +2 -2
- package/{ProgressCircle-ae8cvZhe.mjs.map → ProgressCircle-zSai1HTT.mjs.map} +1 -1
- package/SearchInput-DYIPC8Cd.d.cts.map +1 -1
- package/SearchInput-IfEWePDQ.d.mts.map +1 -1
- package/{Select-BkZu8OLs.mjs → Select-CH_ZN88G.mjs} +2 -2
- package/Select-CH_ZN88G.mjs.map +1 -0
- package/{Select-BXDjzyDs.cjs → Select-DCCcyLT4.cjs} +2 -2
- package/Select-DCCcyLT4.cjs.map +1 -0
- package/{SplitButton-DcmmLW8j.cjs → SplitButton-B_Y253RU.cjs} +2 -2
- package/{SplitButton-DcmmLW8j.cjs.map → SplitButton-B_Y253RU.cjs.map} +1 -1
- package/{SplitButton-WE5ymwCQ.mjs → SplitButton-_poP9Ykq.mjs} +2 -2
- package/{SplitButton-WE5ymwCQ.mjs.map → SplitButton-_poP9Ykq.mjs.map} +1 -1
- package/{Table-M-rANdMt.mjs → Table-CQGtDpvH.mjs} +3 -3
- package/{Table-M-rANdMt.mjs.map → Table-CQGtDpvH.mjs.map} +1 -1
- package/{Table-CLlDragJ.cjs → Table-D4UYosb1.cjs} +3 -3
- package/{Table-CLlDragJ.cjs.map → Table-D4UYosb1.cjs.map} +1 -1
- package/Typography/InlineButton.cjs +1 -1
- package/Typography/InlineButton.cjs.map +1 -1
- package/Typography/InlineButton.mjs +1 -1
- package/Typography/InlineButton.mjs.map +1 -1
- package/{ViewMore-BBoUvo7p.cjs → ViewMore-BcoSRZSl.cjs} +14 -1
- package/ViewMore-BcoSRZSl.cjs.map +1 -0
- package/{ViewMore-BrZPuE4E.mjs → ViewMore-Be0TQZ_2.mjs} +14 -1
- package/ViewMore-Be0TQZ_2.mjs.map +1 -0
- package/bottomSheet.cjs +1 -1
- package/bottomSheet.mjs +1 -1
- package/{buttonColorClasses-C3hg1at8.cjs → buttonColorClasses-CQQmLYfk.cjs} +4 -4
- package/buttonColorClasses-CQQmLYfk.cjs.map +1 -0
- package/{buttonColorClasses-B7OU4aQA.mjs → buttonColorClasses-CQnqAJXl.mjs} +4 -4
- package/buttonColorClasses-CQnqAJXl.mjs.map +1 -0
- package/card/components/createFavoriteButton.cjs +1 -1
- package/card/components/createFavoriteButton.mjs +1 -1
- package/cookieConsent.cjs +1 -1
- package/cookieConsent.mjs +1 -1
- package/drawer.cjs +1 -1
- package/drawer.mjs +1 -1
- package/favoriteButton.cjs +1 -1
- package/favoriteButton.d.cts +1 -1
- package/favoriteButton.d.mts +1 -1
- package/favoriteButton.mjs +1 -1
- package/featureFlags/hooks.d.cts +1 -1
- package/featureFlags/hooks.d.mts +1 -1
- package/fileUpload/testUtils/mockFilesAndImages.d.cts +3 -3
- package/fileUpload/testUtils/mockFilesAndImages.d.cts.map +1 -1
- package/fileUpload/testUtils/mockFilesAndImages.d.mts +3 -3
- package/fileUpload/testUtils/mockFilesAndImages.d.mts.map +1 -1
- package/fileUpload/testUtils/testUtils.d.cts +1 -1
- package/fileUpload/testUtils/testUtils.d.cts.map +1 -1
- package/fileUpload/testUtils/testUtils.d.mts +1 -1
- package/fileUpload/testUtils/testUtils.d.mts.map +1 -1
- package/fileUpload.cjs +1 -1
- package/fileUpload.mjs +1 -1
- package/imageSlider.cjs +1 -1
- package/imageSlider.mjs +1 -1
- package/index.cjs +14 -14
- package/index.d.cts +1 -1
- package/index.d.mts +1 -1
- package/index.mjs +14 -14
- package/menu.cjs +1 -1
- package/menu.mjs +1 -1
- package/modal/useCloseModal.cjs +2 -1
- package/modal/useCloseModal.cjs.map +1 -1
- package/modal/useCloseModal.mjs +2 -1
- package/modal/useCloseModal.mjs.map +1 -1
- package/modal.cjs +1 -1
- package/modal.mjs +1 -1
- package/package.json +2 -4
- package/pagination.cjs +1 -1
- package/pagination.mjs +1 -1
- package/progressCircle.cjs +1 -1
- package/progressCircle.mjs +1 -1
- package/searchInput.cjs +4 -4
- package/searchInput.cjs.map +1 -1
- package/searchInput.mjs +4 -4
- package/searchInput.mjs.map +1 -1
- package/select.cjs +1 -1
- package/select.mjs +1 -1
- package/selectAsync.cjs +1 -1
- package/selectAsync.mjs +1 -1
- package/selectAsyncCreatable.cjs +1 -1
- package/selectAsyncCreatable.mjs +1 -1
- package/selectCreatable.cjs +1 -1
- package/selectCreatable.mjs +1 -1
- package/splitButton.cjs +1 -1
- package/splitButton.mjs +1 -1
- package/src/BottomSheet/components/BottomSheetContentArea/BottomSheetContentArea.tsx +4 -3
- package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +5 -2
- package/src/Button/buttonColorClasses.ts +8 -3
- package/src/Drawer/Drawer.tsx +5 -8
- package/src/FavoriteButton/components/IconOnlyFavoriteButton/IconOnlyFavoriteButton.tsx +4 -1
- package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +13 -6
- package/src/FavoriteButton/types/favoriteButton.ts +1 -1
- package/src/FileUpload/components/GridFileCard/GridFileCard.tsx +1 -1
- package/src/FileUpload/components/ListFileCard/ListFileCard.tsx +2 -2
- package/src/ImageSlider/ImageSlider.tsx +3 -1
- package/src/ImageSlider/components/Thumbnails/Thumbnails.tsx +1 -1
- package/src/JumpMenu/components/JumpMenuItem/JumpMenuItem.tsx +4 -1
- package/src/Menu/components/MenuItem/MenuItem.tsx +1 -1
- package/src/Modal/ComposableModal.tsx +9 -1
- package/src/Modal/hooks/useCloseModal.ts +8 -1
- package/src/PhoneInput/PhoneInput.tsx +7 -1
- package/src/ProgressCircle/ProgressCircle.tsx +1 -1
- package/src/SearchInput/SearchInput.tsx +5 -4
- package/src/Select/selectComponents.tsx +1 -2
- package/src/Tabs/Tabs.tsx +4 -4
- package/src/TextArea/TextArea.tsx +2 -0
- package/src/TextInput/TextInput.tsx +1 -1
- package/src/Tooltip/InfoIconTooltip.tsx +1 -1
- package/src/Typography/InlineButton/InlineButton.tsx +4 -3
- package/src/utils/smoothScrollTo.ts +18 -0
- package/table.cjs +1 -1
- package/table.mjs +1 -1
- package/tabs.cjs +1 -1
- package/tabs.cjs.map +1 -1
- package/tabs.mjs +1 -1
- package/tabs.mjs.map +1 -1
- package/textArea.cjs.map +1 -1
- package/textArea.mjs.map +1 -1
- package/viewMore.cjs +1 -1
- package/viewMore.mjs +1 -1
- package/BottomSheet-ZV_eq3xt.mjs.map +0 -1
- package/BottomSheet-emWP9Fct.cjs.map +0 -1
- package/FavoriteButton-CC3qL0lR.mjs.map +0 -1
- package/FavoriteButton-DliYzkfu.cjs.map +0 -1
- package/FileUpload--e_UJ_ek.cjs.map +0 -1
- package/FileUpload-p_pl9NXr.mjs.map +0 -1
- package/ImageSlider-BidXfnLj.cjs.map +0 -1
- package/ImageSlider-CDrg_TbL.mjs.map +0 -1
- package/Menu-ClUogmwE.cjs.map +0 -1
- package/Menu-Cxu8CaX1.mjs.map +0 -1
- package/Modal-CiBqXyiK.cjs.map +0 -1
- package/Select-BXDjzyDs.cjs.map +0 -1
- package/Select-BkZu8OLs.mjs.map +0 -1
- package/ViewMore-BBoUvo7p.cjs.map +0 -1
- package/ViewMore-BrZPuE4E.mjs.map +0 -1
- package/buttonColorClasses-B7OU4aQA.mjs.map +0 -1
- package/buttonColorClasses-C3hg1at8.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Menu-DuDhtoNP.cjs","names":["MenuContext","ToggleSwitch","Checkbox","RadioOption","H5","BodyPrimary","Caption","useMenuContext","autoUpdate","FloatingNode","MenuContext","FloatingList","FloatingPortal","FloatingFocusManager","FloatingArrow","FloatingTree"],"sources":["../src/Menu/components/MenuItem/MenuItem.tsx","../src/Menu/components/MenuDivider/MenuDivider.tsx","../src/Menu/Menu.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useFloatingTree, useListItem, useMergeRefs } from '@floating-ui/react';\nimport { forwardRef, HTMLAttributes, KeyboardEvent, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { Checkbox, RadioOption } from '../../../ChoiceListItem';\nimport { AnyIcon } from '../../../Icons/anyIcon';\nimport { ToggleSwitch } from '../../../ToggleSwitch/ToggleSwitch';\nimport { BodyPrimary, Caption, H5 } from '../../../Typography/Text/Text';\nimport { MenuContext } from '../../context/menuContext';\n\nexport type MenuItemProps = {\n /** additional CSS class name for the menu item*/\n className?: string;\n /** close menu after action is performed */\n closeOnAction?: boolean;\n /** color of menu item */\n color?: 'disabled' | 'inherit' | 'critical' | 'info' | 'inverse' | 'success' | 'secondary' | 'primary' | 'warning';\n /** second row description, optional */\n description?: string;\n /** disable menu item */\n disabled?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n id?: string | number;\n /** flag if using as header, alters style and hover state */\n isHeader?: boolean;\n /** Icon to use on Left side of menu item, requires numberOfColumns of 3 */\n leftIcon?: AnyIcon;\n /** primary menu label string, required */\n primaryLabel: string;\n /** Icon to use on Right side of menu, requires numberOfColumns of 2 or 3 */\n rightIcon?: AnyIcon;\n /** secondary label to be used to right of primary label, cannot be used with rightIcon, requires numberOfColumns of 2 or 3 */\n secondaryLabel?: string;\n} & (\n | {\n checked?: never;\n id?: never;\n onCheckboxChange?: never;\n onClick?: never;\n onFocus?: never;\n onRadioChange?: never;\n onToggleChange?: never;\n }\n | {\n /** current state of control */\n checked?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n className?: string;\n id?: string | number;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onCheckboxChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in LeftIcon space */\n onClick?: (id: string | number) => void;\n /** if present, trigger when MenuItem is focused */\n onFocus?: (id: string | number) => void;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onRadioChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in RightIcon space, requires numberOfColumns of 2 or 3 */\n onToggleChange?: (id: string | number, checked: boolean) => void;\n }\n);\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps & HTMLAttributes<HTMLDivElement>>(\n (\n {\n checked = false,\n className,\n closeOnAction = false,\n color = 'inherit',\n description,\n disabled,\n id = '',\n isHeader,\n leftIcon: LeftIcon,\n onCheckboxChange,\n onClick,\n onFocus,\n onRadioChange,\n onToggleChange,\n primaryLabel,\n rightIcon: RightIcon,\n secondaryLabel,\n ...rest\n }: MenuItemProps & HTMLAttributes<HTMLDivElement>,\n forwardedRef\n ) => {\n const [isChecked, setIsChecked] = useState(checked);\n const { getItemProps, numberOfColumns } = useContext(MenuContext);\n const { ref: itemRef } = useListItem();\n\n const renderColor = disabled ? 'disabled' : color;\n\n useEffect(() => {\n setIsChecked(checked);\n }, [checked]);\n\n const tree = useFloatingTree();\n\n const rightSection = useMemo(() => {\n if (RightIcon) {\n return (\n <RightIcon\n className=\"self-center justify-self-center grid-area-[right]\"\n color={renderColor}\n size=\"sm\"\n />\n );\n }\n if (onToggleChange) {\n // Note, event handled by component level onClick\n return (\n <ToggleSwitch\n className=\"grid-area-[right]\"\n data-testid={`menu-toggle-${id}`}\n dense\n isToggled={isChecked}\n tabIndex={-1}\n />\n );\n }\n return null;\n }, [id, RightIcon, onToggleChange, isChecked, renderColor]);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n if (e.code === 'Space' || e.code === 'Enter') {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleItemClick = (event: React.MouseEvent<HTMLElement>) => {\n event.stopPropagation();\n if (disabled) {\n return;\n }\n // this is to prevent UI elements like SVGs from triggering an additional click\n if (\n event.target instanceof HTMLButtonElement ||\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLSpanElement ||\n event.target instanceof HTMLDivElement\n ) {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleFocus = () => {\n if (disabled) {\n return;\n }\n onFocus?.(id);\n };\n\n return (\n <div\n {...rest}\n {...getItemProps({})}\n aria-describedby={description ? `menu-item-description-${id}` : undefined}\n aria-disabled={disabled}\n aria-label={primaryLabel}\n className={cn(\n {\n 'active:bg-background-hover': !isHeader,\n 'focus-visible:bg-background-hover': !isHeader,\n 'hover:bg-background-hover': !isHeader,\n },\n 'MenuItem relative grid w-full cursor-pointer items-center justify-start gap-x-xs border-none px-sm py-3 outline-0',\n className\n )}\n data-testid={`menu-item-${id}`}\n onClick={handleItemClick}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={useMergeRefs([itemRef, forwardedRef])}\n role=\"menuitem\"\n style={{\n gridTemplateAreas:\n numberOfColumns === 2\n ? \"'title right' 'description right'\"\n : numberOfColumns === 1\n ? \"'title' 'description'\"\n : // 3 column default\n \"'icon title right' 'icon description right'\",\n gridTemplateColumns:\n numberOfColumns === 2\n ? '1fr min-content'\n : numberOfColumns === 1\n ? '1fr'\n : // 3 column default\n '24px 1fr min-content',\n gridTemplateRows: 'min-content min-content',\n }}\n tabIndex={isHeader ? -1 : 0}\n >\n {/* LEFT */}\n {LeftIcon && (\n <LeftIcon\n className=\"self-center justify-self-center grid-area-[icon]\"\n color={renderColor}\n size=\"sm\"\n />\n )}\n {onCheckboxChange && (\n <Checkbox.Option\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-checkbox-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n {onRadioChange && (\n <RadioOption\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-radio-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n\n {/* MAIN */}\n {isHeader ? (\n <H5 className={cn('grid-area-[title]', `text-text-${renderColor}`)}>{primaryLabel}</H5>\n ) : (\n <div className=\"flex items-center justify-between gap-x-xs grid-area-[title]\">\n <BodyPrimary className={`text-text-${renderColor}`}>{primaryLabel}</BodyPrimary>\n {secondaryLabel && <BodyPrimary className=\"text-text-secondary\">{secondaryLabel}</BodyPrimary>}\n </div>\n )}\n {Boolean(description?.trim()) && (\n <Caption className={cn('grid-area-[description]', `text-text-${renderColor}`)}>\n {description}\n </Caption>\n )}\n\n {/* RIGHT */}\n {rightSection}\n </div>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n","import { cn } from '@evolve.ui/theme-system';\n\nexport const MenuDivider = ({ className }: { className?: string }) => {\n return <div className={cn('border-t border-border-secondary', className)} />;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n Placement,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTypeahead,\n} from '@floating-ui/react';\nimport {\n cloneElement,\n FocusEvent,\n forwardRef,\n HTMLProps,\n isValidElement,\n MouseEvent,\n ReactElement,\n ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { MenuContext, useMenuContext } from './context/menuContext';\n\n/**\n * Hook to detect if component has mounted (client-side only)\n * Useful for preventing SSR hydration mismatches\n */\nconst useHasMounted = () => {\n const [hasMounted, setHasMounted] = useState(false);\n useEffect(() => {\n setHasMounted(true);\n }, []);\n return hasMounted;\n};\n\nexport type MenuProps = {\n /** MenuItem children */\n children?: ReactNode;\n /** additional CSS class name for the menu container*/\n className?: string;\n /** when true, menu will open on first render */\n defaultOpen?: boolean;\n /** when true, menu borders are rounded */\n hasRoundedBorders?: boolean;\n /**\n * Optional stable ID for SSR scenarios. If not provided, a unique ID will be generated.\n * This helps prevent hydration mismatches when using SSR.\n */\n id?: string;\n /** Enable menu custom content vs MenuItem children */\n isCustomContent?: boolean;\n /** initial menu placement */\n menuPlacement?: Placement;\n /** custom menu width */\n menuSize?: 'sm' | 'md' | 'lg' | 'xl';\n /** number of grid columns required for children */\n numberOfColumns: 1 | 2 | 3;\n /** callback that triggers when the menu is closed */\n onMenuClose?: () => void;\n /** callback that triggers when the menu is opened */\n onMenuOpen?: () => void;\n /** when true, menu will open on hover */\n openOnHover?: boolean;\n /** trigger component to open menu */\n trigger: ReactNode;\n /** additional CSS class name for the trigger */\n triggerClassName?: string;\n};\n\nconst MenuComponent = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>(\n (\n {\n children,\n className,\n defaultOpen,\n hasRoundedBorders = false,\n id,\n isCustomContent,\n menuPlacement,\n menuSize = 'lg',\n numberOfColumns,\n onMenuClose,\n onMenuOpen,\n openOnHover = false,\n trigger,\n triggerClassName,\n ...props\n },\n forwardedRef\n ) => {\n const [isOpen, setIsOpen] = useState(defaultOpen ?? false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const elementsRef = useRef<Array<HTMLSpanElement | null>>([]);\n const labelsRef = useRef<Array<string | null>>([]);\n const parent = useMenuContext();\n const hasMounted = useHasMounted();\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId(id);\n const parentId = useFloatingParentNodeId();\n const item = useListItem();\n\n const isNested = parentId !== null;\n\n const arrowRef = useRef(null);\n\n const { context, floatingStyles, refs } = useFloating<HTMLButtonElement>({\n middleware: [\n offset({ alignmentAxis: -2, mainAxis: isNested ? 2 : 8 }),\n flip(),\n shift({ padding: !isNested ? 2 : 0 }),\n arrow({ element: arrowRef, padding: 5 }),\n ],\n nodeId,\n onOpenChange: (open) => {\n setIsOpen(open);\n if (!open) {\n onMenuClose?.();\n } else {\n onMenuOpen?.();\n }\n },\n open: isOpen,\n placement: isNested ? 'right-start' : (menuPlacement ?? 'bottom'),\n whileElementsMounted: autoUpdate,\n });\n const hover = useHover(context, {\n delay: { open: 75 },\n enabled: isNested || openOnHover,\n handleClose: safePolygon({ blockPointerEvents: true }),\n });\n const click = useClick(context, {\n enabled: !context.dataRef.current.openEvent?.defaultPrevented && !openOnHover,\n event: 'click',\n ignoreMouse: isNested,\n toggle: !isNested,\n });\n\n const role = useRole(context, { role: 'menu' });\n const dismiss = useDismiss(context, { bubbles: true });\n const listNavigation = useListNavigation(context, {\n activeIndex,\n focusItemOnOpen: false,\n listRef: elementsRef,\n nested: isNested,\n onNavigate: setActiveIndex,\n });\n const typeahead = useTypeahead(context, {\n activeIndex,\n enabled: !isCustomContent,\n listRef: labelsRef,\n onMatch: isOpen ? setActiveIndex : undefined,\n });\n\n const { getFloatingProps, getItemProps, getReferenceProps } = useInteractions([\n hover,\n click,\n role,\n dismiss,\n listNavigation,\n typeahead,\n ]);\n\n // Event emitter allows you to communicate across tree components.\n // This effect closes all menus when an item gets clicked anywhere\n // in the tree.\n useEffect(() => {\n if (!tree) {\n return;\n }\n\n function handleTreeClick() {\n setIsOpen(false);\n onMenuClose?.();\n }\n\n function onSubMenuOpen(event: { nodeId: string; parentId: string }) {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false);\n onMenuClose?.();\n }\n }\n\n tree.events.on('click', handleTreeClick);\n tree.events.on('menuopen', onSubMenuOpen);\n\n return () => {\n tree.events.off('click', handleTreeClick);\n tree.events.off('menuopen', onSubMenuOpen);\n };\n }, [tree, nodeId, parentId, onMenuClose]);\n\n useEffect(() => {\n if (isOpen && tree) {\n tree.events.emit('menuopen', { nodeId, parentId });\n }\n }, [tree, isOpen, nodeId, parentId]);\n\n // Strip the three ARIA attrs from the floating-ui reference props so the wrapper span keeps\n // every behavior it had before (refs, click/keyboard handlers, positioning), but no longer\n // carries ARIA that its implicit `generic` role disallows (the axe `aria-allowed-attr`\n // violation). The three ARIA attrs are reapplied to the trigger child via `cloneElement`,\n // landing on a node whose role natively permits them (button / link / menuitem).\n const {\n 'aria-controls': ariaControls,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n ...referencePropsWithoutAria\n } = getReferenceProps(\n parent.getItemProps({\n ...props,\n onClick(event: MouseEvent<HTMLButtonElement>) {\n event.stopPropagation();\n props.onClick?.(event);\n },\n onFocus(event: FocusEvent<HTMLButtonElement>) {\n props.onFocus?.(event);\n },\n })\n ) as Record<string, unknown>;\n\n const triggerIsElement = isValidElement(trigger);\n const triggerElement = trigger as ReactElement;\n const ariaPropsForTrigger: Record<string, unknown> = {};\n if (ariaHasPopup !== undefined) {\n ariaPropsForTrigger['aria-haspopup'] = ariaHasPopup;\n }\n if (ariaExpanded !== undefined) {\n ariaPropsForTrigger['aria-expanded'] = ariaExpanded;\n }\n if (ariaControls !== undefined) {\n ariaPropsForTrigger['aria-controls'] = ariaControls;\n }\n\n // For element triggers, clone the ARIA onto the child (preferred — lands on a node whose role\n // natively permits these attrs). Note: this intentionally overrides any same-named ARIA the\n // caller already set on the trigger; menu disclosure semantics (`aria-haspopup=\"menu\"`) must\n // win for the popup to be announced correctly.\n const clonedTrigger = triggerIsElement ? cloneElement(triggerElement, ariaPropsForTrigger) : trigger;\n\n // For non-element triggers (string / number / null), we cannot clone ARIA anywhere meaningful,\n // so the wrapper span itself becomes the disclosure control. Adding `role=\"button\"` +\n // `tabIndex={0}` makes the ARIA attrs valid (no `aria-allowed-attr` violation) and preserves\n // the screen-reader disclosure pattern. Safe because non-element triggers don't contain a\n // nested interactive element (no `nested-interactive` violation).\n const wrapperFallbackProps = !triggerIsElement ? { ...ariaPropsForTrigger, role: 'button' as const } : {};\n\n return (\n <FloatingNode id={nodeId}>\n <span\n className={cn(\n {\n 'w-full': isNested,\n },\n 'm-0 inline-flex cursor-pointer appearance-none items-center border-none bg-none p-0 text-left no-underline outline-0 hover:no-underline',\n triggerClassName\n )}\n data-testid=\"menu-trigger-wrapper\"\n ref={useMergeRefs([refs.setReference, item.ref, forwardedRef])}\n tabIndex={\n !triggerIsElement ? 0 : !isNested ? undefined : parent.activeIndex === item.index ? 0 : -1\n }\n {...wrapperFallbackProps}\n {...referencePropsWithoutAria}\n >\n {clonedTrigger}\n </span>\n <MenuContext.Provider\n value={{\n activeIndex,\n getItemProps,\n isOpen,\n numberOfColumns,\n setActiveIndex,\n }}\n >\n <FloatingList\n elementsRef={elementsRef}\n labelsRef={labelsRef}\n >\n {isOpen && hasMounted && Boolean(refs.domReference) && (\n <FloatingPortal root={refs.domReference}>\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n modal={false}\n returnFocus={!isNested}\n >\n <div\n className={cn(\n 'Menu relative z-50 w-min cursor-default bg-background-primary py-2 shadow-03 outline-0',\n {\n 'min-w-[200px]': menuSize === 'sm',\n 'min-w-[250px]': menuSize === 'md',\n 'min-w-[300px]': menuSize === 'lg',\n 'min-w-[350px]': menuSize === 'xl',\n 'rounded-md': hasRoundedBorders,\n },\n className\n )}\n data-testid=\"menu-wrapper\"\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n {!isNested && (\n <FloatingArrow\n className=\"fill-background-primary\"\n context={context}\n ref={arrowRef}\n tipRadius={hasRoundedBorders ? 2 : 0}\n />\n )}\n {children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n );\n }\n);\n\nMenuComponent.displayName = 'MenuComponent';\n\nexport const Menu = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent\n {...props}\n ref={ref}\n />\n </FloatingTree>\n );\n }\n\n return (\n <MenuComponent\n {...props}\n ref={ref}\n />\n );\n});\n\nMenu.displayName = 'Menu';\n"],"mappings":"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"}
|
package/Modal-DM0aXJZ5.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal-DM0aXJZ5.d.cts","names":[],"sources":["../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"mappings":";;;KAaK,OAAA;;AAVgF;;;;;;;;;;;;;;;;;;EA8BjF,QAAA,EAAU,SAAS;EACnB,SAAA;EA4DS;;;EAxDT,yBAAA;EAwD4B;;;EApD5B,aAAA;EAoD4B;;;;;;;;;;;;EAtC5B,WAAA,GAAc,eAAA;EAsCc;;;;EAjC5B,eAAA;EAiC4B;;;EA7B5B,gBAAA;EA6B4B;;;EAzB5B,gBAAA;EAyB4B;;;EArB5B,wBAAA;EAqB4B;;;;EAhB5B,QAAA;EA6BI;;
|
|
1
|
+
{"version":3,"file":"Modal-DM0aXJZ5.d.cts","names":[],"sources":["../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"mappings":";;;KAaK,OAAA;;AAVgF;;;;;;;;;;;;;;;;;;EA8BjF,QAAA,EAAU,SAAS;EACnB,SAAA;EA4DS;;;EAxDT,yBAAA;EAwD4B;;;EApD5B,aAAA;EAoD4B;;;;;;;;;;;;EAtC5B,WAAA,GAAc,eAAA;EAsCc;;;;EAjC5B,eAAA;EAiC4B;;;EA7B5B,gBAAA;EA6B4B;;;EAzB5B,gBAAA;EAyB4B;;;EArB5B,wBAAA;EAqB4B;;;;EAhB5B,QAAA;EA6BI;;AAiLP;;;EAxMG,sBAAA;ECvEC;;;ED2ED,IAAA;AAAA;;;;cAMS,eAAA;EAAmB,QAAA;EAAA,SAAA;EAAA,yBAAA;EAAA,eAAA,UAAA;EAAA,WAAA,EAAA,eAAA;EAAA,eAAA;EAAA,gBAAA;EAAA,gBAAA;EAAA,wBAAA;EAAA,QAAA;EAAA,sBAAA;EAAA,IAAA,EAAA;AAAA,GAa7B,OAAA,iCAAK,GAAA,CAAA,OAAA;;;KC9FH,mBAAA;EDAA;;;;;;ECOD,OAAA,GAAU,SAAA;EDkBV;;;ECdA,IAAA,GAAO,SAAA;EDqCP;;;ECjCA,QAAA;EDkDA;;;EC9CA,SAAA;EDwDI;AAMR;;;;ECxDI,aAAA;EDwD4B;;;ECpD5B,QAAA,GAAW,SAAA;EDoDiB;;;;;EC9C5B,KAAA,GAAQ,SAAA;ED2DT;;;ECvDC,IAAA;AAAA;AAAA,KAGC,oBAAA;EDuC2B;;;;;;;;;;;;;;;;;;;ECnB5B,QAAA,EAAU,SAAS;EDgCpB;;;EC5BC,IAAA;AAAA;AAAA,KAGC,KAAA;EACD,SAAA;;AAxEgD;;EA4EhD,yBAAA,GAA4B,cAAA,QAAsB,eAAA;EAnExC;;;EAuEV,aAAA;EA3CiB;;;;;;;;;;;;EAwDjB,WAAA,EAAa,cAAA,QAAsB,eAAA;EApDnC;;AAAI;AAAA;EAyDJ,eAAA;;;;EAIA,gBAAA;EAlCA;;AAAI;EAsCJ,gBAAA;EAnCM;;;EAuCN,wBAAA,GAA2B,cAAA,QAAsB,eAAA;EAjBd;;;;EAsBnC,QAAA,GAAW,cAAA,QAAsB,eAAA;EAAtB;;;;;EAMX,sBAAA,GAAyB,cAAA,QAAsB,eAAA;EAKxB;;;EADvB,IAAA,EAAM,cAAA,QAAsB,eAAA;AAAA,KAC3B,mBAAA,GAAsB,oBAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAAoB;AA6B/C;;cAAa,KAAA;EAAS,SAAA;EAAA,yBAAA;EAAA,eAAA,UAAA;EAAA,WAAA;EAAA,eAAA;EAAA,gBAAA;EAAA,gBAAA;EAAA,wBAAA;EAAA,QAAA;EAAA,sBAAA;EAAA,IAAA;EAAA,GAAA;AAAA,GAanB,KAAA,iCAAK,GAAA,CAAA,OAAA"}
|
package/Modal-DM0aXJZ5.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal-DM0aXJZ5.d.mts","names":[],"sources":["../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"mappings":";;;KAaK,OAAA;;AAVgF;;;;;;;;;;;;;;;;;;EA8BjF,QAAA,EAAU,SAAS;EACnB,SAAA;EA4DS;;;EAxDT,yBAAA;EAwD4B;;;EApD5B,aAAA;EAoD4B;;;;;;;;;;;;EAtC5B,WAAA,GAAc,eAAA;EAsCc;;;;EAjC5B,eAAA;EAiC4B;;;EA7B5B,gBAAA;EA6B4B;;;EAzB5B,gBAAA;EAyB4B;;;EArB5B,wBAAA;EAqB4B;;;;EAhB5B,QAAA;EA6BI;;
|
|
1
|
+
{"version":3,"file":"Modal-DM0aXJZ5.d.mts","names":[],"sources":["../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"mappings":";;;KAaK,OAAA;;AAVgF;;;;;;;;;;;;;;;;;;EA8BjF,QAAA,EAAU,SAAS;EACnB,SAAA;EA4DS;;;EAxDT,yBAAA;EAwD4B;;;EApD5B,aAAA;EAoD4B;;;;;;;;;;;;EAtC5B,WAAA,GAAc,eAAA;EAsCc;;;;EAjC5B,eAAA;EAiC4B;;;EA7B5B,gBAAA;EA6B4B;;;EAzB5B,gBAAA;EAyB4B;;;EArB5B,wBAAA;EAqB4B;;;;EAhB5B,QAAA;EA6BI;;AAiLP;;;EAxMG,sBAAA;ECvEC;;;ED2ED,IAAA;AAAA;;;;cAMS,eAAA;EAAmB,QAAA;EAAA,SAAA;EAAA,yBAAA;EAAA,eAAA,UAAA;EAAA,WAAA,EAAA,eAAA;EAAA,eAAA;EAAA,gBAAA;EAAA,gBAAA;EAAA,wBAAA;EAAA,QAAA;EAAA,sBAAA;EAAA,IAAA,EAAA;AAAA,GAa7B,OAAA,iCAAK,GAAA,CAAA,OAAA;;;KC9FH,mBAAA;EDAA;;;;;;ECOD,OAAA,GAAU,SAAA;EDkBV;;;ECdA,IAAA,GAAO,SAAA;EDqCP;;;ECjCA,QAAA;EDkDA;;;EC9CA,SAAA;EDwDI;AAMR;;;;ECxDI,aAAA;EDwD4B;;;ECpD5B,QAAA,GAAW,SAAA;EDoDiB;;;;;EC9C5B,KAAA,GAAQ,SAAA;ED2DT;;;ECvDC,IAAA;AAAA;AAAA,KAGC,oBAAA;EDuC2B;;;;;;;;;;;;;;;;;;;ECnB5B,QAAA,EAAU,SAAS;EDgCpB;;;EC5BC,IAAA;AAAA;AAAA,KAGC,KAAA;EACD,SAAA;;AAxEgD;;EA4EhD,yBAAA,GAA4B,cAAA,QAAsB,eAAA;EAnExC;;;EAuEV,aAAA;EA3CiB;;;;;;;;;;;;EAwDjB,WAAA,EAAa,cAAA,QAAsB,eAAA;EApDnC;;AAAI;AAAA;EAyDJ,eAAA;;;;EAIA,gBAAA;EAlCA;;AAAI;EAsCJ,gBAAA;EAnCM;;;EAuCN,wBAAA,GAA2B,cAAA,QAAsB,eAAA;EAjBd;;;;EAsBnC,QAAA,GAAW,cAAA,QAAsB,eAAA;EAAtB;;;;;EAMX,sBAAA,GAAyB,cAAA,QAAsB,eAAA;EAKxB;;;EADvB,IAAA,EAAM,cAAA,QAAsB,eAAA;AAAA,KAC3B,mBAAA,GAAsB,oBAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAAoB;AA6B/C;;cAAa,KAAA;EAAS,SAAA;EAAA,yBAAA;EAAA,eAAA,UAAA;EAAA,WAAA;EAAA,eAAA;EAAA,gBAAA;EAAA,gBAAA;EAAA,wBAAA;EAAA,QAAA;EAAA,sBAAA;EAAA,IAAA;EAAA,GAAA;AAAA,GAanB,KAAA,iCAAK,GAAA,CAAA,OAAA"}
|
|
@@ -180,7 +180,8 @@ const ComposableModal = ({ children, className, closeModalOnBackdropClick = true
|
|
|
180
180
|
}, { "animate-fadeOut": modalAnimation === "closing" }, { "group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none": mobileFullScreen }, className),
|
|
181
181
|
"data-hui-id": "Modal",
|
|
182
182
|
"data-testid": dataTestId,
|
|
183
|
-
onAnimationEnd: () => {
|
|
183
|
+
onAnimationEnd: (event) => {
|
|
184
|
+
if (event.target !== event.currentTarget) return;
|
|
184
185
|
if (modalAnimation === "closing") onModalCloseAnimationEnd?.();
|
|
185
186
|
},
|
|
186
187
|
open: show,
|
|
@@ -298,4 +299,4 @@ const Modal = ({ className, closeModalOnBackdropClick, "data-testid": dataTestId
|
|
|
298
299
|
//#endregion
|
|
299
300
|
export { Modal as t };
|
|
300
301
|
|
|
301
|
-
//# sourceMappingURL=Modal-
|
|
302
|
+
//# sourceMappingURL=Modal-DtxWd7Le.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal-C6gatdtT.mjs","names":[],"sources":["../src/Modal/components/Backdrop/Backdrop.tsx","../src/Modal/components/PreventModalScroll/PreventModalScroll.tsx","../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useAtom } from 'jotai';\nimport { ReactNode, useContext, useEffect, useRef } from 'react';\n\nimport { effectEventListener } from '../../../utils/effectEventListener';\nimport { ModalContext } from '../../context';\nimport { useCloseModal } from '../../hooks/useCloseModal';\n\ntype Props = {\n children?: ReactNode;\n closeModalOnBackdropClick?: boolean;\n show: boolean;\n};\n\nexport const Backdrop = ({ children, closeModalOnBackdropClick, show }: Props) => {\n const closeModal = useCloseModal('backdrop');\n const { modalAnimationAtom } = useContext(ModalContext);\n const backdropRef = useRef<HTMLDivElement>(null);\n const [modalAnimation, setModalAnimation] = useAtom(modalAnimationAtom);\n\n // NEEDS A DELAY TO ALLOW THE MODAL TO ANIMATE IN\n useEffect(() => {\n if (show && modalAnimation === '') {\n setModalAnimation('opening');\n }\n }, [modalAnimation, setModalAnimation, show]);\n\n useEffect(() => {\n if (!closeModalOnBackdropClick) {\n return;\n }\n\n return effectEventListener(window, 'mousedown', (event: Event) => {\n if (event.target === backdropRef.current) {\n closeModal();\n }\n });\n }, [closeModal, closeModalOnBackdropClick]);\n\n return (\n <div\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-backdrop opacity-0',\n // OPEN\n {\n 'fixed bottom-0 left-0 right-0 top-0 z-[1001] flex items-center justify-center bg-background-overlay':\n show,\n },\n // GENERAL ANIMATION\n 'transition-opacity duration-200 ease-in',\n // OPEN ANIMATION\n { 'opacity-100': modalAnimation === 'opening' },\n // CLOSE ANIMATION\n { 'opacity-0': modalAnimation === 'closing' }\n )}\n ref={backdropRef}\n >\n {children}\n </div>\n );\n};\n","import { useEffect } from 'react';\n\n// Open modals share a single body scroll-lock. Module-scoped and ref-counted\n// (local deviation from hammer — mirrors Drawer's lock): hammer's per-instance\n// save/restore leaves the body locked forever when two instances overlap\n// (docs pages embedding multiple open modals, auto-reopening stories), because\n// the later instance saves the earlier one's `overflow: hidden` as \"original\".\n// The first instance to mount captures the body's real styles + scroll\n// position; the last to unmount restores them.\nlet openLockCount = 0;\nlet previousBodyStyles: {\n overflow: string;\n paddingRight: string;\n position: string;\n top: string;\n width: string;\n} | null = null;\nlet savedScrollPosition = 0;\nlet iosTouchCleanup: (() => void) | undefined;\n\n/**\n * Prevents scrolling of the page while the modal is open.\n * Uses a unified approach with additional touch event handling for iOS Safari.\n *\n * Can be disabled with `preventScrollWhileOpen={false}` on the `Modal`.\n */\nexport const PreventModalScroll = () => {\n useEffect(() => {\n const body = document.body;\n\n if (openLockCount === 0) {\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n // Store current scroll position and original styles\n savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop;\n previousBodyStyles = {\n overflow: body.style.overflow,\n paddingRight: body.style.paddingRight,\n position: body.style.position,\n top: body.style.top,\n width: body.style.width,\n };\n\n // Calculate scrollbar width and add padding to prevent content shift\n const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;\n if (scrollBarWidth > 0) {\n body.style.paddingRight = `${scrollBarWidth}px`;\n }\n\n // Apply scroll prevention\n body.style.overflow = 'hidden';\n body.style.position = 'fixed';\n body.style.top = `-${savedScrollPosition}px`;\n body.style.width = '100%';\n\n // iOS-specific touch event handling\n if (isIOS) {\n const preventDefault = (e: TouchEvent) => {\n // Allow touch events on modal content but prevent on backdrop\n const target = e.target as Element;\n const isModalContent =\n target.closest('[data-testid=\"modal-content\"]') || target.closest('.hui-modal-container');\n\n if (!isModalContent) {\n e.preventDefault();\n }\n };\n\n // Add touch event listeners for iOS\n document.addEventListener('touchstart', preventDefault, { passive: false });\n document.addEventListener('touchmove', preventDefault, { passive: false });\n\n iosTouchCleanup = () => {\n document.removeEventListener('touchstart', preventDefault);\n document.removeEventListener('touchmove', preventDefault);\n };\n }\n }\n\n openLockCount += 1;\n\n // Cleanup function\n return () => {\n openLockCount -= 1;\n\n if (openLockCount === 0) {\n // Remove iOS touch event listeners if they exist\n iosTouchCleanup?.();\n iosTouchCleanup = undefined;\n\n // Restore original styles\n body.style.overflow = previousBodyStyles?.overflow ?? '';\n body.style.position = previousBodyStyles?.position ?? '';\n body.style.top = previousBodyStyles?.top ?? '';\n body.style.width = previousBodyStyles?.width ?? '';\n body.style.paddingRight = previousBodyStyles?.paddingRight ?? '';\n previousBodyStyles = null;\n\n // Restore scroll position\n window.scrollTo(0, savedScrollPosition);\n }\n };\n }, []);\n\n return null;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useAtom, useAtomValue } from 'jotai';\nimport { atomWithReset } from 'jotai/utils';\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { usePrevious } from '../hooks/usePrevious';\nimport { useWindowIsMobile } from '../providers';\nimport { Backdrop } from './components/Backdrop/Backdrop';\nimport { PreventModalScroll } from './components/PreventModalScroll/PreventModalScroll';\nimport { ModalContext } from './context';\nimport { useCloseModal } from './hooks/useCloseModal';\n\ntype Props = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: boolean;\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n handleClose: (handleCloseData?: any) => void;\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: () => void;\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: 'center' | 'top';\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: boolean;\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: boolean;\n};\n\n/**\n * The actual modal logic. This is the \"composable\" version of the modal.\n */\nexport const ComposableModal = ({\n children,\n className,\n closeModalOnBackdropClick = true,\n 'data-testid': dataTestId,\n handleClose: handleCloseProp,\n hasContentPager = false,\n hasProgressSteps = false,\n mobileFullScreen = false,\n onModalCloseAnimationEnd,\n position = 'center',\n preventScrollWhileOpen = true,\n show: showProp,\n}: Props) => {\n const [modalTarget, setModalTarget] = useState<HTMLElement | null>(null);\n const [show, setShow] = useState(showProp);\n const isMobile = useWindowIsMobile();\n\n const modalAtoms = useMemo(\n () => ({\n closeModalOnBackdropClickAtom: atomWithReset(true),\n isMobileKeyboardOpen: atomWithReset<boolean>(false),\n modalAnimationAtom: atomWithReset<'opening' | 'closing' | ''>(''),\n modalFullScreenAtom: atomWithReset<boolean>(mobileFullScreen),\n modalHasFooterAtom: atomWithReset<boolean>(false),\n modalHasProgressStepsAtom: atomWithReset<boolean>(hasProgressSteps),\n modalRefAtom: atomWithReset<{ current: HTMLDialogElement | null }>({ current: null }),\n scrollTopAtom: atomWithReset(0),\n showBottomScrollHintAtom: atomWithReset<boolean>(false),\n showTopScrollHintAtom: atomWithReset<boolean>(false),\n }),\n [hasProgressSteps, mobileFullScreen]\n );\n\n const modalAnimation = useAtomValue(modalAtoms.modalAnimationAtom);\n const [isMobileKeyboardOpen, setIsMobileKeyboardOpen] = useAtom(modalAtoms.isMobileKeyboardOpen);\n\n const handleClose = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n (handleCloseData?: any) => {\n setShow(false); // Must be triggered before the handleCloseProp\n\n handleCloseProp(handleCloseData);\n },\n [handleCloseProp]\n );\n\n useEffect(() => {\n const target = document.querySelector('.hui-modal-target');\n\n if (!target) {\n throw new Error('Modal target not found, add one in the DOM tree.');\n }\n\n setModalTarget(target as HTMLElement);\n }, []);\n\n const ref = useRef<HTMLDialogElement | null>(null);\n\n const [viewportHeight, setViewportHeight] = useState({ current: 0, initial: 0 });\n\n const updateViewport = useCallback(() => {\n if (typeof window === 'undefined' || typeof window.visualViewport === 'undefined') {\n return;\n }\n\n const currentViewportHeight = window.visualViewport?.height ?? 0;\n\n // Get initial viewport height\n if (viewportHeight.initial === 0) {\n setViewportHeight({\n current: currentViewportHeight,\n initial: window.visualViewport?.height ?? 0,\n });\n } else {\n // Get the difference between the current viewport height and the initial viewport height\n // This is to check if mobile keyboard is open\n const isLessThanInitial = Boolean(currentViewportHeight < viewportHeight.initial);\n setIsMobileKeyboardOpen(isLessThanInitial);\n setViewportHeight((prev) => ({\n current: currentViewportHeight,\n initial: prev.initial,\n }));\n }\n }, [setIsMobileKeyboardOpen, viewportHeight.initial]);\n\n useEffect(() => {\n if (typeof window !== 'undefined' && typeof window.visualViewport !== 'undefined' && isMobile) {\n updateViewport();\n\n window.visualViewport?.addEventListener('resize', updateViewport);\n\n return () => window.visualViewport?.removeEventListener('resize', updateViewport);\n }\n\n return undefined;\n }, [isMobile, updateViewport]);\n\n if (!modalTarget || !show) {\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n </ModalContext.Provider>\n );\n }\n\n const modal = createPortal(\n <Backdrop\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n show={show}\n >\n <dialog\n aria-label=\"Modal\"\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-container group relative flex',\n // OPEN\n 'max-h-[calc(100vh-64px)] w-[588px] flex-col overflow-hidden rounded-md border-none bg-background-primary p-0',\n // MOBILE\n 'xsMax:w-[375px]',\n // SMALL MOBILE\n 'mobileSmall:!w-full',\n // POSITION\n { 'absolute top-lg': position === 'top' },\n // GENERAL ANIMATION\n 'transition-opacity duration-100 ease-in',\n // OPEN ANIMATION\n {\n 'animate-fadeIn': modalAnimation === 'opening' && hasContentPager,\n 'animate-fadeInScaled': modalAnimation === 'opening' && !hasContentPager,\n },\n // CLOSE ANIMATION\n { 'animate-fadeOut': modalAnimation === 'closing' },\n // FULL SCREEN\n {\n 'group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none':\n mobileFullScreen,\n },\n className\n )}\n data-hui-id=\"Modal\"\n data-testid={dataTestId}\n onAnimationEnd={() => {\n if (modalAnimation === 'closing') {\n onModalCloseAnimationEnd?.();\n }\n }}\n open={show}\n ref={ref}\n >\n {preventScrollWhileOpen && <PreventModalScroll />}\n {children}\n <div\n className={cn('relative', {\n // Use CSS :has() selector to immediately apply min-height when footer exists\n // Apply 148px on desktop, 74px on mobile fullscreen\n 'mobile:group-only/fullscreen:has-[#modal-footer.flex]:min-h-[74px] smMin:has-[#modal-footer.flex]:min-h-[148px]':\n hasContentPager,\n // Hide the actions portal when the mobile keyboard is open\n 'mobile:group-only/fullscreen:hidden': isMobileKeyboardOpen && hasContentPager,\n })}\n id=\"modal-actions-portal\"\n />\n </dialog>\n </Backdrop>,\n modalTarget\n );\n\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n {modal}\n </ModalContext.Provider>\n );\n};\n\nconst HandleShowProp = ({\n setShow,\n show,\n showProp,\n}: {\n setShow: (value: boolean) => void;\n show: boolean;\n showProp: boolean;\n}) => {\n const previousShowProp = usePrevious(showProp);\n const closeModal = useCloseModal('setShow set to false');\n\n useEffect(() => {\n if (previousShowProp === undefined) {\n return;\n }\n\n const propChanged = showProp !== previousShowProp;\n if (!propChanged) {\n return;\n }\n\n const showMustChange = show !== showProp;\n if (!showMustChange) {\n return;\n }\n if (showProp) {\n setShow(true);\n } else {\n closeModal();\n }\n }, [show, previousShowProp, showProp, closeModal, setShow]);\n\n return null;\n};\n","import { ComponentProps, ReactNode } from 'react';\n\nimport {\n BackButton,\n CloseButton,\n ModalActions,\n ModalContent,\n ModalHeader,\n ModalSubTitle,\n ModalTitle,\n} from './components';\nimport { ComposableModal } from './ComposableModal';\n\ntype TemplatedModalProps = {\n /**\n * This is the actions of the modal. Usually buttons.\n * It is rendered at the bottom of the modal.\n *\n * `ModalActions` is not rendered if this is not passed.\n */\n actions?: ReactNode;\n /**\n * This is the main content of the modal.\n */\n body?: ReactNode;\n /**\n * If you want to pass children, set `type=\"composable\"`.\n */\n children?: never;\n /**\n * If true, the close button will not be shown.\n */\n hideClose?: boolean;\n /**\n * This is a callback that is called when the back button is clicked.\n *\n * When passed, the back button will be shown.\n */\n onBackClicked?: () => void;\n /**\n * If passed, this will be shown as a subtitle in the modal.\n */\n subtitle?: ReactNode;\n /**\n * If passed, this will be shown as a title in the modal.\n *\n * `ModalHeader` is not rendered if this is not passed.\n */\n title?: ReactNode;\n /**\n * Marks the type of modal as templated / simple.\n */\n type?: 'templated';\n};\n\ntype ComposableModalProps = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n /**\n * Marks the type of modal as composable.\n */\n type: 'composable';\n};\n\ntype Props = {\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: ComponentProps<typeof ComposableModal>['closeModalOnBackdropClick'];\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n handleClose: ComponentProps<typeof ComposableModal>['handleClose'];\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: ComponentProps<typeof ComposableModal>['onModalCloseAnimationEnd'];\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: ComponentProps<typeof ComposableModal>['position'];\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: ComponentProps<typeof ComposableModal>['preventScrollWhileOpen'];\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: ComponentProps<typeof ComposableModal>['show'];\n} & (TemplatedModalProps | ComposableModalProps);\n\n/**\n * Primary component for creating modals.\n * When rendered, it automatically opens the modal and backdrop.\n *\n * These preprovided components give you the styles of the modal.\n *\n * By default, you get a particular preset of the `Modal` component that is used for simple modals.\n * It has (optionally) a title, subtitle, body, and actions.\n *\n * If you need to get a little bit more custom, be sure to read the docs and add `type=\"composable\"` to the this component.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\nexport const Modal = ({\n className,\n closeModalOnBackdropClick,\n 'data-testid': dataTestId,\n handleClose,\n hasContentPager,\n hasProgressSteps,\n mobileFullScreen,\n onModalCloseAnimationEnd,\n position,\n preventScrollWhileOpen,\n show,\n ...rest\n}: Props) => {\n if (rest.type === 'composable') {\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {rest.children}\n </ComposableModal>\n );\n }\n\n const { actions, body, hideClose, onBackClicked, subtitle, title } = rest;\n\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {onBackClicked && <BackButton onClick={onBackClicked} />}\n {!hideClose && <CloseButton />}\n {Boolean(title) && (\n <ModalHeader>\n <ModalTitle>{title}</ModalTitle>\n </ModalHeader>\n )}\n <ModalContent>\n {Boolean(subtitle) && <ModalSubTitle>{subtitle}</ModalSubTitle>}\n {Boolean(body) && body}\n </ModalContent>\n {Boolean(actions) && <ModalActions>{actions}</ModalActions>}\n </ComposableModal>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Modal-DtxWd7Le.mjs","names":[],"sources":["../src/Modal/components/Backdrop/Backdrop.tsx","../src/Modal/components/PreventModalScroll/PreventModalScroll.tsx","../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useAtom } from 'jotai';\nimport { ReactNode, useContext, useEffect, useRef } from 'react';\n\nimport { effectEventListener } from '../../../utils/effectEventListener';\nimport { ModalContext } from '../../context';\nimport { useCloseModal } from '../../hooks/useCloseModal';\n\ntype Props = {\n children?: ReactNode;\n closeModalOnBackdropClick?: boolean;\n show: boolean;\n};\n\nexport const Backdrop = ({ children, closeModalOnBackdropClick, show }: Props) => {\n const closeModal = useCloseModal('backdrop');\n const { modalAnimationAtom } = useContext(ModalContext);\n const backdropRef = useRef<HTMLDivElement>(null);\n const [modalAnimation, setModalAnimation] = useAtom(modalAnimationAtom);\n\n // NEEDS A DELAY TO ALLOW THE MODAL TO ANIMATE IN\n useEffect(() => {\n if (show && modalAnimation === '') {\n setModalAnimation('opening');\n }\n }, [modalAnimation, setModalAnimation, show]);\n\n useEffect(() => {\n if (!closeModalOnBackdropClick) {\n return;\n }\n\n return effectEventListener(window, 'mousedown', (event: Event) => {\n if (event.target === backdropRef.current) {\n closeModal();\n }\n });\n }, [closeModal, closeModalOnBackdropClick]);\n\n return (\n <div\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-backdrop opacity-0',\n // OPEN\n {\n 'fixed bottom-0 left-0 right-0 top-0 z-[1001] flex items-center justify-center bg-background-overlay':\n show,\n },\n // GENERAL ANIMATION\n 'transition-opacity duration-200 ease-in',\n // OPEN ANIMATION\n { 'opacity-100': modalAnimation === 'opening' },\n // CLOSE ANIMATION\n { 'opacity-0': modalAnimation === 'closing' }\n )}\n ref={backdropRef}\n >\n {children}\n </div>\n );\n};\n","import { useEffect } from 'react';\n\n// Open modals share a single body scroll-lock. Module-scoped and ref-counted\n// (local deviation from hammer — mirrors Drawer's lock): hammer's per-instance\n// save/restore leaves the body locked forever when two instances overlap\n// (docs pages embedding multiple open modals, auto-reopening stories), because\n// the later instance saves the earlier one's `overflow: hidden` as \"original\".\n// The first instance to mount captures the body's real styles + scroll\n// position; the last to unmount restores them.\nlet openLockCount = 0;\nlet previousBodyStyles: {\n overflow: string;\n paddingRight: string;\n position: string;\n top: string;\n width: string;\n} | null = null;\nlet savedScrollPosition = 0;\nlet iosTouchCleanup: (() => void) | undefined;\n\n/**\n * Prevents scrolling of the page while the modal is open.\n * Uses a unified approach with additional touch event handling for iOS Safari.\n *\n * Can be disabled with `preventScrollWhileOpen={false}` on the `Modal`.\n */\nexport const PreventModalScroll = () => {\n useEffect(() => {\n const body = document.body;\n\n if (openLockCount === 0) {\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n // Store current scroll position and original styles\n savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop;\n previousBodyStyles = {\n overflow: body.style.overflow,\n paddingRight: body.style.paddingRight,\n position: body.style.position,\n top: body.style.top,\n width: body.style.width,\n };\n\n // Calculate scrollbar width and add padding to prevent content shift\n const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;\n if (scrollBarWidth > 0) {\n body.style.paddingRight = `${scrollBarWidth}px`;\n }\n\n // Apply scroll prevention\n body.style.overflow = 'hidden';\n body.style.position = 'fixed';\n body.style.top = `-${savedScrollPosition}px`;\n body.style.width = '100%';\n\n // iOS-specific touch event handling\n if (isIOS) {\n const preventDefault = (e: TouchEvent) => {\n // Allow touch events on modal content but prevent on backdrop\n const target = e.target as Element;\n const isModalContent =\n target.closest('[data-testid=\"modal-content\"]') || target.closest('.hui-modal-container');\n\n if (!isModalContent) {\n e.preventDefault();\n }\n };\n\n // Add touch event listeners for iOS\n document.addEventListener('touchstart', preventDefault, { passive: false });\n document.addEventListener('touchmove', preventDefault, { passive: false });\n\n iosTouchCleanup = () => {\n document.removeEventListener('touchstart', preventDefault);\n document.removeEventListener('touchmove', preventDefault);\n };\n }\n }\n\n openLockCount += 1;\n\n // Cleanup function\n return () => {\n openLockCount -= 1;\n\n if (openLockCount === 0) {\n // Remove iOS touch event listeners if they exist\n iosTouchCleanup?.();\n iosTouchCleanup = undefined;\n\n // Restore original styles\n body.style.overflow = previousBodyStyles?.overflow ?? '';\n body.style.position = previousBodyStyles?.position ?? '';\n body.style.top = previousBodyStyles?.top ?? '';\n body.style.width = previousBodyStyles?.width ?? '';\n body.style.paddingRight = previousBodyStyles?.paddingRight ?? '';\n previousBodyStyles = null;\n\n // Restore scroll position\n window.scrollTo(0, savedScrollPosition);\n }\n };\n }, []);\n\n return null;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useAtom, useAtomValue } from 'jotai';\nimport { atomWithReset } from 'jotai/utils';\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { usePrevious } from '../hooks/usePrevious';\nimport { useWindowIsMobile } from '../providers';\nimport { Backdrop } from './components/Backdrop/Backdrop';\nimport { PreventModalScroll } from './components/PreventModalScroll/PreventModalScroll';\nimport { ModalContext } from './context';\nimport { useCloseModal } from './hooks/useCloseModal';\n\ntype Props = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: boolean;\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n handleClose: (handleCloseData?: any) => void;\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: () => void;\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: 'center' | 'top';\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: boolean;\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: boolean;\n};\n\n/**\n * The actual modal logic. This is the \"composable\" version of the modal.\n */\nexport const ComposableModal = ({\n children,\n className,\n closeModalOnBackdropClick = true,\n 'data-testid': dataTestId,\n handleClose: handleCloseProp,\n hasContentPager = false,\n hasProgressSteps = false,\n mobileFullScreen = false,\n onModalCloseAnimationEnd,\n position = 'center',\n preventScrollWhileOpen = true,\n show: showProp,\n}: Props) => {\n const [modalTarget, setModalTarget] = useState<HTMLElement | null>(null);\n const [show, setShow] = useState(showProp);\n const isMobile = useWindowIsMobile();\n\n const modalAtoms = useMemo(\n () => ({\n closeModalOnBackdropClickAtom: atomWithReset(true),\n isMobileKeyboardOpen: atomWithReset<boolean>(false),\n modalAnimationAtom: atomWithReset<'opening' | 'closing' | ''>(''),\n modalFullScreenAtom: atomWithReset<boolean>(mobileFullScreen),\n modalHasFooterAtom: atomWithReset<boolean>(false),\n modalHasProgressStepsAtom: atomWithReset<boolean>(hasProgressSteps),\n modalRefAtom: atomWithReset<{ current: HTMLDialogElement | null }>({ current: null }),\n scrollTopAtom: atomWithReset(0),\n showBottomScrollHintAtom: atomWithReset<boolean>(false),\n showTopScrollHintAtom: atomWithReset<boolean>(false),\n }),\n [hasProgressSteps, mobileFullScreen]\n );\n\n const modalAnimation = useAtomValue(modalAtoms.modalAnimationAtom);\n const [isMobileKeyboardOpen, setIsMobileKeyboardOpen] = useAtom(modalAtoms.isMobileKeyboardOpen);\n\n const handleClose = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n (handleCloseData?: any) => {\n setShow(false); // Must be triggered before the handleCloseProp\n\n handleCloseProp(handleCloseData);\n },\n [handleCloseProp]\n );\n\n useEffect(() => {\n const target = document.querySelector('.hui-modal-target');\n\n if (!target) {\n throw new Error('Modal target not found, add one in the DOM tree.');\n }\n\n setModalTarget(target as HTMLElement);\n }, []);\n\n const ref = useRef<HTMLDialogElement | null>(null);\n\n const [viewportHeight, setViewportHeight] = useState({ current: 0, initial: 0 });\n\n const updateViewport = useCallback(() => {\n if (typeof window === 'undefined' || typeof window.visualViewport === 'undefined') {\n return;\n }\n\n const currentViewportHeight = window.visualViewport?.height ?? 0;\n\n // Get initial viewport height\n if (viewportHeight.initial === 0) {\n setViewportHeight({\n current: currentViewportHeight,\n initial: window.visualViewport?.height ?? 0,\n });\n } else {\n // Get the difference between the current viewport height and the initial viewport height\n // This is to check if mobile keyboard is open\n const isLessThanInitial = Boolean(currentViewportHeight < viewportHeight.initial);\n setIsMobileKeyboardOpen(isLessThanInitial);\n setViewportHeight((prev) => ({\n current: currentViewportHeight,\n initial: prev.initial,\n }));\n }\n }, [setIsMobileKeyboardOpen, viewportHeight.initial]);\n\n useEffect(() => {\n if (typeof window !== 'undefined' && typeof window.visualViewport !== 'undefined' && isMobile) {\n updateViewport();\n\n window.visualViewport?.addEventListener('resize', updateViewport);\n\n return () => window.visualViewport?.removeEventListener('resize', updateViewport);\n }\n\n return undefined;\n }, [isMobile, updateViewport]);\n\n if (!modalTarget || !show) {\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n </ModalContext.Provider>\n );\n }\n\n const modal = createPortal(\n <Backdrop\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n show={show}\n >\n <dialog\n aria-label=\"Modal\"\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-container group relative flex',\n // OPEN\n 'max-h-[calc(100vh-64px)] w-[588px] flex-col overflow-hidden rounded-md border-none bg-background-primary p-0',\n // MOBILE\n 'xsMax:w-[375px]',\n // SMALL MOBILE\n 'mobileSmall:!w-full',\n // POSITION\n { 'absolute top-lg': position === 'top' },\n // GENERAL ANIMATION\n 'transition-opacity duration-100 ease-in',\n // OPEN ANIMATION\n {\n 'animate-fadeIn': modalAnimation === 'opening' && hasContentPager,\n 'animate-fadeInScaled': modalAnimation === 'opening' && !hasContentPager,\n },\n // CLOSE ANIMATION\n { 'animate-fadeOut': modalAnimation === 'closing' },\n // FULL SCREEN\n {\n 'group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none':\n mobileFullScreen,\n },\n className\n )}\n data-hui-id=\"Modal\"\n data-testid={dataTestId}\n onAnimationEnd={(event) => {\n // `animationend` bubbles, so only the dialog's own close animation counts.\n // Under `prefers-reduced-motion: reduce` every animation collapses to ~1ms,\n // which compresses descendant completions into the same tick as the close —\n // without this check an animated child could close the modal early.\n if (event.target !== event.currentTarget) {\n return;\n }\n\n if (modalAnimation === 'closing') {\n onModalCloseAnimationEnd?.();\n }\n }}\n open={show}\n ref={ref}\n >\n {preventScrollWhileOpen && <PreventModalScroll />}\n {children}\n <div\n className={cn('relative', {\n // Use CSS :has() selector to immediately apply min-height when footer exists\n // Apply 148px on desktop, 74px on mobile fullscreen\n 'mobile:group-only/fullscreen:has-[#modal-footer.flex]:min-h-[74px] smMin:has-[#modal-footer.flex]:min-h-[148px]':\n hasContentPager,\n // Hide the actions portal when the mobile keyboard is open\n 'mobile:group-only/fullscreen:hidden': isMobileKeyboardOpen && hasContentPager,\n })}\n id=\"modal-actions-portal\"\n />\n </dialog>\n </Backdrop>,\n modalTarget\n );\n\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n {modal}\n </ModalContext.Provider>\n );\n};\n\nconst HandleShowProp = ({\n setShow,\n show,\n showProp,\n}: {\n setShow: (value: boolean) => void;\n show: boolean;\n showProp: boolean;\n}) => {\n const previousShowProp = usePrevious(showProp);\n const closeModal = useCloseModal('setShow set to false');\n\n useEffect(() => {\n if (previousShowProp === undefined) {\n return;\n }\n\n const propChanged = showProp !== previousShowProp;\n if (!propChanged) {\n return;\n }\n\n const showMustChange = show !== showProp;\n if (!showMustChange) {\n return;\n }\n if (showProp) {\n setShow(true);\n } else {\n closeModal();\n }\n }, [show, previousShowProp, showProp, closeModal, setShow]);\n\n return null;\n};\n","import { ComponentProps, ReactNode } from 'react';\n\nimport {\n BackButton,\n CloseButton,\n ModalActions,\n ModalContent,\n ModalHeader,\n ModalSubTitle,\n ModalTitle,\n} from './components';\nimport { ComposableModal } from './ComposableModal';\n\ntype TemplatedModalProps = {\n /**\n * This is the actions of the modal. Usually buttons.\n * It is rendered at the bottom of the modal.\n *\n * `ModalActions` is not rendered if this is not passed.\n */\n actions?: ReactNode;\n /**\n * This is the main content of the modal.\n */\n body?: ReactNode;\n /**\n * If you want to pass children, set `type=\"composable\"`.\n */\n children?: never;\n /**\n * If true, the close button will not be shown.\n */\n hideClose?: boolean;\n /**\n * This is a callback that is called when the back button is clicked.\n *\n * When passed, the back button will be shown.\n */\n onBackClicked?: () => void;\n /**\n * If passed, this will be shown as a subtitle in the modal.\n */\n subtitle?: ReactNode;\n /**\n * If passed, this will be shown as a title in the modal.\n *\n * `ModalHeader` is not rendered if this is not passed.\n */\n title?: ReactNode;\n /**\n * Marks the type of modal as templated / simple.\n */\n type?: 'templated';\n};\n\ntype ComposableModalProps = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n /**\n * Marks the type of modal as composable.\n */\n type: 'composable';\n};\n\ntype Props = {\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: ComponentProps<typeof ComposableModal>['closeModalOnBackdropClick'];\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n handleClose: ComponentProps<typeof ComposableModal>['handleClose'];\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: ComponentProps<typeof ComposableModal>['onModalCloseAnimationEnd'];\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: ComponentProps<typeof ComposableModal>['position'];\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: ComponentProps<typeof ComposableModal>['preventScrollWhileOpen'];\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: ComponentProps<typeof ComposableModal>['show'];\n} & (TemplatedModalProps | ComposableModalProps);\n\n/**\n * Primary component for creating modals.\n * When rendered, it automatically opens the modal and backdrop.\n *\n * These preprovided components give you the styles of the modal.\n *\n * By default, you get a particular preset of the `Modal` component that is used for simple modals.\n * It has (optionally) a title, subtitle, body, and actions.\n *\n * If you need to get a little bit more custom, be sure to read the docs and add `type=\"composable\"` to the this component.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\nexport const Modal = ({\n className,\n closeModalOnBackdropClick,\n 'data-testid': dataTestId,\n handleClose,\n hasContentPager,\n hasProgressSteps,\n mobileFullScreen,\n onModalCloseAnimationEnd,\n position,\n preventScrollWhileOpen,\n show,\n ...rest\n}: Props) => {\n if (rest.type === 'composable') {\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {rest.children}\n </ComposableModal>\n );\n }\n\n const { actions, body, hideClose, onBackClicked, subtitle, title } = rest;\n\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {onBackClicked && <BackButton onClick={onBackClicked} />}\n {!hideClose && <CloseButton />}\n {Boolean(title) && (\n <ModalHeader>\n <ModalTitle>{title}</ModalTitle>\n </ModalHeader>\n )}\n <ModalContent>\n {Boolean(subtitle) && <ModalSubTitle>{subtitle}</ModalSubTitle>}\n {Boolean(body) && body}\n </ModalContent>\n {Boolean(actions) && <ModalActions>{actions}</ModalActions>}\n </ComposableModal>\n );\n};\n"],"mappings":"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"}
|
|
@@ -180,7 +180,8 @@ const ComposableModal = ({ children, className, closeModalOnBackdropClick = true
|
|
|
180
180
|
}, { "animate-fadeOut": modalAnimation === "closing" }, { "group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none": mobileFullScreen }, className),
|
|
181
181
|
"data-hui-id": "Modal",
|
|
182
182
|
"data-testid": dataTestId,
|
|
183
|
-
onAnimationEnd: () => {
|
|
183
|
+
onAnimationEnd: (event) => {
|
|
184
|
+
if (event.target !== event.currentTarget) return;
|
|
184
185
|
if (modalAnimation === "closing") onModalCloseAnimationEnd?.();
|
|
185
186
|
},
|
|
186
187
|
open: show,
|
|
@@ -303,4 +304,4 @@ Object.defineProperty(exports, "Modal", {
|
|
|
303
304
|
}
|
|
304
305
|
});
|
|
305
306
|
|
|
306
|
-
//# sourceMappingURL=Modal-
|
|
307
|
+
//# sourceMappingURL=Modal-q4HhBAQU.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal-q4HhBAQU.cjs","names":["useCloseModal","ModalContext","effectEventListener","useWindowIsMobile","ModalContext","usePrevious","useCloseModal","BackButton","CloseButton","ModalHeader","ModalTitle","ModalContent","ModalSubTitle","ModalActions"],"sources":["../src/Modal/components/Backdrop/Backdrop.tsx","../src/Modal/components/PreventModalScroll/PreventModalScroll.tsx","../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useAtom } from 'jotai';\nimport { ReactNode, useContext, useEffect, useRef } from 'react';\n\nimport { effectEventListener } from '../../../utils/effectEventListener';\nimport { ModalContext } from '../../context';\nimport { useCloseModal } from '../../hooks/useCloseModal';\n\ntype Props = {\n children?: ReactNode;\n closeModalOnBackdropClick?: boolean;\n show: boolean;\n};\n\nexport const Backdrop = ({ children, closeModalOnBackdropClick, show }: Props) => {\n const closeModal = useCloseModal('backdrop');\n const { modalAnimationAtom } = useContext(ModalContext);\n const backdropRef = useRef<HTMLDivElement>(null);\n const [modalAnimation, setModalAnimation] = useAtom(modalAnimationAtom);\n\n // NEEDS A DELAY TO ALLOW THE MODAL TO ANIMATE IN\n useEffect(() => {\n if (show && modalAnimation === '') {\n setModalAnimation('opening');\n }\n }, [modalAnimation, setModalAnimation, show]);\n\n useEffect(() => {\n if (!closeModalOnBackdropClick) {\n return;\n }\n\n return effectEventListener(window, 'mousedown', (event: Event) => {\n if (event.target === backdropRef.current) {\n closeModal();\n }\n });\n }, [closeModal, closeModalOnBackdropClick]);\n\n return (\n <div\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-backdrop opacity-0',\n // OPEN\n {\n 'fixed bottom-0 left-0 right-0 top-0 z-[1001] flex items-center justify-center bg-background-overlay':\n show,\n },\n // GENERAL ANIMATION\n 'transition-opacity duration-200 ease-in',\n // OPEN ANIMATION\n { 'opacity-100': modalAnimation === 'opening' },\n // CLOSE ANIMATION\n { 'opacity-0': modalAnimation === 'closing' }\n )}\n ref={backdropRef}\n >\n {children}\n </div>\n );\n};\n","import { useEffect } from 'react';\n\n// Open modals share a single body scroll-lock. Module-scoped and ref-counted\n// (local deviation from hammer — mirrors Drawer's lock): hammer's per-instance\n// save/restore leaves the body locked forever when two instances overlap\n// (docs pages embedding multiple open modals, auto-reopening stories), because\n// the later instance saves the earlier one's `overflow: hidden` as \"original\".\n// The first instance to mount captures the body's real styles + scroll\n// position; the last to unmount restores them.\nlet openLockCount = 0;\nlet previousBodyStyles: {\n overflow: string;\n paddingRight: string;\n position: string;\n top: string;\n width: string;\n} | null = null;\nlet savedScrollPosition = 0;\nlet iosTouchCleanup: (() => void) | undefined;\n\n/**\n * Prevents scrolling of the page while the modal is open.\n * Uses a unified approach with additional touch event handling for iOS Safari.\n *\n * Can be disabled with `preventScrollWhileOpen={false}` on the `Modal`.\n */\nexport const PreventModalScroll = () => {\n useEffect(() => {\n const body = document.body;\n\n if (openLockCount === 0) {\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n // Store current scroll position and original styles\n savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop;\n previousBodyStyles = {\n overflow: body.style.overflow,\n paddingRight: body.style.paddingRight,\n position: body.style.position,\n top: body.style.top,\n width: body.style.width,\n };\n\n // Calculate scrollbar width and add padding to prevent content shift\n const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;\n if (scrollBarWidth > 0) {\n body.style.paddingRight = `${scrollBarWidth}px`;\n }\n\n // Apply scroll prevention\n body.style.overflow = 'hidden';\n body.style.position = 'fixed';\n body.style.top = `-${savedScrollPosition}px`;\n body.style.width = '100%';\n\n // iOS-specific touch event handling\n if (isIOS) {\n const preventDefault = (e: TouchEvent) => {\n // Allow touch events on modal content but prevent on backdrop\n const target = e.target as Element;\n const isModalContent =\n target.closest('[data-testid=\"modal-content\"]') || target.closest('.hui-modal-container');\n\n if (!isModalContent) {\n e.preventDefault();\n }\n };\n\n // Add touch event listeners for iOS\n document.addEventListener('touchstart', preventDefault, { passive: false });\n document.addEventListener('touchmove', preventDefault, { passive: false });\n\n iosTouchCleanup = () => {\n document.removeEventListener('touchstart', preventDefault);\n document.removeEventListener('touchmove', preventDefault);\n };\n }\n }\n\n openLockCount += 1;\n\n // Cleanup function\n return () => {\n openLockCount -= 1;\n\n if (openLockCount === 0) {\n // Remove iOS touch event listeners if they exist\n iosTouchCleanup?.();\n iosTouchCleanup = undefined;\n\n // Restore original styles\n body.style.overflow = previousBodyStyles?.overflow ?? '';\n body.style.position = previousBodyStyles?.position ?? '';\n body.style.top = previousBodyStyles?.top ?? '';\n body.style.width = previousBodyStyles?.width ?? '';\n body.style.paddingRight = previousBodyStyles?.paddingRight ?? '';\n previousBodyStyles = null;\n\n // Restore scroll position\n window.scrollTo(0, savedScrollPosition);\n }\n };\n }, []);\n\n return null;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useAtom, useAtomValue } from 'jotai';\nimport { atomWithReset } from 'jotai/utils';\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { usePrevious } from '../hooks/usePrevious';\nimport { useWindowIsMobile } from '../providers';\nimport { Backdrop } from './components/Backdrop/Backdrop';\nimport { PreventModalScroll } from './components/PreventModalScroll/PreventModalScroll';\nimport { ModalContext } from './context';\nimport { useCloseModal } from './hooks/useCloseModal';\n\ntype Props = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: boolean;\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n handleClose: (handleCloseData?: any) => void;\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: () => void;\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: 'center' | 'top';\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: boolean;\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: boolean;\n};\n\n/**\n * The actual modal logic. This is the \"composable\" version of the modal.\n */\nexport const ComposableModal = ({\n children,\n className,\n closeModalOnBackdropClick = true,\n 'data-testid': dataTestId,\n handleClose: handleCloseProp,\n hasContentPager = false,\n hasProgressSteps = false,\n mobileFullScreen = false,\n onModalCloseAnimationEnd,\n position = 'center',\n preventScrollWhileOpen = true,\n show: showProp,\n}: Props) => {\n const [modalTarget, setModalTarget] = useState<HTMLElement | null>(null);\n const [show, setShow] = useState(showProp);\n const isMobile = useWindowIsMobile();\n\n const modalAtoms = useMemo(\n () => ({\n closeModalOnBackdropClickAtom: atomWithReset(true),\n isMobileKeyboardOpen: atomWithReset<boolean>(false),\n modalAnimationAtom: atomWithReset<'opening' | 'closing' | ''>(''),\n modalFullScreenAtom: atomWithReset<boolean>(mobileFullScreen),\n modalHasFooterAtom: atomWithReset<boolean>(false),\n modalHasProgressStepsAtom: atomWithReset<boolean>(hasProgressSteps),\n modalRefAtom: atomWithReset<{ current: HTMLDialogElement | null }>({ current: null }),\n scrollTopAtom: atomWithReset(0),\n showBottomScrollHintAtom: atomWithReset<boolean>(false),\n showTopScrollHintAtom: atomWithReset<boolean>(false),\n }),\n [hasProgressSteps, mobileFullScreen]\n );\n\n const modalAnimation = useAtomValue(modalAtoms.modalAnimationAtom);\n const [isMobileKeyboardOpen, setIsMobileKeyboardOpen] = useAtom(modalAtoms.isMobileKeyboardOpen);\n\n const handleClose = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n (handleCloseData?: any) => {\n setShow(false); // Must be triggered before the handleCloseProp\n\n handleCloseProp(handleCloseData);\n },\n [handleCloseProp]\n );\n\n useEffect(() => {\n const target = document.querySelector('.hui-modal-target');\n\n if (!target) {\n throw new Error('Modal target not found, add one in the DOM tree.');\n }\n\n setModalTarget(target as HTMLElement);\n }, []);\n\n const ref = useRef<HTMLDialogElement | null>(null);\n\n const [viewportHeight, setViewportHeight] = useState({ current: 0, initial: 0 });\n\n const updateViewport = useCallback(() => {\n if (typeof window === 'undefined' || typeof window.visualViewport === 'undefined') {\n return;\n }\n\n const currentViewportHeight = window.visualViewport?.height ?? 0;\n\n // Get initial viewport height\n if (viewportHeight.initial === 0) {\n setViewportHeight({\n current: currentViewportHeight,\n initial: window.visualViewport?.height ?? 0,\n });\n } else {\n // Get the difference between the current viewport height and the initial viewport height\n // This is to check if mobile keyboard is open\n const isLessThanInitial = Boolean(currentViewportHeight < viewportHeight.initial);\n setIsMobileKeyboardOpen(isLessThanInitial);\n setViewportHeight((prev) => ({\n current: currentViewportHeight,\n initial: prev.initial,\n }));\n }\n }, [setIsMobileKeyboardOpen, viewportHeight.initial]);\n\n useEffect(() => {\n if (typeof window !== 'undefined' && typeof window.visualViewport !== 'undefined' && isMobile) {\n updateViewport();\n\n window.visualViewport?.addEventListener('resize', updateViewport);\n\n return () => window.visualViewport?.removeEventListener('resize', updateViewport);\n }\n\n return undefined;\n }, [isMobile, updateViewport]);\n\n if (!modalTarget || !show) {\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n </ModalContext.Provider>\n );\n }\n\n const modal = createPortal(\n <Backdrop\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n show={show}\n >\n <dialog\n aria-label=\"Modal\"\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-container group relative flex',\n // OPEN\n 'max-h-[calc(100vh-64px)] w-[588px] flex-col overflow-hidden rounded-md border-none bg-background-primary p-0',\n // MOBILE\n 'xsMax:w-[375px]',\n // SMALL MOBILE\n 'mobileSmall:!w-full',\n // POSITION\n { 'absolute top-lg': position === 'top' },\n // GENERAL ANIMATION\n 'transition-opacity duration-100 ease-in',\n // OPEN ANIMATION\n {\n 'animate-fadeIn': modalAnimation === 'opening' && hasContentPager,\n 'animate-fadeInScaled': modalAnimation === 'opening' && !hasContentPager,\n },\n // CLOSE ANIMATION\n { 'animate-fadeOut': modalAnimation === 'closing' },\n // FULL SCREEN\n {\n 'group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none':\n mobileFullScreen,\n },\n className\n )}\n data-hui-id=\"Modal\"\n data-testid={dataTestId}\n onAnimationEnd={(event) => {\n // `animationend` bubbles, so only the dialog's own close animation counts.\n // Under `prefers-reduced-motion: reduce` every animation collapses to ~1ms,\n // which compresses descendant completions into the same tick as the close —\n // without this check an animated child could close the modal early.\n if (event.target !== event.currentTarget) {\n return;\n }\n\n if (modalAnimation === 'closing') {\n onModalCloseAnimationEnd?.();\n }\n }}\n open={show}\n ref={ref}\n >\n {preventScrollWhileOpen && <PreventModalScroll />}\n {children}\n <div\n className={cn('relative', {\n // Use CSS :has() selector to immediately apply min-height when footer exists\n // Apply 148px on desktop, 74px on mobile fullscreen\n 'mobile:group-only/fullscreen:has-[#modal-footer.flex]:min-h-[74px] smMin:has-[#modal-footer.flex]:min-h-[148px]':\n hasContentPager,\n // Hide the actions portal when the mobile keyboard is open\n 'mobile:group-only/fullscreen:hidden': isMobileKeyboardOpen && hasContentPager,\n })}\n id=\"modal-actions-portal\"\n />\n </dialog>\n </Backdrop>,\n modalTarget\n );\n\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n {modal}\n </ModalContext.Provider>\n );\n};\n\nconst HandleShowProp = ({\n setShow,\n show,\n showProp,\n}: {\n setShow: (value: boolean) => void;\n show: boolean;\n showProp: boolean;\n}) => {\n const previousShowProp = usePrevious(showProp);\n const closeModal = useCloseModal('setShow set to false');\n\n useEffect(() => {\n if (previousShowProp === undefined) {\n return;\n }\n\n const propChanged = showProp !== previousShowProp;\n if (!propChanged) {\n return;\n }\n\n const showMustChange = show !== showProp;\n if (!showMustChange) {\n return;\n }\n if (showProp) {\n setShow(true);\n } else {\n closeModal();\n }\n }, [show, previousShowProp, showProp, closeModal, setShow]);\n\n return null;\n};\n","import { ComponentProps, ReactNode } from 'react';\n\nimport {\n BackButton,\n CloseButton,\n ModalActions,\n ModalContent,\n ModalHeader,\n ModalSubTitle,\n ModalTitle,\n} from './components';\nimport { ComposableModal } from './ComposableModal';\n\ntype TemplatedModalProps = {\n /**\n * This is the actions of the modal. Usually buttons.\n * It is rendered at the bottom of the modal.\n *\n * `ModalActions` is not rendered if this is not passed.\n */\n actions?: ReactNode;\n /**\n * This is the main content of the modal.\n */\n body?: ReactNode;\n /**\n * If you want to pass children, set `type=\"composable\"`.\n */\n children?: never;\n /**\n * If true, the close button will not be shown.\n */\n hideClose?: boolean;\n /**\n * This is a callback that is called when the back button is clicked.\n *\n * When passed, the back button will be shown.\n */\n onBackClicked?: () => void;\n /**\n * If passed, this will be shown as a subtitle in the modal.\n */\n subtitle?: ReactNode;\n /**\n * If passed, this will be shown as a title in the modal.\n *\n * `ModalHeader` is not rendered if this is not passed.\n */\n title?: ReactNode;\n /**\n * Marks the type of modal as templated / simple.\n */\n type?: 'templated';\n};\n\ntype ComposableModalProps = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n /**\n * Marks the type of modal as composable.\n */\n type: 'composable';\n};\n\ntype Props = {\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: ComponentProps<typeof ComposableModal>['closeModalOnBackdropClick'];\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n handleClose: ComponentProps<typeof ComposableModal>['handleClose'];\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: ComponentProps<typeof ComposableModal>['onModalCloseAnimationEnd'];\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: ComponentProps<typeof ComposableModal>['position'];\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: ComponentProps<typeof ComposableModal>['preventScrollWhileOpen'];\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: ComponentProps<typeof ComposableModal>['show'];\n} & (TemplatedModalProps | ComposableModalProps);\n\n/**\n * Primary component for creating modals.\n * When rendered, it automatically opens the modal and backdrop.\n *\n * These preprovided components give you the styles of the modal.\n *\n * By default, you get a particular preset of the `Modal` component that is used for simple modals.\n * It has (optionally) a title, subtitle, body, and actions.\n *\n * If you need to get a little bit more custom, be sure to read the docs and add `type=\"composable\"` to the this component.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\nexport const Modal = ({\n className,\n closeModalOnBackdropClick,\n 'data-testid': dataTestId,\n handleClose,\n hasContentPager,\n hasProgressSteps,\n mobileFullScreen,\n onModalCloseAnimationEnd,\n position,\n preventScrollWhileOpen,\n show,\n ...rest\n}: Props) => {\n if (rest.type === 'composable') {\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {rest.children}\n </ComposableModal>\n );\n }\n\n const { actions, body, hideClose, onBackClicked, subtitle, title } = rest;\n\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {onBackClicked && <BackButton onClick={onBackClicked} />}\n {!hideClose && <CloseButton />}\n {Boolean(title) && (\n <ModalHeader>\n <ModalTitle>{title}</ModalTitle>\n </ModalHeader>\n )}\n <ModalContent>\n {Boolean(subtitle) && <ModalSubTitle>{subtitle}</ModalSubTitle>}\n {Boolean(body) && body}\n </ModalContent>\n {Boolean(actions) && <ModalActions>{actions}</ModalActions>}\n </ComposableModal>\n );\n};\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ const require_Icons = require("./Icons.cjs");
|
|
|
2
2
|
const require_Typography_Text = require("./Typography/Text.cjs");
|
|
3
3
|
const require_windowSizeProvider = require("./windowSizeProvider-BMaATFiZ.cjs");
|
|
4
4
|
const require_IconButton = require("./IconButton.cjs");
|
|
5
|
-
const require_Select = require("./Select-
|
|
5
|
+
const require_Select = require("./Select-DCCcyLT4.cjs");
|
|
6
6
|
let _evolve_ui_theme_system = require("@evolve.ui/theme-system");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -406,4 +406,4 @@ Object.defineProperty(exports, "usePagination", {
|
|
|
406
406
|
}
|
|
407
407
|
});
|
|
408
408
|
|
|
409
|
-
//# sourceMappingURL=Pagination-
|
|
409
|
+
//# sourceMappingURL=Pagination-Denb9_zB.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination-bAtbN478.cjs","names":["useWindowIsDesktop","BodyPrimary","IconButton","CaretLeft","CaretRight","components","Select","IconButton","CaretLeft","BodyPrimary","CaretRight","BodyPrimary","Select"],"sources":["../src/Pagination/paginationProvider.tsx","../src/Pagination/utils.tsx","../src/Pagination/Pagination.tsx","../src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx","../src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx","../src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx","../src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx","../src/Pagination/AdvancedPagination.tsx"],"sourcesContent":["import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nexport type CurrentPaginationState = Omit<\n PaginationState,\n 'goToNextPage' | 'goToPage' | 'headInfoUpdateCallback' | 'onPageChange' | 'onPageSizeChange' | 'setPageSize'\n>;\nexport type PageSizeOptions = number | 'all';\n\ntype CommonValues = {\n /**\n * This prop allows you to control how the urls for the links are formatted.\n *\n * By default, they're just `?page=PAGE`,\n * (omitted as necessary)\n * but you can append to that using this object.\n *\n * @see https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading#avoid-indexing-variations\n */\n extraQueryParams?: Record<string, string>;\n /**\n * The path of the current location\n *\n * IE if url = example.com/search?page=3\n * `path` = /search\n */\n path: string;\n};\n\nexport type PaginationState = CommonValues & {\n /**\n * Defacto method of changing pages. Does not route.\n * See PaginationProvider's `onPageChange` to handle these changes.\n *\n * Pagination components use this.\n *\n * @param page Page number to go to\n */\n goToPage: (page: number) => void;\n /**\n * Default page size.\n */\n initialPageSize: PageSizeOptions;\n /**\n * Passes down the `itemCount` given to PaginationProvider\n */\n itemCount: number;\n /**\n * This should always be one indexed\n *\n * Remember pages are `1` indexed NOT `0` indexed.\n */\n page: number;\n /** The total number of pages */\n pageCount: number;\n /** The current page size */\n pageSize: PageSizeOptions;\n /** The current page size options. */\n pageSizeOptions: PageSizeOptions[];\n /**\n * Defacto method of changing page size.\n * See PaginationProvider's `onPageSizeChange` to handle these changes.\n *\n * Pagination components use this. (None implemented right now)\n *\n * @param page Page number to jump to\n */\n setPageSize: (pageSize: PageSizeOptions) => void;\n};\n\nconst PaginationContext = createContext<PaginationState>({\n extraQueryParams: {},\n goToPage: () => 0,\n initialPageSize: 24,\n itemCount: 1,\n page: 1,\n pageCount: 1,\n pageSize: 24,\n pageSizeOptions: [],\n path: '',\n setPageSize: () => 0,\n});\n\ntype Props = CommonValues & {\n children: ReactNode;\n /** The current page number. This is used if you wish to control the page number externally.*/\n currentPage?: number;\n /**\n * The current page size. Use this to control page size externally (e.g. from URL params).\n * Mirrors `currentPage` behaviour — when this value changes, the internal `pageSize` state\n * updates to match without remounting the provider.\n *\n * **Note**: `onPageSizeChange` is not fired when `currentPageSize` drives the update. Adjusting currentPage is the user/developer responsibility.\n */\n currentPageSize?: PageSizeOptions;\n /**\n * Default value for page. Does not affect anything past the first render.\n *\n * Remember pages are `1` indexed NOT `0` indexed.\n */\n initialPage?: number;\n /**\n * Default value for pageSize. Does not affect anything past the first render.\n */\n initialPageSize?: PageSizeOptions;\n /**\n * The total number of items you're paginating over. This is usually provided by the API.\n *\n * Internally, it's only used to determine the number of pages with `Math.ceil(itemCount / pageSize)`\n */\n itemCount: number;\n /**\n * Callback that runs when something changes page. Useful for updating your API call / routing.\n *\n * You can also just listen with the `usePagination` hook.\n */\n onPageChange?: (currentPaginationState: CurrentPaginationState) => void;\n /**\n * Callback that runs when something changes pageSize. Useful for updating your API call / routing.\n *\n * You can also just listen with the `usePagination` hook.\n */\n onPageSizeChange?: (currentPaginationState: CurrentPaginationState) => void;\n /** */\n pageSizeOptions?: PageSizeOptions[];\n};\n\n/**\n * `1` based pagination logic provider\n */\nexport const PaginationProvider = ({\n children,\n currentPage,\n currentPageSize,\n extraQueryParams,\n initialPage = 1,\n initialPageSize = 24,\n itemCount,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [],\n path,\n}: Props) => {\n const [page, setPage] = useState<number>(Math.max(initialPage, 1));\n const [pageSize, _setPageSize] = useState<PageSizeOptions>(initialPageSize);\n\n const pageCount = useMemo(\n () => (pageSize === 'all' ? 1 : Math.max(Math.ceil(itemCount / pageSize), 1)),\n [itemCount, pageSize]\n );\n\n const dataValues = useMemo(\n () => ({\n extraQueryParams,\n initialPageSize,\n itemCount,\n page,\n pageCount,\n pageSize,\n pageSizeOptions,\n path,\n }),\n [extraQueryParams, initialPageSize, itemCount, page, pageCount, pageSize, path, pageSizeOptions]\n );\n\n // If page is changed externally, update the page number to reflect the current page inside the component\n // This will changed the component to be more controlled.\n useEffect(() => {\n if (currentPage && currentPage !== page) {\n setPage(currentPage);\n }\n }, [currentPage, page]);\n\n useEffect(() => {\n if (currentPageSize !== undefined && currentPageSize !== pageSize) {\n _setPageSize(currentPageSize);\n }\n }, [currentPageSize, pageSize]);\n\n const goToPage = useCallback(\n (newPage: number) => {\n setPage(newPage);\n onPageChange?.({ ...dataValues, page: newPage });\n },\n [dataValues, onPageChange]\n );\n\n const setPageSize = useCallback(\n (newPageSize: PageSizeOptions) => {\n _setPageSize(newPageSize);\n\n // Set page to highest possible page if we're on a page that's too high\n if (newPageSize === 'all') {\n setPage(1);\n } else {\n // Make sure page is least 1 since we're doing 1 indexed.\n const newPageCount = Math.max(Math.ceil(itemCount / newPageSize), 1);\n\n if (page > newPageCount) {\n setPage(newPageCount);\n }\n }\n\n onPageSizeChange?.({ ...dataValues, pageSize: newPageSize });\n },\n [dataValues, itemCount, onPageSizeChange, page]\n );\n\n const value: PaginationState = useMemo(\n () => ({\n ...dataValues,\n goToPage,\n setPageSize,\n }),\n [dataValues, goToPage, setPageSize]\n );\n\n return <PaginationContext.Provider value={value}>{children}</PaginationContext.Provider>;\n};\n\n/**\n * Provides access to all these values\n * ```tsx\n * goToPage: (page: number) => void;\n * initialPageSize: PageSizeOptions; // number | 'all'\n * items: number;\n * page: number;\n * pageCount: number;\n * pageSize: PageSizeOptions; // number | 'all'\n * setPageSize: (pageSize: PageSizeOptions) => void;\n * ```\n *\n * @see https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading\n */\nexport const usePagination = () => useContext(PaginationContext);\n","import { cloneDeep, merge } from 'es-toolkit';\nimport { useCallback } from 'react';\n\nimport { CurrentPaginationState, usePagination } from './paginationProvider';\n\nexport const usePaginationQueryParams = () => {\n const currentPaginationState = usePagination();\n\n const buildQueryParams = useCallback(\n (newState: Partial<CurrentPaginationState>): string => {\n const { extraQueryParams, page, path } = merge(cloneDeep(currentPaginationState), newState);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: params values are stringified below regardless of source type\n const params: Record<string, any> = {\n ...extraQueryParams,\n };\n\n if (page !== 1) {\n params.page = page;\n }\n\n if (Object.keys(params).length === 0) {\n return path;\n }\n\n const cleanedParams = Object.fromEntries(\n Object.entries(params).map(([key, value]) => [key, value.toString()])\n );\n\n return `${path.startsWith('/') ? '' : '/'}${path}?${new URLSearchParams(cleanedParams).toString()}`;\n },\n [currentPaginationState]\n );\n\n return buildQueryParams;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useMemo } from 'react';\n\nimport { IconButton } from '../IconButton/IconButton';\nimport { CaretLeft, CaretRight } from '../Icons';\nimport { useWindowIsDesktop } from '../providers';\nimport { BodyPrimary } from '../Typography/Text/Text';\nimport { usePagination } from './paginationProvider';\nimport { usePaginationQueryParams } from './utils';\n\nconst ellipsis = '...' as const;\n\ntype Props = {\n /**\n * This prop is useful when multiple paginations are on the same page.\n *\n * For instance, if a page had a \"featured items\" section\n * and a \"recent activity\" section, you might want to label one as\n * \"Featured Items Pagination\" and the other as \"Recent Activity Pagination\"\n */\n 'aria-label'?: string;\n className?: string;\n /** aria-label applied to the collapsed-pages ellipsis element. */\n collapsedPagesLabel?: string;\n /** aria-label for the next-page button (only applied when not disabled). */\n nextPageLabel?: string;\n /** Returns the aria-label for a specific page anchor. Receives the page number. */\n pageLabel?: (page: number) => string;\n /** aria-label for the previous-page button (only applied when not disabled). */\n previousPageLabel?: string;\n};\n\n/**\n * `1` based pagination component\n *\n * @see https://www.a11ymatters.com/pattern/pagination/\n */\nexport const Pagination = ({\n 'aria-label': ariaLabel = 'Pagination Navigation',\n className,\n collapsedPagesLabel = 'Collapsed pages',\n nextPageLabel = 'Next Page',\n pageLabel = (page) => `Page ${page}`,\n previousPageLabel = 'Previous Page',\n}: Props) => {\n const { goToPage, page, pageCount } = usePagination();\n const isDesktop = useWindowIsDesktop();\n const buildQueryParams = usePaginationQueryParams();\n\n const pageList = useMemo<(typeof ellipsis | number)[]>(() => {\n let max = isDesktop ? 9 : 6;\n const leftEllipsis = pageCount > max + 1 && page > 5;\n if (leftEllipsis && isDesktop) {\n max += 1;\n }\n\n const increment = isDesktop ? 3 : 1;\n const theRestFits = page - increment + (max - 3) >= pageCount;\n let pageCounter = leftEllipsis ? (theRestFits ? pageCount - (max - 3) - 1 : page - increment) : 2;\n\n const resultingPages: (typeof ellipsis | number)[] = [1];\n let pagesAdded = 1;\n\n if (leftEllipsis) {\n pagesAdded += 1;\n resultingPages.push(ellipsis);\n }\n\n while (pagesAdded < max && pageCounter <= pageCount) {\n resultingPages.push(pageCounter);\n\n if (pagesAdded === max - 2 && pageCounter + 2 <= pageCount) {\n if (pageCounter + 2 === pageCount) {\n resultingPages.push(pageCount - 1);\n } else {\n resultingPages.push(ellipsis);\n }\n resultingPages.push(pageCount);\n break;\n }\n\n pageCounter += 1;\n pagesAdded += 1;\n }\n\n return resultingPages;\n }, [isDesktop, page, pageCount]);\n\n const renderedList = useMemo(() => {\n return pageList.map((item, index) => {\n return (\n <li\n className={cn({\n 'flex h-[34px] min-w-[34px] items-center justify-center': item === ellipsis,\n })}\n key={`pagination-${item}-${index}`}\n >\n {item === ellipsis ? (\n <BodyPrimary\n aria-label={collapsedPagesLabel}\n className=\"text-link-disabled\"\n >\n {item}\n </BodyPrimary>\n ) : (\n <a\n aria-current={item === page ? 'page' : undefined}\n aria-label={pageLabel(item)}\n className={cn(\n 'hui-text-body-secondary flex h-[34px] min-w-[34px] items-center justify-center rounded-full px-xs',\n // FOCUS\n 'hui-focus-visible-outline',\n // HOVER\n 'hover:bg-background-hover',\n // CURRENT\n {\n 'hui-text-label-strong border-2 border-border-selected text-link-primary':\n item === page,\n }\n )}\n href={buildQueryParams({ page: item })}\n key={`content-${item}-index-${index}`}\n onClick={(e) => {\n e.preventDefault();\n goToPage(item);\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={\n page - 1 === item && item !== 1\n ? 'prev'\n : page + 1 === item && item !== pageCount\n ? 'next'\n : undefined\n }\n >\n {item}\n </a>\n )}\n </li>\n );\n });\n }, [buildQueryParams, collapsedPagesLabel, goToPage, page, pageCount, pageLabel, pageList]);\n\n const previousPage = useMemo(() => {\n const disabled = page === 1;\n return (\n <li\n className=\"mr-sm\"\n key={`previous-page-${page}`}\n >\n <IconButton\n aria-disabled={disabled}\n aria-label={disabled ? undefined : previousPageLabel}\n as={disabled ? 'button' : 'a'}\n data-testid=\"pagination-previous-page\"\n disabled={disabled}\n href={disabled ? undefined : buildQueryParams({ page: page - 1 })}\n icon={CaretLeft}\n onClick={(event) => {\n event.preventDefault();\n if (!disabled) {\n goToPage(page - 1);\n }\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={disabled ? undefined : 'prev'}\n size=\"sm\"\n variant=\"outlined\"\n />\n </li>\n );\n }, [buildQueryParams, goToPage, page, previousPageLabel]);\n\n const nextPage = useMemo(() => {\n const disabled = page === pageCount;\n return (\n <li\n className=\"ml-sm\"\n key={`next-page-${page}`}\n >\n <IconButton\n aria-disabled={disabled}\n aria-label={disabled ? undefined : nextPageLabel}\n as={disabled ? 'button' : 'a'}\n data-testid=\"pagination-next-page\"\n disabled={disabled}\n href={disabled ? undefined : buildQueryParams({ page: page + 1 })}\n icon={CaretRight}\n onClick={(event) => {\n event.preventDefault();\n if (!disabled) {\n goToPage(page + 1);\n }\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={disabled ? undefined : 'next'}\n size=\"sm\"\n variant=\"outlined\"\n />\n </li>\n );\n }, [buildQueryParams, goToPage, nextPageLabel, page, pageCount]);\n\n return (\n <nav\n aria-label={ariaLabel}\n className={className}\n >\n <ul className=\"flex gap-2xs\">\n {previousPage}\n {renderedList}\n {nextPage}\n </ul>\n </nav>\n );\n};\n","import { useMemo } from 'react';\nimport { components, SingleValueProps } from 'react-select';\n\nimport { OptionType, Select } from '../../../../../Select/Select';\nimport { usePagination } from '../../../../paginationProvider';\n\nconst SingleValue = ({ children, ...props }: SingleValueProps) => {\n return <components.SingleValue {...props}>{children}</components.SingleValue>;\n};\n\nexport const PageSelect = () => {\n const { goToPage, page, pageCount } = usePagination();\n\n const options = useMemo(\n () =>\n new Array(pageCount).fill(0).map((_, i) => ({\n label: `${i + 1}`,\n value: i + 1,\n })),\n [pageCount]\n );\n\n return (\n <Select\n autoComplete=\"off\"\n className=\"pl-sm\"\n components={{ SingleValue }}\n defaultValue={pageCount}\n isInsideLabel\n labelText=\"Page:\"\n onChange={(event?: OptionType) => goToPage(event?.value)}\n options={options}\n small\n styles={{\n singleValue: (base) => ({\n ...base,\n overflow: 'visible',\n }),\n }}\n value={options[page - 1]}\n />\n );\n};\n","import { IconButton } from '../../../IconButton/IconButton';\nimport { CaretLeft, CaretRight } from '../../../Icons';\nimport { BodyPrimary } from '../../../Typography/Text/Text';\nimport { usePagination } from '../../paginationProvider';\nimport { PageSelect } from './components/PageSelect/PageSelect';\n\ntype Props = {\n /** aria-label for the next-page button. */\n nextPageLabel?: string;\n /** Renders the page-count suffix. Receives total page count. */\n ofLabel?: (pageCount: number) => string;\n /** aria-label for the previous-page button. */\n previousPageLabel?: string;\n};\n\nexport const AdvancedPaginator = ({\n nextPageLabel = 'Next Page',\n ofLabel = (pageCount) => `of ${pageCount}`,\n previousPageLabel = 'Previous Page',\n}: Props) => {\n const { goToPage, page, pageCount } = usePagination();\n\n return (\n <div className=\"flex items-center\">\n <IconButton\n aria-label={previousPageLabel}\n data-testid=\"previous-page\"\n disabled={page === 1}\n icon={CaretLeft}\n onClick={() => {\n if (page !== 1) {\n goToPage(page - 1);\n }\n }}\n size=\"sm\"\n />\n <PageSelect /> <BodyPrimary className=\"whitespace-nowrap px-xs\">{ofLabel(pageCount)}</BodyPrimary>\n <IconButton\n aria-label={nextPageLabel}\n data-testid=\"next-page\"\n disabled={page === pageCount}\n icon={CaretRight}\n onClick={() => {\n if (page !== pageCount) {\n goToPage(page + 1);\n }\n }}\n size=\"sm\"\n />\n </div>\n );\n};\n","import { BodyPrimary } from '../../../Typography/Text/Text';\nimport { usePagination } from '../../paginationProvider';\n\nexport type ItemRangeLabelArgs = { end: number; start: number; total: number };\n\ntype Props = {\n /** Renders the label when all items are shown (pageSize === 'all'). Receives total item count. */\n allItemsLabel?: (itemCount: number) => string;\n /** Renders the label for a paginated range. Receives start, end, and total item count. */\n itemRangeLabel?: (args: ItemRangeLabelArgs) => string;\n};\n\nexport const ItemCountDisplay = ({\n allItemsLabel = (itemCount) => `${itemCount} Items`,\n itemRangeLabel = ({ end, start, total }) => `${start} - ${end} of ${total}`,\n}: Props) => {\n const { itemCount, page, pageSize } = usePagination();\n\n if (pageSize === 'all') {\n return <BodyPrimary>{allItemsLabel(itemCount)}</BodyPrimary>;\n }\n\n return (\n <BodyPrimary>\n {itemRangeLabel({\n end: Math.min(page * pageSize, itemCount),\n start: (page - 1) * pageSize + 1,\n total: itemCount,\n })}\n </BodyPrimary>\n );\n};\n","import { useMemo } from 'react';\n\nimport { OptionType, Select } from '../../../Select/Select';\nimport { usePagination } from '../../paginationProvider';\n\ntype Props = {\n /** Label text for the results-per-page select input. */\n resultsPerPageLabel?: string;\n};\n\nexport const ItemCountSelect = ({ resultsPerPageLabel = 'Results per page:' }: Props) => {\n const { pageSize, pageSizeOptions, setPageSize } = usePagination();\n\n const generatedOptions: OptionType[] = useMemo(() => {\n return pageSizeOptions.map((option) => {\n return { label: option.toString(), value: option };\n });\n }, [pageSizeOptions]);\n\n return (\n <Select\n autoComplete=\"off\"\n className=\"mr-sm w-[224px]\"\n defaultValue={pageSize}\n isInsideLabel\n labelText={resultsPerPageLabel}\n onChange={(event?: OptionType) => setPageSize(event?.value)}\n options={generatedOptions}\n small\n value={{ label: pageSize, value: pageSize }}\n />\n );\n};\n","import { cn } from '@evolve.ui/theme-system';\n\nimport { AdvancedPaginator } from './components/AdvancedPaginator/AdvancedPaginator';\nimport { ItemCountDisplay, ItemRangeLabelArgs } from './components/ItemCountDisplay/ItemCountDisplay';\nimport { ItemCountSelect } from './components/ItemCountSelect/ItemCountSelect';\n\ntype Props = {\n /** Renders the label when all items are shown (pageSize === 'all'). Forwarded to ItemCountDisplay. */\n allItemsLabel?: (itemCount: number) => string;\n className?: string;\n /** Renders the label for a paginated range. Forwarded to ItemCountDisplay. */\n itemRangeLabel?: (args: ItemRangeLabelArgs) => string;\n /** aria-label for the next-page button. Forwarded to AdvancedPaginator. */\n nextPageLabel?: string;\n /** Renders the page-count suffix. Forwarded to AdvancedPaginator. */\n ofLabel?: (pageCount: number) => string;\n /** aria-label for the previous-page button. Forwarded to AdvancedPaginator. */\n previousPageLabel?: string;\n /** Label text for the results-per-page select input. Forwarded to ItemCountSelect. */\n resultsPerPageLabel?: string;\n};\n\nexport const AdvancedPagination = ({\n allItemsLabel,\n className,\n itemRangeLabel,\n nextPageLabel,\n ofLabel,\n previousPageLabel,\n resultsPerPageLabel,\n}: Props) => {\n return (\n <div className={cn('flex items-center justify-between p-sm', className)}>\n <AdvancedPaginator\n nextPageLabel={nextPageLabel}\n ofLabel={ofLabel}\n previousPageLabel={previousPageLabel}\n />\n <div className=\"flex items-center\">\n <ItemCountSelect resultsPerPageLabel={resultsPerPageLabel} />\n <ItemCountDisplay\n allItemsLabel={allItemsLabel}\n itemRangeLabel={itemRangeLabel}\n />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Pagination-Denb9_zB.cjs","names":["useWindowIsDesktop","BodyPrimary","IconButton","CaretLeft","CaretRight","components","Select","IconButton","CaretLeft","BodyPrimary","CaretRight","BodyPrimary","Select"],"sources":["../src/Pagination/paginationProvider.tsx","../src/Pagination/utils.tsx","../src/Pagination/Pagination.tsx","../src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx","../src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx","../src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx","../src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx","../src/Pagination/AdvancedPagination.tsx"],"sourcesContent":["import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nexport type CurrentPaginationState = Omit<\n PaginationState,\n 'goToNextPage' | 'goToPage' | 'headInfoUpdateCallback' | 'onPageChange' | 'onPageSizeChange' | 'setPageSize'\n>;\nexport type PageSizeOptions = number | 'all';\n\ntype CommonValues = {\n /**\n * This prop allows you to control how the urls for the links are formatted.\n *\n * By default, they're just `?page=PAGE`,\n * (omitted as necessary)\n * but you can append to that using this object.\n *\n * @see https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading#avoid-indexing-variations\n */\n extraQueryParams?: Record<string, string>;\n /**\n * The path of the current location\n *\n * IE if url = example.com/search?page=3\n * `path` = /search\n */\n path: string;\n};\n\nexport type PaginationState = CommonValues & {\n /**\n * Defacto method of changing pages. Does not route.\n * See PaginationProvider's `onPageChange` to handle these changes.\n *\n * Pagination components use this.\n *\n * @param page Page number to go to\n */\n goToPage: (page: number) => void;\n /**\n * Default page size.\n */\n initialPageSize: PageSizeOptions;\n /**\n * Passes down the `itemCount` given to PaginationProvider\n */\n itemCount: number;\n /**\n * This should always be one indexed\n *\n * Remember pages are `1` indexed NOT `0` indexed.\n */\n page: number;\n /** The total number of pages */\n pageCount: number;\n /** The current page size */\n pageSize: PageSizeOptions;\n /** The current page size options. */\n pageSizeOptions: PageSizeOptions[];\n /**\n * Defacto method of changing page size.\n * See PaginationProvider's `onPageSizeChange` to handle these changes.\n *\n * Pagination components use this. (None implemented right now)\n *\n * @param page Page number to jump to\n */\n setPageSize: (pageSize: PageSizeOptions) => void;\n};\n\nconst PaginationContext = createContext<PaginationState>({\n extraQueryParams: {},\n goToPage: () => 0,\n initialPageSize: 24,\n itemCount: 1,\n page: 1,\n pageCount: 1,\n pageSize: 24,\n pageSizeOptions: [],\n path: '',\n setPageSize: () => 0,\n});\n\ntype Props = CommonValues & {\n children: ReactNode;\n /** The current page number. This is used if you wish to control the page number externally.*/\n currentPage?: number;\n /**\n * The current page size. Use this to control page size externally (e.g. from URL params).\n * Mirrors `currentPage` behaviour — when this value changes, the internal `pageSize` state\n * updates to match without remounting the provider.\n *\n * **Note**: `onPageSizeChange` is not fired when `currentPageSize` drives the update. Adjusting currentPage is the user/developer responsibility.\n */\n currentPageSize?: PageSizeOptions;\n /**\n * Default value for page. Does not affect anything past the first render.\n *\n * Remember pages are `1` indexed NOT `0` indexed.\n */\n initialPage?: number;\n /**\n * Default value for pageSize. Does not affect anything past the first render.\n */\n initialPageSize?: PageSizeOptions;\n /**\n * The total number of items you're paginating over. This is usually provided by the API.\n *\n * Internally, it's only used to determine the number of pages with `Math.ceil(itemCount / pageSize)`\n */\n itemCount: number;\n /**\n * Callback that runs when something changes page. Useful for updating your API call / routing.\n *\n * You can also just listen with the `usePagination` hook.\n */\n onPageChange?: (currentPaginationState: CurrentPaginationState) => void;\n /**\n * Callback that runs when something changes pageSize. Useful for updating your API call / routing.\n *\n * You can also just listen with the `usePagination` hook.\n */\n onPageSizeChange?: (currentPaginationState: CurrentPaginationState) => void;\n /** */\n pageSizeOptions?: PageSizeOptions[];\n};\n\n/**\n * `1` based pagination logic provider\n */\nexport const PaginationProvider = ({\n children,\n currentPage,\n currentPageSize,\n extraQueryParams,\n initialPage = 1,\n initialPageSize = 24,\n itemCount,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [],\n path,\n}: Props) => {\n const [page, setPage] = useState<number>(Math.max(initialPage, 1));\n const [pageSize, _setPageSize] = useState<PageSizeOptions>(initialPageSize);\n\n const pageCount = useMemo(\n () => (pageSize === 'all' ? 1 : Math.max(Math.ceil(itemCount / pageSize), 1)),\n [itemCount, pageSize]\n );\n\n const dataValues = useMemo(\n () => ({\n extraQueryParams,\n initialPageSize,\n itemCount,\n page,\n pageCount,\n pageSize,\n pageSizeOptions,\n path,\n }),\n [extraQueryParams, initialPageSize, itemCount, page, pageCount, pageSize, path, pageSizeOptions]\n );\n\n // If page is changed externally, update the page number to reflect the current page inside the component\n // This will changed the component to be more controlled.\n useEffect(() => {\n if (currentPage && currentPage !== page) {\n setPage(currentPage);\n }\n }, [currentPage, page]);\n\n useEffect(() => {\n if (currentPageSize !== undefined && currentPageSize !== pageSize) {\n _setPageSize(currentPageSize);\n }\n }, [currentPageSize, pageSize]);\n\n const goToPage = useCallback(\n (newPage: number) => {\n setPage(newPage);\n onPageChange?.({ ...dataValues, page: newPage });\n },\n [dataValues, onPageChange]\n );\n\n const setPageSize = useCallback(\n (newPageSize: PageSizeOptions) => {\n _setPageSize(newPageSize);\n\n // Set page to highest possible page if we're on a page that's too high\n if (newPageSize === 'all') {\n setPage(1);\n } else {\n // Make sure page is least 1 since we're doing 1 indexed.\n const newPageCount = Math.max(Math.ceil(itemCount / newPageSize), 1);\n\n if (page > newPageCount) {\n setPage(newPageCount);\n }\n }\n\n onPageSizeChange?.({ ...dataValues, pageSize: newPageSize });\n },\n [dataValues, itemCount, onPageSizeChange, page]\n );\n\n const value: PaginationState = useMemo(\n () => ({\n ...dataValues,\n goToPage,\n setPageSize,\n }),\n [dataValues, goToPage, setPageSize]\n );\n\n return <PaginationContext.Provider value={value}>{children}</PaginationContext.Provider>;\n};\n\n/**\n * Provides access to all these values\n * ```tsx\n * goToPage: (page: number) => void;\n * initialPageSize: PageSizeOptions; // number | 'all'\n * items: number;\n * page: number;\n * pageCount: number;\n * pageSize: PageSizeOptions; // number | 'all'\n * setPageSize: (pageSize: PageSizeOptions) => void;\n * ```\n *\n * @see https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading\n */\nexport const usePagination = () => useContext(PaginationContext);\n","import { cloneDeep, merge } from 'es-toolkit';\nimport { useCallback } from 'react';\n\nimport { CurrentPaginationState, usePagination } from './paginationProvider';\n\nexport const usePaginationQueryParams = () => {\n const currentPaginationState = usePagination();\n\n const buildQueryParams = useCallback(\n (newState: Partial<CurrentPaginationState>): string => {\n const { extraQueryParams, page, path } = merge(cloneDeep(currentPaginationState), newState);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: params values are stringified below regardless of source type\n const params: Record<string, any> = {\n ...extraQueryParams,\n };\n\n if (page !== 1) {\n params.page = page;\n }\n\n if (Object.keys(params).length === 0) {\n return path;\n }\n\n const cleanedParams = Object.fromEntries(\n Object.entries(params).map(([key, value]) => [key, value.toString()])\n );\n\n return `${path.startsWith('/') ? '' : '/'}${path}?${new URLSearchParams(cleanedParams).toString()}`;\n },\n [currentPaginationState]\n );\n\n return buildQueryParams;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useMemo } from 'react';\n\nimport { IconButton } from '../IconButton/IconButton';\nimport { CaretLeft, CaretRight } from '../Icons';\nimport { useWindowIsDesktop } from '../providers';\nimport { BodyPrimary } from '../Typography/Text/Text';\nimport { usePagination } from './paginationProvider';\nimport { usePaginationQueryParams } from './utils';\n\nconst ellipsis = '...' as const;\n\ntype Props = {\n /**\n * This prop is useful when multiple paginations are on the same page.\n *\n * For instance, if a page had a \"featured items\" section\n * and a \"recent activity\" section, you might want to label one as\n * \"Featured Items Pagination\" and the other as \"Recent Activity Pagination\"\n */\n 'aria-label'?: string;\n className?: string;\n /** aria-label applied to the collapsed-pages ellipsis element. */\n collapsedPagesLabel?: string;\n /** aria-label for the next-page button (only applied when not disabled). */\n nextPageLabel?: string;\n /** Returns the aria-label for a specific page anchor. Receives the page number. */\n pageLabel?: (page: number) => string;\n /** aria-label for the previous-page button (only applied when not disabled). */\n previousPageLabel?: string;\n};\n\n/**\n * `1` based pagination component\n *\n * @see https://www.a11ymatters.com/pattern/pagination/\n */\nexport const Pagination = ({\n 'aria-label': ariaLabel = 'Pagination Navigation',\n className,\n collapsedPagesLabel = 'Collapsed pages',\n nextPageLabel = 'Next Page',\n pageLabel = (page) => `Page ${page}`,\n previousPageLabel = 'Previous Page',\n}: Props) => {\n const { goToPage, page, pageCount } = usePagination();\n const isDesktop = useWindowIsDesktop();\n const buildQueryParams = usePaginationQueryParams();\n\n const pageList = useMemo<(typeof ellipsis | number)[]>(() => {\n let max = isDesktop ? 9 : 6;\n const leftEllipsis = pageCount > max + 1 && page > 5;\n if (leftEllipsis && isDesktop) {\n max += 1;\n }\n\n const increment = isDesktop ? 3 : 1;\n const theRestFits = page - increment + (max - 3) >= pageCount;\n let pageCounter = leftEllipsis ? (theRestFits ? pageCount - (max - 3) - 1 : page - increment) : 2;\n\n const resultingPages: (typeof ellipsis | number)[] = [1];\n let pagesAdded = 1;\n\n if (leftEllipsis) {\n pagesAdded += 1;\n resultingPages.push(ellipsis);\n }\n\n while (pagesAdded < max && pageCounter <= pageCount) {\n resultingPages.push(pageCounter);\n\n if (pagesAdded === max - 2 && pageCounter + 2 <= pageCount) {\n if (pageCounter + 2 === pageCount) {\n resultingPages.push(pageCount - 1);\n } else {\n resultingPages.push(ellipsis);\n }\n resultingPages.push(pageCount);\n break;\n }\n\n pageCounter += 1;\n pagesAdded += 1;\n }\n\n return resultingPages;\n }, [isDesktop, page, pageCount]);\n\n const renderedList = useMemo(() => {\n return pageList.map((item, index) => {\n return (\n <li\n className={cn({\n 'flex h-[34px] min-w-[34px] items-center justify-center': item === ellipsis,\n })}\n key={`pagination-${item}-${index}`}\n >\n {item === ellipsis ? (\n <BodyPrimary\n aria-label={collapsedPagesLabel}\n className=\"text-link-disabled\"\n >\n {item}\n </BodyPrimary>\n ) : (\n <a\n aria-current={item === page ? 'page' : undefined}\n aria-label={pageLabel(item)}\n className={cn(\n 'hui-text-body-secondary flex h-[34px] min-w-[34px] items-center justify-center rounded-full px-xs',\n // FOCUS\n 'hui-focus-visible-outline',\n // HOVER\n 'hover:bg-background-hover',\n // CURRENT\n {\n 'hui-text-label-strong border-2 border-border-selected text-link-primary':\n item === page,\n }\n )}\n href={buildQueryParams({ page: item })}\n key={`content-${item}-index-${index}`}\n onClick={(e) => {\n e.preventDefault();\n goToPage(item);\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={\n page - 1 === item && item !== 1\n ? 'prev'\n : page + 1 === item && item !== pageCount\n ? 'next'\n : undefined\n }\n >\n {item}\n </a>\n )}\n </li>\n );\n });\n }, [buildQueryParams, collapsedPagesLabel, goToPage, page, pageCount, pageLabel, pageList]);\n\n const previousPage = useMemo(() => {\n const disabled = page === 1;\n return (\n <li\n className=\"mr-sm\"\n key={`previous-page-${page}`}\n >\n <IconButton\n aria-disabled={disabled}\n aria-label={disabled ? undefined : previousPageLabel}\n as={disabled ? 'button' : 'a'}\n data-testid=\"pagination-previous-page\"\n disabled={disabled}\n href={disabled ? undefined : buildQueryParams({ page: page - 1 })}\n icon={CaretLeft}\n onClick={(event) => {\n event.preventDefault();\n if (!disabled) {\n goToPage(page - 1);\n }\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={disabled ? undefined : 'prev'}\n size=\"sm\"\n variant=\"outlined\"\n />\n </li>\n );\n }, [buildQueryParams, goToPage, page, previousPageLabel]);\n\n const nextPage = useMemo(() => {\n const disabled = page === pageCount;\n return (\n <li\n className=\"ml-sm\"\n key={`next-page-${page}`}\n >\n <IconButton\n aria-disabled={disabled}\n aria-label={disabled ? undefined : nextPageLabel}\n as={disabled ? 'button' : 'a'}\n data-testid=\"pagination-next-page\"\n disabled={disabled}\n href={disabled ? undefined : buildQueryParams({ page: page + 1 })}\n icon={CaretRight}\n onClick={(event) => {\n event.preventDefault();\n if (!disabled) {\n goToPage(page + 1);\n }\n }}\n // `rel` is not recommended by google's seo guidelines\n rel={disabled ? undefined : 'next'}\n size=\"sm\"\n variant=\"outlined\"\n />\n </li>\n );\n }, [buildQueryParams, goToPage, nextPageLabel, page, pageCount]);\n\n return (\n <nav\n aria-label={ariaLabel}\n className={className}\n >\n <ul className=\"flex gap-2xs\">\n {previousPage}\n {renderedList}\n {nextPage}\n </ul>\n </nav>\n );\n};\n","import { useMemo } from 'react';\nimport { components, SingleValueProps } from 'react-select';\n\nimport { OptionType, Select } from '../../../../../Select/Select';\nimport { usePagination } from '../../../../paginationProvider';\n\nconst SingleValue = ({ children, ...props }: SingleValueProps) => {\n return <components.SingleValue {...props}>{children}</components.SingleValue>;\n};\n\nexport const PageSelect = () => {\n const { goToPage, page, pageCount } = usePagination();\n\n const options = useMemo(\n () =>\n new Array(pageCount).fill(0).map((_, i) => ({\n label: `${i + 1}`,\n value: i + 1,\n })),\n [pageCount]\n );\n\n return (\n <Select\n autoComplete=\"off\"\n className=\"pl-sm\"\n components={{ SingleValue }}\n defaultValue={pageCount}\n isInsideLabel\n labelText=\"Page:\"\n onChange={(event?: OptionType) => goToPage(event?.value)}\n options={options}\n small\n styles={{\n singleValue: (base) => ({\n ...base,\n overflow: 'visible',\n }),\n }}\n value={options[page - 1]}\n />\n );\n};\n","import { IconButton } from '../../../IconButton/IconButton';\nimport { CaretLeft, CaretRight } from '../../../Icons';\nimport { BodyPrimary } from '../../../Typography/Text/Text';\nimport { usePagination } from '../../paginationProvider';\nimport { PageSelect } from './components/PageSelect/PageSelect';\n\ntype Props = {\n /** aria-label for the next-page button. */\n nextPageLabel?: string;\n /** Renders the page-count suffix. Receives total page count. */\n ofLabel?: (pageCount: number) => string;\n /** aria-label for the previous-page button. */\n previousPageLabel?: string;\n};\n\nexport const AdvancedPaginator = ({\n nextPageLabel = 'Next Page',\n ofLabel = (pageCount) => `of ${pageCount}`,\n previousPageLabel = 'Previous Page',\n}: Props) => {\n const { goToPage, page, pageCount } = usePagination();\n\n return (\n <div className=\"flex items-center\">\n <IconButton\n aria-label={previousPageLabel}\n data-testid=\"previous-page\"\n disabled={page === 1}\n icon={CaretLeft}\n onClick={() => {\n if (page !== 1) {\n goToPage(page - 1);\n }\n }}\n size=\"sm\"\n />\n <PageSelect /> <BodyPrimary className=\"whitespace-nowrap px-xs\">{ofLabel(pageCount)}</BodyPrimary>\n <IconButton\n aria-label={nextPageLabel}\n data-testid=\"next-page\"\n disabled={page === pageCount}\n icon={CaretRight}\n onClick={() => {\n if (page !== pageCount) {\n goToPage(page + 1);\n }\n }}\n size=\"sm\"\n />\n </div>\n );\n};\n","import { BodyPrimary } from '../../../Typography/Text/Text';\nimport { usePagination } from '../../paginationProvider';\n\nexport type ItemRangeLabelArgs = { end: number; start: number; total: number };\n\ntype Props = {\n /** Renders the label when all items are shown (pageSize === 'all'). Receives total item count. */\n allItemsLabel?: (itemCount: number) => string;\n /** Renders the label for a paginated range. Receives start, end, and total item count. */\n itemRangeLabel?: (args: ItemRangeLabelArgs) => string;\n};\n\nexport const ItemCountDisplay = ({\n allItemsLabel = (itemCount) => `${itemCount} Items`,\n itemRangeLabel = ({ end, start, total }) => `${start} - ${end} of ${total}`,\n}: Props) => {\n const { itemCount, page, pageSize } = usePagination();\n\n if (pageSize === 'all') {\n return <BodyPrimary>{allItemsLabel(itemCount)}</BodyPrimary>;\n }\n\n return (\n <BodyPrimary>\n {itemRangeLabel({\n end: Math.min(page * pageSize, itemCount),\n start: (page - 1) * pageSize + 1,\n total: itemCount,\n })}\n </BodyPrimary>\n );\n};\n","import { useMemo } from 'react';\n\nimport { OptionType, Select } from '../../../Select/Select';\nimport { usePagination } from '../../paginationProvider';\n\ntype Props = {\n /** Label text for the results-per-page select input. */\n resultsPerPageLabel?: string;\n};\n\nexport const ItemCountSelect = ({ resultsPerPageLabel = 'Results per page:' }: Props) => {\n const { pageSize, pageSizeOptions, setPageSize } = usePagination();\n\n const generatedOptions: OptionType[] = useMemo(() => {\n return pageSizeOptions.map((option) => {\n return { label: option.toString(), value: option };\n });\n }, [pageSizeOptions]);\n\n return (\n <Select\n autoComplete=\"off\"\n className=\"mr-sm w-[224px]\"\n defaultValue={pageSize}\n isInsideLabel\n labelText={resultsPerPageLabel}\n onChange={(event?: OptionType) => setPageSize(event?.value)}\n options={generatedOptions}\n small\n value={{ label: pageSize, value: pageSize }}\n />\n );\n};\n","import { cn } from '@evolve.ui/theme-system';\n\nimport { AdvancedPaginator } from './components/AdvancedPaginator/AdvancedPaginator';\nimport { ItemCountDisplay, ItemRangeLabelArgs } from './components/ItemCountDisplay/ItemCountDisplay';\nimport { ItemCountSelect } from './components/ItemCountSelect/ItemCountSelect';\n\ntype Props = {\n /** Renders the label when all items are shown (pageSize === 'all'). Forwarded to ItemCountDisplay. */\n allItemsLabel?: (itemCount: number) => string;\n className?: string;\n /** Renders the label for a paginated range. Forwarded to ItemCountDisplay. */\n itemRangeLabel?: (args: ItemRangeLabelArgs) => string;\n /** aria-label for the next-page button. Forwarded to AdvancedPaginator. */\n nextPageLabel?: string;\n /** Renders the page-count suffix. Forwarded to AdvancedPaginator. */\n ofLabel?: (pageCount: number) => string;\n /** aria-label for the previous-page button. Forwarded to AdvancedPaginator. */\n previousPageLabel?: string;\n /** Label text for the results-per-page select input. Forwarded to ItemCountSelect. */\n resultsPerPageLabel?: string;\n};\n\nexport const AdvancedPagination = ({\n allItemsLabel,\n className,\n itemRangeLabel,\n nextPageLabel,\n ofLabel,\n previousPageLabel,\n resultsPerPageLabel,\n}: Props) => {\n return (\n <div className={cn('flex items-center justify-between p-sm', className)}>\n <AdvancedPaginator\n nextPageLabel={nextPageLabel}\n ofLabel={ofLabel}\n previousPageLabel={previousPageLabel}\n />\n <div className=\"flex items-center\">\n <ItemCountSelect resultsPerPageLabel={resultsPerPageLabel} />\n <ItemCountDisplay\n allItemsLabel={allItemsLabel}\n itemRangeLabel={itemRangeLabel}\n />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { CaretLeft, CaretRight } from "./Icons.mjs";
|
|
|
2
2
|
import { BodyPrimary } from "./Typography/Text.mjs";
|
|
3
3
|
import { c as useWindowIsDesktop } from "./windowSizeProvider-sYwAqaOy.mjs";
|
|
4
4
|
import { IconButton } from "./IconButton.mjs";
|
|
5
|
-
import { t as Select } from "./Select-
|
|
5
|
+
import { t as Select } from "./Select-CH_ZN88G.mjs";
|
|
6
6
|
import { cn } from "@evolve.ui/theme-system";
|
|
7
7
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -383,4 +383,4 @@ const AdvancedPagination = ({ allItemsLabel, className, itemRangeLabel, nextPage
|
|
|
383
383
|
//#endregion
|
|
384
384
|
export { usePagination as i, Pagination as n, PaginationProvider as r, AdvancedPagination as t };
|
|
385
385
|
|
|
386
|
-
//# sourceMappingURL=Pagination-
|
|
386
|
+
//# sourceMappingURL=Pagination-Dyfeys4B.mjs.map
|