@vuu-ui/vuu-layout 0.0.27 → 0.5.4

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 (63) hide show
  1. package/LICENSE +201 -0
  2. package/cjs/index.js +7395 -0
  3. package/index.css +952 -0
  4. package/index.css.map +7 -0
  5. package/package.json +12 -13
  6. package/src/chest-of-drawers/Drawer.css +46 -40
  7. package/src/chest-of-drawers/Drawer.tsx +4 -4
  8. package/src/dialog/Dialog.tsx +2 -2
  9. package/src/drag-drop/BoxModel.ts +1 -1
  10. package/src/drag-drop/DropMenu.css +15 -14
  11. package/src/drag-drop/DropMenu.tsx +8 -15
  12. package/src/drag-drop/DropTarget.ts +6 -6
  13. package/src/drag-drop/DropTargetRenderer.css +3 -3
  14. package/src/drag-drop/DropTargetRenderer.tsx +8 -13
  15. package/src/flexbox/Flexbox.tsx +1 -1
  16. package/src/flexbox/FluidGrid.tsx +1 -1
  17. package/src/index.ts +2 -1
  18. package/src/layout-header/Header.css +3 -3
  19. package/src/layout-header/Header.tsx +2 -2
  20. package/src/layout-provider/useLayoutDragDrop.ts +3 -3
  21. package/src/layout-view/View.css +5 -2
  22. package/src/layout-view/View.tsx +1 -1
  23. package/src/layout-view/useViewResize.ts +1 -1
  24. package/src/menu/ContextMenu.css +22 -0
  25. package/src/menu/ContextMenu.jsx +121 -0
  26. package/src/menu/MenuList.css +150 -0
  27. package/src/menu/MenuList.jsx +179 -0
  28. package/src/menu/aim/aim.js +92 -0
  29. package/src/menu/aim/corners.js +114 -0
  30. package/src/menu/aim/point-in-polygon.js +25 -0
  31. package/src/menu/aim/utils.js +19 -0
  32. package/src/menu/context-menu-provider.jsx +135 -0
  33. package/src/menu/index.js +4 -0
  34. package/src/menu/key-code.js +61 -0
  35. package/src/menu/list-dom-utils.js +22 -0
  36. package/src/menu/use-cascade.js +292 -0
  37. package/src/menu/use-click-away.js +22 -0
  38. package/src/menu/use-items-with-ids.js +75 -0
  39. package/src/menu/use-keyboard-navigation.js +162 -0
  40. package/src/menu/utils.js +5 -0
  41. package/src/palette/Palette.css +2 -2
  42. package/src/palette/Palette.tsx +1 -1
  43. package/src/palette/{PaletteUitk.css → PaletteSalt.css} +0 -0
  44. package/src/palette/{PaletteUitk.tsx → PaletteSalt.tsx} +4 -4
  45. package/src/palette/index.ts +1 -1
  46. package/src/popup/index.js +2 -0
  47. package/src/popup/popup-provider.js +0 -0
  48. package/src/popup/popup-service.css +15 -0
  49. package/src/popup/popup-service.js +281 -0
  50. package/src/portal/Portal.jsx +50 -0
  51. package/src/portal/index.ts +3 -0
  52. package/src/portal/render-portal.jsx +68 -0
  53. package/src/portal/utils.js +16 -0
  54. package/src/responsive/breakpoints.ts +22 -8
  55. package/src/stack/Stack.css +3 -3
  56. package/src/stack/Stack.tsx +3 -2
  57. package/src/stack/StackLayout.tsx +1 -1
  58. package/src/tools/devtools-box/layout-configurator.jsx +1 -1
  59. package/src/tools/devtools-tree/layout-tree-viewer.jsx +1 -1
  60. package/src/utils/apply-handlers.js +15 -0
  61. package/README.md +0 -1
  62. package/src/action-buttons/action-buttons.css +0 -12
  63. package/src/action-buttons/action-buttons.tsx +0 -30
@@ -35,11 +35,11 @@ const getDragElement = (
35
35
  ): [HTMLElement, string, number, number] => {
36
36
  const wrapper = document.createElement("div");
37
37
  wrapper.className = "vuuSimpleDraggableWrapper";
38
- // TODO caller needs to supply the uitk classes
38
+ // TODO caller needs to supply the salt classes
39
39
  wrapper.classList.add(
40
40
  "vuuSimpleDraggableWrapper",
41
- "uitk-theme",
42
- "uitk-density-medium"
41
+ "salt-theme",
42
+ "salt-density-medium"
43
43
  );
44
44
  wrapper.dataset.dragging = "true";
45
45
 
@@ -1,8 +1,11 @@
1
1
  .vuuView {
2
- border: var(--vuuView-border, solid 1px var(--uitk-container-borderColor-medium));
2
+ border-color: var(--vuuView-borderColor, var(--salt-container-primary-borderColor));
3
+ border-width: var(--vuuView-borderWidth, 1px);
4
+ border-style: var(--vuuView-borderStyle, none);
5
+
3
6
  display: flex;
4
7
  flex-direction: column;
5
- margin: var(--vuuView-margin, 3px);
8
+ margin: var(--vuuView-margin, 0px);
6
9
  min-height: 50px;
7
10
  min-width: 50px;
8
11
  outline: none;
@@ -1,4 +1,4 @@
1
- import { useForkRef, useIdMemo as useId } from "@heswell/uitk-core";
1
+ import { useForkRef, useIdMemo as useId } from "@salt-ds/core";
2
2
  import cx from "classnames";
3
3
  import React, { ForwardedRef, forwardRef, useMemo, useRef } from "react";
4
4
  import { Header } from "../layout-header/Header";
@@ -1,4 +1,4 @@
1
- import { useResizeObserver, WidthHeight } from "@heswell/uitk-core";
1
+ import { useResizeObserver, WidthHeight } from "@heswell/salt-lab";
2
2
  import { RefObject, useCallback, useRef } from "react";
3
3
 
4
4
  const NO_MEASUREMENT: string[] = [];
@@ -0,0 +1,22 @@
1
+ .hwPopupContainer.top-bottom-right-right .popup-menu {
2
+ left: auto;
3
+ right: 0;
4
+ }
5
+
6
+ .popup-menu .menu-item.showing > button,
7
+ .popup-menu .menu-item > button:focus,
8
+ .popup-menu .menu-item > button:hover {
9
+ text-decoration: none;
10
+ color: rgb(0, 0, 0);
11
+ background-color: rgb(220, 220, 220);
12
+ }
13
+
14
+ .popup-menu .menu-item.disabled > button {
15
+ clear: both;
16
+ font-weight: normal;
17
+ line-height: 1.5;
18
+ color: rgb(120, 120, 120);
19
+ white-space: nowrap;
20
+ text-decoration: none;
21
+ cursor: default;
22
+ }
@@ -0,0 +1,121 @@
1
+ import { useIdMemo as useId } from "@salt-ds/core";
2
+ import { useCallback, useRef } from "react";
3
+ import { Portal } from "../portal";
4
+
5
+ import { getItemId, getMenuId, useCascade } from "./use-cascade";
6
+ import { useItemsWithIds } from "./use-items-with-ids";
7
+
8
+ import MenuList from "./MenuList";
9
+
10
+ import "./ContextMenu.css";
11
+ import { useClickAway } from "./use-click-away";
12
+
13
+ const ContextMenu = ({
14
+ activatedWithKeyboard = false,
15
+ children: childrenProp,
16
+ id: idProp,
17
+ onClose = () => undefined,
18
+ position = { x: 0, y: 0 },
19
+ source: sourceProp,
20
+ style,
21
+ }) => {
22
+ const id = useId(idProp);
23
+ const closeMenuRef = useRef(null);
24
+ const [menus, actions] = useItemsWithIds(sourceProp, childrenProp);
25
+ const navigatingWithKeyboard = useRef(activatedWithKeyboard);
26
+ const handleMouseEnterItem = useCallback(() => {
27
+ navigatingWithKeyboard.current = false;
28
+ }, []);
29
+
30
+ const handleActivate = useCallback(
31
+ (menuId) => {
32
+ const { action, options } = actions[menuId];
33
+ closeMenuRef.current("root");
34
+ onClose(action, options);
35
+ },
36
+ [actions, onClose]
37
+ );
38
+
39
+ const { closeMenu, listItemProps, openMenu, openMenus, handleRender } =
40
+ useCascade({
41
+ id,
42
+ onActivate: handleActivate,
43
+ onMouseEnterItem: handleMouseEnterItem,
44
+ position,
45
+ });
46
+ closeMenuRef.current = closeMenu;
47
+
48
+ console.log({ openMenus });
49
+
50
+ const handleClose = useCallback(() => {
51
+ closeMenu();
52
+ onClose();
53
+ }, [closeMenu, onClose]);
54
+
55
+ useClickAway({
56
+ containerClassName: "hwMenuList",
57
+ onClose: handleClose,
58
+ isOpen: openMenus.length > 0,
59
+ });
60
+
61
+ const handleOpenMenu = (id) => {
62
+ const itemId = getItemId(id);
63
+ const menuId = getMenuId(itemId);
64
+ navigatingWithKeyboard.current = true;
65
+ openMenu(menuId, itemId);
66
+ };
67
+ const handleCloseMenu = () => {
68
+ navigatingWithKeyboard.current = true;
69
+ closeMenu();
70
+ };
71
+
72
+ const handleHighlightMenuItem = () => {
73
+ // console.log(`highlight ${idx}`);
74
+ };
75
+
76
+ const lastMenu = openMenus.length - 1;
77
+
78
+ const getChildMenuIndex = (i) => {
79
+ if (i >= lastMenu) {
80
+ return -1;
81
+ } else {
82
+ const { id: menuId } = openMenus[i + 1];
83
+ const pos = menuId.lastIndexOf(".");
84
+ const idx =
85
+ pos === -1 ? parseInt(menuId, 10) : parseInt(menuId.slice(-pos), 10);
86
+ return idx;
87
+ }
88
+ };
89
+
90
+ return (
91
+ <>
92
+ {openMenus.map(({ id: menuId, left, top }, i) => {
93
+ const childMenuIndex = getChildMenuIndex(i);
94
+
95
+ return (
96
+ <Portal key={i} x={left} y={top} onRender={handleRender}>
97
+ <MenuList
98
+ activatedByKeyboard={navigatingWithKeyboard.current}
99
+ childMenuShowing={childMenuIndex}
100
+ id={id}
101
+ menuId={menuId}
102
+ isRoot={i === 0}
103
+ key={i}
104
+ listItemProps={listItemProps}
105
+ onActivate={handleActivate}
106
+ onHighlightMenuItem={handleHighlightMenuItem}
107
+ onCloseMenu={handleCloseMenu}
108
+ onOpenMenu={handleOpenMenu}
109
+ style={style}
110
+ >
111
+ {menus[menuId]}
112
+ </MenuList>
113
+ </Portal>
114
+ );
115
+ })}
116
+ </>
117
+ );
118
+ };
119
+
120
+ ContextMenu.displayName = "ContextMenu";
121
+ export default ContextMenu;
@@ -0,0 +1,150 @@
1
+ .hwMenuList {
2
+ --context-menu-color: #161616;
3
+ --context-menu-padding: var(--hw-list-item-padding, 0 6px);
4
+ --context-menu-shadow: var(--hw-dialog-shadow, 0 6px 12px rgba(0, 0, 0, 0.175));
5
+ --focus-visible-border-color: var(--hw-focus-visible-border-color, rgb(141, 154, 179));
6
+ --context-menu-highlight-bg: #a4d5f4;
7
+ --context-menu-blur-focus-bg: #e0e4e9;
8
+ --menu-item-height: var(--hw-list-item-height, 24px);
9
+ --menu-item-icon-color: black;
10
+ --menu-item-twisty-color: black;
11
+ --menu-item-twisty-content: '';
12
+ --menu-item-twisty-top: 50%;
13
+ --menu-item-twisty-left: auto;
14
+ --menu-item-twisty-right: 0px;
15
+ --menu-icon-size: 12px;
16
+
17
+ background-clip: padding-box;
18
+ background-color: white;
19
+ border-radius: 4px;
20
+ border: solid 1px rgba(0, 0, 0, 0.15);
21
+ box-shadow: var(--context-menu-shadow);
22
+ font-size: 13px;
23
+ list-style: none;
24
+ margin: 2px 0 0;
25
+ outline: 0;
26
+ padding: 0;
27
+ position: absolute;
28
+ }
29
+
30
+ .hwMenuItem {
31
+ align-items: center;
32
+ color: var(--context-menu-color);
33
+ display: flex;
34
+ gap: 6px;
35
+ height: var(--menu-item-height);
36
+ padding: var(--context-menu-padding);
37
+ padding-right: 24px;
38
+ position: relative;
39
+ white-space: nowrap;
40
+ }
41
+
42
+ .hwIconContainer {
43
+ display: inline-block;
44
+ flex: 12px 0 0;
45
+ height: var(--menu-icon-size);
46
+ mask-repeat: no-repeat;
47
+ width: var(--menu-icon-size);
48
+ }
49
+
50
+ [data-icon='filter'] {
51
+ --menu-icon-size: 12px;
52
+ --menu-icon: var(--svg-filter);
53
+ }
54
+
55
+ [data-icon='filter'] {
56
+ --menu-icon: var(--svg-filter);
57
+ }
58
+
59
+ [data-icon='sort'] {
60
+ --menu-icon: var(--svg-sort-order-down);
61
+ }
62
+
63
+ [data-icon='sorted-asc'] {
64
+ --menu-icon: var(--svg-sorted-asc);
65
+ }
66
+
67
+ [data-icon='sorted-dsc'] {
68
+ --menu-icon: var(--svg-sorted-dsc);
69
+ }
70
+
71
+ [data-icon] > .hwIconContainer {
72
+ background-color: var(--menu-item-icon-color);
73
+ -webkit-mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size);
74
+ mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size);
75
+ }
76
+
77
+ .hwMenuItem[aria-expanded='true'] {
78
+ background-color: var(--context-menu-blur-focus-bg);
79
+ }
80
+
81
+ .hwMenuItem-separator {
82
+ border-top: solid 1px var(--context-menu-blur-focus-bg);
83
+ }
84
+
85
+ .hwMenuItem[aria-haspopup='true']:after {
86
+ content: var(--menu-item-twisty-content);
87
+ -webkit-mask: var(--svg-chevron-right) center center/12px 12px;
88
+ mask: var(--svg-chevron-down) center center/12px 12px;
89
+ mask-repeat: no-repeat;
90
+ background-color: var(--menu-item-twisty-color);
91
+ height: 16px;
92
+ left: var(--menu-item-twisty-left);
93
+ right: var(--menu-item-twisty-right);
94
+ margin-top: -8px;
95
+ position: absolute;
96
+ top: var(--menu-item-twisty-top);
97
+ transition: transform 0.3s;
98
+ width: 16px;
99
+ }
100
+
101
+ .hwMenuItem[data-highlighted] {
102
+ background-color: var(--context-menu-highlight-bg);
103
+ }
104
+
105
+ .hwMenuItem:hover {
106
+ background-color: var(--context-menu-highlight-bg);
107
+ cursor: default;
108
+ }
109
+
110
+ .hwMenuList-childMenuShowing .hwMenuItem[data-highlighted] {
111
+ background-color: var(--context-menu-blur-focus-bg);
112
+ }
113
+
114
+ .hwMenuItem.focusVisible:before {
115
+ content: '';
116
+ position: absolute;
117
+ top: 0;
118
+ left: 0;
119
+ right: 0;
120
+ bottom: 0px;
121
+ border: dotted var(--focus-visible-border-color) 2px;
122
+ }
123
+
124
+ .hwPopupContainer.top-bottom-right-right .popup-menu {
125
+ left: auto;
126
+ right: 0;
127
+ }
128
+
129
+ .popup-menu .menu-item.showing > button,
130
+ .popup-menu .menu-item > button:focus,
131
+ .popup-menu .menu-item > button:hover {
132
+ text-decoration: none;
133
+ color: rgb(0, 0, 0);
134
+ background-color: rgb(220, 220, 220);
135
+ }
136
+
137
+ .hwMenuItem-button:active,
138
+ .hwMenuItem-button:hover {
139
+ outline: 0;
140
+ }
141
+
142
+ .popup-menu .menu-item.disabled > button {
143
+ clear: both;
144
+ font-weight: normal;
145
+ line-height: 1.5;
146
+ color: rgb(120, 120, 120);
147
+ white-space: nowrap;
148
+ text-decoration: none;
149
+ cursor: default;
150
+ }
@@ -0,0 +1,179 @@
1
+ import React, { useLayoutEffect, useMemo, useRef } from "react";
2
+ import cx from "classnames";
3
+ import { useIdMemo as useId } from "@salt-ds/core";
4
+ import { useKeyboardNavigation } from "./use-keyboard-navigation";
5
+ import { isMenuItemGroup } from "./use-items-with-ids";
6
+
7
+ import "./MenuList.css";
8
+
9
+ const classBase = "hwMenuList";
10
+
11
+ export const Separator = () => <li className="hwMenuItem-divider" />;
12
+
13
+ // Purely used as markers, props will be extracted
14
+ export const MenuItemGroup = () => null;
15
+ // eslint-disable-next-line no-unused-vars
16
+ export const MenuItem = ({ children, idx, ...props }) => {
17
+ return <div {...props}>{children}</div>;
18
+ };
19
+
20
+ const hasIcon = (child) => child.props["data-icon"];
21
+
22
+ const MenuList = ({
23
+ activatedByKeyboard,
24
+ childMenuShowing = -1,
25
+ children,
26
+ highlightedIdx: highlightedIdxProp,
27
+ id: idProp,
28
+ isRoot,
29
+ listItemProps,
30
+ menuId,
31
+ onHighlightMenuItem,
32
+ onActivate,
33
+ onCloseMenu,
34
+ onOpenMenu,
35
+ ...props
36
+ }) => {
37
+ const id = useId(idProp);
38
+ const root = useRef(null);
39
+
40
+ // The id generation be,ongs in useIttemsWithIds
41
+ const mapIdxToId = useMemo(() => new Map(), []);
42
+
43
+ const handleOpenMenu = (idx) => {
44
+ const el = root.current.querySelector(`:scope > [data-idx='${idx}']`);
45
+ onOpenMenu(el.id);
46
+ };
47
+
48
+ const handleActivate = (idx) => {
49
+ const el = root.current.querySelector(`:scope > [data-idx='${idx}']`);
50
+ onActivate(el.id);
51
+ };
52
+
53
+ const { focusVisible, highlightedIdx, listProps } = useKeyboardNavigation({
54
+ count: children.length,
55
+ highlightedIdx: highlightedIdxProp,
56
+ onActivate: handleActivate,
57
+ onHighlight: onHighlightMenuItem,
58
+ onOpenMenu: handleOpenMenu,
59
+ onCloseMenu,
60
+ id,
61
+ });
62
+
63
+ const appliedFocusVisible = childMenuShowing == -1 ? focusVisible : -1;
64
+
65
+ useLayoutEffect(() => {
66
+ if (childMenuShowing === -1 && activatedByKeyboard) {
67
+ root.current.focus();
68
+ }
69
+ }, [activatedByKeyboard, childMenuShowing]);
70
+
71
+ const getActiveDescendant = () =>
72
+ highlightedIdx === undefined || highlightedIdx === -1
73
+ ? undefined
74
+ : mapIdxToId.get(highlightedIdx);
75
+
76
+ return (
77
+ <div
78
+ {...props}
79
+ {...listProps}
80
+ aria-activedescendant={getActiveDescendant()}
81
+ className={cx(classBase, {
82
+ [`${classBase}-childMenuShowing`]: childMenuShowing !== -1,
83
+ })}
84
+ data-root={isRoot || undefined}
85
+ id={`${id}-${menuId}`}
86
+ ref={root}
87
+ role="menu"
88
+ tabIndex={0}
89
+ >
90
+ {renderContent()}
91
+ </div>
92
+ );
93
+
94
+ function renderContent() {
95
+ const propsCommonToAllListItems = {
96
+ ...listItemProps,
97
+ role: "menuitem",
98
+ };
99
+
100
+ const maybeIcon = (children, withIcon) =>
101
+ withIcon
102
+ ? [<span className="hwIconContainer" key="icon" />].concat(children)
103
+ : children;
104
+
105
+ function addClonedChild(list, child, idx, withIcon) {
106
+ const {
107
+ children,
108
+ className,
109
+ id: itemId,
110
+ hasSeparator,
111
+ label,
112
+ ...props
113
+ } = child.props;
114
+ const hasSubMenu = isMenuItemGroup(child);
115
+ const subMenuShowing = hasSubMenu && childMenuShowing === idx;
116
+ const ariaControls = subMenuShowing ? `${id}-${itemId}` : undefined;
117
+
118
+ list.push(
119
+ <MenuItem
120
+ {...props}
121
+ {...propsCommonToAllListItems}
122
+ {...getMenuItemProps(
123
+ `${id}-${menuId}`,
124
+ itemId,
125
+ idx,
126
+ child.key,
127
+ highlightedIdx,
128
+ appliedFocusVisible,
129
+ className,
130
+ hasSeparator
131
+ )}
132
+ aria-controls={ariaControls}
133
+ aria-haspopup={hasSubMenu || undefined}
134
+ aria-expanded={subMenuShowing || undefined}
135
+ >
136
+ {hasSubMenu
137
+ ? maybeIcon(label, withIcon)
138
+ : maybeIcon(children, withIcon)}
139
+ </MenuItem>
140
+ );
141
+ // mapIdxToId.set(idx, itemId);
142
+ }
143
+
144
+ const listItems = [];
145
+
146
+ if (children && children.length > 0) {
147
+ const withIcon = children.some(hasIcon);
148
+
149
+ children.forEach((child, idx) => {
150
+ addClonedChild(listItems, child, idx, withIcon);
151
+ });
152
+ }
153
+
154
+ return listItems;
155
+ }
156
+ };
157
+
158
+ const getMenuItemProps = (
159
+ baseId,
160
+ itemId,
161
+ idx,
162
+ key,
163
+ highlightedIdx,
164
+ focusVisible,
165
+ className,
166
+ hasSeparator
167
+ ) => ({
168
+ id: `${baseId}-${itemId}`,
169
+ key: key ?? idx,
170
+ "data-idx": idx,
171
+ "data-highlighted": idx === highlightedIdx || undefined,
172
+ className: cx("hwMenuItem", className, {
173
+ "hwMenuItem-separator": hasSeparator,
174
+ focusVisible: focusVisible === idx,
175
+ }),
176
+ });
177
+
178
+ MenuList.displayName = "MenuList";
179
+ export default MenuList;
@@ -0,0 +1,92 @@
1
+ import findCorners, { boundaries } from './corners';
2
+ import pointInPolygon from './point-in-polygon';
3
+
4
+ export function distance(source, target) {
5
+ const a = source.x - target.x;
6
+ const b = source.y - target.y;
7
+ return Math.sqrt(a * a + b * b);
8
+ }
9
+
10
+ export function side(corners) {
11
+ if (corners[0] === 'top-right' && corners[1] === 'bottom-right') return 'right';
12
+ else if (corners[0] === 'top-left' && corners[1] === 'bottom-right') return 'top-right';
13
+ else if (corners[0] === 'top-left' && corners[1] === 'top-right') return 'top';
14
+ else if (corners[0] === 'bottom-left' && corners[1] === 'top-right') return 'top-left';
15
+ else if (corners[0] === 'bottom-left' && corners[1] === 'top-left') return 'left';
16
+ else if (corners[0] === 'bottom-right' && corners[1] === 'top-left') return 'bottom-left';
17
+ else if (corners[0] === 'bottom-right' && corners[1] === 'bottom-left') return 'bottom';
18
+ else if (corners[0] === 'top-right' && corners[1] === 'bottom-left') return 'bottom-right';
19
+ }
20
+
21
+ export function bullseye(corners, boundaries, mousePosition) {
22
+ switch (side(corners)) {
23
+ case 'right':
24
+ return {
25
+ x: boundaries[0].x,
26
+ y: mousePosition.y
27
+ };
28
+ case 'top-right':
29
+ return {
30
+ x: boundaries[1].x,
31
+ y: boundaries[0].y
32
+ };
33
+ case 'top':
34
+ return {
35
+ x: mousePosition.x,
36
+ y: boundaries[0].y
37
+ };
38
+ case 'top-left':
39
+ return {
40
+ x: boundaries[0].x,
41
+ y: boundaries[1].y
42
+ };
43
+ case 'left':
44
+ return {
45
+ x: boundaries[0].x,
46
+ y: mousePosition.y
47
+ };
48
+ case 'bottom-left':
49
+ return {
50
+ x: boundaries[1].x,
51
+ y: boundaries[0].y
52
+ };
53
+ case 'bottom':
54
+ return {
55
+ x: mousePosition.x,
56
+ y: boundaries[0].y
57
+ };
58
+ case 'bottom-right':
59
+ return {
60
+ x: boundaries[0].x,
61
+ y: boundaries[1].y
62
+ };
63
+ }
64
+ }
65
+
66
+ function formatPoints(points) {
67
+ const finalPoints = [];
68
+ for (let i = 0, len = points.length; i < len; ++i) {
69
+ finalPoints.push([points[i].x, points[i].y]);
70
+ }
71
+ return finalPoints;
72
+ }
73
+
74
+ export function aiming(e, mousePosition, prevMousePosition, target, alreadyAiming) {
75
+ if (!prevMousePosition) return false;
76
+ else if (
77
+ !alreadyAiming &&
78
+ mousePosition.x === prevMousePosition.x &&
79
+ mousePosition.y === prevMousePosition.y
80
+ ) {
81
+ return false;
82
+ }
83
+
84
+ const corners = findCorners(e, target);
85
+ const bound = boundaries(corners, prevMousePosition, target);
86
+
87
+ if (pointInPolygon([mousePosition.x, mousePosition.y], formatPoints(bound))) {
88
+ const dist = Math.round(distance(mousePosition, bullseye(corners, bound, mousePosition)));
89
+ return Math.max(dist, 1);
90
+ }
91
+ return false;
92
+ }