@ndlib/component-library 0.0.17 → 0.0.19
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/providers/menu.d.ts +46 -0
- package/dist/components/providers/menu.js +305 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +11 -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/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,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { NavMenu } from './';
|
|
3
|
+
import { DemoMenuImplementation } from './demo';
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Composites/NavMenu',
|
|
6
|
+
component: NavMenu,
|
|
7
|
+
};
|
|
8
|
+
export default meta;
|
|
9
|
+
export const Default = {
|
|
10
|
+
render: () => _jsx(DemoMenuImplementation, {}),
|
|
11
|
+
args: {},
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { fireEvent } from '@testing-library/react';
|
|
3
|
+
import { render } from '../../../utils/test';
|
|
4
|
+
import { KEY_CODES } from '../../../utils/misc';
|
|
5
|
+
import { DemoMenuImplementation } from './demo';
|
|
6
|
+
describe('NavMenu', () => {
|
|
7
|
+
it('can be navigated with events', () => {
|
|
8
|
+
const { getByRole } = render(_jsx(DemoMenuImplementation, {}));
|
|
9
|
+
const menu = getByRole('menu');
|
|
10
|
+
const firstMenuItem = getByRole('menuitem', {
|
|
11
|
+
name: 'test menu 1',
|
|
12
|
+
});
|
|
13
|
+
const secondMenuItem = getByRole('menuitem', {
|
|
14
|
+
name: 'test menu 2',
|
|
15
|
+
});
|
|
16
|
+
fireEvent.focus(menu);
|
|
17
|
+
expect(firstMenuItem).toHaveFocus();
|
|
18
|
+
fireEvent.keyDown(firstMenuItem, {
|
|
19
|
+
key: KEY_CODES.ARROW_RIGHT,
|
|
20
|
+
});
|
|
21
|
+
expect(secondMenuItem).toHaveFocus();
|
|
22
|
+
const firstSubmenuItem = getByRole('menuitem', {
|
|
23
|
+
name: 'test submenu 1',
|
|
24
|
+
});
|
|
25
|
+
const secondSubmenuItem = getByRole('menuitem', {
|
|
26
|
+
name: 'test submenu 2',
|
|
27
|
+
});
|
|
28
|
+
const firstLeaf = getByRole('menuitem', {
|
|
29
|
+
name: 'test leaf 1',
|
|
30
|
+
});
|
|
31
|
+
const secondLeaf = getByRole('menuitem', {
|
|
32
|
+
name: 'test leaf 2',
|
|
33
|
+
});
|
|
34
|
+
fireEvent.keyDown(secondMenuItem, {
|
|
35
|
+
key: KEY_CODES.ARROW_DOWN,
|
|
36
|
+
});
|
|
37
|
+
expect(firstSubmenuItem).toHaveFocus();
|
|
38
|
+
fireEvent.keyDown(firstMenuItem, {
|
|
39
|
+
key: KEY_CODES.ARROW_RIGHT,
|
|
40
|
+
});
|
|
41
|
+
expect(secondSubmenuItem).toHaveFocus();
|
|
42
|
+
fireEvent.keyDown(secondMenuItem, {
|
|
43
|
+
key: KEY_CODES.ARROW_LEFT,
|
|
44
|
+
});
|
|
45
|
+
expect(firstSubmenuItem).toHaveFocus();
|
|
46
|
+
fireEvent.keyDown(secondMenuItem, {
|
|
47
|
+
key: KEY_CODES.ENTER,
|
|
48
|
+
});
|
|
49
|
+
expect(firstLeaf).toHaveFocus();
|
|
50
|
+
fireEvent.keyDown(firstLeaf, {
|
|
51
|
+
key: KEY_CODES.ARROW_DOWN,
|
|
52
|
+
});
|
|
53
|
+
expect(secondLeaf).toHaveFocus();
|
|
54
|
+
fireEvent.keyDown(secondLeaf, {
|
|
55
|
+
key: KEY_CODES.ARROW_UP,
|
|
56
|
+
});
|
|
57
|
+
expect(firstLeaf).toHaveFocus();
|
|
58
|
+
fireEvent.keyDown(firstLeaf, {
|
|
59
|
+
key: KEY_CODES.ARROW_UP,
|
|
60
|
+
});
|
|
61
|
+
expect(firstSubmenuItem).toHaveFocus();
|
|
62
|
+
fireEvent.keyDown(firstSubmenuItem, {
|
|
63
|
+
key: KEY_CODES.ARROW_UP,
|
|
64
|
+
});
|
|
65
|
+
expect(secondMenuItem).toHaveFocus();
|
|
66
|
+
});
|
|
67
|
+
it('can be navigated with keyboard events', () => {
|
|
68
|
+
const { getByRole } = render(_jsx(DemoMenuImplementation, {}));
|
|
69
|
+
const secondMenuItem = getByRole('menuitem', {
|
|
70
|
+
name: 'test menu 2',
|
|
71
|
+
});
|
|
72
|
+
fireEvent.mouseDown(secondMenuItem);
|
|
73
|
+
fireEvent.click(secondMenuItem);
|
|
74
|
+
fireEvent.mouseUp(secondMenuItem);
|
|
75
|
+
getByRole('menuitem', {
|
|
76
|
+
name: 'test submenu 1',
|
|
77
|
+
});
|
|
78
|
+
getByRole('menuitem', {
|
|
79
|
+
name: 'test submenu 2',
|
|
80
|
+
});
|
|
81
|
+
getByRole('menuitem', {
|
|
82
|
+
name: 'test leaf 1',
|
|
83
|
+
});
|
|
84
|
+
getByRole('menuitem', {
|
|
85
|
+
name: 'test leaf 2',
|
|
86
|
+
});
|
|
87
|
+
fireEvent.mouseDown(secondMenuItem);
|
|
88
|
+
fireEvent.click(secondMenuItem);
|
|
89
|
+
fireEvent.mouseUp(secondMenuItem);
|
|
90
|
+
expect(() => {
|
|
91
|
+
getByRole('menuitem', {
|
|
92
|
+
name: 'test submenu 1',
|
|
93
|
+
});
|
|
94
|
+
}).toThrow();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DemoMenuImplementation: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createElement as _createElement } from "react";
|
|
3
|
+
import { NavMenu } from '.';
|
|
4
|
+
import { Button } from '../../elements/Button';
|
|
5
|
+
import { Row } from '../../elements/layout/Row';
|
|
6
|
+
import { MENU_ACTION_TYPE, MENU_ORIENTATION, MenuProvider, } from '../../providers/menu';
|
|
7
|
+
const demoMenu = {
|
|
8
|
+
orientation: MENU_ORIENTATION.HORIZONTAL,
|
|
9
|
+
items: [
|
|
10
|
+
{
|
|
11
|
+
id: 'test-menu-1',
|
|
12
|
+
label: 'test menu 1',
|
|
13
|
+
action: {
|
|
14
|
+
type: MENU_ACTION_TYPE.LINK,
|
|
15
|
+
to: '/',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: 'test-menu-2',
|
|
20
|
+
label: 'test menu 2',
|
|
21
|
+
action: {
|
|
22
|
+
type: MENU_ACTION_TYPE.SUBMENU,
|
|
23
|
+
submenu: {
|
|
24
|
+
orientation: MENU_ORIENTATION.HORIZONTAL,
|
|
25
|
+
items: [
|
|
26
|
+
{
|
|
27
|
+
label: 'test submenu 1',
|
|
28
|
+
id: 'test-submenu-1',
|
|
29
|
+
action: {
|
|
30
|
+
type: MENU_ACTION_TYPE.SUBMENU,
|
|
31
|
+
submenu: {
|
|
32
|
+
orientation: MENU_ORIENTATION.VERTICAL,
|
|
33
|
+
items: [
|
|
34
|
+
{
|
|
35
|
+
label: 'test leaf 1',
|
|
36
|
+
id: 'test-leaf-1',
|
|
37
|
+
action: {
|
|
38
|
+
type: MENU_ACTION_TYPE.LINK,
|
|
39
|
+
to: '/',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: 'test leaf 2',
|
|
44
|
+
id: 'test-leaf-2',
|
|
45
|
+
action: {
|
|
46
|
+
type: MENU_ACTION_TYPE.LINK,
|
|
47
|
+
to: '/',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
action: {
|
|
56
|
+
type: MENU_ACTION_TYPE.SUBMENU,
|
|
57
|
+
submenu: {
|
|
58
|
+
orientation: MENU_ORIENTATION.VERTICAL,
|
|
59
|
+
items: [
|
|
60
|
+
{
|
|
61
|
+
label: 'test leaf 3',
|
|
62
|
+
id: 'test-leaf-3',
|
|
63
|
+
action: {
|
|
64
|
+
type: MENU_ACTION_TYPE.LINK,
|
|
65
|
+
to: '/',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: 'test leaf 4',
|
|
70
|
+
id: 'test-leaf-4',
|
|
71
|
+
action: {
|
|
72
|
+
type: MENU_ACTION_TYPE.LINK,
|
|
73
|
+
to: '/',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
label: 'test submenu 2',
|
|
80
|
+
id: 'test-submenu-2',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
// This is needed because NavMenu doesn't control rendering of top-level menu items
|
|
89
|
+
export const DemoMenuImplementation = () => (_jsx(MenuProvider, Object.assign({ menu: demoMenu }, { children: ({ menu, getMenuProps, getMenuItemProps }) => (_jsxs(_Fragment, { children: [_jsx(Row, Object.assign({}, getMenuProps(), { children: menu.items.map((menuItem) => (_createElement(Button, Object.assign({}, getMenuItemProps([menuItem.id]), { sx: { m: 1 }, key: menuItem.id }), menuItem.label))) })), _jsx(NavMenu, {})] })) })));
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
3
|
+
import { List, ListItem } from '../../elements/List';
|
|
4
|
+
import { MENU_ACTION_TYPE, useMenu } from '../../providers/menu';
|
|
5
|
+
import { Row } from '../../elements/layout/Row';
|
|
6
|
+
import { Column } from '../../elements/layout/Column';
|
|
7
|
+
import { HEADING_SIZE, Heading } from '../../elements/text/Heading';
|
|
8
|
+
import { Link } from '../../elements/Link';
|
|
9
|
+
import { LINE_HEIGHT } from '../../../theme/typography';
|
|
10
|
+
import { COLOR } from '../../../theme/colors';
|
|
11
|
+
export const NavMenu = (props) => {
|
|
12
|
+
const { isOpen, activePath, getMenuItem, getMenuItemProps, getMenuProps } = useMenu();
|
|
13
|
+
if (!isOpen) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const topLevelMenuId = activePath[0];
|
|
17
|
+
const activeTopLevelMenu = getMenuItem([topLevelMenuId]);
|
|
18
|
+
if (!activeTopLevelMenu ||
|
|
19
|
+
!(activeTopLevelMenu.action.type === MENU_ACTION_TYPE.SUBMENU)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const submenu = activeTopLevelMenu.action.submenu;
|
|
23
|
+
return (_jsxs(Row, Object.assign({}, props, { sx: {
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
justifyContent: 'center',
|
|
26
|
+
p: 3,
|
|
27
|
+
border: 'solid 1px',
|
|
28
|
+
borderColor: COLOR.FAINT_GRAY,
|
|
29
|
+
borderRadius: '4px',
|
|
30
|
+
} }, { children: [_jsx(Column, { sx: { flexGrow: 1 } }), submenu.items.map((submenuItem) => {
|
|
31
|
+
if (!(submenuItem.action.type === MENU_ACTION_TYPE.SUBMENU)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const leafMenuItems = submenuItem.action.submenu.items;
|
|
35
|
+
const submenuPath = [topLevelMenuId, submenuItem.id];
|
|
36
|
+
return (_jsxs(Column, Object.assign({ sx: { flexBasis: '275px', p: 2, flexShrink: 0, flexGrow: 0 } }, { children: [_jsx(Heading, Object.assign({ standalone: true, size: HEADING_SIZE.SM, underline: true }, getMenuItemProps(submenuPath), { children: submenuItem.label })), _jsx(List, Object.assign({}, getMenuProps(submenuPath), { icon: ChevronRightIcon }, { children: leafMenuItems.map((leafMenuItem, i) => {
|
|
37
|
+
const leafMenuPath = submenuPath.concat(leafMenuItem.id);
|
|
38
|
+
return (_jsx(ListItem, Object.assign({ index: i, sx: { mt: 1 } }, getMenuItemProps(leafMenuPath), { children: _jsx(Link, Object.assign({ to: "/", sx: { lineHeight: LINE_HEIGHT.CONDENSED } }, { children: leafMenuItem.label })) }), leafMenuItem.id));
|
|
39
|
+
}) }))] }), submenuItem.id));
|
|
40
|
+
}), _jsx(Column, { sx: { flexGrow: 1 } })] })));
|
|
41
|
+
};
|
|
@@ -137,7 +137,7 @@ export const Button = React.forwardRef((_a, ref) => {
|
|
|
137
137
|
justifyContent: 'center',
|
|
138
138
|
} }, { children: [_jsx(Spinner, { size: SPINNER_SIZE.SM, color: textColor, sx: { position: 'absolute' } }), _jsx("div", Object.assign({ sx: { visibility: 'hidden' } }, { children: body }))] })));
|
|
139
139
|
}
|
|
140
|
-
return (_jsxs("button", Object.assign({ ref: ref, disabled: disabled, onMouseEnter: () => {
|
|
140
|
+
return (_jsxs("button", Object.assign({ ref: ref, tabIndex: disabled ? -1 : 0, disabled: disabled, onMouseEnter: () => {
|
|
141
141
|
setHover(true);
|
|
142
142
|
}, onMouseLeave: () => {
|
|
143
143
|
setHover(false);
|
|
@@ -149,6 +149,15 @@ export const Button = React.forwardRef((_a, ref) => {
|
|
|
149
149
|
transform: hoverTransform,
|
|
150
150
|
textDecoration: hoverDecoration,
|
|
151
151
|
}
|
|
152
|
+
: undefined, ':focus': !disabled
|
|
153
|
+
? {
|
|
154
|
+
bg: hoverBg,
|
|
155
|
+
color: hoverTextColor,
|
|
156
|
+
boxShadow: hoverShadow,
|
|
157
|
+
cursor: 'pointer',
|
|
158
|
+
transform: hoverTransform,
|
|
159
|
+
textDecoration: hoverDecoration,
|
|
160
|
+
}
|
|
152
161
|
: undefined }, typographyStyles), sx) }, rest, { children: [leftIcon && (_jsx(Icon, { icon: leftIcon, size: typographyStyles.fontSize, sx: { mr: iconMargin[size] }, color: hover ? hoverTextColor : textColor })), _jsx("div", Object.assign({ css: {
|
|
153
162
|
flexGrow: 1,
|
|
154
163
|
justifyContent: 'flex-start',
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { DatePicker } from '.';
|
|
3
|
+
declare const meta: Meta<typeof DatePicker>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof DatePicker>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const Inline: Story;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { DatePicker } from '.';
|
|
4
|
+
import { Box } from '../../layout/Box';
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Elements/Fields/DatePicker',
|
|
7
|
+
component: DatePicker,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
};
|
|
10
|
+
export default meta;
|
|
11
|
+
const StatefulDatePicker = (props) => {
|
|
12
|
+
const [date, setDate] = useState(new Date());
|
|
13
|
+
return _jsx(DatePicker, Object.assign({}, props, { value: date, onChange: setDate }));
|
|
14
|
+
};
|
|
15
|
+
export const Default = {
|
|
16
|
+
render: () => (_jsx(Box, Object.assign({ sx: { height: '500px' } }, { children: _jsx(StatefulDatePicker, { placeholder: "test" }) }))),
|
|
17
|
+
};
|
|
18
|
+
export const Inline = {
|
|
19
|
+
render: () => (_jsx(Box, Object.assign({ sx: { height: '500px' } }, { children: _jsx(StatefulDatePicker, { inline: true }) }))),
|
|
20
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import 'react-datepicker/dist/react-datepicker.css';
|
|
3
|
+
import { TextInputProps } from '../TextInput';
|
|
4
|
+
import { BoxProps } from '../../layout/Box';
|
|
5
|
+
export declare const InputWrapper: React.ForwardRefExoticComponent<{
|
|
6
|
+
onChange?: ((e: React.ChangeEvent) => void) | undefined;
|
|
7
|
+
onClick?: ((e: React.MouseEvent) => void) | undefined;
|
|
8
|
+
value?: string | undefined;
|
|
9
|
+
children: React.ReactElement;
|
|
10
|
+
} & React.RefAttributes<any>>;
|
|
11
|
+
export declare const DatePicker: React.FC<{
|
|
12
|
+
value: Date;
|
|
13
|
+
onChange: (date: Date) => void;
|
|
14
|
+
minDate?: Date;
|
|
15
|
+
maxDate?: Date;
|
|
16
|
+
inline?: boolean;
|
|
17
|
+
wrapperProps?: BoxProps;
|
|
18
|
+
inputProps?: Partial<TextInputProps>;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,34 @@
|
|
|
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 } from "react/jsx-runtime";
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import ReactDatePicker from 'react-datepicker';
|
|
15
|
+
import 'react-datepicker/dist/react-datepicker.css';
|
|
16
|
+
import { TextInput } from '../TextInput';
|
|
17
|
+
import CalendarIcon from '@mui/icons-material/CalendarMonth';
|
|
18
|
+
import { Box } from '../../layout/Box';
|
|
19
|
+
// Need to do this to allow passing props to TextInput
|
|
20
|
+
// react-datepicker will overwrite all props passed to customInput
|
|
21
|
+
export const InputWrapper = React.forwardRef(({ onChange, value, children, onClick }, ref) => {
|
|
22
|
+
return React.cloneElement(children, {
|
|
23
|
+
value: value,
|
|
24
|
+
onChangeRaw: onChange,
|
|
25
|
+
ref: ref,
|
|
26
|
+
leftIcon: CalendarIcon,
|
|
27
|
+
onClick,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
const PermissiveTextInput = TextInput;
|
|
31
|
+
export const DatePicker = (_a) => {
|
|
32
|
+
var { value, wrapperProps, inputProps } = _a, rest = __rest(_a, ["value", "wrapperProps", "inputProps"]);
|
|
33
|
+
return (_jsx(Box, Object.assign({}, wrapperProps, { children: _jsx(ReactDatePicker, Object.assign({ calendarClassName: "ndlib-date-picker", selected: value, customInput: _jsx(InputWrapper, { children: _jsx(PermissiveTextInput, Object.assign({}, inputProps)) }) }, rest)) })));
|
|
34
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { MonthPicker } from '.';
|
|
3
|
+
declare const meta: Meta<typeof MonthPicker>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof MonthPicker>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const Inline: Story;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { MonthPicker } from '.';
|
|
4
|
+
import { Box } from '../../layout/Box';
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Elements/Fields/MonthPicker',
|
|
7
|
+
component: MonthPicker,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
};
|
|
10
|
+
export default meta;
|
|
11
|
+
const StatefulMonthPicker = (props) => {
|
|
12
|
+
const [date, setDate] = useState(new Date());
|
|
13
|
+
return _jsx(MonthPicker, Object.assign({}, props, { value: date, onChange: setDate }));
|
|
14
|
+
};
|
|
15
|
+
export const Default = {
|
|
16
|
+
render: () => (_jsx(Box, Object.assign({ sx: { height: '500px' } }, { children: _jsx(StatefulMonthPicker, {}) }))),
|
|
17
|
+
};
|
|
18
|
+
export const Inline = {
|
|
19
|
+
render: () => (_jsx(Box, Object.assign({ sx: { height: '500px' } }, { children: _jsx(StatefulMonthPicker, { inline: true }) }))),
|
|
20
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import 'react-datepicker/dist/react-datepicker.css';
|
|
3
|
+
import { TextInputProps } from '../TextInput';
|
|
4
|
+
import { BoxProps } from '../../layout/Box';
|
|
5
|
+
export declare const MonthPicker: React.FC<{
|
|
6
|
+
value: Date;
|
|
7
|
+
onChange: (date: Date) => void;
|
|
8
|
+
minDate?: Date;
|
|
9
|
+
maxDate?: Date;
|
|
10
|
+
inline?: boolean;
|
|
11
|
+
inputProps?: Partial<TextInputProps>;
|
|
12
|
+
wrapperProps?: BoxProps;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
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 } from "react/jsx-runtime";
|
|
13
|
+
import ReactDatePicker from 'react-datepicker';
|
|
14
|
+
import 'react-datepicker/dist/react-datepicker.css';
|
|
15
|
+
import { TextInput } from '../TextInput';
|
|
16
|
+
import { InputWrapper } from '../DatePicker';
|
|
17
|
+
import { Box } from '../../layout/Box';
|
|
18
|
+
const PermissiveTextInput = TextInput;
|
|
19
|
+
export const MonthPicker = (_a) => {
|
|
20
|
+
var { value, inputProps, wrapperProps } = _a, rest = __rest(_a, ["value", "inputProps", "wrapperProps"]);
|
|
21
|
+
return (_jsx(Box, Object.assign({}, wrapperProps, { children: _jsx(ReactDatePicker, Object.assign({ calendarClassName: "ndlib-date-picker", selected: value, customInput: _jsx(InputWrapper, { children: _jsx(PermissiveTextInput, Object.assign({}, inputProps)) }), showMonthYearPicker: true }, rest)) })));
|
|
22
|
+
};
|
|
@@ -4,13 +4,13 @@ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
|
|
4
4
|
import { useFloating, size as sizeMiddleware, offset, autoPlacement, } from '@floating-ui/react';
|
|
5
5
|
import { TYPOGRAPHY_TYPE, getTypographyStyles, } from '../../../../theme/typography';
|
|
6
6
|
import { useTheme } from '../../../../theme';
|
|
7
|
-
import { COLOR } from '../../../..';
|
|
8
7
|
import { INPUT_SIZE } from '../TextInput';
|
|
9
8
|
import { ListBox } from '../../ListBox';
|
|
10
9
|
import { BUTTON_SIZE, BUTTON_TYPE, Button } from '../../Button';
|
|
11
10
|
import { defaultRenderOptionLabel, getOptionId, } from '../option';
|
|
12
11
|
import { useUniqueHtmlId } from '../../../../utils/hooks/useUniqueHtmlId';
|
|
13
12
|
import { KEY_CODES } from '../../../../utils/misc';
|
|
13
|
+
import { COLOR } from '../../../../theme/colors';
|
|
14
14
|
const typographyMap = {
|
|
15
15
|
[INPUT_SIZE.SM]: TYPOGRAPHY_TYPE.PARAGRAPH_SMALL,
|
|
16
16
|
[INPUT_SIZE.MD]: TYPOGRAPHY_TYPE.PARAGRAPH_MEDIUM,
|
|
@@ -18,7 +18,7 @@ const sizes = [
|
|
|
18
18
|
];
|
|
19
19
|
const StatefulInput = (props) => {
|
|
20
20
|
const [value, setValue] = useState('');
|
|
21
|
-
return _jsx(TextInput, Object.assign({ value: value, onChange: setValue }, props));
|
|
21
|
+
return (_jsx(TextInput, Object.assign({ value: value, onChange: setValue, placeholder: "test" }, props)));
|
|
22
22
|
};
|
|
23
23
|
export const Default = {
|
|
24
24
|
render: () => (_jsx(Column, { children: sizes.map((size) => (_jsxs(Group, { children: [_jsx(Heading, Object.assign({ size: HEADING_SIZE.MD }, { children: size.label })), _jsx(StatefulInput, { size: size.size, leftIcon: SearchIcon, placeholder: "Placeholder", sx: { mt: 1 } })] }))) })),
|
|
@@ -6,12 +6,22 @@ export declare enum INPUT_SIZE {
|
|
|
6
6
|
MD = "md",
|
|
7
7
|
LG = "lg"
|
|
8
8
|
}
|
|
9
|
-
type TextInputProps = StyledElementProps<HTMLInputElement, {
|
|
9
|
+
export type TextInputProps = StyledElementProps<HTMLInputElement, {
|
|
10
10
|
size?: INPUT_SIZE;
|
|
11
11
|
leftIcon?: React.FC<any>;
|
|
12
12
|
inline?: boolean;
|
|
13
13
|
value: string;
|
|
14
|
-
onChange
|
|
14
|
+
onChange?: (value: string) => void;
|
|
15
|
+
onChangeRaw?: (e: string | React.ChangeEvent) => void;
|
|
15
16
|
}, string>;
|
|
16
|
-
export declare const TextInput: React.
|
|
17
|
-
|
|
17
|
+
export declare const TextInput: React.ForwardRefExoticComponent<{
|
|
18
|
+
sx?: import("../../../../theme").StylesProp | undefined;
|
|
19
|
+
children?: string | undefined;
|
|
20
|
+
} & React.HTMLAttributes<HTMLInputElement> & {
|
|
21
|
+
size?: INPUT_SIZE | undefined;
|
|
22
|
+
leftIcon?: React.FC<any> | undefined;
|
|
23
|
+
inline?: boolean | undefined;
|
|
24
|
+
value: string;
|
|
25
|
+
onChange?: ((value: string) => void) | undefined;
|
|
26
|
+
onChangeRaw?: ((e: string | React.ChangeEvent) => void) | undefined;
|
|
27
|
+
} & React.RefAttributes<any>>;
|
|
@@ -10,10 +10,12 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
13
|
+
/** @jsxImportSource theme-ui */
|
|
14
|
+
import React from 'react';
|
|
13
15
|
import { TYPOGRAPHY_TYPE, getIconSize, getTypographyStyles, } from '../../../../theme/typography';
|
|
14
16
|
import { useTheme } from '../../../../theme';
|
|
15
|
-
import { COLOR } from '../../../..';
|
|
16
17
|
import { Icon } from '../../Icon';
|
|
18
|
+
import { COLOR } from '../../../../theme/colors';
|
|
17
19
|
export var INPUT_SIZE;
|
|
18
20
|
(function (INPUT_SIZE) {
|
|
19
21
|
INPUT_SIZE["SM"] = "sm";
|
|
@@ -35,8 +37,8 @@ const defaultHeight = {
|
|
|
35
37
|
[INPUT_SIZE.MD]: '2.5rem',
|
|
36
38
|
[INPUT_SIZE.LG]: '3rem',
|
|
37
39
|
};
|
|
38
|
-
export const TextInput = (_a) => {
|
|
39
|
-
var { value, onChange, inline, size: sizeParam, leftIcon, sx } = _a, rest = __rest(_a, ["value", "onChange", "inline", "size", "leftIcon", "sx"]);
|
|
40
|
+
export const TextInput = React.forwardRef((_a, ref) => {
|
|
41
|
+
var { value, onChange, onChangeRaw, onClick, inline, size: sizeParam, leftIcon, sx } = _a, rest = __rest(_a, ["value", "onChange", "onChangeRaw", "onClick", "inline", "size", "leftIcon", "sx"]);
|
|
40
42
|
const theme = useTheme();
|
|
41
43
|
const size = sizeParam || INPUT_SIZE.MD;
|
|
42
44
|
const display = inline === false ? 'flex' : 'inline-flex';
|
|
@@ -44,7 +46,7 @@ export const TextInput = (_a) => {
|
|
|
44
46
|
const height = defaultHeight[size];
|
|
45
47
|
const typography = typographyMap[size];
|
|
46
48
|
const typographyStyles = getTypographyStyles(typography);
|
|
47
|
-
return (_jsxs("div", Object.assign({ sx: Object.assign(Object.assign({ height,
|
|
49
|
+
return (_jsxs("div", Object.assign({ ref: ref, onClick: onClick, sx: Object.assign(Object.assign({ height,
|
|
48
50
|
display, px: paddingX, border: 'solid 1px', borderColor: COLOR.LIGHT_GRAY, borderRadius: '4px', flexDirection: 'row', alignItems: 'center', ':hover': {
|
|
49
51
|
boxShadow: theme.boxShadow.NORMAL,
|
|
50
52
|
}, ':focus': {
|
|
@@ -53,8 +55,9 @@ export const TextInput = (_a) => {
|
|
|
53
55
|
mr: 2,
|
|
54
56
|
fontSize: getIconSize(typographyStyles.fontSize),
|
|
55
57
|
} })), _jsx("input", Object.assign({ value: value, onChange: (event) => {
|
|
56
|
-
onChange(event.target.value);
|
|
58
|
+
onChange && onChange(event.target.value);
|
|
59
|
+
onChangeRaw && onChangeRaw(event);
|
|
57
60
|
}, sx: Object.assign(Object.assign({ px: 0, py: 0, border: 'none' }, typographyStyles), { ':focus': {
|
|
58
61
|
outline: 'none',
|
|
59
62
|
} }) }, rest))] })));
|
|
60
|
-
};
|
|
63
|
+
});
|
|
@@ -31,7 +31,7 @@ export const Link = (_a) => {
|
|
|
31
31
|
const InternalLink = link.internalLinkComponent;
|
|
32
32
|
const ExternalLink = link.externalLinkComponent;
|
|
33
33
|
const isExternal = link.externalMatcher.test(to);
|
|
34
|
-
const styles = Object.assign(Object.assign({ color: COLOR.
|
|
34
|
+
const styles = Object.assign(Object.assign({ color: COLOR.ND_BLUE_LIGHT, textDecoration: 'none' }, getTypographyStyles(typography)), sx);
|
|
35
35
|
if (isExternal) {
|
|
36
36
|
return _jsx(ExternalLink, Object.assign({ to: to }, rest, { sx: styles }));
|
|
37
37
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
/** @jsxImportSource theme-ui */
|
|
3
3
|
import { StyledElementProps } from '../../../theme';
|
|
4
|
-
type BoxProps = StyledElementProps<HTMLDivElement>;
|
|
4
|
+
export type BoxProps = StyledElementProps<HTMLDivElement>;
|
|
5
5
|
export declare const Box: React.FC<BoxProps>;
|
|
6
|
-
export {};
|
|
@@ -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 {};
|