@chayns-components/core 5.4.5 → 5.4.6

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.
@@ -54,10 +54,13 @@ const DropdownBodyWrapper = /*#__PURE__*/(0, _react.forwardRef)(({
54
54
  shouldShowDropdown
55
55
  });
56
56
  (0, _react.useEffect)(() => {
57
- if (typeof onAvailableMaxHeightChange === 'function') {
57
+ // Only report the available max height while the dropdown is shown. Reporting it while
58
+ // the dropdown is closed would trigger unnecessary re-renders of the consumer (e.g. the
59
+ // ComboBox) during the initial layout, which can cause visible layout shifts.
60
+ if (shouldShowDropdown && typeof onAvailableMaxHeightChange === 'function') {
58
61
  onAvailableMaxHeightChange(availableMaxHeight);
59
62
  }
60
- }, [availableMaxHeight, onAvailableMaxHeightChange]);
63
+ }, [availableMaxHeight, onAvailableMaxHeightChange, shouldShowDropdown]);
61
64
  const handleClose = (0, _react.useCallback)(() => {
62
65
  if (typeof onClose === 'function') {
63
66
  onClose();
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownBodyWrapper.js","names":["_react","_interopRequireWildcard","require","_DropdownBodyWrapper","_reactDom","_dropdown","_DelayedDropdownContent","_interopRequireDefault","_dropdown2","_container","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DropdownBodyWrapper","forwardRef","anchorElement","bodyWidth","children","container","containerProp","contentHeight","direction","DropdownDirection","BOTTOM_RIGHT","maxHeight","minBodyWidth","onAvailableMaxHeightChange","onClose","onOutsideClick","onMeasure","shouldCaptureEvents","shouldShowDropdown","ref","isInChaynsWalletRef","useRef","measuredContentHeight","setMeasuredContentHeight","useState","measuredContentWidth","setMeasuredContentWidth","portal","setPortal","contentRef","shouldPreventClickRef","touchTimeoutRef","undefined","useContainer","transform","width","coordinates","availableMaxHeight","useDropdown","contentWidth","useEffect","handleClose","useCallback","handleClick","event","current","contains","target","preventDefault","stopPropagation","shouldPreventCloseOnClick","handleContentMeasure","measurements","height","handleTouchEnd","clearTimeout","handleTouchStart","window","setTimeout","useDropdownListener","onClick","onTouchEnd","onTouchStart","isBottomDirection","BOTTOM","BOTTOM_LEFT","includes","reservationWrapperElement","closest","ContainerAnchor","RESERVATION_WRAPPER","availableHeight","innerHeight","getBoundingClientRect","bottom","additionalNeededSpace","style","marginBottom","createPortal","createElement","shouldShowContent","StyledDropdownBodyWrapperContent","$width","$minWidth","$maxHeight","$direction","className","tabIndex","useImperativeHandle","StyledDropdownBodyWrapper","displayName","_default","exports"],"sources":["../../../../src/components/dropdown-body-wrapper/DropdownBodyWrapper.tsx"],"sourcesContent":["import React, {\n forwardRef,\n ReactNode,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport {\n StyledDropdownBodyWrapper,\n StyledDropdownBodyWrapperContent,\n} from './DropdownBodyWrapper.styles';\nimport { createPortal } from 'react-dom';\nimport { DropdownDirection, DropdownMeasurements } from '../../types/dropdown';\nimport DelayedDropdownContent, {\n DelayedDropdownContentProps,\n} from './delayed-dropdown-content/DelayedDropdownContent';\nimport { useDropdown, useDropdownListener } from '../../hooks/dropdown';\nimport { ContainerAnchor, useContainer } from '../../hooks/container';\n\ninterface DropdownBodyWrapperProps {\n /**\n * The anchor element of the dropdown.\n */\n anchorElement: Element;\n /**\n * The width of the Body.\n */\n bodyWidth?: number;\n /**\n * The content of the dropdown body.\n */\n children: ReactNode;\n /**\n * The element where the content should be rendered via React Portal.\n */\n container?: Element;\n /**\n * The height of the content\n */\n contentHeight?: number;\n /**\n * The direction of the dropdown.\n */\n direction?: DropdownDirection;\n /**\n * The max height of the dropdown.\n */\n maxHeight?: number;\n /**\n * The minimum width of the body.\n */\n minBodyWidth?: number;\n /**\n * Function to be executed when the available maximum height of the dropdown changes. The\n * available maximum height is the space that is available for the dropdown content until the\n * edge of the container is reached (minus a small spacing). This can be used to limit the\n * content height, so the dropdown is not cut off when there is not enough space.\n */\n onAvailableMaxHeightChange?: (availableMaxHeight: number) => void;\n /**\n * Function to be executed when the body is closed.\n */\n onClose?: VoidFunction;\n /**\n * Function to be executed when the user clicks outside the dropdown.\n * If the function returns `true`, the dropdown will not be closed.\n */\n onOutsideClick?: () => boolean | void;\n /**\n * Function to be executed when the content is measured.\n */\n onMeasure?: DelayedDropdownContentProps['onMeasure'];\n /**\n * Whether the dropdown should be visible.\n */\n shouldShowDropdown: boolean;\n /**\n * Whether the outside events should be captured.\n */\n shouldCaptureEvents?: boolean;\n}\n\nconst DropdownBodyWrapper = forwardRef<HTMLDivElement, DropdownBodyWrapperProps>(\n (\n {\n anchorElement,\n bodyWidth,\n children,\n container: containerProp,\n contentHeight = 0,\n direction = DropdownDirection.BOTTOM_RIGHT,\n maxHeight,\n minBodyWidth = 0,\n onAvailableMaxHeightChange,\n onClose,\n onOutsideClick,\n onMeasure,\n shouldCaptureEvents = true,\n shouldShowDropdown,\n },\n ref,\n ) => {\n const isInChaynsWalletRef = useRef(false);\n\n const [measuredContentHeight, setMeasuredContentHeight] = useState<number>(0);\n const [measuredContentWidth, setMeasuredContentWidth] = useState<number>(0);\n const [portal, setPortal] = useState<ReactPortal>();\n\n const contentRef = useRef<HTMLDivElement>(null);\n const shouldPreventClickRef = useRef<boolean>(false);\n const touchTimeoutRef = useRef<number | undefined>(undefined);\n\n const container = useContainer({ anchorElement, container: containerProp });\n\n const { transform, width, coordinates, availableMaxHeight } = useDropdown({\n anchorElement,\n container,\n contentHeight,\n contentWidth: bodyWidth ?? measuredContentWidth,\n direction,\n shouldShowDropdown,\n });\n\n useEffect(() => {\n if (typeof onAvailableMaxHeightChange === 'function') {\n onAvailableMaxHeightChange(availableMaxHeight);\n }\n }, [availableMaxHeight, onAvailableMaxHeightChange]);\n\n const handleClose = useCallback(() => {\n if (typeof onClose === 'function') {\n onClose();\n }\n }, [onClose]);\n\n /**\n * This function closes the body\n */\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (\n contentRef.current &&\n shouldShowDropdown &&\n !anchorElement.contains(event.target as Node) &&\n !contentRef.current.contains(event.target as Node)\n ) {\n event.preventDefault();\n event.stopPropagation();\n\n const shouldPreventCloseOnClick = onOutsideClick?.() ?? false;\n\n if (!shouldPreventClickRef.current && !shouldPreventCloseOnClick) {\n handleClose();\n }\n }\n\n shouldPreventClickRef.current = false;\n },\n [anchorElement, handleClose, onOutsideClick, shouldShowDropdown],\n );\n\n const handleContentMeasure = useCallback(\n (measurements: DropdownMeasurements) => {\n // Measurements are only needed if the content is shown in the chayns wallet. To prevent\n // unnecessary renders, we only set the height if the content is shown in the wallet.\n if (isInChaynsWalletRef.current) {\n setMeasuredContentHeight(measurements.height);\n }\n\n setMeasuredContentWidth(measurements.width);\n\n if (typeof onMeasure === 'function') {\n onMeasure(measurements);\n }\n },\n [onMeasure],\n );\n\n const handleTouchEnd = useCallback(() => {\n clearTimeout(touchTimeoutRef.current);\n }, []);\n\n const handleTouchStart = useCallback(() => {\n touchTimeoutRef.current = window.setTimeout(() => {\n shouldPreventClickRef.current = true;\n }, 500);\n }, []);\n\n /**\n * This hook listens for clicks\n */\n useDropdownListener({\n onClick: handleClick,\n onClose: handleClose,\n onTouchEnd: handleTouchEnd,\n onTouchStart: handleTouchStart,\n shouldCaptureEvents,\n });\n\n useEffect(() => {\n const isBottomDirection = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n const reservationWrapperElement = anchorElement.closest<HTMLDivElement>(\n ContainerAnchor.RESERVATION_WRAPPER,\n );\n\n isInChaynsWalletRef.current =\n !!(\n reservationWrapperElement && reservationWrapperElement.contains(anchorElement)\n ) || true;\n\n // This effect checks if additional space is needed to show dropdown content in chayns cards.\n if (\n isBottomDirection &&\n isInChaynsWalletRef.current &&\n measuredContentHeight > 0 &&\n reservationWrapperElement &&\n shouldShowDropdown\n ) {\n const availableHeight =\n window.innerHeight - anchorElement.getBoundingClientRect().bottom;\n\n // If the content height is greater than the available height, we need to add additional space.\n // This is to ensure that the dropdown content is fully visible. The 16 pixels are a buffer for shadows.\n const additionalNeededSpace = measuredContentHeight + 16 - availableHeight;\n\n if (additionalNeededSpace > 0) {\n // Add margin bottom to the reservation wrapper to ensure the dropdown content is fully visible.\n reservationWrapperElement.style.marginBottom = `${additionalNeededSpace}px`;\n } else {\n // Reset the margin bottom if no additional space is needed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n }\n\n if (isInChaynsWalletRef.current && reservationWrapperElement && !shouldShowDropdown) {\n // Reset the margin bottom when the dropdown is closed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n\n return () => {\n if (reservationWrapperElement) {\n reservationWrapperElement.style.marginBottom = '0px';\n }\n };\n }, [anchorElement, direction, measuredContentHeight, shouldShowDropdown]);\n\n useEffect(() => {\n if (!container) return;\n\n setPortal(() =>\n createPortal(\n <DelayedDropdownContent\n coordinates={coordinates}\n onMeasure={handleContentMeasure}\n shouldShowContent={shouldShowDropdown}\n transform={transform}\n >\n <StyledDropdownBodyWrapperContent\n $width={width}\n $minWidth={minBodyWidth}\n $maxHeight={maxHeight}\n $direction={direction}\n ref={contentRef}\n className={\n typeof maxHeight === 'number' ? 'chayns-scrollbar' : undefined\n }\n tabIndex={0}\n >\n {children}\n </StyledDropdownBodyWrapperContent>\n </DelayedDropdownContent>,\n container,\n ),\n );\n }, [\n children,\n container,\n coordinates,\n direction,\n handleContentMeasure,\n maxHeight,\n minBodyWidth,\n shouldShowDropdown,\n transform,\n width,\n ]);\n\n useImperativeHandle(ref, () => contentRef.current!, []);\n\n return <StyledDropdownBodyWrapper>{portal}</StyledDropdownBodyWrapper>;\n },\n);\n\nDropdownBodyWrapper.displayName = 'DropdownBodyWrapper';\n\nexport default DropdownBodyWrapper;\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AAUA,IAAAC,oBAAA,GAAAD,OAAA;AAIA,IAAAE,SAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;AACA,IAAAI,uBAAA,GAAAC,sBAAA,CAAAL,OAAA;AAGA,IAAAM,UAAA,GAAAN,OAAA;AACA,IAAAO,UAAA,GAAAP,OAAA;AAAsE,SAAAK,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAT,wBAAAS,CAAA,EAAAG,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAb,uBAAA,YAAAA,CAAAS,CAAA,EAAAG,CAAA,SAAAA,CAAA,IAAAH,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAO,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAR,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAS,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAX,CAAA,UAAAO,CAAA,CAAAK,GAAA,CAAAZ,CAAA,GAAAO,CAAA,CAAAM,GAAA,CAAAb,CAAA,EAAAS,CAAA,gBAAAN,CAAA,IAAAH,CAAA,gBAAAG,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAG,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAG,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAH,CAAA,CAAAG,CAAA,WAAAM,CAAA,KAAAT,CAAA,EAAAG,CAAA;AAiEtE,MAAMgB,mBAAmB,gBAAG,IAAAC,iBAAU,EAClC,CACI;EACIC,aAAa;EACbC,SAAS;EACTC,QAAQ;EACRC,SAAS,EAAEC,aAAa;EACxBC,aAAa,GAAG,CAAC;EACjBC,SAAS,GAAGC,2BAAiB,CAACC,YAAY;EAC1CC,SAAS;EACTC,YAAY,GAAG,CAAC;EAChBC,0BAA0B;EAC1BC,OAAO;EACPC,cAAc;EACdC,SAAS;EACTC,mBAAmB,GAAG,IAAI;EAC1BC;AACJ,CAAC,EACDC,GAAG,KACF;EACD,MAAMC,mBAAmB,GAAG,IAAAC,aAAM,EAAC,KAAK,CAAC;EAEzC,MAAM,CAACC,qBAAqB,EAAEC,wBAAwB,CAAC,GAAG,IAAAC,eAAQ,EAAS,CAAC,CAAC;EAC7E,MAAM,CAACC,oBAAoB,EAAEC,uBAAuB,CAAC,GAAG,IAAAF,eAAQ,EAAS,CAAC,CAAC;EAC3E,MAAM,CAACG,MAAM,EAAEC,SAAS,CAAC,GAAG,IAAAJ,eAAQ,EAAc,CAAC;EAEnD,MAAMK,UAAU,GAAG,IAAAR,aAAM,EAAiB,IAAI,CAAC;EAC/C,MAAMS,qBAAqB,GAAG,IAAAT,aAAM,EAAU,KAAK,CAAC;EACpD,MAAMU,eAAe,GAAG,IAAAV,aAAM,EAAqBW,SAAS,CAAC;EAE7D,MAAM3B,SAAS,GAAG,IAAA4B,uBAAY,EAAC;IAAE/B,aAAa;IAAEG,SAAS,EAAEC;EAAc,CAAC,CAAC;EAE3E,MAAM;IAAE4B,SAAS;IAAEC,KAAK;IAAEC,WAAW;IAAEC;EAAmB,CAAC,GAAG,IAAAC,sBAAW,EAAC;IACtEpC,aAAa;IACbG,SAAS;IACTE,aAAa;IACbgC,YAAY,EAAEpC,SAAS,IAAIsB,oBAAoB;IAC/CjB,SAAS;IACTU;EACJ,CAAC,CAAC;EAEF,IAAAsB,gBAAS,EAAC,MAAM;IACZ,IAAI,OAAO3B,0BAA0B,KAAK,UAAU,EAAE;MAClDA,0BAA0B,CAACwB,kBAAkB,CAAC;IAClD;EACJ,CAAC,EAAE,CAACA,kBAAkB,EAAExB,0BAA0B,CAAC,CAAC;EAEpD,MAAM4B,WAAW,GAAG,IAAAC,kBAAW,EAAC,MAAM;IAClC,IAAI,OAAO5B,OAAO,KAAK,UAAU,EAAE;MAC/BA,OAAO,CAAC,CAAC;IACb;EACJ,CAAC,EAAE,CAACA,OAAO,CAAC,CAAC;;EAEb;AACR;AACA;EACQ,MAAM6B,WAAW,GAAG,IAAAD,kBAAW,EAC1BE,KAAiB,IAAK;IACnB,IACIf,UAAU,CAACgB,OAAO,IAClB3B,kBAAkB,IAClB,CAAChB,aAAa,CAAC4C,QAAQ,CAACF,KAAK,CAACG,MAAc,CAAC,IAC7C,CAAClB,UAAU,CAACgB,OAAO,CAACC,QAAQ,CAACF,KAAK,CAACG,MAAc,CAAC,EACpD;MACEH,KAAK,CAACI,cAAc,CAAC,CAAC;MACtBJ,KAAK,CAACK,eAAe,CAAC,CAAC;MAEvB,MAAMC,yBAAyB,GAAG,CAAAnC,cAAc,aAAdA,cAAc,uBAAdA,cAAc,CAAG,CAAC,KAAI,KAAK;MAE7D,IAAI,CAACe,qBAAqB,CAACe,OAAO,IAAI,CAACK,yBAAyB,EAAE;QAC9DT,WAAW,CAAC,CAAC;MACjB;IACJ;IAEAX,qBAAqB,CAACe,OAAO,GAAG,KAAK;EACzC,CAAC,EACD,CAAC3C,aAAa,EAAEuC,WAAW,EAAE1B,cAAc,EAAEG,kBAAkB,CACnE,CAAC;EAED,MAAMiC,oBAAoB,GAAG,IAAAT,kBAAW,EACnCU,YAAkC,IAAK;IACpC;IACA;IACA,IAAIhC,mBAAmB,CAACyB,OAAO,EAAE;MAC7BtB,wBAAwB,CAAC6B,YAAY,CAACC,MAAM,CAAC;IACjD;IAEA3B,uBAAuB,CAAC0B,YAAY,CAACjB,KAAK,CAAC;IAE3C,IAAI,OAAOnB,SAAS,KAAK,UAAU,EAAE;MACjCA,SAAS,CAACoC,YAAY,CAAC;IAC3B;EACJ,CAAC,EACD,CAACpC,SAAS,CACd,CAAC;EAED,MAAMsC,cAAc,GAAG,IAAAZ,kBAAW,EAAC,MAAM;IACrCa,YAAY,CAACxB,eAAe,CAACc,OAAO,CAAC;EACzC,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMW,gBAAgB,GAAG,IAAAd,kBAAW,EAAC,MAAM;IACvCX,eAAe,CAACc,OAAO,GAAGY,MAAM,CAACC,UAAU,CAAC,MAAM;MAC9C5B,qBAAqB,CAACe,OAAO,GAAG,IAAI;IACxC,CAAC,EAAE,GAAG,CAAC;EACX,CAAC,EAAE,EAAE,CAAC;;EAEN;AACR;AACA;EACQ,IAAAc,8BAAmB,EAAC;IAChBC,OAAO,EAAEjB,WAAW;IACpB7B,OAAO,EAAE2B,WAAW;IACpBoB,UAAU,EAAEP,cAAc;IAC1BQ,YAAY,EAAEN,gBAAgB;IAC9BvC;EACJ,CAAC,CAAC;EAEF,IAAAuB,gBAAS,EAAC,MAAM;IACZ,MAAMuB,iBAAiB,GAAG,CACtBtD,2BAAiB,CAACuD,MAAM,EACxBvD,2BAAiB,CAACwD,WAAW,EAC7BxD,2BAAiB,CAACC,YAAY,CACjC,CAACwD,QAAQ,CAAC1D,SAAS,CAAC;IAErB,MAAM2D,yBAAyB,GAAGjE,aAAa,CAACkE,OAAO,CACnDC,0BAAe,CAACC,mBACpB,CAAC;IAEDlD,mBAAmB,CAACyB,OAAO,GACvB,CAAC,EACGsB,yBAAyB,IAAIA,yBAAyB,CAACrB,QAAQ,CAAC5C,aAAa,CAAC,CACjF,IAAI,IAAI;;IAEb;IACA,IACI6D,iBAAiB,IACjB3C,mBAAmB,CAACyB,OAAO,IAC3BvB,qBAAqB,GAAG,CAAC,IACzB6C,yBAAyB,IACzBjD,kBAAkB,EACpB;MACE,MAAMqD,eAAe,GACjBd,MAAM,CAACe,WAAW,GAAGtE,aAAa,CAACuE,qBAAqB,CAAC,CAAC,CAACC,MAAM;;MAErE;MACA;MACA,MAAMC,qBAAqB,GAAGrD,qBAAqB,GAAG,EAAE,GAAGiD,eAAe;MAE1E,IAAII,qBAAqB,GAAG,CAAC,EAAE;QAC3B;QACAR,yBAAyB,CAACS,KAAK,CAACC,YAAY,GAAG,GAAGF,qBAAqB,IAAI;MAC/E,CAAC,MAAM;QACH;QACAR,yBAAyB,CAACS,KAAK,CAACC,YAAY,GAAG,KAAK;MACxD;IACJ;IAEA,IAAIzD,mBAAmB,CAACyB,OAAO,IAAIsB,yBAAyB,IAAI,CAACjD,kBAAkB,EAAE;MACjF;MACAiD,yBAAyB,CAACS,KAAK,CAACC,YAAY,GAAG,KAAK;IACxD;IAEA,OAAO,MAAM;MACT,IAAIV,yBAAyB,EAAE;QAC3BA,yBAAyB,CAACS,KAAK,CAACC,YAAY,GAAG,KAAK;MACxD;IACJ,CAAC;EACL,CAAC,EAAE,CAAC3E,aAAa,EAAEM,SAAS,EAAEc,qBAAqB,EAAEJ,kBAAkB,CAAC,CAAC;EAEzE,IAAAsB,gBAAS,EAAC,MAAM;IACZ,IAAI,CAACnC,SAAS,EAAE;IAEhBuB,SAAS,CAAC,mBACN,IAAAkD,sBAAY,eACR3G,MAAA,CAAAY,OAAA,CAAAgG,aAAA,CAACtG,uBAAA,CAAAM,OAAsB;MACnBqD,WAAW,EAAEA,WAAY;MACzBpB,SAAS,EAAEmC,oBAAqB;MAChC6B,iBAAiB,EAAE9D,kBAAmB;MACtCgB,SAAS,EAAEA;IAAU,gBAErB/D,MAAA,CAAAY,OAAA,CAAAgG,aAAA,CAACzG,oBAAA,CAAA2G,gCAAgC;MAC7BC,MAAM,EAAE/C,KAAM;MACdgD,SAAS,EAAEvE,YAAa;MACxBwE,UAAU,EAAEzE,SAAU;MACtB0E,UAAU,EAAE7E,SAAU;MACtBW,GAAG,EAAEU,UAAW;MAChByD,SAAS,EACL,OAAO3E,SAAS,KAAK,QAAQ,GAAG,kBAAkB,GAAGqB,SACxD;MACDuD,QAAQ,EAAE;IAAE,GAEXnF,QAC6B,CACd,CAAC,EACzBC,SACJ,CACJ,CAAC;EACL,CAAC,EAAE,CACCD,QAAQ,EACRC,SAAS,EACT+B,WAAW,EACX5B,SAAS,EACT2C,oBAAoB,EACpBxC,SAAS,EACTC,YAAY,EACZM,kBAAkB,EAClBgB,SAAS,EACTC,KAAK,CACR,CAAC;EAEF,IAAAqD,0BAAmB,EAACrE,GAAG,EAAE,MAAMU,UAAU,CAACgB,OAAQ,EAAE,EAAE,CAAC;EAEvD,oBAAO1E,MAAA,CAAAY,OAAA,CAAAgG,aAAA,CAACzG,oBAAA,CAAAmH,yBAAyB,QAAE9D,MAAkC,CAAC;AAC1E,CACJ,CAAC;AAED3B,mBAAmB,CAAC0F,WAAW,GAAG,qBAAqB;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAA7G,OAAA,GAEzCiB,mBAAmB","ignoreList":[]}
1
+ {"version":3,"file":"DropdownBodyWrapper.js","names":["_react","_interopRequireWildcard","require","_DropdownBodyWrapper","_reactDom","_dropdown","_DelayedDropdownContent","_interopRequireDefault","_dropdown2","_container","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DropdownBodyWrapper","forwardRef","anchorElement","bodyWidth","children","container","containerProp","contentHeight","direction","DropdownDirection","BOTTOM_RIGHT","maxHeight","minBodyWidth","onAvailableMaxHeightChange","onClose","onOutsideClick","onMeasure","shouldCaptureEvents","shouldShowDropdown","ref","isInChaynsWalletRef","useRef","measuredContentHeight","setMeasuredContentHeight","useState","measuredContentWidth","setMeasuredContentWidth","portal","setPortal","contentRef","shouldPreventClickRef","touchTimeoutRef","undefined","useContainer","transform","width","coordinates","availableMaxHeight","useDropdown","contentWidth","useEffect","handleClose","useCallback","handleClick","event","current","contains","target","preventDefault","stopPropagation","shouldPreventCloseOnClick","handleContentMeasure","measurements","height","handleTouchEnd","clearTimeout","handleTouchStart","window","setTimeout","useDropdownListener","onClick","onTouchEnd","onTouchStart","isBottomDirection","BOTTOM","BOTTOM_LEFT","includes","reservationWrapperElement","closest","ContainerAnchor","RESERVATION_WRAPPER","availableHeight","innerHeight","getBoundingClientRect","bottom","additionalNeededSpace","style","marginBottom","createPortal","createElement","shouldShowContent","StyledDropdownBodyWrapperContent","$width","$minWidth","$maxHeight","$direction","className","tabIndex","useImperativeHandle","StyledDropdownBodyWrapper","displayName","_default","exports"],"sources":["../../../../src/components/dropdown-body-wrapper/DropdownBodyWrapper.tsx"],"sourcesContent":["import React, {\n forwardRef,\n ReactNode,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport {\n StyledDropdownBodyWrapper,\n StyledDropdownBodyWrapperContent,\n} from './DropdownBodyWrapper.styles';\nimport { createPortal } from 'react-dom';\nimport { DropdownDirection, DropdownMeasurements } from '../../types/dropdown';\nimport DelayedDropdownContent, {\n DelayedDropdownContentProps,\n} from './delayed-dropdown-content/DelayedDropdownContent';\nimport { useDropdown, useDropdownListener } from '../../hooks/dropdown';\nimport { ContainerAnchor, useContainer } from '../../hooks/container';\n\ninterface DropdownBodyWrapperProps {\n /**\n * The anchor element of the dropdown.\n */\n anchorElement: Element;\n /**\n * The width of the Body.\n */\n bodyWidth?: number;\n /**\n * The content of the dropdown body.\n */\n children: ReactNode;\n /**\n * The element where the content should be rendered via React Portal.\n */\n container?: Element;\n /**\n * The height of the content\n */\n contentHeight?: number;\n /**\n * The direction of the dropdown.\n */\n direction?: DropdownDirection;\n /**\n * The max height of the dropdown.\n */\n maxHeight?: number;\n /**\n * The minimum width of the body.\n */\n minBodyWidth?: number;\n /**\n * Function to be executed when the available maximum height of the dropdown changes. The\n * available maximum height is the space that is available for the dropdown content until the\n * edge of the container is reached (minus a small spacing). This can be used to limit the\n * content height, so the dropdown is not cut off when there is not enough space.\n */\n onAvailableMaxHeightChange?: (availableMaxHeight: number) => void;\n /**\n * Function to be executed when the body is closed.\n */\n onClose?: VoidFunction;\n /**\n * Function to be executed when the user clicks outside the dropdown.\n * If the function returns `true`, the dropdown will not be closed.\n */\n onOutsideClick?: () => boolean | void;\n /**\n * Function to be executed when the content is measured.\n */\n onMeasure?: DelayedDropdownContentProps['onMeasure'];\n /**\n * Whether the dropdown should be visible.\n */\n shouldShowDropdown: boolean;\n /**\n * Whether the outside events should be captured.\n */\n shouldCaptureEvents?: boolean;\n}\n\nconst DropdownBodyWrapper = forwardRef<HTMLDivElement, DropdownBodyWrapperProps>(\n (\n {\n anchorElement,\n bodyWidth,\n children,\n container: containerProp,\n contentHeight = 0,\n direction = DropdownDirection.BOTTOM_RIGHT,\n maxHeight,\n minBodyWidth = 0,\n onAvailableMaxHeightChange,\n onClose,\n onOutsideClick,\n onMeasure,\n shouldCaptureEvents = true,\n shouldShowDropdown,\n },\n ref,\n ) => {\n const isInChaynsWalletRef = useRef(false);\n\n const [measuredContentHeight, setMeasuredContentHeight] = useState<number>(0);\n const [measuredContentWidth, setMeasuredContentWidth] = useState<number>(0);\n const [portal, setPortal] = useState<ReactPortal>();\n\n const contentRef = useRef<HTMLDivElement>(null);\n const shouldPreventClickRef = useRef<boolean>(false);\n const touchTimeoutRef = useRef<number | undefined>(undefined);\n\n const container = useContainer({ anchorElement, container: containerProp });\n\n const { transform, width, coordinates, availableMaxHeight } = useDropdown({\n anchorElement,\n container,\n contentHeight,\n contentWidth: bodyWidth ?? measuredContentWidth,\n direction,\n shouldShowDropdown,\n });\n\n useEffect(() => {\n // Only report the available max height while the dropdown is shown. Reporting it while\n // the dropdown is closed would trigger unnecessary re-renders of the consumer (e.g. the\n // ComboBox) during the initial layout, which can cause visible layout shifts.\n if (shouldShowDropdown && typeof onAvailableMaxHeightChange === 'function') {\n onAvailableMaxHeightChange(availableMaxHeight);\n }\n }, [availableMaxHeight, onAvailableMaxHeightChange, shouldShowDropdown]);\n\n const handleClose = useCallback(() => {\n if (typeof onClose === 'function') {\n onClose();\n }\n }, [onClose]);\n\n /**\n * This function closes the body\n */\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (\n contentRef.current &&\n shouldShowDropdown &&\n !anchorElement.contains(event.target as Node) &&\n !contentRef.current.contains(event.target as Node)\n ) {\n event.preventDefault();\n event.stopPropagation();\n\n const shouldPreventCloseOnClick = onOutsideClick?.() ?? false;\n\n if (!shouldPreventClickRef.current && !shouldPreventCloseOnClick) {\n handleClose();\n }\n }\n\n shouldPreventClickRef.current = false;\n },\n [anchorElement, handleClose, onOutsideClick, shouldShowDropdown],\n );\n\n const handleContentMeasure = useCallback(\n (measurements: DropdownMeasurements) => {\n // Measurements are only needed if the content is shown in the chayns wallet. To prevent\n // unnecessary renders, we only set the height if the content is shown in the wallet.\n if (isInChaynsWalletRef.current) {\n setMeasuredContentHeight(measurements.height);\n }\n\n setMeasuredContentWidth(measurements.width);\n\n if (typeof onMeasure === 'function') {\n onMeasure(measurements);\n }\n },\n [onMeasure],\n );\n\n const handleTouchEnd = useCallback(() => {\n clearTimeout(touchTimeoutRef.current);\n }, []);\n\n const handleTouchStart = useCallback(() => {\n touchTimeoutRef.current = window.setTimeout(() => {\n shouldPreventClickRef.current = true;\n }, 500);\n }, []);\n\n /**\n * This hook listens for clicks\n */\n useDropdownListener({\n onClick: handleClick,\n onClose: handleClose,\n onTouchEnd: handleTouchEnd,\n onTouchStart: handleTouchStart,\n shouldCaptureEvents,\n });\n\n useEffect(() => {\n const isBottomDirection = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n const reservationWrapperElement = anchorElement.closest<HTMLDivElement>(\n ContainerAnchor.RESERVATION_WRAPPER,\n );\n\n isInChaynsWalletRef.current =\n !!(\n reservationWrapperElement && reservationWrapperElement.contains(anchorElement)\n ) || true;\n\n // This effect checks if additional space is needed to show dropdown content in chayns cards.\n if (\n isBottomDirection &&\n isInChaynsWalletRef.current &&\n measuredContentHeight > 0 &&\n reservationWrapperElement &&\n shouldShowDropdown\n ) {\n const availableHeight =\n window.innerHeight - anchorElement.getBoundingClientRect().bottom;\n\n // If the content height is greater than the available height, we need to add additional space.\n // This is to ensure that the dropdown content is fully visible. The 16 pixels are a buffer for shadows.\n const additionalNeededSpace = measuredContentHeight + 16 - availableHeight;\n\n if (additionalNeededSpace > 0) {\n // Add margin bottom to the reservation wrapper to ensure the dropdown content is fully visible.\n reservationWrapperElement.style.marginBottom = `${additionalNeededSpace}px`;\n } else {\n // Reset the margin bottom if no additional space is needed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n }\n\n if (isInChaynsWalletRef.current && reservationWrapperElement && !shouldShowDropdown) {\n // Reset the margin bottom when the dropdown is closed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n\n return () => {\n if (reservationWrapperElement) {\n reservationWrapperElement.style.marginBottom = '0px';\n }\n };\n }, [anchorElement, direction, measuredContentHeight, shouldShowDropdown]);\n\n useEffect(() => {\n if (!container) return;\n\n setPortal(() =>\n createPortal(\n <DelayedDropdownContent\n coordinates={coordinates}\n onMeasure={handleContentMeasure}\n shouldShowContent={shouldShowDropdown}\n transform={transform}\n >\n <StyledDropdownBodyWrapperContent\n $width={width}\n $minWidth={minBodyWidth}\n $maxHeight={maxHeight}\n $direction={direction}\n ref={contentRef}\n className={\n typeof maxHeight === 'number' ? 'chayns-scrollbar' : undefined\n }\n tabIndex={0}\n >\n {children}\n </StyledDropdownBodyWrapperContent>\n </DelayedDropdownContent>,\n container,\n ),\n );\n }, [\n children,\n container,\n coordinates,\n direction,\n handleContentMeasure,\n maxHeight,\n minBodyWidth,\n shouldShowDropdown,\n transform,\n width,\n ]);\n\n useImperativeHandle(ref, () => contentRef.current!, []);\n\n return <StyledDropdownBodyWrapper>{portal}</StyledDropdownBodyWrapper>;\n },\n);\n\nDropdownBodyWrapper.displayName = 'DropdownBodyWrapper';\n\nexport default DropdownBodyWrapper;\n"],"mappings":"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","ignoreList":[]}
@@ -106,8 +106,12 @@ const useDropdownPosition = ({
106
106
  // not touch the container edge (e.g. to leave room for shadows).
107
107
  const spaceToTop = y;
108
108
  const spaceToBottom = height - (y + anchorHeight);
109
- const nextAvailableMaxHeight = Math.max((useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING, 0);
110
- setAvailableMaxHeight(nextAvailableMaxHeight);
109
+ const nextAvailableMaxHeight = Math.max(Math.round((useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING), 0);
110
+
111
+ // Only update the available max height when it changes by more than one pixel. This
112
+ // prevents subpixel fluctuations of getBoundingClientRect from repeatedly triggering
113
+ // re-renders of the consumer, which could otherwise cause a layout shift loop.
114
+ setAvailableMaxHeight(currentAvailableMaxHeight => Math.abs(currentAvailableMaxHeight - nextAvailableMaxHeight) <= 1 ? currentAvailableMaxHeight : nextAvailableMaxHeight);
111
115
  setCoordinates({
112
116
  x,
113
117
  y: useTopAlignment ? y : y + anchorHeight
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.js","names":["_react","require","_dropdown","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","useDropdownListener","onClick","onClose","onTouchEnd","onTouchStart","shouldCaptureEvents","document","addEventListener","removeEventListener","exports","useDropdownAlignment","anchorElement","contentWidth","direction","shouldUseTopAlignment","translateX","setTranslateX","useState","translateY","setTranslateY","DropdownDirection","BOTTOM_LEFT","TOP_LEFT","LEFT","includes","difference","clientWidth","useTopAlignment","TOP","TOP_RIGHT","useMemo","x","y","AVAILABLE_HEIGHT_SPACING","useDropdownPosition","container","contentHeight","shouldShowDropdown","coordinates","setCoordinates","setShouldUseTopAlignment","availableMaxHeight","setAvailableMaxHeight","calculateCoordinates","useCallback","left","anchorLeft","top","anchorTop","height","anchorHeight","getBoundingClientRect","scrollLeft","scrollTop","hasBottomAlignment","BOTTOM","BOTTOM_RIGHT","spaceToTop","spaceToBottom","nextAvailableMaxHeight","Math","max","handleResize","setTimeout","useDropdown","transform","width"],"sources":["../../../src/hooks/dropdown.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { DropdownCoordinates, DropdownDirection } from '../types/dropdown';\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\ninterface UseDropdownListenerOptions {\n onClick: (event: MouseEvent) => void;\n onClose: () => void;\n onTouchEnd: (event: TouchEvent) => void;\n onTouchStart: (event: TouchEvent) => void;\n shouldCaptureEvents?: boolean;\n}\n\nexport const useDropdownListener = ({\n onClick,\n onClose,\n onTouchEnd,\n onTouchStart,\n shouldCaptureEvents,\n}: UseDropdownListenerOptions) => {\n useEffect(() => {\n document.addEventListener('click', onClick, shouldCaptureEvents);\n document.addEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.addEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.addEventListener('blur', onClose);\n\n return () => {\n document.removeEventListener('click', onClick, shouldCaptureEvents);\n document.removeEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.removeEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.removeEventListener('blur', onClose);\n };\n }, [onClick, onClose, onTouchEnd, onTouchStart]);\n};\n\ninterface UseDropdownAlignmentOptions {\n direction: DropdownDirection;\n shouldUseTopAlignment: boolean;\n contentWidth: number;\n anchorElement: Element;\n}\n\nexport const useDropdownAlignment = ({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n}: UseDropdownAlignmentOptions) => {\n const [translateX, setTranslateX] = useState<string>('0px');\n const [translateY, setTranslateY] = useState<string>('0px');\n\n useEffect(() => {\n if (\n [\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.LEFT,\n ].includes(direction)\n ) {\n const difference = anchorElement.clientWidth - contentWidth;\n\n setTranslateX(`${difference}px`);\n } else {\n setTranslateX('0px');\n }\n }, [anchorElement.clientWidth, contentWidth, direction]);\n\n useEffect(() => {\n const useTopAlignment =\n shouldUseTopAlignment ||\n [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n if (useTopAlignment) {\n setTranslateY('-100%');\n } else {\n setTranslateY('0px');\n }\n }, [direction, shouldUseTopAlignment]);\n\n return useMemo(() => ({ x: translateX, y: translateY }), [translateX, translateY]);\n};\n\ninterface UseDropdownPositionOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\n/**\n * The space (in pixels) that should be kept between the dropdown content and the edge of the\n * container when calculating the available maximum height.\n */\nconst AVAILABLE_HEIGHT_SPACING = 16;\n\nexport const useDropdownPosition = ({\n anchorElement,\n container,\n contentHeight = 0,\n direction,\n shouldShowDropdown,\n}: UseDropdownPositionOptions) => {\n const [coordinates, setCoordinates] = useState<DropdownCoordinates>({ x: 0, y: 0 });\n const [shouldUseTopAlignment, setShouldUseTopAlignment] = useState(false);\n const [availableMaxHeight, setAvailableMaxHeight] = useState<number>(0);\n\n const calculateCoordinates = useCallback(() => {\n if (container) {\n const {\n left: anchorLeft,\n top: anchorTop,\n height: anchorHeight,\n } = anchorElement.getBoundingClientRect();\n\n const { left, top, height } = container.getBoundingClientRect();\n\n const x = anchorLeft - left + container.scrollLeft;\n const y = anchorTop - top + container.scrollTop;\n\n let useTopAlignment = [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n const hasBottomAlignment = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n if (!hasBottomAlignment && y + anchorHeight + contentHeight > height) {\n useTopAlignment = true;\n\n setShouldUseTopAlignment(true);\n } else {\n setShouldUseTopAlignment(false);\n }\n\n // Calculate the space that is available for the dropdown content. When the dropdown is\n // opened to the top, the available space reaches from the anchor to the top edge of the\n // container. When it is opened to the bottom, it reaches from the bottom of the anchor\n // to the bottom edge of the container. A small spacing is subtracted so the content does\n // not touch the container edge (e.g. to leave room for shadows).\n const spaceToTop = y;\n const spaceToBottom = height - (y + anchorHeight);\n\n const nextAvailableMaxHeight = Math.max(\n (useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING,\n 0,\n );\n\n setAvailableMaxHeight(nextAvailableMaxHeight);\n\n setCoordinates({ x, y: useTopAlignment ? y : y + anchorHeight });\n }\n }, [anchorElement, container, contentHeight, direction]);\n\n useIsomorphicLayoutEffect(() => {\n const handleResize = () => {\n calculateCoordinates();\n\n setTimeout(calculateCoordinates, 300);\n };\n\n handleResize();\n\n if (shouldShowDropdown) {\n window.addEventListener('resize', handleResize);\n }\n\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n }, [calculateCoordinates, shouldShowDropdown]);\n\n return useMemo(\n () => ({ shouldUseTopAlignment, coordinates, availableMaxHeight }),\n [availableMaxHeight, coordinates, shouldUseTopAlignment],\n );\n};\n\ninterface UseDropdownOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n contentWidth: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\nexport const useDropdown = ({\n anchorElement,\n container,\n contentHeight,\n contentWidth,\n direction,\n shouldShowDropdown,\n}: UseDropdownOptions) => {\n const { shouldUseTopAlignment, coordinates, availableMaxHeight } = useDropdownPosition({\n anchorElement,\n container,\n contentHeight,\n direction,\n shouldShowDropdown,\n });\n\n const transform = useDropdownAlignment({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n });\n\n const width = anchorElement.clientWidth;\n\n return useMemo(\n () => ({ coordinates, transform, width, availableMaxHeight }),\n [availableMaxHeight, coordinates, transform, width],\n );\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"dropdown.js","names":["_react","require","_dropdown","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","useDropdownListener","onClick","onClose","onTouchEnd","onTouchStart","shouldCaptureEvents","document","addEventListener","removeEventListener","exports","useDropdownAlignment","anchorElement","contentWidth","direction","shouldUseTopAlignment","translateX","setTranslateX","useState","translateY","setTranslateY","DropdownDirection","BOTTOM_LEFT","TOP_LEFT","LEFT","includes","difference","clientWidth","useTopAlignment","TOP","TOP_RIGHT","useMemo","x","y","AVAILABLE_HEIGHT_SPACING","useDropdownPosition","container","contentHeight","shouldShowDropdown","coordinates","setCoordinates","setShouldUseTopAlignment","availableMaxHeight","setAvailableMaxHeight","calculateCoordinates","useCallback","left","anchorLeft","top","anchorTop","height","anchorHeight","getBoundingClientRect","scrollLeft","scrollTop","hasBottomAlignment","BOTTOM","BOTTOM_RIGHT","spaceToTop","spaceToBottom","nextAvailableMaxHeight","Math","max","round","currentAvailableMaxHeight","abs","handleResize","setTimeout","useDropdown","transform","width"],"sources":["../../../src/hooks/dropdown.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { DropdownCoordinates, DropdownDirection } from '../types/dropdown';\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\ninterface UseDropdownListenerOptions {\n onClick: (event: MouseEvent) => void;\n onClose: () => void;\n onTouchEnd: (event: TouchEvent) => void;\n onTouchStart: (event: TouchEvent) => void;\n shouldCaptureEvents?: boolean;\n}\n\nexport const useDropdownListener = ({\n onClick,\n onClose,\n onTouchEnd,\n onTouchStart,\n shouldCaptureEvents,\n}: UseDropdownListenerOptions) => {\n useEffect(() => {\n document.addEventListener('click', onClick, shouldCaptureEvents);\n document.addEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.addEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.addEventListener('blur', onClose);\n\n return () => {\n document.removeEventListener('click', onClick, shouldCaptureEvents);\n document.removeEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.removeEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.removeEventListener('blur', onClose);\n };\n }, [onClick, onClose, onTouchEnd, onTouchStart]);\n};\n\ninterface UseDropdownAlignmentOptions {\n direction: DropdownDirection;\n shouldUseTopAlignment: boolean;\n contentWidth: number;\n anchorElement: Element;\n}\n\nexport const useDropdownAlignment = ({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n}: UseDropdownAlignmentOptions) => {\n const [translateX, setTranslateX] = useState<string>('0px');\n const [translateY, setTranslateY] = useState<string>('0px');\n\n useEffect(() => {\n if (\n [\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.LEFT,\n ].includes(direction)\n ) {\n const difference = anchorElement.clientWidth - contentWidth;\n\n setTranslateX(`${difference}px`);\n } else {\n setTranslateX('0px');\n }\n }, [anchorElement.clientWidth, contentWidth, direction]);\n\n useEffect(() => {\n const useTopAlignment =\n shouldUseTopAlignment ||\n [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n if (useTopAlignment) {\n setTranslateY('-100%');\n } else {\n setTranslateY('0px');\n }\n }, [direction, shouldUseTopAlignment]);\n\n return useMemo(() => ({ x: translateX, y: translateY }), [translateX, translateY]);\n};\n\ninterface UseDropdownPositionOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\n/**\n * The space (in pixels) that should be kept between the dropdown content and the edge of the\n * container when calculating the available maximum height.\n */\nconst AVAILABLE_HEIGHT_SPACING = 16;\n\nexport const useDropdownPosition = ({\n anchorElement,\n container,\n contentHeight = 0,\n direction,\n shouldShowDropdown,\n}: UseDropdownPositionOptions) => {\n const [coordinates, setCoordinates] = useState<DropdownCoordinates>({ x: 0, y: 0 });\n const [shouldUseTopAlignment, setShouldUseTopAlignment] = useState(false);\n const [availableMaxHeight, setAvailableMaxHeight] = useState<number>(0);\n\n const calculateCoordinates = useCallback(() => {\n if (container) {\n const {\n left: anchorLeft,\n top: anchorTop,\n height: anchorHeight,\n } = anchorElement.getBoundingClientRect();\n\n const { left, top, height } = container.getBoundingClientRect();\n\n const x = anchorLeft - left + container.scrollLeft;\n const y = anchorTop - top + container.scrollTop;\n\n let useTopAlignment = [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n const hasBottomAlignment = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n if (!hasBottomAlignment && y + anchorHeight + contentHeight > height) {\n useTopAlignment = true;\n\n setShouldUseTopAlignment(true);\n } else {\n setShouldUseTopAlignment(false);\n }\n\n // Calculate the space that is available for the dropdown content. When the dropdown is\n // opened to the top, the available space reaches from the anchor to the top edge of the\n // container. When it is opened to the bottom, it reaches from the bottom of the anchor\n // to the bottom edge of the container. A small spacing is subtracted so the content does\n // not touch the container edge (e.g. to leave room for shadows).\n const spaceToTop = y;\n const spaceToBottom = height - (y + anchorHeight);\n\n const nextAvailableMaxHeight = Math.max(\n Math.round(\n (useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING,\n ),\n 0,\n );\n\n // Only update the available max height when it changes by more than one pixel. This\n // prevents subpixel fluctuations of getBoundingClientRect from repeatedly triggering\n // re-renders of the consumer, which could otherwise cause a layout shift loop.\n setAvailableMaxHeight((currentAvailableMaxHeight) =>\n Math.abs(currentAvailableMaxHeight - nextAvailableMaxHeight) <= 1\n ? currentAvailableMaxHeight\n : nextAvailableMaxHeight,\n );\n\n setCoordinates({ x, y: useTopAlignment ? y : y + anchorHeight });\n }\n }, [anchorElement, container, contentHeight, direction]);\n\n useIsomorphicLayoutEffect(() => {\n const handleResize = () => {\n calculateCoordinates();\n\n setTimeout(calculateCoordinates, 300);\n };\n\n handleResize();\n\n if (shouldShowDropdown) {\n window.addEventListener('resize', handleResize);\n }\n\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n }, [calculateCoordinates, shouldShowDropdown]);\n\n return useMemo(\n () => ({ shouldUseTopAlignment, coordinates, availableMaxHeight }),\n [availableMaxHeight, coordinates, shouldUseTopAlignment],\n );\n};\n\ninterface UseDropdownOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n contentWidth: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\nexport const useDropdown = ({\n anchorElement,\n container,\n contentHeight,\n contentWidth,\n direction,\n shouldShowDropdown,\n}: UseDropdownOptions) => {\n const { shouldUseTopAlignment, coordinates, availableMaxHeight } = useDropdownPosition({\n anchorElement,\n container,\n contentHeight,\n direction,\n shouldShowDropdown,\n });\n\n const transform = useDropdownAlignment({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n });\n\n const width = anchorElement.clientWidth;\n\n return useMemo(\n () => ({ coordinates, transform, width, availableMaxHeight }),\n [availableMaxHeight, coordinates, transform, width],\n );\n};\n"],"mappings":"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","ignoreList":[]}
@@ -46,10 +46,13 @@ const DropdownBodyWrapper = /*#__PURE__*/forwardRef(({
46
46
  shouldShowDropdown
47
47
  });
48
48
  useEffect(() => {
49
- if (typeof onAvailableMaxHeightChange === 'function') {
49
+ // Only report the available max height while the dropdown is shown. Reporting it while
50
+ // the dropdown is closed would trigger unnecessary re-renders of the consumer (e.g. the
51
+ // ComboBox) during the initial layout, which can cause visible layout shifts.
52
+ if (shouldShowDropdown && typeof onAvailableMaxHeightChange === 'function') {
50
53
  onAvailableMaxHeightChange(availableMaxHeight);
51
54
  }
52
- }, [availableMaxHeight, onAvailableMaxHeightChange]);
55
+ }, [availableMaxHeight, onAvailableMaxHeightChange, shouldShowDropdown]);
53
56
  const handleClose = useCallback(() => {
54
57
  if (typeof onClose === 'function') {
55
58
  onClose();
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownBodyWrapper.js","names":["React","forwardRef","useCallback","useEffect","useImperativeHandle","useRef","useState","StyledDropdownBodyWrapper","StyledDropdownBodyWrapperContent","createPortal","DropdownDirection","DelayedDropdownContent","useDropdown","useDropdownListener","ContainerAnchor","useContainer","DropdownBodyWrapper","anchorElement","bodyWidth","children","container","containerProp","contentHeight","direction","BOTTOM_RIGHT","maxHeight","minBodyWidth","onAvailableMaxHeightChange","onClose","onOutsideClick","onMeasure","shouldCaptureEvents","shouldShowDropdown","ref","isInChaynsWalletRef","measuredContentHeight","setMeasuredContentHeight","measuredContentWidth","setMeasuredContentWidth","portal","setPortal","contentRef","shouldPreventClickRef","touchTimeoutRef","undefined","transform","width","coordinates","availableMaxHeight","contentWidth","handleClose","handleClick","event","current","contains","target","preventDefault","stopPropagation","shouldPreventCloseOnClick","handleContentMeasure","measurements","height","handleTouchEnd","clearTimeout","handleTouchStart","window","setTimeout","onClick","onTouchEnd","onTouchStart","isBottomDirection","BOTTOM","BOTTOM_LEFT","includes","reservationWrapperElement","closest","RESERVATION_WRAPPER","availableHeight","innerHeight","getBoundingClientRect","bottom","additionalNeededSpace","style","marginBottom","createElement","shouldShowContent","$width","$minWidth","$maxHeight","$direction","className","tabIndex","displayName"],"sources":["../../../../src/components/dropdown-body-wrapper/DropdownBodyWrapper.tsx"],"sourcesContent":["import React, {\n forwardRef,\n ReactNode,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport {\n StyledDropdownBodyWrapper,\n StyledDropdownBodyWrapperContent,\n} from './DropdownBodyWrapper.styles';\nimport { createPortal } from 'react-dom';\nimport { DropdownDirection, DropdownMeasurements } from '../../types/dropdown';\nimport DelayedDropdownContent, {\n DelayedDropdownContentProps,\n} from './delayed-dropdown-content/DelayedDropdownContent';\nimport { useDropdown, useDropdownListener } from '../../hooks/dropdown';\nimport { ContainerAnchor, useContainer } from '../../hooks/container';\n\ninterface DropdownBodyWrapperProps {\n /**\n * The anchor element of the dropdown.\n */\n anchorElement: Element;\n /**\n * The width of the Body.\n */\n bodyWidth?: number;\n /**\n * The content of the dropdown body.\n */\n children: ReactNode;\n /**\n * The element where the content should be rendered via React Portal.\n */\n container?: Element;\n /**\n * The height of the content\n */\n contentHeight?: number;\n /**\n * The direction of the dropdown.\n */\n direction?: DropdownDirection;\n /**\n * The max height of the dropdown.\n */\n maxHeight?: number;\n /**\n * The minimum width of the body.\n */\n minBodyWidth?: number;\n /**\n * Function to be executed when the available maximum height of the dropdown changes. The\n * available maximum height is the space that is available for the dropdown content until the\n * edge of the container is reached (minus a small spacing). This can be used to limit the\n * content height, so the dropdown is not cut off when there is not enough space.\n */\n onAvailableMaxHeightChange?: (availableMaxHeight: number) => void;\n /**\n * Function to be executed when the body is closed.\n */\n onClose?: VoidFunction;\n /**\n * Function to be executed when the user clicks outside the dropdown.\n * If the function returns `true`, the dropdown will not be closed.\n */\n onOutsideClick?: () => boolean | void;\n /**\n * Function to be executed when the content is measured.\n */\n onMeasure?: DelayedDropdownContentProps['onMeasure'];\n /**\n * Whether the dropdown should be visible.\n */\n shouldShowDropdown: boolean;\n /**\n * Whether the outside events should be captured.\n */\n shouldCaptureEvents?: boolean;\n}\n\nconst DropdownBodyWrapper = forwardRef<HTMLDivElement, DropdownBodyWrapperProps>(\n (\n {\n anchorElement,\n bodyWidth,\n children,\n container: containerProp,\n contentHeight = 0,\n direction = DropdownDirection.BOTTOM_RIGHT,\n maxHeight,\n minBodyWidth = 0,\n onAvailableMaxHeightChange,\n onClose,\n onOutsideClick,\n onMeasure,\n shouldCaptureEvents = true,\n shouldShowDropdown,\n },\n ref,\n ) => {\n const isInChaynsWalletRef = useRef(false);\n\n const [measuredContentHeight, setMeasuredContentHeight] = useState<number>(0);\n const [measuredContentWidth, setMeasuredContentWidth] = useState<number>(0);\n const [portal, setPortal] = useState<ReactPortal>();\n\n const contentRef = useRef<HTMLDivElement>(null);\n const shouldPreventClickRef = useRef<boolean>(false);\n const touchTimeoutRef = useRef<number | undefined>(undefined);\n\n const container = useContainer({ anchorElement, container: containerProp });\n\n const { transform, width, coordinates, availableMaxHeight } = useDropdown({\n anchorElement,\n container,\n contentHeight,\n contentWidth: bodyWidth ?? measuredContentWidth,\n direction,\n shouldShowDropdown,\n });\n\n useEffect(() => {\n if (typeof onAvailableMaxHeightChange === 'function') {\n onAvailableMaxHeightChange(availableMaxHeight);\n }\n }, [availableMaxHeight, onAvailableMaxHeightChange]);\n\n const handleClose = useCallback(() => {\n if (typeof onClose === 'function') {\n onClose();\n }\n }, [onClose]);\n\n /**\n * This function closes the body\n */\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (\n contentRef.current &&\n shouldShowDropdown &&\n !anchorElement.contains(event.target as Node) &&\n !contentRef.current.contains(event.target as Node)\n ) {\n event.preventDefault();\n event.stopPropagation();\n\n const shouldPreventCloseOnClick = onOutsideClick?.() ?? false;\n\n if (!shouldPreventClickRef.current && !shouldPreventCloseOnClick) {\n handleClose();\n }\n }\n\n shouldPreventClickRef.current = false;\n },\n [anchorElement, handleClose, onOutsideClick, shouldShowDropdown],\n );\n\n const handleContentMeasure = useCallback(\n (measurements: DropdownMeasurements) => {\n // Measurements are only needed if the content is shown in the chayns wallet. To prevent\n // unnecessary renders, we only set the height if the content is shown in the wallet.\n if (isInChaynsWalletRef.current) {\n setMeasuredContentHeight(measurements.height);\n }\n\n setMeasuredContentWidth(measurements.width);\n\n if (typeof onMeasure === 'function') {\n onMeasure(measurements);\n }\n },\n [onMeasure],\n );\n\n const handleTouchEnd = useCallback(() => {\n clearTimeout(touchTimeoutRef.current);\n }, []);\n\n const handleTouchStart = useCallback(() => {\n touchTimeoutRef.current = window.setTimeout(() => {\n shouldPreventClickRef.current = true;\n }, 500);\n }, []);\n\n /**\n * This hook listens for clicks\n */\n useDropdownListener({\n onClick: handleClick,\n onClose: handleClose,\n onTouchEnd: handleTouchEnd,\n onTouchStart: handleTouchStart,\n shouldCaptureEvents,\n });\n\n useEffect(() => {\n const isBottomDirection = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n const reservationWrapperElement = anchorElement.closest<HTMLDivElement>(\n ContainerAnchor.RESERVATION_WRAPPER,\n );\n\n isInChaynsWalletRef.current =\n !!(\n reservationWrapperElement && reservationWrapperElement.contains(anchorElement)\n ) || true;\n\n // This effect checks if additional space is needed to show dropdown content in chayns cards.\n if (\n isBottomDirection &&\n isInChaynsWalletRef.current &&\n measuredContentHeight > 0 &&\n reservationWrapperElement &&\n shouldShowDropdown\n ) {\n const availableHeight =\n window.innerHeight - anchorElement.getBoundingClientRect().bottom;\n\n // If the content height is greater than the available height, we need to add additional space.\n // This is to ensure that the dropdown content is fully visible. The 16 pixels are a buffer for shadows.\n const additionalNeededSpace = measuredContentHeight + 16 - availableHeight;\n\n if (additionalNeededSpace > 0) {\n // Add margin bottom to the reservation wrapper to ensure the dropdown content is fully visible.\n reservationWrapperElement.style.marginBottom = `${additionalNeededSpace}px`;\n } else {\n // Reset the margin bottom if no additional space is needed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n }\n\n if (isInChaynsWalletRef.current && reservationWrapperElement && !shouldShowDropdown) {\n // Reset the margin bottom when the dropdown is closed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n\n return () => {\n if (reservationWrapperElement) {\n reservationWrapperElement.style.marginBottom = '0px';\n }\n };\n }, [anchorElement, direction, measuredContentHeight, shouldShowDropdown]);\n\n useEffect(() => {\n if (!container) return;\n\n setPortal(() =>\n createPortal(\n <DelayedDropdownContent\n coordinates={coordinates}\n onMeasure={handleContentMeasure}\n shouldShowContent={shouldShowDropdown}\n transform={transform}\n >\n <StyledDropdownBodyWrapperContent\n $width={width}\n $minWidth={minBodyWidth}\n $maxHeight={maxHeight}\n $direction={direction}\n ref={contentRef}\n className={\n typeof maxHeight === 'number' ? 'chayns-scrollbar' : undefined\n }\n tabIndex={0}\n >\n {children}\n </StyledDropdownBodyWrapperContent>\n </DelayedDropdownContent>,\n container,\n ),\n );\n }, [\n children,\n container,\n coordinates,\n direction,\n handleContentMeasure,\n maxHeight,\n minBodyWidth,\n shouldShowDropdown,\n transform,\n width,\n ]);\n\n useImperativeHandle(ref, () => contentRef.current!, []);\n\n return <StyledDropdownBodyWrapper>{portal}</StyledDropdownBodyWrapper>;\n },\n);\n\nDropdownBodyWrapper.displayName = 'DropdownBodyWrapper';\n\nexport default DropdownBodyWrapper;\n"],"mappings":"AAAA,OAAOA,KAAK,IACRC,UAAU,EAGVC,WAAW,EACXC,SAAS,EACTC,mBAAmB,EACnBC,MAAM,EACNC,QAAQ,QACL,OAAO;AACd,SACIC,yBAAyB,EACzBC,gCAAgC,QAC7B,8BAA8B;AACrC,SAASC,YAAY,QAAQ,WAAW;AACxC,SAASC,iBAAiB,QAA8B,sBAAsB;AAC9E,OAAOC,sBAAsB,MAEtB,mDAAmD;AAC1D,SAASC,WAAW,EAAEC,mBAAmB,QAAQ,sBAAsB;AACvE,SAASC,eAAe,EAAEC,YAAY,QAAQ,uBAAuB;AAiErE,MAAMC,mBAAmB,gBAAGf,UAAU,CAClC,CACI;EACIgB,aAAa;EACbC,SAAS;EACTC,QAAQ;EACRC,SAAS,EAAEC,aAAa;EACxBC,aAAa,GAAG,CAAC;EACjBC,SAAS,GAAGb,iBAAiB,CAACc,YAAY;EAC1CC,SAAS;EACTC,YAAY,GAAG,CAAC;EAChBC,0BAA0B;EAC1BC,OAAO;EACPC,cAAc;EACdC,SAAS;EACTC,mBAAmB,GAAG,IAAI;EAC1BC;AACJ,CAAC,EACDC,GAAG,KACF;EACD,MAAMC,mBAAmB,GAAG7B,MAAM,CAAC,KAAK,CAAC;EAEzC,MAAM,CAAC8B,qBAAqB,EAAEC,wBAAwB,CAAC,GAAG9B,QAAQ,CAAS,CAAC,CAAC;EAC7E,MAAM,CAAC+B,oBAAoB,EAAEC,uBAAuB,CAAC,GAAGhC,QAAQ,CAAS,CAAC,CAAC;EAC3E,MAAM,CAACiC,MAAM,EAAEC,SAAS,CAAC,GAAGlC,QAAQ,CAAc,CAAC;EAEnD,MAAMmC,UAAU,GAAGpC,MAAM,CAAiB,IAAI,CAAC;EAC/C,MAAMqC,qBAAqB,GAAGrC,MAAM,CAAU,KAAK,CAAC;EACpD,MAAMsC,eAAe,GAAGtC,MAAM,CAAqBuC,SAAS,CAAC;EAE7D,MAAMxB,SAAS,GAAGL,YAAY,CAAC;IAAEE,aAAa;IAAEG,SAAS,EAAEC;EAAc,CAAC,CAAC;EAE3E,MAAM;IAAEwB,SAAS;IAAEC,KAAK;IAAEC,WAAW;IAAEC;EAAmB,CAAC,GAAGpC,WAAW,CAAC;IACtEK,aAAa;IACbG,SAAS;IACTE,aAAa;IACb2B,YAAY,EAAE/B,SAAS,IAAImB,oBAAoB;IAC/Cd,SAAS;IACTS;EACJ,CAAC,CAAC;EAEF7B,SAAS,CAAC,MAAM;IACZ,IAAI,OAAOwB,0BAA0B,KAAK,UAAU,EAAE;MAClDA,0BAA0B,CAACqB,kBAAkB,CAAC;IAClD;EACJ,CAAC,EAAE,CAACA,kBAAkB,EAAErB,0BAA0B,CAAC,CAAC;EAEpD,MAAMuB,WAAW,GAAGhD,WAAW,CAAC,MAAM;IAClC,IAAI,OAAO0B,OAAO,KAAK,UAAU,EAAE;MAC/BA,OAAO,CAAC,CAAC;IACb;EACJ,CAAC,EAAE,CAACA,OAAO,CAAC,CAAC;;EAEb;AACR;AACA;EACQ,MAAMuB,WAAW,GAAGjD,WAAW,CAC1BkD,KAAiB,IAAK;IACnB,IACIX,UAAU,CAACY,OAAO,IAClBrB,kBAAkB,IAClB,CAACf,aAAa,CAACqC,QAAQ,CAACF,KAAK,CAACG,MAAc,CAAC,IAC7C,CAACd,UAAU,CAACY,OAAO,CAACC,QAAQ,CAACF,KAAK,CAACG,MAAc,CAAC,EACpD;MACEH,KAAK,CAACI,cAAc,CAAC,CAAC;MACtBJ,KAAK,CAACK,eAAe,CAAC,CAAC;MAEvB,MAAMC,yBAAyB,GAAG7B,cAAc,GAAG,CAAC,IAAI,KAAK;MAE7D,IAAI,CAACa,qBAAqB,CAACW,OAAO,IAAI,CAACK,yBAAyB,EAAE;QAC9DR,WAAW,CAAC,CAAC;MACjB;IACJ;IAEAR,qBAAqB,CAACW,OAAO,GAAG,KAAK;EACzC,CAAC,EACD,CAACpC,aAAa,EAAEiC,WAAW,EAAErB,cAAc,EAAEG,kBAAkB,CACnE,CAAC;EAED,MAAM2B,oBAAoB,GAAGzD,WAAW,CACnC0D,YAAkC,IAAK;IACpC;IACA;IACA,IAAI1B,mBAAmB,CAACmB,OAAO,EAAE;MAC7BjB,wBAAwB,CAACwB,YAAY,CAACC,MAAM,CAAC;IACjD;IAEAvB,uBAAuB,CAACsB,YAAY,CAACd,KAAK,CAAC;IAE3C,IAAI,OAAOhB,SAAS,KAAK,UAAU,EAAE;MACjCA,SAAS,CAAC8B,YAAY,CAAC;IAC3B;EACJ,CAAC,EACD,CAAC9B,SAAS,CACd,CAAC;EAED,MAAMgC,cAAc,GAAG5D,WAAW,CAAC,MAAM;IACrC6D,YAAY,CAACpB,eAAe,CAACU,OAAO,CAAC;EACzC,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMW,gBAAgB,GAAG9D,WAAW,CAAC,MAAM;IACvCyC,eAAe,CAACU,OAAO,GAAGY,MAAM,CAACC,UAAU,CAAC,MAAM;MAC9CxB,qBAAqB,CAACW,OAAO,GAAG,IAAI;IACxC,CAAC,EAAE,GAAG,CAAC;EACX,CAAC,EAAE,EAAE,CAAC;;EAEN;AACR;AACA;EACQxC,mBAAmB,CAAC;IAChBsD,OAAO,EAAEhB,WAAW;IACpBvB,OAAO,EAAEsB,WAAW;IACpBkB,UAAU,EAAEN,cAAc;IAC1BO,YAAY,EAAEL,gBAAgB;IAC9BjC;EACJ,CAAC,CAAC;EAEF5B,SAAS,CAAC,MAAM;IACZ,MAAMmE,iBAAiB,GAAG,CACtB5D,iBAAiB,CAAC6D,MAAM,EACxB7D,iBAAiB,CAAC8D,WAAW,EAC7B9D,iBAAiB,CAACc,YAAY,CACjC,CAACiD,QAAQ,CAAClD,SAAS,CAAC;IAErB,MAAMmD,yBAAyB,GAAGzD,aAAa,CAAC0D,OAAO,CACnD7D,eAAe,CAAC8D,mBACpB,CAAC;IAED1C,mBAAmB,CAACmB,OAAO,GACvB,CAAC,EACGqB,yBAAyB,IAAIA,yBAAyB,CAACpB,QAAQ,CAACrC,aAAa,CAAC,CACjF,IAAI,IAAI;;IAEb;IACA,IACIqD,iBAAiB,IACjBpC,mBAAmB,CAACmB,OAAO,IAC3BlB,qBAAqB,GAAG,CAAC,IACzBuC,yBAAyB,IACzB1C,kBAAkB,EACpB;MACE,MAAM6C,eAAe,GACjBZ,MAAM,CAACa,WAAW,GAAG7D,aAAa,CAAC8D,qBAAqB,CAAC,CAAC,CAACC,MAAM;;MAErE;MACA;MACA,MAAMC,qBAAqB,GAAG9C,qBAAqB,GAAG,EAAE,GAAG0C,eAAe;MAE1E,IAAII,qBAAqB,GAAG,CAAC,EAAE;QAC3B;QACAP,yBAAyB,CAACQ,KAAK,CAACC,YAAY,GAAG,GAAGF,qBAAqB,IAAI;MAC/E,CAAC,MAAM;QACH;QACAP,yBAAyB,CAACQ,KAAK,CAACC,YAAY,GAAG,KAAK;MACxD;IACJ;IAEA,IAAIjD,mBAAmB,CAACmB,OAAO,IAAIqB,yBAAyB,IAAI,CAAC1C,kBAAkB,EAAE;MACjF;MACA0C,yBAAyB,CAACQ,KAAK,CAACC,YAAY,GAAG,KAAK;IACxD;IAEA,OAAO,MAAM;MACT,IAAIT,yBAAyB,EAAE;QAC3BA,yBAAyB,CAACQ,KAAK,CAACC,YAAY,GAAG,KAAK;MACxD;IACJ,CAAC;EACL,CAAC,EAAE,CAAClE,aAAa,EAAEM,SAAS,EAAEY,qBAAqB,EAAEH,kBAAkB,CAAC,CAAC;EAEzE7B,SAAS,CAAC,MAAM;IACZ,IAAI,CAACiB,SAAS,EAAE;IAEhBoB,SAAS,CAAC,mBACN/B,YAAY,cACRT,KAAA,CAAAoF,aAAA,CAACzE,sBAAsB;MACnBoC,WAAW,EAAEA,WAAY;MACzBjB,SAAS,EAAE6B,oBAAqB;MAChC0B,iBAAiB,EAAErD,kBAAmB;MACtCa,SAAS,EAAEA;IAAU,gBAErB7C,KAAA,CAAAoF,aAAA,CAAC5E,gCAAgC;MAC7B8E,MAAM,EAAExC,KAAM;MACdyC,SAAS,EAAE7D,YAAa;MACxB8D,UAAU,EAAE/D,SAAU;MACtBgE,UAAU,EAAElE,SAAU;MACtBU,GAAG,EAAEQ,UAAW;MAChBiD,SAAS,EACL,OAAOjE,SAAS,KAAK,QAAQ,GAAG,kBAAkB,GAAGmB,SACxD;MACD+C,QAAQ,EAAE;IAAE,GAEXxE,QAC6B,CACd,CAAC,EACzBC,SACJ,CACJ,CAAC;EACL,CAAC,EAAE,CACCD,QAAQ,EACRC,SAAS,EACT2B,WAAW,EACXxB,SAAS,EACToC,oBAAoB,EACpBlC,SAAS,EACTC,YAAY,EACZM,kBAAkB,EAClBa,SAAS,EACTC,KAAK,CACR,CAAC;EAEF1C,mBAAmB,CAAC6B,GAAG,EAAE,MAAMQ,UAAU,CAACY,OAAQ,EAAE,EAAE,CAAC;EAEvD,oBAAOrD,KAAA,CAAAoF,aAAA,CAAC7E,yBAAyB,QAAEgC,MAAkC,CAAC;AAC1E,CACJ,CAAC;AAEDvB,mBAAmB,CAAC4E,WAAW,GAAG,qBAAqB;AAEvD,eAAe5E,mBAAmB","ignoreList":[]}
1
+ {"version":3,"file":"DropdownBodyWrapper.js","names":["React","forwardRef","useCallback","useEffect","useImperativeHandle","useRef","useState","StyledDropdownBodyWrapper","StyledDropdownBodyWrapperContent","createPortal","DropdownDirection","DelayedDropdownContent","useDropdown","useDropdownListener","ContainerAnchor","useContainer","DropdownBodyWrapper","anchorElement","bodyWidth","children","container","containerProp","contentHeight","direction","BOTTOM_RIGHT","maxHeight","minBodyWidth","onAvailableMaxHeightChange","onClose","onOutsideClick","onMeasure","shouldCaptureEvents","shouldShowDropdown","ref","isInChaynsWalletRef","measuredContentHeight","setMeasuredContentHeight","measuredContentWidth","setMeasuredContentWidth","portal","setPortal","contentRef","shouldPreventClickRef","touchTimeoutRef","undefined","transform","width","coordinates","availableMaxHeight","contentWidth","handleClose","handleClick","event","current","contains","target","preventDefault","stopPropagation","shouldPreventCloseOnClick","handleContentMeasure","measurements","height","handleTouchEnd","clearTimeout","handleTouchStart","window","setTimeout","onClick","onTouchEnd","onTouchStart","isBottomDirection","BOTTOM","BOTTOM_LEFT","includes","reservationWrapperElement","closest","RESERVATION_WRAPPER","availableHeight","innerHeight","getBoundingClientRect","bottom","additionalNeededSpace","style","marginBottom","createElement","shouldShowContent","$width","$minWidth","$maxHeight","$direction","className","tabIndex","displayName"],"sources":["../../../../src/components/dropdown-body-wrapper/DropdownBodyWrapper.tsx"],"sourcesContent":["import React, {\n forwardRef,\n ReactNode,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport {\n StyledDropdownBodyWrapper,\n StyledDropdownBodyWrapperContent,\n} from './DropdownBodyWrapper.styles';\nimport { createPortal } from 'react-dom';\nimport { DropdownDirection, DropdownMeasurements } from '../../types/dropdown';\nimport DelayedDropdownContent, {\n DelayedDropdownContentProps,\n} from './delayed-dropdown-content/DelayedDropdownContent';\nimport { useDropdown, useDropdownListener } from '../../hooks/dropdown';\nimport { ContainerAnchor, useContainer } from '../../hooks/container';\n\ninterface DropdownBodyWrapperProps {\n /**\n * The anchor element of the dropdown.\n */\n anchorElement: Element;\n /**\n * The width of the Body.\n */\n bodyWidth?: number;\n /**\n * The content of the dropdown body.\n */\n children: ReactNode;\n /**\n * The element where the content should be rendered via React Portal.\n */\n container?: Element;\n /**\n * The height of the content\n */\n contentHeight?: number;\n /**\n * The direction of the dropdown.\n */\n direction?: DropdownDirection;\n /**\n * The max height of the dropdown.\n */\n maxHeight?: number;\n /**\n * The minimum width of the body.\n */\n minBodyWidth?: number;\n /**\n * Function to be executed when the available maximum height of the dropdown changes. The\n * available maximum height is the space that is available for the dropdown content until the\n * edge of the container is reached (minus a small spacing). This can be used to limit the\n * content height, so the dropdown is not cut off when there is not enough space.\n */\n onAvailableMaxHeightChange?: (availableMaxHeight: number) => void;\n /**\n * Function to be executed when the body is closed.\n */\n onClose?: VoidFunction;\n /**\n * Function to be executed when the user clicks outside the dropdown.\n * If the function returns `true`, the dropdown will not be closed.\n */\n onOutsideClick?: () => boolean | void;\n /**\n * Function to be executed when the content is measured.\n */\n onMeasure?: DelayedDropdownContentProps['onMeasure'];\n /**\n * Whether the dropdown should be visible.\n */\n shouldShowDropdown: boolean;\n /**\n * Whether the outside events should be captured.\n */\n shouldCaptureEvents?: boolean;\n}\n\nconst DropdownBodyWrapper = forwardRef<HTMLDivElement, DropdownBodyWrapperProps>(\n (\n {\n anchorElement,\n bodyWidth,\n children,\n container: containerProp,\n contentHeight = 0,\n direction = DropdownDirection.BOTTOM_RIGHT,\n maxHeight,\n minBodyWidth = 0,\n onAvailableMaxHeightChange,\n onClose,\n onOutsideClick,\n onMeasure,\n shouldCaptureEvents = true,\n shouldShowDropdown,\n },\n ref,\n ) => {\n const isInChaynsWalletRef = useRef(false);\n\n const [measuredContentHeight, setMeasuredContentHeight] = useState<number>(0);\n const [measuredContentWidth, setMeasuredContentWidth] = useState<number>(0);\n const [portal, setPortal] = useState<ReactPortal>();\n\n const contentRef = useRef<HTMLDivElement>(null);\n const shouldPreventClickRef = useRef<boolean>(false);\n const touchTimeoutRef = useRef<number | undefined>(undefined);\n\n const container = useContainer({ anchorElement, container: containerProp });\n\n const { transform, width, coordinates, availableMaxHeight } = useDropdown({\n anchorElement,\n container,\n contentHeight,\n contentWidth: bodyWidth ?? measuredContentWidth,\n direction,\n shouldShowDropdown,\n });\n\n useEffect(() => {\n // Only report the available max height while the dropdown is shown. Reporting it while\n // the dropdown is closed would trigger unnecessary re-renders of the consumer (e.g. the\n // ComboBox) during the initial layout, which can cause visible layout shifts.\n if (shouldShowDropdown && typeof onAvailableMaxHeightChange === 'function') {\n onAvailableMaxHeightChange(availableMaxHeight);\n }\n }, [availableMaxHeight, onAvailableMaxHeightChange, shouldShowDropdown]);\n\n const handleClose = useCallback(() => {\n if (typeof onClose === 'function') {\n onClose();\n }\n }, [onClose]);\n\n /**\n * This function closes the body\n */\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (\n contentRef.current &&\n shouldShowDropdown &&\n !anchorElement.contains(event.target as Node) &&\n !contentRef.current.contains(event.target as Node)\n ) {\n event.preventDefault();\n event.stopPropagation();\n\n const shouldPreventCloseOnClick = onOutsideClick?.() ?? false;\n\n if (!shouldPreventClickRef.current && !shouldPreventCloseOnClick) {\n handleClose();\n }\n }\n\n shouldPreventClickRef.current = false;\n },\n [anchorElement, handleClose, onOutsideClick, shouldShowDropdown],\n );\n\n const handleContentMeasure = useCallback(\n (measurements: DropdownMeasurements) => {\n // Measurements are only needed if the content is shown in the chayns wallet. To prevent\n // unnecessary renders, we only set the height if the content is shown in the wallet.\n if (isInChaynsWalletRef.current) {\n setMeasuredContentHeight(measurements.height);\n }\n\n setMeasuredContentWidth(measurements.width);\n\n if (typeof onMeasure === 'function') {\n onMeasure(measurements);\n }\n },\n [onMeasure],\n );\n\n const handleTouchEnd = useCallback(() => {\n clearTimeout(touchTimeoutRef.current);\n }, []);\n\n const handleTouchStart = useCallback(() => {\n touchTimeoutRef.current = window.setTimeout(() => {\n shouldPreventClickRef.current = true;\n }, 500);\n }, []);\n\n /**\n * This hook listens for clicks\n */\n useDropdownListener({\n onClick: handleClick,\n onClose: handleClose,\n onTouchEnd: handleTouchEnd,\n onTouchStart: handleTouchStart,\n shouldCaptureEvents,\n });\n\n useEffect(() => {\n const isBottomDirection = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n const reservationWrapperElement = anchorElement.closest<HTMLDivElement>(\n ContainerAnchor.RESERVATION_WRAPPER,\n );\n\n isInChaynsWalletRef.current =\n !!(\n reservationWrapperElement && reservationWrapperElement.contains(anchorElement)\n ) || true;\n\n // This effect checks if additional space is needed to show dropdown content in chayns cards.\n if (\n isBottomDirection &&\n isInChaynsWalletRef.current &&\n measuredContentHeight > 0 &&\n reservationWrapperElement &&\n shouldShowDropdown\n ) {\n const availableHeight =\n window.innerHeight - anchorElement.getBoundingClientRect().bottom;\n\n // If the content height is greater than the available height, we need to add additional space.\n // This is to ensure that the dropdown content is fully visible. The 16 pixels are a buffer for shadows.\n const additionalNeededSpace = measuredContentHeight + 16 - availableHeight;\n\n if (additionalNeededSpace > 0) {\n // Add margin bottom to the reservation wrapper to ensure the dropdown content is fully visible.\n reservationWrapperElement.style.marginBottom = `${additionalNeededSpace}px`;\n } else {\n // Reset the margin bottom if no additional space is needed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n }\n\n if (isInChaynsWalletRef.current && reservationWrapperElement && !shouldShowDropdown) {\n // Reset the margin bottom when the dropdown is closed.\n reservationWrapperElement.style.marginBottom = '0px';\n }\n\n return () => {\n if (reservationWrapperElement) {\n reservationWrapperElement.style.marginBottom = '0px';\n }\n };\n }, [anchorElement, direction, measuredContentHeight, shouldShowDropdown]);\n\n useEffect(() => {\n if (!container) return;\n\n setPortal(() =>\n createPortal(\n <DelayedDropdownContent\n coordinates={coordinates}\n onMeasure={handleContentMeasure}\n shouldShowContent={shouldShowDropdown}\n transform={transform}\n >\n <StyledDropdownBodyWrapperContent\n $width={width}\n $minWidth={minBodyWidth}\n $maxHeight={maxHeight}\n $direction={direction}\n ref={contentRef}\n className={\n typeof maxHeight === 'number' ? 'chayns-scrollbar' : undefined\n }\n tabIndex={0}\n >\n {children}\n </StyledDropdownBodyWrapperContent>\n </DelayedDropdownContent>,\n container,\n ),\n );\n }, [\n children,\n container,\n coordinates,\n direction,\n handleContentMeasure,\n maxHeight,\n minBodyWidth,\n shouldShowDropdown,\n transform,\n width,\n ]);\n\n useImperativeHandle(ref, () => contentRef.current!, []);\n\n return <StyledDropdownBodyWrapper>{portal}</StyledDropdownBodyWrapper>;\n },\n);\n\nDropdownBodyWrapper.displayName = 'DropdownBodyWrapper';\n\nexport default DropdownBodyWrapper;\n"],"mappings":"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","ignoreList":[]}
@@ -98,8 +98,12 @@ export const useDropdownPosition = ({
98
98
  // not touch the container edge (e.g. to leave room for shadows).
99
99
  const spaceToTop = y;
100
100
  const spaceToBottom = height - (y + anchorHeight);
101
- const nextAvailableMaxHeight = Math.max((useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING, 0);
102
- setAvailableMaxHeight(nextAvailableMaxHeight);
101
+ const nextAvailableMaxHeight = Math.max(Math.round((useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING), 0);
102
+
103
+ // Only update the available max height when it changes by more than one pixel. This
104
+ // prevents subpixel fluctuations of getBoundingClientRect from repeatedly triggering
105
+ // re-renders of the consumer, which could otherwise cause a layout shift loop.
106
+ setAvailableMaxHeight(currentAvailableMaxHeight => Math.abs(currentAvailableMaxHeight - nextAvailableMaxHeight) <= 1 ? currentAvailableMaxHeight : nextAvailableMaxHeight);
103
107
  setCoordinates({
104
108
  x,
105
109
  y: useTopAlignment ? y : y + anchorHeight
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.js","names":["useCallback","useEffect","useLayoutEffect","useMemo","useState","DropdownDirection","useIsomorphicLayoutEffect","window","useDropdownListener","onClick","onClose","onTouchEnd","onTouchStart","shouldCaptureEvents","document","addEventListener","removeEventListener","useDropdownAlignment","anchorElement","contentWidth","direction","shouldUseTopAlignment","translateX","setTranslateX","translateY","setTranslateY","BOTTOM_LEFT","TOP_LEFT","LEFT","includes","difference","clientWidth","useTopAlignment","TOP","TOP_RIGHT","x","y","AVAILABLE_HEIGHT_SPACING","useDropdownPosition","container","contentHeight","shouldShowDropdown","coordinates","setCoordinates","setShouldUseTopAlignment","availableMaxHeight","setAvailableMaxHeight","calculateCoordinates","left","anchorLeft","top","anchorTop","height","anchorHeight","getBoundingClientRect","scrollLeft","scrollTop","hasBottomAlignment","BOTTOM","BOTTOM_RIGHT","spaceToTop","spaceToBottom","nextAvailableMaxHeight","Math","max","handleResize","setTimeout","useDropdown","transform","width"],"sources":["../../../src/hooks/dropdown.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { DropdownCoordinates, DropdownDirection } from '../types/dropdown';\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\ninterface UseDropdownListenerOptions {\n onClick: (event: MouseEvent) => void;\n onClose: () => void;\n onTouchEnd: (event: TouchEvent) => void;\n onTouchStart: (event: TouchEvent) => void;\n shouldCaptureEvents?: boolean;\n}\n\nexport const useDropdownListener = ({\n onClick,\n onClose,\n onTouchEnd,\n onTouchStart,\n shouldCaptureEvents,\n}: UseDropdownListenerOptions) => {\n useEffect(() => {\n document.addEventListener('click', onClick, shouldCaptureEvents);\n document.addEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.addEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.addEventListener('blur', onClose);\n\n return () => {\n document.removeEventListener('click', onClick, shouldCaptureEvents);\n document.removeEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.removeEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.removeEventListener('blur', onClose);\n };\n }, [onClick, onClose, onTouchEnd, onTouchStart]);\n};\n\ninterface UseDropdownAlignmentOptions {\n direction: DropdownDirection;\n shouldUseTopAlignment: boolean;\n contentWidth: number;\n anchorElement: Element;\n}\n\nexport const useDropdownAlignment = ({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n}: UseDropdownAlignmentOptions) => {\n const [translateX, setTranslateX] = useState<string>('0px');\n const [translateY, setTranslateY] = useState<string>('0px');\n\n useEffect(() => {\n if (\n [\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.LEFT,\n ].includes(direction)\n ) {\n const difference = anchorElement.clientWidth - contentWidth;\n\n setTranslateX(`${difference}px`);\n } else {\n setTranslateX('0px');\n }\n }, [anchorElement.clientWidth, contentWidth, direction]);\n\n useEffect(() => {\n const useTopAlignment =\n shouldUseTopAlignment ||\n [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n if (useTopAlignment) {\n setTranslateY('-100%');\n } else {\n setTranslateY('0px');\n }\n }, [direction, shouldUseTopAlignment]);\n\n return useMemo(() => ({ x: translateX, y: translateY }), [translateX, translateY]);\n};\n\ninterface UseDropdownPositionOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\n/**\n * The space (in pixels) that should be kept between the dropdown content and the edge of the\n * container when calculating the available maximum height.\n */\nconst AVAILABLE_HEIGHT_SPACING = 16;\n\nexport const useDropdownPosition = ({\n anchorElement,\n container,\n contentHeight = 0,\n direction,\n shouldShowDropdown,\n}: UseDropdownPositionOptions) => {\n const [coordinates, setCoordinates] = useState<DropdownCoordinates>({ x: 0, y: 0 });\n const [shouldUseTopAlignment, setShouldUseTopAlignment] = useState(false);\n const [availableMaxHeight, setAvailableMaxHeight] = useState<number>(0);\n\n const calculateCoordinates = useCallback(() => {\n if (container) {\n const {\n left: anchorLeft,\n top: anchorTop,\n height: anchorHeight,\n } = anchorElement.getBoundingClientRect();\n\n const { left, top, height } = container.getBoundingClientRect();\n\n const x = anchorLeft - left + container.scrollLeft;\n const y = anchorTop - top + container.scrollTop;\n\n let useTopAlignment = [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n const hasBottomAlignment = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n if (!hasBottomAlignment && y + anchorHeight + contentHeight > height) {\n useTopAlignment = true;\n\n setShouldUseTopAlignment(true);\n } else {\n setShouldUseTopAlignment(false);\n }\n\n // Calculate the space that is available for the dropdown content. When the dropdown is\n // opened to the top, the available space reaches from the anchor to the top edge of the\n // container. When it is opened to the bottom, it reaches from the bottom of the anchor\n // to the bottom edge of the container. A small spacing is subtracted so the content does\n // not touch the container edge (e.g. to leave room for shadows).\n const spaceToTop = y;\n const spaceToBottom = height - (y + anchorHeight);\n\n const nextAvailableMaxHeight = Math.max(\n (useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING,\n 0,\n );\n\n setAvailableMaxHeight(nextAvailableMaxHeight);\n\n setCoordinates({ x, y: useTopAlignment ? y : y + anchorHeight });\n }\n }, [anchorElement, container, contentHeight, direction]);\n\n useIsomorphicLayoutEffect(() => {\n const handleResize = () => {\n calculateCoordinates();\n\n setTimeout(calculateCoordinates, 300);\n };\n\n handleResize();\n\n if (shouldShowDropdown) {\n window.addEventListener('resize', handleResize);\n }\n\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n }, [calculateCoordinates, shouldShowDropdown]);\n\n return useMemo(\n () => ({ shouldUseTopAlignment, coordinates, availableMaxHeight }),\n [availableMaxHeight, coordinates, shouldUseTopAlignment],\n );\n};\n\ninterface UseDropdownOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n contentWidth: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\nexport const useDropdown = ({\n anchorElement,\n container,\n contentHeight,\n contentWidth,\n direction,\n shouldShowDropdown,\n}: UseDropdownOptions) => {\n const { shouldUseTopAlignment, coordinates, availableMaxHeight } = useDropdownPosition({\n anchorElement,\n container,\n contentHeight,\n direction,\n shouldShowDropdown,\n });\n\n const transform = useDropdownAlignment({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n });\n\n const width = anchorElement.clientWidth;\n\n return useMemo(\n () => ({ coordinates, transform, width, availableMaxHeight }),\n [availableMaxHeight, coordinates, transform, width],\n );\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"dropdown.js","names":["useCallback","useEffect","useLayoutEffect","useMemo","useState","DropdownDirection","useIsomorphicLayoutEffect","window","useDropdownListener","onClick","onClose","onTouchEnd","onTouchStart","shouldCaptureEvents","document","addEventListener","removeEventListener","useDropdownAlignment","anchorElement","contentWidth","direction","shouldUseTopAlignment","translateX","setTranslateX","translateY","setTranslateY","BOTTOM_LEFT","TOP_LEFT","LEFT","includes","difference","clientWidth","useTopAlignment","TOP","TOP_RIGHT","x","y","AVAILABLE_HEIGHT_SPACING","useDropdownPosition","container","contentHeight","shouldShowDropdown","coordinates","setCoordinates","setShouldUseTopAlignment","availableMaxHeight","setAvailableMaxHeight","calculateCoordinates","left","anchorLeft","top","anchorTop","height","anchorHeight","getBoundingClientRect","scrollLeft","scrollTop","hasBottomAlignment","BOTTOM","BOTTOM_RIGHT","spaceToTop","spaceToBottom","nextAvailableMaxHeight","Math","max","round","currentAvailableMaxHeight","abs","handleResize","setTimeout","useDropdown","transform","width"],"sources":["../../../src/hooks/dropdown.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { DropdownCoordinates, DropdownDirection } from '../types/dropdown';\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\ninterface UseDropdownListenerOptions {\n onClick: (event: MouseEvent) => void;\n onClose: () => void;\n onTouchEnd: (event: TouchEvent) => void;\n onTouchStart: (event: TouchEvent) => void;\n shouldCaptureEvents?: boolean;\n}\n\nexport const useDropdownListener = ({\n onClick,\n onClose,\n onTouchEnd,\n onTouchStart,\n shouldCaptureEvents,\n}: UseDropdownListenerOptions) => {\n useEffect(() => {\n document.addEventListener('click', onClick, shouldCaptureEvents);\n document.addEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.addEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.addEventListener('blur', onClose);\n\n return () => {\n document.removeEventListener('click', onClick, shouldCaptureEvents);\n document.removeEventListener('touchend', onTouchEnd, shouldCaptureEvents);\n document.removeEventListener('touchstart', onTouchStart, shouldCaptureEvents);\n\n window.removeEventListener('blur', onClose);\n };\n }, [onClick, onClose, onTouchEnd, onTouchStart]);\n};\n\ninterface UseDropdownAlignmentOptions {\n direction: DropdownDirection;\n shouldUseTopAlignment: boolean;\n contentWidth: number;\n anchorElement: Element;\n}\n\nexport const useDropdownAlignment = ({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n}: UseDropdownAlignmentOptions) => {\n const [translateX, setTranslateX] = useState<string>('0px');\n const [translateY, setTranslateY] = useState<string>('0px');\n\n useEffect(() => {\n if (\n [\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.LEFT,\n ].includes(direction)\n ) {\n const difference = anchorElement.clientWidth - contentWidth;\n\n setTranslateX(`${difference}px`);\n } else {\n setTranslateX('0px');\n }\n }, [anchorElement.clientWidth, contentWidth, direction]);\n\n useEffect(() => {\n const useTopAlignment =\n shouldUseTopAlignment ||\n [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n if (useTopAlignment) {\n setTranslateY('-100%');\n } else {\n setTranslateY('0px');\n }\n }, [direction, shouldUseTopAlignment]);\n\n return useMemo(() => ({ x: translateX, y: translateY }), [translateX, translateY]);\n};\n\ninterface UseDropdownPositionOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\n/**\n * The space (in pixels) that should be kept between the dropdown content and the edge of the\n * container when calculating the available maximum height.\n */\nconst AVAILABLE_HEIGHT_SPACING = 16;\n\nexport const useDropdownPosition = ({\n anchorElement,\n container,\n contentHeight = 0,\n direction,\n shouldShowDropdown,\n}: UseDropdownPositionOptions) => {\n const [coordinates, setCoordinates] = useState<DropdownCoordinates>({ x: 0, y: 0 });\n const [shouldUseTopAlignment, setShouldUseTopAlignment] = useState(false);\n const [availableMaxHeight, setAvailableMaxHeight] = useState<number>(0);\n\n const calculateCoordinates = useCallback(() => {\n if (container) {\n const {\n left: anchorLeft,\n top: anchorTop,\n height: anchorHeight,\n } = anchorElement.getBoundingClientRect();\n\n const { left, top, height } = container.getBoundingClientRect();\n\n const x = anchorLeft - left + container.scrollLeft;\n const y = anchorTop - top + container.scrollTop;\n\n let useTopAlignment = [\n DropdownDirection.TOP,\n DropdownDirection.TOP_LEFT,\n DropdownDirection.TOP_RIGHT,\n ].includes(direction);\n\n const hasBottomAlignment = [\n DropdownDirection.BOTTOM,\n DropdownDirection.BOTTOM_LEFT,\n DropdownDirection.BOTTOM_RIGHT,\n ].includes(direction);\n\n if (!hasBottomAlignment && y + anchorHeight + contentHeight > height) {\n useTopAlignment = true;\n\n setShouldUseTopAlignment(true);\n } else {\n setShouldUseTopAlignment(false);\n }\n\n // Calculate the space that is available for the dropdown content. When the dropdown is\n // opened to the top, the available space reaches from the anchor to the top edge of the\n // container. When it is opened to the bottom, it reaches from the bottom of the anchor\n // to the bottom edge of the container. A small spacing is subtracted so the content does\n // not touch the container edge (e.g. to leave room for shadows).\n const spaceToTop = y;\n const spaceToBottom = height - (y + anchorHeight);\n\n const nextAvailableMaxHeight = Math.max(\n Math.round(\n (useTopAlignment ? spaceToTop : spaceToBottom) - AVAILABLE_HEIGHT_SPACING,\n ),\n 0,\n );\n\n // Only update the available max height when it changes by more than one pixel. This\n // prevents subpixel fluctuations of getBoundingClientRect from repeatedly triggering\n // re-renders of the consumer, which could otherwise cause a layout shift loop.\n setAvailableMaxHeight((currentAvailableMaxHeight) =>\n Math.abs(currentAvailableMaxHeight - nextAvailableMaxHeight) <= 1\n ? currentAvailableMaxHeight\n : nextAvailableMaxHeight,\n );\n\n setCoordinates({ x, y: useTopAlignment ? y : y + anchorHeight });\n }\n }, [anchorElement, container, contentHeight, direction]);\n\n useIsomorphicLayoutEffect(() => {\n const handleResize = () => {\n calculateCoordinates();\n\n setTimeout(calculateCoordinates, 300);\n };\n\n handleResize();\n\n if (shouldShowDropdown) {\n window.addEventListener('resize', handleResize);\n }\n\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n }, [calculateCoordinates, shouldShowDropdown]);\n\n return useMemo(\n () => ({ shouldUseTopAlignment, coordinates, availableMaxHeight }),\n [availableMaxHeight, coordinates, shouldUseTopAlignment],\n );\n};\n\ninterface UseDropdownOptions {\n anchorElement: Element;\n container?: Element;\n contentHeight?: number;\n contentWidth: number;\n direction: DropdownDirection;\n shouldShowDropdown: boolean;\n}\n\nexport const useDropdown = ({\n anchorElement,\n container,\n contentHeight,\n contentWidth,\n direction,\n shouldShowDropdown,\n}: UseDropdownOptions) => {\n const { shouldUseTopAlignment, coordinates, availableMaxHeight } = useDropdownPosition({\n anchorElement,\n container,\n contentHeight,\n direction,\n shouldShowDropdown,\n });\n\n const transform = useDropdownAlignment({\n anchorElement,\n contentWidth,\n direction,\n shouldUseTopAlignment,\n });\n\n const width = anchorElement.clientWidth;\n\n return useMemo(\n () => ({ coordinates, transform, width, availableMaxHeight }),\n [availableMaxHeight, coordinates, transform, width],\n );\n};\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chayns-components/core",
3
- "version": "5.4.5",
3
+ "version": "5.4.6",
4
4
  "description": "A set of beautiful React components for developing your own applications with chayns.",
5
5
  "sideEffects": false,
6
6
  "browserslist": [
@@ -88,5 +88,5 @@
88
88
  "publishConfig": {
89
89
  "access": "public"
90
90
  },
91
- "gitHead": "0d6bc7229b2b0c504583ac371f8997fa216243c3"
91
+ "gitHead": "9c0a91d34988e0176e7fff1de007165f65aba5bc"
92
92
  }