@linzjs/step-ag-grid 1.4.4 → 1.4.6
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.
- package/dist/index.js +1631 -3040
- package/dist/index.js.map +1 -1
- package/dist/src/components/GridLoadableCell.d.ts +2 -0
- package/dist/src/components/gridForm/GridFormDropDown.d.ts +1 -1
- package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +1 -1
- package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +1 -1
- package/dist/src/react-menu3/components/ControlledMenu.d.ts +2 -0
- package/dist/src/react-menu3/components/FocusableItem.d.ts +9 -0
- package/dist/src/react-menu3/components/Menu.d.ts +16 -0
- package/dist/src/react-menu3/components/MenuButton.d.ts +8 -0
- package/dist/src/react-menu3/components/MenuDivider.d.ts +3 -0
- package/dist/src/react-menu3/components/MenuGroup.d.ts +12 -0
- package/dist/src/react-menu3/components/MenuHeader.d.ts +4 -0
- package/dist/src/react-menu3/components/MenuItem.d.ts +59 -0
- package/dist/src/react-menu3/components/MenuList.d.ts +57 -0
- package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +44 -0
- package/dist/src/react-menu3/components/SubMenu.d.ts +110 -0
- package/dist/src/react-menu3/hooks/index.d.ts +9 -0
- package/dist/src/react-menu3/hooks/useBEM.d.ts +10 -0
- package/dist/src/react-menu3/hooks/useCombinedRef.d.ts +2 -0
- package/dist/src/react-menu3/hooks/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/src/react-menu3/hooks/useItemEffect.d.ts +2 -0
- package/dist/src/react-menu3/hooks/useItemState.d.ts +7 -0
- package/dist/src/react-menu3/hooks/useItems.d.ts +7 -0
- package/dist/src/react-menu3/hooks/useMenuChange.d.ts +2 -0
- package/dist/src/react-menu3/hooks/useMenuState.d.ts +14 -0
- package/dist/src/react-menu3/hooks/useMenuStateAndFocus.d.ts +2 -0
- package/dist/src/react-menu3/index.d.ts +402 -0
- package/dist/src/react-menu3/positionUtils/getPositionHelpers.d.ts +11 -0
- package/dist/src/react-menu3/positionUtils/index.d.ts +3 -0
- package/dist/src/react-menu3/positionUtils/placeArrowHorizontal.d.ts +8 -0
- package/dist/src/react-menu3/positionUtils/placeArrowVertical.d.ts +8 -0
- package/dist/src/react-menu3/positionUtils/placeLeftorRight.d.ts +19 -0
- package/dist/src/react-menu3/positionUtils/placeToporBottom.d.ts +19 -0
- package/dist/src/react-menu3/positionUtils/positionContextMenu.d.ts +13 -0
- package/dist/src/react-menu3/positionUtils/positionMenu.d.ts +26 -0
- package/dist/src/react-menu3/style-utils/index.d.ts +11 -0
- package/dist/src/react-menu3/utils/constants.d.ts +92 -0
- package/dist/src/react-menu3/utils/index.d.ts +4 -0
- package/dist/src/react-menu3/utils/propTypes.d.ts +56 -0
- package/dist/src/react-menu3/utils/utils.d.ts +36 -0
- package/dist/src/react-menu3/utils/withHovering.d.ts +7 -0
- package/dist/src/stories/components/ReactMenu.stories.d.ts +8 -0
- package/dist/step-ag-grid.esm.js +1543 -2951
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +22 -13
- package/src/components/GridLoadableCell.scss +4 -0
- package/src/components/GridLoadableCell.tsx +5 -1
- package/src/components/GridPopoverHook.tsx +4 -50
- package/src/components/gridForm/GridFormDropDown.tsx +3 -3
- package/src/components/gridForm/GridFormMultiSelect.tsx +12 -6
- package/src/components/gridForm/GridFormPopoutMenu.tsx +1 -1
- package/src/components/gridPopoverEdit/GridPopoverMenu.scss +6 -2
- package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +1 -1
- package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +7 -9
- package/src/react-menu3/components/ControlledMenu.tsx +261 -0
- package/src/react-menu3/components/FocusableItem.tsx +75 -0
- package/src/react-menu3/components/Menu.tsx +108 -0
- package/src/react-menu3/components/MenuButton.tsx +34 -0
- package/src/react-menu3/components/MenuDivider.tsx +17 -0
- package/src/react-menu3/components/MenuGroup.tsx +47 -0
- package/src/react-menu3/components/MenuHeader.tsx +17 -0
- package/src/react-menu3/components/MenuItem.tsx +183 -0
- package/src/react-menu3/components/MenuList.tsx +502 -0
- package/src/react-menu3/components/MenuRadioGroup.tsx +72 -0
- package/src/react-menu3/components/SubMenu.tsx +349 -0
- package/src/react-menu3/hooks/index.ts +9 -0
- package/src/react-menu3/hooks/useBEM.ts +33 -0
- package/src/react-menu3/hooks/useCombinedRef.ts +24 -0
- package/src/react-menu3/hooks/useIsomorphicLayoutEffect.ts +15 -0
- package/src/react-menu3/hooks/useItemEffect.ts +23 -0
- package/src/react-menu3/hooks/useItemState.ts +67 -0
- package/src/react-menu3/hooks/useItems.ts +111 -0
- package/src/react-menu3/hooks/useMenuChange.ts +12 -0
- package/src/react-menu3/hooks/useMenuState.ts +42 -0
- package/src/react-menu3/hooks/useMenuStateAndFocus.ts +17 -0
- package/src/react-menu3/index.d.ts +683 -0
- package/src/react-menu3/index.ts +442 -0
- package/src/react-menu3/positionUtils/getPositionHelpers.ts +83 -0
- package/src/react-menu3/positionUtils/index.ts +3 -0
- package/src/react-menu3/positionUtils/placeArrowHorizontal.ts +15 -0
- package/src/react-menu3/positionUtils/placeArrowVertical.ts +15 -0
- package/src/react-menu3/positionUtils/placeLeftorRight.ts +92 -0
- package/src/react-menu3/positionUtils/placeToporBottom.ts +93 -0
- package/src/react-menu3/positionUtils/positionContextMenu.ts +61 -0
- package/src/react-menu3/positionUtils/positionMenu.ts +80 -0
- package/src/react-menu3/style-utils/index.ts +83 -0
- package/src/react-menu3/style-utils.d.ts +110 -0
- package/src/react-menu3/styles/_mixins.scss +11 -0
- package/src/react-menu3/styles/_var.scss +20 -0
- package/src/react-menu3/styles/core.scss +80 -0
- package/src/react-menu3/styles/index.scss +70 -0
- package/src/react-menu3/styles/theme-dark.scss +30 -0
- package/src/react-menu3/styles/transitions/slide.scss +47 -0
- package/src/react-menu3/utils/constants.ts +116 -0
- package/src/react-menu3/utils/index.ts +4 -0
- package/src/react-menu3/utils/propTypes.ts +63 -0
- package/src/react-menu3/utils/utils.ts +88 -0
- package/src/react-menu3/utils/withHovering.tsx +27 -0
- package/src/stories/components/GridPopoutEditDropDown.stories.tsx +1 -3
- package/src/stories/components/ReactMenu.stories.tsx +37 -0
- package/src/utils/util.ts +2 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { placeArrowHorizontal } from "./placeArrowHorizontal";
|
|
2
|
+
import { getPositionHelpers } from "./getPositionHelpers";
|
|
3
|
+
import { MutableRefObject } from "react";
|
|
4
|
+
import { MenuDirection } from "../index";
|
|
5
|
+
|
|
6
|
+
export interface placeToporBottomParams {
|
|
7
|
+
anchorRect: DOMRect;
|
|
8
|
+
placeToporBottomX: number;
|
|
9
|
+
placeTopY: number;
|
|
10
|
+
placeBottomY: number;
|
|
11
|
+
arrowRef: MutableRefObject<HTMLElement | null>;
|
|
12
|
+
arrow?: boolean;
|
|
13
|
+
direction: "left" | "right" | "top" | "bottom";
|
|
14
|
+
position: "auto" | "anchor" | "initial";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const placeToporBottom = (
|
|
18
|
+
props: ReturnType<typeof getPositionHelpers> & placeToporBottomParams,
|
|
19
|
+
): { arrowX?: number | undefined; x: number; y: number; computedDirection: MenuDirection } => {
|
|
20
|
+
const {
|
|
21
|
+
anchorRect,
|
|
22
|
+
containerRect,
|
|
23
|
+
menuRect,
|
|
24
|
+
placeToporBottomX,
|
|
25
|
+
placeTopY,
|
|
26
|
+
placeBottomY,
|
|
27
|
+
getTopOverflow,
|
|
28
|
+
getBottomOverflow,
|
|
29
|
+
confineHorizontally,
|
|
30
|
+
confineVertically,
|
|
31
|
+
arrowRef,
|
|
32
|
+
arrow,
|
|
33
|
+
direction,
|
|
34
|
+
position,
|
|
35
|
+
} = props;
|
|
36
|
+
// make sure invalid direction is treated as 'bottom'
|
|
37
|
+
let computedDirection: MenuDirection = direction === "top" ? "top" : "bottom";
|
|
38
|
+
let x = placeToporBottomX;
|
|
39
|
+
if (position !== "initial") {
|
|
40
|
+
x = confineHorizontally(x);
|
|
41
|
+
if (position === "anchor") {
|
|
42
|
+
// restrict menu to the edge of anchor element
|
|
43
|
+
x = Math.min(x, anchorRect.right - containerRect.left);
|
|
44
|
+
x = Math.max(x, anchorRect.left - containerRect.left - menuRect.width);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let y, topOverflow, bottomOverflow;
|
|
49
|
+
if (computedDirection === "top") {
|
|
50
|
+
y = placeTopY;
|
|
51
|
+
|
|
52
|
+
if (position !== "initial") {
|
|
53
|
+
// if menu overflows to the top,
|
|
54
|
+
// try to reposition it to the bottom of the anchor.
|
|
55
|
+
topOverflow = getTopOverflow(y);
|
|
56
|
+
if (topOverflow < 0) {
|
|
57
|
+
// if menu overflows to the bottom after repositioning,
|
|
58
|
+
// choose a side which has less overflow
|
|
59
|
+
bottomOverflow = getBottomOverflow(placeBottomY);
|
|
60
|
+
if (bottomOverflow <= 0 || -topOverflow > bottomOverflow) {
|
|
61
|
+
y = placeBottomY;
|
|
62
|
+
computedDirection = "bottom";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
// Opposite logic to the 'top' direction above
|
|
68
|
+
y = placeBottomY;
|
|
69
|
+
|
|
70
|
+
if (position !== "initial") {
|
|
71
|
+
bottomOverflow = getBottomOverflow(y);
|
|
72
|
+
if (bottomOverflow > 0) {
|
|
73
|
+
topOverflow = getTopOverflow(placeTopY);
|
|
74
|
+
if (topOverflow >= 0 || -topOverflow < bottomOverflow) {
|
|
75
|
+
y = placeTopY;
|
|
76
|
+
computedDirection = "top";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (position === "auto") y = confineVertically(y);
|
|
83
|
+
const arrowX = arrow
|
|
84
|
+
? placeArrowHorizontal({
|
|
85
|
+
menuX: x,
|
|
86
|
+
arrowRef,
|
|
87
|
+
anchorRect,
|
|
88
|
+
containerRect,
|
|
89
|
+
menuRect,
|
|
90
|
+
})
|
|
91
|
+
: undefined;
|
|
92
|
+
return { arrowX, x, y, computedDirection };
|
|
93
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getPositionHelpers } from "./getPositionHelpers";
|
|
2
|
+
import { MenuDirection } from "../index";
|
|
3
|
+
|
|
4
|
+
export const positionContextMenu = ({
|
|
5
|
+
positionHelpers,
|
|
6
|
+
anchorPoint,
|
|
7
|
+
}: {
|
|
8
|
+
positionHelpers: ReturnType<typeof getPositionHelpers>;
|
|
9
|
+
anchorPoint: { x: number; y: number };
|
|
10
|
+
}): {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
computedDirection: MenuDirection;
|
|
14
|
+
} => {
|
|
15
|
+
const {
|
|
16
|
+
menuRect,
|
|
17
|
+
containerRect,
|
|
18
|
+
getLeftOverflow,
|
|
19
|
+
getRightOverflow,
|
|
20
|
+
getTopOverflow,
|
|
21
|
+
getBottomOverflow,
|
|
22
|
+
confineHorizontally,
|
|
23
|
+
confineVertically,
|
|
24
|
+
} = positionHelpers;
|
|
25
|
+
|
|
26
|
+
let x, y;
|
|
27
|
+
|
|
28
|
+
// position the menu with cursor pointing to its top-left corner
|
|
29
|
+
x = anchorPoint.x - containerRect.left;
|
|
30
|
+
y = anchorPoint.y - containerRect.top;
|
|
31
|
+
|
|
32
|
+
// If menu overflows to the right of viewport,
|
|
33
|
+
// try to reposition it on the left side of cursor.
|
|
34
|
+
// If menu overflows to the left of viewport after repositioning,
|
|
35
|
+
// choose a side which has less overflow
|
|
36
|
+
// and adjust x to have it contained within the viewport.
|
|
37
|
+
const rightOverflow = getRightOverflow(x);
|
|
38
|
+
if (rightOverflow > 0) {
|
|
39
|
+
const adjustedX = x - menuRect.width;
|
|
40
|
+
const leftOverflow = getLeftOverflow(adjustedX);
|
|
41
|
+
if (leftOverflow >= 0 || -leftOverflow < rightOverflow) {
|
|
42
|
+
x = adjustedX;
|
|
43
|
+
}
|
|
44
|
+
x = confineHorizontally(x);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Similar logic to the left and right side above.
|
|
48
|
+
let computedDirection: MenuDirection = "bottom";
|
|
49
|
+
const bottomOverflow = getBottomOverflow(y);
|
|
50
|
+
if (bottomOverflow > 0) {
|
|
51
|
+
const adjustedY = y - menuRect.height;
|
|
52
|
+
const topOverflow = getTopOverflow(adjustedY);
|
|
53
|
+
if (topOverflow >= 0 || -topOverflow < bottomOverflow) {
|
|
54
|
+
y = adjustedY;
|
|
55
|
+
computedDirection = "top";
|
|
56
|
+
}
|
|
57
|
+
y = confineVertically(y);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { x, y, computedDirection };
|
|
61
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { placeLeftorRight } from "./placeLeftorRight";
|
|
2
|
+
import { placeToporBottom } from "./placeToporBottom";
|
|
3
|
+
import { MutableRefObject } from "react";
|
|
4
|
+
import { getPositionHelpers } from "./getPositionHelpers";
|
|
5
|
+
import { MenuDirection } from "../index";
|
|
6
|
+
|
|
7
|
+
interface positionMenuProps {
|
|
8
|
+
offsetX: number;
|
|
9
|
+
offsetY: number;
|
|
10
|
+
arrowRef: MutableRefObject<HTMLDivElement | null>;
|
|
11
|
+
anchorRef: MutableRefObject<HTMLElement | null>;
|
|
12
|
+
arrow?: boolean;
|
|
13
|
+
direction: MenuDirection;
|
|
14
|
+
position: "auto" | "anchor" | "initial";
|
|
15
|
+
align: "start" | "center" | "end";
|
|
16
|
+
positionHelpers: ReturnType<typeof getPositionHelpers>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const positionMenu = (props: positionMenuProps) => {
|
|
20
|
+
const { arrow, align, direction, offsetX, offsetY, position, anchorRef, arrowRef, positionHelpers } = props;
|
|
21
|
+
const { menuRect, containerRect } = positionHelpers;
|
|
22
|
+
|
|
23
|
+
let horizontalOffset = offsetX;
|
|
24
|
+
let verticalOffset = offsetY;
|
|
25
|
+
if (arrow && arrowRef.current) {
|
|
26
|
+
if (direction === "left" || direction === "right") {
|
|
27
|
+
horizontalOffset += arrowRef.current.offsetWidth;
|
|
28
|
+
} else {
|
|
29
|
+
verticalOffset += arrowRef.current.offsetHeight;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const anchorRect = anchorRef.current
|
|
34
|
+
? anchorRef.current.getBoundingClientRect()
|
|
35
|
+
: ({ left: 0, right: 0, top: 200, bottom: 200, width: 200, height: 200 } as DOMRect);
|
|
36
|
+
const placeLeftX = anchorRect.left - containerRect.left - menuRect.width - horizontalOffset;
|
|
37
|
+
const placeRightX = anchorRect.right - containerRect.left + horizontalOffset;
|
|
38
|
+
const placeTopY = anchorRect.top - containerRect.top - menuRect.height - verticalOffset;
|
|
39
|
+
const placeBottomY = anchorRect.bottom - containerRect.top + verticalOffset;
|
|
40
|
+
|
|
41
|
+
let placeToporBottomX, placeLeftorRightY;
|
|
42
|
+
if (align === "end") {
|
|
43
|
+
placeToporBottomX = anchorRect.right - containerRect.left - menuRect.width;
|
|
44
|
+
placeLeftorRightY = anchorRect.bottom - containerRect.top - menuRect.height;
|
|
45
|
+
} else if (align === "center") {
|
|
46
|
+
placeToporBottomX = anchorRect.left - containerRect.left - (menuRect.width - anchorRect.width) / 2;
|
|
47
|
+
placeLeftorRightY = anchorRect.top - containerRect.top - (menuRect.height - anchorRect.height) / 2;
|
|
48
|
+
} else {
|
|
49
|
+
placeToporBottomX = anchorRect.left - containerRect.left;
|
|
50
|
+
placeLeftorRightY = anchorRect.top - containerRect.top;
|
|
51
|
+
}
|
|
52
|
+
placeToporBottomX += horizontalOffset;
|
|
53
|
+
placeLeftorRightY += verticalOffset;
|
|
54
|
+
|
|
55
|
+
const options = {
|
|
56
|
+
...positionHelpers,
|
|
57
|
+
anchorRect,
|
|
58
|
+
placeLeftX,
|
|
59
|
+
placeRightX,
|
|
60
|
+
placeLeftorRightY,
|
|
61
|
+
placeTopY,
|
|
62
|
+
placeBottomY,
|
|
63
|
+
placeToporBottomX,
|
|
64
|
+
arrowRef,
|
|
65
|
+
arrow,
|
|
66
|
+
direction,
|
|
67
|
+
position,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
switch (direction) {
|
|
71
|
+
case "left":
|
|
72
|
+
case "right":
|
|
73
|
+
return placeLeftorRight(options);
|
|
74
|
+
|
|
75
|
+
case "top":
|
|
76
|
+
case "bottom":
|
|
77
|
+
default:
|
|
78
|
+
return placeToporBottom(options);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
menuContainerClass,
|
|
3
|
+
menuButtonClass,
|
|
4
|
+
menuClass,
|
|
5
|
+
menuArrowClass,
|
|
6
|
+
menuItemClass,
|
|
7
|
+
menuDividerClass,
|
|
8
|
+
menuHeaderClass,
|
|
9
|
+
menuGroupClass,
|
|
10
|
+
radioGroupClass,
|
|
11
|
+
subMenuClass,
|
|
12
|
+
} from "../utils";
|
|
13
|
+
|
|
14
|
+
const bem =
|
|
15
|
+
(block: string) =>
|
|
16
|
+
(element?: string) =>
|
|
17
|
+
(modifier?: string): string => {
|
|
18
|
+
let selector = `.${block}`;
|
|
19
|
+
if (element) selector += `__${element}`;
|
|
20
|
+
if (modifier) selector += `--${modifier}`;
|
|
21
|
+
return selector;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const createSelector = (blockElement: (modifier?: string) => string, modifiers: string[] = []) => {
|
|
25
|
+
const selectorObj = {};
|
|
26
|
+
Object.defineProperty(selectorObj, "name", {
|
|
27
|
+
value: blockElement(),
|
|
28
|
+
enumerable: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
modifiers.forEach((modifier) => {
|
|
32
|
+
const selector = modifier.split("-").reduce((prev, curr) => `${prev}${curr[0].toUpperCase()}${curr.slice(1)}`);
|
|
33
|
+
Object.defineProperty(selectorObj, selector, {
|
|
34
|
+
value: blockElement(modifier),
|
|
35
|
+
enumerable: true,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return selectorObj;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const directions = ["dir-left", "dir-right", "dir-top", "dir-bottom"];
|
|
43
|
+
const menuBlock = bem(menuClass);
|
|
44
|
+
const menuSelector = createSelector(menuBlock(), [
|
|
45
|
+
"state-opening",
|
|
46
|
+
"state-open",
|
|
47
|
+
"state-closing",
|
|
48
|
+
"state-closed",
|
|
49
|
+
...directions,
|
|
50
|
+
]);
|
|
51
|
+
const menuArrowSelector = createSelector(menuBlock(menuArrowClass), directions);
|
|
52
|
+
const menuItemSelector = createSelector(menuBlock(menuItemClass), [
|
|
53
|
+
"hover",
|
|
54
|
+
"disabled",
|
|
55
|
+
"anchor",
|
|
56
|
+
"checked",
|
|
57
|
+
"open",
|
|
58
|
+
"submenu",
|
|
59
|
+
"focusable",
|
|
60
|
+
"type-radio",
|
|
61
|
+
"type-checkbox",
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const menuDividerSelector = createSelector(menuBlock(menuDividerClass));
|
|
65
|
+
const menuHeaderSelector = createSelector(menuBlock(menuHeaderClass));
|
|
66
|
+
const menuGroupSelector = createSelector(menuBlock(menuGroupClass));
|
|
67
|
+
const radioGroupSelector = createSelector(menuBlock(radioGroupClass));
|
|
68
|
+
const submenuSelector = createSelector(menuBlock(subMenuClass));
|
|
69
|
+
const menuContainerSelector = createSelector(bem(menuContainerClass)(), ["itemTransition"]);
|
|
70
|
+
const menuButtonSelector = createSelector(bem(menuButtonClass)(), ["open"]);
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
menuContainerSelector,
|
|
74
|
+
menuButtonSelector,
|
|
75
|
+
menuSelector,
|
|
76
|
+
menuArrowSelector,
|
|
77
|
+
menuItemSelector,
|
|
78
|
+
menuDividerSelector,
|
|
79
|
+
menuHeaderSelector,
|
|
80
|
+
menuGroupSelector,
|
|
81
|
+
radioGroupSelector,
|
|
82
|
+
submenuSelector,
|
|
83
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
interface Base {
|
|
2
|
+
/**
|
|
3
|
+
* CSS selector for the element itself
|
|
4
|
+
*/
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Directions {
|
|
9
|
+
/**
|
|
10
|
+
* Menu opens to the left
|
|
11
|
+
*/
|
|
12
|
+
dirLeft: string;
|
|
13
|
+
/**
|
|
14
|
+
* Menu opens to the right
|
|
15
|
+
*/
|
|
16
|
+
dirRight: string;
|
|
17
|
+
/**
|
|
18
|
+
* Menu opens to the top
|
|
19
|
+
*/
|
|
20
|
+
dirTop: string;
|
|
21
|
+
/**
|
|
22
|
+
* Menu opens to the bottom
|
|
23
|
+
*/
|
|
24
|
+
dirBottom: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const menuSelector: Readonly<
|
|
28
|
+
Base &
|
|
29
|
+
Directions & {
|
|
30
|
+
/**
|
|
31
|
+
* Menu transitions from closed to open
|
|
32
|
+
*/
|
|
33
|
+
stateOpening: string;
|
|
34
|
+
/**
|
|
35
|
+
* Menu is open
|
|
36
|
+
*/
|
|
37
|
+
stateOpen: string;
|
|
38
|
+
/**
|
|
39
|
+
* Menu transitions from open to closed
|
|
40
|
+
*/
|
|
41
|
+
stateClosing: string;
|
|
42
|
+
/**
|
|
43
|
+
* Menu is closed
|
|
44
|
+
*/
|
|
45
|
+
stateClosed: string;
|
|
46
|
+
}
|
|
47
|
+
>;
|
|
48
|
+
|
|
49
|
+
export const menuArrowSelector: Readonly<Base & Directions>;
|
|
50
|
+
|
|
51
|
+
export const menuItemSelector: Readonly<
|
|
52
|
+
Base & {
|
|
53
|
+
/**
|
|
54
|
+
* Menu item is hovered and focused
|
|
55
|
+
*/
|
|
56
|
+
hover: string;
|
|
57
|
+
/**
|
|
58
|
+
* Menu item is disabled
|
|
59
|
+
*/
|
|
60
|
+
disabled: string;
|
|
61
|
+
/**
|
|
62
|
+
* Menu item is a URL link (when the `href` prop is set)
|
|
63
|
+
*/
|
|
64
|
+
anchor: string;
|
|
65
|
+
/**
|
|
66
|
+
* Menu item is checked (only for a radio or checkbox item)
|
|
67
|
+
*/
|
|
68
|
+
checked: string;
|
|
69
|
+
/**
|
|
70
|
+
* Present on a submenu item when it's submenu is open
|
|
71
|
+
*/
|
|
72
|
+
open: string;
|
|
73
|
+
/**
|
|
74
|
+
* Present on a submenu item, which is set by the `label` prop on `SubMenu` component
|
|
75
|
+
*/
|
|
76
|
+
submenu: string;
|
|
77
|
+
/**
|
|
78
|
+
* Present on a `FocusableItem`
|
|
79
|
+
*/
|
|
80
|
+
focusable: string;
|
|
81
|
+
/**
|
|
82
|
+
* Menu item is a radio item
|
|
83
|
+
*/
|
|
84
|
+
typeRadio: string;
|
|
85
|
+
/**
|
|
86
|
+
* Menu item is a checkbox item
|
|
87
|
+
*/
|
|
88
|
+
typeCheckbox: string;
|
|
89
|
+
}
|
|
90
|
+
>;
|
|
91
|
+
|
|
92
|
+
export const menuDividerSelector: Readonly<Base>;
|
|
93
|
+
export const menuHeaderSelector: Readonly<Base>;
|
|
94
|
+
export const menuGroupSelector: Readonly<Base>;
|
|
95
|
+
export const radioGroupSelector: Readonly<Base>;
|
|
96
|
+
export const submenuSelector: Readonly<Base>;
|
|
97
|
+
|
|
98
|
+
export const menuContainerSelector: Readonly<
|
|
99
|
+
Base & {
|
|
100
|
+
itemTransition: string;
|
|
101
|
+
}
|
|
102
|
+
>;
|
|
103
|
+
|
|
104
|
+
export const menuButtonSelector: Readonly<
|
|
105
|
+
Base & {
|
|
106
|
+
open: string;
|
|
107
|
+
}
|
|
108
|
+
>;
|
|
109
|
+
|
|
110
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
@use 'sass:math';
|
|
2
|
+
|
|
3
|
+
$color: #212529;
|
|
4
|
+
$color-dark: #cad1d8;
|
|
5
|
+
$color-disabled: #aaa;
|
|
6
|
+
$color-disabled-dark: #666;
|
|
7
|
+
|
|
8
|
+
$header-color: #888;
|
|
9
|
+
$divider-color: rgba(0, 0, 0, 0.12);
|
|
10
|
+
$divider-color-dark: #3a3a3a;
|
|
11
|
+
$border-color: rgba(0, 0, 0, 0.1);
|
|
12
|
+
$border-color-dark: #333;
|
|
13
|
+
|
|
14
|
+
$background-color: #fff;
|
|
15
|
+
$background-color-dark: #22262c;
|
|
16
|
+
$background-color-hover: #ebebeb;
|
|
17
|
+
$background-color-hover-dark: #31363c;
|
|
18
|
+
|
|
19
|
+
$arrow-size: 0.75rem;
|
|
20
|
+
$arrow-pos: -(math.div($arrow-size, 2));
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
@use 'var';
|
|
2
|
+
@use 'mixins';
|
|
3
|
+
|
|
4
|
+
.szh-menu {
|
|
5
|
+
@include mixins.reset-list;
|
|
6
|
+
@include mixins.remove-focus;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
width: max-content;
|
|
9
|
+
z-index: 100;
|
|
10
|
+
border: 1px solid var.$border-color;
|
|
11
|
+
background-color: var.$background-color;
|
|
12
|
+
|
|
13
|
+
&__arrow {
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
width: var.$arrow-size;
|
|
16
|
+
height: var.$arrow-size;
|
|
17
|
+
background-color: var.$background-color;
|
|
18
|
+
border: 1px solid transparent;
|
|
19
|
+
border-left-color: var.$border-color;
|
|
20
|
+
border-top-color: var.$border-color;
|
|
21
|
+
z-index: -1;
|
|
22
|
+
|
|
23
|
+
&--dir-left {
|
|
24
|
+
right: var.$arrow-pos;
|
|
25
|
+
transform: translateY(-50%) rotate(135deg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&--dir-right {
|
|
29
|
+
left: var.$arrow-pos;
|
|
30
|
+
transform: translateY(-50%) rotate(-45deg);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&--dir-top {
|
|
34
|
+
bottom: var.$arrow-pos;
|
|
35
|
+
transform: translateX(-50%) rotate(-135deg);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&--dir-bottom {
|
|
39
|
+
top: var.$arrow-pos;
|
|
40
|
+
transform: translateX(-50%) rotate(45deg);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&__item {
|
|
45
|
+
@include mixins.remove-focus;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
|
|
48
|
+
&--hover {
|
|
49
|
+
background-color: var.$background-color-hover;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&--focusable {
|
|
53
|
+
cursor: default;
|
|
54
|
+
background-color: inherit;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&--disabled {
|
|
58
|
+
cursor: default;
|
|
59
|
+
color: var.$color-disabled;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&__group {
|
|
64
|
+
box-sizing: border-box;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&__radio-group {
|
|
68
|
+
@include mixins.reset-list;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&__divider {
|
|
72
|
+
height: 1px;
|
|
73
|
+
margin: 0.5rem 0;
|
|
74
|
+
background-color: var.$divider-color;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.szh-menu-button {
|
|
79
|
+
box-sizing: border-box;
|
|
80
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
@use 'var';
|
|
2
|
+
@use 'core';
|
|
3
|
+
|
|
4
|
+
.szh-menu {
|
|
5
|
+
user-select: none;
|
|
6
|
+
color: var.$color;
|
|
7
|
+
border: none;
|
|
8
|
+
border-radius: 0.25rem;
|
|
9
|
+
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.133), 0 0.6px 2px rgba(0, 0, 0, 0.1);
|
|
10
|
+
min-width: 10rem;
|
|
11
|
+
padding: 0.5rem 0;
|
|
12
|
+
|
|
13
|
+
&__item {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
position: relative;
|
|
17
|
+
padding: 0.375rem 1.5rem;
|
|
18
|
+
|
|
19
|
+
.szh-menu-container--itemTransition & {
|
|
20
|
+
transition: {
|
|
21
|
+
property: background-color, color;
|
|
22
|
+
duration: 0.15s;
|
|
23
|
+
timing-function: ease-in-out;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&--type-radio {
|
|
28
|
+
padding-left: 2.2rem;
|
|
29
|
+
&::before {
|
|
30
|
+
content: '\25cb';
|
|
31
|
+
position: absolute;
|
|
32
|
+
left: 0.8rem;
|
|
33
|
+
top: 0.55rem;
|
|
34
|
+
font-size: 0.8rem;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&--type-radio#{&}--checked::before {
|
|
39
|
+
content: '\25cf';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&--type-checkbox {
|
|
43
|
+
padding-left: 2.2rem;
|
|
44
|
+
&::before {
|
|
45
|
+
position: absolute;
|
|
46
|
+
left: 0.8rem;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&--type-checkbox#{&}--checked::before {
|
|
51
|
+
content: '\2714';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&__submenu > .szh-menu__item {
|
|
56
|
+
padding-right: 2.5rem;
|
|
57
|
+
&::after {
|
|
58
|
+
content: '\276f';
|
|
59
|
+
position: absolute;
|
|
60
|
+
right: 1rem;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&__header {
|
|
65
|
+
color: var.$header-color;
|
|
66
|
+
font-size: 0.8rem;
|
|
67
|
+
padding: 0.2rem 1.5rem;
|
|
68
|
+
text-transform: uppercase;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
@use 'var';
|
|
2
|
+
|
|
3
|
+
.szh-menu-container--theme-dark .szh-menu {
|
|
4
|
+
color: var.$color-dark;
|
|
5
|
+
background-color: var.$background-color-dark;
|
|
6
|
+
border: 1px solid var.$border-color-dark;
|
|
7
|
+
box-shadow: 0 2px 9px 3px rgba(0, 0, 0, 0.25);
|
|
8
|
+
|
|
9
|
+
&__arrow {
|
|
10
|
+
background-color: var.$background-color-dark;
|
|
11
|
+
border-left-color: var.$border-color-dark;
|
|
12
|
+
border-top-color: var.$border-color-dark;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&__item {
|
|
16
|
+
&--hover {
|
|
17
|
+
background-color: var.$background-color-hover-dark;
|
|
18
|
+
}
|
|
19
|
+
&--focusable {
|
|
20
|
+
background-color: inherit;
|
|
21
|
+
}
|
|
22
|
+
&--disabled {
|
|
23
|
+
color: var.$color-disabled-dark;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&__divider {
|
|
28
|
+
background-color: var.$divider-color-dark;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@use 'sass:list';
|
|
2
|
+
@use 'sass:map';
|
|
3
|
+
|
|
4
|
+
$menu: 'szh-menu';
|
|
5
|
+
$duration: 0.15s;
|
|
6
|
+
$directions: (
|
|
7
|
+
'left': 'X' 1,
|
|
8
|
+
'right': 'X' -1,
|
|
9
|
+
'top': 'Y' 1,
|
|
10
|
+
'bottom': 'Y' -1
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
@mixin animation($name, $dir) {
|
|
14
|
+
.#{$menu}--state-opening.#{$menu}--dir-#{$dir} {
|
|
15
|
+
animation: #{$menu}-show-#{$name}-#{$dir} $duration ease-out;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.#{$menu}--state-closing.#{$menu}--dir-#{$dir} {
|
|
19
|
+
animation: #{$menu}-hide-#{$name}-#{$dir} $duration ease-in forwards;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@mixin slide-start($axis, $sign) {
|
|
24
|
+
opacity: 0;
|
|
25
|
+
transform: translate#{$axis }($sign * 0.75rem);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@each $dir, $value in $directions {
|
|
29
|
+
$axis: list.nth($value, 1);
|
|
30
|
+
$sign: list.nth($value, 2);
|
|
31
|
+
|
|
32
|
+
@keyframes #{$menu}-show-slide-#{$dir} {
|
|
33
|
+
from {
|
|
34
|
+
@include slide-start($axis, $sign);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@keyframes #{$menu}-hide-slide-#{$dir} {
|
|
39
|
+
to {
|
|
40
|
+
@include slide-start($axis, $sign);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@each $dir in map.keys($directions) {
|
|
46
|
+
@include animation('slide', $dir);
|
|
47
|
+
}
|