@vuu-ui/vuu-popups 2.1.18 → 2.1.19-beta.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 (74) hide show
  1. package/package.json +10 -13
  2. package/src/index.js +4 -0
  3. package/src/popup/Popup.js +29 -0
  4. package/src/popup/getPositionRelativeToAnchor.js +47 -0
  5. package/src/popup/index.js +2 -0
  6. package/src/popup/useAnchoredPosition.js +41 -0
  7. package/src/popup-menu/PopupMenu.css.js +11 -0
  8. package/src/popup-menu/PopupMenu.js +67 -0
  9. package/src/popup-menu/index.js +1 -0
  10. package/src/popup-menu/usePopupMenu.js +72 -0
  11. package/src/portal/Portal.css.js +27 -0
  12. package/src/portal/Portal.js +62 -0
  13. package/src/portal/index.js +1 -0
  14. package/src/tooltip/Tooltip.css.js +76 -0
  15. package/src/tooltip/Tooltip.js +41 -0
  16. package/src/tooltip/index.js +2 -0
  17. package/src/tooltip/useTooltip.js +91 -0
  18. package/src/tooltip/useTooltipAnchoredPosition.js +102 -0
  19. package/cjs/index.js +0 -18
  20. package/cjs/index.js.map +0 -1
  21. package/cjs/popup/Popup.css.js +0 -6
  22. package/cjs/popup/Popup.css.js.map +0 -1
  23. package/cjs/popup/Popup.js +0 -38
  24. package/cjs/popup/Popup.js.map +0 -1
  25. package/cjs/popup/getPositionRelativeToAnchor.js +0 -43
  26. package/cjs/popup/getPositionRelativeToAnchor.js.map +0 -1
  27. package/cjs/popup/useAnchoredPosition.js +0 -58
  28. package/cjs/popup/useAnchoredPosition.js.map +0 -1
  29. package/cjs/popup-menu/PopupMenu.css.js +0 -6
  30. package/cjs/popup-menu/PopupMenu.css.js.map +0 -1
  31. package/cjs/popup-menu/PopupMenu.js +0 -100
  32. package/cjs/popup-menu/PopupMenu.js.map +0 -1
  33. package/cjs/popup-menu/usePopupMenu.js +0 -100
  34. package/cjs/popup-menu/usePopupMenu.js.map +0 -1
  35. package/cjs/portal/Portal.css.js +0 -6
  36. package/cjs/portal/Portal.css.js.map +0 -1
  37. package/cjs/portal/Portal.js +0 -73
  38. package/cjs/portal/Portal.js.map +0 -1
  39. package/cjs/tooltip/Tooltip.css.js +0 -6
  40. package/cjs/tooltip/Tooltip.css.js.map +0 -1
  41. package/cjs/tooltip/Tooltip.js +0 -56
  42. package/cjs/tooltip/Tooltip.js.map +0 -1
  43. package/cjs/tooltip/useTooltip.js +0 -106
  44. package/cjs/tooltip/useTooltip.js.map +0 -1
  45. package/cjs/tooltip/useTooltipAnchoredPosition.js +0 -117
  46. package/cjs/tooltip/useTooltipAnchoredPosition.js.map +0 -1
  47. package/esm/index.js +0 -7
  48. package/esm/index.js.map +0 -1
  49. package/esm/popup/Popup.css.js +0 -4
  50. package/esm/popup/Popup.css.js.map +0 -1
  51. package/esm/popup/Popup.js +0 -36
  52. package/esm/popup/Popup.js.map +0 -1
  53. package/esm/popup/getPositionRelativeToAnchor.js +0 -41
  54. package/esm/popup/getPositionRelativeToAnchor.js.map +0 -1
  55. package/esm/popup/useAnchoredPosition.js +0 -56
  56. package/esm/popup/useAnchoredPosition.js.map +0 -1
  57. package/esm/popup-menu/PopupMenu.css.js +0 -4
  58. package/esm/popup-menu/PopupMenu.css.js.map +0 -1
  59. package/esm/popup-menu/PopupMenu.js +0 -98
  60. package/esm/popup-menu/PopupMenu.js.map +0 -1
  61. package/esm/popup-menu/usePopupMenu.js +0 -98
  62. package/esm/popup-menu/usePopupMenu.js.map +0 -1
  63. package/esm/portal/Portal.css.js +0 -4
  64. package/esm/portal/Portal.css.js.map +0 -1
  65. package/esm/portal/Portal.js +0 -71
  66. package/esm/portal/Portal.js.map +0 -1
  67. package/esm/tooltip/Tooltip.css.js +0 -4
  68. package/esm/tooltip/Tooltip.css.js.map +0 -1
  69. package/esm/tooltip/Tooltip.js +0 -54
  70. package/esm/tooltip/Tooltip.js.map +0 -1
  71. package/esm/tooltip/useTooltip.js +0 -104
  72. package/esm/tooltip/useTooltip.js.map +0 -1
  73. package/esm/tooltip/useTooltipAnchoredPosition.js +0 -115
  74. package/esm/tooltip/useTooltipAnchoredPosition.js.map +0 -1
@@ -1,98 +0,0 @@
1
- import { useState, useRef, useCallback } from 'react';
2
- import { getPositionRelativeToAnchor } from '../popup/getPositionRelativeToAnchor.js';
3
- import { useContextMenu } from '@vuu-ui/vuu-context-menu';
4
-
5
- const usePopupMenu = ({
6
- anchorElement,
7
- "aria-label": ariaLabel = "Popup menu",
8
- id,
9
- menuActionHandler,
10
- menuBuilder,
11
- menuLocation,
12
- menuOptions,
13
- onMenuClose,
14
- onMenuOpen,
15
- popupPlacement,
16
- tabIndex
17
- }) => {
18
- const [menuOpen, _setMenuOpen] = useState(false);
19
- const suppressShowMenuRef = useRef(false);
20
- const rootRef = useRef(null);
21
- const setMenuOpen = useCallback(
22
- (isOpen) => {
23
- _setMenuOpen(isOpen);
24
- if (isOpen) {
25
- onMenuOpen?.();
26
- setTimeout(() => {
27
- const firstOption = document.activeElement?.querySelector(
28
- ".saltMenuItem"
29
- );
30
- firstOption?.focus();
31
- }, 40);
32
- } else {
33
- suppressShowMenuRef.current = false;
34
- }
35
- },
36
- [onMenuOpen]
37
- );
38
- const showContextMenu = useContextMenu(menuBuilder, menuActionHandler);
39
- const handleMenuOpenChange = useCallback(
40
- (isOpen) => {
41
- if (!isOpen) {
42
- setMenuOpen(false);
43
- onMenuClose?.();
44
- }
45
- },
46
- [onMenuClose, setMenuOpen]
47
- );
48
- const showMenu = useCallback(
49
- (e) => {
50
- if (suppressShowMenuRef.current) {
51
- suppressShowMenuRef.current = false;
52
- } else {
53
- suppressShowMenuRef.current = true;
54
- const anchorEl = anchorElement?.current ?? rootRef.current;
55
- if (anchorEl) {
56
- const {
57
- left: x,
58
- top: y
59
- // width,
60
- } = getPositionRelativeToAnchor(anchorEl, popupPlacement, 0, 0);
61
- setMenuOpen(true);
62
- showContextMenu(e, menuLocation, menuOptions, {
63
- // className: menuClassName,
64
- // id: `${id}-menu`,
65
- onOpenChange: handleMenuOpenChange,
66
- x,
67
- y
68
- // style: { width: width ? width - 2 : undefined },
69
- });
70
- }
71
- }
72
- },
73
- [
74
- anchorElement,
75
- popupPlacement,
76
- setMenuOpen,
77
- showContextMenu,
78
- menuLocation,
79
- menuOptions,
80
- handleMenuOpenChange
81
- ]
82
- );
83
- const ariaAttributes = {
84
- "aria-controls": menuOpen ? `${id}-menu` : void 0,
85
- "aria-label": ariaLabel,
86
- "aria-expanded": menuOpen,
87
- "aria-haspopup": "menu"
88
- };
89
- const buttonProps = {
90
- id,
91
- onClick: showMenu,
92
- tabIndex
93
- };
94
- return { ariaAttributes, buttonProps, menuOpen, rootRef };
95
- };
96
-
97
- export { usePopupMenu };
98
- //# sourceMappingURL=usePopupMenu.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePopupMenu.js","sources":["../../../../packages/vuu-popups/src/popup-menu/usePopupMenu.ts"],"sourcesContent":["import {\n AriaAttributes,\n MouseEvent,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { PopupMenuProps } from \"./PopupMenu\";\nimport { getPositionRelativeToAnchor } from \"../popup/getPositionRelativeToAnchor\";\nimport { PopupPlacement } from \"../popup/Popup\";\nimport { useContextMenu } from \"@vuu-ui/vuu-context-menu\";\n\nexport interface PopupMenuHookProps\n extends Pick<\n PopupMenuProps,\n | \"anchorElement\"\n | \"aria-label\"\n | \"menuActionHandler\"\n | \"menuBuilder\"\n | \"menuClassName\"\n | \"menuOptions\"\n | \"onMenuClose\"\n | \"onMenuOpen\"\n > {\n id: string;\n menuLocation: string;\n popupPlacement: PopupPlacement;\n tabIndex: number;\n}\n\nexport const usePopupMenu = ({\n anchorElement,\n \"aria-label\": ariaLabel = \"Popup menu\",\n id,\n menuActionHandler,\n menuBuilder,\n menuLocation,\n menuOptions,\n onMenuClose,\n onMenuOpen,\n popupPlacement,\n tabIndex,\n}: PopupMenuHookProps) => {\n const [menuOpen, _setMenuOpen] = useState(false);\n const suppressShowMenuRef = useRef(false);\n const rootRef = useRef<HTMLButtonElement>(null);\n\n const setMenuOpen = useCallback(\n (isOpen: boolean) => {\n _setMenuOpen(isOpen);\n if (isOpen) {\n onMenuOpen?.();\n setTimeout(() => {\n const firstOption = document.activeElement?.querySelector(\n \".saltMenuItem\",\n ) as HTMLElement;\n firstOption?.focus();\n }, 40);\n } else {\n suppressShowMenuRef.current = false;\n }\n },\n [onMenuOpen],\n );\n\n const showContextMenu = useContextMenu(menuBuilder, menuActionHandler);\n\n const handleMenuOpenChange = useCallback(\n (isOpen: boolean) => {\n if (!isOpen) {\n setMenuOpen(false);\n onMenuClose?.();\n }\n },\n [onMenuClose, setMenuOpen],\n );\n\n const showMenu = useCallback(\n (e: MouseEvent<HTMLElement>) => {\n if (suppressShowMenuRef.current) {\n suppressShowMenuRef.current = false;\n } else {\n suppressShowMenuRef.current = true;\n const anchorEl = anchorElement?.current ?? rootRef.current;\n if (anchorEl) {\n const {\n left: x,\n top: y,\n // width,\n } = getPositionRelativeToAnchor(anchorEl, popupPlacement, 0, 0);\n setMenuOpen(true);\n\n showContextMenu(e, menuLocation, menuOptions, {\n // className: menuClassName,\n // id: `${id}-menu`,\n onOpenChange: handleMenuOpenChange,\n x,\n y,\n // style: { width: width ? width - 2 : undefined },\n });\n }\n }\n },\n [\n anchorElement,\n popupPlacement,\n setMenuOpen,\n showContextMenu,\n menuLocation,\n menuOptions,\n handleMenuOpenChange,\n ],\n );\n\n const ariaAttributes: AriaAttributes = {\n \"aria-controls\": menuOpen ? `${id}-menu` : undefined,\n \"aria-label\": ariaLabel,\n \"aria-expanded\": menuOpen,\n \"aria-haspopup\": \"menu\",\n };\n\n const buttonProps = {\n id,\n onClick: showMenu,\n tabIndex,\n };\n\n return { ariaAttributes, buttonProps, menuOpen, rootRef };\n};\n"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- var portalCss = "/*\nThere is work to do to sort out styling across Portal/Popup/Draggable\n*/\n.vuuPortal {\n position: absolute;\n z-index: 100;\n}\n\n.vuuPortal:not(.vuuPopup) {\n background-color: var(--salt-container-primary-background);\n border-radius:4px;\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n border-color: var(--vuuMenuList-borderColor, var(--salt-container-primary-borderColor));\n border-style: solid;\n border-width: 1px;\n padding: 4px 0;\n}\n\n.vuuPortal:has(.vuuDropdown-popup-component.vuuList-empty){\n display: none;\n}\n\n#vuu-portal-root {\n z-index: 1000;\n}";
2
-
3
- export { portalCss as default };
4
- //# sourceMappingURL=Portal.css.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Portal.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,71 +0,0 @@
1
- import { useThemeAttributes } from '@vuu-ui/vuu-utils';
2
- import { useState, useRef, useLayoutEffect } from 'react';
3
- import { createPortal } from 'react-dom';
4
- import { useComponentCssInjection } from '@salt-ds/styles';
5
- import { useWindow } from '@salt-ds/window';
6
- import portalCss from './Portal.css.js';
7
-
8
- function getContainer(container) {
9
- return typeof container === "function" ? container() : container;
10
- }
11
- const DEFAULT_ID = ["vuu-dialog-portal-root", "vuu-portal-root"];
12
- const getFirstAvailableElementById = (id) => {
13
- if (Array.isArray(id)) {
14
- for (const i of id) {
15
- const element = document.getElementById(i);
16
- if (element) {
17
- return element;
18
- }
19
- }
20
- } else {
21
- return document.getElementById(id);
22
- }
23
- return null;
24
- };
25
- const Portal = ({
26
- children,
27
- container: containerProp = document.body,
28
- id = DEFAULT_ID,
29
- onRender,
30
- open = true,
31
- themeAttributes
32
- }) => {
33
- const targetWindow = useWindow();
34
- useComponentCssInjection({
35
- testId: "vuu-portal",
36
- css: portalCss,
37
- window: targetWindow
38
- });
39
- const [mounted, setMounted] = useState(false);
40
- const portalRef = useRef(null);
41
- const container = getContainer(containerProp) ?? document.body;
42
- const [themeClass, densityClass, dataMode] = useThemeAttributes(themeAttributes);
43
- useLayoutEffect(() => {
44
- const root = getFirstAvailableElementById(id);
45
- if (root) {
46
- portalRef.current = root;
47
- } else {
48
- portalRef.current = document.createElement("div");
49
- portalRef.current.id = typeof id === "string" ? id : id.length > 0 ? id.at(-1) : "vuu-portal-root";
50
- }
51
- const el = portalRef.current;
52
- if (!container.contains(el)) {
53
- container.appendChild(el);
54
- }
55
- el.classList.add(themeClass, densityClass);
56
- el.dataset.mode = dataMode;
57
- setMounted(true);
58
- }, [id, container, themeClass, densityClass, dataMode]);
59
- useLayoutEffect(() => {
60
- requestAnimationFrame(() => {
61
- onRender?.();
62
- });
63
- }, [onRender]);
64
- if (open && mounted && portalRef.current && children) {
65
- return createPortal(children, portalRef.current);
66
- }
67
- return null;
68
- };
69
-
70
- export { Portal };
71
- //# sourceMappingURL=Portal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Portal.js","sources":["../../../../packages/vuu-popups/src/portal/Portal.tsx"],"sourcesContent":["import { ThemeAttributes, useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport portalCss from \"./Portal.css\";\n\nexport interface PortalProps {\n /**\n * The children to render into the `container`.\n */\n children?: ReactNode;\n /**\n * An HTML element, component instance, or function that returns either.\n * The `container` will have the portal children appended to it.\n *\n * By default, it uses the body of the top-level document object,\n * so it's simply `document.body` most of the time.\n */\n container?: Element | (() => Element | null) | null;\n /**\n * Id of element into which portal will be rendered. If this node does not exist on the document,\n * it will be created for you. If more than one value is provided, the first element found will\n * be used.\n */\n id?: string | string[];\n /**\n * Callback invoked immediately after render (in layoutEffect). Can be\n * used to check position vis-a-vis viewport and adjust if out of bounds\n */\n onRender?: () => void;\n /**\n * Allow conditional rendering of this Portal, if false, will render nothing.\n * Defaults to true\n */\n open?: boolean;\n /**\n * ThemeAttributes can be passed in for cases where ContextMenu is\n * rendered via popup-service showPopup, outside the Context hierarchy.\n */\n themeAttributes?: ThemeAttributes;\n}\n\nfunction getContainer(container: PortalProps[\"container\"]) {\n return typeof container === \"function\" ? container() : container;\n}\n\nconst DEFAULT_ID = [\"vuu-dialog-portal-root\", \"vuu-portal-root\"];\n\nconst getFirstAvailableElementById = (id: string | string[]) => {\n if (Array.isArray(id)) {\n for (const i of id) {\n const element = document.getElementById(i);\n if (element) {\n return element;\n }\n }\n } else {\n return document.getElementById(id);\n }\n return null;\n};\n\n/**\n * Portals provide a first-class way to render children into a DOM node\n * that exists outside the DOM hierarchy of the parent component.\n */\nexport const Portal = ({\n children,\n container: containerProp = document.body,\n id = DEFAULT_ID,\n onRender,\n open = true,\n themeAttributes,\n}: PortalProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-portal\",\n css: portalCss,\n window: targetWindow,\n });\n\n const [mounted, setMounted] = useState(false);\n const portalRef = useRef<HTMLElement | null>(null);\n const container = getContainer(containerProp) ?? document.body;\n const [themeClass, densityClass, dataMode] =\n useThemeAttributes(themeAttributes);\n\n useLayoutEffect(() => {\n const root = getFirstAvailableElementById(id);\n if (root) {\n portalRef.current = root;\n } else {\n portalRef.current = document.createElement(\"div\");\n portalRef.current.id =\n typeof id === \"string\"\n ? id\n : id.length > 0\n ? (id.at(-1) as string)\n : \"vuu-portal-root\";\n }\n const el = portalRef.current;\n if (!container.contains(el)) {\n container.appendChild(el);\n }\n el.classList.add(themeClass, densityClass);\n el.dataset.mode = dataMode;\n setMounted(true);\n }, [id, container, themeClass, densityClass, dataMode]);\n\n useLayoutEffect(() => {\n requestAnimationFrame(() => {\n onRender?.();\n });\n }, [onRender]);\n\n if (open && mounted && portalRef.current && children) {\n return createPortal(children, portalRef.current);\n }\n\n return null;\n};\n"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- var tooltipCss = ".vuuTooltip {\n --tooltip-align: flex-start;\n --tooltip-background: var(--salt-actionable-bold-background-hover);\n --tooltip-border: var(--salt-actionable-bold-background-hover);\n --tooltip-color: var(--salt-actionable-bold-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
-
3
- export { tooltipCss as default };
4
- //# sourceMappingURL=Tooltip.css.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Tooltip.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,54 +0,0 @@
1
- import { jsx } from 'react/jsx-runtime';
2
- import { Portal } from '../portal/Portal.js';
3
- import { useTooltipAnchoredPosition } from './useTooltipAnchoredPosition.js';
4
- import cx from 'clsx';
5
- import { useComponentCssInjection } from '@salt-ds/styles';
6
- import { useWindow } from '@salt-ds/window';
7
- import tooltipCss from './Tooltip.css.js';
8
-
9
- const classBase = "vuuTooltip";
10
- const Tooltip = ({
11
- anchorElement,
12
- children,
13
- className,
14
- id,
15
- onMouseEnter,
16
- onMouseLeave,
17
- placement: placementProp,
18
- status,
19
- style: styleProp
20
- }) => {
21
- const targetWindow = useWindow();
22
- useComponentCssInjection({
23
- testId: "vuu-tooltip",
24
- css: tooltipCss,
25
- window: targetWindow
26
- });
27
- const ref = useTooltipAnchoredPosition({
28
- anchorElement,
29
- placement: placementProp
30
- });
31
- return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
32
- "div",
33
- {
34
- className: cx(classBase, className, "vuuHidden", {
35
- [`${classBase}-error`]: status === "error"
36
- }),
37
- id,
38
- ref,
39
- style: { ...styleProp, left: 0, top: 0 },
40
- children: /* @__PURE__ */ jsx(
41
- "span",
42
- {
43
- className: `${classBase}-content`,
44
- onMouseEnter,
45
- onMouseLeave,
46
- children
47
- }
48
- )
49
- }
50
- ) });
51
- };
52
-
53
- export { Tooltip };
54
- //# sourceMappingURL=Tooltip.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../../packages/vuu-popups/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 | null>;\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;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;AACT,CAAoB,KAAA;AAClB,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,aAAA;AAAA,IACR,GAAK,EAAA,UAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,MAAM,0BAA2B,CAAA;AAAA,IACrC,aAAA;AAAA,IACA,SAAW,EAAA;AAAA,GACZ,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;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;AAAA;AAAA;AACH;AAAA,GAEJ,EAAA,CAAA;AAEJ;;;;"}
@@ -1,104 +0,0 @@
1
- import { useId, queryClosest } from '@vuu-ui/vuu-utils';
2
- import { useRef, useState, useCallback } from 'react';
3
-
4
- const useTooltip = ({
5
- anchorQuery = "*",
6
- id: idProp,
7
- placement = ["right", "above", "below"],
8
- tooltipContent
9
- }) => {
10
- const hideTooltipRef = useRef(void 0);
11
- const isHoveringRef = useRef(false);
12
- const anchorElementRef = useRef(null);
13
- const mouseEnterTimerRef = useRef(void 0);
14
- const mouseLeaveTimerRef = useRef(void 0);
15
- const [tooltipProps, setTooltipProps] = useState();
16
- const id = useId(idProp);
17
- const escapeListener = useCallback((evt) => {
18
- if (evt.key === "Escape") {
19
- hideTooltipRef.current?.();
20
- }
21
- }, []);
22
- hideTooltipRef.current = useCallback(() => {
23
- setTooltipProps(void 0);
24
- document.removeEventListener("keydown", escapeListener);
25
- }, [escapeListener]);
26
- const handleMouseEnterTooltip = useCallback(() => {
27
- window.clearTimeout(mouseLeaveTimerRef.current);
28
- }, []);
29
- const handleMouseLeaveTooltip = useCallback(() => {
30
- hideTooltipRef.current?.();
31
- }, []);
32
- const hideTooltip = useCallback((defer = 0) => {
33
- if (mouseEnterTimerRef.current) {
34
- window.clearTimeout(mouseEnterTimerRef.current);
35
- mouseEnterTimerRef.current = void 0;
36
- } else if (hideTooltipRef.current) {
37
- if (defer === 0) {
38
- hideTooltipRef.current();
39
- } else {
40
- mouseLeaveTimerRef.current = window.setTimeout(
41
- hideTooltipRef.current,
42
- defer
43
- );
44
- }
45
- }
46
- }, []);
47
- const showTooltip = useCallback(
48
- (ref = anchorElementRef) => {
49
- const { current: anchorEl } = ref;
50
- if (anchorEl) {
51
- setTooltipProps({
52
- anchorElement: ref,
53
- children: tooltipContent,
54
- id: `${id}-tooltip`,
55
- onMouseEnter: handleMouseEnterTooltip,
56
- onMouseLeave: handleMouseLeaveTooltip,
57
- placement
58
- });
59
- document.addEventListener("keydown", escapeListener);
60
- }
61
- mouseEnterTimerRef.current = void 0;
62
- hideTooltip(isHoveringRef.current ? 3e3 : 1e3);
63
- },
64
- [
65
- escapeListener,
66
- handleMouseEnterTooltip,
67
- handleMouseLeaveTooltip,
68
- hideTooltip,
69
- id,
70
- placement,
71
- tooltipContent
72
- ]
73
- );
74
- const handleMouseEnter = useCallback(
75
- (evt) => {
76
- isHoveringRef.current = true;
77
- const el = queryClosest(evt.target, anchorQuery);
78
- if (el) {
79
- console.log(`el ${el.classList}`);
80
- anchorElementRef.current = el;
81
- mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);
82
- }
83
- },
84
- [anchorQuery, showTooltip]
85
- );
86
- const handleMouseLeave = useCallback(() => {
87
- isHoveringRef.current = false;
88
- hideTooltip(200);
89
- }, [hideTooltip]);
90
- const anchorProps = {
91
- "aria-describedby": `${id}-tooltip`,
92
- onMouseEnter: handleMouseEnter,
93
- onMouseLeave: handleMouseLeave
94
- };
95
- return {
96
- anchorProps,
97
- hideTooltip,
98
- showTooltip,
99
- tooltipProps
100
- };
101
- };
102
-
103
- export { useTooltip };
104
- //# sourceMappingURL=useTooltip.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTooltip.js","sources":["../../../../packages/vuu-popups/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>(undefined);\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>(undefined);\n const mouseLeaveTimerRef = useRef<number | undefined>(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,115 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTooltipAnchoredPosition.js","sources":["../../../../packages/vuu-popups/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 | null>;\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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"}