@elliemae/ds-floating-context 3.52.0-rc.8 → 3.52.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.
@@ -34,12 +34,12 @@ __export(DSFloatingContext_exports, {
34
34
  module.exports = __toCommonJS(DSFloatingContext_exports);
35
35
  var React = __toESM(require("react"));
36
36
  var import_react = __toESM(require("react"));
37
- var import_lodash = require("lodash");
38
37
  var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
39
38
  var import_ds_hooks_headless_tooltip = require("@elliemae/ds-hooks-headless-tooltip");
40
39
  var import_ds_system = require("@elliemae/ds-system");
41
- var import_computePosition = require("./utils/computePosition.js");
42
40
  var import_react_desc_prop_types = require("./react-desc-prop-types.js");
41
+ var import_useComputedPositionStyles = require("./useComputedPositionStyles.js");
42
+ var import_positionObserver = require("./utils/positionObserver.js");
43
43
  const useFloatingContext = (props = {}) => {
44
44
  const propsWithDefault = (0, import_ds_props_helpers.useMemoMergePropsWithDefault)(props, import_react_desc_prop_types.defaultProps);
45
45
  (0, import_ds_props_helpers.useValidateTypescriptPropTypes)(propsWithDefault, import_react_desc_prop_types.DSFloatingContextPropTypes, "FloatingContext");
@@ -70,48 +70,51 @@ const useFloatingContext = (props = {}) => {
70
70
  }, [onClose]);
71
71
  const tooltipHelpers = (0, import_ds_hooks_headless_tooltip.useHeadlessTooltip)({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });
72
72
  const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;
73
- const [floatingStyles, setFloatingStyles] = (0, import_react.useState)({
74
- position: "absolute",
75
- zIndex: 3e3,
76
- top: 0,
77
- left: 0,
78
- visibility: "hidden"
79
- });
80
- const [arrowStyles, setArrowStyles] = (0, import_react.useState)({
81
- style: { left: 0 },
82
- placement: "top"
83
- });
84
73
  const [reference, _setReference] = import_react.default.useState(null);
85
74
  const [floating, setFloating] = import_react.default.useState(null);
75
+ const [workaroundToEnsureAPositionWasCalculatedIfOpen, setWorkaroundToEnsureAPositionWasCalculatedIfOpen] = import_react.default.useState(0);
76
+ const { arrowStyles, floatingStyles, mutableUpdateStyles, debouncedUpdateStyles } = (0, import_useComputedPositionStyles.useComputedPositionStyles)({
77
+ reference,
78
+ floating,
79
+ placement,
80
+ placementOrderPreference,
81
+ customOffset,
82
+ withoutPortal
83
+ });
84
+ (0, import_react.useEffect)(() => {
85
+ requestAnimationFrame(() => {
86
+ mutableUpdateStyles?.current();
87
+ });
88
+ }, [reference, mutableUpdateStyles]);
89
+ const updatePosOnIntersection = import_react.default.useCallback(() => {
90
+ if (reference) {
91
+ requestAnimationFrame(() => {
92
+ debouncedUpdateStyles();
93
+ });
94
+ }
95
+ }, [reference, debouncedUpdateStyles]);
96
+ (0, import_positionObserver.usePositionObserver)(reference, updatePosOnIntersection);
97
+ (0, import_react.useEffect)(() => {
98
+ requestAnimationFrame(() => {
99
+ mutableUpdateStyles?.current();
100
+ });
101
+ }, [isOpenSourceOfTruth, mutableUpdateStyles]);
102
+ const { visibility } = floatingStyles;
103
+ const needsToCalculateBecauseStillInvisibleWhenShouldBeOpen = isOpenSourceOfTruth && visibility === "hidden";
86
104
  (0, import_react.useEffect)(() => {
87
- const update = () => {
88
- if (isOpenSourceOfTruth && reference && floating) {
89
- const { coordsStyle, finalPlacement, coordsArrow } = (0, import_computePosition.computePosition)({
90
- reference,
91
- floating,
92
- placement,
93
- placementOrderPreference,
94
- customOffset,
95
- withoutPortal
96
- });
97
- const styles = {
98
- position: "absolute",
99
- zIndex: 3e3,
100
- // top: 0,
101
- // left: 0,
102
- ...coordsStyle
103
- };
104
- setFloatingStyles(styles);
105
- setArrowStyles({ style: coordsArrow, placement: finalPlacement });
106
- }
107
- };
108
- update();
109
- const debouncedCb = (0, import_lodash.debounce)(update, 300);
110
- window.addEventListener("scroll", debouncedCb);
111
- return () => {
112
- window.removeEventListener("scroll", debouncedCb);
113
- };
114
- }, [reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, isOpenSourceOfTruth]);
105
+ if (needsToCalculateBecauseStillInvisibleWhenShouldBeOpen) {
106
+ mutableUpdateStyles?.current();
107
+ requestAnimationFrame(() => {
108
+ setWorkaroundToEnsureAPositionWasCalculatedIfOpen((o) => o + 1);
109
+ });
110
+ }
111
+ }, [
112
+ needsToCalculateBecauseStillInvisibleWhenShouldBeOpen,
113
+ mutableUpdateStyles,
114
+ // this dependency is the point of this useEffect
115
+ // it will keep triggering until the position is calculated if it needs to be calculated
116
+ workaroundToEnsureAPositionWasCalculatedIfOpen
117
+ ]);
115
118
  const setReference = (0, import_ds_system.mergeRefs)(_setReference, setReferenceElement);
116
119
  const refs = import_react.default.useMemo(
117
120
  () => ({
@@ -145,7 +148,8 @@ const useFloatingContext = (props = {}) => {
145
148
  withoutAnimation,
146
149
  portalDOMContainer,
147
150
  animationDuration
148
- }
151
+ },
152
+ mutableUpdateStyles
149
153
  }),
150
154
  [
151
155
  refs,
@@ -158,7 +162,8 @@ const useFloatingContext = (props = {}) => {
158
162
  withoutPortal,
159
163
  withoutAnimation,
160
164
  portalDOMContainer,
161
- animationDuration
165
+ animationDuration,
166
+ mutableUpdateStyles
162
167
  ]
163
168
  );
164
169
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/DSFloatingContext.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable no-nested-ternary */\n/* eslint-disable arrow-body-style */\n/* eslint-disable no-unused-vars */\n/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable @typescript-eslint/no-use-before-define */\nimport React, { useState, useEffect, useMemo } from 'react';\nimport { debounce } from 'lodash';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip } from '@elliemae/ds-hooks-headless-tooltip';\nimport { type CSSProperties } from 'styled-components';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\n\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(props, defaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n onOpen,\n onClose,\n externallyControlledIsOpen,\n } = propsWithDefault;\n\n const [internalIsOpen, setInternalIsOpen] = React.useState<boolean>(false);\n const isOpenSourceOfTruth = useMemo(() => {\n if (externallyControlledIsOpen !== undefined) return externallyControlledIsOpen;\n return internalIsOpen;\n }, [externallyControlledIsOpen, internalIsOpen]);\n\n const overChargedOnOpen = React.useCallback(() => {\n setInternalIsOpen(true);\n onOpen?.();\n }, [onOpen]);\n const overChargedOnClose = React.useCallback(() => {\n setInternalIsOpen(false);\n onClose?.();\n }, [onClose]);\n const tooltipHelpers = useHeadlessTooltip({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });\n\n const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({\n style: { left: 0 },\n placement: 'top',\n });\n\n const [reference, _setReference] = React.useState<Element | null>(null);\n const [floating, setFloating] = React.useState<HTMLElement | null>(null);\n useEffect(() => {\n const update = () => {\n if (isOpenSourceOfTruth && reference && floating) {\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n const styles: CSSProperties = {\n position: 'absolute',\n zIndex: 3000,\n // top: 0,\n // left: 0,\n ...coordsStyle,\n };\n\n setFloatingStyles(styles);\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n }\n };\n\n // initial position calculation\n update();\n\n const debouncedCb = debounce(update, 300);\n\n // auto update position on scrolling\n window.addEventListener('scroll', debouncedCb);\n\n return () => {\n window.removeEventListener('scroll', debouncedCb);\n };\n }, [reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, isOpenSourceOfTruth]);\n\n const setReference = mergeRefs(_setReference, setReferenceElement);\n\n const refs = React.useMemo(\n () => ({\n setReference,\n setFloating,\n floating,\n reference,\n }),\n [setReference, floating, reference],\n );\n\n const handlers = React.useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles,\n handlers,\n isOpen: isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n }),\n [\n refs,\n floatingStyles,\n handlers,\n isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/* eslint-disable max-statements */\nimport React, { useEffect, useMemo } from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip } from '@elliemae/ds-hooks-headless-tooltip';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\nimport { useComputedPositionStyles } from './useComputedPositionStyles.js';\nimport { usePositionObserver } from './utils/positionObserver.js';\n\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(props, defaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n onOpen,\n onClose,\n externallyControlledIsOpen,\n } = propsWithDefault;\n\n const [internalIsOpen, setInternalIsOpen] = React.useState<boolean>(false);\n const isOpenSourceOfTruth = useMemo(() => {\n if (externallyControlledIsOpen !== undefined) return externallyControlledIsOpen;\n return internalIsOpen;\n }, [externallyControlledIsOpen, internalIsOpen]);\n\n const overChargedOnOpen = React.useCallback(() => {\n setInternalIsOpen(true);\n onOpen?.();\n }, [onOpen]);\n const overChargedOnClose = React.useCallback(() => {\n setInternalIsOpen(false);\n onClose?.();\n }, [onClose]);\n const tooltipHelpers = useHeadlessTooltip({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });\n const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const [reference, _setReference] = React.useState<Element | null>(null);\n const [floating, setFloating] = React.useState<HTMLElement | null>(null);\n const [workaroundToEnsureAPositionWasCalculatedIfOpen, setWorkaroundToEnsureAPositionWasCalculatedIfOpen] =\n React.useState<number>(0);\n\n const { arrowStyles, floatingStyles, mutableUpdateStyles, debouncedUpdateStyles } = useComputedPositionStyles({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n // calculate position on mount\n // AND everytime the reference (which is actually immutable because it's stored in a React.useState)\n // changes\n useEffect(() => {\n requestAnimationFrame(() => {\n mutableUpdateStyles?.current();\n });\n // the dependency array is equal to being empty because mutableUpdateStyles is a ref.\n // this is effectively an \"on mount\"\n }, [reference, mutableUpdateStyles]);\n\n // use intersection observer to detect when the position of the reference changes needing to recalculate the position\n const updatePosOnIntersection = React.useCallback(() => {\n if (reference) {\n requestAnimationFrame(() => {\n debouncedUpdateStyles();\n });\n }\n }, [reference, debouncedUpdateStyles]);\n usePositionObserver(reference, updatePosOnIntersection);\n\n // when we detect that the flag about it being open/closed changes\n // we refresh the position of the tooltip calculation\n useEffect(() => {\n requestAnimationFrame(() => {\n mutableUpdateStyles?.current();\n });\n }, [isOpenSourceOfTruth, mutableUpdateStyles]);\n\n // this is a workaround to ensure that the position is calculated at least once when the tooltip is open\n const { visibility } = floatingStyles;\n const needsToCalculateBecauseStillInvisibleWhenShouldBeOpen = isOpenSourceOfTruth && visibility === 'hidden';\n useEffect(() => {\n if (needsToCalculateBecauseStillInvisibleWhenShouldBeOpen) {\n mutableUpdateStyles?.current();\n requestAnimationFrame(() => {\n setWorkaroundToEnsureAPositionWasCalculatedIfOpen((o) => o + 1);\n });\n }\n }, [\n needsToCalculateBecauseStillInvisibleWhenShouldBeOpen,\n mutableUpdateStyles,\n // this dependency is the point of this useEffect\n // it will keep triggering until the position is calculated if it needs to be calculated\n workaroundToEnsureAPositionWasCalculatedIfOpen,\n ]);\n\n const setReference = mergeRefs(_setReference, setReferenceElement);\n const refs = React.useMemo(\n () => ({\n setReference,\n setFloating,\n floating,\n reference,\n }),\n [setReference, floating, reference],\n );\n\n const handlers = React.useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles,\n handlers,\n isOpen: isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n mutableUpdateStyles,\n }),\n [\n refs,\n floatingStyles,\n handlers,\n isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n mutableUpdateStyles,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": "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",
6
6
  "names": ["React"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/FloatingWrapper/react-desc-prop-types.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement>;\n onAnimationStartTriggered?: () => void;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export type ExampleState = '0' | '1';\n}\n\nexport const defaultProps: Partial<DSFloatingWrapperT.DefaultProps> = {\n context: {\n withoutPortal: false,\n animationDuration: 300,\n withoutAnimation: false,\n },\n customOffset: [0, 12],\n};\n\nexport const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps> = {\n ...getPropsPerSlotPropTypes(DSFloatingWrapperName, DSFloatingWrapperSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n children: PropTypes.node.description('Content of the floating wrapper').isRequired,\n innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).description('Ref for the floating wrapper')\n .isRequired,\n isOpen: PropTypes.bool.description('Whether the floating wrapper is open').isRequired,\n floatingStyles: PropTypes.object.description('Style for the floating wrapper').isRequired,\n context: PropTypes.shape({\n portalDOMContainer: PropTypes.instanceOf(HTMLElement)\n .description('The DOM element where the tooltip will be rendered.')\n .defaultValue('the first \"main\" landmark available in the document or the body if no \"main\" is found'),\n withoutPortal: PropTypes.bool.description('Whether to render the floating wrapper without a portal'),\n animationDuration: PropTypes.number.description('Duration of the animation'),\n withoutAnimation: PropTypes.bool.description('Whether to render the floating wrapper without animation'),\n }).description('Context for the floating wrapper'),\n onAnimationStartTriggered: PropTypes.func.description(\n 'Callback invoked when the component trigger the animation start. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n onAnimationEnd: PropTypes.func.description(\n 'Callback when the animation ends. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n customOffset: PropTypes.arrayOf(PropTypes.number).description('Custom offset for the floating wrapper'),\n};\n\nexport const DSFloatingWrapperPropTypesSchema =\n DSFloatingWrapperPropTypes as unknown as ValidationMap<DSFloatingWrapperT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAKO;AAEP,uBAA8D;AAiDvD,MAAM,eAAyD;AAAA,EACpE,SAAS;AAAA,IACP,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AAAA,EACA,cAAc,CAAC,GAAG,EAAE;AACtB;AAEO,MAAM,6BAAkF;AAAA,EAC7F,OAAG,kDAAyB,wCAAuB,uCAAsB;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,UAAU,kCAAU,KAAK,YAAY,iCAAiC,EAAE;AAAA,EACxE,UAAU,kCAAU,UAAU,CAAC,kCAAU,QAAQ,kCAAU,IAAI,CAAC,EAAE,YAAY,8BAA8B,EACzG;AAAA,EACH,QAAQ,kCAAU,KAAK,YAAY,sCAAsC,EAAE;AAAA,EAC3E,gBAAgB,kCAAU,OAAO,YAAY,gCAAgC,EAAE;AAAA,EAC/E,SAAS,kCAAU,MAAM;AAAA,IACvB,oBAAoB,kCAAU,WAAW,WAAW,EACjD,YAAY,qDAAqD,EACjE,aAAa,uFAAuF;AAAA,IACvG,eAAe,kCAAU,KAAK,YAAY,yDAAyD;AAAA,IACnG,mBAAmB,kCAAU,OAAO,YAAY,2BAA2B;AAAA,IAC3E,kBAAkB,kCAAU,KAAK,YAAY,0DAA0D;AAAA,EACzG,CAAC,EAAE,YAAY,kCAAkC;AAAA,EACjD,2BAA2B,kCAAU,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EACA,gBAAgB,kCAAU,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,cAAc,kCAAU,QAAQ,kCAAU,MAAM,EAAE,YAAY,wCAAwC;AACxG;AAEO,MAAM,mCACX;",
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement>;\n onAnimationStartTriggered?: () => void;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n}\n\nexport const defaultProps: Partial<DSFloatingWrapperT.DefaultProps> = {\n context: {\n withoutPortal: false,\n animationDuration: 300,\n withoutAnimation: false,\n },\n customOffset: [0, 12],\n};\n\nexport const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps> = {\n ...getPropsPerSlotPropTypes(DSFloatingWrapperName, DSFloatingWrapperSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n children: PropTypes.node.description('Content of the floating wrapper').isRequired,\n innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).description('Ref for the floating wrapper')\n .isRequired,\n isOpen: PropTypes.bool.description('Whether the floating wrapper is open').isRequired,\n floatingStyles: PropTypes.object.description('Style for the floating wrapper').isRequired,\n context: PropTypes.shape({\n portalDOMContainer: PropTypes.instanceOf(HTMLElement)\n .description('The DOM element where the tooltip will be rendered.')\n .defaultValue('the first \"main\" landmark available in the document or the body if no \"main\" is found'),\n withoutPortal: PropTypes.bool.description('Whether to render the floating wrapper without a portal'),\n animationDuration: PropTypes.number.description('Duration of the animation'),\n withoutAnimation: PropTypes.bool.description('Whether to render the floating wrapper without animation'),\n }).description('Context for the floating wrapper'),\n onAnimationStartTriggered: PropTypes.func.description(\n 'Callback invoked when the component trigger the animation start. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n onAnimationEnd: PropTypes.func.description(\n 'Callback when the animation ends. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n customOffset: PropTypes.arrayOf(PropTypes.number).description('Custom offset for the floating wrapper'),\n};\n\nexport const DSFloatingWrapperPropTypesSchema =\n DSFloatingWrapperPropTypes as unknown as ValidationMap<DSFloatingWrapperT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAKO;AAEP,uBAA8D;AA+CvD,MAAM,eAAyD;AAAA,EACpE,SAAS;AAAA,IACP,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AAAA,EACA,cAAc,CAAC,GAAG,EAAE;AACtB;AAEO,MAAM,6BAAkF;AAAA,EAC7F,OAAG,kDAAyB,wCAAuB,uCAAsB;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,UAAU,kCAAU,KAAK,YAAY,iCAAiC,EAAE;AAAA,EACxE,UAAU,kCAAU,UAAU,CAAC,kCAAU,QAAQ,kCAAU,IAAI,CAAC,EAAE,YAAY,8BAA8B,EACzG;AAAA,EACH,QAAQ,kCAAU,KAAK,YAAY,sCAAsC,EAAE;AAAA,EAC3E,gBAAgB,kCAAU,OAAO,YAAY,gCAAgC,EAAE;AAAA,EAC/E,SAAS,kCAAU,MAAM;AAAA,IACvB,oBAAoB,kCAAU,WAAW,WAAW,EACjD,YAAY,qDAAqD,EACjE,aAAa,uFAAuF;AAAA,IACvG,eAAe,kCAAU,KAAK,YAAY,yDAAyD;AAAA,IACnG,mBAAmB,kCAAU,OAAO,YAAY,2BAA2B;AAAA,IAC3E,kBAAkB,kCAAU,KAAK,YAAY,0DAA0D;AAAA,EACzG,CAAC,EAAE,YAAY,kCAAkC;AAAA,EACjD,2BAA2B,kCAAU,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EACA,gBAAgB,kCAAU,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,cAAc,kCAAU,QAAQ,kCAAU,MAAM,EAAE,YAAY,wCAAwC;AACxG;AAEO,MAAM,mCACX;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var useComputedPositionStyles_exports = {};
30
+ __export(useComputedPositionStyles_exports, {
31
+ useComputedPositionStyles: () => useComputedPositionStyles
32
+ });
33
+ module.exports = __toCommonJS(useComputedPositionStyles_exports);
34
+ var React = __toESM(require("react"));
35
+ var import_react = __toESM(require("react"));
36
+ var import_lodash_es = require("lodash-es");
37
+ var import_computePosition = require("./utils/computePosition.js");
38
+ const useComputedPositionStyles = (config) => {
39
+ const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, preventComputing } = config;
40
+ const [arrowStyles, setArrowStyles] = (0, import_react.useState)({
41
+ style: { left: 0 },
42
+ placement: "top"
43
+ });
44
+ const [floatingStyles, setFloatingStyles] = (0, import_react.useState)({
45
+ position: "absolute",
46
+ zIndex: 3e3,
47
+ top: 0,
48
+ left: 0,
49
+ visibility: "hidden"
50
+ });
51
+ const canComputePosition = reference !== null && floating !== null;
52
+ const canAndShouldComputePosition = canComputePosition && preventComputing !== true;
53
+ const updateStyles = import_react.default.useCallback(() => {
54
+ if (canAndShouldComputePosition) {
55
+ const { coordsStyle, finalPlacement, coordsArrow } = (0, import_computePosition.computePosition)({
56
+ reference,
57
+ floating,
58
+ placement,
59
+ placementOrderPreference,
60
+ customOffset,
61
+ withoutPortal
62
+ });
63
+ setFloatingStyles({
64
+ position: "absolute",
65
+ zIndex: 3e3,
66
+ ...coordsStyle
67
+ });
68
+ setArrowStyles({ style: coordsArrow, placement: finalPlacement });
69
+ }
70
+ }, [
71
+ canAndShouldComputePosition,
72
+ reference,
73
+ floating,
74
+ placement,
75
+ placementOrderPreference,
76
+ customOffset,
77
+ withoutPortal
78
+ ]);
79
+ const mutableUpdateStyles = import_react.default.useRef(updateStyles);
80
+ mutableUpdateStyles.current = updateStyles;
81
+ const debouncedUpdateStyles = import_react.default.useMemo(() => (0, import_lodash_es.debounce)(() => mutableUpdateStyles.current(), 100), []);
82
+ const resetStyles = import_react.default.useCallback(() => {
83
+ setFloatingStyles({
84
+ position: "absolute",
85
+ zIndex: 3e3,
86
+ top: 0,
87
+ left: 0,
88
+ visibility: "hidden"
89
+ });
90
+ setArrowStyles({ style: { left: 0 }, placement: "top" });
91
+ }, []);
92
+ return import_react.default.useMemo(
93
+ () => ({ arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, mutableUpdateStyles, resetStyles }),
94
+ [arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, resetStyles]
95
+ );
96
+ };
97
+ //# sourceMappingURL=useComputedPositionStyles.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/useComputedPositionStyles.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["import React, { useState } from 'react';\nimport { debounce } from 'lodash-es';\nimport { type CSSProperties } from 'styled-components';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\n\ntype UseComputedPositionStylesT = {\n preventComputing?: boolean;\n reference: Element | null;\n floating: HTMLElement | null;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n};\n/**\n * this custom hook has a single purpose, to compute the position of the floating element relative to the reference element\n *\n * we ideally don't want to calculate positions if the open flag is false as the styles should not be visible so not relevant.\n * @param {UseComputedPositionStylesT} config - The configuration object.\n * @param {Boolean} config.preventComputing - If true, the position will not be computed, usually used when the open flag is false.\n * @param {Element} config.reference - The reference element as a DOM element.\n * @param {HTMLElement} config.floating - The floating element as a DOM element (required to calculate the best fitting position).\n * @param {DSHookFloatingContextT.PopperPlacementsT} config.placement - The placement of the floating element relative to the reference element to be applied if possible.\n * @param {DSHookFloatingContextT.PopperPlacementsT[]} config.placementOrderPreference - The order of preference for the placement of the floating element relative to the reference element, the first one that fits will be used.\n * @param {[number, number]} config.customOffset - The offset of the floating element relative to the reference element if any is desired.\n * @param {Boolean} config.withoutPortal - If true, the floating element will be positioned relative to the reference element, otherwise it will be positioned relative to the viewport.\n *\n * @returns results\n * @returns results.arrowStyles - the styles to be applied to the arrow element if any is desired\n * @returns results.floatingStyles - the styles to be applied to the floating element\n * @returns results.updateStyles - a function to be called to update the styles of the floating element on demand if needed\n * @returns results.debouncedUpdateStyles - a debounced version of the updateStyles function to be used when lot of invocations are expected (e.g. on scroll)\n * @returns results.mutableUpdateStyles - a ref to the updateStyles function to be used when the function needs to be called in a useEffect or similar\n */\nexport const useComputedPositionStyles = (config: UseComputedPositionStylesT) => {\n const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, preventComputing } =\n config;\n\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({\n style: { left: 0 },\n placement: 'top',\n });\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n const canComputePosition = reference !== null && floating !== null;\n const canAndShouldComputePosition = canComputePosition && preventComputing !== true;\n\n const updateStyles = React.useCallback(() => {\n if (canAndShouldComputePosition) {\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n setFloatingStyles({\n position: 'absolute',\n zIndex: 3000,\n ...coordsStyle,\n });\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n }\n }, [\n canAndShouldComputePosition,\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n ]);\n\n // when deboucing we only care to invoke the most updated version of the function\n // continuously redefining the debouncedUpdateStyles function is a waste of resources\n // so we use a ref to store the latest version of the function\n const mutableUpdateStyles = React.useRef(updateStyles);\n mutableUpdateStyles.current = updateStyles;\n // and we only define the debounced version once, using the ref to always have the latest version of the function.\n // notice the ()=> mutableUpdateStyles.current() syntax\n // we create a new closure (the anonymous function) that is referientially stable\n // and we call the mutableUpdateStyles.current function inside it (which is NOT referentially stable)\n const debouncedUpdateStyles = React.useMemo(() => debounce(() => mutableUpdateStyles.current(), 100), []);\n\n const resetStyles = React.useCallback(() => {\n setFloatingStyles({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n setArrowStyles({ style: { left: 0 }, placement: 'top' });\n }, []);\n\n return React.useMemo(\n () => ({ arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, mutableUpdateStyles, resetStyles }),\n [arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, resetStyles],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAgC;AAChC,uBAAyB;AAEzB,6BAAgC;AAiCzB,MAAM,4BAA4B,CAAC,WAAuC;AAC/E,QAAM,EAAE,WAAW,UAAU,WAAW,0BAA0B,cAAc,eAAe,iBAAiB,IAC9G;AAEF,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAwB;AAAA,IAC5D,OAAO,EAAE,MAAM,EAAE;AAAA,IACjB,WAAW;AAAA,EACb,CAAC;AACD,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,uBAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd,CAAC;AACD,QAAM,qBAAqB,cAAc,QAAQ,aAAa;AAC9D,QAAM,8BAA8B,sBAAsB,qBAAqB;AAE/E,QAAM,eAAe,aAAAA,QAAM,YAAY,MAAM;AAC3C,QAAI,6BAA6B;AAC/B,YAAM,EAAE,aAAa,gBAAgB,YAAY,QAAI,wCAAgB;AAAA,QACnE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,wBAAkB;AAAA,QAChB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,GAAG;AAAA,MACL,CAAC;AACD,qBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAAA,IAClE;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,sBAAsB,aAAAA,QAAM,OAAO,YAAY;AACrD,sBAAoB,UAAU;AAK9B,QAAM,wBAAwB,aAAAA,QAAM,QAAQ,UAAM,2BAAS,MAAM,oBAAoB,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC;AAExG,QAAM,cAAc,aAAAA,QAAM,YAAY,MAAM;AAC1C,sBAAkB;AAAA,MAChB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,IACd,CAAC;AACD,mBAAe,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO,EAAE,aAAa,gBAAgB,cAAc,uBAAuB,qBAAqB,YAAY;AAAA,IAC5G,CAAC,aAAa,gBAAgB,cAAc,uBAAuB,WAAW;AAAA,EAChF;AACF;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var positionObserver_exports = {};
30
+ __export(positionObserver_exports, {
31
+ PositionObserver: () => PositionObserver,
32
+ usePositionObserver: () => usePositionObserver
33
+ });
34
+ module.exports = __toCommonJS(positionObserver_exports);
35
+ var React = __toESM(require("react"));
36
+ var import_react = __toESM(require("react"));
37
+ class PositionObserver {
38
+ intersectionObserver;
39
+ positionObserverCallback;
40
+ thresholdList;
41
+ constructor(positionObserverCallback, thresholdFraction = 1e3) {
42
+ this.positionObserverCallback = positionObserverCallback;
43
+ this.thresholdList = new Array(thresholdFraction + 1).fill(0).map((_, ind) => ind / thresholdFraction);
44
+ }
45
+ observe(targetElement) {
46
+ this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {
47
+ threshold: this.thresholdList,
48
+ rootMargin: "0px 0px 0px 0px",
49
+ root: document
50
+ });
51
+ this.intersectionObserver.observe(targetElement);
52
+ }
53
+ viewportCallback(e) {
54
+ const entry = e[0];
55
+ const { target } = entry;
56
+ const targetBounds = entry.boundingClientRect;
57
+ if (this.positionObserverCallback) {
58
+ this.positionObserverCallback({
59
+ x: targetBounds.left,
60
+ y: targetBounds.top,
61
+ target,
62
+ outOfViewport: !entry.isIntersecting,
63
+ rootBounds: entry.rootBounds
64
+ });
65
+ }
66
+ if (entry.intersectionRatio > 0) {
67
+ this.intersectionObserver?.unobserve(target);
68
+ this.intersectionObserver?.disconnect();
69
+ const options = {
70
+ threshold: this.thresholdList,
71
+ rootMargin: this.getMargins(
72
+ this.constructBoxWindow(targetBounds, entry.rootBounds),
73
+ entry.rootBounds
74
+ ),
75
+ root: document
76
+ };
77
+ this.intersectionObserver = new IntersectionObserver(this.intersectionObsCallback.bind(this), options);
78
+ this.intersectionObserver?.observe(target);
79
+ }
80
+ }
81
+ intersectionObsCallback(e) {
82
+ const entry = e[0];
83
+ const { target } = entry;
84
+ const targetBounds = entry.boundingClientRect;
85
+ if (this.positionObserverCallback) {
86
+ this.positionObserverCallback({
87
+ x: targetBounds.left,
88
+ y: targetBounds.top,
89
+ target,
90
+ outOfViewport: false,
91
+ rootBounds: entry.rootBounds
92
+ });
93
+ }
94
+ if (entry.intersectionRatio === 0) {
95
+ this.intersectionObserver?.unobserve(target);
96
+ this.intersectionObserver?.disconnect();
97
+ this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {
98
+ threshold: this.thresholdList,
99
+ rootMargin: "0px 0px 0px 0px",
100
+ root: document
101
+ });
102
+ this.intersectionObserver?.observe(target);
103
+ }
104
+ }
105
+ disconnect() {
106
+ this.intersectionObserver?.disconnect();
107
+ }
108
+ constructBoxWindow(targetBounds, rootBounds) {
109
+ const constrainedLeft = Math.min(
110
+ Math.max(rootBounds.left, targetBounds.left),
111
+ rootBounds.right - targetBounds.width
112
+ );
113
+ const constrainedTop = Math.min(
114
+ Math.max(rootBounds.top, targetBounds.top),
115
+ rootBounds.bottom - targetBounds.height
116
+ );
117
+ const constrainedRight = constrainedLeft + targetBounds.width;
118
+ const constrainedBottom = constrainedTop + targetBounds.height;
119
+ return {
120
+ left: constrainedLeft,
121
+ top: constrainedTop,
122
+ right: constrainedRight,
123
+ bottom: constrainedBottom
124
+ };
125
+ }
126
+ getMargins(windowDimensions, rootBounds) {
127
+ let viewportBounds;
128
+ if (!rootBounds) {
129
+ viewportBounds = {
130
+ top: visualViewport.offsetTop,
131
+ left: visualViewport.offsetLeft,
132
+ right: visualViewport.width + visualViewport.offsetLeft,
133
+ bottom: visualViewport.height + visualViewport.offsetTop
134
+ };
135
+ } else {
136
+ viewportBounds = rootBounds;
137
+ }
138
+ const constrainedTopMarginOfWindow = Math.min(-(windowDimensions.top - 1 - viewportBounds.top), 0);
139
+ const constrainedRightMarginOfWindow = Math.min(-(viewportBounds.right - (windowDimensions.right + 1)), 0);
140
+ const constrainedBottomMarginOfWindow = Math.min(-(viewportBounds.bottom - (windowDimensions.bottom + 1)), 0);
141
+ const constrainedLeftMarginOfWindow = Math.min(-(windowDimensions.left - 1 - viewportBounds.left), 0);
142
+ return `${constrainedTopMarginOfWindow}px ${constrainedRightMarginOfWindow}px ${constrainedBottomMarginOfWindow}px ${constrainedLeftMarginOfWindow}px`;
143
+ }
144
+ }
145
+ const usePositionObserver = (elementNode, onPositionChange = () => {
146
+ }) => {
147
+ import_react.default.useEffect(() => {
148
+ const hasIOSupport = !!window.IntersectionObserver;
149
+ if (!hasIOSupport || !elementNode) return () => {
150
+ };
151
+ const positionObs = new PositionObserver(onPositionChange);
152
+ positionObs.observe(elementNode);
153
+ return () => {
154
+ positionObs.disconnect();
155
+ };
156
+ }, [elementNode, onPositionChange]);
157
+ };
158
+ //# sourceMappingURL=positionObserver.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/positionObserver.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["import React from 'react';\n\n/**\n * Copyright (c) 2025 AJK-Essential\n * This file is licensed under the MIT License.\n * See the LICENSE file in the project root for license information.\n */\n\nexport type PositionData = {\n x: number;\n y: number;\n target: HTMLElement | Element;\n outOfViewport: boolean;\n rootBounds: DOMRect | null;\n};\nexport type PositionObserverCallback = (data: PositionData) => void;\n\nexport class PositionObserver {\n private intersectionObserver!: IntersectionObserver;\n\n private positionObserverCallback;\n\n private thresholdList;\n\n constructor(positionObserverCallback: PositionObserverCallback, thresholdFraction = 1000) {\n this.positionObserverCallback = positionObserverCallback;\n this.thresholdList = new Array(thresholdFraction + 1).fill(0).map((_, ind) => ind / thresholdFraction);\n }\n\n public observe(targetElement: HTMLElement | Element) {\n this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {\n threshold: this.thresholdList,\n rootMargin: '0px 0px 0px 0px',\n root: document,\n });\n this.intersectionObserver.observe(targetElement);\n }\n\n private viewportCallback(e: IntersectionObserverEntry[]) {\n const entry = e[0];\n const { target } = entry;\n const targetBounds = entry.boundingClientRect;\n if (this.positionObserverCallback) {\n this.positionObserverCallback({\n x: targetBounds.left,\n y: targetBounds.top,\n target,\n outOfViewport: !entry.isIntersecting,\n rootBounds: entry.rootBounds,\n });\n }\n // If ever there is an intersection in this callback which observes\n // viewport hits, that means, the target is peaking itself inside\n // the viewport (Some part of the target is visible in the viewport).\n // We therefore immediately pass it to the other callback with a finer\n // window to capture changes.\n\n // The finer window is constructed such that it is limited within the\n // viewport boundaries and it has same size as that of target so that\n // if the target enters or exits further, it will eventually increase\n // or decrease the area of intersection (the common area between the\n // target and the finer window) within the window, thus signalling\n // the movement.\n if (entry.intersectionRatio > 0) {\n this.intersectionObserver?.unobserve(target);\n this.intersectionObserver?.disconnect();\n const options: IntersectionObserverInit = {\n threshold: this.thresholdList,\n rootMargin: this.getMargins(\n this.constructBoxWindow(targetBounds, entry.rootBounds as DOMRect),\n entry.rootBounds,\n ),\n root: document,\n };\n this.intersectionObserver = new IntersectionObserver(this.intersectionObsCallback.bind(this), options);\n this.intersectionObserver?.observe(target);\n }\n }\n\n private intersectionObsCallback(e: IntersectionObserverEntry[]) {\n const entry = e[0];\n const { target } = entry;\n const targetBounds = entry.boundingClientRect;\n if (this.positionObserverCallback) {\n this.positionObserverCallback({\n x: targetBounds.left,\n y: targetBounds.top,\n target,\n outOfViewport: false,\n rootBounds: entry.rootBounds,\n });\n }\n // if intersectionRatio is 0, then it means\n // the target is fully out of the finer window.\n // In that case, we pass this to the viewport\n // detector callback (whether it is inside the\n // viewport or not).\n // And it stays there in that callback until\n // the viewport detector callback says, yah, we found it..\n // when it comes back to this callback with an updated finer window\n if (entry.intersectionRatio === 0) {\n this.intersectionObserver?.unobserve(target);\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {\n threshold: this.thresholdList,\n rootMargin: '0px 0px 0px 0px',\n root: document,\n });\n this.intersectionObserver?.observe(target);\n }\n }\n\n public disconnect() {\n this.intersectionObserver?.disconnect();\n }\n\n private constructBoxWindow(targetBounds: DOMRect, rootBounds: DOMRect) {\n const constrainedLeft = Math.min(\n Math.max(rootBounds.left, targetBounds.left),\n rootBounds.right - targetBounds.width,\n );\n const constrainedTop = Math.min(\n Math.max(rootBounds.top, targetBounds.top),\n rootBounds.bottom - targetBounds.height,\n );\n const constrainedRight = constrainedLeft + targetBounds.width;\n const constrainedBottom = constrainedTop + targetBounds.height;\n return {\n left: constrainedLeft,\n top: constrainedTop,\n right: constrainedRight,\n bottom: constrainedBottom,\n };\n }\n\n private getMargins(\n windowDimensions: {\n left: number;\n top: number;\n right: number;\n bottom: number;\n },\n rootBounds: DOMRect | null,\n ) {\n let viewportBounds;\n if (!rootBounds) {\n viewportBounds = {\n top: visualViewport!.offsetTop,\n left: visualViewport!.offsetLeft,\n right: visualViewport!.width + visualViewport!.offsetLeft,\n bottom: visualViewport!.height + visualViewport!.offsetTop,\n };\n } else {\n viewportBounds = rootBounds;\n }\n const constrainedTopMarginOfWindow = Math.min(-(windowDimensions.top - 1 - viewportBounds.top), 0);\n const constrainedRightMarginOfWindow = Math.min(-(viewportBounds.right - (windowDimensions.right + 1)), 0);\n const constrainedBottomMarginOfWindow = Math.min(-(viewportBounds.bottom - (windowDimensions.bottom + 1)), 0);\n const constrainedLeftMarginOfWindow = Math.min(-(windowDimensions.left - 1 - viewportBounds.left), 0);\n return `${constrainedTopMarginOfWindow}px ${constrainedRightMarginOfWindow}px ${constrainedBottomMarginOfWindow}px ${constrainedLeftMarginOfWindow}px`;\n }\n}\n\nexport const usePositionObserver = (\n elementNode: Element | null,\n onPositionChange: PositionObserverCallback = () => {},\n) => {\n React.useEffect(() => {\n const hasIOSupport = !!window.IntersectionObserver;\n if (!hasIOSupport || !elementNode) return () => {};\n const positionObs = new PositionObserver(onPositionChange);\n positionObs.observe(elementNode);\n\n return () => {\n positionObs.disconnect();\n };\n }, [elementNode, onPositionChange]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": "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",
6
+ "names": ["React"]
7
+ }
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import React2, { useState, useEffect, useMemo } from "react";
3
- import { debounce } from "lodash";
2
+ import React2, { useEffect, useMemo } from "react";
4
3
  import {
5
4
  useMemoMergePropsWithDefault,
6
5
  useValidateTypescriptPropTypes,
@@ -8,8 +7,9 @@ import {
8
7
  } from "@elliemae/ds-props-helpers";
9
8
  import { useHeadlessTooltip } from "@elliemae/ds-hooks-headless-tooltip";
10
9
  import { mergeRefs } from "@elliemae/ds-system";
11
- import { computePosition } from "./utils/computePosition.js";
12
10
  import { defaultProps, DSFloatingContextPropTypes } from "./react-desc-prop-types.js";
11
+ import { useComputedPositionStyles } from "./useComputedPositionStyles.js";
12
+ import { usePositionObserver } from "./utils/positionObserver.js";
13
13
  const useFloatingContext = (props = {}) => {
14
14
  const propsWithDefault = useMemoMergePropsWithDefault(props, defaultProps);
15
15
  useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, "FloatingContext");
@@ -40,48 +40,51 @@ const useFloatingContext = (props = {}) => {
40
40
  }, [onClose]);
41
41
  const tooltipHelpers = useHeadlessTooltip({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });
42
42
  const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;
43
- const [floatingStyles, setFloatingStyles] = useState({
44
- position: "absolute",
45
- zIndex: 3e3,
46
- top: 0,
47
- left: 0,
48
- visibility: "hidden"
49
- });
50
- const [arrowStyles, setArrowStyles] = useState({
51
- style: { left: 0 },
52
- placement: "top"
53
- });
54
43
  const [reference, _setReference] = React2.useState(null);
55
44
  const [floating, setFloating] = React2.useState(null);
45
+ const [workaroundToEnsureAPositionWasCalculatedIfOpen, setWorkaroundToEnsureAPositionWasCalculatedIfOpen] = React2.useState(0);
46
+ const { arrowStyles, floatingStyles, mutableUpdateStyles, debouncedUpdateStyles } = useComputedPositionStyles({
47
+ reference,
48
+ floating,
49
+ placement,
50
+ placementOrderPreference,
51
+ customOffset,
52
+ withoutPortal
53
+ });
54
+ useEffect(() => {
55
+ requestAnimationFrame(() => {
56
+ mutableUpdateStyles?.current();
57
+ });
58
+ }, [reference, mutableUpdateStyles]);
59
+ const updatePosOnIntersection = React2.useCallback(() => {
60
+ if (reference) {
61
+ requestAnimationFrame(() => {
62
+ debouncedUpdateStyles();
63
+ });
64
+ }
65
+ }, [reference, debouncedUpdateStyles]);
66
+ usePositionObserver(reference, updatePosOnIntersection);
67
+ useEffect(() => {
68
+ requestAnimationFrame(() => {
69
+ mutableUpdateStyles?.current();
70
+ });
71
+ }, [isOpenSourceOfTruth, mutableUpdateStyles]);
72
+ const { visibility } = floatingStyles;
73
+ const needsToCalculateBecauseStillInvisibleWhenShouldBeOpen = isOpenSourceOfTruth && visibility === "hidden";
56
74
  useEffect(() => {
57
- const update = () => {
58
- if (isOpenSourceOfTruth && reference && floating) {
59
- const { coordsStyle, finalPlacement, coordsArrow } = computePosition({
60
- reference,
61
- floating,
62
- placement,
63
- placementOrderPreference,
64
- customOffset,
65
- withoutPortal
66
- });
67
- const styles = {
68
- position: "absolute",
69
- zIndex: 3e3,
70
- // top: 0,
71
- // left: 0,
72
- ...coordsStyle
73
- };
74
- setFloatingStyles(styles);
75
- setArrowStyles({ style: coordsArrow, placement: finalPlacement });
76
- }
77
- };
78
- update();
79
- const debouncedCb = debounce(update, 300);
80
- window.addEventListener("scroll", debouncedCb);
81
- return () => {
82
- window.removeEventListener("scroll", debouncedCb);
83
- };
84
- }, [reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, isOpenSourceOfTruth]);
75
+ if (needsToCalculateBecauseStillInvisibleWhenShouldBeOpen) {
76
+ mutableUpdateStyles?.current();
77
+ requestAnimationFrame(() => {
78
+ setWorkaroundToEnsureAPositionWasCalculatedIfOpen((o) => o + 1);
79
+ });
80
+ }
81
+ }, [
82
+ needsToCalculateBecauseStillInvisibleWhenShouldBeOpen,
83
+ mutableUpdateStyles,
84
+ // this dependency is the point of this useEffect
85
+ // it will keep triggering until the position is calculated if it needs to be calculated
86
+ workaroundToEnsureAPositionWasCalculatedIfOpen
87
+ ]);
85
88
  const setReference = mergeRefs(_setReference, setReferenceElement);
86
89
  const refs = React2.useMemo(
87
90
  () => ({
@@ -115,7 +118,8 @@ const useFloatingContext = (props = {}) => {
115
118
  withoutAnimation,
116
119
  portalDOMContainer,
117
120
  animationDuration
118
- }
121
+ },
122
+ mutableUpdateStyles
119
123
  }),
120
124
  [
121
125
  refs,
@@ -128,7 +132,8 @@ const useFloatingContext = (props = {}) => {
128
132
  withoutPortal,
129
133
  withoutAnimation,
130
134
  portalDOMContainer,
131
- animationDuration
135
+ animationDuration,
136
+ mutableUpdateStyles
132
137
  ]
133
138
  );
134
139
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSFloatingContext.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-nested-ternary */\n/* eslint-disable arrow-body-style */\n/* eslint-disable no-unused-vars */\n/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable @typescript-eslint/no-use-before-define */\nimport React, { useState, useEffect, useMemo } from 'react';\nimport { debounce } from 'lodash';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip } from '@elliemae/ds-hooks-headless-tooltip';\nimport { type CSSProperties } from 'styled-components';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\n\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(props, defaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n onOpen,\n onClose,\n externallyControlledIsOpen,\n } = propsWithDefault;\n\n const [internalIsOpen, setInternalIsOpen] = React.useState<boolean>(false);\n const isOpenSourceOfTruth = useMemo(() => {\n if (externallyControlledIsOpen !== undefined) return externallyControlledIsOpen;\n return internalIsOpen;\n }, [externallyControlledIsOpen, internalIsOpen]);\n\n const overChargedOnOpen = React.useCallback(() => {\n setInternalIsOpen(true);\n onOpen?.();\n }, [onOpen]);\n const overChargedOnClose = React.useCallback(() => {\n setInternalIsOpen(false);\n onClose?.();\n }, [onClose]);\n const tooltipHelpers = useHeadlessTooltip({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });\n\n const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({\n style: { left: 0 },\n placement: 'top',\n });\n\n const [reference, _setReference] = React.useState<Element | null>(null);\n const [floating, setFloating] = React.useState<HTMLElement | null>(null);\n useEffect(() => {\n const update = () => {\n if (isOpenSourceOfTruth && reference && floating) {\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n const styles: CSSProperties = {\n position: 'absolute',\n zIndex: 3000,\n // top: 0,\n // left: 0,\n ...coordsStyle,\n };\n\n setFloatingStyles(styles);\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n }\n };\n\n // initial position calculation\n update();\n\n const debouncedCb = debounce(update, 300);\n\n // auto update position on scrolling\n window.addEventListener('scroll', debouncedCb);\n\n return () => {\n window.removeEventListener('scroll', debouncedCb);\n };\n }, [reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, isOpenSourceOfTruth]);\n\n const setReference = mergeRefs(_setReference, setReferenceElement);\n\n const refs = React.useMemo(\n () => ({\n setReference,\n setFloating,\n floating,\n reference,\n }),\n [setReference, floating, reference],\n );\n\n const handlers = React.useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles,\n handlers,\n isOpen: isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n }),\n [\n refs,\n floatingStyles,\n handlers,\n isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACMvB,OAAOA,UAAS,UAAU,WAAW,eAAe;AACpD,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,0BAA0B;AAEnC,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAGhC,SAAS,cAAc,kCAAkC;AAEzD,MAAM,qBAAqB,CAAC,QAAsC,CAAC,MAAM;AACvE,QAAM,mBAAmB,6BAAmE,OAAO,YAAY;AAC/G,iCAA+B,kBAAkB,4BAA4B,iBAAiB;AAE9F,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,OAAM,SAAkB,KAAK;AACzE,QAAM,sBAAsB,QAAQ,MAAM;AACxC,QAAI,+BAA+B,OAAW,QAAO;AACrD,WAAO;AAAA,EACT,GAAG,CAAC,4BAA4B,cAAc,CAAC;AAE/C,QAAM,oBAAoBA,OAAM,YAAY,MAAM;AAChD,sBAAkB,IAAI;AACtB,aAAS;AAAA,EACX,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,qBAAqBA,OAAM,YAAY,MAAM;AACjD,sBAAkB,KAAK;AACvB,cAAU;AAAA,EACZ,GAAG,CAAC,OAAO,CAAC;AACZ,QAAM,iBAAiB,mBAAmB,EAAE,QAAQ,mBAAmB,SAAS,mBAAmB,CAAC;AAEpG,QAAM,EAAE,qBAAqB,aAAa,YAAY,IAAI;AAC1D,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd,CAAC;AACD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB;AAAA,IAC5D,OAAO,EAAE,MAAM,EAAE;AAAA,IACjB,WAAW;AAAA,EACb,CAAC;AAED,QAAM,CAAC,WAAW,aAAa,IAAIA,OAAM,SAAyB,IAAI;AACtE,QAAM,CAAC,UAAU,WAAW,IAAIA,OAAM,SAA6B,IAAI;AACvE,YAAU,MAAM;AACd,UAAM,SAAS,MAAM;AACnB,UAAI,uBAAuB,aAAa,UAAU;AAChD,cAAM,EAAE,aAAa,gBAAgB,YAAY,IAAI,gBAAgB;AAAA,UACnE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAED,cAAM,SAAwB;AAAA,UAC5B,UAAU;AAAA,UACV,QAAQ;AAAA;AAAA;AAAA,UAGR,GAAG;AAAA,QACL;AAEA,0BAAkB,MAAM;AACxB,uBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAAA,MAClE;AAAA,IACF;AAGA,WAAO;AAEP,UAAM,cAAc,SAAS,QAAQ,GAAG;AAGxC,WAAO,iBAAiB,UAAU,WAAW;AAE7C,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,WAAW;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,WAAW,0BAA0B,cAAc,eAAe,mBAAmB,CAAC;AAE/G,QAAM,eAAe,UAAU,eAAe,mBAAmB;AAEjE,QAAM,OAAOA,OAAM;AAAA,IACjB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,cAAc,UAAU,SAAS;AAAA,EACpC;AAEA,QAAM,WAAWA,OAAM;AAAA,IACrB,OAAO;AAAA,MACL,cAAc,eAAe;AAAA,MAC7B,cAAc,eAAe;AAAA,MAC7B,SAAS,eAAe;AAAA,MACxB,QAAQ,eAAe;AAAA,IACzB;AAAA,IACA,CAAC,eAAe,QAAQ,eAAe,SAAS,eAAe,cAAc,eAAe,YAAY;AAAA,EAC1G;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,mBAAmB,cAAc;AACjC,MAAM,+BAA+B,SAAS,kBAAkB;AAChE,6BAA6B,YAC3B;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-statements */\nimport React, { useEffect, useMemo } from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip } from '@elliemae/ds-hooks-headless-tooltip';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\nimport { useComputedPositionStyles } from './useComputedPositionStyles.js';\nimport { usePositionObserver } from './utils/positionObserver.js';\n\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(props, defaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n onOpen,\n onClose,\n externallyControlledIsOpen,\n } = propsWithDefault;\n\n const [internalIsOpen, setInternalIsOpen] = React.useState<boolean>(false);\n const isOpenSourceOfTruth = useMemo(() => {\n if (externallyControlledIsOpen !== undefined) return externallyControlledIsOpen;\n return internalIsOpen;\n }, [externallyControlledIsOpen, internalIsOpen]);\n\n const overChargedOnOpen = React.useCallback(() => {\n setInternalIsOpen(true);\n onOpen?.();\n }, [onOpen]);\n const overChargedOnClose = React.useCallback(() => {\n setInternalIsOpen(false);\n onClose?.();\n }, [onClose]);\n const tooltipHelpers = useHeadlessTooltip({ onOpen: overChargedOnOpen, onClose: overChargedOnClose });\n const { setReferenceElement, hideTooltip, showTooltip } = tooltipHelpers;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const [reference, _setReference] = React.useState<Element | null>(null);\n const [floating, setFloating] = React.useState<HTMLElement | null>(null);\n const [workaroundToEnsureAPositionWasCalculatedIfOpen, setWorkaroundToEnsureAPositionWasCalculatedIfOpen] =\n React.useState<number>(0);\n\n const { arrowStyles, floatingStyles, mutableUpdateStyles, debouncedUpdateStyles } = useComputedPositionStyles({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n // calculate position on mount\n // AND everytime the reference (which is actually immutable because it's stored in a React.useState)\n // changes\n useEffect(() => {\n requestAnimationFrame(() => {\n mutableUpdateStyles?.current();\n });\n // the dependency array is equal to being empty because mutableUpdateStyles is a ref.\n // this is effectively an \"on mount\"\n }, [reference, mutableUpdateStyles]);\n\n // use intersection observer to detect when the position of the reference changes needing to recalculate the position\n const updatePosOnIntersection = React.useCallback(() => {\n if (reference) {\n requestAnimationFrame(() => {\n debouncedUpdateStyles();\n });\n }\n }, [reference, debouncedUpdateStyles]);\n usePositionObserver(reference, updatePosOnIntersection);\n\n // when we detect that the flag about it being open/closed changes\n // we refresh the position of the tooltip calculation\n useEffect(() => {\n requestAnimationFrame(() => {\n mutableUpdateStyles?.current();\n });\n }, [isOpenSourceOfTruth, mutableUpdateStyles]);\n\n // this is a workaround to ensure that the position is calculated at least once when the tooltip is open\n const { visibility } = floatingStyles;\n const needsToCalculateBecauseStillInvisibleWhenShouldBeOpen = isOpenSourceOfTruth && visibility === 'hidden';\n useEffect(() => {\n if (needsToCalculateBecauseStillInvisibleWhenShouldBeOpen) {\n mutableUpdateStyles?.current();\n requestAnimationFrame(() => {\n setWorkaroundToEnsureAPositionWasCalculatedIfOpen((o) => o + 1);\n });\n }\n }, [\n needsToCalculateBecauseStillInvisibleWhenShouldBeOpen,\n mutableUpdateStyles,\n // this dependency is the point of this useEffect\n // it will keep triggering until the position is calculated if it needs to be calculated\n workaroundToEnsureAPositionWasCalculatedIfOpen,\n ]);\n\n const setReference = mergeRefs(_setReference, setReferenceElement);\n const refs = React.useMemo(\n () => ({\n setReference,\n setFloating,\n floating,\n reference,\n }),\n [setReference, floating, reference],\n );\n\n const handlers = React.useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles,\n handlers,\n isOpen: isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n mutableUpdateStyles,\n }),\n [\n refs,\n floatingStyles,\n handlers,\n isOpenSourceOfTruth,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n mutableUpdateStyles,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n"],
5
+ "mappings": "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",
6
6
  "names": ["React"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/FloatingWrapper/react-desc-prop-types.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement>;\n onAnimationStartTriggered?: () => void;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export type ExampleState = '0' | '1';\n}\n\nexport const defaultProps: Partial<DSFloatingWrapperT.DefaultProps> = {\n context: {\n withoutPortal: false,\n animationDuration: 300,\n withoutAnimation: false,\n },\n customOffset: [0, 12],\n};\n\nexport const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps> = {\n ...getPropsPerSlotPropTypes(DSFloatingWrapperName, DSFloatingWrapperSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n children: PropTypes.node.description('Content of the floating wrapper').isRequired,\n innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).description('Ref for the floating wrapper')\n .isRequired,\n isOpen: PropTypes.bool.description('Whether the floating wrapper is open').isRequired,\n floatingStyles: PropTypes.object.description('Style for the floating wrapper').isRequired,\n context: PropTypes.shape({\n portalDOMContainer: PropTypes.instanceOf(HTMLElement)\n .description('The DOM element where the tooltip will be rendered.')\n .defaultValue('the first \"main\" landmark available in the document or the body if no \"main\" is found'),\n withoutPortal: PropTypes.bool.description('Whether to render the floating wrapper without a portal'),\n animationDuration: PropTypes.number.description('Duration of the animation'),\n withoutAnimation: PropTypes.bool.description('Whether to render the floating wrapper without animation'),\n }).description('Context for the floating wrapper'),\n onAnimationStartTriggered: PropTypes.func.description(\n 'Callback invoked when the component trigger the animation start. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n onAnimationEnd: PropTypes.func.description(\n 'Callback when the animation ends. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n customOffset: PropTypes.arrayOf(PropTypes.number).description('Custom offset for the floating wrapper'),\n};\n\nexport const DSFloatingWrapperPropTypesSchema =\n DSFloatingWrapperPropTypes as unknown as ValidationMap<DSFloatingWrapperT.Props>;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,uBAAuB,8BAA8B;AAiDvD,MAAM,eAAyD;AAAA,EACpE,SAAS;AAAA,IACP,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AAAA,EACA,cAAc,CAAC,GAAG,EAAE;AACtB;AAEO,MAAM,6BAAkF;AAAA,EAC7F,GAAG,yBAAyB,uBAAuB,sBAAsB;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,UAAU,UAAU,KAAK,YAAY,iCAAiC,EAAE;AAAA,EACxE,UAAU,UAAU,UAAU,CAAC,UAAU,QAAQ,UAAU,IAAI,CAAC,EAAE,YAAY,8BAA8B,EACzG;AAAA,EACH,QAAQ,UAAU,KAAK,YAAY,sCAAsC,EAAE;AAAA,EAC3E,gBAAgB,UAAU,OAAO,YAAY,gCAAgC,EAAE;AAAA,EAC/E,SAAS,UAAU,MAAM;AAAA,IACvB,oBAAoB,UAAU,WAAW,WAAW,EACjD,YAAY,qDAAqD,EACjE,aAAa,uFAAuF;AAAA,IACvG,eAAe,UAAU,KAAK,YAAY,yDAAyD;AAAA,IACnG,mBAAmB,UAAU,OAAO,YAAY,2BAA2B;AAAA,IAC3E,kBAAkB,UAAU,KAAK,YAAY,0DAA0D;AAAA,EACzG,CAAC,EAAE,YAAY,kCAAkC;AAAA,EACjD,2BAA2B,UAAU,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EACA,gBAAgB,UAAU,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,cAAc,UAAU,QAAQ,UAAU,MAAM,EAAE,YAAY,wCAAwC;AACxG;AAEO,MAAM,mCACX;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement>;\n onAnimationStartTriggered?: () => void;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n}\n\nexport const defaultProps: Partial<DSFloatingWrapperT.DefaultProps> = {\n context: {\n withoutPortal: false,\n animationDuration: 300,\n withoutAnimation: false,\n },\n customOffset: [0, 12],\n};\n\nexport const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps> = {\n ...getPropsPerSlotPropTypes(DSFloatingWrapperName, DSFloatingWrapperSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n children: PropTypes.node.description('Content of the floating wrapper').isRequired,\n innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).description('Ref for the floating wrapper')\n .isRequired,\n isOpen: PropTypes.bool.description('Whether the floating wrapper is open').isRequired,\n floatingStyles: PropTypes.object.description('Style for the floating wrapper').isRequired,\n context: PropTypes.shape({\n portalDOMContainer: PropTypes.instanceOf(HTMLElement)\n .description('The DOM element where the tooltip will be rendered.')\n .defaultValue('the first \"main\" landmark available in the document or the body if no \"main\" is found'),\n withoutPortal: PropTypes.bool.description('Whether to render the floating wrapper without a portal'),\n animationDuration: PropTypes.number.description('Duration of the animation'),\n withoutAnimation: PropTypes.bool.description('Whether to render the floating wrapper without animation'),\n }).description('Context for the floating wrapper'),\n onAnimationStartTriggered: PropTypes.func.description(\n 'Callback invoked when the component trigger the animation start. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n onAnimationEnd: PropTypes.func.description(\n 'Callback when the animation ends. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n customOffset: PropTypes.arrayOf(PropTypes.number).description('Custom offset for the floating wrapper'),\n};\n\nexport const DSFloatingWrapperPropTypesSchema =\n DSFloatingWrapperPropTypes as unknown as ValidationMap<DSFloatingWrapperT.Props>;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,uBAAuB,8BAA8B;AA+CvD,MAAM,eAAyD;AAAA,EACpE,SAAS;AAAA,IACP,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AAAA,EACA,cAAc,CAAC,GAAG,EAAE;AACtB;AAEO,MAAM,6BAAkF;AAAA,EAC7F,GAAG,yBAAyB,uBAAuB,sBAAsB;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,UAAU,UAAU,KAAK,YAAY,iCAAiC,EAAE;AAAA,EACxE,UAAU,UAAU,UAAU,CAAC,UAAU,QAAQ,UAAU,IAAI,CAAC,EAAE,YAAY,8BAA8B,EACzG;AAAA,EACH,QAAQ,UAAU,KAAK,YAAY,sCAAsC,EAAE;AAAA,EAC3E,gBAAgB,UAAU,OAAO,YAAY,gCAAgC,EAAE;AAAA,EAC/E,SAAS,UAAU,MAAM;AAAA,IACvB,oBAAoB,UAAU,WAAW,WAAW,EACjD,YAAY,qDAAqD,EACjE,aAAa,uFAAuF;AAAA,IACvG,eAAe,UAAU,KAAK,YAAY,yDAAyD;AAAA,IACnG,mBAAmB,UAAU,OAAO,YAAY,2BAA2B;AAAA,IAC3E,kBAAkB,UAAU,KAAK,YAAY,0DAA0D;AAAA,EACzG,CAAC,EAAE,YAAY,kCAAkC;AAAA,EACjD,2BAA2B,UAAU,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EACA,gBAAgB,UAAU,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,cAAc,UAAU,QAAQ,UAAU,MAAM,EAAE,YAAY,wCAAwC;AACxG;AAEO,MAAM,mCACX;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ import React2, { useState } from "react";
3
+ import { debounce } from "lodash-es";
4
+ import { computePosition } from "./utils/computePosition.js";
5
+ const useComputedPositionStyles = (config) => {
6
+ const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, preventComputing } = config;
7
+ const [arrowStyles, setArrowStyles] = useState({
8
+ style: { left: 0 },
9
+ placement: "top"
10
+ });
11
+ const [floatingStyles, setFloatingStyles] = useState({
12
+ position: "absolute",
13
+ zIndex: 3e3,
14
+ top: 0,
15
+ left: 0,
16
+ visibility: "hidden"
17
+ });
18
+ const canComputePosition = reference !== null && floating !== null;
19
+ const canAndShouldComputePosition = canComputePosition && preventComputing !== true;
20
+ const updateStyles = React2.useCallback(() => {
21
+ if (canAndShouldComputePosition) {
22
+ const { coordsStyle, finalPlacement, coordsArrow } = computePosition({
23
+ reference,
24
+ floating,
25
+ placement,
26
+ placementOrderPreference,
27
+ customOffset,
28
+ withoutPortal
29
+ });
30
+ setFloatingStyles({
31
+ position: "absolute",
32
+ zIndex: 3e3,
33
+ ...coordsStyle
34
+ });
35
+ setArrowStyles({ style: coordsArrow, placement: finalPlacement });
36
+ }
37
+ }, [
38
+ canAndShouldComputePosition,
39
+ reference,
40
+ floating,
41
+ placement,
42
+ placementOrderPreference,
43
+ customOffset,
44
+ withoutPortal
45
+ ]);
46
+ const mutableUpdateStyles = React2.useRef(updateStyles);
47
+ mutableUpdateStyles.current = updateStyles;
48
+ const debouncedUpdateStyles = React2.useMemo(() => debounce(() => mutableUpdateStyles.current(), 100), []);
49
+ const resetStyles = React2.useCallback(() => {
50
+ setFloatingStyles({
51
+ position: "absolute",
52
+ zIndex: 3e3,
53
+ top: 0,
54
+ left: 0,
55
+ visibility: "hidden"
56
+ });
57
+ setArrowStyles({ style: { left: 0 }, placement: "top" });
58
+ }, []);
59
+ return React2.useMemo(
60
+ () => ({ arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, mutableUpdateStyles, resetStyles }),
61
+ [arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, resetStyles]
62
+ );
63
+ };
64
+ export {
65
+ useComputedPositionStyles
66
+ };
67
+ //# sourceMappingURL=useComputedPositionStyles.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/useComputedPositionStyles.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useState } from 'react';\nimport { debounce } from 'lodash-es';\nimport { type CSSProperties } from 'styled-components';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\n\ntype UseComputedPositionStylesT = {\n preventComputing?: boolean;\n reference: Element | null;\n floating: HTMLElement | null;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n};\n/**\n * this custom hook has a single purpose, to compute the position of the floating element relative to the reference element\n *\n * we ideally don't want to calculate positions if the open flag is false as the styles should not be visible so not relevant.\n * @param {UseComputedPositionStylesT} config - The configuration object.\n * @param {Boolean} config.preventComputing - If true, the position will not be computed, usually used when the open flag is false.\n * @param {Element} config.reference - The reference element as a DOM element.\n * @param {HTMLElement} config.floating - The floating element as a DOM element (required to calculate the best fitting position).\n * @param {DSHookFloatingContextT.PopperPlacementsT} config.placement - The placement of the floating element relative to the reference element to be applied if possible.\n * @param {DSHookFloatingContextT.PopperPlacementsT[]} config.placementOrderPreference - The order of preference for the placement of the floating element relative to the reference element, the first one that fits will be used.\n * @param {[number, number]} config.customOffset - The offset of the floating element relative to the reference element if any is desired.\n * @param {Boolean} config.withoutPortal - If true, the floating element will be positioned relative to the reference element, otherwise it will be positioned relative to the viewport.\n *\n * @returns results\n * @returns results.arrowStyles - the styles to be applied to the arrow element if any is desired\n * @returns results.floatingStyles - the styles to be applied to the floating element\n * @returns results.updateStyles - a function to be called to update the styles of the floating element on demand if needed\n * @returns results.debouncedUpdateStyles - a debounced version of the updateStyles function to be used when lot of invocations are expected (e.g. on scroll)\n * @returns results.mutableUpdateStyles - a ref to the updateStyles function to be used when the function needs to be called in a useEffect or similar\n */\nexport const useComputedPositionStyles = (config: UseComputedPositionStylesT) => {\n const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal, preventComputing } =\n config;\n\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({\n style: { left: 0 },\n placement: 'top',\n });\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n const canComputePosition = reference !== null && floating !== null;\n const canAndShouldComputePosition = canComputePosition && preventComputing !== true;\n\n const updateStyles = React.useCallback(() => {\n if (canAndShouldComputePosition) {\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n setFloatingStyles({\n position: 'absolute',\n zIndex: 3000,\n ...coordsStyle,\n });\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n }\n }, [\n canAndShouldComputePosition,\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n ]);\n\n // when deboucing we only care to invoke the most updated version of the function\n // continuously redefining the debouncedUpdateStyles function is a waste of resources\n // so we use a ref to store the latest version of the function\n const mutableUpdateStyles = React.useRef(updateStyles);\n mutableUpdateStyles.current = updateStyles;\n // and we only define the debounced version once, using the ref to always have the latest version of the function.\n // notice the ()=> mutableUpdateStyles.current() syntax\n // we create a new closure (the anonymous function) that is referientially stable\n // and we call the mutableUpdateStyles.current function inside it (which is NOT referentially stable)\n const debouncedUpdateStyles = React.useMemo(() => debounce(() => mutableUpdateStyles.current(), 100), []);\n\n const resetStyles = React.useCallback(() => {\n setFloatingStyles({\n position: 'absolute',\n zIndex: 3000,\n top: 0,\n left: 0,\n visibility: 'hidden',\n });\n setArrowStyles({ style: { left: 0 }, placement: 'top' });\n }, []);\n\n return React.useMemo(\n () => ({ arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, mutableUpdateStyles, resetStyles }),\n [arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, resetStyles],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,UAAS,gBAAgB;AAChC,SAAS,gBAAgB;AAEzB,SAAS,uBAAuB;AAiCzB,MAAM,4BAA4B,CAAC,WAAuC;AAC/E,QAAM,EAAE,WAAW,UAAU,WAAW,0BAA0B,cAAc,eAAe,iBAAiB,IAC9G;AAEF,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB;AAAA,IAC5D,OAAO,EAAE,MAAM,EAAE;AAAA,IACjB,WAAW;AAAA,EACb,CAAC;AACD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd,CAAC;AACD,QAAM,qBAAqB,cAAc,QAAQ,aAAa;AAC9D,QAAM,8BAA8B,sBAAsB,qBAAqB;AAE/E,QAAM,eAAeA,OAAM,YAAY,MAAM;AAC3C,QAAI,6BAA6B;AAC/B,YAAM,EAAE,aAAa,gBAAgB,YAAY,IAAI,gBAAgB;AAAA,QACnE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,wBAAkB;AAAA,QAChB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,GAAG;AAAA,MACL,CAAC;AACD,qBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAAA,IAClE;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,sBAAsBA,OAAM,OAAO,YAAY;AACrD,sBAAoB,UAAU;AAK9B,QAAM,wBAAwBA,OAAM,QAAQ,MAAM,SAAS,MAAM,oBAAoB,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC;AAExG,QAAM,cAAcA,OAAM,YAAY,MAAM;AAC1C,sBAAkB;AAAA,MAChB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,IACd,CAAC;AACD,mBAAe,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,SAAOA,OAAM;AAAA,IACX,OAAO,EAAE,aAAa,gBAAgB,cAAc,uBAAuB,qBAAqB,YAAY;AAAA,IAC5G,CAAC,aAAa,gBAAgB,cAAc,uBAAuB,WAAW;AAAA,EAChF;AACF;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,128 @@
1
+ import * as React from "react";
2
+ import React2 from "react";
3
+ class PositionObserver {
4
+ intersectionObserver;
5
+ positionObserverCallback;
6
+ thresholdList;
7
+ constructor(positionObserverCallback, thresholdFraction = 1e3) {
8
+ this.positionObserverCallback = positionObserverCallback;
9
+ this.thresholdList = new Array(thresholdFraction + 1).fill(0).map((_, ind) => ind / thresholdFraction);
10
+ }
11
+ observe(targetElement) {
12
+ this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {
13
+ threshold: this.thresholdList,
14
+ rootMargin: "0px 0px 0px 0px",
15
+ root: document
16
+ });
17
+ this.intersectionObserver.observe(targetElement);
18
+ }
19
+ viewportCallback(e) {
20
+ const entry = e[0];
21
+ const { target } = entry;
22
+ const targetBounds = entry.boundingClientRect;
23
+ if (this.positionObserverCallback) {
24
+ this.positionObserverCallback({
25
+ x: targetBounds.left,
26
+ y: targetBounds.top,
27
+ target,
28
+ outOfViewport: !entry.isIntersecting,
29
+ rootBounds: entry.rootBounds
30
+ });
31
+ }
32
+ if (entry.intersectionRatio > 0) {
33
+ this.intersectionObserver?.unobserve(target);
34
+ this.intersectionObserver?.disconnect();
35
+ const options = {
36
+ threshold: this.thresholdList,
37
+ rootMargin: this.getMargins(
38
+ this.constructBoxWindow(targetBounds, entry.rootBounds),
39
+ entry.rootBounds
40
+ ),
41
+ root: document
42
+ };
43
+ this.intersectionObserver = new IntersectionObserver(this.intersectionObsCallback.bind(this), options);
44
+ this.intersectionObserver?.observe(target);
45
+ }
46
+ }
47
+ intersectionObsCallback(e) {
48
+ const entry = e[0];
49
+ const { target } = entry;
50
+ const targetBounds = entry.boundingClientRect;
51
+ if (this.positionObserverCallback) {
52
+ this.positionObserverCallback({
53
+ x: targetBounds.left,
54
+ y: targetBounds.top,
55
+ target,
56
+ outOfViewport: false,
57
+ rootBounds: entry.rootBounds
58
+ });
59
+ }
60
+ if (entry.intersectionRatio === 0) {
61
+ this.intersectionObserver?.unobserve(target);
62
+ this.intersectionObserver?.disconnect();
63
+ this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {
64
+ threshold: this.thresholdList,
65
+ rootMargin: "0px 0px 0px 0px",
66
+ root: document
67
+ });
68
+ this.intersectionObserver?.observe(target);
69
+ }
70
+ }
71
+ disconnect() {
72
+ this.intersectionObserver?.disconnect();
73
+ }
74
+ constructBoxWindow(targetBounds, rootBounds) {
75
+ const constrainedLeft = Math.min(
76
+ Math.max(rootBounds.left, targetBounds.left),
77
+ rootBounds.right - targetBounds.width
78
+ );
79
+ const constrainedTop = Math.min(
80
+ Math.max(rootBounds.top, targetBounds.top),
81
+ rootBounds.bottom - targetBounds.height
82
+ );
83
+ const constrainedRight = constrainedLeft + targetBounds.width;
84
+ const constrainedBottom = constrainedTop + targetBounds.height;
85
+ return {
86
+ left: constrainedLeft,
87
+ top: constrainedTop,
88
+ right: constrainedRight,
89
+ bottom: constrainedBottom
90
+ };
91
+ }
92
+ getMargins(windowDimensions, rootBounds) {
93
+ let viewportBounds;
94
+ if (!rootBounds) {
95
+ viewportBounds = {
96
+ top: visualViewport.offsetTop,
97
+ left: visualViewport.offsetLeft,
98
+ right: visualViewport.width + visualViewport.offsetLeft,
99
+ bottom: visualViewport.height + visualViewport.offsetTop
100
+ };
101
+ } else {
102
+ viewportBounds = rootBounds;
103
+ }
104
+ const constrainedTopMarginOfWindow = Math.min(-(windowDimensions.top - 1 - viewportBounds.top), 0);
105
+ const constrainedRightMarginOfWindow = Math.min(-(viewportBounds.right - (windowDimensions.right + 1)), 0);
106
+ const constrainedBottomMarginOfWindow = Math.min(-(viewportBounds.bottom - (windowDimensions.bottom + 1)), 0);
107
+ const constrainedLeftMarginOfWindow = Math.min(-(windowDimensions.left - 1 - viewportBounds.left), 0);
108
+ return `${constrainedTopMarginOfWindow}px ${constrainedRightMarginOfWindow}px ${constrainedBottomMarginOfWindow}px ${constrainedLeftMarginOfWindow}px`;
109
+ }
110
+ }
111
+ const usePositionObserver = (elementNode, onPositionChange = () => {
112
+ }) => {
113
+ React2.useEffect(() => {
114
+ const hasIOSupport = !!window.IntersectionObserver;
115
+ if (!hasIOSupport || !elementNode) return () => {
116
+ };
117
+ const positionObs = new PositionObserver(onPositionChange);
118
+ positionObs.observe(elementNode);
119
+ return () => {
120
+ positionObs.disconnect();
121
+ };
122
+ }, [elementNode, onPositionChange]);
123
+ };
124
+ export {
125
+ PositionObserver,
126
+ usePositionObserver
127
+ };
128
+ //# sourceMappingURL=positionObserver.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/utils/positionObserver.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\n\n/**\n * Copyright (c) 2025 AJK-Essential\n * This file is licensed under the MIT License.\n * See the LICENSE file in the project root for license information.\n */\n\nexport type PositionData = {\n x: number;\n y: number;\n target: HTMLElement | Element;\n outOfViewport: boolean;\n rootBounds: DOMRect | null;\n};\nexport type PositionObserverCallback = (data: PositionData) => void;\n\nexport class PositionObserver {\n private intersectionObserver!: IntersectionObserver;\n\n private positionObserverCallback;\n\n private thresholdList;\n\n constructor(positionObserverCallback: PositionObserverCallback, thresholdFraction = 1000) {\n this.positionObserverCallback = positionObserverCallback;\n this.thresholdList = new Array(thresholdFraction + 1).fill(0).map((_, ind) => ind / thresholdFraction);\n }\n\n public observe(targetElement: HTMLElement | Element) {\n this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {\n threshold: this.thresholdList,\n rootMargin: '0px 0px 0px 0px',\n root: document,\n });\n this.intersectionObserver.observe(targetElement);\n }\n\n private viewportCallback(e: IntersectionObserverEntry[]) {\n const entry = e[0];\n const { target } = entry;\n const targetBounds = entry.boundingClientRect;\n if (this.positionObserverCallback) {\n this.positionObserverCallback({\n x: targetBounds.left,\n y: targetBounds.top,\n target,\n outOfViewport: !entry.isIntersecting,\n rootBounds: entry.rootBounds,\n });\n }\n // If ever there is an intersection in this callback which observes\n // viewport hits, that means, the target is peaking itself inside\n // the viewport (Some part of the target is visible in the viewport).\n // We therefore immediately pass it to the other callback with a finer\n // window to capture changes.\n\n // The finer window is constructed such that it is limited within the\n // viewport boundaries and it has same size as that of target so that\n // if the target enters or exits further, it will eventually increase\n // or decrease the area of intersection (the common area between the\n // target and the finer window) within the window, thus signalling\n // the movement.\n if (entry.intersectionRatio > 0) {\n this.intersectionObserver?.unobserve(target);\n this.intersectionObserver?.disconnect();\n const options: IntersectionObserverInit = {\n threshold: this.thresholdList,\n rootMargin: this.getMargins(\n this.constructBoxWindow(targetBounds, entry.rootBounds as DOMRect),\n entry.rootBounds,\n ),\n root: document,\n };\n this.intersectionObserver = new IntersectionObserver(this.intersectionObsCallback.bind(this), options);\n this.intersectionObserver?.observe(target);\n }\n }\n\n private intersectionObsCallback(e: IntersectionObserverEntry[]) {\n const entry = e[0];\n const { target } = entry;\n const targetBounds = entry.boundingClientRect;\n if (this.positionObserverCallback) {\n this.positionObserverCallback({\n x: targetBounds.left,\n y: targetBounds.top,\n target,\n outOfViewport: false,\n rootBounds: entry.rootBounds,\n });\n }\n // if intersectionRatio is 0, then it means\n // the target is fully out of the finer window.\n // In that case, we pass this to the viewport\n // detector callback (whether it is inside the\n // viewport or not).\n // And it stays there in that callback until\n // the viewport detector callback says, yah, we found it..\n // when it comes back to this callback with an updated finer window\n if (entry.intersectionRatio === 0) {\n this.intersectionObserver?.unobserve(target);\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = new IntersectionObserver(this.viewportCallback.bind(this), {\n threshold: this.thresholdList,\n rootMargin: '0px 0px 0px 0px',\n root: document,\n });\n this.intersectionObserver?.observe(target);\n }\n }\n\n public disconnect() {\n this.intersectionObserver?.disconnect();\n }\n\n private constructBoxWindow(targetBounds: DOMRect, rootBounds: DOMRect) {\n const constrainedLeft = Math.min(\n Math.max(rootBounds.left, targetBounds.left),\n rootBounds.right - targetBounds.width,\n );\n const constrainedTop = Math.min(\n Math.max(rootBounds.top, targetBounds.top),\n rootBounds.bottom - targetBounds.height,\n );\n const constrainedRight = constrainedLeft + targetBounds.width;\n const constrainedBottom = constrainedTop + targetBounds.height;\n return {\n left: constrainedLeft,\n top: constrainedTop,\n right: constrainedRight,\n bottom: constrainedBottom,\n };\n }\n\n private getMargins(\n windowDimensions: {\n left: number;\n top: number;\n right: number;\n bottom: number;\n },\n rootBounds: DOMRect | null,\n ) {\n let viewportBounds;\n if (!rootBounds) {\n viewportBounds = {\n top: visualViewport!.offsetTop,\n left: visualViewport!.offsetLeft,\n right: visualViewport!.width + visualViewport!.offsetLeft,\n bottom: visualViewport!.height + visualViewport!.offsetTop,\n };\n } else {\n viewportBounds = rootBounds;\n }\n const constrainedTopMarginOfWindow = Math.min(-(windowDimensions.top - 1 - viewportBounds.top), 0);\n const constrainedRightMarginOfWindow = Math.min(-(viewportBounds.right - (windowDimensions.right + 1)), 0);\n const constrainedBottomMarginOfWindow = Math.min(-(viewportBounds.bottom - (windowDimensions.bottom + 1)), 0);\n const constrainedLeftMarginOfWindow = Math.min(-(windowDimensions.left - 1 - viewportBounds.left), 0);\n return `${constrainedTopMarginOfWindow}px ${constrainedRightMarginOfWindow}px ${constrainedBottomMarginOfWindow}px ${constrainedLeftMarginOfWindow}px`;\n }\n}\n\nexport const usePositionObserver = (\n elementNode: Element | null,\n onPositionChange: PositionObserverCallback = () => {},\n) => {\n React.useEffect(() => {\n const hasIOSupport = !!window.IntersectionObserver;\n if (!hasIOSupport || !elementNode) return () => {};\n const positionObs = new PositionObserver(onPositionChange);\n positionObs.observe(elementNode);\n\n return () => {\n positionObs.disconnect();\n };\n }, [elementNode, onPositionChange]);\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React"]
7
+ }
@@ -1,7 +1,5 @@
1
1
  import React from 'react';
2
- import { type CSSProperties } from 'styled-components';
3
2
  import type { DSHookFloatingContextT } from './react-desc-prop-types.js';
4
- import type { PopoverArrowT } from './parts/PopoverArrow.js';
5
3
  declare const useFloatingContext: {
6
4
  (props?: DSHookFloatingContextT.Props): {
7
5
  refs: {
@@ -10,7 +8,7 @@ declare const useFloatingContext: {
10
8
  floating: HTMLElement | null;
11
9
  reference: Element | null;
12
10
  };
13
- floatingStyles: CSSProperties;
11
+ floatingStyles: import("styled-components").CSSProperties;
14
12
  handlers: {
15
13
  onMouseEnter: () => void;
16
14
  onMouseLeave: () => void;
@@ -18,7 +16,7 @@ declare const useFloatingContext: {
18
16
  onBlur: () => void;
19
17
  };
20
18
  isOpen: boolean;
21
- arrowStyles: PopoverArrowT;
19
+ arrowStyles: import("./parts/PopoverArrow.js").PopoverArrowT;
22
20
  hideTooltip: () => void;
23
21
  showTooltip: () => void;
24
22
  context: {
@@ -27,6 +25,7 @@ declare const useFloatingContext: {
27
25
  portalDOMContainer: HTMLElement | undefined;
28
26
  animationDuration: number;
29
27
  };
28
+ mutableUpdateStyles: React.MutableRefObject<() => void>;
30
29
  };
31
30
  displayName: string;
32
31
  };
@@ -11,7 +11,7 @@ export declare const useFloatingWrapper: (propsFromUser: DSFloatingWrapperT.Prop
11
11
  propsWithDefault: DSFloatingWrapperT.InternalProps;
12
12
  xstyledProps: import("@elliemae/ds-props-helpers").XstyledProps;
13
13
  instanceUid: string;
14
- globalsAttrs: Partial<Pick<object, "start" | "height" | "width" | "content" | "style" | "cite" | "data" | "form" | "label" | "slot" | "span" | "summary" | "title" | "pattern" | "default" | "type" | "name" | "suppressHydrationWarning" | "className" | "color" | "id" | "lang" | "max" | "media" | "method" | "min" | "target" | "role" | "tabIndex" | "crossOrigin" | "href" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "classID" | "useMap" | "wmode" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "enterKeyHint" | "hidden" | "nonce" | "spellCheck" | "translate" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "scoped" | "download" | "hrefLang" | "alt" | "coords" | "shape" | "autoPlay" | "controls" | "loop" | "mediaGroup" | "muted" | "playsInline" | "preload" | "src" | "disabled" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "value" | "dateTime" | "open" | "acceptCharset" | "action" | "autoComplete" | "encType" | "noValidate" | "manifest" | "allowFullScreen" | "allowTransparency" | "frameBorder" | "marginHeight" | "marginWidth" | "sandbox" | "scrolling" | "seamless" | "srcDoc" | "sizes" | "srcSet" | "accept" | "capture" | "checked" | "list" | "maxLength" | "minLength" | "multiple" | "placeholder" | "readOnly" | "required" | "size" | "step" | "challenge" | "keyType" | "keyParams" | "htmlFor" | "integrity" | "charSet" | "httpEquiv" | "high" | "low" | "optimum" | "reversed" | "selected" | "async" | "defer" | "cellPadding" | "cellSpacing" | "colSpan" | "headers" | "rowSpan" | "scope" | "cols" | "rows" | "wrap" | "kind" | "srcLang" | "poster"> & Omit<{
14
+ globalsAttrs: Partial<Pick<object, "start" | "height" | "width" | "content" | "style" | "cite" | "data" | "form" | "label" | "slot" | "span" | "summary" | "title" | "pattern" | "default" | "type" | "name" | "suppressHydrationWarning" | "className" | "color" | "id" | "lang" | "max" | "media" | "method" | "min" | "target" | "role" | "tabIndex" | "crossOrigin" | "href" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "classID" | "useMap" | "wmode" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "enterKeyHint" | "hidden" | "nonce" | "spellCheck" | "translate" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "scoped" | "download" | "hrefLang" | "alt" | "coords" | "shape" | "autoPlay" | "controls" | "loop" | "mediaGroup" | "muted" | "playsInline" | "preload" | "src" | "disabled" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "value" | "dateTime" | "open" | "acceptCharset" | "action" | "autoComplete" | "encType" | "noValidate" | "manifest" | "allowFullScreen" | "allowTransparency" | "frameBorder" | "marginHeight" | "marginWidth" | "sandbox" | "scrolling" | "seamless" | "srcDoc" | "sizes" | "srcSet" | "accept" | "capture" | "checked" | "list" | "maxLength" | "minLength" | "multiple" | "placeholder" | "readOnly" | "required" | "size" | "step" | "challenge" | "keyType" | "keyParams" | "htmlFor" | "integrity" | "charSet" | "httpEquiv" | "high" | "low" | "optimum" | "reversed" | "selected" | "async" | "defer" | "cellPadding" | "cellSpacing" | "colSpan" | "headers" | "rowSpan" | "scope" | "cols" | "rows" | "wrap" | "kind" | "srcLang" | "poster"> & Omit<{
15
15
  start?: number | undefined;
16
16
  height?: string | number | undefined;
17
17
  width?: string | number | undefined;
@@ -165,8 +165,6 @@ export declare const useFloatingWrapper: (propsFromUser: DSFloatingWrapperT.Prop
165
165
  onProgressCapture?: React.ReactEventHandler<Element> | undefined;
166
166
  onRateChange?: React.ReactEventHandler<Element> | undefined;
167
167
  onRateChangeCapture?: React.ReactEventHandler<Element> | undefined;
168
- onResize?: React.ReactEventHandler<Element> | undefined;
169
- onResizeCapture?: React.ReactEventHandler<Element> | undefined;
170
168
  onSeeked?: React.ReactEventHandler<Element> | undefined;
171
169
  onSeekedCapture?: React.ReactEventHandler<Element> | undefined;
172
170
  onSeeking?: React.ReactEventHandler<Element> | undefined;
@@ -27,7 +27,6 @@ export declare namespace DSFloatingWrapperT {
27
27
  }
28
28
  interface InternalProps extends DefaultProps, RequiredProps, OptionalProps, Omit<GlobalAttributesT<HTMLElement>, keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps>, XstyledProps {
29
29
  }
30
- type ExampleState = '0' | '1';
31
30
  }
32
31
  export declare const defaultProps: Partial<DSFloatingWrapperT.DefaultProps>;
33
32
  export declare const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps>;
@@ -0,0 +1,43 @@
1
+ /// <reference types="lodash" />
2
+ import React from 'react';
3
+ import { type CSSProperties } from 'styled-components';
4
+ import type { DSHookFloatingContextT } from './react-desc-prop-types.js';
5
+ import type { PopoverArrowT } from './parts/PopoverArrow.js';
6
+ type UseComputedPositionStylesT = {
7
+ preventComputing?: boolean;
8
+ reference: Element | null;
9
+ floating: HTMLElement | null;
10
+ placement: DSHookFloatingContextT.PopperPlacementsT;
11
+ placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];
12
+ customOffset: [number, number];
13
+ withoutPortal: boolean;
14
+ };
15
+ /**
16
+ * this custom hook has a single purpose, to compute the position of the floating element relative to the reference element
17
+ *
18
+ * we ideally don't want to calculate positions if the open flag is false as the styles should not be visible so not relevant.
19
+ * @param {UseComputedPositionStylesT} config - The configuration object.
20
+ * @param {Boolean} config.preventComputing - If true, the position will not be computed, usually used when the open flag is false.
21
+ * @param {Element} config.reference - The reference element as a DOM element.
22
+ * @param {HTMLElement} config.floating - The floating element as a DOM element (required to calculate the best fitting position).
23
+ * @param {DSHookFloatingContextT.PopperPlacementsT} config.placement - The placement of the floating element relative to the reference element to be applied if possible.
24
+ * @param {DSHookFloatingContextT.PopperPlacementsT[]} config.placementOrderPreference - The order of preference for the placement of the floating element relative to the reference element, the first one that fits will be used.
25
+ * @param {[number, number]} config.customOffset - The offset of the floating element relative to the reference element if any is desired.
26
+ * @param {Boolean} config.withoutPortal - If true, the floating element will be positioned relative to the reference element, otherwise it will be positioned relative to the viewport.
27
+ *
28
+ * @returns results
29
+ * @returns results.arrowStyles - the styles to be applied to the arrow element if any is desired
30
+ * @returns results.floatingStyles - the styles to be applied to the floating element
31
+ * @returns results.updateStyles - a function to be called to update the styles of the floating element on demand if needed
32
+ * @returns results.debouncedUpdateStyles - a debounced version of the updateStyles function to be used when lot of invocations are expected (e.g. on scroll)
33
+ * @returns results.mutableUpdateStyles - a ref to the updateStyles function to be used when the function needs to be called in a useEffect or similar
34
+ */
35
+ export declare const useComputedPositionStyles: (config: UseComputedPositionStylesT) => {
36
+ arrowStyles: PopoverArrowT;
37
+ floatingStyles: CSSProperties;
38
+ updateStyles: () => void;
39
+ debouncedUpdateStyles: import("lodash").DebouncedFunc<() => void>;
40
+ mutableUpdateStyles: React.MutableRefObject<() => void>;
41
+ resetStyles: () => void;
42
+ };
43
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) 2025 AJK-Essential
3
+ * This file is licensed under the MIT License.
4
+ * See the LICENSE file in the project root for license information.
5
+ */
6
+ export type PositionData = {
7
+ x: number;
8
+ y: number;
9
+ target: HTMLElement | Element;
10
+ outOfViewport: boolean;
11
+ rootBounds: DOMRect | null;
12
+ };
13
+ export type PositionObserverCallback = (data: PositionData) => void;
14
+ export declare class PositionObserver {
15
+ private intersectionObserver;
16
+ private positionObserverCallback;
17
+ private thresholdList;
18
+ constructor(positionObserverCallback: PositionObserverCallback, thresholdFraction?: number);
19
+ observe(targetElement: HTMLElement | Element): void;
20
+ private viewportCallback;
21
+ private intersectionObsCallback;
22
+ disconnect(): void;
23
+ private constructBoxWindow;
24
+ private getMargins;
25
+ }
26
+ export declare const usePositionObserver: (elementNode: Element | null, onPositionChange?: PositionObserverCallback) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-floating-context",
3
- "version": "3.52.0-rc.8",
3
+ "version": "3.52.0",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Popper Hook",
6
6
  "files": [
@@ -36,18 +36,18 @@
36
36
  "indent": 4
37
37
  },
38
38
  "dependencies": {
39
- "@elliemae/ds-hooks-headless-tooltip": "3.52.0-rc.8",
40
- "@elliemae/ds-system": "3.52.0-rc.8",
41
- "@elliemae/ds-props-helpers": "3.52.0-rc.8",
42
- "@elliemae/ds-typescript-helpers": "3.52.0-rc.8"
39
+ "@elliemae/ds-hooks-headless-tooltip": "3.52.0",
40
+ "@elliemae/ds-props-helpers": "3.52.0",
41
+ "@elliemae/ds-system": "3.52.0",
42
+ "@elliemae/ds-typescript-helpers": "3.52.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@elliemae/pui-cli": "9.0.0-next.55",
45
+ "@elliemae/pui-cli": "9.0.0-next.63",
46
46
  "jest": "~29.7.0",
47
- "@elliemae/ds-monorepo-devops": "3.52.0-rc.8"
47
+ "@elliemae/ds-monorepo-devops": "3.52.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "lodash": "^4.17.21",
50
+ "lodash-es": "^4.17.21",
51
51
  "react": "^18.3.1",
52
52
  "react-dom": "^18.3.1",
53
53
  "styled-components": "~5.3.9",