@ndlib/component-library 0.0.29 → 0.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/components/composites/DropdownLinks/DropdownLinks.stories.d.ts +7 -0
  2. package/dist/components/composites/DropdownLinks/DropdownLinks.stories.js +21 -0
  3. package/dist/components/composites/DropdownLinks/DropdownLinks.test.d.ts +1 -0
  4. package/dist/components/composites/DropdownLinks/DropdownLinks.test.js +27 -0
  5. package/dist/components/composites/DropdownLinks/index.d.ts +15 -0
  6. package/dist/components/composites/DropdownLinks/index.js +73 -0
  7. package/dist/components/composites/EmptyState/index.js +1 -1
  8. package/dist/components/composites/NavMenu/index.js +1 -1
  9. package/dist/components/elements/Button/Button.stories.d.ts +1 -0
  10. package/dist/components/elements/Button/Button.stories.js +12 -3
  11. package/dist/components/elements/Button/index.d.ts +19 -0
  12. package/dist/components/elements/Button/index.js +26 -55
  13. package/dist/components/elements/Fields/Select/index.js +1 -1
  14. package/dist/components/elements/Fields/TextInput/index.js +1 -1
  15. package/dist/components/elements/Fields/option.d.ts +1 -0
  16. package/dist/components/elements/Link/index.d.ts +1 -0
  17. package/dist/components/elements/Link/index.js +3 -3
  18. package/dist/components/elements/ListBox/index.js +6 -4
  19. package/dist/components/providers/componentConfig.d.ts +2 -0
  20. package/dist/components/providers/componentConfig.js +3 -0
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.js +2 -1
  23. package/dist/theme/Color.stories.js +10 -4
  24. package/dist/theme/colors.d.ts +12 -3
  25. package/dist/theme/colors.js +28 -10
  26. package/dist/theme/index.d.ts +24 -6
  27. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { DropdownLinks } from '.';
3
+ declare const meta: Meta<typeof DropdownLinks>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof DropdownLinks>;
6
+ export declare const Default: Story;
7
+ export declare const OpenInNewTab: Story;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
3
+ import { DropdownLinks } from '.';
4
+ import { Button } from '../../elements/Button';
5
+ import { Box } from '../../elements/layout/Box';
6
+ const meta = {
7
+ title: 'Composites/DropdownLinks',
8
+ component: DropdownLinks,
9
+ tags: ['autodocs'],
10
+ };
11
+ export default meta;
12
+ const options = [
13
+ { value: 'https://google.com', label: 'Google' },
14
+ { value: 'https://facebook.com', label: 'Facebook' },
15
+ ];
16
+ export const Default = {
17
+ render: () => (_jsx(Box, Object.assign({ sx: { width: '200px', height: '200px' } }, { children: _jsx(DropdownLinks, Object.assign({ options: options }, { children: ({ anchorProps }) => (_jsx(Button, Object.assign({}, anchorProps, { rightIcon: ArrowDropDownIcon }, { children: "Links" }))) })) }))),
18
+ };
19
+ export const OpenInNewTab = {
20
+ render: () => (_jsx(Box, Object.assign({ sx: { width: '200px', height: '200px' } }, { children: _jsx(DropdownLinks, Object.assign({ options: options, openNewTab: true }, { children: ({ anchorProps }) => _jsx(Button, Object.assign({}, anchorProps, { children: "Links" })) })) }))),
21
+ };
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from '../../../utils/test';
3
+ import { DropdownLinks } from '.';
4
+ import { Button } from '../../elements/Button';
5
+ import { fireEvent } from '@testing-library/react';
6
+ const options = [
7
+ { value: 'https://google.com', label: 'Google' },
8
+ { value: 'https://facebook.com', label: 'Facebook' },
9
+ ];
10
+ const DropdownExample = (_jsx(DropdownLinks, Object.assign({ options: options }, { children: ({ anchorProps }) => _jsx(Button, Object.assign({}, anchorProps, { children: "Links" })) })));
11
+ describe('DropdownLinks', () => {
12
+ it('toggle links when button is clicked', () => {
13
+ const { getByRole, getAllByRole } = render(DropdownExample);
14
+ expect(() => getByRole('link')).toThrow();
15
+ expect(() => getByRole('navigation')).toThrow();
16
+ const button = getByRole('button');
17
+ expect(button).not.toHaveAttribute('aria-expanded', 'true');
18
+ fireEvent.click(button);
19
+ expect(button).toHaveAttribute('aria-expanded', 'true');
20
+ expect(getAllByRole('link')).toHaveLength(2);
21
+ expect(getByRole('navigation')).toBeDefined();
22
+ fireEvent.click(button);
23
+ expect(button).not.toHaveAttribute('aria-expanded', 'true');
24
+ expect(() => getByRole('link')).toThrow();
25
+ expect(() => getByRole('navigation')).toThrow();
26
+ });
27
+ });
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { BasicOption, RenderOption } from '../../elements/Fields/option';
3
+ import { StyledElementProps } from '../../../theme';
4
+ type AnchorProps = Omit<React.HTMLAttributes<HTMLButtonElement>, 'color'>;
5
+ type LinkOption = BasicOption<string>;
6
+ type DropdownChildrenFn = (params: {
7
+ anchorProps: AnchorProps;
8
+ }) => React.ReactNode;
9
+ type DropdownLinksProps = StyledElementProps<HTMLDivElement, {
10
+ options: BasicOption<string>[];
11
+ renderOption?: RenderOption<string, LinkOption>;
12
+ openNewTab?: boolean;
13
+ }, DropdownChildrenFn>;
14
+ export declare const DropdownLinks: React.FC<DropdownLinksProps>;
15
+ export {};
@@ -0,0 +1,73 @@
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 "react/jsx-runtime";
13
+ import { useCallback, useMemo, useState } from 'react';
14
+ import { autoPlacement, offset, size, useFloating } from '@floating-ui/react';
15
+ import { ListBox } from '../../elements/ListBox';
16
+ import { useUniqueHtmlId } from '../../../utils/hooks/useUniqueHtmlId';
17
+ import { Link } from '../../elements/Link';
18
+ import { Box } from '../../elements/layout/Box';
19
+ import { useComponentConfig } from '../../providers/componentConfig';
20
+ export const DropdownLinks = (_a) => {
21
+ var { children, options: optionsParam, renderOption: renderOptionParam, openNewTab, role = 'navigation' } = _a, rest = __rest(_a, ["children", "options", "renderOption", "openNewTab", "role"]);
22
+ const [isOpen, setIsOpen] = useState(false);
23
+ const [dropdownMinWidth, setDropdownMinWidth] = useState('0px');
24
+ const listboxId = useUniqueHtmlId('dropdown-links');
25
+ const anchorId = useUniqueHtmlId('dropdown-links-anchor');
26
+ const { navigate } = useComponentConfig().link;
27
+ const options = optionsParam.map((option) => (Object.assign(Object.assign({}, option), { onClick: () => {
28
+ if (option.onClick) {
29
+ option.onClick();
30
+ }
31
+ else if (openNewTab) {
32
+ window.open(option.value, '_blank');
33
+ }
34
+ else if (option.value) {
35
+ navigate(option.value);
36
+ }
37
+ setIsOpen(false);
38
+ } })));
39
+ const renderOption = renderOptionParam
40
+ ? renderOptionParam
41
+ : (params) => (_jsx(Link, Object.assign({ to: params.option.value, target: openNewTab ? '_blank' : undefined, onClick: (e) => {
42
+ e.preventDefault();
43
+ } }, { children: params.option.label })));
44
+ const { refs, floatingStyles } = useFloating({
45
+ placement: 'bottom-start',
46
+ middleware: [
47
+ offset(2),
48
+ size({
49
+ apply({ rects }) {
50
+ setDropdownMinWidth(`${rects.reference.width}px`);
51
+ },
52
+ }),
53
+ autoPlacement({
54
+ allowedPlacements: ['top-start', 'bottom-start'],
55
+ }),
56
+ ],
57
+ });
58
+ const onClick = useCallback(() => {
59
+ setIsOpen(!isOpen);
60
+ }, [isOpen]);
61
+ const dropdownAnchorProps = useMemo(() => ({
62
+ id: anchorId,
63
+ 'aria-haspopup': true,
64
+ 'aria-expanded': isOpen,
65
+ 'aria-owns': listboxId,
66
+ ref: refs.setReference,
67
+ onClick,
68
+ }), [refs, onClick, anchorId, isOpen, listboxId]);
69
+ return (_jsxs(Box, Object.assign({}, rest, { children: [children &&
70
+ children({
71
+ anchorProps: dropdownAnchorProps,
72
+ }), isOpen && (_jsx(ListBox, { role: role, id: listboxId, options: options, ref: refs.setFloating, renderOption: renderOption, style: Object.assign(Object.assign({ minWidth: dropdownMinWidth }, floatingStyles), { zIndex: 1 }) }))] })));
73
+ };
@@ -20,5 +20,5 @@ import { FONT_SIZE } from '../../../theme/typography';
20
20
  export const DEFAULT_MESSAGE = 'No results found.';
21
21
  export const EmptyState = (_a) => {
22
22
  var { icon, message, sx } = _a, rest = __rest(_a, ["icon", "message", "sx"]);
23
- return (_jsxs(Column, Object.assign({ sx: Object.assign(Object.assign({}, sx), { width: '100%', alignItems: 'center', justifyContent: 'center', mt: 5 }) }, rest, { children: [_jsx(Row, { children: _jsx(Icon, { icon: icon || SearchOffIcon, size: FONT_SIZE.XL, color: COLOR.LIGHT_GRAY }) }), _jsx(Row, Object.assign({ sx: { mt: 1 } }, { children: _jsx(Paragraph, Object.assign({ sx: { color: COLOR.LIGHT_GRAY }, size: PARAGRAPH_SIZE.LG }, { children: message || DEFAULT_MESSAGE })) }))] })));
23
+ return (_jsxs(Column, Object.assign({ sx: Object.assign(Object.assign({}, sx), { width: '100%', alignItems: 'center', justifyContent: 'center', mt: 5 }) }, rest, { children: [_jsx(Row, { children: _jsx(Icon, { icon: icon || SearchOffIcon, size: FONT_SIZE.XL, color: COLOR.GRAY }) }), _jsx(Row, Object.assign({ sx: { mt: 1 } }, { children: _jsx(Paragraph, Object.assign({ sx: { color: COLOR.GRAY }, size: PARAGRAPH_SIZE.LG }, { children: message || DEFAULT_MESSAGE })) }))] })));
24
24
  };
@@ -28,7 +28,7 @@ export const NavMenu = (props) => {
28
28
  justifyContent: 'center',
29
29
  p: 3,
30
30
  border: 'solid 1px',
31
- borderColor: COLOR.FAINT_GRAY,
31
+ borderColor: COLOR.EXTRA_LIGHT_GRAY,
32
32
  borderRadius: '4px',
33
33
  } }, { children: [_jsx(Column, { sx: { flexGrow: 1 } }), submenu.items.map((submenuItem) => {
34
34
  if (!(submenuItem.action.type === MENU_ACTION_TYPE.SUBMENU)) {
@@ -5,6 +5,7 @@ export default meta;
5
5
  type Story = StoryObj<typeof Button>;
6
6
  export declare const Default: Story;
7
7
  export declare const CustomColor: Story;
8
+ export declare const Link: Story;
8
9
  export declare const OutlineButton: Story;
9
10
  export declare const TextButton: Story;
10
11
  export declare const IconButton: Story;
@@ -2,12 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import SearchIcon from '@mui/icons-material/Search';
3
3
  import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
4
4
  import SettingsIcon from '@mui/icons-material/Settings';
5
- import { BUTTON_SIZE, BUTTON_TYPE, Button } from '.';
5
+ import { BUTTON_SIZE, BUTTON_TYPE, Button, LinkButton } from '.';
6
6
  import { GROUP_TYPE, Group } from '../Group';
7
7
  import { HEADING_SIZE, Heading } from '../text/Heading';
8
8
  import { Column } from '../layout/Column';
9
- import { COLOR } from '../../../theme/colors';
10
9
  import { Row } from '../layout/Row';
10
+ import { Paragraph } from '../text/Paragraph';
11
+ import { COLOR } from '../../../theme/colors';
11
12
  const meta = {
12
13
  title: 'Elements/Button',
13
14
  component: Button,
@@ -26,8 +27,16 @@ export const Default = {
26
27
  children: 'Click Me',
27
28
  },
28
29
  };
30
+ const facebookBlue = '#4267B2';
29
31
  export const CustomColor = {
30
- render: (args) => (_jsx(Column, { children: sizes.map((size) => (_jsxs(Group, Object.assign({ type: GROUP_TYPE.REGION }, { children: [_jsx(Heading, Object.assign({ size: HEADING_SIZE.MD }, { children: size.label })), _jsx(Button, Object.assign({}, args, { size: size.size, color: COLOR.SECONDARY, sx: { mt: 1 } }))] })))) })),
32
+ render: (args) => (_jsxs(Column, { children: [_jsx(Paragraph, { children: "Use customColor prop for colors not in theme" }), _jsx(Row, { children: _jsx(Button, Object.assign({}, args, { customColor: facebookBlue, textColor: COLOR.WHITE, sx: { mt: 1 } })) })] })),
33
+ args: {
34
+ type: BUTTON_TYPE.DEFAULT,
35
+ children: 'Click Me',
36
+ },
37
+ };
38
+ export const Link = {
39
+ render: (args) => (_jsx(Column, { children: sizes.map((size) => (_jsxs(Group, Object.assign({ type: GROUP_TYPE.REGION }, { children: [_jsx(Heading, Object.assign({ size: HEADING_SIZE.MD }, { children: size.label })), _jsx(LinkButton, Object.assign({}, args, { sx: { mt: 1 } }))] })))) })),
31
40
  args: {
32
41
  type: BUTTON_TYPE.DEFAULT,
33
42
  children: 'Click Me',
@@ -1,5 +1,6 @@
1
1
  /** @jsxImportSource theme-ui */
2
2
  import React from 'react';
3
+ import { StyledElementProps } from '../../../theme';
3
4
  import { COLOR } from '../../../theme/colors';
4
5
  export declare enum BUTTON_SIZE {
5
6
  SM = "sm",
@@ -11,6 +12,19 @@ export declare enum BUTTON_TYPE {
11
12
  TEXT = "text",
12
13
  OUTLINE = "outline"
13
14
  }
15
+ type ButtonProps = StyledElementProps<HTMLButtonElement, {
16
+ size?: BUTTON_SIZE;
17
+ type?: BUTTON_TYPE;
18
+ color?: COLOR;
19
+ textColor?: COLOR;
20
+ customColor?: string;
21
+ primaryIcon?: React.FC<any>;
22
+ leftIcon?: React.FC<any>;
23
+ rightIcon?: React.FC<any>;
24
+ accessibleLabel?: string;
25
+ loading?: boolean;
26
+ disabled?: boolean;
27
+ }>;
14
28
  export declare const Button: React.ForwardRefExoticComponent<{
15
29
  sx?: import("../../../theme").StylesProp | undefined;
16
30
  children?: React.ReactNode;
@@ -18,6 +32,8 @@ export declare const Button: React.ForwardRefExoticComponent<{
18
32
  size?: BUTTON_SIZE | undefined;
19
33
  type?: BUTTON_TYPE | undefined;
20
34
  color?: COLOR | undefined;
35
+ textColor?: COLOR | undefined;
36
+ customColor?: string | undefined;
21
37
  primaryIcon?: React.FC<any> | undefined;
22
38
  leftIcon?: React.FC<any> | undefined;
23
39
  rightIcon?: React.FC<any> | undefined;
@@ -25,3 +41,6 @@ export declare const Button: React.ForwardRefExoticComponent<{
25
41
  loading?: boolean | undefined;
26
42
  disabled?: boolean | undefined;
27
43
  } & React.RefAttributes<HTMLButtonElement>>;
44
+ type LinkButtonProps = Omit<ButtonProps, 'type' | 'color' | 'textColor'>;
45
+ export declare const LinkButton: React.FC<LinkButtonProps>;
46
+ export {};
@@ -11,9 +11,9 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
13
13
  /** @jsxImportSource theme-ui */
14
- import React, { useState } from 'react';
14
+ import React from 'react';
15
15
  import { useTheme } from '../../../theme';
16
- import { COLOR, colors } from '../../../theme/colors';
16
+ import { COLOR } from '../../../theme/colors';
17
17
  import { TYPOGRAPHY_TYPE, getIconSize, getTypographyStyles, } from '../../../theme/typography';
18
18
  import { Icon } from '../Icon';
19
19
  import { useEnvironment } from '../../providers/env';
@@ -52,17 +52,14 @@ export var BUTTON_TYPE;
52
52
  // ARROW
53
53
  })(BUTTON_TYPE || (BUTTON_TYPE = {}));
54
54
  export const Button = React.forwardRef((_a, ref) => {
55
- var { size: sizeParam, type: typeParam, color, primaryIcon, leftIcon, rightIcon, disabled: disabledParam, children, sx, loading } = _a, rest = __rest(_a, ["size", "type", "color", "primaryIcon", "leftIcon", "rightIcon", "disabled", "children", "sx", "loading"]);
55
+ var { size: sizeParam, type: typeParam, color, customColor, textColor: textColorParam, primaryIcon, leftIcon, rightIcon, disabled: disabledParam, children, sx, loading } = _a, rest = __rest(_a, ["size", "type", "color", "customColor", "textColor", "primaryIcon", "leftIcon", "rightIcon", "disabled", "children", "sx", "loading"]);
56
56
  const disabled = disabledParam || loading;
57
57
  const theme = useTheme();
58
- const [hover, setHover] = useState(false);
59
58
  const { flagInDevelopment } = useEnvironment();
60
59
  let bg = COLOR.PRIMARY;
61
- let hoverBg = COLOR.PRIMARY_HIGHLIGHT;
62
- let textColor = COLOR.TEXT;
63
- let hoverTextColor = undefined;
64
60
  let borderColor = COLOR.TRANSPARENT;
65
61
  let cursor = 'pointer';
62
+ let textColor = COLOR.BACKGROUND;
66
63
  let hoverShadow = theme.boxShadow.NORMAL;
67
64
  let hoverDecoration = undefined;
68
65
  let hoverTransform = 'scale(1.03)';
@@ -73,7 +70,6 @@ export const Button = React.forwardRef((_a, ref) => {
73
70
  const paddingX = isIconButton || isTextButton ? 0 : defaultPaddingX[size];
74
71
  const height = isTextButton ? undefined : defaultHeight[size];
75
72
  const width = primaryIcon ? height : undefined;
76
- // const height = width;
77
73
  if (isIconButton && !rest['aria-label']) {
78
74
  flagInDevelopment('Icon buttons should include aria-label prop for accessibility');
79
75
  }
@@ -81,53 +77,37 @@ export const Button = React.forwardRef((_a, ref) => {
81
77
  hoverTransform = 'scale(1.15)';
82
78
  }
83
79
  if (type === BUTTON_TYPE.DEFAULT) {
84
- bg = color || COLOR.PRIMARY;
85
- hoverBg =
86
- bg === COLOR.PRIMARY
87
- ? COLOR.PRIMARY_HIGHLIGHT
88
- : bg === COLOR.SECONDARY
89
- ? COLOR.SECONDARY_HIGHLIGHT
90
- : bg;
91
- textColor =
92
- bg === COLOR.PRIMARY
93
- ? COLOR.TEXT_ON_PRIMARY
94
- : bg === COLOR.SECONDARY
95
- ? COLOR.TEXT_ON_SECONDARY
96
- : COLOR.TEXT;
97
- hoverTextColor = textColor;
80
+ bg = color || COLOR.SECONDARY;
81
+ textColor = COLOR.BLACK;
98
82
  }
99
83
  if (type === BUTTON_TYPE.TEXT) {
100
84
  bg = COLOR.TRANSPARENT;
101
- hoverBg = bg;
102
85
  textColor = color || COLOR.PRIMARY;
103
- hoverTextColor = textColor;
104
86
  hoverShadow = undefined;
105
87
  hoverDecoration = 'underline';
106
88
  }
107
89
  if (type === BUTTON_TYPE.OUTLINE) {
108
90
  bg = COLOR.BACKGROUND;
109
- hoverBg = COLOR.BACKGROUND;
110
91
  textColor = color || COLOR.PRIMARY;
111
- hoverTextColor = textColor;
112
92
  borderColor = textColor;
113
93
  }
94
+ if (textColorParam) {
95
+ textColor = textColorParam;
96
+ }
114
97
  if (disabled) {
115
98
  cursor = 'not-allowed';
116
- if (bg === COLOR.PRIMARY) {
117
- bg = hoverBg = COLOR.LIGHT_GRAY;
118
- }
119
99
  if (bg === COLOR.BACKGROUND || bg === COLOR.TRANSPARENT) {
120
- textColor = COLOR.LIGHT_GRAY;
100
+ textColor = COLOR.GRAY;
121
101
  }
122
102
  else {
123
- bg = COLOR.LIGHT_GRAY;
103
+ bg = COLOR.GRAY;
124
104
  }
125
105
  }
126
106
  const typography = typographyMap[size];
127
107
  const typographyStyles = getTypographyStyles(typography);
128
108
  let body = children;
129
109
  if (primaryIcon) {
130
- body = (_jsx(Icon, { icon: primaryIcon, size: getIconSize(typographyStyles.fontSize), color: hover ? hoverTextColor : textColor }));
110
+ body = (_jsx(Icon, { icon: primaryIcon, size: getIconSize(typographyStyles.fontSize), color: textColor }));
131
111
  }
132
112
  if (loading) {
133
113
  body = (_jsxs("div", Object.assign({ sx: {
@@ -137,33 +117,24 @@ export const Button = React.forwardRef((_a, ref) => {
137
117
  justifyContent: 'center',
138
118
  } }, { children: [_jsx(Spinner, { size: SPINNER_SIZE.SM, color: textColor, sx: { position: 'absolute' } }), _jsx("div", Object.assign({ sx: { visibility: 'hidden' } }, { children: body }))] })));
139
119
  }
140
- return (_jsxs("button", Object.assign({ ref: ref, tabIndex: disabled ? -1 : 0, disabled: disabled, onMouseEnter: () => {
141
- setHover(true);
142
- }, onMouseLeave: () => {
143
- setHover(false);
144
- }, sx: Object.assign(Object.assign({ cursor, bg: bg || colors.primary, color: textColor, px: paddingX, width: width, height: height, border: 'solid 1px', borderRadius: '4px', borderColor, display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', ':hover': !disabled
145
- ? {
146
- bg: hoverBg,
147
- color: hoverTextColor,
148
- boxShadow: hoverShadow,
149
- transform: hoverTransform,
150
- textDecoration: hoverDecoration,
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
- }
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: {
120
+ const hoverStyles = !disabled
121
+ ? {
122
+ boxShadow: hoverShadow,
123
+ transform: hoverTransform,
124
+ textDecoration: hoverDecoration,
125
+ }
126
+ : undefined;
127
+ return (_jsxs("button", Object.assign({ ref: ref, tabIndex: disabled ? -1 : 0, disabled: disabled, css: {
128
+ backgroundColor: customColor,
129
+ }, sx: Object.assign(Object.assign({ cursor, bg: customColor ? undefined : bg, color: textColor, px: paddingX, width: width, height: height, border: 'solid 1px', borderRadius: '4px', borderColor, display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', ':hover': hoverStyles, ':focus': hoverStyles }, typographyStyles), sx) }, rest, { children: [leftIcon && (_jsx(Icon, { icon: leftIcon, size: typographyStyles.fontSize, sx: { mr: iconMargin[size] }, color: textColor })), _jsx("div", Object.assign({ css: {
162
130
  flexGrow: 1,
163
131
  justifyContent: 'flex-start',
164
132
  textOverflow: 'ellipsis',
165
133
  whiteSpace: 'nowrap',
166
134
  overflow: 'hidden',
167
135
  textAlign: 'start',
168
- } }, { children: body })), rightIcon && (_jsx(Icon, { icon: rightIcon, size: typographyStyles.fontSize, sx: { ml: iconMargin[size] }, color: hover ? hoverTextColor : textColor }))] })));
136
+ } }, { children: body })), rightIcon && (_jsx(Icon, { icon: rightIcon, size: typographyStyles.fontSize, sx: { ml: iconMargin[size] }, color: textColor }))] })));
169
137
  });
138
+ export const LinkButton = (props) => {
139
+ return (_jsx(Button, Object.assign({}, props, { color: COLOR.ND_BLUE_BRIGHT, textColor: COLOR.WHITE })));
140
+ };
@@ -126,7 +126,7 @@ export function Select({ size: sizeParam, placeholder, leftIcon, value, onSelect
126
126
  else {
127
127
  close();
128
128
  }
129
- }, sx: Object.assign(Object.assign({ height, width: DEFAULT_WIDTH, border: 'solid 1px', borderColor: COLOR.LIGHT_GRAY, borderRadius: '4px', flexDirection: 'row', alignItems: 'center', position: 'relative', ':hover': {
129
+ }, sx: Object.assign(Object.assign({ height, width: DEFAULT_WIDTH, border: 'solid 1px', borderColor: COLOR.GRAY, borderRadius: '4px', flexDirection: 'row', alignItems: 'center', position: 'relative', ':hover': {
130
130
  boxShadow: theme.boxShadow.NORMAL,
131
131
  }, ':focus': {
132
132
  boxShadow: theme.boxShadow.NORMAL,
@@ -47,7 +47,7 @@ export const TextInput = React.forwardRef((_a, ref) => {
47
47
  const typography = typographyMap[size];
48
48
  const typographyStyles = getTypographyStyles(typography);
49
49
  return (_jsxs("div", Object.assign({ ref: ref, onClick: onClick, sx: Object.assign(Object.assign({ height,
50
- display, px: paddingX, border: 'solid 1px', borderColor: COLOR.LIGHT_GRAY, borderRadius: '4px', flexDirection: 'row', alignItems: 'center', ':hover': {
50
+ display, px: paddingX, border: 'solid 1px', borderColor: COLOR.GRAY, borderRadius: '4px', flexDirection: 'row', alignItems: 'center', ':hover': {
51
51
  boxShadow: theme.boxShadow.NORMAL,
52
52
  }, ':focus': {
53
53
  boxShadow: theme.boxShadow.NORMAL,
@@ -3,6 +3,7 @@ export type Key = string | number;
3
3
  export interface BasicOption<Value extends Key> {
4
4
  value: Value;
5
5
  label?: string;
6
+ onClick?: () => void;
6
7
  }
7
8
  export type RenderOption<Value extends Key, Option extends BasicOption<Value>> = (params: {
8
9
  option: Option;
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  import { StyledElementProps } from '../../../theme';
4
4
  type LinkProps = StyledElementProps<HTMLSpanElement, {
5
5
  to: string;
6
+ target?: string;
6
7
  size?: LINK_SIZE;
7
8
  }>;
8
9
  export declare enum LINK_SIZE {
@@ -25,7 +25,7 @@ const SIZE_TYPOGRAPHY_MAP = {
25
25
  [LINK_SIZE.LG]: TYPOGRAPHY_TYPE.CONTROL_LARGE,
26
26
  };
27
27
  export const Link = (_a) => {
28
- var { size, to, sx } = _a, rest = __rest(_a, ["size", "to", "sx"]);
28
+ var { size, to, sx, target } = _a, rest = __rest(_a, ["size", "to", "sx", "target"]);
29
29
  const { link } = useComponentConfig();
30
30
  const typography = SIZE_TYPOGRAPHY_MAP[size || LINK_SIZE.MD];
31
31
  const InternalLink = link.internalLinkComponent;
@@ -33,9 +33,9 @@ export const Link = (_a) => {
33
33
  const isExternal = link.externalMatcher.test(to);
34
34
  const styles = Object.assign(Object.assign({ color: COLOR.ND_BLUE_LIGHT, textDecoration: 'none' }, getTypographyStyles(typography)), sx);
35
35
  if (isExternal) {
36
- return _jsx(ExternalLink, Object.assign({ to: to }, rest, { sx: styles }));
36
+ return _jsx(ExternalLink, Object.assign({ to: to }, rest, { sx: styles, target: target }));
37
37
  }
38
38
  else {
39
- return _jsx(InternalLink, Object.assign({ to: to }, rest, { sx: styles }));
39
+ return _jsx(InternalLink, Object.assign({ to: to }, rest, { sx: styles, target: target }));
40
40
  }
41
41
  };
@@ -21,10 +21,12 @@ function ListBoxInner(_a, ref) {
21
21
  const typography = getTypographyStyles(TYPOGRAPHY_TYPE.PARAGRAPH_MEDIUM);
22
22
  return (_jsx("div", Object.assign({ role: "listbox", ref: ref, sx: Object.assign(Object.assign({ border: 'solid 1px', borderRadius: '4px', borderColor: COLOR.LIGHT_GRAY, backgroundColor: COLOR.BACKGROUND, boxShadow: '0px 0px 8px 2px #dddddd' }, typography), sx), onKeyDown: (e) => {
23
23
  console.log(e);
24
- } }, rest, { children: options.map((option) => (_jsx("div", Object.assign({ id: getOptionId(option.value), "aria-selected": selected === option.value, role: "option", onMouseDown: () => selectOption && selectOption(option.value), sx: {
24
+ } }, rest, { children: options.map((option) => (_jsx("div", Object.assign({ id: getOptionId(option.value), "aria-selected": selected === option.value, role: "option", onClick: option.onClick, onMouseDown: () => selectOption && selectOption(option.value), sx: {
25
25
  px: 4,
26
26
  py: 3,
27
- backgroundColor: focused === option.value ? COLOR.FAINT_GRAY : COLOR.BACKGROUND,
27
+ backgroundColor: focused === option.value
28
+ ? COLOR.EXTRA_EXTRA_LIGHT_GRAY
29
+ : COLOR.BACKGROUND,
28
30
  cursor: 'pointer',
29
31
  borderBottom: 'solid 1px',
30
32
  borderBottomColor: COLOR.LIGHT_GRAY,
@@ -39,12 +41,12 @@ function ListBoxInner(_a, ref) {
39
41
  borderTopLeftRadius: '4px',
40
42
  },
41
43
  ':hover': {
42
- backgroundColor: COLOR.FAINT_GRAY,
44
+ backgroundColor: COLOR.EXTRA_EXTRA_LIGHT_GRAY,
43
45
  },
44
46
  } }, { children: renderOption({
45
47
  option,
46
48
  selected: selected === option.value,
47
49
  focused: focused === option.value,
48
- }) })))) })));
50
+ }) }), option.value))) })));
49
51
  }
50
52
  export const ListBox = React.forwardRef(ListBoxInner);
@@ -4,6 +4,7 @@ import { StyledElementProps } from '../../theme';
4
4
  export type ComponentConfig = {
5
5
  link: {
6
6
  externalMatcher: RegExp;
7
+ navigate: (url: string) => void;
7
8
  internalLinkComponent: React.FC<LinkComponentProps>;
8
9
  externalLinkComponent: React.FC<LinkComponentProps>;
9
10
  };
@@ -11,6 +12,7 @@ export type ComponentConfig = {
11
12
  export type ComponentConfigParam = DeepPartial<ComponentConfig>;
12
13
  export type LinkComponentProps = StyledElementProps<HTMLAnchorElement, {
13
14
  to: string;
15
+ target?: string;
14
16
  }>;
15
17
  export declare const DefaultLink: React.FC<LinkComponentProps>;
16
18
  export declare const ComponentConfigContext: import("react").Context<ComponentConfig>;
@@ -19,6 +19,9 @@ export const DefaultLink = (_a) => {
19
19
  const defaultComponentConfig = {
20
20
  link: {
21
21
  externalMatcher: DEFAULT_EXTERNAL_LINK_MATCHER,
22
+ navigate: (url) => {
23
+ window.location.href = url;
24
+ },
22
25
  internalLinkComponent: DefaultLink,
23
26
  externalLinkComponent: DefaultLink,
24
27
  },
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { TYPOGRAPHY_TYPE, FONT, FONT_SIZE, FONT_WEIGHT, LINE_HEIGHT, } from './t
4
4
  export { GlobalStyles } from './theme/GlobalStyles';
5
5
  export { Alert, Alerts } from './components/elements/Alerts';
6
6
  export { BrandingBar } from './components/elements/BrandingBar';
7
- export { Button, BUTTON_SIZE, BUTTON_TYPE } from './components/elements/Button';
7
+ export { Button, BUTTON_SIZE, BUTTON_TYPE, LinkButton, } from './components/elements/Button';
8
8
  export { Heading, HEADING_SIZE } from './components/elements/text/Heading';
9
9
  export { Label, LABEL_SIZE } from './components/elements/text/Label';
10
10
  export { Paragraph, PARAGRAPH_SIZE } from './components/elements/text/Paragraph';
@@ -30,6 +30,7 @@ export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
30
30
  export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
31
31
  export { NavMenu } from './components/composites/NavMenu';
32
32
  export { EmptyState } from './components/composites/EmptyState';
33
+ export { DropdownLinks } from './components/composites/DropdownLinks';
33
34
  export { UiProvider } from './components/providers/ui';
34
35
  export { MenuProvider, useMenu } from './components/providers/menu';
35
36
  export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export { TYPOGRAPHY_TYPE, FONT, FONT_SIZE, FONT_WEIGHT, LINE_HEIGHT, } from './t
4
4
  export { GlobalStyles } from './theme/GlobalStyles';
5
5
  export { Alert, Alerts } from './components/elements/Alerts';
6
6
  export { BrandingBar } from './components/elements/BrandingBar';
7
- export { Button, BUTTON_SIZE, BUTTON_TYPE } from './components/elements/Button';
7
+ export { Button, BUTTON_SIZE, BUTTON_TYPE, LinkButton, } from './components/elements/Button';
8
8
  export { Heading, HEADING_SIZE } from './components/elements/text/Heading';
9
9
  export { Label, LABEL_SIZE } from './components/elements/text/Label';
10
10
  export { Paragraph, PARAGRAPH_SIZE } from './components/elements/text/Paragraph';
@@ -30,6 +30,7 @@ export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
30
30
  export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
31
31
  export { NavMenu } from './components/composites/NavMenu';
32
32
  export { EmptyState } from './components/composites/EmptyState';
33
+ export { DropdownLinks } from './components/composites/DropdownLinks';
33
34
  export { UiProvider } from './components/providers/ui';
34
35
  export { MenuProvider, useMenu } from './components/providers/menu';
35
36
  export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
@@ -16,12 +16,18 @@ const colors = [
16
16
  { color: COLOR.BACKGROUND, label: 'BACKGROUND' },
17
17
  { color: COLOR.PRIMARY, label: 'PRIMARY' },
18
18
  { color: COLOR.PRIMARY_HIGHLIGHT, label: 'PRIMARY_HIGHLIGHT' },
19
- { color: COLOR.TEXT_ON_PRIMARY, label: 'TEXT_ON_PRIMARY' },
20
- { color: COLOR.SECONDARY, label: 'SECONDARY' },
21
- { color: COLOR.SECONDARY_HIGHLIGHT, label: 'SECONDARY_HIGHLIGHT' },
22
- { color: COLOR.TEXT_ON_SECONDARY, label: 'TEXT_ON_SECONDARY' },
19
+ { color: COLOR.GRAY, label: 'GRAY' },
20
+ { color: COLOR.DARK_GRAY, label: 'DARK_GRAY' },
21
+ { color: COLOR.LIGHT_GRAY, label: 'LIGHT GRAY' },
22
+ { color: COLOR.EXTRA_LIGHT_GRAY, label: 'EXTRA_LIGHT_GRAY' },
23
+ { color: COLOR.EXTRA_EXTRA_LIGHT_GRAY, label: 'EXTRA_EXTRA_LIGHT_GRAY' },
23
24
  { color: COLOR.ND_BLUE, label: 'ND_BLUE' },
25
+ { color: COLOR.ND_BLUE_DARK, label: 'ND_BLUE_DARK' },
26
+ { color: COLOR.ND_BLUE_LIGHT, label: 'ND_BLUE_LIGHT' },
27
+ { color: COLOR.ND_BLUE_BRIGHT, label: 'ND_BLUE_BRIGHT' },
24
28
  { color: COLOR.ND_GOLD, label: 'ND_GOLD' },
29
+ { color: COLOR.ND_GOLD_LIGHT, label: 'ND_GOLD_LIGHT' },
30
+ { color: COLOR.ND_GOLD_DARK, label: 'ND_GOLD_DARK' },
25
31
  { color: COLOR.ND_METALLIC_GOLD, label: 'ND_METALLIC_GOLD' },
26
32
  { color: COLOR.ND_PROVOST_BLUE, label: 'ND_PROVOST_BLUE' },
27
33
  { color: COLOR.ND_SECONDARY_1, label: 'ND_SECONDARY_1' },
@@ -3,16 +3,25 @@ export declare enum COLOR {
3
3
  BACKGROUND = "background",
4
4
  TRANSPARENT = "transparent",
5
5
  PRIMARY = "primary",
6
+ TEXT_ON_PRIMARY = "textOnPrimary",
6
7
  PRIMARY_HIGHLIGHT = "primaryHighlight",
7
8
  SECONDARY = "secondary",
8
- SECONDARY_HIGHLIGHT = "secondaryHighlight",
9
- TEXT_ON_PRIMARY = "textOnPrimary",
10
9
  TEXT_ON_SECONDARY = "textOnSecondary",
10
+ SECONDARY_HIGHLIGHT = "secondaryHighlight",
11
+ WHITE = "white",
12
+ BLACK = "black",
13
+ DARK_GRAY = "darkGray",
14
+ GRAY = "gray",
11
15
  LIGHT_GRAY = "lightGray",
12
- FAINT_GRAY = "faintGray",
16
+ EXTRA_LIGHT_GRAY = "extraLightGray",
17
+ EXTRA_EXTRA_LIGHT_GRAY = "extraExtraLightGray",
13
18
  ND_BLUE = "ndBlue",
19
+ ND_BLUE_DARK = "ndBlueDark",
14
20
  ND_BLUE_LIGHT = "ndBlueLight",
21
+ ND_BLUE_BRIGHT = "ndBlueBright",
15
22
  ND_GOLD = "ndGold",
23
+ ND_GOLD_LIGHT = "ndGoldLight",
24
+ ND_GOLD_DARK = "ndGoldDark",
16
25
  ND_SKY_BLUE = "ndSkyBlue",
17
26
  ND_SKY_BLUE_DARK = "ndSkyBlueDark",
18
27
  ND_METALLIC_GOLD = "ndMetallicGold",
@@ -4,16 +4,25 @@ export var COLOR;
4
4
  COLOR["BACKGROUND"] = "background";
5
5
  COLOR["TRANSPARENT"] = "transparent";
6
6
  COLOR["PRIMARY"] = "primary";
7
+ COLOR["TEXT_ON_PRIMARY"] = "textOnPrimary";
7
8
  COLOR["PRIMARY_HIGHLIGHT"] = "primaryHighlight";
8
9
  COLOR["SECONDARY"] = "secondary";
9
- COLOR["SECONDARY_HIGHLIGHT"] = "secondaryHighlight";
10
- COLOR["TEXT_ON_PRIMARY"] = "textOnPrimary";
11
10
  COLOR["TEXT_ON_SECONDARY"] = "textOnSecondary";
11
+ COLOR["SECONDARY_HIGHLIGHT"] = "secondaryHighlight";
12
+ COLOR["WHITE"] = "white";
13
+ COLOR["BLACK"] = "black";
14
+ COLOR["DARK_GRAY"] = "darkGray";
15
+ COLOR["GRAY"] = "gray";
12
16
  COLOR["LIGHT_GRAY"] = "lightGray";
13
- COLOR["FAINT_GRAY"] = "faintGray";
17
+ COLOR["EXTRA_LIGHT_GRAY"] = "extraLightGray";
18
+ COLOR["EXTRA_EXTRA_LIGHT_GRAY"] = "extraExtraLightGray";
14
19
  COLOR["ND_BLUE"] = "ndBlue";
20
+ COLOR["ND_BLUE_DARK"] = "ndBlueDark";
15
21
  COLOR["ND_BLUE_LIGHT"] = "ndBlueLight";
22
+ COLOR["ND_BLUE_BRIGHT"] = "ndBlueBright";
16
23
  COLOR["ND_GOLD"] = "ndGold";
24
+ COLOR["ND_GOLD_LIGHT"] = "ndGoldLight";
25
+ COLOR["ND_GOLD_DARK"] = "ndGoldDark";
17
26
  COLOR["ND_SKY_BLUE"] = "ndSkyBlue";
18
27
  COLOR["ND_SKY_BLUE_DARK"] = "ndSkyBlueDark";
19
28
  COLOR["ND_METALLIC_GOLD"] = "ndMetallicGold";
@@ -38,20 +47,29 @@ export var COLOR;
38
47
  COLOR["ALERT_WARNING_BORDER"] = "alertWarningBorder";
39
48
  })(COLOR || (COLOR = {}));
40
49
  export const colors = {
41
- [COLOR.TEXT]: '#222222',
50
+ [COLOR.TEXT]: '#333333',
42
51
  [COLOR.BACKGROUND]: '#ffffff',
43
52
  [COLOR.TRANSPARENT]: 'rgba(0,0,0,0)',
44
53
  [COLOR.PRIMARY]: '#0c2340',
45
- [COLOR.PRIMARY_HIGHLIGHT]: '#000d1d',
46
54
  [COLOR.TEXT_ON_PRIMARY]: '#ffffff',
47
- [COLOR.SECONDARY]: '#f8e999',
55
+ [COLOR.PRIMARY_HIGHLIGHT]: '#000d1d',
56
+ [COLOR.SECONDARY]: '#d39f10',
48
57
  [COLOR.SECONDARY_HIGHLIGHT]: '#ddcc70',
49
- [COLOR.TEXT_ON_SECONDARY]: '#242111',
50
- [COLOR.LIGHT_GRAY]: '#767676',
51
- [COLOR.FAINT_GRAY]: '#eeeeee',
58
+ [COLOR.TEXT_ON_SECONDARY]: '#040401',
59
+ [COLOR.WHITE]: '#ffffff',
60
+ [COLOR.BLACK]: '#000000',
61
+ [COLOR.DARK_GRAY]: '#333333',
62
+ [COLOR.GRAY]: '#555555',
63
+ [COLOR.LIGHT_GRAY]: '#d2d2d2',
64
+ [COLOR.EXTRA_LIGHT_GRAY]: '#e2e2e2',
65
+ [COLOR.EXTRA_EXTRA_LIGHT_GRAY]: '#f2f2f2',
66
+ [COLOR.ND_GOLD]: '#ae9142',
67
+ [COLOR.ND_GOLD_LIGHT]: '#d39f10',
68
+ [COLOR.ND_GOLD_DARK]: '#8c7535',
52
69
  [COLOR.ND_BLUE]: '#0c2340',
70
+ [COLOR.ND_BLUE_DARK]: '#081629',
53
71
  [COLOR.ND_BLUE_LIGHT]: '#143865',
54
- [COLOR.ND_GOLD]: '#d39F10',
72
+ [COLOR.ND_BLUE_BRIGHT]: '#1c4f8f',
55
73
  [COLOR.ND_SKY_BLUE]: '#e1e8f2',
56
74
  [COLOR.ND_SKY_BLUE_DARK]: '#c1cddd',
57
75
  [COLOR.ND_METALLIC_GOLD]: '#ae9142',
@@ -11,16 +11,25 @@ export declare const theme: {
11
11
  background: string;
12
12
  transparent: string;
13
13
  primary: string;
14
+ textOnPrimary: string;
14
15
  primaryHighlight: string;
15
16
  secondary: string;
16
- secondaryHighlight: string;
17
- textOnPrimary: string;
18
17
  textOnSecondary: string;
18
+ secondaryHighlight: string;
19
+ white: string;
20
+ black: string;
21
+ darkGray: string;
22
+ gray: string;
19
23
  lightGray: string;
20
- faintGray: string;
24
+ extraLightGray: string;
25
+ extraExtraLightGray: string;
21
26
  ndBlue: string;
27
+ ndBlueDark: string;
22
28
  ndBlueLight: string;
29
+ ndBlueBright: string;
23
30
  ndGold: string;
31
+ ndGoldLight: string;
32
+ ndGoldDark: string;
24
33
  ndSkyBlue: string;
25
34
  ndSkyBlueDark: string;
26
35
  ndMetallicGold: string;
@@ -94,16 +103,25 @@ export declare const useTheme: () => {
94
103
  background: string;
95
104
  transparent: string;
96
105
  primary: string;
106
+ textOnPrimary: string;
97
107
  primaryHighlight: string;
98
108
  secondary: string;
99
- secondaryHighlight: string;
100
- textOnPrimary: string;
101
109
  textOnSecondary: string;
110
+ secondaryHighlight: string;
111
+ white: string;
112
+ black: string;
113
+ darkGray: string;
114
+ gray: string;
102
115
  lightGray: string;
103
- faintGray: string;
116
+ extraLightGray: string;
117
+ extraExtraLightGray: string;
104
118
  ndBlue: string;
119
+ ndBlueDark: string;
105
120
  ndBlueLight: string;
121
+ ndBlueBright: string;
106
122
  ndGold: string;
123
+ ndGoldLight: string;
124
+ ndGoldDark: string;
107
125
  ndSkyBlue: string;
108
126
  ndSkyBlueDark: string;
109
127
  ndMetallicGold: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndlib/component-library",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [