@ndlib/component-library 0.0.48 → 0.0.52

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 (64) hide show
  1. package/dist/components/composites/DragDropList/DragDropList.stories.d.ts +7 -0
  2. package/dist/components/composites/DragDropList/DragDropList.stories.js +32 -0
  3. package/dist/components/composites/DragDropList/index.d.ts +23 -0
  4. package/dist/components/composites/DragDropList/index.js +46 -0
  5. package/dist/components/composites/DropdownLinks/index.js +3 -3
  6. package/dist/components/composites/Modal/Modal.stories.js +1 -1
  7. package/dist/components/composites/Seo/SeoDataDisplay/index.d.ts +2 -0
  8. package/dist/components/composites/Seo/SeoDataDisplay/index.js +9 -0
  9. package/dist/components/composites/Seo/index.d.ts +11 -0
  10. package/dist/components/composites/Seo/index.js +16 -0
  11. package/dist/components/composites/Seo/seo.stories.d.ts +6 -0
  12. package/dist/components/composites/Seo/seo.stories.js +12 -0
  13. package/dist/components/composites/Seo/seo.test.d.ts +1 -0
  14. package/dist/components/composites/Seo/seo.test.js +56 -0
  15. package/dist/components/composites/Seo/useSiteMetadata.d.ts +9 -0
  16. package/dist/components/composites/Seo/useSiteMetadata.js +16 -0
  17. package/dist/components/composites/SnackBar/SnackBar.stories.d.ts +8 -0
  18. package/dist/components/composites/SnackBar/SnackBar.stories.js +20 -0
  19. package/dist/components/composites/SnackBar/SnackBar.test.d.ts +1 -0
  20. package/dist/components/composites/SnackBar/SnackBar.test.js +75 -0
  21. package/dist/components/composites/SnackBar/examples.d.ts +3 -0
  22. package/dist/components/composites/SnackBar/examples.js +35 -0
  23. package/dist/components/composites/SnackBar/index.d.ts +1 -0
  24. package/dist/components/composites/SnackBar/index.js +45 -0
  25. package/dist/components/elements/Button/index.js +1 -1
  26. package/dist/components/elements/Fields/Select/index.js +6 -6
  27. package/dist/components/elements/Fields/TextInput/index.js +4 -4
  28. package/dist/components/elements/ListBox/index.d.ts +1 -1
  29. package/dist/components/elements/TabList/TabList.stories.d.ts +6 -0
  30. package/dist/components/elements/TabList/TabList.stories.js +12 -0
  31. package/dist/components/elements/TabList/TabList.test.d.ts +1 -0
  32. package/dist/components/elements/TabList/TabList.test.js +19 -0
  33. package/dist/components/elements/TabList/example.d.ts +7 -0
  34. package/dist/components/elements/TabList/example.js +36 -0
  35. package/dist/components/elements/TabList/index.d.ts +10 -0
  36. package/dist/components/elements/TabList/index.js +30 -0
  37. package/dist/components/elements/Table/Table.stories.d.ts +6 -0
  38. package/dist/components/elements/Table/Table.stories.js +42 -0
  39. package/dist/components/elements/Table/Table.test.d.ts +1 -0
  40. package/dist/components/elements/Table/Table.test.js +36 -0
  41. package/dist/components/elements/Table/index.d.ts +23 -0
  42. package/dist/components/elements/Table/index.js +47 -0
  43. package/dist/components/elements/layout/Box.d.ts +7 -2
  44. package/dist/components/elements/layout/Box.js +2 -3
  45. package/dist/components/elements/layout/Column.d.ts +7 -5
  46. package/dist/components/elements/layout/Column.js +4 -3
  47. package/dist/components/elements/layout/Row.d.ts +9 -7
  48. package/dist/components/elements/layout/Row.js +4 -3
  49. package/dist/components/providers/menu.js +3 -3
  50. package/dist/components/providers/snackBar.d.ts +23 -0
  51. package/dist/components/providers/snackBar.js +53 -0
  52. package/dist/components/providers/ui.js +3 -1
  53. package/dist/components/providers/uniqueIds.d.ts +3 -0
  54. package/dist/components/providers/uniqueIds.js +23 -0
  55. package/dist/components/providers/uniqueIds.test.d.ts +1 -0
  56. package/dist/components/providers/uniqueIds.test.js +26 -0
  57. package/dist/index.d.ts +8 -0
  58. package/dist/index.js +7 -0
  59. package/dist/theme/GlobalStyles.js +4 -5
  60. package/dist/theme/custom.d.ts +2 -2
  61. package/dist/theme/custom.js +2 -2
  62. package/package.json +8 -3
  63. package/dist/utils/hooks/useUniqueHtmlId.d.ts +0 -1
  64. package/dist/utils/hooks/useUniqueHtmlId.js +0 -7
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { DragDropList } from './index';
3
+ declare const meta: Meta<typeof DragDropList>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof DragDropList>;
6
+ export declare const Default: Story;
7
+ export declare const Disabled: Story;
@@ -0,0 +1,32 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DragDropList, DragHandle } from './index';
3
+ import React from 'react';
4
+ import { Paragraph } from '../../elements/text/Paragraph';
5
+ const meta = {
6
+ title: 'Composites/DragDropList',
7
+ component: DragDropList,
8
+ tags: ['autodocs'],
9
+ };
10
+ export default meta;
11
+ const _items = [
12
+ {
13
+ id: '1',
14
+ label: 'Foo',
15
+ accessibleLabel: 'Foo',
16
+ },
17
+ {
18
+ id: '2',
19
+ label: 'Bar',
20
+ accessibleLabel: 'Bar',
21
+ },
22
+ ];
23
+ const StateManager = ({ children }) => {
24
+ const [items, setItems] = React.useState(_items);
25
+ return _jsx(_Fragment, { children: children({ items, setItems }) });
26
+ };
27
+ export const Default = {
28
+ render: () => (_jsx(StateManager, { children: ({ items, setItems }) => (_jsx(DragDropList, Object.assign({ items: items, onReorder: ({ reorderedList }) => setItems(reorderedList) }, { children: (item) => (_jsxs(_Fragment, { children: [_jsx(DragHandle, {}), _jsx(Paragraph, Object.assign({ sx: { ml: 2 } }, { children: item.label }))] })) }))) })),
29
+ };
30
+ export const Disabled = {
31
+ render: () => (_jsx(DragDropList, Object.assign({ disabled: true, items: _items, onReorder: () => { } }, { children: (item) => (_jsxs(_Fragment, { children: [_jsx(DragHandle, {}), _jsx(Paragraph, Object.assign({ sx: { ml: 2 } }, { children: item.label }))] })) }))),
32
+ };
@@ -0,0 +1,23 @@
1
+ /// <reference types="react" />
2
+ import { DropResult } from 'react-beautiful-dnd';
3
+ import { StylesProp } from '../../../theme';
4
+ import { ButtonProps } from '../../elements/Button';
5
+ type DraggableItem = {
6
+ accessibleLabel: string;
7
+ };
8
+ type DragDropListProps<Item extends DraggableItem> = {
9
+ onReorder: (params: {
10
+ reorderedList: Item[];
11
+ dropEvent: DropResult;
12
+ }) => void;
13
+ items: Item[];
14
+ itemIdKey?: keyof Item;
15
+ wrapperStyles?: StylesProp;
16
+ itemStyles?: StylesProp;
17
+ dragItemsDirectly?: boolean;
18
+ disabled?: boolean;
19
+ children: (item: Item) => React.ReactNode;
20
+ };
21
+ export declare const DragHandle: React.FC<ButtonProps>;
22
+ export declare function DragDropList<Item extends DraggableItem>({ items, itemIdKey, wrapperStyles, itemStyles, children: renderChild, onReorder, disabled, dragItemsDirectly, }: DragDropListProps<Item>): import("react/jsx-runtime").JSX.Element;
23
+ export {};
@@ -0,0 +1,46 @@
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, Fragment as _Fragment } from "react/jsx-runtime";
13
+ import { DragDropContext, Droppable, Draggable, } from 'react-beautiful-dnd';
14
+ import DragIndicator from '@mui/icons-material/DragIndicator';
15
+ import { BUTTON_TYPE, Button } from '../../elements/Button';
16
+ import { Column } from '../../elements/layout/Column';
17
+ import { Row } from '../../elements/layout/Row';
18
+ import { useUniqueId } from '../../providers/uniqueIds';
19
+ export const DragHandle = (_a) => {
20
+ var { sx } = _a, props = __rest(_a, ["sx"]);
21
+ return (_jsx(Button, Object.assign({ type: BUTTON_TYPE.TEXT, primaryIcon: DragIndicator, disableFocusStyles: true, sx: Object.assign({ cursor: 'inherit' }, sx) }, props)));
22
+ };
23
+ export function DragDropList({ items, itemIdKey = 'id', wrapperStyles, itemStyles, children: renderChild, onReorder, disabled, dragItemsDirectly = false, }) {
24
+ const id = useUniqueId('dnd-list');
25
+ return (_jsx(DragDropContext, Object.assign({ onDragStart: (start, provided) => {
26
+ const selectedItem = items.find((item) => String(item[itemIdKey]) === start.draggableId);
27
+ provided.announce(`Selected item: ${selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.accessibleLabel}`);
28
+ }, onDragEnd: (e) => {
29
+ if (e.destination &&
30
+ e.source &&
31
+ e.destination.index !== e.source.index) {
32
+ const reordered = Array.from(items);
33
+ const [removed] = reordered.splice(e.source.index, 1);
34
+ reordered.splice(e.destination.index, 0, removed);
35
+ onReorder({
36
+ reorderedList: reordered,
37
+ dropEvent: e,
38
+ });
39
+ }
40
+ } }, { children: _jsx(Droppable, Object.assign({ droppableId: id }, { children: (provided) => (_jsx(Column, Object.assign({}, provided.droppableProps, { sx: wrapperStyles, ref: provided.innerRef }, { children: _jsx(_Fragment, { children: items.map((item, index) => (_jsx(Draggable, Object.assign({ draggableId: String(item[itemIdKey]), isDragDisabled: disabled, index: index }, { children: (provided) => {
41
+ return (_jsx(Row, Object.assign({ sx: {
42
+ alignItems: 'center',
43
+ itemStyles,
44
+ }, ref: provided.innerRef }, provided.draggableProps, provided.dragHandleProps, { "aria-describedby": `item-${index}` }, (dragItemsDirectly ? provided.dragHandleProps : {}), { children: _jsx(Row, Object.assign({ sx: { mt: 1 }, id: `item-${index}` }, { children: renderChild(item) })) })));
45
+ } }), String(item[itemIdKey])))) }) }))) })) })));
46
+ }
@@ -13,16 +13,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useCallback, useMemo, useState } from 'react';
14
14
  import { autoPlacement, offset, size, useFloating } from '@floating-ui/react';
15
15
  import { ListBox } from '../../elements/ListBox';
16
- import { useUniqueHtmlId } from '../../../utils/hooks/useUniqueHtmlId';
17
16
  import { Link } from '../../elements/Link';
18
17
  import { Box } from '../../elements/layout/Box';
19
18
  import { useComponentConfig } from '../../providers/componentConfig';
19
+ import { useUniqueId } from '../../providers/uniqueIds';
20
20
  export const DropdownLinks = (_a) => {
21
21
  var { children, options: optionsParam, renderOption: renderOptionParam, openNewTab, role = 'navigation' } = _a, rest = __rest(_a, ["children", "options", "renderOption", "openNewTab", "role"]);
22
22
  const [isOpen, setIsOpen] = useState(false);
23
23
  const [dropdownMinWidth, setDropdownMinWidth] = useState('0px');
24
- const listboxId = useUniqueHtmlId('dropdown-links');
25
- const anchorId = useUniqueHtmlId('dropdown-links-anchor');
24
+ const listboxId = useUniqueId('dropdown-links');
25
+ const anchorId = useUniqueId('dropdown-links-anchor');
26
26
  const { navigate } = useComponentConfig().link;
27
27
  const options = optionsParam.map((option) => (Object.assign(Object.assign({}, option), { onClick: () => {
28
28
  if (option.onClick) {
@@ -14,7 +14,7 @@ const ModalExample = () => {
14
14
  const modalId = 'modal-example';
15
15
  const { open, close, state } = useDialog(modalId);
16
16
  const theme = useTheme();
17
- return (_jsxs(_Fragment, { children: [_jsx(Button, Object.assign({ onClick: open, sx: { position: 'relative', zIndex: theme.zIndex.DROPDOWN } }, { children: "Open Modal" })), _jsx(Modal, Object.assign({ isOpen: state.isOpen, heading: "Heading", close: close, actions: [
17
+ return (_jsxs(_Fragment, { children: [_jsx(Button, Object.assign({ onClick: open, sx: { position: 'relative', zIndex: theme.zIndex.DIALOG } }, { children: "Open Modal" })), _jsx(Modal, Object.assign({ isOpen: state.isOpen, heading: "Heading", close: close, actions: [
18
18
  {
19
19
  label: 'Secondary',
20
20
  isPrimary: false,
@@ -0,0 +1,2 @@
1
+ export declare const SeoDataDisplay: () => import("react/jsx-runtime").JSX.Element;
2
+ export default SeoDataDisplay;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ReactDOMServer from 'react-dom/server';
3
+ import pretty from 'pretty';
4
+ import { Seo } from '../index';
5
+ export const SeoDataDisplay = () => {
6
+ const seoHtml = ReactDOMServer.renderToString(_jsx(Seo, {}));
7
+ return (_jsx("code", { children: _jsx("pre", { children: pretty(seoHtml) }) }));
8
+ };
9
+ export default SeoDataDisplay;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface SeoProps {
3
+ title?: string;
4
+ description?: string;
5
+ image?: string;
6
+ pathname?: string;
7
+ nofollow?: boolean;
8
+ noindex?: boolean;
9
+ }
10
+ export declare const Seo: React.FC<SeoProps>;
11
+ export default Seo;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSiteMetadata } from './useSiteMetadata';
3
+ export const Seo = ({ title, description, image, nofollow, noindex, }) => {
4
+ const { title: defaultTitle, description: defaultDescription, image: defaultImage, siteUrl, twitterUsername, nofollow: defaultNoindex, noindex: defaultNofollow, } = useSiteMetadata();
5
+ const seo = {
6
+ title: title || defaultTitle,
7
+ description: description || defaultDescription,
8
+ image: image ? siteUrl + image : siteUrl + defaultImage,
9
+ url: siteUrl + location.pathname || '',
10
+ twitterUsername,
11
+ nofollow: nofollow || defaultNofollow,
12
+ noindex: noindex || defaultNoindex,
13
+ };
14
+ return (_jsxs(_Fragment, { children: [seo.title ? _jsx("title", Object.assign({ "data-testid": "seo-title" }, { children: seo.title })) : null, seo.title ? (_jsx("meta", { "data-testid": "seo-twitter-title", name: "twitter:title", content: seo.title })) : null, seo.title ? (_jsx("meta", { "data-testid": "seo-og-title", property: "og:title", content: seo.title })) : null, seo.url ? (_jsx("meta", { "data-testid": "seo-twitter-url", name: "twitter:url", content: seo.url })) : null, seo.url ? (_jsx("meta", { "data-testid": "seo-og-url", property: "og:url", content: seo.url })) : null, seo.description ? (_jsx("meta", { "data-testid": "seo-twitter-description", name: "twitter:description", content: seo.description })) : null, seo.description ? (_jsx("meta", { "data-testid": "seo-og-description", property: "og:description", content: seo.description })) : null, seo.image ? (_jsx("meta", { "data-testid": "seo-twitter-image", name: "twitter:image", content: seo.image })) : null, seo.image ? (_jsx("meta", { "data-testid": "seo-og-image", name: "og:image", content: seo.image })) : null, seo.twitterUsername ? (_jsx("meta", { "data-testid": "seo-twitter-creator", name: "twitter:creator", content: seo.twitterUsername })) : null, seo.nofollow ? (_jsx("meta", { "data-testid": "seo-nofollow", name: "robots", content: "nofollow" })) : null, seo.noindex ? (_jsx("meta", { "data-testid": "seo-noindex", name: "robots", content: "noindex" })) : null, _jsx("meta", { name: "twitter:card", content: "summary_large_image" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" })] }));
15
+ };
16
+ export default Seo;
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import Seo from './index';
3
+ declare const meta: Meta<typeof Seo>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Seo>;
6
+ export declare const Default: Story;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import SeoDataDisplay from './SeoDataDisplay';
3
+ import Seo from './index';
4
+ const meta = {
5
+ title: 'Composites/Seo',
6
+ component: Seo,
7
+ tags: ['autodocs'],
8
+ };
9
+ export default meta;
10
+ export const Default = {
11
+ render: () => (_jsx(_Fragment, { children: _jsx(SeoDataDisplay, {}) })),
12
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from '../../../utils/test';
3
+ import { screen } from '@testing-library/dom';
4
+ import { Seo } from './index';
5
+ const title = 'Component Library';
6
+ const description = 'Component Library for the Hesburgh Libraries';
7
+ const image = '/image.png';
8
+ const nofollow = true;
9
+ const noindex = true;
10
+ describe('Seo', () => {
11
+ it('renders meta tag for title', () => {
12
+ render(_jsx(Seo, { title: title }));
13
+ const element = screen.getByTestId('seo-title');
14
+ expect(element).toContainHTML('Component Library');
15
+ });
16
+ it('renders meta tag for twitter title', () => {
17
+ render(_jsx(Seo, { title: title }));
18
+ const element = screen.getByTestId('seo-twitter-title');
19
+ expect(element).toContainHTML('Component Library');
20
+ });
21
+ it('renders meta tag for open graph title', () => {
22
+ render(_jsx(Seo, { title: title }));
23
+ const element = screen.getByTestId('seo-og-title');
24
+ expect(element).toContainHTML('Component Library');
25
+ });
26
+ it('renders meta tag for twitter description', () => {
27
+ render(_jsx(Seo, { description: description }));
28
+ const element = screen.getByTestId('seo-twitter-description');
29
+ expect(element).toContainHTML('Component Library for the Hesburgh Libraries');
30
+ });
31
+ it('renders meta tag for open graph description', () => {
32
+ render(_jsx(Seo, { description: description }));
33
+ const element = screen.getByTestId('seo-og-description');
34
+ expect(element).toContainHTML('Component Library for the Hesburgh Libraries');
35
+ });
36
+ it('renders meta tag for twitter image', () => {
37
+ render(_jsx(Seo, { image: image }));
38
+ const element = screen.getByTestId('seo-twitter-image');
39
+ expect(element).toContainHTML('https://www.library.nd.edu/image.png');
40
+ });
41
+ it('renders meta tag for og image', () => {
42
+ render(_jsx(Seo, { image: image }));
43
+ const element = screen.getByTestId('seo-og-image');
44
+ expect(element).toContainHTML('https://www.library.nd.edu/image.png');
45
+ });
46
+ it('renders meta tag for nofollow', () => {
47
+ render(_jsx(Seo, { nofollow: nofollow }));
48
+ const element = screen.getByTestId('seo-nofollow');
49
+ expect(element).toContainHTML('nofollow');
50
+ });
51
+ it('renders meta tag for noindex', () => {
52
+ render(_jsx(Seo, { noindex: noindex }));
53
+ const element = screen.getByTestId('seo-noindex');
54
+ expect(element).toContainHTML('noindex');
55
+ });
56
+ });
@@ -0,0 +1,9 @@
1
+ export declare const useSiteMetadata: () => {
2
+ title: string;
3
+ image: string;
4
+ description: string;
5
+ twitterUsername: string;
6
+ siteUrl: string;
7
+ nofollow: boolean;
8
+ noindex: boolean;
9
+ };
@@ -0,0 +1,16 @@
1
+ export const useSiteMetadata = () => {
2
+ const data = {
3
+ site: {
4
+ siteMetadata: {
5
+ title: 'Hesburgh Component Library',
6
+ image: '/images/fakeimage.png',
7
+ description: 'Component library for the Hesburgh Libraries',
8
+ twitterUsername: 'hlibraries',
9
+ siteUrl: 'https://www.library.nd.edu',
10
+ nofollow: false,
11
+ noindex: false,
12
+ },
13
+ },
14
+ };
15
+ return data.site.siteMetadata;
16
+ };
@@ -0,0 +1,8 @@
1
+ import { SnackBar } from './';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ declare const meta: Meta<typeof SnackBar>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof SnackBar>;
6
+ export declare const Default: Story;
7
+ export declare const ReplaceMessage: Story;
8
+ export declare const WipeMessages: Story;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SnackBar } from './';
3
+ import { BasicExample, ReplaceMessageExample, WipeMessagesExample, } from './examples';
4
+ const meta = {
5
+ title: 'Composites/SnackBar',
6
+ component: SnackBar,
7
+ };
8
+ export default meta;
9
+ export const Default = {
10
+ render: () => _jsx(BasicExample, {}),
11
+ args: {},
12
+ };
13
+ export const ReplaceMessage = {
14
+ render: () => _jsx(ReplaceMessageExample, {}),
15
+ args: {},
16
+ };
17
+ export const WipeMessages = {
18
+ render: () => _jsx(WipeMessagesExample, {}),
19
+ args: {},
20
+ };
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { act, fireEvent, waitFor } from '@testing-library/react';
3
+ import { vi } from 'vitest';
4
+ import { render } from '../../../utils/test';
5
+ import { BasicExample, ReplaceMessageExample, WipeMessagesExample, } from './examples';
6
+ vi.useFakeTimers();
7
+ describe('SnackBar', () => {
8
+ it('supports adding messages', () => {
9
+ const { getByText } = render(_jsx(BasicExample, {}));
10
+ expect(() => getByText('Message 1')).toThrow();
11
+ const addButton = getByText('Add Message');
12
+ act(() => {
13
+ fireEvent.click(addButton);
14
+ });
15
+ expect(getByText('Message 1')).toBeInTheDocument();
16
+ act(() => {
17
+ fireEvent.click(addButton);
18
+ });
19
+ expect(getByText('Message 1')).toBeInTheDocument();
20
+ expect(getByText('Message 2')).toBeInTheDocument();
21
+ act(() => {
22
+ vi.runAllTimers();
23
+ });
24
+ waitFor(() => {
25
+ expect(() => getByText('Message 1')).toThrow();
26
+ expect(() => getByText('Message 2')).toThrow();
27
+ });
28
+ });
29
+ it('supports replacing messages', () => {
30
+ const { getByText } = render(_jsx(ReplaceMessageExample, {}));
31
+ expect(() => getByText('Message 1')).toThrow();
32
+ const addButton = getByText('Add Message');
33
+ act(() => {
34
+ fireEvent.click(addButton);
35
+ });
36
+ expect(getByText('Message 1')).toBeInTheDocument();
37
+ act(() => {
38
+ fireEvent.click(addButton);
39
+ });
40
+ expect(() => getByText('Message 1')).toThrow();
41
+ expect(getByText('Message 2')).toBeInTheDocument();
42
+ act(() => {
43
+ vi.runAllTimers();
44
+ });
45
+ waitFor(() => {
46
+ expect(() => getByText('Message 2')).toThrow();
47
+ });
48
+ });
49
+ it('supports wiping messages', () => {
50
+ const { getByText } = render(_jsx(WipeMessagesExample, {}));
51
+ expect(() => getByText('Message 1')).toThrow();
52
+ const addButton = getByText('Add Message');
53
+ act(() => {
54
+ fireEvent.click(addButton);
55
+ });
56
+ act(() => {
57
+ fireEvent.click(addButton);
58
+ });
59
+ expect(getByText('Message 1')).toBeInTheDocument();
60
+ expect(getByText('Message 2')).toBeInTheDocument();
61
+ const wipeButton = getByText('Wipe and Add');
62
+ act(() => {
63
+ fireEvent.click(wipeButton);
64
+ });
65
+ expect(() => getByText('Message 1')).toThrow();
66
+ expect(() => getByText('Message 2')).toThrow();
67
+ expect(getByText('Message 3')).toBeInTheDocument();
68
+ act(() => {
69
+ vi.runAllTimers();
70
+ });
71
+ waitFor(() => {
72
+ expect(() => getByText('Message 3')).toThrow();
73
+ });
74
+ });
75
+ });
@@ -0,0 +1,3 @@
1
+ export declare const BasicExample: () => import("react/jsx-runtime").JSX.Element;
2
+ export declare const ReplaceMessageExample: () => import("react/jsx-runtime").JSX.Element;
3
+ export declare const WipeMessagesExample: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useSnackBar } from '../../providers/snackBar';
4
+ import { Row } from '../../elements/layout/Row';
5
+ import { Button } from '../../elements/Button';
6
+ import { SnackBar } from '.';
7
+ export const BasicExample = () => {
8
+ const { addMessage } = useSnackBar();
9
+ const [messageCount, setMessageCount] = useState(1);
10
+ return (_jsxs(_Fragment, { children: [_jsx(Button, Object.assign({ onClick: () => {
11
+ setMessageCount(messageCount + 1);
12
+ addMessage({ message: `Message ${messageCount}` });
13
+ } }, { children: "Add Message" })), _jsx(SnackBar, {})] }));
14
+ };
15
+ export const ReplaceMessageExample = () => {
16
+ const { addMessage } = useSnackBar();
17
+ const [messageCount, setMessageCount] = useState(1);
18
+ return (_jsxs(_Fragment, { children: [_jsx(Button, Object.assign({ onClick: () => {
19
+ setMessageCount(messageCount + 1);
20
+ addMessage({ message: `Message ${messageCount}`, id: 'same-id' });
21
+ } }, { children: "Add Message" })), _jsx(SnackBar, {})] }));
22
+ };
23
+ export const WipeMessagesExample = () => {
24
+ const { addMessage } = useSnackBar();
25
+ const [messageCount, setMessageCount] = useState(1);
26
+ return (_jsxs(Row, { children: [_jsx(Button, Object.assign({ onClick: () => {
27
+ setMessageCount((count) => count + 1);
28
+ addMessage({ message: `Message ${messageCount}` });
29
+ }, sx: { mr: 1 } }, { children: "Add Message" })), _jsx(Button, Object.assign({ onClick: () => {
30
+ setMessageCount((count) => count + 1);
31
+ addMessage({ message: `Message ${messageCount}` }, {
32
+ wipePrevious: true,
33
+ });
34
+ } }, { children: "Wipe and Add" })), _jsx(SnackBar, {})] }));
35
+ };
@@ -0,0 +1 @@
1
+ export declare const SnackBar: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { keyframes } from '@emotion/react';
3
+ import { COLOR } from '../../../theme/colors';
4
+ import { TYPOGRAPHY_TYPE, getTypographyStyles } from '../../../theme/typography';
5
+ import { BUTTON_TYPE, Button } from '../../elements/Button';
6
+ import { Box } from '../../elements/layout/Box';
7
+ import { Column } from '../../elements/layout/Column';
8
+ import { Row } from '../../elements/layout/Row';
9
+ import { useSnackBar } from '../../providers/snackBar';
10
+ import CloseIcon from '@mui/icons-material/Close';
11
+ import { Z_INDEX } from '../../../theme/custom';
12
+ const getTransformForMessageCount = (messageCount) => messageCount ? `translateY(-${messageCount * 4 + 1}rem)` : '0rem';
13
+ const getAnimation = (messageCount, previousMessageCount) => {
14
+ return keyframes `
15
+ from {
16
+ transform: ${getTransformForMessageCount(previousMessageCount)};
17
+ }
18
+ to {
19
+ transform: ${getTransformForMessageCount(messageCount)};
20
+ }
21
+ `;
22
+ };
23
+ export const SnackBar = () => {
24
+ const { messages, removeMessage, previousMessageCount } = useSnackBar();
25
+ const typographyStyles = getTypographyStyles(TYPOGRAPHY_TYPE.CONDENSED_TEXT_MEDIUM);
26
+ const animation = getAnimation(messages.length, previousMessageCount);
27
+ const animationStyle = `${animation} 100ms linear 1 forwards`;
28
+ return (_jsx(Column, Object.assign({ sx: {
29
+ position: 'fixed',
30
+ left: 0,
31
+ top: '100%',
32
+ width: '100vw',
33
+ display: 'flex',
34
+ alignItems: 'center',
35
+ pb: 3,
36
+ animation: animationStyle,
37
+ zIndex: Z_INDEX.DIALOG,
38
+ } }, { children: messages.map((message) => (_jsxs(Row, Object.assign({ sx: Object.assign({ width: ['90vw', '500px'], height: '56px', borderRadius: '4px', p: 4, mt: '0.5rem', border: '1px solid', bg: COLOR.PRIMARY, color: COLOR.WHITE, justifyContent: 'space-between', alignItems: 'center' }, typographyStyles) }, { children: [_jsx(Box, Object.assign({ sx: {
39
+ overflow: 'hidden',
40
+ whiteSpace: 'nowrap',
41
+ textOverflow: 'ellipsis',
42
+ }, "aria-live": "polite" }, { children: message.message })), _jsx(Box, { children: _jsx(Button, { "aria-label": "Dismiss Notice", type: BUTTON_TYPE.TEXT, primaryIcon: CloseIcon, onClick: () => {
43
+ removeMessage(message.id);
44
+ }, textColor: COLOR.WHITE }) })] }), message.id))) })));
45
+ };
@@ -72,7 +72,7 @@ export const Button = React.forwardRef((_a, ref) => {
72
72
  flagInDevelopment('Icon buttons should include aria-label prop for accessibility');
73
73
  }
74
74
  if (isIconButton) {
75
- hoverTransform = 'scale(1.15)';
75
+ hoverTransform = 'scale(1.05)';
76
76
  }
77
77
  if (type === BUTTON_TYPE.DEFAULT) {
78
78
  bg = color || COLOR.SECONDARY;
@@ -8,11 +8,11 @@ import { INPUT_SIZE, labelOffsetMap, labelTypographyMap } from '../TextInput';
8
8
  import { ListBox } from '../../ListBox';
9
9
  import { BUTTON_SIZE, BUTTON_TYPE, Button } from '../../Button';
10
10
  import { defaultRenderOptionLabel, getOptionId, } from '../option';
11
- import { useUniqueHtmlId } from '../../../../utils/hooks/useUniqueHtmlId';
12
11
  import { KEY_CODES, importedDefaultComponentShim } from '../../../../utils/misc';
13
12
  import { COLOR } from '../../../../theme/colors';
14
13
  import { Box } from '../../layout/Box';
15
14
  import { Label } from '../../text/Label';
15
+ import { useUniqueId } from '../../../providers/uniqueIds';
16
16
  const ArrowDropDownIcon = importedDefaultComponentShim(_ArrowDropDownIcon);
17
17
  const typographyMap = {
18
18
  [INPUT_SIZE.SM]: TYPOGRAPHY_TYPE.PARAGRAPH_SMALL,
@@ -32,8 +32,8 @@ const buttonSizeMap = {
32
32
  const DEFAULT_WIDTH = '16rem';
33
33
  export function Select({ size: sizeParam, placeholder, leftIcon, value, label, onSelectOption, options, renderOption, inverted, renderOptionLabel: renderOptionLabelParam, sx, }) {
34
34
  const theme = useTheme();
35
- const listboxId = useUniqueHtmlId('select-list-box');
36
- const inputId = useUniqueHtmlId('select-input');
35
+ const listboxId = useUniqueId('select-list-box');
36
+ const inputId = useUniqueId('select-input');
37
37
  const [isOpen, setIsOpen] = useState(false);
38
38
  const [stagedOptionValue, setStagedOptionValue] = useState();
39
39
  const currentOption = useMemo(() => {
@@ -132,7 +132,7 @@ export function Select({ size: sizeParam, placeholder, leftIcon, value, label, o
132
132
  overflow: 'hidden',
133
133
  minWidth: '0%',
134
134
  borderColor: inverted ? COLOR.GRAY : COLOR.LIGHT_GRAY,
135
- zIndex: theme.zIndex.LABEL,
135
+ zIndex: theme.zIndex.ELEVATED,
136
136
  } }, { children: _jsx("legend", Object.assign({ style: {
137
137
  width: 'auto',
138
138
  float: 'unset',
@@ -154,7 +154,7 @@ export function Select({ size: sizeParam, placeholder, leftIcon, value, label, o
154
154
  position: 'absolute',
155
155
  left: '0.5rem',
156
156
  lineHeight: 1,
157
- zIndex: theme.zIndex.LABEL,
157
+ zIndex: theme.zIndex.ELEVATED,
158
158
  color: inverted ? COLOR.EXTRA_LIGHT_GRAY : COLOR.PRIMARY,
159
159
  px: 1,
160
160
  top: labelOffsetMap[size],
@@ -171,7 +171,7 @@ export function Select({ size: sizeParam, placeholder, leftIcon, value, label, o
171
171
  onSelectOption && onSelectOption(option.value);
172
172
  close();
173
173
  }, ref: refs.setFloating, renderOption: renderOption, sx: {
174
- zIndex: theme.zIndex.DROPDOWN,
174
+ zIndex: theme.zIndex.DIALOG,
175
175
  }, style: Object.assign(Object.assign({ minWidth: dropdownMinWidth }, floatingStyles), { boxShadow: inverted
176
176
  ? theme.boxShadow.INVERTED
177
177
  : theme.boxShadow.NORMAL }) }))] })));
@@ -16,7 +16,7 @@ import { useTheme } from '../../../../theme';
16
16
  import { Icon } from '../../Icon';
17
17
  import { COLOR } from '../../../../theme/colors';
18
18
  import { Label } from '../../text/Label';
19
- import { useUniqueHtmlId } from '../../../../utils/hooks/useUniqueHtmlId';
19
+ import { useUniqueId } from '../../../providers/uniqueIds';
20
20
  export var INPUT_SIZE;
21
21
  (function (INPUT_SIZE) {
22
22
  INPUT_SIZE["SM"] = "sm";
@@ -50,7 +50,7 @@ const defaultHeight = {
50
50
  };
51
51
  export const TextInput = React.forwardRef((_a, ref) => {
52
52
  var { value, label, onChange, onChangeRaw, onClick, inline, inverted, size: sizeParam, leftIcon, sx, disabled } = _a, rest = __rest(_a, ["value", "label", "onChange", "onChangeRaw", "onClick", "inline", "inverted", "size", "leftIcon", "sx", "disabled"]);
53
- const id = useUniqueHtmlId('text-input');
53
+ const id = useUniqueId('text-input');
54
54
  const theme = useTheme();
55
55
  const size = sizeParam || INPUT_SIZE.MD;
56
56
  const display = inline === false ? 'flex' : 'inline-flex';
@@ -79,7 +79,7 @@ export const TextInput = React.forwardRef((_a, ref) => {
79
79
  overflow: 'hidden',
80
80
  minWidth: '0%',
81
81
  borderColor: inverted ? COLOR.GRAY : COLOR.LIGHT_GRAY,
82
- zIndex: theme.zIndex.LABEL,
82
+ zIndex: theme.zIndex.ELEVATED,
83
83
  }, "aria-ignore": true }, { children: _jsx("legend", Object.assign({ style: {
84
84
  width: 'auto',
85
85
  float: 'unset',
@@ -112,7 +112,7 @@ export const TextInput = React.forwardRef((_a, ref) => {
112
112
  color: inverted ? COLOR.EXTRA_LIGHT_GRAY : COLOR.ND_PROVOST_BLUE,
113
113
  left: '0.5rem',
114
114
  lineHeight: 1,
115
- zIndex: theme.zIndex.LABEL,
115
+ zIndex: theme.zIndex.ELEVATED,
116
116
  px: 1,
117
117
  top: labelOffsetMap[size],
118
118
  } }, { children: label })))] })));
@@ -13,7 +13,7 @@ type ListBoxProps<Value extends Key, Option extends BasicOption<Value>> = Styled
13
13
  onBlur?: () => void;
14
14
  }>;
15
15
  export declare const ListBox: <Value extends React.Key = string, Option extends BasicOption<Value> = any>(props: {
16
- sx?: import("../../../theme").StylesProp | undefined;
16
+ sx?: import("../../..").StylesProp | undefined;
17
17
  children?: React.ReactNode;
18
18
  } & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
19
19
  options: Option[];
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { TabList } from './index';
3
+ declare const meta: Meta<typeof TabList>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TabList>;
6
+ export declare const Default: Story;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TabList } from './index';
3
+ import { ExampleTabs } from './example';
4
+ const meta = {
5
+ title: 'Elements/TabList',
6
+ component: TabList,
7
+ tags: ['autodocs'],
8
+ };
9
+ export default meta;
10
+ export const Default = {
11
+ render: () => _jsx(ExampleTabs, {}),
12
+ };
@@ -0,0 +1 @@
1
+ export {};