no-frills-ui 0.0.14-alpha.4 → 0.0.14-alpha.5
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 +1335 -493
- package/dist/index.js.map +1 -1
- package/lib-esm/components/Accordion/AccordionStep.d.ts.map +1 -1
- package/lib-esm/components/Accordion/AccordionStep.js +11 -29
- package/lib-esm/components/Accordion/AccordionStep.js.map +1 -1
- package/lib-esm/components/Badge/Badge.js +7 -7
- package/lib-esm/components/Badge/Badge.js.map +1 -1
- package/lib-esm/components/Button/ActionButton.d.ts.map +1 -1
- package/lib-esm/components/Button/ActionButton.js +12 -11
- package/lib-esm/components/Button/ActionButton.js.map +1 -1
- package/lib-esm/components/Button/Button.d.ts.map +1 -1
- package/lib-esm/components/Button/Button.js +14 -13
- package/lib-esm/components/Button/Button.js.map +1 -1
- package/lib-esm/components/Button/IconButton.d.ts.map +1 -1
- package/lib-esm/components/Button/IconButton.js +15 -14
- package/lib-esm/components/Button/IconButton.js.map +1 -1
- package/lib-esm/components/Button/LinkButton.d.ts.map +1 -1
- package/lib-esm/components/Button/LinkButton.js +7 -6
- package/lib-esm/components/Button/LinkButton.js.map +1 -1
- package/lib-esm/components/Button/RaisedButton.d.ts.map +1 -1
- package/lib-esm/components/Button/RaisedButton.js +15 -14
- package/lib-esm/components/Button/RaisedButton.js.map +1 -1
- package/lib-esm/components/Card/Card.d.ts.map +1 -1
- package/lib-esm/components/Card/Card.js +4 -4
- package/lib-esm/components/Card/Card.js.map +1 -1
- package/lib-esm/components/Chip/Chip.js +8 -8
- package/lib-esm/components/Chip/Chip.js.map +1 -1
- package/lib-esm/components/ChipInput/ChipInput.js +20 -20
- package/lib-esm/components/ChipInput/ChipInput.js.map +1 -1
- package/lib-esm/components/Dialog/AlertDialog.d.ts.map +1 -1
- package/lib-esm/components/Dialog/AlertDialog.js +4 -1
- package/lib-esm/components/Dialog/AlertDialog.js.map +1 -1
- package/lib-esm/components/Dialog/Dialog.d.ts +26 -1
- package/lib-esm/components/Dialog/Dialog.d.ts.map +1 -1
- package/lib-esm/components/Dialog/Dialog.js +84 -1
- package/lib-esm/components/Dialog/Dialog.js.map +1 -1
- package/lib-esm/components/DragAndDrop/DragItem.js +8 -8
- package/lib-esm/components/DragAndDrop/DragItem.js.map +1 -1
- package/lib-esm/components/Drawer/Drawer.d.ts +76 -1
- package/lib-esm/components/Drawer/Drawer.d.ts.map +1 -1
- package/lib-esm/components/Drawer/Drawer.js +158 -24
- package/lib-esm/components/Drawer/Drawer.js.map +1 -1
- package/lib-esm/components/Groups/Group.d.ts.map +1 -1
- package/lib-esm/components/Groups/Group.js +10 -8
- package/lib-esm/components/Groups/Group.js.map +1 -1
- package/lib-esm/components/Groups/GroupLabel.d.ts.map +1 -1
- package/lib-esm/components/Groups/GroupLabel.js +3 -3
- package/lib-esm/components/Groups/GroupLabel.js.map +1 -1
- package/lib-esm/components/Input/Checkbox.d.ts.map +1 -1
- package/lib-esm/components/Input/Checkbox.js +63 -58
- package/lib-esm/components/Input/Checkbox.js.map +1 -1
- package/lib-esm/components/Input/Dropdown.d.ts +8 -0
- package/lib-esm/components/Input/Dropdown.d.ts.map +1 -1
- package/lib-esm/components/Input/Dropdown.js +54 -31
- package/lib-esm/components/Input/Dropdown.js.map +1 -1
- package/lib-esm/components/Input/Input.d.ts.map +1 -1
- package/lib-esm/components/Input/Input.js +27 -21
- package/lib-esm/components/Input/Input.js.map +1 -1
- package/lib-esm/components/Input/Radio.d.ts.map +1 -1
- package/lib-esm/components/Input/Radio.js +58 -42
- package/lib-esm/components/Input/Radio.js.map +1 -1
- package/lib-esm/components/Input/RadioButton.d.ts.map +1 -1
- package/lib-esm/components/Input/RadioButton.js +12 -12
- package/lib-esm/components/Input/RadioButton.js.map +1 -1
- package/lib-esm/components/Input/Select.d.ts.map +1 -1
- package/lib-esm/components/Input/Select.js +27 -21
- package/lib-esm/components/Input/Select.js.map +1 -1
- package/lib-esm/components/Input/TextArea.d.ts.map +1 -1
- package/lib-esm/components/Input/TextArea.js +27 -21
- package/lib-esm/components/Input/TextArea.js.map +1 -1
- package/lib-esm/components/Input/Toggle.d.ts.map +1 -1
- package/lib-esm/components/Input/Toggle.js +17 -14
- package/lib-esm/components/Input/Toggle.js.map +1 -1
- package/lib-esm/components/Menu/Menu.d.ts +13 -1
- package/lib-esm/components/Menu/Menu.d.ts.map +1 -1
- package/lib-esm/components/Menu/Menu.js +98 -3
- package/lib-esm/components/Menu/Menu.js.map +1 -1
- package/lib-esm/components/Menu/MenuItem.d.ts +6 -3
- package/lib-esm/components/Menu/MenuItem.d.ts.map +1 -1
- package/lib-esm/components/Menu/MenuItem.js +10 -10
- package/lib-esm/components/Menu/MenuItem.js.map +1 -1
- package/lib-esm/components/Modal/Modal.d.ts +70 -1
- package/lib-esm/components/Modal/Modal.d.ts.map +1 -1
- package/lib-esm/components/Modal/Modal.js +145 -11
- package/lib-esm/components/Modal/Modal.js.map +1 -1
- package/lib-esm/components/Notification/Notification.d.ts +3 -1
- package/lib-esm/components/Notification/Notification.d.ts.map +1 -1
- package/lib-esm/components/Notification/Notification.js +4 -2
- package/lib-esm/components/Notification/Notification.js.map +1 -1
- package/lib-esm/components/Notification/NotificationManager.d.ts +11 -1
- package/lib-esm/components/Notification/NotificationManager.d.ts.map +1 -1
- package/lib-esm/components/Notification/NotificationManager.js +43 -8
- package/lib-esm/components/Notification/NotificationManager.js.map +1 -1
- package/lib-esm/components/Notification/style.d.ts +4 -0
- package/lib-esm/components/Notification/style.d.ts.map +1 -1
- package/lib-esm/components/Notification/style.js +30 -15
- package/lib-esm/components/Notification/style.js.map +1 -1
- package/lib-esm/components/Notification/types.d.ts +2 -0
- package/lib-esm/components/Notification/types.d.ts.map +1 -1
- package/lib-esm/components/Notification/types.js.map +1 -1
- package/lib-esm/components/Popover/Popover.d.ts.map +1 -1
- package/lib-esm/components/Popover/Popover.js +17 -2
- package/lib-esm/components/Popover/Popover.js.map +1 -1
- package/lib-esm/components/Spinner/Spinner.d.ts +3 -0
- package/lib-esm/components/Spinner/Spinner.d.ts.map +1 -1
- package/lib-esm/components/Spinner/Spinner.js +19 -4
- package/lib-esm/components/Spinner/Spinner.js.map +1 -1
- package/lib-esm/components/Stepper/Stepper.d.ts.map +1 -1
- package/lib-esm/components/Stepper/Stepper.js +29 -10
- package/lib-esm/components/Stepper/Stepper.js.map +1 -1
- package/lib-esm/components/Tabs/Tabs.d.ts.map +1 -1
- package/lib-esm/components/Tabs/Tabs.js +45 -12
- package/lib-esm/components/Tabs/Tabs.js.map +1 -1
- package/lib-esm/components/Toast/Toast.d.ts +25 -4
- package/lib-esm/components/Toast/Toast.d.ts.map +1 -1
- package/lib-esm/components/Toast/Toast.js +114 -18
- package/lib-esm/components/Toast/Toast.js.map +1 -1
- package/lib-esm/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/lib-esm/components/Tooltip/Tooltip.js +16 -5
- package/lib-esm/components/Tooltip/Tooltip.js.map +1 -1
- package/lib-esm/shared/LayerManager.d.ts.map +1 -1
- package/lib-esm/shared/LayerManager.js +63 -1
- package/lib-esm/shared/LayerManager.js.map +1 -1
- package/lib-esm/shared/constants.d.ts +58 -27
- package/lib-esm/shared/constants.d.ts.map +1 -1
- package/lib-esm/shared/constants.js +88 -25
- package/lib-esm/shared/constants.js.map +1 -1
- package/lib-esm/shared/styles.d.ts +1 -1
- package/lib-esm/shared/styles.d.ts.map +1 -1
- package/lib-esm/shared/styles.js +5 -3
- package/lib-esm/shared/styles.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import styled from '@emotion/styled';
|
|
4
|
-
import
|
|
4
|
+
import { getThemeValue, THEME_NAME } from '../../shared/constants';
|
|
5
5
|
const Switch = styled.label `
|
|
6
6
|
position: relative;
|
|
7
7
|
display: inline-flex;
|
|
8
8
|
margin: 5px 0;
|
|
9
9
|
`;
|
|
10
10
|
const Input = styled.input `
|
|
11
|
+
position: absolute;
|
|
12
|
+
width: 0;
|
|
13
|
+
height: 0;
|
|
11
14
|
appearance: none;
|
|
12
15
|
margin: 0;
|
|
13
16
|
|
|
@@ -16,7 +19,7 @@ const Input = styled.input `
|
|
|
16
19
|
cursor: pointer;
|
|
17
20
|
width: 30px;
|
|
18
21
|
height: 18px;
|
|
19
|
-
background-color: ${
|
|
22
|
+
background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
|
|
20
23
|
transition: 0.4s;
|
|
21
24
|
border-radius: 10px;
|
|
22
25
|
padding: 0 3px;
|
|
@@ -29,51 +32,51 @@ const Input = styled.input `
|
|
|
29
32
|
width: 14px;
|
|
30
33
|
left: 1px;
|
|
31
34
|
top: 1px;
|
|
32
|
-
border: 1px solid
|
|
35
|
+
border: 1px solid ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
|
|
33
36
|
border-radius: 50%;
|
|
34
|
-
background-color:
|
|
37
|
+
background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
|
|
35
38
|
transition: 0.4s;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/* checked */
|
|
39
42
|
&:checked + span {
|
|
40
|
-
background-color:
|
|
43
|
+
background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
&:checked + span:before {
|
|
44
47
|
transform: translateX(18px);
|
|
45
|
-
border-color:
|
|
48
|
+
border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
/* focus */
|
|
49
52
|
&:enabled:focus + span:before {
|
|
50
|
-
box-shadow: 0 0 0 3px
|
|
51
|
-
border-color:
|
|
53
|
+
box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
|
|
54
|
+
border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
/* hover */
|
|
55
58
|
&:enabled:hover ~ span {
|
|
56
59
|
cursor: pointer;
|
|
57
|
-
color:
|
|
60
|
+
color: ${getThemeValue(THEME_NAME.PRIMARY)};
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
/* disabled */
|
|
61
64
|
&:disabled ~ span {
|
|
62
|
-
color:
|
|
65
|
+
color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
&:disabled + span {
|
|
66
|
-
background-color: ${
|
|
69
|
+
background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
|
|
67
70
|
cursor: not-allowed;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
&:disabled + span:before {
|
|
71
|
-
background-color:
|
|
72
|
-
border-color:
|
|
74
|
+
background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
|
|
75
|
+
border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
|
|
73
76
|
}
|
|
74
77
|
`;
|
|
75
78
|
function Toggle(props) {
|
|
76
|
-
return (_jsxs(Switch, { children: [_jsx(Input, Object.assign({}, props, { type: "checkbox" })), _jsx("span", {}), _jsx("span", { children: props.label })] }));
|
|
79
|
+
return (_jsxs(Switch, { children: [_jsx(Input, Object.assign({}, props, { type: "checkbox", role: "switch", "aria-checked": props.checked })), _jsx("span", {}), _jsx("span", { children: props.label })] }));
|
|
77
80
|
}
|
|
78
81
|
Toggle.propTypes = {
|
|
79
82
|
/** Label for the field */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle.js","sourceRoot":"","sources":["../../../src/components/Input/Toggle.tsx"],"names":[],"mappings":";AACA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,
|
|
1
|
+
{"version":3,"file":"Toggle.js","sourceRoot":"","sources":["../../../src/components/Input/Toggle.tsx"],"names":[],"mappings":";AACA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEnE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAA;;;;CAI1B,CAAC;AAEF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;;;;;;;;;;;;4BAYE,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;4BAapC,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC;;4BAEzC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC;;;;;;4BAMpC,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC;;;;;wBAK3C,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC;;;;;gCAKzB,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC;wBAC/C,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC;;;;;;iBAMxC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC;;;;;iBAKjC,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC;;;;4BAI9B,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC;;;;;4BAKpC,aAAa,CAAC,UAAU,CAAC,kBAAkB,CAAC;wBAChD,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC;;CAEhE,CAAC;AAMF,SAAS,MAAM,CAAC,KAAkB;IAC9B,OAAO,CACH,MAAC,MAAM,eACH,KAAC,KAAK,oBAAK,KAAK,IAAE,IAAI,EAAC,UAAU,EAAC,IAAI,EAAC,QAAQ,kBAAe,KAAK,CAAC,OAAO,IAAI,EAC/E,gBAAa,EACb,yBAAO,KAAK,CAAC,KAAK,GAAQ,IACrB,CACZ,CAAC;AACN,CAAC;AAED,MAAM,CAAC,SAAS,GAAG;IACf,0BAA0B;IAC1B,KAAK,EAAE,SAAS,CAAC,MAAM;CAC1B,CAAC;AAEF,eAAe,MAAM,CAAC","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport styled from '@emotion/styled';\nimport { getThemeValue, THEME_NAME } from '../../shared/constants';\n\nconst Switch = styled.label`\n position: relative;\n display: inline-flex;\n margin: 5px 0;\n`;\n\nconst Input = styled.input`\n position: absolute;\n width: 0;\n height: 0;\n appearance: none;\n margin: 0;\n\n & + span {\n position: relative;\n cursor: pointer;\n width: 30px;\n height: 18px;\n background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};\n transition: 0.4s;\n border-radius: 10px;\n padding: 0 3px;\n margin: 0 10px 0 5px;\n }\n & + span:before {\n position: absolute;\n content: '';\n height: 14px;\n width: 14px;\n left: 1px;\n top: 1px;\n border: 1px solid ${getThemeValue(THEME_NAME.DISABLED_BORDER)};\n border-radius: 50%;\n background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};\n transition: 0.4s;\n }\n\n /* checked */\n &:checked + span {\n background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};\n }\n\n &:checked + span:before {\n transform: translateX(18px);\n border-color: ${getThemeValue(THEME_NAME.PRIMARY)};\n }\n\n /* focus */\n &:enabled:focus + span:before {\n box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};\n border-color: ${getThemeValue(THEME_NAME.PRIMARY)};\n }\n\n /* hover */\n &:enabled:hover ~ span {\n cursor: pointer;\n color: ${getThemeValue(THEME_NAME.PRIMARY)};\n }\n\n /* disabled */\n &:disabled ~ span {\n color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};\n }\n\n &:disabled + span {\n background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};\n cursor: not-allowed;\n }\n\n &:disabled + span:before {\n background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};\n border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};\n }\n`;\n\ntype ToggleProps = PropTypes.InferProps<\n React.AllHTMLAttributes<HTMLInputElement> & typeof Toggle.propTypes\n>;\n\nfunction Toggle(props: ToggleProps) {\n return (\n <Switch>\n <Input {...props} type=\"checkbox\" role=\"switch\" aria-checked={props.checked} />\n <span></span>\n <span>{props.label}</span>\n </Switch>\n );\n}\n\nToggle.propTypes = {\n /** Label for the field */\n label: PropTypes.string,\n};\n\nexport default Toggle;\n"]}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the Menu component.
|
|
4
|
+
* @template T - The type of value(s) in the menu.
|
|
5
|
+
*/
|
|
2
6
|
interface MenuProps<T> {
|
|
3
7
|
/** Multiple Menu Items can be selected */
|
|
4
8
|
multiSelect?: boolean;
|
|
@@ -9,6 +13,14 @@ interface MenuProps<T> {
|
|
|
9
13
|
/** Menu Items */
|
|
10
14
|
children?: ReactNode;
|
|
11
15
|
}
|
|
12
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Menu component that allows selection of items from a list.
|
|
18
|
+
* Supports single and multi-select modes and keyboard navigation.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type of value(s) in the menu.
|
|
21
|
+
* @param {MenuProps<T> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>} props - The menu properties.
|
|
22
|
+
* @param {ForwardedRef<HTMLDivElement>} ref - The ref forwarded to the menu container.
|
|
23
|
+
*/
|
|
24
|
+
declare const Menu: React.ForwardRefExoticComponent<MenuProps<object> & Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> & React.RefAttributes<HTMLDivElement>>;
|
|
13
25
|
export default Menu;
|
|
14
26
|
//# sourceMappingURL=Menu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAY,SAAS,EAAgB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAY,SAAS,EAAgB,MAAM,OAAO,CAAC;AAIjE;;;GAGG;AACH,UAAU,SAAS,CAAC,CAAC;IACjB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wBAAwB;IACxB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;IACpC,iBAAiB;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAgBD;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,mJAwHR,CAAC;AAQH,eAAe,IAAI,CAAC"}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
13
|
import React, { useState } from 'react';
|
|
3
14
|
import styled from '@emotion/styled';
|
|
15
|
+
import { getThemeValue, THEME_NAME } from '../../shared/constants';
|
|
4
16
|
import MenuContext from './MenuContext';
|
|
5
17
|
const MenuContainer = styled.div `
|
|
6
18
|
flex: 1;
|
|
@@ -10,10 +22,28 @@ const MenuContainer = styled.div `
|
|
|
10
22
|
& div:last-child {
|
|
11
23
|
border-bottom: none;
|
|
12
24
|
}
|
|
25
|
+
|
|
26
|
+
&:focus-within {
|
|
27
|
+
box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
|
|
28
|
+
}
|
|
13
29
|
`;
|
|
30
|
+
/**
|
|
31
|
+
* Menu component that allows selection of items from a list.
|
|
32
|
+
* Supports single and multi-select modes and keyboard navigation.
|
|
33
|
+
*
|
|
34
|
+
* @template T - The type of value(s) in the menu.
|
|
35
|
+
* @param {MenuProps<T> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>} props - The menu properties.
|
|
36
|
+
* @param {ForwardedRef<HTMLDivElement>} ref - The ref forwarded to the menu container.
|
|
37
|
+
*/
|
|
14
38
|
const Menu = React.forwardRef(function (props, ref) {
|
|
15
|
-
const { multiSelect, onChange } = props;
|
|
16
|
-
const [value, setValue] = useState(
|
|
39
|
+
const { multiSelect, onChange, value: propValue } = props, rest = __rest(props, ["multiSelect", "onChange", "value"]);
|
|
40
|
+
const [value, setValue] = useState(propValue || (multiSelect ? [] : ''));
|
|
41
|
+
/**
|
|
42
|
+
* Updates the selected value(s).
|
|
43
|
+
* Handles both single and multi-select logic.
|
|
44
|
+
*
|
|
45
|
+
* @param {T} val - The value to select or deselect.
|
|
46
|
+
*/
|
|
17
47
|
const updateValue = (val) => {
|
|
18
48
|
let newVal;
|
|
19
49
|
if (multiSelect) {
|
|
@@ -32,11 +62,76 @@ const Menu = React.forwardRef(function (props, ref) {
|
|
|
32
62
|
setValue(newVal);
|
|
33
63
|
onChange === null || onChange === void 0 ? void 0 : onChange(newVal);
|
|
34
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* Handles keyboard navigation within the menu.
|
|
67
|
+
* Supports Arrow keys for navigation, and Enter/Space for selection.
|
|
68
|
+
*
|
|
69
|
+
* @param {React.KeyboardEvent} e - The keyboard event.
|
|
70
|
+
*/
|
|
71
|
+
const handleKeyDown = (e) => {
|
|
72
|
+
var _a, _b, _c, _d;
|
|
73
|
+
const target = e.target;
|
|
74
|
+
const container = e.currentTarget;
|
|
75
|
+
const items = Array.from(container.querySelectorAll('[role="option"]'));
|
|
76
|
+
const currentIndex = items.indexOf(target);
|
|
77
|
+
let nextIndex;
|
|
78
|
+
switch (e.key) {
|
|
79
|
+
case 'ArrowDown':
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
nextIndex = currentIndex + 1;
|
|
82
|
+
if (nextIndex >= items.length)
|
|
83
|
+
nextIndex = 0;
|
|
84
|
+
(_a = items[nextIndex]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
85
|
+
break;
|
|
86
|
+
case 'ArrowUp':
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
nextIndex = currentIndex - 1;
|
|
89
|
+
if (nextIndex < 0)
|
|
90
|
+
nextIndex = items.length - 1;
|
|
91
|
+
(_b = items[nextIndex]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
92
|
+
break;
|
|
93
|
+
case 'Home':
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
(_c = items[0]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
96
|
+
break;
|
|
97
|
+
case 'End':
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
(_d = items[items.length - 1]) === null || _d === void 0 ? void 0 : _d.focus();
|
|
100
|
+
break;
|
|
101
|
+
case 'Enter':
|
|
102
|
+
case ' ': // Space
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
target.click();
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Handles focus events on the menu container.
|
|
112
|
+
* Delegates focus to the first item if the container itself receives focus.
|
|
113
|
+
*
|
|
114
|
+
* @param {React.FocusEvent} e - The focus event.
|
|
115
|
+
*/
|
|
116
|
+
const focusHandler = (e) => {
|
|
117
|
+
// Prevent trap: If focus came from inside (Shift+Tab), do NOT auto-focus again.
|
|
118
|
+
// This allows focus to land on the container, and the next Shift+Tab will exit.
|
|
119
|
+
if (e.currentTarget.contains(e.relatedTarget)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Only if focus is actually on the container (e.g. tabbing into it)
|
|
123
|
+
// and not bubbling up from a child
|
|
124
|
+
if (e.target === e.currentTarget) {
|
|
125
|
+
// Prevent the container from holding focus; delegate to first item
|
|
126
|
+
const firstItem = e.currentTarget.querySelector('[role="option"]');
|
|
127
|
+
firstItem === null || firstItem === void 0 ? void 0 : firstItem.focus();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
35
130
|
return (_jsx(MenuContext.Provider, { value: {
|
|
36
131
|
value,
|
|
37
132
|
multiSelect,
|
|
38
133
|
updateValue,
|
|
39
|
-
}, children: _jsx(MenuContainer, { ref: ref, children: props.children }) }));
|
|
134
|
+
}, children: _jsx(MenuContainer, Object.assign({}, rest, { ref: ref, role: "listbox", "aria-multiselectable": multiSelect, tabIndex: 0, onKeyDown: handleKeyDown, onFocus: focusHandler, children: props.children })) }));
|
|
40
135
|
});
|
|
41
136
|
Menu.displayName = 'Menu';
|
|
42
137
|
Menu.defaultProps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAA2B,MAAM,OAAO,CAAC;AACjE,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,WAAW,MAAM,eAAe,CAAC;AAgBxC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;gCAUA,aAAa,CAAC,UAAU,CAAC,aAAa,CAAC;;CAEtE,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,UAC1B,KAA4E,EAC5E,GAAiC;IAEjC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAA5D,oCAAoD,CAAQ,CAAC;IACnE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzE;;;;;OAKG;IACH,MAAM,WAAW,GAAG,CAAC,GAAM,EAAE,EAAE;QAC3B,IAAI,MAAM,CAAC;QACX,IAAI,WAAW,EAAE,CAAC;YACd,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvB,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;gBAClD,CAAC;qBAAM,CAAC;oBACJ,MAAM,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC7B,CAAC;YACL,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,MAAM,GAAG,GAAG,CAAC;QACjB,CAAC;QACD,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjB,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,MAAM,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF;;;;;OAKG;IACH,MAAM,aAAa,GAAG,CAAC,CAAsB,EAAE,EAAE;;QAC7C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAqB,CAAC;QACvC,MAAM,SAAS,GAAG,CAAC,CAAC,aAA4B,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAkB,CAAC;QACzF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,MAAqB,CAAC,CAAC;QAE1D,IAAI,SAAS,CAAC;QAEd,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;YACZ,KAAK,WAAW;gBACZ,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC;gBAC7B,IAAI,SAAS,IAAI,KAAK,CAAC,MAAM;oBAAE,SAAS,GAAG,CAAC,CAAC;gBAC7C,MAAA,KAAK,CAAC,SAAS,CAAC,0CAAE,KAAK,EAAE,CAAC;gBAC1B,MAAM;YACV,KAAK,SAAS;gBACV,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC;gBAC7B,IAAI,SAAS,GAAG,CAAC;oBAAE,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;gBAChD,MAAA,KAAK,CAAC,SAAS,CAAC,0CAAE,KAAK,EAAE,CAAC;gBAC1B,MAAM;YACV,KAAK,MAAM;gBACP,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,KAAK,EAAE,CAAC;gBAClB,MAAM;YACV,KAAK,KAAK;gBACN,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,MAAA,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,0CAAE,KAAK,EAAE,CAAC;gBACjC,MAAM;YACV,KAAK,OAAO,CAAC;YACb,KAAK,GAAG,EAAE,QAAQ;gBACd,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,MAAM;YACV;gBACI,MAAM;QACd,CAAC;IACL,CAAC,CAAC;IAEF;;;;;OAKG;IACH,MAAM,YAAY,GAAG,CAAC,CAAmB,EAAE,EAAE;QACzC,gFAAgF;QAChF,gFAAgF;QAChF,IAAI,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAqB,CAAC,EAAE,CAAC;YACpD,OAAO;QACX,CAAC;QAED,oEAAoE;QACpE,mCAAmC;QACnC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YAC/B,mEAAmE;YACnE,MAAM,SAAS,GAAG,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,iBAAiB,CAAgB,CAAC;YAClF,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,EAAE,CAAC;QACvB,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,WAAW,CAAC,QAAQ,IACjB,KAAK,EACD;YACI,KAAK;YACL,WAAW;YACX,WAAW;SACsC,YAGzD,KAAC,aAAa,oBACN,IAAI,IACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,SAAS,0BACQ,WAAW,EACjC,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,YAAY,YAEpB,KAAK,CAAC,QAAQ,IACH,GACG,CAC1B,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;AAE1B,IAAI,CAAC,YAAY,GAAG;IAChB,WAAW,EAAE,KAAK;CACrB,CAAC;AAEF,eAAe,IAAI,CAAC","sourcesContent":["import React, { useState, ReactNode, ForwardedRef } from 'react';\nimport styled from '@emotion/styled';\nimport { getThemeValue, THEME_NAME } from '../../shared/constants';\nimport MenuContext from './MenuContext';\n/**\n * Props for the Menu component.\n * @template T - The type of value(s) in the menu.\n */\ninterface MenuProps<T> {\n /** Multiple Menu Items can be selected */\n multiSelect?: boolean;\n /** Value(s) selected */\n value?: T | T[];\n /** Callback when the selected value changes */\n onChange?: (value: T | T[]) => void;\n /** Menu Items */\n children?: ReactNode;\n}\n\nconst MenuContainer = styled.div`\n flex: 1;\n display: flex;\n flex-direction: column;\n\n & div:last-child {\n border-bottom: none;\n }\n\n &:focus-within {\n box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};\n }\n`;\n\n/**\n * Menu component that allows selection of items from a list.\n * Supports single and multi-select modes and keyboard navigation.\n *\n * @template T - The type of value(s) in the menu.\n * @param {MenuProps<T> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>} props - The menu properties.\n * @param {ForwardedRef<HTMLDivElement>} ref - The ref forwarded to the menu container.\n */\nconst Menu = React.forwardRef(function <T extends object>(\n props: MenuProps<T> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>,\n ref: ForwardedRef<HTMLDivElement>,\n) {\n const { multiSelect, onChange, value: propValue, ...rest } = props;\n const [value, setValue] = useState(propValue || (multiSelect ? [] : ''));\n\n /**\n * Updates the selected value(s).\n * Handles both single and multi-select logic.\n *\n * @param {T} val - The value to select or deselect.\n */\n const updateValue = (val: T) => {\n let newVal;\n if (multiSelect) {\n if (Array.isArray(value)) {\n if (value.includes(val)) {\n newVal = value.filter((item) => item !== val);\n } else {\n newVal = [...value, val];\n }\n }\n } else {\n newVal = val;\n }\n setValue(newVal);\n onChange?.(newVal);\n };\n\n /**\n * Handles keyboard navigation within the menu.\n * Supports Arrow keys for navigation, and Enter/Space for selection.\n *\n * @param {React.KeyboardEvent} e - The keyboard event.\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n const target = e.target as HTMLElement;\n const container = e.currentTarget as HTMLElement;\n const items = Array.from(container.querySelectorAll('[role=\"option\"]')) as HTMLElement[];\n const currentIndex = items.indexOf(target as HTMLElement);\n\n let nextIndex;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n nextIndex = currentIndex + 1;\n if (nextIndex >= items.length) nextIndex = 0;\n items[nextIndex]?.focus();\n break;\n case 'ArrowUp':\n e.preventDefault();\n nextIndex = currentIndex - 1;\n if (nextIndex < 0) nextIndex = items.length - 1;\n items[nextIndex]?.focus();\n break;\n case 'Home':\n e.preventDefault();\n items[0]?.focus();\n break;\n case 'End':\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n case 'Enter':\n case ' ': // Space\n e.preventDefault();\n target.click();\n break;\n default:\n break;\n }\n };\n\n /**\n * Handles focus events on the menu container.\n * Delegates focus to the first item if the container itself receives focus.\n *\n * @param {React.FocusEvent} e - The focus event.\n */\n const focusHandler = (e: React.FocusEvent) => {\n // Prevent trap: If focus came from inside (Shift+Tab), do NOT auto-focus again.\n // This allows focus to land on the container, and the next Shift+Tab will exit.\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n // Only if focus is actually on the container (e.g. tabbing into it)\n // and not bubbling up from a child\n if (e.target === e.currentTarget) {\n // Prevent the container from holding focus; delegate to first item\n const firstItem = e.currentTarget.querySelector('[role=\"option\"]') as HTMLElement;\n firstItem?.focus();\n }\n };\n\n return (\n <MenuContext.Provider\n value={\n {\n value,\n multiSelect,\n updateValue,\n } as unknown as React.ContextType<typeof MenuContext>\n }\n >\n <MenuContainer\n {...rest}\n ref={ref}\n role=\"listbox\"\n aria-multiselectable={multiSelect}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onFocus={focusHandler}\n >\n {props.children}\n </MenuContainer>\n </MenuContext.Provider>\n );\n});\n\nMenu.displayName = 'Menu';\n\nMenu.defaultProps = {\n multiSelect: false,\n};\n\nexport default Menu;\n"]}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
interface MenuItemProps<T> {
|
|
3
3
|
/** Value of the element */
|
|
4
|
-
value: T
|
|
4
|
+
value: T;
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
declare const MenuItemInner: <T>(props: MenuItemProps<T> & React.PropsWithChildren, ref: React.Ref<HTMLButtonElement>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare const MenuItem: <T>(props: MenuItemProps<T> & React.PropsWithChildren & {
|
|
8
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
9
|
+
}) => ReturnType<typeof MenuItemInner>;
|
|
10
|
+
export default MenuItem;
|
|
8
11
|
//# sourceMappingURL=MenuItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAM1D,UAAU,aAAa,CAAC,CAAC;IACrB,2BAA2B;IAC3B,KAAK,EAAE,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAM1D,UAAU,aAAa,CAAC,CAAC;IACrB,2BAA2B;IAC3B,KAAK,EAAE,CAAC,CAAC;CACZ;AA2BD,QAAA,MAAM,aAAa,GAAI,CAAC,SACb,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,iBAAiB,OAC5C,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,qDAkCpC,CAAC;AAEF,QAAA,MAAM,QAAQ,EAAsC,CAAC,CAAC,EAClD,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,iBAAiB,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;CAAE,KACzF,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AAEtC,eAAe,QAAQ,CAAC"}
|
|
@@ -10,9 +10,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
13
|
-
import { useContext } from 'react';
|
|
13
|
+
import React, { useContext } from 'react';
|
|
14
14
|
import styled from '@emotion/styled';
|
|
15
|
-
import
|
|
15
|
+
import { getThemeValue, THEME_NAME } from '../../shared/constants';
|
|
16
16
|
import Checkbox from '../Input/Checkbox';
|
|
17
17
|
import MenuContext from './MenuContext';
|
|
18
18
|
const Container = styled.button `
|
|
@@ -21,37 +21,37 @@ const Container = styled.button `
|
|
|
21
21
|
border: none;
|
|
22
22
|
background-color: transparent;
|
|
23
23
|
font-size: 16px;
|
|
24
|
-
border-bottom: 1px solid
|
|
24
|
+
border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
|
|
25
25
|
min-height: 41px;
|
|
26
26
|
display: flex;
|
|
27
27
|
align-items: center;
|
|
28
28
|
cursor: pointer;
|
|
29
29
|
position: relative;
|
|
30
|
+
color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
|
|
30
31
|
|
|
31
32
|
&:hover,
|
|
32
33
|
&:focus,
|
|
33
34
|
&:focus-within {
|
|
34
|
-
background-color:
|
|
35
|
+
background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
& > label {
|
|
38
39
|
margin: 0 4px 0 0;
|
|
39
40
|
}
|
|
40
41
|
`;
|
|
41
|
-
|
|
42
|
+
const MenuItemInner = (props, ref) => {
|
|
42
43
|
var _a, _b;
|
|
43
44
|
const context = useContext(MenuContext);
|
|
44
45
|
const { value, children } = props, rest = __rest(props, ["value", "children"]);
|
|
45
46
|
const clickHandler = (e) => {
|
|
46
47
|
e.stopPropagation();
|
|
47
|
-
if (context.multiSelect) {
|
|
48
|
-
e.nativeEvent.stopImmediatePropagation();
|
|
49
|
-
}
|
|
50
48
|
context.updateValue(value);
|
|
51
49
|
};
|
|
52
50
|
const selected = context.multiSelect
|
|
53
51
|
? (_b = (_a = context.value) === null || _a === void 0 ? void 0 : _a.includes) === null || _b === void 0 ? void 0 : _b.call(_a, value)
|
|
54
52
|
: context.value === value;
|
|
55
|
-
return (_jsxs(Container, Object.assign({}, rest, { type: "button",
|
|
56
|
-
}
|
|
53
|
+
return (_jsxs(Container, Object.assign({}, rest, { ref: ref, type: "button", role: "option", "aria-selected": selected, selected: selected, onClick: clickHandler, children: [context.multiSelect && (_jsx(Checkbox, { checked: selected, readOnly: true, tabIndex: -1, onClick: (e) => e.stopPropagation() })), children] })));
|
|
54
|
+
};
|
|
55
|
+
const MenuItem = React.forwardRef(MenuItemInner);
|
|
56
|
+
export default MenuItem;
|
|
57
57
|
//# sourceMappingURL=MenuItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.js","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"MenuItem.js","sourceRoot":"","sources":["../../../src/components/Menu/MenuItem.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAkB,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,WAAgC,MAAM,eAAe,CAAC;AAO7D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAuB;mBACnC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;;;;;+BAKnC,aAAa,CAAC,UAAU,CAAC,kBAAkB,CAAC;;;;;;aAM9D,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC;;;;;4BAK1B,aAAa,CAAC,UAAU,CAAC,kBAAkB,CAAC;;;;;;CAMvE,CAAC;AAEF,MAAM,aAAa,GAAG,CAClB,KAAiD,EACjD,GAAiC,EACnC,EAAE;;IACA,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAuB,CAAC;IAC9D,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAApC,qBAA4B,CAAQ,CAAC;IAC3C,MAAM,YAAY,GAAG,CAAC,CAAiB,EAAE,EAAE;QACvC,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,WAAW,CAAC,KAAgB,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW;QAChC,CAAC,CAAC,MAAA,MAAA,OAAO,CAAC,KAAK,0CAAE,QAAQ,mDAAG,KAAK,CAAC;QAClC,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC;IAE9B,OAAO,CACH,MAAC,SAAS,oBACF,IAAI,IACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,mBACE,QAAQ,EACvB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,aAEpB,OAAO,CAAC,WAAW,IAAI,CACpB,KAAC,QAAQ,IACL,OAAO,EAAE,QAAQ,EACjB,QAAQ,QACR,QAAQ,EAAE,CAAC,CAAC,EACZ,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,GACrC,CACL,EACA,QAAQ,KACD,CACf,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAEV,CAAC;AAEtC,eAAe,QAAQ,CAAC","sourcesContent":["import React, { SyntheticEvent, useContext } from 'react';\nimport styled from '@emotion/styled';\nimport { getThemeValue, THEME_NAME } from '../../shared/constants';\nimport Checkbox from '../Input/Checkbox';\nimport MenuContext, { MenuContextType } from './MenuContext';\n\ninterface MenuItemProps<T> {\n /** Value of the element */\n value: T;\n}\n\nconst Container = styled.button<{ selected: boolean }>`\n font-weight: ${(props) => (props.selected ? 'bold' : 'normal')};\n padding: 8px 6px;\n border: none;\n background-color: transparent;\n font-size: 16px;\n border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};\n min-height: 41px;\n display: flex;\n align-items: center;\n cursor: pointer;\n position: relative;\n color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};\n\n &:hover,\n &:focus,\n &:focus-within {\n background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};\n }\n\n & > label {\n margin: 0 4px 0 0;\n }\n`;\n\nconst MenuItemInner = <T,>(\n props: MenuItemProps<T> & React.PropsWithChildren,\n ref: React.Ref<HTMLButtonElement>,\n) => {\n const context = useContext(MenuContext) as MenuContextType<T>;\n const { value, children, ...rest } = props;\n const clickHandler = (e: SyntheticEvent) => {\n e.stopPropagation();\n context.updateValue(value as T & T[]);\n };\n\n const selected = context.multiSelect\n ? context.value?.includes?.(value)\n : context.value === value;\n\n return (\n <Container\n {...rest}\n ref={ref}\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n selected={selected}\n onClick={clickHandler}\n >\n {context.multiSelect && (\n <Checkbox\n checked={selected}\n readOnly\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n />\n )}\n {children}\n </Container>\n );\n};\n\nconst MenuItem = React.forwardRef(MenuItemInner) as <T>(\n props: MenuItemProps<T> & React.PropsWithChildren & { ref?: React.Ref<HTMLButtonElement> },\n) => ReturnType<typeof MenuItemInner>;\n\nexport default MenuItem;\n"]}
|
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
export { Header as ModalHeader, Body as ModalBody, Footer as ModalFooter, } from '../../shared/styles';
|
|
4
|
-
|
|
4
|
+
declare const modalPropTypes: {
|
|
5
|
+
/** Opens the modal */
|
|
6
|
+
open: PropTypes.Validator<boolean>;
|
|
7
|
+
/** Closes the modal on esc */
|
|
8
|
+
closeOnEsc: PropTypes.Requireable<boolean>;
|
|
9
|
+
/** Closes the modal on overlay click */
|
|
10
|
+
closeOnOverlayClick: PropTypes.Requireable<boolean>;
|
|
11
|
+
/** Call back function called when the modal closes. */
|
|
12
|
+
onClose: PropTypes.Requireable<(...args: any[]) => any>;
|
|
13
|
+
};
|
|
14
|
+
type ModalProps = PropTypes.InferProps<typeof modalPropTypes>;
|
|
5
15
|
interface ModalState {
|
|
6
16
|
open: boolean;
|
|
7
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Modal component
|
|
20
|
+
*
|
|
21
|
+
* A dialog window that sits on top of the main application content.
|
|
22
|
+
* It disrupts the user's workflow to demand attention for a critical task or decision.
|
|
23
|
+
*
|
|
24
|
+
* Accessibility:
|
|
25
|
+
* - Implements ARIA `role="dialog"` and `aria-modal="true"`.
|
|
26
|
+
* - Traps focus effectively within the modal while open.
|
|
27
|
+
* - Restores focus to the triggering element upon closure.
|
|
28
|
+
* - Supports closing via ESC key and overlay click.
|
|
29
|
+
*/
|
|
8
30
|
export default class Modal extends React.Component<React.PropsWithChildren<ModalProps>, ModalState> {
|
|
9
31
|
state: {
|
|
10
32
|
open: boolean;
|
|
@@ -23,13 +45,60 @@ export default class Modal extends React.Component<React.PropsWithChildren<Modal
|
|
|
23
45
|
closeOnEsc: boolean;
|
|
24
46
|
closeOnOverlayClick: boolean;
|
|
25
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Syncs state with props.
|
|
50
|
+
*/
|
|
26
51
|
static getDerivedStateFromProps(props: ModalProps): {
|
|
27
52
|
open: boolean;
|
|
28
53
|
};
|
|
29
54
|
private layer;
|
|
30
55
|
private closeCallback;
|
|
56
|
+
/**
|
|
57
|
+
* Internal close handler.
|
|
58
|
+
* Restores focus and calls the external onClose callback.
|
|
59
|
+
*/
|
|
31
60
|
private onClose;
|
|
61
|
+
private lastFocusedElement;
|
|
62
|
+
private modalRef;
|
|
63
|
+
/**
|
|
64
|
+
* Retrieves all focusable elements within the modal.
|
|
65
|
+
*/
|
|
66
|
+
private getFocusableElements;
|
|
67
|
+
/**
|
|
68
|
+
* Handles keydown events to implement the focus trap.
|
|
69
|
+
* Traps Tab and Shift+Tab within the modal.
|
|
70
|
+
*/
|
|
71
|
+
private handleKeyDown;
|
|
72
|
+
/**
|
|
73
|
+
* Lifecycle method to save the currently focused element when the modal mounts while open.
|
|
74
|
+
*/
|
|
75
|
+
componentDidMount(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Lifecycle method to restore focus when the modal unmounts.
|
|
78
|
+
*/
|
|
79
|
+
componentWillUnmount(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Restores focus to the element that was focused before the modal opened.
|
|
82
|
+
*/
|
|
83
|
+
private restoreFocus;
|
|
84
|
+
/**
|
|
85
|
+
* Callback ref to capture the Modal DOM element.
|
|
86
|
+
* Triggers initial focus setting when the element mounts.
|
|
87
|
+
*/
|
|
88
|
+
private setModalRef;
|
|
89
|
+
/**
|
|
90
|
+
* Sets initial focus within the modal.
|
|
91
|
+
* Tries to focus the header (first child) first, then the first interactive element, or falls back to the container.
|
|
92
|
+
*/
|
|
93
|
+
private setInitialFocus;
|
|
94
|
+
/**
|
|
95
|
+
* Lifecycle method to handle Modal updates.
|
|
96
|
+
* Manages opening/closing logic via LayerManager and focus preservation.
|
|
97
|
+
*/
|
|
32
98
|
getSnapshotBeforeUpdate(prevProps: ModalProps): void;
|
|
99
|
+
/**
|
|
100
|
+
* Renders the Modal component via the LayerManager portal.
|
|
101
|
+
*/
|
|
33
102
|
render(): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
34
103
|
}
|
|
35
104
|
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,EACH,MAAM,IAAI,WAAW,EACrB,IAAI,IAAI,SAAS,EACjB,MAAM,IAAI,WAAW,GACxB,MAAM,qBAAqB,CAAC;AAG7B,KAAK,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,EACH,MAAM,IAAI,WAAW,EACrB,IAAI,IAAI,SAAS,EACjB,MAAM,IAAI,WAAW,GACxB,MAAM,qBAAqB,CAAC;AAG7B,QAAA,MAAM,cAAc;IAChB,sBAAsB;;IAEtB,8BAA8B;;IAE9B,wCAAwC;;IAExC,uDAAuD;;CAE1D,CAAC;AAEF,KAAK,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE9D,UAAU,UAAU;IAChB,IAAI,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,KAAK,CAAC,SAAS,CAC9C,KAAK,CAAC,iBAAiB,CAAC,UAAU,CAAC,EACnC,UAAU,CACb;IACG,KAAK;;MAEH;IAEF,MAAM,CAAC,SAAS;QApChB,sBAAsB;;QAEtB,8BAA8B;;QAE9B,wCAAwC;;QAExC,uDAAuD;;MA8BrB;IAElC,MAAM,CAAC,YAAY;;;MAGjB;IAEF;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,UAAU;;;IASjD,OAAO,CAAC,KAAK,CAA8C;IAE3D,OAAO,CAAC,aAAa,CAA2B;IAEhD;;;OAGG;IACH,OAAO,CAAC,OAAO,CAQb;IAEF,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAqC;IAErD;;OAEG;IACH,OAAO,CAAC,oBAAoB,CAO1B;IAEF;;;OAGG;IACH,OAAO,CAAC,aAAa,CAoBnB;IAEF;;OAEG;IACH,iBAAiB;IAMjB;;OAEG;IACH,oBAAoB;IAMpB;;OAEG;IACH,OAAO,CAAC,YAAY,CAWlB;IAEF;;;OAGG;IACH,OAAO,CAAC,WAAW,CAQjB;IAEF;;;OAGG;IACH,OAAO,CAAC,eAAe,CAoBrB;IAEF;;;OAGG;IACH,uBAAuB,CAAC,SAAS,EAAE,UAAU;IAuC7C;;OAEG;IACH,MAAM;CAQT"}
|