@vuu-ui/vuu-popups 0.8.74 → 0.8.75

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var tooltipCss = ".vuuTooltip {\n --tooltip-align: flex-start;\n --tooltip-background: var(--salt-actionable-primary-background-hover);\n --tooltip-border: var(--salt-actionable-primary-background-hover);\n --tooltip-color: var(--salt-actionable-primary-foreground-hover);\n --tooltip-justify: flex-start;\n --tooltip-top: auto;\n --tooltip-right: auto;\n --tooltip-bottom: auto;\n --tooltip-left: auto;\n align-items: var(--tooltip-align);\n justify-content: var(--tooltip-justify);\n display: flex;\n position: absolute;\n transition: opacity .15s ease-in;\n z-index: 100;\n\n\n &.vuuHidden {\n opacity: 0;\n }\n }\n \n .vuuTooltip-content {\n background-color: var(--tooltip-background);\n border-color: var(--tooltip-border);\n border-width: 1px;\n border-style: solid;\n border-radius: var(--vuuTooltip-borderRadius, 6px);\n box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);\n color: var(--tooltip-color);\n line-height: 24px;\n padding: 2px 8px;\n white-space: nowrap;\n }\n \n .vuuTooltip::before {\n background-color: var(--tooltip-border);\n content: ' ';\n display: block;\n position: absolute;\n transform: rotate(45deg);\n width: 12px;\n height: 12px;\n z-index: -1;\n}\n\n.vuuTooltip[data-align='above']::before {\n bottom: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align='below']::before {\n top: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align='right']::before {\n}\n\n.vuuTooltip[data-align='left']::before {\n}\n\n.vuuTooltip-error {\n --tooltip-background: var(--vuu-color-red-50);\n --tooltip-color: white;\n color: white;\n}";
3
+ var tooltipCss = ".vuuTooltip {\n --tooltip-align: flex-start;\n --tooltip-background: var(--salt-actionable-primary-background-hover);\n --tooltip-border: var(--salt-actionable-primary-background-hover);\n --tooltip-color: var(--salt-actionable-primary-foreground-hover);\n --tooltip-justify: flex-start;\n --tooltip-top: auto;\n --tooltip-right: auto;\n --tooltip-bottom: auto;\n --tooltip-left: auto;\n align-items: var(--tooltip-align);\n justify-content: var(--tooltip-justify);\n display: flex;\n position: absolute;\n transition: opacity 0.15s ease-in;\n z-index: 100;\n\n &.vuuHidden {\n opacity: 0;\n }\n}\n\n.vuuTooltip-content {\n background-color: var(--tooltip-background);\n border-color: var(--tooltip-border);\n border-width: 1px;\n border-style: solid;\n border-radius: var(--vuuTooltip-borderRadius, 6px);\n box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);\n color: var(--tooltip-color);\n line-height: 24px;\n padding: 2px 8px;\n white-space: nowrap;\n}\n\n.vuuTooltip::before {\n background-color: var(--tooltip-border);\n content: \" \";\n display: block;\n position: absolute;\n transform: rotate(45deg);\n width: 12px;\n height: 12px;\n z-index: -1;\n}\n\n.vuuTooltip[data-align=\"above\"]:before {\n bottom: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"below\"]:before {\n top: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"right\"]:before {\n left: -6px;\n top: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"left\"]:before {\n right: -6px;\n top: calc(50% - 6px);\n}\n\n.vuuTooltip-error {\n --tooltip-background: var(--vuu-color-red-50);\n --tooltip-color: white;\n color: white;\n}\n";
4
4
 
5
5
  module.exports = tooltipCss;
6
6
  //# sourceMappingURL=Tooltip.css.js.map
@@ -2,7 +2,7 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var Portal = require('../portal/Portal.js');
5
- var useAnchoredPosition = require('./useAnchoredPosition.js');
5
+ var useTooltipAnchoredPosition = require('./useTooltipAnchoredPosition.js');
6
6
  var cx = require('clsx');
7
7
  var styles = require('@salt-ds/styles');
8
8
  var window = require('@salt-ds/window');
@@ -26,7 +26,7 @@ const Tooltip = ({
26
26
  css: Tooltip$1,
27
27
  window: targetWindow
28
28
  });
29
- const ref = useAnchoredPosition.useAnchoredPosition({
29
+ const ref = useTooltipAnchoredPosition.useTooltipAnchoredPosition({
30
30
  anchorElement,
31
31
  placement: placementProp
32
32
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from \"react\";\nimport { Portal } from \"../portal\";\nimport { TooltipPlacement, useAnchoredPosition } from \"./useAnchoredPosition\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport tooltipCss from \"./Tooltip.css\";\n\nconst classBase = \"vuuTooltip\";\n\nexport type TooltipStatus = \"warning\" | \"error\" | \"info\";\nexport interface TooltipProps {\n anchorElement: RefObject<HTMLElement>;\n children: ReactNode;\n className?: string;\n id?: string;\n onMouseEnter: MouseEventHandler;\n onMouseLeave: MouseEventHandler;\n placement: TooltipPlacement | TooltipPlacement[];\n status?: TooltipStatus;\n style?: CSSProperties;\n}\n\nexport const Tooltip = ({\n anchorElement,\n children,\n className,\n id,\n onMouseEnter,\n onMouseLeave,\n placement: placementProp,\n status,\n style: styleProp,\n}: TooltipProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const ref = useAnchoredPosition({\n anchorElement,\n placement: placementProp,\n });\n return (\n <Portal>\n <div\n className={cx(classBase, className, \"vuuHidden\", {\n [`${classBase}-error`]: status === \"error\",\n })}\n id={id}\n ref={ref}\n style={{ ...styleProp, left: 0, top: 0 }}\n >\n <span\n className={`${classBase}-content`}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </span>\n </div>\n </Portal>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","tooltipCss","useAnchoredPosition","Portal","jsx"],"mappings":";;;;;;;;;;AASA,MAAM,SAAY,GAAA,YAAA,CAAA;AAeX,MAAM,UAAU,CAAC;AAAA,EACtB,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,EAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAW,EAAA,aAAA;AAAA,EACX,MAAA;AAAA,EACA,KAAO,EAAA,SAAA;AACT,CAAoB,KAAA;AAClB,EAAA,MAAM,eAAeA,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,aAAA;AAAA,IACR,GAAK,EAAAC,SAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,MAAMC,uCAAoB,CAAA;AAAA,IAC9B,aAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,GACZ,CAAA,CAAA;AACD,EAAA,sCACGC,aACC,EAAA,EAAA,QAAA,kBAAAC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAW,EAAA,EAAA,CAAG,SAAW,EAAA,SAAA,EAAW,WAAa,EAAA;AAAA,QAC/C,CAAC,CAAA,EAAG,SAAS,CAAA,MAAA,CAAQ,GAAG,MAAW,KAAA,OAAA;AAAA,OACpC,CAAA;AAAA,MACD,EAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAO,EAAE,GAAG,WAAW,IAAM,EAAA,CAAA,EAAG,KAAK,CAAE,EAAA;AAAA,MAEvC,QAAA,kBAAAA,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,UACvB,YAAA;AAAA,UACA,YAAA;AAAA,UAEC,QAAA;AAAA,SAAA;AAAA,OACH;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from \"react\";\nimport { Portal } from \"../portal\";\nimport {\n TooltipPlacement,\n useTooltipAnchoredPosition,\n} from \"./useTooltipAnchoredPosition\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport tooltipCss from \"./Tooltip.css\";\n\nconst classBase = \"vuuTooltip\";\n\nexport type TooltipStatus = \"warning\" | \"error\" | \"info\";\nexport interface TooltipProps {\n anchorElement: RefObject<HTMLElement>;\n children: ReactNode;\n className?: string;\n id?: string;\n onMouseEnter: MouseEventHandler;\n onMouseLeave: MouseEventHandler;\n placement: TooltipPlacement | TooltipPlacement[];\n status?: TooltipStatus;\n style?: CSSProperties;\n}\n\nexport const Tooltip = ({\n anchorElement,\n children,\n className,\n id,\n onMouseEnter,\n onMouseLeave,\n placement: placementProp,\n status,\n style: styleProp,\n}: TooltipProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const ref = useTooltipAnchoredPosition({\n anchorElement,\n placement: placementProp,\n });\n return (\n <Portal>\n <div\n className={cx(classBase, className, \"vuuHidden\", {\n [`${classBase}-error`]: status === \"error\",\n })}\n id={id}\n ref={ref}\n style={{ ...styleProp, left: 0, top: 0 }}\n >\n <span\n className={`${classBase}-content`}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </span>\n </div>\n </Portal>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","tooltipCss","useTooltipAnchoredPosition","Portal","jsx"],"mappings":";;;;;;;;;;AAYA,MAAM,SAAY,GAAA,YAAA,CAAA;AAeX,MAAM,UAAU,CAAC;AAAA,EACtB,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,EAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAW,EAAA,aAAA;AAAA,EACX,MAAA;AAAA,EACA,KAAO,EAAA,SAAA;AACT,CAAoB,KAAA;AAClB,EAAA,MAAM,eAAeA,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,aAAA;AAAA,IACR,GAAK,EAAAC,SAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,MAAMC,qDAA2B,CAAA;AAAA,IACrC,aAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,GACZ,CAAA,CAAA;AACD,EAAA,sCACGC,aACC,EAAA,EAAA,QAAA,kBAAAC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAW,EAAA,EAAA,CAAG,SAAW,EAAA,SAAA,EAAW,WAAa,EAAA;AAAA,QAC/C,CAAC,CAAA,EAAG,SAAS,CAAA,MAAA,CAAQ,GAAG,MAAW,KAAA,OAAA;AAAA,OACpC,CAAA;AAAA,MACD,EAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAO,EAAE,GAAG,WAAW,IAAM,EAAA,CAAA,EAAG,KAAK,CAAE,EAAA;AAAA,MAEvC,QAAA,kBAAAA,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,UACvB,YAAA;AAAA,UACA,YAAA;AAAA,UAEC,QAAA;AAAA,SAAA;AAAA,OACH;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -6,7 +6,7 @@ var React = require('react');
6
6
  const useTooltip = ({
7
7
  anchorQuery = "*",
8
8
  id: idProp,
9
- placement = "right",
9
+ placement = ["right", "above", "below"],
10
10
  tooltipContent
11
11
  }) => {
12
12
  const hideTooltipRef = React.useRef();
@@ -1 +1 @@
1
- {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = \"right\",\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":["useRef","useState","useId","useCallback","queryClosest"],"mappings":"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"}
1
+ {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":["useRef","useState","useId","useCallback","queryClosest"],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ const pointerSize = 12;
6
+ const roomAbove = (anchor, tooltip) => tooltip.height + pointerSize < anchor.top;
7
+ const roomLeft = (anchor, tooltip) => tooltip.width + pointerSize < anchor.left;
8
+ const roomRight = (anchor, tooltip) => anchor.right + tooltip.width + pointerSize < document.body.clientWidth;
9
+ const roomBelow = (anchor, tooltip) => document.body.clientHeight - anchor.bottom > tooltip.height + pointerSize;
10
+ const roomAvailableAtPlacement = (placement, anchor, tooltip) => {
11
+ switch (placement) {
12
+ case "above":
13
+ return roomAbove(anchor, tooltip);
14
+ case "left":
15
+ return roomLeft(anchor, tooltip);
16
+ case "below":
17
+ return roomBelow(anchor, tooltip);
18
+ case "right":
19
+ return roomRight(anchor, tooltip);
20
+ default:
21
+ throw Error("invalid tooltip placement");
22
+ }
23
+ };
24
+ const positionAbove = (anchor, tooltip) => ({
25
+ left: anchor.left - (tooltip.width - anchor.width) / 2,
26
+ top: anchor.top - (tooltip.height + pointerSize)
27
+ });
28
+ const positionBelow = (anchor, tooltip) => ({
29
+ left: anchor.left - (tooltip.width - anchor.width) / 2,
30
+ top: anchor.bottom + pointerSize
31
+ });
32
+ const positionLeft = (anchor, tooltip) => ({
33
+ left: anchor.left - pointerSize - tooltip.width,
34
+ top: anchor.top - (tooltip.height - anchor.height) / 2
35
+ });
36
+ const positionRight = (anchor, tooltip) => ({
37
+ left: anchor.right + pointerSize,
38
+ top: anchor.top - (tooltip.height - anchor.height) / 2
39
+ });
40
+ const positionAtPlacement = (placement, anchor, tooltip) => {
41
+ switch (placement) {
42
+ case "above":
43
+ return positionAbove(anchor, tooltip);
44
+ case "left":
45
+ return positionLeft(anchor, tooltip);
46
+ case "below":
47
+ return positionBelow(anchor, tooltip);
48
+ case "right":
49
+ return positionRight(anchor, tooltip);
50
+ default:
51
+ throw Error("invalid tooltip placement");
52
+ }
53
+ };
54
+ const keepWithinTheScreen = ({ height, width }, position) => {
55
+ const { clientWidth, clientHeight } = document.body;
56
+ let { left, top } = position;
57
+ if (left + width > clientWidth) {
58
+ left -= left + width - clientWidth;
59
+ }
60
+ if (left < 0) {
61
+ left = 0;
62
+ }
63
+ if (top + height > clientHeight) {
64
+ top -= top + height - clientHeight;
65
+ }
66
+ if (top < 0) {
67
+ top = 0;
68
+ }
69
+ return { left, top };
70
+ };
71
+ const toCSSText = ({ left, top }) => `left:${left}px;top:${top}px;opacity:1;`;
72
+ const getNextPlacement = (placement) => {
73
+ if (Array.isArray(placement)) {
74
+ if (placement.length === 0) {
75
+ return [void 0, placement];
76
+ } else {
77
+ return [placement[0], placement.slice(1)];
78
+ }
79
+ } else {
80
+ return [placement, []];
81
+ }
82
+ };
83
+ const useTooltipAnchoredPosition = ({
84
+ anchorElement,
85
+ placement
86
+ }) => {
87
+ const ref = React.useCallback(
88
+ (el) => {
89
+ if (el && anchorElement.current) {
90
+ const anchorRect = anchorElement.current.getBoundingClientRect();
91
+ const tooltipRect = el.getBoundingClientRect();
92
+ let nextPlacement;
93
+ let placements = placement;
94
+ [nextPlacement = "right", placements] = getNextPlacement(placements);
95
+ do {
96
+ if (roomAvailableAtPlacement(nextPlacement, anchorRect, tooltipRect)) {
97
+ el.style.cssText = toCSSText(
98
+ keepWithinTheScreen(
99
+ tooltipRect,
100
+ positionAtPlacement(nextPlacement, anchorRect, tooltipRect)
101
+ )
102
+ );
103
+ el.dataset.align = nextPlacement;
104
+ return;
105
+ }
106
+ [nextPlacement, placements] = getNextPlacement(placements);
107
+ } while (nextPlacement);
108
+ }
109
+ el?.classList.remove("vuuHidden");
110
+ },
111
+ [anchorElement, placement]
112
+ );
113
+ return ref;
114
+ };
115
+
116
+ exports.useTooltipAnchoredPosition = useTooltipAnchoredPosition;
117
+ //# sourceMappingURL=useTooltipAnchoredPosition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTooltipAnchoredPosition.js","sources":["../../src/tooltip/useTooltipAnchoredPosition.ts"],"sourcesContent":["// TODO merge with Popup\n\nimport { RefCallback, RefObject, useCallback } from \"react\";\n\nexport type TooltipPlacement = \"above\" | \"right\" | \"below\" | \"left\";\n\nconst pointerSize = 12;\nexport interface TooltipAnchoredPositionHookProps {\n anchorElement: RefObject<HTMLElement>;\n placement: TooltipPlacement | TooltipPlacement[];\n}\n\nconst roomAbove = (anchor: DOMRect, tooltip: DOMRect) =>\n tooltip.height + pointerSize < anchor.top;\nconst roomLeft = (anchor: DOMRect, tooltip: DOMRect) =>\n tooltip.width + pointerSize < anchor.left;\nconst roomRight = (anchor: DOMRect, tooltip: DOMRect) =>\n anchor.right + tooltip.width + pointerSize < document.body.clientWidth;\nconst roomBelow = (anchor: DOMRect, tooltip: DOMRect) =>\n document.body.clientHeight - anchor.bottom > tooltip.height + pointerSize;\n\nconst roomAvailableAtPlacement = (\n placement: TooltipPlacement,\n anchor: DOMRect,\n tooltip: DOMRect\n) => {\n switch (placement) {\n case \"above\":\n return roomAbove(anchor, tooltip);\n case \"left\":\n return roomLeft(anchor, tooltip);\n case \"below\":\n return roomBelow(anchor, tooltip);\n case \"right\":\n return roomRight(anchor, tooltip);\n default:\n throw Error(\"invalid tooltip placement\");\n }\n};\n\ntype Position = { left: number; top: number };\ntype Positioner = (anchorRect: DOMRect, tooltipRect: DOMRect) => Position;\n\nconst positionAbove: Positioner = (anchor, tooltip) => ({\n left: anchor.left - (tooltip.width - anchor.width) / 2,\n top: anchor.top - (tooltip.height + pointerSize),\n});\n\nconst positionBelow: Positioner = (anchor, tooltip) => ({\n left: anchor.left - (tooltip.width - anchor.width) / 2,\n top: anchor.bottom + pointerSize,\n});\nconst positionLeft: Positioner = (anchor, tooltip) => ({\n left: anchor.left - pointerSize - tooltip.width,\n top: anchor.top - (tooltip.height - anchor.height) / 2,\n});\n\nconst positionRight: Positioner = (anchor, tooltip) => ({\n left: anchor.right + pointerSize,\n top: anchor.top - (tooltip.height - anchor.height) / 2,\n});\n\nconst positionAtPlacement = (\n placement: TooltipPlacement,\n anchor: DOMRect,\n tooltip: DOMRect\n) => {\n switch (placement) {\n case \"above\":\n return positionAbove(anchor, tooltip);\n case \"left\":\n return positionLeft(anchor, tooltip);\n case \"below\":\n return positionBelow(anchor, tooltip);\n case \"right\":\n return positionRight(anchor, tooltip);\n default:\n throw Error(\"invalid tooltip placement\");\n }\n};\n\nconst keepWithinTheScreen = (\n { height, width }: DOMRect,\n position: Position\n) => {\n const { clientWidth, clientHeight } = document.body;\n let { left, top } = position;\n if (left + width > clientWidth) {\n left -= left + width - clientWidth;\n }\n if (left < 0) {\n left = 0;\n }\n if (top + height > clientHeight) {\n top -= top + height - clientHeight;\n }\n if (top < 0) {\n top = 0;\n }\n\n return { left, top };\n};\n\nconst toCSSText = ({ left, top }: Position) =>\n `left:${left}px;top:${top}px;opacity:1;`;\n\nconst getNextPlacement = (\n placement: TooltipPlacement | TooltipPlacement[]\n): [TooltipPlacement | undefined, TooltipPlacement[]] => {\n if (Array.isArray(placement)) {\n if (placement.length === 0) {\n return [undefined, placement];\n } else {\n return [placement[0], placement.slice(1)];\n }\n } else {\n return [placement, []];\n }\n};\n\nexport const useTooltipAnchoredPosition = ({\n anchorElement,\n placement,\n}: TooltipAnchoredPositionHookProps) => {\n const ref = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el && anchorElement.current) {\n const anchorRect = anchorElement.current.getBoundingClientRect();\n const tooltipRect = el.getBoundingClientRect();\n let nextPlacement: TooltipPlacement | undefined;\n let placements: TooltipPlacement | TooltipPlacement[] = placement;\n [nextPlacement = \"right\", placements] = getNextPlacement(placements);\n do {\n if (\n roomAvailableAtPlacement(nextPlacement, anchorRect, tooltipRect)\n ) {\n el.style.cssText = toCSSText(\n keepWithinTheScreen(\n tooltipRect,\n positionAtPlacement(nextPlacement, anchorRect, tooltipRect)\n )\n );\n el.dataset.align = nextPlacement;\n return;\n }\n [nextPlacement, placements] = getNextPlacement(placements);\n } while (nextPlacement);\n }\n el?.classList.remove(\"vuuHidden\");\n },\n [anchorElement, placement]\n );\n return ref;\n};\n"],"names":["useCallback"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var tooltipCss = ".vuuTooltip {\n --tooltip-align: flex-start;\n --tooltip-background: var(--salt-actionable-primary-background-hover);\n --tooltip-border: var(--salt-actionable-primary-background-hover);\n --tooltip-color: var(--salt-actionable-primary-foreground-hover);\n --tooltip-justify: flex-start;\n --tooltip-top: auto;\n --tooltip-right: auto;\n --tooltip-bottom: auto;\n --tooltip-left: auto;\n align-items: var(--tooltip-align);\n justify-content: var(--tooltip-justify);\n display: flex;\n position: absolute;\n transition: opacity .15s ease-in;\n z-index: 100;\n\n\n &.vuuHidden {\n opacity: 0;\n }\n }\n \n .vuuTooltip-content {\n background-color: var(--tooltip-background);\n border-color: var(--tooltip-border);\n border-width: 1px;\n border-style: solid;\n border-radius: var(--vuuTooltip-borderRadius, 6px);\n box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);\n color: var(--tooltip-color);\n line-height: 24px;\n padding: 2px 8px;\n white-space: nowrap;\n }\n \n .vuuTooltip::before {\n background-color: var(--tooltip-border);\n content: ' ';\n display: block;\n position: absolute;\n transform: rotate(45deg);\n width: 12px;\n height: 12px;\n z-index: -1;\n}\n\n.vuuTooltip[data-align='above']::before {\n bottom: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align='below']::before {\n top: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align='right']::before {\n}\n\n.vuuTooltip[data-align='left']::before {\n}\n\n.vuuTooltip-error {\n --tooltip-background: var(--vuu-color-red-50);\n --tooltip-color: white;\n color: white;\n}";
1
+ var tooltipCss = ".vuuTooltip {\n --tooltip-align: flex-start;\n --tooltip-background: var(--salt-actionable-primary-background-hover);\n --tooltip-border: var(--salt-actionable-primary-background-hover);\n --tooltip-color: var(--salt-actionable-primary-foreground-hover);\n --tooltip-justify: flex-start;\n --tooltip-top: auto;\n --tooltip-right: auto;\n --tooltip-bottom: auto;\n --tooltip-left: auto;\n align-items: var(--tooltip-align);\n justify-content: var(--tooltip-justify);\n display: flex;\n position: absolute;\n transition: opacity 0.15s ease-in;\n z-index: 100;\n\n &.vuuHidden {\n opacity: 0;\n }\n}\n\n.vuuTooltip-content {\n background-color: var(--tooltip-background);\n border-color: var(--tooltip-border);\n border-width: 1px;\n border-style: solid;\n border-radius: var(--vuuTooltip-borderRadius, 6px);\n box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);\n color: var(--tooltip-color);\n line-height: 24px;\n padding: 2px 8px;\n white-space: nowrap;\n}\n\n.vuuTooltip::before {\n background-color: var(--tooltip-border);\n content: \" \";\n display: block;\n position: absolute;\n transform: rotate(45deg);\n width: 12px;\n height: 12px;\n z-index: -1;\n}\n\n.vuuTooltip[data-align=\"above\"]:before {\n bottom: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"below\"]:before {\n top: -6px;\n left: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"right\"]:before {\n left: -6px;\n top: calc(50% - 6px);\n}\n\n.vuuTooltip[data-align=\"left\"]:before {\n right: -6px;\n top: calc(50% - 6px);\n}\n\n.vuuTooltip-error {\n --tooltip-background: var(--vuu-color-red-50);\n --tooltip-color: white;\n color: white;\n}\n";
2
2
 
3
3
  export { tooltipCss as default };
4
4
  //# sourceMappingURL=Tooltip.css.js.map
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { Portal } from '../portal/Portal.js';
3
- import { useAnchoredPosition } from './useAnchoredPosition.js';
3
+ import { useTooltipAnchoredPosition } from './useTooltipAnchoredPosition.js';
4
4
  import cx from 'clsx';
5
5
  import { useComponentCssInjection } from '@salt-ds/styles';
6
6
  import { useWindow } from '@salt-ds/window';
@@ -24,7 +24,7 @@ const Tooltip = ({
24
24
  css: tooltipCss,
25
25
  window: targetWindow
26
26
  });
27
- const ref = useAnchoredPosition({
27
+ const ref = useTooltipAnchoredPosition({
28
28
  anchorElement,
29
29
  placement: placementProp
30
30
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from \"react\";\nimport { Portal } from \"../portal\";\nimport { TooltipPlacement, useAnchoredPosition } from \"./useAnchoredPosition\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport tooltipCss from \"./Tooltip.css\";\n\nconst classBase = \"vuuTooltip\";\n\nexport type TooltipStatus = \"warning\" | \"error\" | \"info\";\nexport interface TooltipProps {\n anchorElement: RefObject<HTMLElement>;\n children: ReactNode;\n className?: string;\n id?: string;\n onMouseEnter: MouseEventHandler;\n onMouseLeave: MouseEventHandler;\n placement: TooltipPlacement | TooltipPlacement[];\n status?: TooltipStatus;\n style?: CSSProperties;\n}\n\nexport const Tooltip = ({\n anchorElement,\n children,\n className,\n id,\n onMouseEnter,\n onMouseLeave,\n placement: placementProp,\n status,\n style: styleProp,\n}: TooltipProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const ref = useAnchoredPosition({\n anchorElement,\n placement: placementProp,\n });\n return (\n <Portal>\n <div\n className={cx(classBase, className, \"vuuHidden\", {\n [`${classBase}-error`]: status === \"error\",\n })}\n id={id}\n ref={ref}\n style={{ ...styleProp, left: 0, top: 0 }}\n >\n <span\n className={`${classBase}-content`}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </span>\n </div>\n </Portal>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AASA,MAAM,SAAY,GAAA,YAAA,CAAA;AAeX,MAAM,UAAU,CAAC;AAAA,EACtB,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,EAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAW,EAAA,aAAA;AAAA,EACX,MAAA;AAAA,EACA,KAAO,EAAA,SAAA;AACT,CAAoB,KAAA;AAClB,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,aAAA;AAAA,IACR,GAAK,EAAA,UAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,MAAM,mBAAoB,CAAA;AAAA,IAC9B,aAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,GACZ,CAAA,CAAA;AACD,EAAA,2BACG,MACC,EAAA,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAW,EAAA,EAAA,CAAG,SAAW,EAAA,SAAA,EAAW,WAAa,EAAA;AAAA,QAC/C,CAAC,CAAA,EAAG,SAAS,CAAA,MAAA,CAAQ,GAAG,MAAW,KAAA,OAAA;AAAA,OACpC,CAAA;AAAA,MACD,EAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAO,EAAE,GAAG,WAAW,IAAM,EAAA,CAAA,EAAG,KAAK,CAAE,EAAA;AAAA,MAEvC,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,UACvB,YAAA;AAAA,UACA,YAAA;AAAA,UAEC,QAAA;AAAA,SAAA;AAAA,OACH;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from \"react\";\nimport { Portal } from \"../portal\";\nimport {\n TooltipPlacement,\n useTooltipAnchoredPosition,\n} from \"./useTooltipAnchoredPosition\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport tooltipCss from \"./Tooltip.css\";\n\nconst classBase = \"vuuTooltip\";\n\nexport type TooltipStatus = \"warning\" | \"error\" | \"info\";\nexport interface TooltipProps {\n anchorElement: RefObject<HTMLElement>;\n children: ReactNode;\n className?: string;\n id?: string;\n onMouseEnter: MouseEventHandler;\n onMouseLeave: MouseEventHandler;\n placement: TooltipPlacement | TooltipPlacement[];\n status?: TooltipStatus;\n style?: CSSProperties;\n}\n\nexport const Tooltip = ({\n anchorElement,\n children,\n className,\n id,\n onMouseEnter,\n onMouseLeave,\n placement: placementProp,\n status,\n style: styleProp,\n}: TooltipProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const ref = useTooltipAnchoredPosition({\n anchorElement,\n placement: placementProp,\n });\n return (\n <Portal>\n <div\n className={cx(classBase, className, \"vuuHidden\", {\n [`${classBase}-error`]: status === \"error\",\n })}\n id={id}\n ref={ref}\n style={{ ...styleProp, left: 0, top: 0 }}\n >\n <span\n className={`${classBase}-content`}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </span>\n </div>\n </Portal>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAYA,MAAM,SAAY,GAAA,YAAA,CAAA;AAeX,MAAM,UAAU,CAAC;AAAA,EACtB,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,EAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAW,EAAA,aAAA;AAAA,EACX,MAAA;AAAA,EACA,KAAO,EAAA,SAAA;AACT,CAAoB,KAAA;AAClB,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,aAAA;AAAA,IACR,GAAK,EAAA,UAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,MAAM,0BAA2B,CAAA;AAAA,IACrC,aAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,GACZ,CAAA,CAAA;AACD,EAAA,2BACG,MACC,EAAA,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAW,EAAA,EAAA,CAAG,SAAW,EAAA,SAAA,EAAW,WAAa,EAAA;AAAA,QAC/C,CAAC,CAAA,EAAG,SAAS,CAAA,MAAA,CAAQ,GAAG,MAAW,KAAA,OAAA;AAAA,OACpC,CAAA;AAAA,MACD,EAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAO,EAAE,GAAG,WAAW,IAAM,EAAA,CAAA,EAAG,KAAK,CAAE,EAAA;AAAA,MAEvC,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,UACvB,YAAA;AAAA,UACA,YAAA;AAAA,UAEC,QAAA;AAAA,SAAA;AAAA,OACH;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -4,7 +4,7 @@ import { useRef, useState, useCallback } from 'react';
4
4
  const useTooltip = ({
5
5
  anchorQuery = "*",
6
6
  id: idProp,
7
- placement = "right",
7
+ placement = ["right", "above", "below"],
8
8
  tooltipContent
9
9
  }) => {
10
10
  const hideTooltipRef = useRef();
@@ -1 +1 @@
1
- {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = \"right\",\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { useCallback } from 'react';
2
+
3
+ const pointerSize = 12;
4
+ const roomAbove = (anchor, tooltip) => tooltip.height + pointerSize < anchor.top;
5
+ const roomLeft = (anchor, tooltip) => tooltip.width + pointerSize < anchor.left;
6
+ const roomRight = (anchor, tooltip) => anchor.right + tooltip.width + pointerSize < document.body.clientWidth;
7
+ const roomBelow = (anchor, tooltip) => document.body.clientHeight - anchor.bottom > tooltip.height + pointerSize;
8
+ const roomAvailableAtPlacement = (placement, anchor, tooltip) => {
9
+ switch (placement) {
10
+ case "above":
11
+ return roomAbove(anchor, tooltip);
12
+ case "left":
13
+ return roomLeft(anchor, tooltip);
14
+ case "below":
15
+ return roomBelow(anchor, tooltip);
16
+ case "right":
17
+ return roomRight(anchor, tooltip);
18
+ default:
19
+ throw Error("invalid tooltip placement");
20
+ }
21
+ };
22
+ const positionAbove = (anchor, tooltip) => ({
23
+ left: anchor.left - (tooltip.width - anchor.width) / 2,
24
+ top: anchor.top - (tooltip.height + pointerSize)
25
+ });
26
+ const positionBelow = (anchor, tooltip) => ({
27
+ left: anchor.left - (tooltip.width - anchor.width) / 2,
28
+ top: anchor.bottom + pointerSize
29
+ });
30
+ const positionLeft = (anchor, tooltip) => ({
31
+ left: anchor.left - pointerSize - tooltip.width,
32
+ top: anchor.top - (tooltip.height - anchor.height) / 2
33
+ });
34
+ const positionRight = (anchor, tooltip) => ({
35
+ left: anchor.right + pointerSize,
36
+ top: anchor.top - (tooltip.height - anchor.height) / 2
37
+ });
38
+ const positionAtPlacement = (placement, anchor, tooltip) => {
39
+ switch (placement) {
40
+ case "above":
41
+ return positionAbove(anchor, tooltip);
42
+ case "left":
43
+ return positionLeft(anchor, tooltip);
44
+ case "below":
45
+ return positionBelow(anchor, tooltip);
46
+ case "right":
47
+ return positionRight(anchor, tooltip);
48
+ default:
49
+ throw Error("invalid tooltip placement");
50
+ }
51
+ };
52
+ const keepWithinTheScreen = ({ height, width }, position) => {
53
+ const { clientWidth, clientHeight } = document.body;
54
+ let { left, top } = position;
55
+ if (left + width > clientWidth) {
56
+ left -= left + width - clientWidth;
57
+ }
58
+ if (left < 0) {
59
+ left = 0;
60
+ }
61
+ if (top + height > clientHeight) {
62
+ top -= top + height - clientHeight;
63
+ }
64
+ if (top < 0) {
65
+ top = 0;
66
+ }
67
+ return { left, top };
68
+ };
69
+ const toCSSText = ({ left, top }) => `left:${left}px;top:${top}px;opacity:1;`;
70
+ const getNextPlacement = (placement) => {
71
+ if (Array.isArray(placement)) {
72
+ if (placement.length === 0) {
73
+ return [void 0, placement];
74
+ } else {
75
+ return [placement[0], placement.slice(1)];
76
+ }
77
+ } else {
78
+ return [placement, []];
79
+ }
80
+ };
81
+ const useTooltipAnchoredPosition = ({
82
+ anchorElement,
83
+ placement
84
+ }) => {
85
+ const ref = useCallback(
86
+ (el) => {
87
+ if (el && anchorElement.current) {
88
+ const anchorRect = anchorElement.current.getBoundingClientRect();
89
+ const tooltipRect = el.getBoundingClientRect();
90
+ let nextPlacement;
91
+ let placements = placement;
92
+ [nextPlacement = "right", placements] = getNextPlacement(placements);
93
+ do {
94
+ if (roomAvailableAtPlacement(nextPlacement, anchorRect, tooltipRect)) {
95
+ el.style.cssText = toCSSText(
96
+ keepWithinTheScreen(
97
+ tooltipRect,
98
+ positionAtPlacement(nextPlacement, anchorRect, tooltipRect)
99
+ )
100
+ );
101
+ el.dataset.align = nextPlacement;
102
+ return;
103
+ }
104
+ [nextPlacement, placements] = getNextPlacement(placements);
105
+ } while (nextPlacement);
106
+ }
107
+ el?.classList.remove("vuuHidden");
108
+ },
109
+ [anchorElement, placement]
110
+ );
111
+ return ref;
112
+ };
113
+
114
+ export { useTooltipAnchoredPosition };
115
+ //# sourceMappingURL=useTooltipAnchoredPosition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTooltipAnchoredPosition.js","sources":["../../src/tooltip/useTooltipAnchoredPosition.ts"],"sourcesContent":["// TODO merge with Popup\n\nimport { RefCallback, RefObject, useCallback } from \"react\";\n\nexport type TooltipPlacement = \"above\" | \"right\" | \"below\" | \"left\";\n\nconst pointerSize = 12;\nexport interface TooltipAnchoredPositionHookProps {\n anchorElement: RefObject<HTMLElement>;\n placement: TooltipPlacement | TooltipPlacement[];\n}\n\nconst roomAbove = (anchor: DOMRect, tooltip: DOMRect) =>\n tooltip.height + pointerSize < anchor.top;\nconst roomLeft = (anchor: DOMRect, tooltip: DOMRect) =>\n tooltip.width + pointerSize < anchor.left;\nconst roomRight = (anchor: DOMRect, tooltip: DOMRect) =>\n anchor.right + tooltip.width + pointerSize < document.body.clientWidth;\nconst roomBelow = (anchor: DOMRect, tooltip: DOMRect) =>\n document.body.clientHeight - anchor.bottom > tooltip.height + pointerSize;\n\nconst roomAvailableAtPlacement = (\n placement: TooltipPlacement,\n anchor: DOMRect,\n tooltip: DOMRect\n) => {\n switch (placement) {\n case \"above\":\n return roomAbove(anchor, tooltip);\n case \"left\":\n return roomLeft(anchor, tooltip);\n case \"below\":\n return roomBelow(anchor, tooltip);\n case \"right\":\n return roomRight(anchor, tooltip);\n default:\n throw Error(\"invalid tooltip placement\");\n }\n};\n\ntype Position = { left: number; top: number };\ntype Positioner = (anchorRect: DOMRect, tooltipRect: DOMRect) => Position;\n\nconst positionAbove: Positioner = (anchor, tooltip) => ({\n left: anchor.left - (tooltip.width - anchor.width) / 2,\n top: anchor.top - (tooltip.height + pointerSize),\n});\n\nconst positionBelow: Positioner = (anchor, tooltip) => ({\n left: anchor.left - (tooltip.width - anchor.width) / 2,\n top: anchor.bottom + pointerSize,\n});\nconst positionLeft: Positioner = (anchor, tooltip) => ({\n left: anchor.left - pointerSize - tooltip.width,\n top: anchor.top - (tooltip.height - anchor.height) / 2,\n});\n\nconst positionRight: Positioner = (anchor, tooltip) => ({\n left: anchor.right + pointerSize,\n top: anchor.top - (tooltip.height - anchor.height) / 2,\n});\n\nconst positionAtPlacement = (\n placement: TooltipPlacement,\n anchor: DOMRect,\n tooltip: DOMRect\n) => {\n switch (placement) {\n case \"above\":\n return positionAbove(anchor, tooltip);\n case \"left\":\n return positionLeft(anchor, tooltip);\n case \"below\":\n return positionBelow(anchor, tooltip);\n case \"right\":\n return positionRight(anchor, tooltip);\n default:\n throw Error(\"invalid tooltip placement\");\n }\n};\n\nconst keepWithinTheScreen = (\n { height, width }: DOMRect,\n position: Position\n) => {\n const { clientWidth, clientHeight } = document.body;\n let { left, top } = position;\n if (left + width > clientWidth) {\n left -= left + width - clientWidth;\n }\n if (left < 0) {\n left = 0;\n }\n if (top + height > clientHeight) {\n top -= top + height - clientHeight;\n }\n if (top < 0) {\n top = 0;\n }\n\n return { left, top };\n};\n\nconst toCSSText = ({ left, top }: Position) =>\n `left:${left}px;top:${top}px;opacity:1;`;\n\nconst getNextPlacement = (\n placement: TooltipPlacement | TooltipPlacement[]\n): [TooltipPlacement | undefined, TooltipPlacement[]] => {\n if (Array.isArray(placement)) {\n if (placement.length === 0) {\n return [undefined, placement];\n } else {\n return [placement[0], placement.slice(1)];\n }\n } else {\n return [placement, []];\n }\n};\n\nexport const useTooltipAnchoredPosition = ({\n anchorElement,\n placement,\n}: TooltipAnchoredPositionHookProps) => {\n const ref = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el && anchorElement.current) {\n const anchorRect = anchorElement.current.getBoundingClientRect();\n const tooltipRect = el.getBoundingClientRect();\n let nextPlacement: TooltipPlacement | undefined;\n let placements: TooltipPlacement | TooltipPlacement[] = placement;\n [nextPlacement = \"right\", placements] = getNextPlacement(placements);\n do {\n if (\n roomAvailableAtPlacement(nextPlacement, anchorRect, tooltipRect)\n ) {\n el.style.cssText = toCSSText(\n keepWithinTheScreen(\n tooltipRect,\n positionAtPlacement(nextPlacement, anchorRect, tooltipRect)\n )\n );\n el.dataset.align = nextPlacement;\n return;\n }\n [nextPlacement, placements] = getNextPlacement(placements);\n } while (nextPlacement);\n }\n el?.classList.remove(\"vuuHidden\");\n },\n [anchorElement, placement]\n );\n return ref;\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.8.74",
2
+ "version": "0.8.75",
3
3
  "description": "VUU popup components - Context Menu, Dialog etc",
4
4
  "author": "heswell",
5
5
  "license": "Apache-2.0",
@@ -7,10 +7,10 @@
7
7
  "@salt-ds/core": "1.27.1",
8
8
  "@salt-ds/styles": "0.2.1",
9
9
  "@salt-ds/window": "0.1.1",
10
- "@vuu-ui/vuu-data-types": "0.8.74",
11
- "@vuu-ui/vuu-layout": "0.8.74",
12
- "@vuu-ui/vuu-utils": "0.8.74",
13
- "@vuu-ui/vuu-ui-controls": "0.8.74"
10
+ "@vuu-ui/vuu-data-types": "0.8.75",
11
+ "@vuu-ui/vuu-layout": "0.8.75",
12
+ "@vuu-ui/vuu-utils": "0.8.75",
13
+ "@vuu-ui/vuu-ui-controls": "0.8.75"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "clsx": "^2.0.0",
@@ -1,5 +1,5 @@
1
1
  import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from "react";
2
- import { TooltipPlacement } from "./useAnchoredPosition";
2
+ import { TooltipPlacement } from "./useTooltipAnchoredPosition";
3
3
  export type TooltipStatus = "warning" | "error" | "info";
4
4
  export interface TooltipProps {
5
5
  anchorElement: RefObject<HTMLElement>;
@@ -1,6 +1,6 @@
1
1
  import { MouseEvent, ReactNode } from "react";
2
2
  import { TooltipProps } from "./Tooltip";
3
- import { TooltipPlacement } from "./useAnchoredPosition";
3
+ import { TooltipPlacement } from "./useTooltipAnchoredPosition";
4
4
  export interface TooltipHookProps {
5
5
  anchorQuery?: string;
6
6
  id: string;
@@ -0,0 +1,7 @@
1
+ import { RefCallback, RefObject } from "react";
2
+ export type TooltipPlacement = "above" | "right" | "below" | "left";
3
+ export interface TooltipAnchoredPositionHookProps {
4
+ anchorElement: RefObject<HTMLElement>;
5
+ placement: TooltipPlacement | TooltipPlacement[];
6
+ }
7
+ export declare const useTooltipAnchoredPosition: ({ anchorElement, placement, }: TooltipAnchoredPositionHookProps) => RefCallback<HTMLDivElement>;
@@ -1,71 +0,0 @@
1
- 'use strict';
2
-
3
- var React = require('react');
4
-
5
- const pointerSize = 12;
6
- const roomAbove = (anchor, height) => height < anchor.top;
7
- const roomBelow = (anchor, height) => document.body.clientHeight - anchor.bottom > height;
8
- const getNextPlacement = (placement) => {
9
- if (Array.isArray(placement)) {
10
- if (placement.length === 0) {
11
- return [void 0, placement];
12
- } else {
13
- return [placement[0], placement.slice(1)];
14
- }
15
- } else {
16
- return [placement, []];
17
- }
18
- };
19
- const useAnchoredPosition = ({
20
- anchorElement,
21
- offsetLeft = 0,
22
- offsetTop = 0,
23
- placement
24
- }) => {
25
- const ref = React.useCallback(
26
- (el) => {
27
- if (el && anchorElement.current) {
28
- const anchor = anchorElement.current.getBoundingClientRect();
29
- const { height, width } = el.getBoundingClientRect();
30
- let nextPlacement;
31
- let placements = placement;
32
- do {
33
- [nextPlacement, placements] = getNextPlacement(placements);
34
- switch (nextPlacement) {
35
- case "above":
36
- if (roomAbove(anchor, height + pointerSize)) {
37
- const midDiff = (width - anchor.width) / 2;
38
- el.style.cssText = `left:${anchor.left - midDiff}px;top:${anchor.top - height - pointerSize}px;opacity: 1;`;
39
- el.dataset.align = "above";
40
- return;
41
- }
42
- break;
43
- case "below":
44
- if (roomBelow(anchor, height + pointerSize)) {
45
- const midDiff = (width - anchor.width) / 2;
46
- el.style.cssText = `left:${anchor.left - midDiff}px;top:${anchor.bottom + pointerSize}px;opacity: 1;`;
47
- el.dataset.align = "below";
48
- return;
49
- }
50
- break;
51
- case "right":
52
- console.log("place right");
53
- break;
54
- case "left":
55
- console.log("place left");
56
- break;
57
- default:
58
- console.warn(`unklnown tooltip placement ${placement}`);
59
- }
60
- } while (nextPlacement);
61
- }
62
- },
63
- [anchorElement, placement]
64
- );
65
- React.useLayoutEffect(() => {
66
- }, [anchorElement, offsetLeft, offsetTop, placement]);
67
- return ref;
68
- };
69
-
70
- exports.useAnchoredPosition = useAnchoredPosition;
71
- //# sourceMappingURL=useAnchoredPosition.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAnchoredPosition.js","sources":["../../src/tooltip/useAnchoredPosition.ts"],"sourcesContent":["// TODO merge with Popup\n\nimport { RefCallback, RefObject, useCallback, useLayoutEffect } from \"react\";\n\nexport type TooltipPlacement = \"above\" | \"right\" | \"below\" | \"left\";\n\nconst pointerSize = 12;\nexport interface AnchoredPositionHookProps {\n anchorElement: RefObject<HTMLElement>;\n offsetLeft?: number;\n offsetTop?: number;\n placement: TooltipPlacement | TooltipPlacement[];\n}\n\nconst roomAbove = (anchor: DOMRect, height: number) => height < anchor.top;\nconst roomBelow = (anchor: DOMRect, height: number) =>\n document.body.clientHeight - anchor.bottom > height;\n\nconst getNextPlacement = (\n placement: TooltipPlacement | TooltipPlacement[]\n): [TooltipPlacement | undefined, TooltipPlacement[]] => {\n if (Array.isArray(placement)) {\n if (placement.length === 0) {\n return [undefined, placement];\n } else {\n return [placement[0], placement.slice(1)];\n }\n } else {\n return [placement, []];\n }\n};\n\nexport const useAnchoredPosition = ({\n anchorElement,\n offsetLeft = 0,\n offsetTop = 0,\n placement,\n}: AnchoredPositionHookProps) => {\n const ref = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el && anchorElement.current) {\n const anchor = anchorElement.current.getBoundingClientRect();\n const { height, width } = el.getBoundingClientRect();\n let nextPlacement: TooltipPlacement | undefined;\n let placements: TooltipPlacement | TooltipPlacement[] = placement;\n do {\n [nextPlacement, placements] = getNextPlacement(placements);\n switch (nextPlacement) {\n case \"above\":\n if (roomAbove(anchor, height + pointerSize)) {\n const midDiff = (width - anchor.width) / 2;\n el.style.cssText = `left:${anchor.left - midDiff}px;top:${\n anchor.top - height - pointerSize\n }px;opacity: 1;`;\n el.dataset.align = \"above\";\n return;\n }\n break;\n case \"below\":\n if (roomBelow(anchor, height + pointerSize)) {\n const midDiff = (width - anchor.width) / 2;\n el.style.cssText = `left:${anchor.left - midDiff}px;top:${\n anchor.bottom + pointerSize\n }px;opacity: 1;`;\n el.dataset.align = \"below\";\n return;\n }\n break;\n\n case \"right\":\n console.log(\"place right\");\n break;\n case \"left\":\n console.log(\"place left\");\n break;\n default:\n console.warn(`unklnown tooltip placement ${placement}`);\n }\n } while (nextPlacement);\n }\n\n // el?.classList.remove(\"vuuHidden\");\n },\n [anchorElement, placement]\n );\n // const [position, setPosition] = useState<\n // { left: number; top: number } | undefined\n // >();\n\n // maybe better as useMemo ?\n useLayoutEffect(() => {\n // if (anchorElement.current) {\n // const position = getPositionRelativeToAnchor(\n // anchorElement.current,\n // placement,\n // offsetLeft,\n // offsetTop\n // );\n // setPosition(position);\n // }\n }, [anchorElement, offsetLeft, offsetTop, placement]);\n\n return ref;\n};\n"],"names":["useCallback","useLayoutEffect"],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- import { useCallback, useLayoutEffect } from 'react';
2
-
3
- const pointerSize = 12;
4
- const roomAbove = (anchor, height) => height < anchor.top;
5
- const roomBelow = (anchor, height) => document.body.clientHeight - anchor.bottom > height;
6
- const getNextPlacement = (placement) => {
7
- if (Array.isArray(placement)) {
8
- if (placement.length === 0) {
9
- return [void 0, placement];
10
- } else {
11
- return [placement[0], placement.slice(1)];
12
- }
13
- } else {
14
- return [placement, []];
15
- }
16
- };
17
- const useAnchoredPosition = ({
18
- anchorElement,
19
- offsetLeft = 0,
20
- offsetTop = 0,
21
- placement
22
- }) => {
23
- const ref = useCallback(
24
- (el) => {
25
- if (el && anchorElement.current) {
26
- const anchor = anchorElement.current.getBoundingClientRect();
27
- const { height, width } = el.getBoundingClientRect();
28
- let nextPlacement;
29
- let placements = placement;
30
- do {
31
- [nextPlacement, placements] = getNextPlacement(placements);
32
- switch (nextPlacement) {
33
- case "above":
34
- if (roomAbove(anchor, height + pointerSize)) {
35
- const midDiff = (width - anchor.width) / 2;
36
- el.style.cssText = `left:${anchor.left - midDiff}px;top:${anchor.top - height - pointerSize}px;opacity: 1;`;
37
- el.dataset.align = "above";
38
- return;
39
- }
40
- break;
41
- case "below":
42
- if (roomBelow(anchor, height + pointerSize)) {
43
- const midDiff = (width - anchor.width) / 2;
44
- el.style.cssText = `left:${anchor.left - midDiff}px;top:${anchor.bottom + pointerSize}px;opacity: 1;`;
45
- el.dataset.align = "below";
46
- return;
47
- }
48
- break;
49
- case "right":
50
- console.log("place right");
51
- break;
52
- case "left":
53
- console.log("place left");
54
- break;
55
- default:
56
- console.warn(`unklnown tooltip placement ${placement}`);
57
- }
58
- } while (nextPlacement);
59
- }
60
- },
61
- [anchorElement, placement]
62
- );
63
- useLayoutEffect(() => {
64
- }, [anchorElement, offsetLeft, offsetTop, placement]);
65
- return ref;
66
- };
67
-
68
- export { useAnchoredPosition };
69
- //# sourceMappingURL=useAnchoredPosition.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAnchoredPosition.js","sources":["../../src/tooltip/useAnchoredPosition.ts"],"sourcesContent":["// TODO merge with Popup\n\nimport { RefCallback, RefObject, useCallback, useLayoutEffect } from \"react\";\n\nexport type TooltipPlacement = \"above\" | \"right\" | \"below\" | \"left\";\n\nconst pointerSize = 12;\nexport interface AnchoredPositionHookProps {\n anchorElement: RefObject<HTMLElement>;\n offsetLeft?: number;\n offsetTop?: number;\n placement: TooltipPlacement | TooltipPlacement[];\n}\n\nconst roomAbove = (anchor: DOMRect, height: number) => height < anchor.top;\nconst roomBelow = (anchor: DOMRect, height: number) =>\n document.body.clientHeight - anchor.bottom > height;\n\nconst getNextPlacement = (\n placement: TooltipPlacement | TooltipPlacement[]\n): [TooltipPlacement | undefined, TooltipPlacement[]] => {\n if (Array.isArray(placement)) {\n if (placement.length === 0) {\n return [undefined, placement];\n } else {\n return [placement[0], placement.slice(1)];\n }\n } else {\n return [placement, []];\n }\n};\n\nexport const useAnchoredPosition = ({\n anchorElement,\n offsetLeft = 0,\n offsetTop = 0,\n placement,\n}: AnchoredPositionHookProps) => {\n const ref = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el && anchorElement.current) {\n const anchor = anchorElement.current.getBoundingClientRect();\n const { height, width } = el.getBoundingClientRect();\n let nextPlacement: TooltipPlacement | undefined;\n let placements: TooltipPlacement | TooltipPlacement[] = placement;\n do {\n [nextPlacement, placements] = getNextPlacement(placements);\n switch (nextPlacement) {\n case \"above\":\n if (roomAbove(anchor, height + pointerSize)) {\n const midDiff = (width - anchor.width) / 2;\n el.style.cssText = `left:${anchor.left - midDiff}px;top:${\n anchor.top - height - pointerSize\n }px;opacity: 1;`;\n el.dataset.align = \"above\";\n return;\n }\n break;\n case \"below\":\n if (roomBelow(anchor, height + pointerSize)) {\n const midDiff = (width - anchor.width) / 2;\n el.style.cssText = `left:${anchor.left - midDiff}px;top:${\n anchor.bottom + pointerSize\n }px;opacity: 1;`;\n el.dataset.align = \"below\";\n return;\n }\n break;\n\n case \"right\":\n console.log(\"place right\");\n break;\n case \"left\":\n console.log(\"place left\");\n break;\n default:\n console.warn(`unklnown tooltip placement ${placement}`);\n }\n } while (nextPlacement);\n }\n\n // el?.classList.remove(\"vuuHidden\");\n },\n [anchorElement, placement]\n );\n // const [position, setPosition] = useState<\n // { left: number; top: number } | undefined\n // >();\n\n // maybe better as useMemo ?\n useLayoutEffect(() => {\n // if (anchorElement.current) {\n // const position = getPositionRelativeToAnchor(\n // anchorElement.current,\n // placement,\n // offsetLeft,\n // offsetTop\n // );\n // setPosition(position);\n // }\n }, [anchorElement, offsetLeft, offsetTop, placement]);\n\n return ref;\n};\n"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import { RefCallback, RefObject } from "react";
2
- export type TooltipPlacement = "above" | "right" | "below" | "left";
3
- export interface AnchoredPositionHookProps {
4
- anchorElement: RefObject<HTMLElement>;
5
- offsetLeft?: number;
6
- offsetTop?: number;
7
- placement: TooltipPlacement | TooltipPlacement[];
8
- }
9
- export declare const useAnchoredPosition: ({ anchorElement, offsetLeft, offsetTop, placement, }: AnchoredPositionHookProps) => RefCallback<HTMLDivElement>;