@ndlib/component-library 0.0.18 → 0.0.20
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/components/composites/NavMenu/NavMenu.stories.d.ts +6 -0
- package/dist/components/composites/NavMenu/NavMenu.stories.js +12 -0
- package/dist/components/composites/NavMenu/NavMenu.test.d.ts +1 -0
- package/dist/components/composites/NavMenu/NavMenu.test.js +96 -0
- package/dist/components/composites/NavMenu/demo.d.ts +1 -0
- package/dist/components/composites/NavMenu/demo.js +89 -0
- package/dist/components/composites/NavMenu/index.d.ts +5 -0
- package/dist/components/composites/NavMenu/index.js +41 -0
- package/dist/components/elements/Button/index.js +10 -1
- package/dist/components/elements/Fields/DatePicker/DatePicker.stories.d.ts +7 -0
- package/dist/components/elements/Fields/DatePicker/DatePicker.stories.js +20 -0
- package/dist/components/elements/Fields/DatePicker/index.d.ts +19 -0
- package/dist/components/elements/Fields/DatePicker/index.js +34 -0
- package/dist/components/elements/Fields/MonthPicker/MonthPicker.stories.d.ts +7 -0
- package/dist/components/elements/Fields/MonthPicker/MonthPicker.stories.js +20 -0
- package/dist/components/elements/Fields/MonthPicker/index.d.ts +13 -0
- package/dist/components/elements/Fields/MonthPicker/index.js +22 -0
- package/dist/components/elements/Fields/Select/index.js +1 -1
- package/dist/components/elements/Fields/TextInput/TextInput.stories.js +1 -1
- package/dist/components/elements/Fields/TextInput/index.d.ts +14 -4
- package/dist/components/elements/Fields/TextInput/index.js +9 -6
- package/dist/components/elements/Link/index.js +1 -1
- package/dist/components/elements/layout/Box.d.ts +1 -2
- package/dist/components/elements/text/ReadMore/ReadMore.stories.d.ts +7 -0
- package/dist/components/elements/text/ReadMore/ReadMore.stories.js +19 -0
- package/dist/components/elements/text/ReadMore/index.d.ts +10 -0
- package/dist/components/elements/text/ReadMore/index.js +74 -0
- package/dist/components/providers/menu.d.ts +46 -0
- package/dist/components/providers/menu.js +305 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +13 -1
- package/dist/theme/GlobalStyles.d.ts +1 -0
- package/dist/theme/GlobalStyles.js +162 -0
- package/dist/theme/colors.d.ts +1 -0
- package/dist/theme/colors.js +2 -0
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/typography.d.ts +2 -2
- package/dist/utils/hooks/useCheckMidClick.d.ts +8 -0
- package/dist/utils/hooks/useCheckMidClick.js +17 -0
- package/dist/utils/misc.d.ts +3 -0
- package/dist/utils/misc.js +3 -0
- package/package.json +3 -1
- package/global.css +0 -54
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
13
|
+
/** @jsxImportSource theme-ui */
|
|
14
|
+
import React, { useState } from 'react';
|
|
15
|
+
import { useTheme } from '../../../../theme';
|
|
16
|
+
import { COLOR } from '../../../../theme/colors';
|
|
17
|
+
import { getTypographyStyles, } from '../../../../theme/typography';
|
|
18
|
+
const ReadMoreLink = () => {
|
|
19
|
+
return (_jsx("div", Object.assign({ css: {
|
|
20
|
+
whiteSpace: 'nowrap',
|
|
21
|
+
position: 'absolute',
|
|
22
|
+
right: 0,
|
|
23
|
+
bottom: 0,
|
|
24
|
+
paddingLeft: '3rem',
|
|
25
|
+
background: 'linear-gradient(to right, rgba(255, 255, 255, 0), rgb(255, 255, 255) 30%, rgb(255, 255, 255))',
|
|
26
|
+
} }, { children: _jsx("div", Object.assign({ "aria-hidden": "true", sx: {
|
|
27
|
+
transform: 'scale(0.9)',
|
|
28
|
+
color: COLOR.ND_BLUE_LIGHT,
|
|
29
|
+
cursor: 'pointer',
|
|
30
|
+
} }, { children: "Read More..." })) })));
|
|
31
|
+
};
|
|
32
|
+
const useLinesHeight = (args) => {
|
|
33
|
+
const theme = useTheme();
|
|
34
|
+
const styles = getTypographyStyles(args.typography);
|
|
35
|
+
const fontSize = styles.fontSize;
|
|
36
|
+
const fontSizeRem = theme.fontSizes[fontSize];
|
|
37
|
+
// slice of the 'rem' from end of fontSize string and convert to number
|
|
38
|
+
const fontSizeNumber = Number(fontSizeRem.slice(0, fontSizeRem.length - 3));
|
|
39
|
+
// Multiply the fontSize by the lineHeight ratio and the number of lines
|
|
40
|
+
const linesHeight = fontSizeNumber * theme.lineHeights[styles.lineHeight] * args.lines;
|
|
41
|
+
return `${linesHeight}rem`;
|
|
42
|
+
};
|
|
43
|
+
// A react component that accepts text content and truncates it 3 lines. If the content
|
|
44
|
+
// exceeds the alloted space, an ellipsis will be placed at the end of the last line.
|
|
45
|
+
// This component does not use the css property `text-overflow: ellipsis`
|
|
46
|
+
// because it does not work with multiple lines of text.
|
|
47
|
+
export const ReadMore = (_a) => {
|
|
48
|
+
var { text, typography, sx, role, lines, fixedHeight } = _a, rest = __rest(_a, ["text", "typography", "sx", "role", "lines", "fixedHeight"]);
|
|
49
|
+
const ref = React.useRef(null);
|
|
50
|
+
const [showEllipsis, setShowEllipsis] = useState(true);
|
|
51
|
+
const wrapperHeight = useLinesHeight({ typography, lines });
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
if (ref.current) {
|
|
54
|
+
// Check if the content exceeds the alloted space
|
|
55
|
+
if (fixedHeight) {
|
|
56
|
+
ref.current.style.height = wrapperHeight;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
ref.current.style.maxHeight = wrapperHeight;
|
|
60
|
+
}
|
|
61
|
+
const isOverflowing = ref.current.scrollHeight > ref.current.clientHeight;
|
|
62
|
+
if (isOverflowing) {
|
|
63
|
+
setShowEllipsis(true);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
setShowEllipsis(false);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}, [text, wrapperHeight, fixedHeight]);
|
|
70
|
+
return (_jsxs("div", Object.assign({ role: role || 'paragraph', ref: ref, style: {
|
|
71
|
+
overflow: 'hidden',
|
|
72
|
+
position: 'relative',
|
|
73
|
+
}, sx: Object.assign(Object.assign({}, getTypographyStyles(typography)), sx) }, rest, { children: [text, showEllipsis && _jsx(ReadMoreLink, {})] })));
|
|
74
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare enum MENU_ACTION_TYPE {
|
|
3
|
+
SUBMENU = "SUBMENU",
|
|
4
|
+
LINK = "LINK"
|
|
5
|
+
}
|
|
6
|
+
export declare enum MENU_ORIENTATION {
|
|
7
|
+
HORIZONTAL = "HORIZONTAL",
|
|
8
|
+
VERTICAL = "VERTICAL"
|
|
9
|
+
}
|
|
10
|
+
type SubmenuAction = {
|
|
11
|
+
type: MENU_ACTION_TYPE.SUBMENU;
|
|
12
|
+
submenu: Menu;
|
|
13
|
+
};
|
|
14
|
+
type LinkAction = {
|
|
15
|
+
type: MENU_ACTION_TYPE.LINK;
|
|
16
|
+
to: string;
|
|
17
|
+
};
|
|
18
|
+
type Action = SubmenuAction | LinkAction;
|
|
19
|
+
type MenuItem = {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
action: Action;
|
|
23
|
+
};
|
|
24
|
+
export type Menu = {
|
|
25
|
+
orientation: MENU_ORIENTATION;
|
|
26
|
+
items: MenuItem[];
|
|
27
|
+
};
|
|
28
|
+
type Path = string[];
|
|
29
|
+
type HtmlAttributes = Omit<React.HTMLAttributes<any>, 'color'>;
|
|
30
|
+
type MenuContextType = {
|
|
31
|
+
menu: Menu;
|
|
32
|
+
activePath: Path;
|
|
33
|
+
isOpen: boolean;
|
|
34
|
+
open: () => void;
|
|
35
|
+
close: () => void;
|
|
36
|
+
getMenuItem: (path: Path) => MenuItem | undefined;
|
|
37
|
+
getMenuItemProps: (path: Path) => HtmlAttributes;
|
|
38
|
+
getMenuProps: (path?: Path) => HtmlAttributes;
|
|
39
|
+
};
|
|
40
|
+
type MenuProviderProps = {
|
|
41
|
+
menu: Menu;
|
|
42
|
+
children: React.ReactNode | ((context: MenuContextType) => React.ReactNode);
|
|
43
|
+
};
|
|
44
|
+
export declare const useMenu: () => MenuContextType;
|
|
45
|
+
export declare const MenuProvider: React.FC<MenuProviderProps>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import { useEnvironment } from './env';
|
|
4
|
+
import { KEY_CODES, equals } from '../../utils/misc';
|
|
5
|
+
import { useUniqueHtmlId } from '../../utils/hooks/useUniqueHtmlId';
|
|
6
|
+
import { useCheckMidClick } from '../../utils/hooks/useCheckMidClick';
|
|
7
|
+
export var MENU_ACTION_TYPE;
|
|
8
|
+
(function (MENU_ACTION_TYPE) {
|
|
9
|
+
MENU_ACTION_TYPE["SUBMENU"] = "SUBMENU";
|
|
10
|
+
MENU_ACTION_TYPE["LINK"] = "LINK";
|
|
11
|
+
})(MENU_ACTION_TYPE || (MENU_ACTION_TYPE = {}));
|
|
12
|
+
export var MENU_ORIENTATION;
|
|
13
|
+
(function (MENU_ORIENTATION) {
|
|
14
|
+
MENU_ORIENTATION["HORIZONTAL"] = "HORIZONTAL";
|
|
15
|
+
MENU_ORIENTATION["VERTICAL"] = "VERTICAL";
|
|
16
|
+
})(MENU_ORIENTATION || (MENU_ORIENTATION = {}));
|
|
17
|
+
const MenuContext = React.createContext({
|
|
18
|
+
menu: { items: [], orientation: MENU_ORIENTATION.HORIZONTAL },
|
|
19
|
+
activePath: [],
|
|
20
|
+
isOpen: false,
|
|
21
|
+
open: () => { },
|
|
22
|
+
close: () => { },
|
|
23
|
+
getMenuItem: () => undefined,
|
|
24
|
+
getMenuItemProps: () => ({}),
|
|
25
|
+
getMenuProps: () => ({}),
|
|
26
|
+
});
|
|
27
|
+
const getAriaRoleDescription = (orientation) => {
|
|
28
|
+
if (orientation === MENU_ORIENTATION.HORIZONTAL) {
|
|
29
|
+
return 'Menu item, press right arrow to navigate to next item, press enter to select';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return 'Menu item, press down arrow to navigate to next item, press enter to select';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
export const useMenu = () => React.useContext(MenuContext);
|
|
36
|
+
const activeStyles = {
|
|
37
|
+
outline: '2px solid blue',
|
|
38
|
+
};
|
|
39
|
+
const inactiveStyles = {
|
|
40
|
+
outline: 'none',
|
|
41
|
+
};
|
|
42
|
+
export const MenuProvider = ({ menu, children, }) => {
|
|
43
|
+
const { flagInDevelopment } = useEnvironment();
|
|
44
|
+
const salt = useUniqueHtmlId();
|
|
45
|
+
const { isMidClick, elementProps: checkMidclickProps } = useCheckMidClick();
|
|
46
|
+
const [usingKeyboard, setUsingKeyboard] = useState(false);
|
|
47
|
+
const closeOnBlurTimeout = React.useRef();
|
|
48
|
+
const initialPath = React.useMemo(() => [menu.items[0].id], [menu]);
|
|
49
|
+
const [activePath, setActivePath] = useState(initialPath);
|
|
50
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
51
|
+
const getItemId = React.useCallback((path) => `menu-${salt}-item-${path.join('-')}`, [salt]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (activePath && isOpen) {
|
|
54
|
+
const activeChild = window.document.getElementById(getItemId(activePath));
|
|
55
|
+
activeChild === null || activeChild === void 0 ? void 0 : activeChild.focus();
|
|
56
|
+
clearTimeout(closeOnBlurTimeout.current);
|
|
57
|
+
}
|
|
58
|
+
}, [activePath, getItemId, isOpen]);
|
|
59
|
+
const open = React.useCallback(() => {
|
|
60
|
+
setIsOpen(true);
|
|
61
|
+
}, []);
|
|
62
|
+
const close = React.useCallback(() => {
|
|
63
|
+
setIsOpen(false);
|
|
64
|
+
setUsingKeyboard(false);
|
|
65
|
+
}, []);
|
|
66
|
+
const getMenuItem = React.useCallback((path) => {
|
|
67
|
+
let menuItem = undefined;
|
|
68
|
+
for (const pathSegment of path) {
|
|
69
|
+
if (!menuItem) {
|
|
70
|
+
menuItem = menu.items.find((item) => item.id === pathSegment);
|
|
71
|
+
}
|
|
72
|
+
else if (menuItem.action.type === MENU_ACTION_TYPE.SUBMENU) {
|
|
73
|
+
menuItem = menuItem.action.submenu.items.find((item) => item.id === pathSegment);
|
|
74
|
+
}
|
|
75
|
+
if (!menuItem) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return menuItem;
|
|
80
|
+
}, [menu]);
|
|
81
|
+
const activeMenuItem = React.useMemo(() => getMenuItem(activePath), [activePath, getMenuItem]);
|
|
82
|
+
const activeParentMenu = React.useMemo(() => {
|
|
83
|
+
let parentMenu = menu;
|
|
84
|
+
const tempActivePath = [...activePath];
|
|
85
|
+
tempActivePath.pop();
|
|
86
|
+
if (tempActivePath.length > 0) {
|
|
87
|
+
const parentMenuItem = getMenuItem(tempActivePath);
|
|
88
|
+
if ((parentMenuItem === null || parentMenuItem === void 0 ? void 0 : parentMenuItem.action.type) === MENU_ACTION_TYPE.SUBMENU) {
|
|
89
|
+
parentMenu = parentMenuItem === null || parentMenuItem === void 0 ? void 0 : parentMenuItem.action.submenu;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
flagInDevelopment('');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return parentMenu;
|
|
96
|
+
}, [activePath, menu, getMenuItem, flagInDevelopment]);
|
|
97
|
+
const activeIndex = React.useMemo(() => {
|
|
98
|
+
return activeParentMenu.items.findIndex((item) => item.id === activePath[activePath.length - 1]);
|
|
99
|
+
}, [activeParentMenu, activePath]);
|
|
100
|
+
const currentMenuLength = activeParentMenu.items.length;
|
|
101
|
+
const onFocus = React.useCallback(() => {
|
|
102
|
+
if (!isMidClick.current) {
|
|
103
|
+
setUsingKeyboard(true);
|
|
104
|
+
open();
|
|
105
|
+
}
|
|
106
|
+
}, [isMidClick, open]);
|
|
107
|
+
const onBlur = React.useCallback(() => {
|
|
108
|
+
closeOnBlurTimeout.current = setTimeout(() => {
|
|
109
|
+
close();
|
|
110
|
+
setActivePath(initialPath);
|
|
111
|
+
}, 300);
|
|
112
|
+
}, [close, initialPath]);
|
|
113
|
+
const onKeyDown = React.useCallback((e) => {
|
|
114
|
+
const navigateNext = () => {
|
|
115
|
+
const nextIndex = (activeIndex + 1) % currentMenuLength;
|
|
116
|
+
const nextId = activeParentMenu.items[nextIndex].id;
|
|
117
|
+
setActivePath([...activePath.slice(0, activePath.length - 1), nextId]);
|
|
118
|
+
};
|
|
119
|
+
const navigatePrevious = () => {
|
|
120
|
+
if (activeIndex === 0) {
|
|
121
|
+
navigateOut();
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const prevIndex = activeIndex - 1;
|
|
125
|
+
const prevId = activeParentMenu.items[prevIndex].id;
|
|
126
|
+
setActivePath([...activePath.slice(0, activePath.length - 1), prevId]);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const navigateIn = () => {
|
|
130
|
+
var _a;
|
|
131
|
+
if (((_a = activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.action) === null || _a === void 0 ? void 0 : _a.type) === MENU_ACTION_TYPE.SUBMENU) {
|
|
132
|
+
setActivePath([
|
|
133
|
+
...activePath,
|
|
134
|
+
activeMenuItem.action.submenu.items[0].id,
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
navigateNext();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const navigateOut = () => {
|
|
142
|
+
if (activePath.length > 1) {
|
|
143
|
+
setActivePath(activePath.slice(0, activePath.length - 1));
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const select = () => {
|
|
147
|
+
if ((activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.action.type) === MENU_ACTION_TYPE.SUBMENU) {
|
|
148
|
+
setActivePath(activePath.concat([activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.id]));
|
|
149
|
+
}
|
|
150
|
+
else if ((activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.action.type) === MENU_ACTION_TYPE.LINK) {
|
|
151
|
+
window.location.href = activeMenuItem.action.to;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const isVertical = activeParentMenu.orientation === MENU_ORIENTATION.VERTICAL;
|
|
155
|
+
if (e.key === KEY_CODES.ENTER) {
|
|
156
|
+
if ((activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.action.type) === MENU_ACTION_TYPE.LINK) {
|
|
157
|
+
select();
|
|
158
|
+
}
|
|
159
|
+
else if ((activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.action.type) === MENU_ACTION_TYPE.SUBMENU) {
|
|
160
|
+
navigateIn();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
setUsingKeyboard(true);
|
|
165
|
+
}
|
|
166
|
+
if (e.key === KEY_CODES.ESCAPE) {
|
|
167
|
+
if (activePath.length > 1) {
|
|
168
|
+
navigateOut();
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const activeChild = window.document.getElementById(getItemId(activePath));
|
|
172
|
+
activeChild === null || activeChild === void 0 ? void 0 : activeChild.blur();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (e.key === KEY_CODES.ARROW_DOWN) {
|
|
176
|
+
if (isVertical) {
|
|
177
|
+
navigateNext();
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
navigateIn();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (e.key === KEY_CODES.ARROW_UP) {
|
|
184
|
+
if (isVertical) {
|
|
185
|
+
navigatePrevious();
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
navigateOut();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (e.key === KEY_CODES.ARROW_RIGHT) {
|
|
192
|
+
if (isVertical) {
|
|
193
|
+
navigateIn();
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
navigateNext();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (e.key === KEY_CODES.ARROW_LEFT) {
|
|
200
|
+
if (isVertical) {
|
|
201
|
+
navigateOut();
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
navigatePrevious();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}, [
|
|
208
|
+
activePath,
|
|
209
|
+
activeIndex,
|
|
210
|
+
activeMenuItem,
|
|
211
|
+
activeParentMenu,
|
|
212
|
+
currentMenuLength,
|
|
213
|
+
getItemId,
|
|
214
|
+
]);
|
|
215
|
+
const getMenuProps = React.useCallback((path) => {
|
|
216
|
+
const isTopLevel = !path;
|
|
217
|
+
let _menu = menu;
|
|
218
|
+
let menuItem = undefined;
|
|
219
|
+
if (path) {
|
|
220
|
+
menuItem = getMenuItem(path);
|
|
221
|
+
if ((menuItem === null || menuItem === void 0 ? void 0 : menuItem.action.type) === MENU_ACTION_TYPE.SUBMENU) {
|
|
222
|
+
_menu = menuItem.action.submenu;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const isVertical = _menu.orientation === MENU_ORIENTATION.VERTICAL;
|
|
226
|
+
const topLevelProps = Object.assign(Object.assign({}, checkMidclickProps), { onKeyDown,
|
|
227
|
+
onFocus,
|
|
228
|
+
onBlur });
|
|
229
|
+
return Object.assign({ role: 'menu', 'aria-orientation': isVertical ? 'vertical' : 'horizontal', tabIndex: isTopLevel ? 0 : -1 }, (isTopLevel ? topLevelProps : {}));
|
|
230
|
+
}, [menu, onFocus, onBlur, checkMidclickProps, getMenuItem, onKeyDown]);
|
|
231
|
+
const getMenuItemProps = React.useCallback((path) => {
|
|
232
|
+
const isTopLevel = path.length === 1;
|
|
233
|
+
const isActivePath = equals(path, activePath);
|
|
234
|
+
return Object.assign(Object.assign({}, checkMidclickProps), { role: 'menuitem', 'aria-roledescription': getAriaRoleDescription(activeParentMenu.orientation), id: getItemId(path), onKeyDown: equals(path, activePath) ? onKeyDown : undefined, tabIndex: -1, onFocus: () => {
|
|
235
|
+
// Screen readers will send focus to buttons without firing keydown or click
|
|
236
|
+
// Call setActivePath to sync
|
|
237
|
+
if (!isMidClick) {
|
|
238
|
+
setActivePath(path);
|
|
239
|
+
}
|
|
240
|
+
}, onMouseDown: () => {
|
|
241
|
+
checkMidclickProps.onMouseDown();
|
|
242
|
+
const menuItem = getMenuItem(path);
|
|
243
|
+
// Because blurring will close the dropdown menu, link navigation should be
|
|
244
|
+
// triggered before that happened. Mousedown is used instead of click because
|
|
245
|
+
// it is triggered before blur event
|
|
246
|
+
if ((menuItem === null || menuItem === void 0 ? void 0 : menuItem.action.type) === MENU_ACTION_TYPE.LINK) {
|
|
247
|
+
window.location.href = menuItem.action.to;
|
|
248
|
+
}
|
|
249
|
+
}, onClick: (e) => {
|
|
250
|
+
const menuItem = getMenuItem(path);
|
|
251
|
+
const isSubmenu = (menuItem === null || menuItem === void 0 ? void 0 : menuItem.action.type) === MENU_ACTION_TYPE.SUBMENU;
|
|
252
|
+
if (!isSubmenu) {
|
|
253
|
+
// Link menu items should not trigger navigation because that is handled by mousedown listener
|
|
254
|
+
e.preventDefault();
|
|
255
|
+
}
|
|
256
|
+
// If user is using a mouse, clicking the top level menu that is open
|
|
257
|
+
// should close the menu
|
|
258
|
+
if (isSubmenu &&
|
|
259
|
+
isActivePath &&
|
|
260
|
+
isTopLevel &&
|
|
261
|
+
!usingKeyboard &&
|
|
262
|
+
isOpen) {
|
|
263
|
+
close();
|
|
264
|
+
// Clicking a top level menu that is closed or not the active menu should
|
|
265
|
+
// open that menu
|
|
266
|
+
}
|
|
267
|
+
else if (isSubmenu && isTopLevel && !usingKeyboard && !isOpen) {
|
|
268
|
+
setActivePath(path);
|
|
269
|
+
open();
|
|
270
|
+
// If user is using a mouse, or if the menu is a link, handle the same way
|
|
271
|
+
// as enter key press
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
onKeyDown({
|
|
275
|
+
key: KEY_CODES.ENTER,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}, style: isOpen && usingKeyboard && equals(path, activePath)
|
|
279
|
+
? activeStyles
|
|
280
|
+
: inactiveStyles });
|
|
281
|
+
}, [
|
|
282
|
+
getItemId,
|
|
283
|
+
getMenuItem,
|
|
284
|
+
activePath,
|
|
285
|
+
isOpen,
|
|
286
|
+
checkMidclickProps,
|
|
287
|
+
close,
|
|
288
|
+
open,
|
|
289
|
+
onKeyDown,
|
|
290
|
+
usingKeyboard,
|
|
291
|
+
activeParentMenu,
|
|
292
|
+
isMidClick,
|
|
293
|
+
]);
|
|
294
|
+
const contextValue = {
|
|
295
|
+
menu,
|
|
296
|
+
isOpen,
|
|
297
|
+
open,
|
|
298
|
+
close,
|
|
299
|
+
activePath,
|
|
300
|
+
getMenuItem,
|
|
301
|
+
getMenuProps,
|
|
302
|
+
getMenuItemProps,
|
|
303
|
+
};
|
|
304
|
+
return (_jsx(MenuContext.Provider, Object.assign({ value: contextValue }, { children: typeof children === 'function' ? children(contextValue) : children })));
|
|
305
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { theme, ThemeProvider } from './theme';
|
|
1
|
+
export { theme, ThemeProvider, useTheme } from './theme';
|
|
2
2
|
export { COLOR } from './theme/colors';
|
|
3
3
|
export { TYPOGRAPHY_TYPE, FONT, FONT_SIZE, FONT_WEIGHT, LINE_HEIGHT, } from './theme/typography';
|
|
4
4
|
export { Alert, Alerts } from './components/elements/Alerts';
|
|
@@ -13,6 +13,18 @@ export { Box } from './components/elements/layout/Box';
|
|
|
13
13
|
export { Column } from './components/elements/layout/Column';
|
|
14
14
|
export { Row } from './components/elements/layout/Row';
|
|
15
15
|
export { Link, LINK_SIZE } from './components/elements/Link';
|
|
16
|
+
export { NavMenu } from './components/composites/NavMenu';
|
|
17
|
+
export { INPUT_SIZE, TextInput } from './components/elements/Fields/TextInput';
|
|
18
|
+
export { Select } from './components/elements/Fields/Select';
|
|
19
|
+
export { DatePicker } from './components/elements/Fields/DatePicker';
|
|
20
|
+
export { MonthPicker } from './components/elements/Fields/MonthPicker';
|
|
21
|
+
export { Checkbox } from './components/elements/Fields/Checkbox';
|
|
22
|
+
export { CheckboxGroup } from './components/elements/Fields/CheckboxGroup';
|
|
23
|
+
export { Radio } from './components/elements/Fields/Radio';
|
|
24
|
+
export { RadioGroup } from './components/elements/Fields/RadioGroup';
|
|
25
|
+
export { List, ListItem, LIST_SIZE } from './components/elements/List';
|
|
26
|
+
export { ReadMore } from './components/elements/text/ReadMore';
|
|
16
27
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
17
28
|
export { UiProvider } from './components/providers/ui';
|
|
29
|
+
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
18
30
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { theme, ThemeProvider } from './theme';
|
|
1
|
+
export { theme, ThemeProvider, useTheme } from './theme';
|
|
2
2
|
export { COLOR } from './theme/colors';
|
|
3
3
|
export { TYPOGRAPHY_TYPE, FONT, FONT_SIZE, FONT_WEIGHT, LINE_HEIGHT, } from './theme/typography';
|
|
4
4
|
export { Alert, Alerts } from './components/elements/Alerts';
|
|
@@ -13,6 +13,18 @@ export { Box } from './components/elements/layout/Box';
|
|
|
13
13
|
export { Column } from './components/elements/layout/Column';
|
|
14
14
|
export { Row } from './components/elements/layout/Row';
|
|
15
15
|
export { Link, LINK_SIZE } from './components/elements/Link';
|
|
16
|
+
export { NavMenu } from './components/composites/NavMenu';
|
|
17
|
+
export { INPUT_SIZE, TextInput } from './components/elements/Fields/TextInput';
|
|
18
|
+
export { Select } from './components/elements/Fields/Select';
|
|
19
|
+
export { DatePicker } from './components/elements/Fields/DatePicker';
|
|
20
|
+
export { MonthPicker } from './components/elements/Fields/MonthPicker';
|
|
21
|
+
export { Checkbox } from './components/elements/Fields/Checkbox';
|
|
22
|
+
export { CheckboxGroup } from './components/elements/Fields/CheckboxGroup';
|
|
23
|
+
export { Radio } from './components/elements/Fields/Radio';
|
|
24
|
+
export { RadioGroup } from './components/elements/Fields/RadioGroup';
|
|
25
|
+
export { List, ListItem, LIST_SIZE } from './components/elements/List';
|
|
26
|
+
export { ReadMore } from './components/elements/text/ReadMore';
|
|
16
27
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
17
28
|
export { UiProvider } from './components/providers/ui';
|
|
29
|
+
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
18
30
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const GlobalStyles: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Global, css } from '@emotion/react';
|
|
3
|
+
import { colors } from './colors';
|
|
4
|
+
const globalStyles = css `
|
|
5
|
+
html,
|
|
6
|
+
body,
|
|
7
|
+
div,
|
|
8
|
+
span,
|
|
9
|
+
applet,
|
|
10
|
+
object,
|
|
11
|
+
iframe,
|
|
12
|
+
h1,
|
|
13
|
+
h2,
|
|
14
|
+
h3,
|
|
15
|
+
h4,
|
|
16
|
+
h5,
|
|
17
|
+
h6,
|
|
18
|
+
p,
|
|
19
|
+
blockquote,
|
|
20
|
+
pre,
|
|
21
|
+
a,
|
|
22
|
+
abbr,
|
|
23
|
+
acronym,
|
|
24
|
+
address,
|
|
25
|
+
big,
|
|
26
|
+
cite,
|
|
27
|
+
code,
|
|
28
|
+
del,
|
|
29
|
+
dfn,
|
|
30
|
+
em,
|
|
31
|
+
img,
|
|
32
|
+
ins,
|
|
33
|
+
kbd,
|
|
34
|
+
q,
|
|
35
|
+
s,
|
|
36
|
+
samp,
|
|
37
|
+
small,
|
|
38
|
+
strike,
|
|
39
|
+
strong,
|
|
40
|
+
sub,
|
|
41
|
+
sup,
|
|
42
|
+
tt,
|
|
43
|
+
var,
|
|
44
|
+
b,
|
|
45
|
+
u,
|
|
46
|
+
i,
|
|
47
|
+
center,
|
|
48
|
+
dl,
|
|
49
|
+
dt,
|
|
50
|
+
dd,
|
|
51
|
+
ol,
|
|
52
|
+
ul,
|
|
53
|
+
li,
|
|
54
|
+
fieldset,
|
|
55
|
+
form,
|
|
56
|
+
label,
|
|
57
|
+
legend,
|
|
58
|
+
table,
|
|
59
|
+
caption,
|
|
60
|
+
tbody,
|
|
61
|
+
tfoot,
|
|
62
|
+
thead,
|
|
63
|
+
tr,
|
|
64
|
+
th,
|
|
65
|
+
td,
|
|
66
|
+
article,
|
|
67
|
+
aside,
|
|
68
|
+
canvas,
|
|
69
|
+
details,
|
|
70
|
+
embed,
|
|
71
|
+
figure,
|
|
72
|
+
figcaption,
|
|
73
|
+
footer,
|
|
74
|
+
header,
|
|
75
|
+
hgroup,
|
|
76
|
+
menu,
|
|
77
|
+
nav,
|
|
78
|
+
output,
|
|
79
|
+
ruby,
|
|
80
|
+
section,
|
|
81
|
+
summary,
|
|
82
|
+
time,
|
|
83
|
+
mark,
|
|
84
|
+
audio,
|
|
85
|
+
video {
|
|
86
|
+
margin: 0;
|
|
87
|
+
padding: 0;
|
|
88
|
+
border: 0;
|
|
89
|
+
font-size: 100%;
|
|
90
|
+
font: inherit;
|
|
91
|
+
vertical-align: baseline;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* HTML5 display-role reset for older browsers */
|
|
95
|
+
article,
|
|
96
|
+
aside,
|
|
97
|
+
details,
|
|
98
|
+
figcaption,
|
|
99
|
+
figure,
|
|
100
|
+
footer,
|
|
101
|
+
header,
|
|
102
|
+
hgroup,
|
|
103
|
+
menu,
|
|
104
|
+
nav,
|
|
105
|
+
section {
|
|
106
|
+
display: block;
|
|
107
|
+
}
|
|
108
|
+
body {
|
|
109
|
+
line-height: 1;
|
|
110
|
+
font-size: 16px;
|
|
111
|
+
}
|
|
112
|
+
ol,
|
|
113
|
+
ul {
|
|
114
|
+
list-style: none;
|
|
115
|
+
}
|
|
116
|
+
blockquote,
|
|
117
|
+
q {
|
|
118
|
+
quotes: none;
|
|
119
|
+
}
|
|
120
|
+
blockquote:before,
|
|
121
|
+
blockquote:after,
|
|
122
|
+
q:before,
|
|
123
|
+
q:after {
|
|
124
|
+
content: '';
|
|
125
|
+
content: none;
|
|
126
|
+
}
|
|
127
|
+
table {
|
|
128
|
+
border-collapse: collapse;
|
|
129
|
+
border-spacing: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ndlib-date-picker .react-datepicker__header,
|
|
133
|
+
.ndlib-date-picker .react-datepicker__header * {
|
|
134
|
+
color: white;
|
|
135
|
+
background-color: ${colors.primary};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.ndlib-date-picker .react-datepicker__header {
|
|
139
|
+
width: 280px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.ndlib-date-picker .react-datepicker__day-names {
|
|
143
|
+
margin-top: 4px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.ndlib-date-picker .react-datepicker__month .react-datepicker__month-text {
|
|
147
|
+
padding: 4px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@font-face {
|
|
151
|
+
font-family: GPCMed;
|
|
152
|
+
font-display: swap;
|
|
153
|
+
src: url('https://static.nd.edu/fonts/gp-min/gpc-medium.woff2')
|
|
154
|
+
format('woff2'),
|
|
155
|
+
url('https://static.nd.edu/fonts/gp-min/gpc-medium.woff') format('woff'),
|
|
156
|
+
url('https://static.nd.edu/fonts/gp-min/gpc-medium.ttf')
|
|
157
|
+
format('truetype');
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
export const GlobalStyles = () => {
|
|
161
|
+
return _jsx(Global, { styles: globalStyles });
|
|
162
|
+
};
|
package/dist/theme/colors.d.ts
CHANGED
package/dist/theme/colors.js
CHANGED
|
@@ -12,6 +12,7 @@ export var COLOR;
|
|
|
12
12
|
COLOR["LIGHT_GRAY"] = "lightGray";
|
|
13
13
|
COLOR["FAINT_GRAY"] = "faintGray";
|
|
14
14
|
COLOR["ND_BLUE"] = "ndBlue";
|
|
15
|
+
COLOR["ND_BLUE_LIGHT"] = "ndBlueLight";
|
|
15
16
|
COLOR["ND_GOLD"] = "ndGold";
|
|
16
17
|
COLOR["ND_SKY_BLUE"] = "ndSkyBlue";
|
|
17
18
|
COLOR["ND_SKY_BLUE_DARK"] = "ndSkyBlueDark";
|
|
@@ -49,6 +50,7 @@ export const colors = {
|
|
|
49
50
|
[COLOR.LIGHT_GRAY]: '#949494',
|
|
50
51
|
[COLOR.FAINT_GRAY]: '#eeeeee',
|
|
51
52
|
[COLOR.ND_BLUE]: '#0c2340',
|
|
53
|
+
[COLOR.ND_BLUE_LIGHT]: '#143865',
|
|
52
54
|
[COLOR.ND_GOLD]: '#d39F10',
|
|
53
55
|
[COLOR.ND_SKY_BLUE]: '#e1e8f2',
|
|
54
56
|
[COLOR.ND_SKY_BLUE_DARK]: '#c1cddd',
|
package/dist/theme/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare const theme: {
|
|
|
18
18
|
lightGray: string;
|
|
19
19
|
faintGray: string;
|
|
20
20
|
ndBlue: string;
|
|
21
|
+
ndBlueLight: string;
|
|
21
22
|
ndGold: string;
|
|
22
23
|
ndSkyBlue: string;
|
|
23
24
|
ndSkyBlueDark: string;
|
|
@@ -99,6 +100,7 @@ export declare const useTheme: () => {
|
|
|
99
100
|
lightGray: string;
|
|
100
101
|
faintGray: string;
|
|
101
102
|
ndBlue: string;
|
|
103
|
+
ndBlueLight: string;
|
|
102
104
|
ndGold: string;
|
|
103
105
|
ndSkyBlue: string;
|
|
104
106
|
ndSkyBlueDark: string;
|