@elliemae/ds-floating-context 3.52.1 → 3.53.0-alpha.2

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.
Files changed (43) hide show
  1. package/dist/cjs/DSFloatingContext.js +47 -57
  2. package/dist/cjs/DSFloatingContext.js.map +2 -2
  3. package/dist/cjs/parts/FloatingWrapper/FloatingWrapper.js +0 -1
  4. package/dist/cjs/parts/FloatingWrapper/FloatingWrapper.js.map +2 -2
  5. package/dist/cjs/parts/PopoverArrow.js +42 -9
  6. package/dist/cjs/parts/PopoverArrow.js.map +2 -2
  7. package/dist/cjs/typescript-testing/typescript-floating-context-valid.js +94 -0
  8. package/dist/cjs/typescript-testing/typescript-floating-context-valid.js.map +7 -0
  9. package/dist/cjs/useComputedPositionStyles.js +69 -48
  10. package/dist/cjs/useComputedPositionStyles.js.map +3 -3
  11. package/dist/cjs/utils/computePosition.js +4 -7
  12. package/dist/cjs/utils/computePosition.js.map +2 -2
  13. package/dist/cjs/utils/detectOverflow.js +5 -3
  14. package/dist/cjs/utils/detectOverflow.js.map +2 -2
  15. package/dist/esm/DSFloatingContext.js +48 -58
  16. package/dist/esm/DSFloatingContext.js.map +2 -2
  17. package/dist/esm/parts/FloatingWrapper/FloatingWrapper.js +0 -1
  18. package/dist/esm/parts/FloatingWrapper/FloatingWrapper.js.map +2 -2
  19. package/dist/esm/parts/PopoverArrow.js +42 -9
  20. package/dist/esm/parts/PopoverArrow.js.map +2 -2
  21. package/dist/esm/typescript-testing/typescript-floating-context-valid.js +71 -0
  22. package/dist/esm/typescript-testing/typescript-floating-context-valid.js.map +7 -0
  23. package/dist/esm/useComputedPositionStyles.js +69 -48
  24. package/dist/esm/useComputedPositionStyles.js.map +3 -3
  25. package/dist/esm/utils/computePosition.js +4 -7
  26. package/dist/esm/utils/computePosition.js.map +2 -2
  27. package/dist/esm/utils/detectOverflow.js +5 -3
  28. package/dist/esm/utils/detectOverflow.js.map +2 -2
  29. package/dist/types/DSFloatingContext.d.ts +3 -2
  30. package/dist/types/constants/index.d.ts +3 -0
  31. package/dist/types/parts/FloatingWrapper/config/useFloatingWrapper.d.ts +182 -182
  32. package/dist/types/parts/FloatingWrapper/react-desc-prop-types.d.ts +0 -2
  33. package/dist/types/tests/ControlledTestRenderer.d.ts +1 -0
  34. package/dist/types/tests/FloatingContext.a11y.test.d.ts +1 -0
  35. package/dist/types/tests/FloatingContext.data-testid.test.d.ts +1 -0
  36. package/dist/types/tests/FloatingContext.event.test.d.ts +1 -0
  37. package/dist/types/tests/FloatingContext.exports.test.d.ts +1 -0
  38. package/dist/types/tests/FloatingContext.get-owner-props.test.d.ts +1 -0
  39. package/dist/types/tests/playwright/FloatingContext.test.playwright.d.ts +1 -0
  40. package/dist/types/typescript-testing/typescript-floating-context-valid.d.ts +1 -0
  41. package/dist/types/useComputedPositionStyles.d.ts +6 -24
  42. package/dist/types/utils/computePosition.d.ts +2 -2
  43. package/package.json +8 -8
@@ -4,15 +4,23 @@ import { useOwnerProps, useGetGlobalAttributes, useGetXstyledProps } from "@elli
4
4
  import { styled } from "@elliemae/ds-system";
5
5
  import { DSFloatingWrapperSlots, DSFloatingWrapperName } from "../constants/index.js";
6
6
  const arrowWidth = 18;
7
- const arrowHeight = 18;
8
7
  const OFFSET_FIX_SHADOW_DEFECT = 0.25;
8
+ const arrowDimensionBase13 = arrowWidth / 13;
9
+ const OFFSET_FIX_SHADOW_DEFECT_BASE13 = OFFSET_FIX_SHADOW_DEFECT / 13;
10
+ const arrowDimensionBase16 = arrowWidth / 16;
11
+ const OFFSET_FIX_SHADOW_DEFECT_BASE16 = OFFSET_FIX_SHADOW_DEFECT / 16;
12
+ const arrowPlacementBase13 = arrowDimensionBase13 - OFFSET_FIX_SHADOW_DEFECT_BASE13;
13
+ const arrowPlacementBase16 = arrowDimensionBase16 - OFFSET_FIX_SHADOW_DEFECT_BASE16;
14
+ const isTopOrBottom = (placement) => placement.startsWith("top") || placement.startsWith("bottom");
15
+ const isLeftOrRight = (placement) => placement.startsWith("left") || placement.startsWith("right");
9
16
  const StyledArrow = styled("div", {
10
17
  name: DSFloatingWrapperName,
11
18
  slot: DSFloatingWrapperSlots.ARROW
12
19
  })`
20
+ line-height: 0;
13
21
  position: absolute;
14
- width: ${arrowWidth}px;
15
- height: ${arrowHeight}px;
22
+ width: ${arrowDimensionBase16}rem;
23
+ height: ${arrowDimensionBase16}rem;
16
24
  pointer-events: none;
17
25
  background-color: transparent;
18
26
  & .stroke {
@@ -27,7 +35,7 @@ const StyledArrow = styled("div", {
27
35
  svg {
28
36
  transform: rotateZ(180deg);
29
37
  }
30
- bottom: -${arrowHeight - OFFSET_FIX_SHADOW_DEFECT}px;
38
+ bottom: -${arrowPlacementBase16}rem;
31
39
  left: ${(props) => {
32
40
  if (props["data-placement"].endsWith("start")) return `25%`;
33
41
  if (props["data-placement"].endsWith("end")) return `75%`;
@@ -38,10 +46,10 @@ const StyledArrow = styled("div", {
38
46
  svg {
39
47
  transform: rotateZ(-90deg);
40
48
  }
41
- left: -${arrowWidth - OFFSET_FIX_SHADOW_DEFECT}px;
49
+ left: -${arrowPlacementBase16}rem;
42
50
  }
43
51
  &[data-placement^='bottom'] {
44
- top: -${arrowHeight - OFFSET_FIX_SHADOW_DEFECT}px;
52
+ top: -${arrowPlacementBase16}rem;
45
53
  left: ${(props) => {
46
54
  if (props["data-placement"].endsWith("start")) return `25%`;
47
55
  if (props["data-placement"].endsWith("end")) return `75%`;
@@ -52,10 +60,35 @@ const StyledArrow = styled("div", {
52
60
  svg {
53
61
  transform: rotateZ(90deg);
54
62
  }
55
- right: -${arrowWidth - OFFSET_FIX_SHADOW_DEFECT}px;
63
+ right: -${arrowPlacementBase16}rem;
64
+ }
65
+ margin-left: ${(props) => isTopOrBottom(props["data-placement"]) ? `-${arrowDimensionBase16 / 2}rem` : "0"};
66
+ margin-top: ${(props) => isLeftOrRight(props["data-placement"]) ? `-${arrowDimensionBase16 / 2}rem` : "0"};
67
+
68
+ @media (min-width: ${({ theme }) => theme.breakpoints.small}) {
69
+ width: ${arrowDimensionBase13}rem;
70
+ height: ${arrowDimensionBase13}rem;
71
+
72
+ &[data-placement^='top'] {
73
+ bottom: -${arrowPlacementBase13}rem;
74
+ }
75
+
76
+ &[data-placement^='bottom'] {
77
+ top: -${arrowPlacementBase13}rem;
78
+ }
79
+
80
+ &[data-placement^='left'] {
81
+ right: -${arrowPlacementBase13}rem;
82
+ }
83
+
84
+ &[data-placement^='right'] {
85
+ left: -${arrowPlacementBase13}rem;
86
+ }
87
+
88
+ margin-left: ${(props) => isTopOrBottom(props["data-placement"]) ? `-${arrowDimensionBase13 / 2}rem` : "0"};
89
+
90
+ margin-top: ${(props) => isLeftOrRight(props["data-placement"]) ? `-${arrowDimensionBase13 / 2}rem` : "0"};
56
91
  }
57
- margin-left: ${(props) => props["data-placement"].startsWith("top") || props["data-placement"].startsWith("bottom") ? `-${arrowWidth / 2}px;` : "0;"};
58
- margin-top: ${(props) => props["data-placement"].startsWith("left") || props["data-placement"].startsWith("right") ? `-${arrowHeight / 2}px;` : "0;"};
59
92
  `;
60
93
  const StylePathShadow = styled("path", {
61
94
  name: DSFloatingWrapperName,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/PopoverArrow.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { useOwnerProps, useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport { styled } from '@elliemae/ds-system';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperSlots, DSFloatingWrapperName } from '../constants/index.js';\nexport interface PopoverArrowT\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n placement: string;\n style: React.CSSProperties;\n arrowElementRef?: React.Dispatch<React.SetStateAction<HTMLDivElement | null>>;\n}\nconst arrowWidth = 18;\nconst arrowHeight = 18;\n\nconst OFFSET_FIX_SHADOW_DEFECT = 0.25;\nconst StyledArrow = styled('div', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW,\n})<{ 'data-placement': string }>`\n position: absolute;\n width: ${arrowWidth}px;\n height: ${arrowHeight}px;\n pointer-events: none;\n background-color: transparent;\n & .stroke {\n fill: rgb(105, 116, 137);\n fill-opacity: 0.4;\n }\n & .fill {\n fill: rgb(255, 255, 255);\n }\n\n &[data-placement^='top'] {\n svg {\n transform: rotateZ(180deg);\n }\n bottom: -${arrowHeight - OFFSET_FIX_SHADOW_DEFECT}px;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='right'] {\n svg {\n transform: rotateZ(-90deg);\n }\n left: -${arrowWidth - OFFSET_FIX_SHADOW_DEFECT}px;\n }\n &[data-placement^='bottom'] {\n top: -${arrowHeight - OFFSET_FIX_SHADOW_DEFECT}px;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='left'] {\n svg {\n transform: rotateZ(90deg);\n }\n right: -${arrowWidth - OFFSET_FIX_SHADOW_DEFECT}px;\n }\n margin-left: ${(props) =>\n props['data-placement'].startsWith('top') || props['data-placement'].startsWith('bottom')\n ? `-${arrowWidth / 2}px;`\n : '0;'};\n margin-top: ${(props) =>\n props['data-placement'].startsWith('left') || props['data-placement'].startsWith('right')\n ? `-${arrowHeight / 2}px;`\n : '0;'};\n`;\n\nconst StylePathShadow = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_SHADOW,\n})``;\n\nconst StylePathFill = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_FILL,\n})``;\n\nexport const PopoverArrow = ({ placement, style, arrowElementRef, ...rest }: PopoverArrowT): React.ReactElement => {\n const ownerProps = useOwnerProps(rest);\n const globalAttributes = useGetGlobalAttributes(rest);\n const xstyledProps = useGetXstyledProps(rest);\n return (\n <StyledArrow\n key=\"popper-arrow\"\n data-placement={placement}\n style={style}\n innerRef={arrowElementRef}\n data-testid=\"ds-tooltip-arrow\"\n aria-hidden=\"true\"\n {...ownerProps}\n {...globalAttributes}\n {...xstyledProps}\n >\n <svg viewBox=\"0 0 30 30\">\n <StylePathShadow\n {...ownerProps}\n className=\"stroke\"\n d=\"M23.7,27.1L17,19.9C16.5,19.3,15.8,19,15,19s-1.6,0.3-2.1,0.9l-6.6,7.2C5.3,28.1,3.4,29,2,29h26\n C26.7,29,24.6,28.1,23.7,27.1z\"\n />\n <StylePathFill\n {...ownerProps}\n className=\"fill\"\n d=\"M23,27.8c1.1,1.2,3.4,2.2,5,2.2h2H0h2c1.7,0,3.9-1,5-2.2l6.6-7.2c0.7-0.8,2-0.8,2.7,0L23,27.8L23,27.8z\"\n />\n </svg>\n </StyledArrow>\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACmGjB,SACE,KADF;AAlGN,SAAS,eAAe,wBAAwB,0BAA0B;AAC1E,SAAS,cAAc;AAEvB,SAAS,wBAAwB,6BAA6B;AAO9D,MAAM,aAAa;AACnB,MAAM,cAAc;AAEpB,MAAM,2BAA2B;AACjC,MAAM,cAAc,OAAO,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM,uBAAuB;AAC/B,CAAC;AAAA;AAAA,WAEU,UAAU;AAAA,YACT,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAeR,cAAc,wBAAwB;AAAA,YACzC,CAAC,UAAU;AACjB,MAAI,MAAM,gBAAgB,EAAE,SAAS,OAAO,EAAG,QAAO;AACtD,MAAI,MAAM,gBAAgB,EAAE,SAAS,KAAK,EAAG,QAAO;AACpD,SAAO;AACT,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMQ,aAAa,wBAAwB;AAAA;AAAA;AAAA,YAGtC,cAAc,wBAAwB;AAAA,YACtC,CAAC,UAAU;AACjB,MAAI,MAAM,gBAAgB,EAAE,SAAS,OAAO,EAAG,QAAO;AACtD,MAAI,MAAM,gBAAgB,EAAE,SAAS,KAAK,EAAG,QAAO;AACpD,SAAO;AACT,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMS,aAAa,wBAAwB;AAAA;AAAA,iBAElC,CAAC,UACd,MAAM,gBAAgB,EAAE,WAAW,KAAK,KAAK,MAAM,gBAAgB,EAAE,WAAW,QAAQ,IACpF,IAAI,aAAa,CAAC,QAClB,IAAI;AAAA,gBACI,CAAC,UACb,MAAM,gBAAgB,EAAE,WAAW,MAAM,KAAK,MAAM,gBAAgB,EAAE,WAAW,OAAO,IACpF,IAAI,cAAc,CAAC,QACnB,IAAI;AAAA;AAGZ,MAAM,kBAAkB,OAAO,QAAQ;AAAA,EACrC,MAAM;AAAA,EACN,MAAM,uBAAuB;AAC/B,CAAC;AAED,MAAM,gBAAgB,OAAO,QAAQ;AAAA,EACnC,MAAM;AAAA,EACN,MAAM,uBAAuB;AAC/B,CAAC;AAEM,MAAM,eAAe,CAAC,EAAE,WAAW,OAAO,iBAAiB,GAAG,KAAK,MAAyC;AACjH,QAAM,aAAa,cAAc,IAAI;AACrC,QAAM,mBAAmB,uBAAuB,IAAI;AACpD,QAAM,eAAe,mBAAmB,IAAI;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MAEC,kBAAgB;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,MACV,eAAY;AAAA,MACZ,eAAY;AAAA,MACX,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MAEJ,+BAAC,SAAI,SAAQ,aACX;AAAA;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,WAAU;AAAA,YACV,GAAE;AAAA;AAAA,QAEJ;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,WAAU;AAAA,YACV,GAAE;AAAA;AAAA,QACJ;AAAA,SACF;AAAA;AAAA,IAtBI;AAAA,EAuBN;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { useOwnerProps, useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport { styled } from '@elliemae/ds-system';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperSlots, DSFloatingWrapperName } from '../constants/index.js';\nexport interface PopoverArrowT\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFloatingWrapperName, typeof DSFloatingWrapperSlots> {\n placement: string;\n style: React.CSSProperties;\n arrowElementRef?: React.Dispatch<React.SetStateAction<HTMLDivElement | null>>;\n}\nconst arrowWidth = 18;\nconst OFFSET_FIX_SHADOW_DEFECT = 0.25;\n\nconst arrowDimensionBase13 = arrowWidth / 13;\nconst OFFSET_FIX_SHADOW_DEFECT_BASE13 = OFFSET_FIX_SHADOW_DEFECT / 13;\nconst arrowDimensionBase16 = arrowWidth / 16;\nconst OFFSET_FIX_SHADOW_DEFECT_BASE16 = OFFSET_FIX_SHADOW_DEFECT / 16;\n\nconst arrowPlacementBase13 = arrowDimensionBase13 - OFFSET_FIX_SHADOW_DEFECT_BASE13;\nconst arrowPlacementBase16 = arrowDimensionBase16 - OFFSET_FIX_SHADOW_DEFECT_BASE16;\n\nconst isTopOrBottom = (placement: string) => placement.startsWith('top') || placement.startsWith('bottom');\n\nconst isLeftOrRight = (placement: string) => placement.startsWith('left') || placement.startsWith('right');\n\nconst StyledArrow = styled('div', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW,\n})<{ 'data-placement': string }>`\n line-height: 0;\n position: absolute;\n width: ${arrowDimensionBase16}rem;\n height: ${arrowDimensionBase16}rem;\n pointer-events: none;\n background-color: transparent;\n & .stroke {\n fill: rgb(105, 116, 137);\n fill-opacity: 0.4;\n }\n & .fill {\n fill: rgb(255, 255, 255);\n }\n\n &[data-placement^='top'] {\n svg {\n transform: rotateZ(180deg);\n }\n bottom: -${arrowPlacementBase16}rem;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='right'] {\n svg {\n transform: rotateZ(-90deg);\n }\n left: -${arrowPlacementBase16}rem;\n }\n &[data-placement^='bottom'] {\n top: -${arrowPlacementBase16}rem;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='left'] {\n svg {\n transform: rotateZ(90deg);\n }\n right: -${arrowPlacementBase16}rem;\n }\n margin-left: ${(props) => (isTopOrBottom(props['data-placement']) ? `-${arrowDimensionBase16 / 2}rem` : '0')};\n margin-top: ${(props) => (isLeftOrRight(props['data-placement']) ? `-${arrowDimensionBase16 / 2}rem` : '0')};\n\n @media (min-width: ${({ theme }) => theme.breakpoints.small}) {\n width: ${arrowDimensionBase13}rem;\n height: ${arrowDimensionBase13}rem;\n\n &[data-placement^='top'] {\n bottom: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='bottom'] {\n top: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='left'] {\n right: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='right'] {\n left: -${arrowPlacementBase13}rem;\n }\n\n margin-left: ${(props) => (isTopOrBottom(props['data-placement']) ? `-${arrowDimensionBase13 / 2}rem` : '0')};\n\n margin-top: ${(props) => (isLeftOrRight(props['data-placement']) ? `-${arrowDimensionBase13 / 2}rem` : '0')};\n }\n`;\n\nconst StylePathShadow = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_SHADOW,\n})``;\n\nconst StylePathFill = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_FILL,\n})``;\n\nexport const PopoverArrow = ({ placement, style, arrowElementRef, ...rest }: PopoverArrowT): React.ReactElement => {\n const ownerProps = useOwnerProps(rest);\n const globalAttributes = useGetGlobalAttributes(rest);\n const xstyledProps = useGetXstyledProps(rest);\n return (\n <StyledArrow\n key=\"popper-arrow\"\n data-placement={placement}\n style={style}\n innerRef={arrowElementRef}\n data-testid=\"ds-tooltip-arrow\"\n aria-hidden=\"true\"\n {...ownerProps}\n {...globalAttributes}\n {...xstyledProps}\n >\n <svg viewBox=\"0 0 30 30\">\n <StylePathShadow\n {...ownerProps}\n className=\"stroke\"\n d=\"M23.7,27.1L17,19.9C16.5,19.3,15.8,19,15,19s-1.6,0.3-2.1,0.9l-6.6,7.2C5.3,28.1,3.4,29,2,29h26\n C26.7,29,24.6,28.1,23.7,27.1z\"\n />\n <StylePathFill\n {...ownerProps}\n className=\"fill\"\n d=\"M23,27.8c1.1,1.2,3.4,2.2,5,2.2h2H0h2c1.7,0,3.9-1,5-2.2l6.6-7.2c0.7-0.8,2-0.8,2.7,0L23,27.8L23,27.8z\"\n />\n </svg>\n </StyledArrow>\n );\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,71 @@
1
+ import * as React from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import React2 from "react";
4
+ import { FloatingWrapper } from "../index.js";
5
+ const testOptionalProps = {};
6
+ const testPartialDefaults = {
7
+ withoutAnimation: false,
8
+ withoutPortal: false,
9
+ animationDuration: 300
10
+ };
11
+ const testCompleteDefaults = {
12
+ withoutAnimation: false,
13
+ withoutPortal: false,
14
+ animationDuration: 300,
15
+ placement: "top",
16
+ customOffset: [10, 10],
17
+ portalDOMContainer: document.body
18
+ };
19
+ const testInternalProps = {
20
+ ...testOptionalProps,
21
+ ...testCompleteDefaults
22
+ };
23
+ const testInternalPropsAsSyntax = {
24
+ ...testOptionalProps,
25
+ ...testCompleteDefaults
26
+ };
27
+ const testExplicitDefinition = {
28
+ animationDuration: 300,
29
+ withoutAnimation: false,
30
+ withoutPortal: false,
31
+ placement: "top",
32
+ customOffset: [10, 10],
33
+ portalDOMContainer: document.body,
34
+ ...testOptionalProps
35
+ };
36
+ const testInferedTypeCompatibility = {
37
+ ...testOptionalProps,
38
+ ...testPartialDefaults,
39
+ animationDuration: 300
40
+ };
41
+ const testDefinitionAsConst = {
42
+ animationDuration: 300,
43
+ withoutAnimation: false,
44
+ withoutPortal: false,
45
+ placement: "top",
46
+ portalDOMContainer: document.body
47
+ };
48
+ const ExampleUsageComponent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
49
+ /* @__PURE__ */ jsx(
50
+ FloatingWrapper,
51
+ {
52
+ ...testExplicitDefinition,
53
+ innerRef: React2.createRef(),
54
+ isOpen: true,
55
+ floatingStyles: {},
56
+ children: /* @__PURE__ */ jsx("div", { children: "Content" })
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx(
60
+ FloatingWrapper,
61
+ {
62
+ ...testInferedTypeCompatibility,
63
+ innerRef: React2.createRef(),
64
+ isOpen: true,
65
+ floatingStyles: {},
66
+ children: /* @__PURE__ */ jsx("div", { children: "Content" })
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx(FloatingWrapper, { ...testDefinitionAsConst, innerRef: React2.createRef(), isOpen: true, floatingStyles: {}, children: /* @__PURE__ */ jsx("div", { children: "Content" }) })
70
+ ] });
71
+ //# sourceMappingURL=typescript-floating-context-valid.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/typescript-testing/typescript-floating-context-valid.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport React from 'react';\nimport { FloatingWrapper } from '../index.js';\nimport type { DSHookFloatingContextT } from '../index.js';\n\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSHookFloatingContextT.Props;\ntype ComponentPropsInternals = DSHookFloatingContextT.InternalProps;\ntype ComponentPropsDefaultProps = DSHookFloatingContextT.DefaultProps;\ntype ComponentPropsOptionalProps = DSHookFloatingContextT.OptionalProps;\n\nconst testOptionalProps: ComponentPropsOptionalProps = {};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {\n withoutAnimation: false,\n withoutPortal: false,\n animationDuration: 300,\n};\n\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n withoutAnimation: false,\n withoutPortal: false,\n animationDuration: 300,\n placement: 'top',\n customOffset: [10, 10],\n portalDOMContainer: document.body,\n};\n\nconst testInternalProps: ComponentPropsInternals = {\n ...testOptionalProps,\n ...testCompleteDefaults,\n};\n\nconst testInternalPropsAsSyntax = {\n ...testOptionalProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n animationDuration: 300,\n withoutAnimation: false,\n withoutPortal: false,\n placement: 'top',\n customOffset: [10, 10],\n portalDOMContainer: document.body,\n ...testOptionalProps,\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferedTypeCompatibility = {\n ...testOptionalProps,\n ...testPartialDefaults,\n animationDuration: 300,\n} as ComponentPropsForApp;\n\nconst testDefinitionAsConst = {\n animationDuration: 300,\n withoutAnimation: false,\n withoutPortal: false,\n placement: 'top',\n portalDOMContainer: document.body,\n} as const;\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <FloatingWrapper\n {...testExplicitDefinition}\n innerRef={React.createRef<HTMLDivElement>()}\n isOpen\n floatingStyles={{}}\n >\n <div>Content</div>\n </FloatingWrapper>\n <FloatingWrapper\n {...testInferedTypeCompatibility}\n innerRef={React.createRef<HTMLDivElement>()}\n isOpen\n floatingStyles={{}}\n >\n <div>Content</div>\n </FloatingWrapper>\n <FloatingWrapper {...testDefinitionAsConst} innerRef={React.createRef<HTMLDivElement>()} isOpen floatingStyles={{}}>\n <div>Content</div>\n </FloatingWrapper>\n {/* works with inline values */}\n </>\n);\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACoErB,mBAQI,KARJ;AAnEF,OAAOA,YAAW;AAClB,SAAS,uBAAuB;AAShC,MAAM,oBAAiD,CAAC;AAIxD,MAAM,sBAA2D;AAAA,EAC/D,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,mBAAmB;AACrB;AAGA,MAAM,uBAA6D;AAAA,EACjE,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,WAAW;AAAA,EACX,cAAc,CAAC,IAAI,EAAE;AAAA,EACrB,oBAAoB,SAAS;AAC/B;AAEA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,WAAW;AAAA,EACX,cAAc,CAAC,IAAI,EAAE;AAAA,EACrB,oBAAoB,SAAS;AAAA,EAC7B,GAAG;AACL;AAGA,MAAM,+BAA+B;AAAA,EACnC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,mBAAmB;AACrB;AAEA,MAAM,wBAAwB;AAAA,EAC5B,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,WAAW;AAAA,EACX,oBAAoB,SAAS;AAC/B;AAEA,MAAM,wBAAwB,MAC5B,iCAEE;AAAA;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAUA,OAAM,UAA0B;AAAA,MAC1C,QAAM;AAAA,MACN,gBAAgB,CAAC;AAAA,MAEjB,8BAAC,SAAI,qBAAO;AAAA;AAAA,EACd;AAAA,EACA;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAUA,OAAM,UAA0B;AAAA,MAC1C,QAAM;AAAA,MACN,gBAAgB,CAAC;AAAA,MAEjB,8BAAC,SAAI,qBAAO;AAAA;AAAA,EACd;AAAA,EACA,oBAAC,mBAAiB,GAAG,uBAAuB,UAAUA,OAAM,UAA0B,GAAG,QAAM,MAAC,gBAAgB,CAAC,GAC/G,8BAAC,SAAI,qBAAO,GACd;AAAA,GAEF;",
6
+ "names": ["React"]
7
+ }
@@ -1,64 +1,85 @@
1
1
  import * as React from "react";
2
- import React2, { useState } from "react";
2
+ import { useLayoutEffect, useMemo, useRef, useState, useCallback } from "react";
3
3
  import { debounce } from "lodash-es";
4
4
  import { computePosition } from "./utils/computePosition.js";
5
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,
6
+ const {
39
7
  reference,
40
8
  floating,
41
9
  placement,
42
10
  placementOrderPreference,
43
11
  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({
12
+ withoutPortal,
13
+ preventComputing = false,
14
+ debounceMs = 150
15
+ } = config;
16
+ const [arrowStyles, setArrowStyles] = useState({ style: { left: 0 }, placement: "top" });
17
+ const [floatingStyles, setFloatingStyles] = useState({
18
+ position: "absolute",
19
+ zIndex: 3e3,
20
+ visibility: "hidden",
21
+ willChange: "transform"
22
+ });
23
+ const [hasComputedOnce, setHasComputedOnce] = useState(false);
24
+ const canCompute = reference !== null && floating !== null && !preventComputing;
25
+ const updateStyles = useCallback(() => {
26
+ if (!canCompute) return;
27
+ const { coordsStyle, finalPlacement, coordsArrow } = computePosition({
28
+ reference,
29
+ floating,
30
+ placement,
31
+ placementOrderPreference,
32
+ customOffset,
33
+ withoutPortal
34
+ });
35
+ setFloatingStyles((prev) => ({
51
36
  position: "absolute",
52
37
  zIndex: 3e3,
53
- top: 0,
54
- left: 0,
38
+ ...prev,
39
+ ...coordsStyle
40
+ }));
41
+ setArrowStyles({ style: coordsArrow, placement: finalPlacement });
42
+ setHasComputedOnce(true);
43
+ }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);
44
+ const mutableUpdateStyles = useRef(updateStyles);
45
+ mutableUpdateStyles.current = updateStyles;
46
+ const debouncedUpdateStyles = useMemo(() => {
47
+ const d = debounce(() => {
48
+ mutableUpdateStyles.current();
49
+ }, debounceMs);
50
+ return d;
51
+ }, [debounceMs]);
52
+ useLayoutEffect(
53
+ () => () => {
54
+ debouncedUpdateStyles.cancel();
55
+ },
56
+ [debouncedUpdateStyles]
57
+ );
58
+ useLayoutEffect(() => {
59
+ if (canCompute) {
60
+ mutableUpdateStyles.current();
61
+ }
62
+ }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);
63
+ const forceUpdatePosition = useCallback(() => {
64
+ mutableUpdateStyles.current();
65
+ }, []);
66
+ const resetVisibilityOnly = useCallback(() => {
67
+ setFloatingStyles((prev) => ({
68
+ ...prev,
55
69
  visibility: "hidden"
56
- });
57
- setArrowStyles({ style: { left: 0 }, placement: "top" });
70
+ }));
58
71
  }, []);
59
- return React2.useMemo(
60
- () => ({ arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, mutableUpdateStyles, resetStyles }),
61
- [arrowStyles, floatingStyles, updateStyles, debouncedUpdateStyles, resetStyles]
72
+ return useMemo(
73
+ () => ({
74
+ arrowStyles,
75
+ floatingStyles,
76
+ hasComputedOnce,
77
+ updateStyles: forceUpdatePosition,
78
+ debouncedUpdateStyles,
79
+ mutableUpdateStyles,
80
+ resetVisibilityOnly
81
+ }),
82
+ [arrowStyles, floatingStyles, hasComputedOnce, forceUpdatePosition, debouncedUpdateStyles, resetVisibilityOnly]
62
83
  );
63
84
  };
64
85
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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"]
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-statements */\nimport { useLayoutEffect, useMemo, useRef, useState, useCallback } 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 /** Prevent computing when closed (optimization + avoids unnecessary frames) */\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 /** Debounce ms for scroll/resize/observer events */\n debounceMs?: number;\n};\n\nexport const useComputedPositionStyles = (config: UseComputedPositionStylesT) => {\n const {\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n preventComputing = false,\n debounceMs = 150,\n } = config;\n\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({ style: { left: 0 }, placement: 'top' });\n\n // Important: do not initialize top/left to (0,0); keep hidden until the first computation\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n visibility: 'hidden',\n willChange: 'transform',\n });\n\n const [hasComputedOnce, setHasComputedOnce] = useState(false);\n\n const canCompute = reference !== null && floating !== null && !preventComputing;\n\n const updateStyles = useCallback(() => {\n if (!canCompute) return;\n\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n // Do not touch visibility here; it is managed outside depending on open/hasComputedOnce\n setFloatingStyles((prev) => ({\n position: 'absolute',\n zIndex: 3000,\n ...prev,\n ...coordsStyle,\n }));\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n setHasComputedOnce(true);\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n // Store latest update function in a ref to keep debounced stable\n const mutableUpdateStyles = useRef(updateStyles);\n mutableUpdateStyles.current = updateStyles;\n\n const debouncedUpdateStyles = useMemo(() => {\n const d = debounce(() => {\n mutableUpdateStyles.current();\n }, debounceMs);\n return d;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debounceMs]);\n\n // Clean up debounce on unmount\n useLayoutEffect(\n () => () => {\n debouncedUpdateStyles.cancel();\n },\n [debouncedUpdateStyles],\n );\n\n // Recalculate BEFORE paint when dependencies change\n useLayoutEffect(() => {\n if (canCompute) {\n mutableUpdateStyles.current();\n }\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n const forceUpdatePosition = useCallback(() => {\n mutableUpdateStyles.current();\n }, []);\n\n // Do not reset coordinates when closing; just hide\n const resetVisibilityOnly = useCallback(() => {\n setFloatingStyles((prev) => ({\n ...prev,\n visibility: 'hidden',\n }));\n }, []);\n\n return useMemo(\n () => ({\n arrowStyles,\n floatingStyles,\n hasComputedOnce,\n updateStyles: forceUpdatePosition,\n debouncedUpdateStyles,\n mutableUpdateStyles,\n resetVisibilityOnly,\n }),\n [arrowStyles, floatingStyles, hasComputedOnce, forceUpdatePosition, debouncedUpdateStyles, resetVisibilityOnly],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,iBAAiB,SAAS,QAAQ,UAAU,mBAAmB;AACxE,SAAS,gBAAgB;AAEzB,SAAS,uBAAuB;AAiBzB,MAAM,4BAA4B,CAAC,WAAuC;AAC/E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB,aAAa;AAAA,EACf,IAAI;AAEJ,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AAGtG,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,EACd,CAAC;AAED,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAE5D,QAAM,aAAa,cAAc,QAAQ,aAAa,QAAQ,CAAC;AAE/D,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,WAAY;AAEjB,UAAM,EAAE,aAAa,gBAAgB,YAAY,IAAI,gBAAgB;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,sBAAkB,CAAC,UAAU;AAAA,MAC3B,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE;AACF,mBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAChE,uBAAmB,IAAI;AAAA,EACzB,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAGtG,QAAM,sBAAsB,OAAO,YAAY;AAC/C,sBAAoB,UAAU;AAE9B,QAAM,wBAAwB,QAAQ,MAAM;AAC1C,UAAM,IAAI,SAAS,MAAM;AACvB,0BAAoB,QAAQ;AAAA,IAC9B,GAAG,UAAU;AACb,WAAO;AAAA,EAET,GAAG,CAAC,UAAU,CAAC;AAGf;AAAA,IACE,MAAM,MAAM;AACV,4BAAsB,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,qBAAqB;AAAA,EACxB;AAGA,kBAAgB,MAAM;AACpB,QAAI,YAAY;AACd,0BAAoB,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAEtG,QAAM,sBAAsB,YAAY,MAAM;AAC5C,wBAAoB,QAAQ;AAAA,EAC9B,GAAG,CAAC,CAAC;AAGL,QAAM,sBAAsB,YAAY,MAAM;AAC5C,sBAAkB,CAAC,UAAU;AAAA,MAC3B,GAAG;AAAA,MACH,YAAY;AAAA,IACd,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,aAAa,gBAAgB,iBAAiB,qBAAqB,uBAAuB,mBAAmB;AAAA,EAChH;AACF;",
6
+ "names": []
7
7
  }
@@ -27,6 +27,7 @@ const adjustForFixedParent = (child) => {
27
27
  };
28
28
  const computePosition = (props) => {
29
29
  const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal } = props;
30
+ const scrollBarY = window.innerHeight - document.documentElement.clientHeight;
30
31
  const parentOffsets = withoutPortal ? adjustForFixedParent(reference) : {
31
32
  top: 0,
32
33
  left: 0
@@ -57,7 +58,7 @@ const computePosition = (props) => {
57
58
  if (checks.every((check) => {
58
59
  return check;
59
60
  })) {
60
- coords.top = -overflows.top + window.scrollY - parentOffsets.top;
61
+ coords.top = -overflows.top + window.scrollY - parentOffsets.top + scrollBarY;
61
62
  coords.left = -overflows.left + window.scrollX - parentOffsets.left;
62
63
  finalPlacement = currentPlacement;
63
64
  break;
@@ -71,13 +72,9 @@ const computePosition = (props) => {
71
72
  }
72
73
  return {
73
74
  coordsStyle: {
74
- left: 0,
75
+ transform: `translate3d(${Math.round(coords.left ?? 0)}px, ${Math.round(coords.top ?? 0)}px, 0)`,
75
76
  top: 0,
76
- // we use transform -> translate because we know final computed left/top probably "split a pixel" (e.g. 10.005px)
77
- // when we use transform we force the browser to use hardware acceleration
78
- // hardware acceleration is faster and more reliable than the browser's own rounding
79
- // it also helps with css animations and so on
80
- transform: `translate(${coords.left}px, ${coords.top}px)`
77
+ left: 0
81
78
  },
82
79
  finalPlacement,
83
80
  coordsArrow: getArrowOffset(finalPlacement, isVertical)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/utils/computePosition.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-nested-ternary */\n/* eslint-disable complexity */\n/* eslint-disable max-statements */\n/* eslint-disable @typescript-eslint/no-use-before-define */\n/* eslint-disable max-params */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable arrow-body-style */\nimport type { DSHookFloatingContextT } from '../react-desc-prop-types.js';\nimport { getExpandedFallbackPlacements } from './getExpandedFallbackPlacements.js';\nimport { getArrowOffset } from './getArrowOffset.js';\nimport getOppositePlacement from './getOppositePlacement.js';\nimport { detectOverflow } from './detectOverflow.js';\n\ninterface ComputePositionProps {\n reference: Element;\n floating: HTMLElement;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n}\n\nconst findFixedParent = (el: Element | null) => {\n let element = el;\n while (element && element !== document.body) {\n const style = getComputedStyle(element);\n if (style.position === 'fixed' || style.position === 'absolute') {\n return element;\n }\n element = element.parentElement;\n }\n return null;\n};\n\nconst adjustForFixedParent = (child: Element) => {\n const fixedParent = findFixedParent(child);\n if (fixedParent) {\n const rect = fixedParent.getBoundingClientRect();\n return { top: rect.top, left: rect.left };\n }\n return {\n top: 0,\n left: 0,\n };\n};\n\nexport const computePosition = (props: ComputePositionProps) => {\n const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal } = props;\n\n const parentOffsets = withoutPortal\n ? adjustForFixedParent(reference)\n : {\n top: 0,\n left: 0,\n };\n const referenceRect = reference.getBoundingClientRect();\n const floatingRect = floating.getBoundingClientRect();\n\n const variationPlacement = placement.split('-')[1];\n const fallbackPlacements = placementOrderPreference || getExpandedFallbackPlacements(placement);\n\n const coords: { top?: number; left?: number; bottom?: number; right?: number } = {};\n\n let isVertical = false;\n const placements = [placement].concat(fallbackPlacements as DSHookFloatingContextT.PopperPlacementsT[]);\n let finalPlacement = '';\n\n for (let i = 0; i < placements.length; i += 1) {\n const currentPlacement = placements[i];\n\n const currentBasePlacement = currentPlacement.split('-')[0] as keyof typeof coords;\n isVertical = ['top', 'bottom'].indexOf(currentBasePlacement) >= 0;\n\n const overflows = detectOverflow(referenceRect, floatingRect, currentPlacement, customOffset);\n\n const checks: boolean[] = [];\n\n const isStartVariation = variationPlacement === 'start';\n\n let mainVariationSide: keyof typeof coords = isVertical\n ? isStartVariation\n ? 'right'\n : 'left'\n : isStartVariation\n ? 'bottom'\n : 'top';\n\n const len = isVertical ? 'width' : 'height';\n\n if (referenceRect[len] > floatingRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide) as keyof typeof coords;\n }\n\n const altVariationSide = getOppositePlacement(mainVariationSide) as keyof typeof coords;\n\n checks.push(overflows[currentBasePlacement] <= 0);\n checks.push(overflows[mainVariationSide] <= 0, overflows[altVariationSide] <= 0);\n\n if (\n checks.every((check) => {\n return check;\n })\n ) {\n coords.top = -overflows.top + window.scrollY - parentOffsets.top;\n coords.left = -overflows.left + window.scrollX - parentOffsets.left;\n finalPlacement = currentPlacement;\n\n break;\n }\n }\n\n if (!finalPlacement) {\n // if we don't find a placement that fits, we use the original one\n finalPlacement = placement;\n const overflows = detectOverflow(referenceRect, floatingRect, placement, customOffset);\n coords.top = -overflows.top + window.scrollY - parentOffsets.top;\n coords.left = -overflows.left + window.scrollX - parentOffsets.left;\n }\n\n return {\n coordsStyle: {\n left: 0,\n top: 0,\n // we use transform -> translate because we know final computed left/top probably \"split a pixel\" (e.g. 10.005px)\n // when we use transform we force the browser to use hardware acceleration\n // hardware acceleration is faster and more reliable than the browser's own rounding\n // it also helps with css animations and so on\n transform: `translate(${coords.left}px, ${coords.top}px)`,\n },\n finalPlacement,\n coordsArrow: getArrowOffset(finalPlacement, isVertical),\n };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-nested-ternary */\n/* eslint-disable complexity */\n/* eslint-disable max-statements */\n/* eslint-disable @typescript-eslint/no-use-before-define */\n/* eslint-disable max-params */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable arrow-body-style */\nimport type { DSHookFloatingContextT } from '../react-desc-prop-types.js';\nimport { getExpandedFallbackPlacements } from './getExpandedFallbackPlacements.js';\nimport { getArrowOffset } from './getArrowOffset.js';\nimport getOppositePlacement from './getOppositePlacement.js';\nimport { detectOverflow } from './detectOverflow.js';\n\ninterface ComputePositionProps {\n reference: Element;\n floating: HTMLElement;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n}\n\nconst findFixedParent = (el: Element | null) => {\n let element = el;\n while (element && element !== document.body) {\n const style = getComputedStyle(element);\n if (style.position === 'fixed' || style.position === 'absolute') {\n return element;\n }\n element = element.parentElement;\n }\n return null;\n};\n\nconst adjustForFixedParent = (child: Element) => {\n const fixedParent = findFixedParent(child);\n if (fixedParent) {\n const rect = fixedParent.getBoundingClientRect();\n return { top: rect.top, left: rect.left };\n }\n return {\n top: 0,\n left: 0,\n };\n};\n\nexport const computePosition = (props: ComputePositionProps) => {\n const { reference, floating, placement, placementOrderPreference, customOffset, withoutPortal } = props;\n\n const scrollBarY = window.innerHeight - document.documentElement.clientHeight;\n\n const parentOffsets = withoutPortal\n ? adjustForFixedParent(reference)\n : {\n top: 0,\n left: 0,\n };\n const referenceRect = reference.getBoundingClientRect();\n const floatingRect = floating.getBoundingClientRect();\n\n const variationPlacement = placement.split('-')[1];\n const fallbackPlacements = placementOrderPreference || getExpandedFallbackPlacements(placement);\n\n const coords: { top?: number; left?: number; bottom?: number; right?: number } = {};\n\n let isVertical = false;\n const placements = [placement].concat(fallbackPlacements as DSHookFloatingContextT.PopperPlacementsT[]);\n let finalPlacement = '';\n\n for (let i = 0; i < placements.length; i += 1) {\n const currentPlacement = placements[i];\n\n const currentBasePlacement = currentPlacement.split('-')[0] as keyof typeof coords;\n isVertical = ['top', 'bottom'].indexOf(currentBasePlacement) >= 0;\n\n const overflows = detectOverflow(referenceRect, floatingRect, currentPlacement, customOffset);\n\n const checks: boolean[] = [];\n\n const isStartVariation = variationPlacement === 'start';\n\n let mainVariationSide: keyof typeof coords = isVertical\n ? isStartVariation\n ? 'right'\n : 'left'\n : isStartVariation\n ? 'bottom'\n : 'top';\n\n const len = isVertical ? 'width' : 'height';\n\n if (referenceRect[len] > floatingRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide) as keyof typeof coords;\n }\n\n const altVariationSide = getOppositePlacement(mainVariationSide) as keyof typeof coords;\n\n checks.push(overflows[currentBasePlacement] <= 0);\n checks.push(overflows[mainVariationSide] <= 0, overflows[altVariationSide] <= 0);\n if (\n checks.every((check) => {\n return check;\n })\n ) {\n coords.top = -overflows.top + window.scrollY - parentOffsets.top + scrollBarY;\n coords.left = -overflows.left + window.scrollX - parentOffsets.left;\n finalPlacement = currentPlacement;\n\n break;\n }\n }\n\n if (!finalPlacement) {\n // if we don't find a placement that fits, we use the original one\n finalPlacement = placement;\n const overflows = detectOverflow(referenceRect, floatingRect, placement, customOffset);\n coords.top = -overflows.top + window.scrollY - parentOffsets.top;\n coords.left = -overflows.left + window.scrollX - parentOffsets.left;\n }\n\n return {\n coordsStyle: {\n transform: `translate3d(${Math.round(coords.left ?? 0)}px, ${Math.round(coords.top ?? 0)}px, 0)`,\n top: 0,\n left: 0,\n },\n finalPlacement,\n coordsArrow: getArrowOffset(finalPlacement, isVertical),\n };\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACQvB,SAAS,qCAAqC;AAC9C,SAAS,sBAAsB;AAC/B,OAAO,0BAA0B;AACjC,SAAS,sBAAsB;AAW/B,MAAM,kBAAkB,CAAC,OAAuB;AAC9C,MAAI,UAAU;AACd,SAAO,WAAW,YAAY,SAAS,MAAM;AAC3C,UAAM,QAAQ,iBAAiB,OAAO;AACtC,QAAI,MAAM,aAAa,WAAW,MAAM,aAAa,YAAY;AAC/D,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AACT;AAEA,MAAM,uBAAuB,CAAC,UAAmB;AAC/C,QAAM,cAAc,gBAAgB,KAAK;AACzC,MAAI,aAAa;AACf,UAAM,OAAO,YAAY,sBAAsB;AAC/C,WAAO,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK;AAAA,EAC1C;AACA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAEO,MAAM,kBAAkB,CAAC,UAAgC;AAC9D,QAAM,EAAE,WAAW,UAAU,WAAW,0BAA0B,cAAc,cAAc,IAAI;AAElG,QAAM,aAAa,OAAO,cAAc,SAAS,gBAAgB;AAEjE,QAAM,gBAAgB,gBAClB,qBAAqB,SAAS,IAC9B;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACJ,QAAM,gBAAgB,UAAU,sBAAsB;AACtD,QAAM,eAAe,SAAS,sBAAsB;AAEpD,QAAM,qBAAqB,UAAU,MAAM,GAAG,EAAE,CAAC;AACjD,QAAM,qBAAqB,4BAA4B,8BAA8B,SAAS;AAE9F,QAAM,SAA2E,CAAC;AAElF,MAAI,aAAa;AACjB,QAAM,aAAa,CAAC,SAAS,EAAE,OAAO,kBAAgE;AACtG,MAAI,iBAAiB;AAErB,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;AAC7C,UAAM,mBAAmB,WAAW,CAAC;AAErC,UAAM,uBAAuB,iBAAiB,MAAM,GAAG,EAAE,CAAC;AAC1D,iBAAa,CAAC,OAAO,QAAQ,EAAE,QAAQ,oBAAoB,KAAK;AAEhE,UAAM,YAAY,eAAe,eAAe,cAAc,kBAAkB,YAAY;AAE5F,UAAM,SAAoB,CAAC;AAE3B,UAAM,mBAAmB,uBAAuB;AAEhD,QAAI,oBAAyC,aACzC,mBACE,UACA,SACF,mBACE,WACA;AAEN,UAAM,MAAM,aAAa,UAAU;AAEnC,QAAI,cAAc,GAAG,IAAI,aAAa,GAAG,GAAG;AAC1C,0BAAoB,qBAAqB,iBAAiB;AAAA,IAC5D;AAEA,UAAM,mBAAmB,qBAAqB,iBAAiB;AAE/D,WAAO,KAAK,UAAU,oBAAoB,KAAK,CAAC;AAChD,WAAO,KAAK,UAAU,iBAAiB,KAAK,GAAG,UAAU,gBAAgB,KAAK,CAAC;AAC/E,QACE,OAAO,MAAM,CAAC,UAAU;AACtB,aAAO;AAAA,IACT,CAAC,GACD;AACA,aAAO,MAAM,CAAC,UAAU,MAAM,OAAO,UAAU,cAAc,MAAM;AACnE,aAAO,OAAO,CAAC,UAAU,OAAO,OAAO,UAAU,cAAc;AAC/D,uBAAiB;AAEjB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AAEnB,qBAAiB;AACjB,UAAM,YAAY,eAAe,eAAe,cAAc,WAAW,YAAY;AACrF,WAAO,MAAM,CAAC,UAAU,MAAM,OAAO,UAAU,cAAc;AAC7D,WAAO,OAAO,CAAC,UAAU,OAAO,OAAO,UAAU,cAAc;AAAA,EACjE;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,MACX,WAAW,eAAe,KAAK,MAAM,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK,MAAM,OAAO,OAAO,CAAC,CAAC;AAAA,MACxF,KAAK;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IACA;AAAA,IACA,aAAa,eAAe,gBAAgB,UAAU;AAAA,EACxD;AACF;",
6
6
  "names": []
7
7
  }
@@ -21,11 +21,13 @@ function domRectToObject(rect) {
21
21
  const detectOverflow = (referenceRect, floatingRect, placement, customOffset) => {
22
22
  const basePlacement = placement.split("-")[0];
23
23
  const isVertical = ["top", "bottom"].indexOf(basePlacement) >= 0;
24
+ const scrollBarX = window.innerWidth - document.documentElement.clientWidth;
25
+ const scrollBarY = window.innerHeight - document.documentElement.clientHeight;
24
26
  const clippingClientRect = {
25
27
  top: 0,
26
- right: document.documentElement.clientWidth,
27
- bottom: document.documentElement.clientHeight,
28
- left: 0
28
+ left: 0,
29
+ right: document.documentElement.clientWidth + scrollBarX,
30
+ bottom: document.documentElement.clientHeight + scrollBarY
29
31
  };
30
32
  const popperOffsets = computeOffsets(placement, referenceRect, floatingRect);
31
33
  const popperClientRect = rectToClientRect({ ...domRectToObject(floatingRect), ...popperOffsets });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/utils/detectOverflow.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-nested-ternary */\n/* eslint-disable max-params */\nimport { type DSHookFloatingContextT } from '../react-desc-prop-types.js';\nimport computeOffsets from './computeOffsets.js';\n\nconst paddingObject = { top: 0, right: 0, bottom: 0, left: 0 };\n\nfunction rectToClientRect(rect: DOMRect) {\n return { ...rect, left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height };\n}\n\nfunction domRectToObject(rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n top: number;\n right: number;\n bottom: number;\n left: number;\n}): DOMRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n toJSON: () => {},\n };\n}\n\nexport const detectOverflow = (\n referenceRect: DOMRect,\n floatingRect: DOMRect,\n placement: DSHookFloatingContextT.PopperPlacementsT,\n customOffset: [number, number],\n) => {\n const basePlacement = placement.split('-')[0];\n const isVertical = ['top', 'bottom'].indexOf(basePlacement) >= 0;\n const clippingClientRect = {\n top: 0,\n right: document.documentElement.clientWidth,\n bottom: document.documentElement.clientHeight,\n left: 0,\n };\n const popperOffsets = computeOffsets(placement, referenceRect, floatingRect);\n const popperClientRect = rectToClientRect({ ...domRectToObject(floatingRect), ...popperOffsets });\n\n const overflowOffsets = {\n top: clippingClientRect.top - popperClientRect.top + paddingObject.top,\n bottom: popperClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - popperClientRect.left + paddingObject.left,\n right: popperClientRect.right - clippingClientRect.right + paddingObject.right,\n };\n\n const offset = {\n x: basePlacement === 'left' ? -(customOffset?.[0] ?? 12) : customOffset?.[0] ?? 12,\n y: basePlacement === 'top' ? -(customOffset?.[1] ?? -12) : customOffset?.[1] ?? 12,\n };\n\n // if vertical switch x for y and vice versa\n if (!isVertical) {\n const temp = offset.x;\n offset.x = offset.y * (basePlacement === 'right' ? 1 : -1);\n offset.y = temp;\n }\n\n Object.keys(overflowOffsets).forEach((key) => {\n const multiply = ['right', 'bottom'].indexOf(key) >= 0 ? 1 : -1;\n const axis = ['top', 'bottom'].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key as keyof typeof overflowOffsets] += offset[axis] * multiply;\n });\n return overflowOffsets;\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAO,oBAAoB;AAE3B,MAAM,gBAAgB,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE;AAE7D,SAAS,iBAAiB,MAAe;AACvC,SAAO,EAAE,GAAG,MAAM,MAAM,KAAK,GAAG,KAAK,KAAK,GAAG,OAAO,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,IAAI,KAAK,OAAO;AACxG;AAEA,SAAS,gBAAgB,MASb;AACV,SAAO;AAAA,IACL,GAAG,KAAK;AAAA,IACR,GAAG,KAAK;AAAA,IACR,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,QAAQ,MAAM;AAAA,IAAC;AAAA,EACjB;AACF;AAEO,MAAM,iBAAiB,CAC5B,eACA,cACA,WACA,iBACG;AACH,QAAM,gBAAgB,UAAU,MAAM,GAAG,EAAE,CAAC;AAC5C,QAAM,aAAa,CAAC,OAAO,QAAQ,EAAE,QAAQ,aAAa,KAAK;AAC/D,QAAM,qBAAqB;AAAA,IACzB,KAAK;AAAA,IACL,OAAO,SAAS,gBAAgB;AAAA,IAChC,QAAQ,SAAS,gBAAgB;AAAA,IACjC,MAAM;AAAA,EACR;AACA,QAAM,gBAAgB,eAAe,WAAW,eAAe,YAAY;AAC3E,QAAM,mBAAmB,iBAAiB,EAAE,GAAG,gBAAgB,YAAY,GAAG,GAAG,cAAc,CAAC;AAEhG,QAAM,kBAAkB;AAAA,IACtB,KAAK,mBAAmB,MAAM,iBAAiB,MAAM,cAAc;AAAA,IACnE,QAAQ,iBAAiB,SAAS,mBAAmB,SAAS,cAAc;AAAA,IAC5E,MAAM,mBAAmB,OAAO,iBAAiB,OAAO,cAAc;AAAA,IACtE,OAAO,iBAAiB,QAAQ,mBAAmB,QAAQ,cAAc;AAAA,EAC3E;AAEA,QAAM,SAAS;AAAA,IACb,GAAG,kBAAkB,SAAS,EAAE,eAAe,CAAC,KAAK,MAAM,eAAe,CAAC,KAAK;AAAA,IAChF,GAAG,kBAAkB,QAAQ,EAAE,eAAe,CAAC,KAAK,OAAO,eAAe,CAAC,KAAK;AAAA,EAClF;AAGA,MAAI,CAAC,YAAY;AACf,UAAM,OAAO,OAAO;AACpB,WAAO,IAAI,OAAO,KAAK,kBAAkB,UAAU,IAAI;AACvD,WAAO,IAAI;AAAA,EACb;AAEA,SAAO,KAAK,eAAe,EAAE,QAAQ,CAAC,QAAQ;AAC5C,UAAM,WAAW,CAAC,SAAS,QAAQ,EAAE,QAAQ,GAAG,KAAK,IAAI,IAAI;AAC7D,UAAM,OAAO,CAAC,OAAO,QAAQ,EAAE,QAAQ,GAAG,KAAK,IAAI,MAAM;AACzD,oBAAgB,GAAmC,KAAK,OAAO,IAAI,IAAI;AAAA,EACzE,CAAC;AACD,SAAO;AACT;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-nested-ternary */\n/* eslint-disable max-params */\nimport { type DSHookFloatingContextT } from '../react-desc-prop-types.js';\nimport computeOffsets from './computeOffsets.js';\n\nconst paddingObject = { top: 0, right: 0, bottom: 0, left: 0 };\n\nfunction rectToClientRect(rect: DOMRect) {\n return { ...rect, left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height };\n}\n\nfunction domRectToObject(rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n top: number;\n right: number;\n bottom: number;\n left: number;\n}): DOMRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n toJSON: () => {},\n };\n}\n\nexport const detectOverflow = (\n referenceRect: DOMRect,\n floatingRect: DOMRect,\n placement: DSHookFloatingContextT.PopperPlacementsT,\n customOffset: [number, number],\n) => {\n const basePlacement = placement.split('-')[0];\n const isVertical = ['top', 'bottom'].indexOf(basePlacement) >= 0;\n\n const scrollBarX = window.innerWidth - document.documentElement.clientWidth;\n const scrollBarY = window.innerHeight - document.documentElement.clientHeight;\n\n const clippingClientRect = {\n top: 0,\n left: 0,\n right: document.documentElement.clientWidth + scrollBarX,\n bottom: document.documentElement.clientHeight + scrollBarY,\n };\n\n const popperOffsets = computeOffsets(placement, referenceRect, floatingRect);\n const popperClientRect = rectToClientRect({ ...domRectToObject(floatingRect), ...popperOffsets });\n\n const overflowOffsets = {\n top: clippingClientRect.top - popperClientRect.top + paddingObject.top,\n bottom: popperClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - popperClientRect.left + paddingObject.left,\n right: popperClientRect.right - clippingClientRect.right + paddingObject.right,\n };\n\n const offset = {\n x: basePlacement === 'left' ? -(customOffset?.[0] ?? 12) : (customOffset?.[0] ?? 12),\n y: basePlacement === 'top' ? -(customOffset?.[1] ?? -12) : (customOffset?.[1] ?? 12),\n };\n\n // if vertical switch x for y and vice versa\n if (!isVertical) {\n const temp = offset.x;\n offset.x = offset.y * (basePlacement === 'right' ? 1 : -1);\n offset.y = temp;\n }\n\n Object.keys(overflowOffsets).forEach((key) => {\n const multiply = ['right', 'bottom'].indexOf(key) >= 0 ? 1 : -1;\n const axis = ['top', 'bottom'].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key as keyof typeof overflowOffsets] += offset[axis] * multiply;\n });\n return overflowOffsets;\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAO,oBAAoB;AAE3B,MAAM,gBAAgB,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE;AAE7D,SAAS,iBAAiB,MAAe;AACvC,SAAO,EAAE,GAAG,MAAM,MAAM,KAAK,GAAG,KAAK,KAAK,GAAG,OAAO,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,IAAI,KAAK,OAAO;AACxG;AAEA,SAAS,gBAAgB,MASb;AACV,SAAO;AAAA,IACL,GAAG,KAAK;AAAA,IACR,GAAG,KAAK;AAAA,IACR,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,QAAQ,MAAM;AAAA,IAAC;AAAA,EACjB;AACF;AAEO,MAAM,iBAAiB,CAC5B,eACA,cACA,WACA,iBACG;AACH,QAAM,gBAAgB,UAAU,MAAM,GAAG,EAAE,CAAC;AAC5C,QAAM,aAAa,CAAC,OAAO,QAAQ,EAAE,QAAQ,aAAa,KAAK;AAE/D,QAAM,aAAa,OAAO,aAAa,SAAS,gBAAgB;AAChE,QAAM,aAAa,OAAO,cAAc,SAAS,gBAAgB;AAEjE,QAAM,qBAAqB;AAAA,IACzB,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO,SAAS,gBAAgB,cAAc;AAAA,IAC9C,QAAQ,SAAS,gBAAgB,eAAe;AAAA,EAClD;AAEA,QAAM,gBAAgB,eAAe,WAAW,eAAe,YAAY;AAC3E,QAAM,mBAAmB,iBAAiB,EAAE,GAAG,gBAAgB,YAAY,GAAG,GAAG,cAAc,CAAC;AAEhG,QAAM,kBAAkB;AAAA,IACtB,KAAK,mBAAmB,MAAM,iBAAiB,MAAM,cAAc;AAAA,IACnE,QAAQ,iBAAiB,SAAS,mBAAmB,SAAS,cAAc;AAAA,IAC5E,MAAM,mBAAmB,OAAO,iBAAiB,OAAO,cAAc;AAAA,IACtE,OAAO,iBAAiB,QAAQ,mBAAmB,QAAQ,cAAc;AAAA,EAC3E;AAEA,QAAM,SAAS;AAAA,IACb,GAAG,kBAAkB,SAAS,EAAE,eAAe,CAAC,KAAK,MAAO,eAAe,CAAC,KAAK;AAAA,IACjF,GAAG,kBAAkB,QAAQ,EAAE,eAAe,CAAC,KAAK,OAAQ,eAAe,CAAC,KAAK;AAAA,EACnF;AAGA,MAAI,CAAC,YAAY;AACf,UAAM,OAAO,OAAO;AACpB,WAAO,IAAI,OAAO,KAAK,kBAAkB,UAAU,IAAI;AACvD,WAAO,IAAI;AAAA,EACb;AAEA,SAAO,KAAK,eAAe,EAAE,QAAQ,CAAC,QAAQ;AAC5C,UAAM,WAAW,CAAC,SAAS,QAAQ,EAAE,QAAQ,GAAG,KAAK,IAAI,IAAI;AAC7D,UAAM,OAAO,CAAC,OAAO,QAAQ,EAAE,QAAQ,GAAG,KAAK,IAAI,MAAM;AACzD,oBAAgB,GAAmC,KAAK,OAAO,IAAI,IAAI;AAAA,EACzE,CAAC;AACD,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -3,12 +3,12 @@ import type { DSHookFloatingContextT } from './react-desc-prop-types.js';
3
3
  declare const useFloatingContext: {
4
4
  (props?: DSHookFloatingContextT.Props): {
5
5
  refs: {
6
- setReference: (node: HTMLElement | null) => void;
6
+ setReference: React.Dispatch<React.SetStateAction<Element | null>>;
7
7
  setFloating: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
8
8
  floating: HTMLElement | null;
9
9
  reference: Element | null;
10
10
  };
11
- floatingStyles: import("styled-components").CSSProperties;
11
+ floatingStyles: React.CSSProperties;
12
12
  handlers: {
13
13
  onMouseEnter: () => void;
14
14
  onMouseLeave: () => void;
@@ -26,6 +26,7 @@ declare const useFloatingContext: {
26
26
  animationDuration: number;
27
27
  };
28
28
  mutableUpdateStyles: React.MutableRefObject<() => void>;
29
+ forceUpdatePosition: () => void;
29
30
  };
30
31
  displayName: string;
31
32
  };
@@ -9,4 +9,7 @@ export declare const DSFloatingWrapperSlots: {
9
9
  export declare const DSFloatingWrapperDataTestids: {
10
10
  ROOT: string;
11
11
  ARROW: string;
12
+ CONTENT: `ds-floatingwrapper-${string}`;
13
+ ARROW_SHADOW: `ds-floatingwrapper-${string}`;
14
+ ARROW_FILL: `ds-floatingwrapper-${string}`;
12
15
  };