@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.
- package/dist/components/composites/DragDropList/DragDropList.stories.d.ts +7 -0
- package/dist/components/composites/DragDropList/DragDropList.stories.js +32 -0
- package/dist/components/composites/DragDropList/index.d.ts +23 -0
- package/dist/components/composites/DragDropList/index.js +46 -0
- package/dist/components/composites/DropdownLinks/index.js +3 -3
- package/dist/components/composites/Modal/Modal.stories.js +1 -1
- package/dist/components/composites/Seo/SeoDataDisplay/index.d.ts +2 -0
- package/dist/components/composites/Seo/SeoDataDisplay/index.js +9 -0
- package/dist/components/composites/Seo/index.d.ts +11 -0
- package/dist/components/composites/Seo/index.js +16 -0
- package/dist/components/composites/Seo/seo.stories.d.ts +6 -0
- package/dist/components/composites/Seo/seo.stories.js +12 -0
- package/dist/components/composites/Seo/seo.test.d.ts +1 -0
- package/dist/components/composites/Seo/seo.test.js +56 -0
- package/dist/components/composites/Seo/useSiteMetadata.d.ts +9 -0
- package/dist/components/composites/Seo/useSiteMetadata.js +16 -0
- package/dist/components/composites/SnackBar/SnackBar.stories.d.ts +8 -0
- package/dist/components/composites/SnackBar/SnackBar.stories.js +20 -0
- package/dist/components/composites/SnackBar/SnackBar.test.d.ts +1 -0
- package/dist/components/composites/SnackBar/SnackBar.test.js +75 -0
- package/dist/components/composites/SnackBar/examples.d.ts +3 -0
- package/dist/components/composites/SnackBar/examples.js +35 -0
- package/dist/components/composites/SnackBar/index.d.ts +1 -0
- package/dist/components/composites/SnackBar/index.js +45 -0
- package/dist/components/elements/Button/index.js +1 -1
- package/dist/components/elements/Fields/Select/index.js +6 -6
- package/dist/components/elements/Fields/TextInput/index.js +4 -4
- package/dist/components/elements/ListBox/index.d.ts +1 -1
- package/dist/components/elements/TabList/TabList.stories.d.ts +6 -0
- package/dist/components/elements/TabList/TabList.stories.js +12 -0
- package/dist/components/elements/TabList/TabList.test.d.ts +1 -0
- package/dist/components/elements/TabList/TabList.test.js +19 -0
- package/dist/components/elements/TabList/example.d.ts +7 -0
- package/dist/components/elements/TabList/example.js +36 -0
- package/dist/components/elements/TabList/index.d.ts +10 -0
- package/dist/components/elements/TabList/index.js +30 -0
- package/dist/components/elements/Table/Table.stories.d.ts +6 -0
- package/dist/components/elements/Table/Table.stories.js +42 -0
- package/dist/components/elements/Table/Table.test.d.ts +1 -0
- package/dist/components/elements/Table/Table.test.js +36 -0
- package/dist/components/elements/Table/index.d.ts +23 -0
- package/dist/components/elements/Table/index.js +47 -0
- package/dist/components/elements/layout/Box.d.ts +7 -2
- package/dist/components/elements/layout/Box.js +2 -3
- package/dist/components/elements/layout/Column.d.ts +7 -5
- package/dist/components/elements/layout/Column.js +4 -3
- package/dist/components/elements/layout/Row.d.ts +9 -7
- package/dist/components/elements/layout/Row.js +4 -3
- package/dist/components/providers/menu.js +3 -3
- package/dist/components/providers/snackBar.d.ts +23 -0
- package/dist/components/providers/snackBar.js +53 -0
- package/dist/components/providers/ui.js +3 -1
- package/dist/components/providers/uniqueIds.d.ts +3 -0
- package/dist/components/providers/uniqueIds.js +23 -0
- package/dist/components/providers/uniqueIds.test.d.ts +1 -0
- package/dist/components/providers/uniqueIds.test.js +26 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/theme/GlobalStyles.js +4 -5
- package/dist/theme/custom.d.ts +2 -2
- package/dist/theme/custom.js +2 -2
- package/package.json +8 -3
- package/dist/utils/hooks/useUniqueHtmlId.d.ts +0 -1
- package/dist/utils/hooks/useUniqueHtmlId.js +0 -7
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
3
|
+
import { items, ExampleTabs } from './example';
|
|
4
|
+
describe('TabList', () => {
|
|
5
|
+
it('renders interactive tabs', () => {
|
|
6
|
+
const { getByRole } = render(_jsx(ExampleTabs, {}));
|
|
7
|
+
expect(getByRole('tablist')).toBeInTheDocument();
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
expect(getByRole('tab', { name: item.label })).toBeInTheDocument();
|
|
10
|
+
}
|
|
11
|
+
const firstTab = getByRole('tab', { name: items[0].label });
|
|
12
|
+
const secondTab = getByRole('tab', { name: items[1].label });
|
|
13
|
+
expect(firstTab).toHaveAttribute('aria-selected', 'true');
|
|
14
|
+
expect(secondTab).toHaveAttribute('aria-selected', 'false');
|
|
15
|
+
fireEvent.click(secondTab);
|
|
16
|
+
expect(firstTab).toHaveAttribute('aria-selected', 'false');
|
|
17
|
+
expect(secondTab).toHaveAttribute('aria-selected', 'true');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TabList, Tab } from '.';
|
|
4
|
+
export const items = [
|
|
5
|
+
{
|
|
6
|
+
id: '1',
|
|
7
|
+
label: 'Items & Requests',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: '2',
|
|
11
|
+
label: 'Courses',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: '3',
|
|
15
|
+
label: 'Checkout',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: '4',
|
|
19
|
+
label: 'History',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: '5',
|
|
23
|
+
label: 'Preferences',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: '6',
|
|
27
|
+
label: 'Reservations',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
const StateManager = ({ children }) => {
|
|
31
|
+
const [selected, setSelected] = React.useState('1');
|
|
32
|
+
return _jsx(_Fragment, { children: children({ selected, setSelected }) });
|
|
33
|
+
};
|
|
34
|
+
export const ExampleTabs = () => (_jsx(StateManager, { children: ({ selected, setSelected }) => (_jsx(TabList, { children: items.map((item) => (_jsx(Tab, Object.assign({ onClick: () => {
|
|
35
|
+
setSelected(item.id);
|
|
36
|
+
}, selected: selected === item.id }, { children: item.label }), item.id))) })) }));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyledElementProps } from '../../../theme';
|
|
3
|
+
type TabListProps = StyledElementProps<HTMLDivElement>;
|
|
4
|
+
export declare const TabList: React.FC<TabListProps>;
|
|
5
|
+
type TabProps = StyledElementProps<HTMLButtonElement, {
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
children: string;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const Tab: React.FC<TabProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
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 "theme-ui/jsx-runtime";
|
|
13
|
+
import { TYPOGRAPHY_TYPE, getTypographyStyles } from '../../../theme/typography';
|
|
14
|
+
import { COLOR } from '../../../theme/colors';
|
|
15
|
+
import { useUniqueId } from '../../providers/uniqueIds';
|
|
16
|
+
export const TabList = (_a) => {
|
|
17
|
+
var { children, sx } = _a, props = __rest(_a, ["children", "sx"]);
|
|
18
|
+
return (_jsx("div", Object.assign({ role: "tablist", sx: Object.assign({ flexDirection: 'row' }, sx) }, props, { children: children })));
|
|
19
|
+
};
|
|
20
|
+
export const Tab = (_a) => {
|
|
21
|
+
var { selected, children } = _a, rest = __rest(_a, ["selected", "children"]);
|
|
22
|
+
const typographyStyles = getTypographyStyles(TYPOGRAPHY_TYPE.CONDENSED_TEXT_LARGE);
|
|
23
|
+
const labelId = useUniqueId('tab-label');
|
|
24
|
+
return (_jsx("button", Object.assign({ role: "tab", sx: Object.assign({ height: '3.25rem', boxSizing: 'border-box', px: 4, bg: COLOR.WHITE, color: selected ? COLOR.DARK_GRAY : COLOR.GRAY, border: 'none', borderBottom: selected ? 'solid 3px' : 'solid 1px', borderColor: selected ? COLOR.ND_BLUE_BRIGHT : COLOR.LIGHT_GRAY, cursor: 'pointer' }, typographyStyles), "aria-labelledby": labelId, "aria-selected": selected ? 'true' : 'false' }, rest, { children: _jsx("div", Object.assign({ id: labelId, sx: {
|
|
25
|
+
transform: selected ? 'scale(1.1)' : undefined,
|
|
26
|
+
':hover': {
|
|
27
|
+
transform: selected ? 'scale(1.1)' : 'scale(1.05)',
|
|
28
|
+
},
|
|
29
|
+
} }, { children: children })) })));
|
|
30
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Table, TableColumn } from '.';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Elements/Table',
|
|
5
|
+
component: Table,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
};
|
|
8
|
+
export default meta;
|
|
9
|
+
const data = [
|
|
10
|
+
{
|
|
11
|
+
name: 'Steve Rogers',
|
|
12
|
+
age: 100,
|
|
13
|
+
position: 'Ethics Officer',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Natasha Romanoff',
|
|
17
|
+
age: 35,
|
|
18
|
+
position: 'Opposition Researcher',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'Thor',
|
|
22
|
+
age: 1500,
|
|
23
|
+
position: 'VP of Thunder',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Peter Parker',
|
|
27
|
+
age: 18,
|
|
28
|
+
position: 'Web Crawling Expert',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Kate Bishop',
|
|
32
|
+
age: 22,
|
|
33
|
+
position: 'Trust Fund Recipient',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
export const Default = {
|
|
37
|
+
render: () => (_jsxs(Table, Object.assign({ data: data, alternateRowColor: true }, { children: [_jsx(TableColumn, { header: "Name", dataKey: "name", sx: {
|
|
38
|
+
width: '160px',
|
|
39
|
+
} }), _jsx(TableColumn, Object.assign({ header: "Age", sx: {
|
|
40
|
+
width: '100px',
|
|
41
|
+
} }, { children: (row) => row.age })), _jsx(TableColumn, Object.assign({ header: "Occupation" }, { children: (row) => row.position }))] }))),
|
|
42
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const testExample: import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { Table, TableColumn } from '.';
|
|
4
|
+
const data = [
|
|
5
|
+
{
|
|
6
|
+
col1: 'Cell 1-1',
|
|
7
|
+
col2: 'Cell 1-2',
|
|
8
|
+
col3: 'Cell 1-3',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
col1: 'Cell 2-1',
|
|
12
|
+
col2: 'Cell 2-2',
|
|
13
|
+
col3: 'Cell 2-3',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export const testExample = (_jsxs(Table, Object.assign({ data: data }, { children: [_jsx(TableColumn, { header: "Column 1", dataKey: "col1" }), _jsx(TableColumn, Object.assign({ header: "Column 2" }, { children: (row) => row.col2 })), _jsx(TableColumn, { dataKey: "col3", header: _jsx("div", { children: "Column 3" }) })] })));
|
|
17
|
+
describe('Table', () => {
|
|
18
|
+
it('renders all headers and cells', () => {
|
|
19
|
+
const { getByText } = render(testExample);
|
|
20
|
+
const headers = ['Column 1', 'Column 2', 'Column 3'];
|
|
21
|
+
const cells = [
|
|
22
|
+
'Cell 1-1',
|
|
23
|
+
'Cell 1-2',
|
|
24
|
+
'Cell 1-3',
|
|
25
|
+
'Cell 2-1',
|
|
26
|
+
'Cell 2-2',
|
|
27
|
+
'Cell 2-3',
|
|
28
|
+
];
|
|
29
|
+
headers.forEach((header) => {
|
|
30
|
+
expect(getByText(header)).toBeInTheDocument();
|
|
31
|
+
});
|
|
32
|
+
cells.forEach((cell) => {
|
|
33
|
+
expect(getByText(cell)).toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { StyledElementProps, StylesProp } from '../../../theme';
|
|
3
|
+
type ColumnRenderFn<RowData> = (data: RowData) => React.ReactNode;
|
|
4
|
+
type ColumnProps<RowData extends object> = {
|
|
5
|
+
header: string | React.ReactNode;
|
|
6
|
+
dataKey?: keyof RowData;
|
|
7
|
+
headerStyles?: StylesProp;
|
|
8
|
+
align?: 'left' | 'center' | 'right';
|
|
9
|
+
alignHeader?: 'left' | 'center' | 'right';
|
|
10
|
+
children?: ColumnRenderFn<RowData>;
|
|
11
|
+
sx?: StylesProp;
|
|
12
|
+
};
|
|
13
|
+
type TableProps<RowData> = StyledElementProps<HTMLTableElement, {
|
|
14
|
+
data: RowData[];
|
|
15
|
+
children: JSX.Element[];
|
|
16
|
+
cellStyles?: StylesProp;
|
|
17
|
+
alternateRowColor?: boolean;
|
|
18
|
+
showRowDividers?: boolean;
|
|
19
|
+
showColumnDividers?: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function TableColumn<RowData extends object>(props: ColumnProps<RowData>): null;
|
|
22
|
+
export declare function Table<RowData extends object>(props: TableProps<RowData>): import("react").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { COLOR } from '../../../theme/colors';
|
|
4
|
+
import { useEnvironment } from '../../providers/env';
|
|
5
|
+
import { TYPOGRAPHY_TYPE, typographyStyleMap } from '../../../theme/typography';
|
|
6
|
+
const useColumnSpec = (children) => {
|
|
7
|
+
const columnList = JSON.stringify(children.map((child) => child.props.header));
|
|
8
|
+
return useMemo(() => {
|
|
9
|
+
return children.map((child) => child.props);
|
|
10
|
+
}, [columnList]);
|
|
11
|
+
};
|
|
12
|
+
export function TableColumn(props) {
|
|
13
|
+
const { flagInDevelopment } = useEnvironment();
|
|
14
|
+
flagInDevelopment('TableColumn should not be used outside of Table component');
|
|
15
|
+
console.log('We offer this log to you in reverence, oh compiler gods', props);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
export function Table(props) {
|
|
19
|
+
const { role, data, alternateRowColor = true, cellStyles, sx, children, showRowDividers = true, showColumnDividers = false, } = props;
|
|
20
|
+
const cellTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONDENSED_TEXT_MEDIUM];
|
|
21
|
+
const headerTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONTROL_MEDIUM];
|
|
22
|
+
const columnSpec = useColumnSpec(children);
|
|
23
|
+
const getCellStyles = (params) => {
|
|
24
|
+
const { columnProps, rowIndex, columnIndex } = params;
|
|
25
|
+
const isLastColumn = columnIndex === columnSpec.length - 1;
|
|
26
|
+
const isLastRow = rowIndex === data.length - 1;
|
|
27
|
+
const cellAlign = columnProps.align || 'left';
|
|
28
|
+
const styles = Object.assign({ bg: alternateRowColor && rowIndex % 2 === 1
|
|
29
|
+
? COLOR.EXTRA_EXTRA_LIGHT_GRAY
|
|
30
|
+
: COLOR.WHITE, p: 3, borderBottom: showRowDividers && !isLastRow ? '1px solid' : 'none', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, textAlign: cellAlign }, cellTypographyStyles);
|
|
31
|
+
return Object.assign(Object.assign(Object.assign({}, styles), cellStyles), columnProps.sx);
|
|
32
|
+
};
|
|
33
|
+
return (_jsxs("table", Object.assign({ role: role, sx: sx }, { children: [_jsx("thead", Object.assign({ role: "rowgroup" }, { children: _jsx("tr", { children: columnSpec.map((column, i) => {
|
|
34
|
+
const isLastColumn = i === columnSpec.length - 1;
|
|
35
|
+
return (_jsx("th", Object.assign({ role: "columnheader", sx: Object.assign(Object.assign({ textAlign: column.alignHeader || column.align || 'left', borderBottom: '1px solid', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, px: 3, pb: 1 }, headerTypographyStyles), column.headerStyles) }, { children: column.header }), i));
|
|
36
|
+
}) }) })), _jsx("tbody", Object.assign({ role: "rowgroup" }, { children: data.map((rowData, rowIndex) => {
|
|
37
|
+
return (_jsx("tr", Object.assign({ role: "row" }, { children: columnSpec.map((column, columnIndex) => {
|
|
38
|
+
const { children, dataKey } = column;
|
|
39
|
+
const cellStyles = getCellStyles({
|
|
40
|
+
columnProps: column,
|
|
41
|
+
rowIndex,
|
|
42
|
+
columnIndex,
|
|
43
|
+
});
|
|
44
|
+
return (_jsx("td", Object.assign({ sx: cellStyles }, { children: _jsxs(_Fragment, { children: [dataKey ? rowData[dataKey] : null, !dataKey && children && children(rowData)] }) }), columnIndex));
|
|
45
|
+
}) }), rowIndex));
|
|
46
|
+
}) }))] })));
|
|
47
|
+
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { StyledElementProps } from '../../../theme';
|
|
3
3
|
export type BoxProps = StyledElementProps<HTMLDivElement>;
|
|
4
|
-
export declare const Box: React.
|
|
4
|
+
export declare const Box: React.ForwardRefExoticComponent<{
|
|
5
|
+
sx?: import("../../../theme").StylesProp | undefined;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
} & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & object & {
|
|
8
|
+
htmlFor?: string | undefined;
|
|
9
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const Box = React.forwardRef((props, ref) => (_jsx("div", Object.assign({}, props, { ref: ref }))));
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { StyledElementProps } from '../../../theme';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import { FlexHelperProps } from './Row';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export declare const Column: React.ForwardRefExoticComponent<{
|
|
4
|
+
sx?: import("../../../theme").StylesProp | undefined;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
} & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & FlexHelperProps & {
|
|
7
|
+
htmlFor?: string | undefined;
|
|
8
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -10,9 +10,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
13
|
+
import React from 'react';
|
|
13
14
|
import { convertFlexHelperProps } from './Row';
|
|
14
|
-
export const Column = (_a) => {
|
|
15
|
+
export const Column = React.forwardRef((_a, ref) => {
|
|
15
16
|
var { sx, children } = _a, rest = __rest(_a, ["sx", "children"]);
|
|
16
17
|
const flexStyles = convertFlexHelperProps(rest);
|
|
17
|
-
return (_jsx("div", Object.assign({}, rest, { sx: Object.assign(Object.assign(Object.assign({}, flexStyles), sx), { display: 'flex', flexDirection: 'column' }) }, { children: children })));
|
|
18
|
-
};
|
|
18
|
+
return (_jsx("div", Object.assign({ ref: ref }, rest, { sx: Object.assign(Object.assign(Object.assign({}, flexStyles), sx), { display: 'flex', flexDirection: 'column' }) }, { children: children })));
|
|
19
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { CSSProperties, ThemeUICSSProperties } from 'theme-ui';
|
|
3
|
-
import
|
|
2
|
+
import React from 'react';
|
|
4
3
|
export declare const convertFlexHelperProps: (props: FlexHelperProps) => ThemeUICSSProperties;
|
|
5
4
|
export type FlexHelperProps = {
|
|
6
5
|
grow?: number;
|
|
@@ -11,8 +10,11 @@ export type FlexHelperProps = {
|
|
|
11
10
|
justify?: CSSProperties['justifyContent'];
|
|
12
11
|
centered?: boolean;
|
|
13
12
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
export declare const Row: React.ForwardRefExoticComponent<{
|
|
14
|
+
sx?: import("../../../theme").StylesProp | undefined;
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
} & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & FlexHelperProps & {
|
|
17
|
+
breakpoint?: number | undefined;
|
|
18
|
+
} & {
|
|
19
|
+
htmlFor?: string | undefined;
|
|
20
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -10,6 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
13
|
+
import React from 'react';
|
|
13
14
|
export const convertFlexHelperProps = (props) => {
|
|
14
15
|
const styleObject = {};
|
|
15
16
|
if (props.grow) {
|
|
@@ -36,7 +37,7 @@ export const convertFlexHelperProps = (props) => {
|
|
|
36
37
|
}
|
|
37
38
|
return styleObject;
|
|
38
39
|
};
|
|
39
|
-
export const Row = (_a) => {
|
|
40
|
+
export const Row = React.forwardRef((_a, ref) => {
|
|
40
41
|
var { sx, children, breakpoint: breakpointParam } = _a, rest = __rest(_a, ["sx", "children", "breakpoint"]);
|
|
41
42
|
const flexStyles = convertFlexHelperProps(rest);
|
|
42
43
|
let flexDirection = 'row';
|
|
@@ -47,5 +48,5 @@ export const Row = (_a) => {
|
|
|
47
48
|
}
|
|
48
49
|
flexDirection.push('row');
|
|
49
50
|
}
|
|
50
|
-
return (_jsx("div", Object.assign({}, rest, { sx: Object.assign(Object.assign(Object.assign({}, flexStyles), sx), { flexDirection, display: 'flex' }) }, { children: children })));
|
|
51
|
-
};
|
|
51
|
+
return (_jsx("div", Object.assign({}, rest, { ref: ref, sx: Object.assign(Object.assign(Object.assign({}, flexStyles), sx), { flexDirection, display: 'flex' }) }, { children: children })));
|
|
52
|
+
});
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import React, { useEffect, useState } from 'react';
|
|
3
3
|
import { useEnvironment } from './env';
|
|
4
4
|
import { KEY_CODES, equals } from '../../utils/misc';
|
|
5
|
-
import { useUniqueHtmlId } from '../../utils/hooks/useUniqueHtmlId';
|
|
6
5
|
import { useCheckMidClick } from '../../utils/hooks/useCheckMidClick';
|
|
6
|
+
import { useUniqueId } from './uniqueIds';
|
|
7
7
|
export var MENU_ACTION_TYPE;
|
|
8
8
|
(function (MENU_ACTION_TYPE) {
|
|
9
9
|
MENU_ACTION_TYPE["SUBMENU"] = "SUBMENU";
|
|
@@ -41,14 +41,14 @@ const inactiveStyles = {
|
|
|
41
41
|
};
|
|
42
42
|
export const MenuProvider = ({ menu, children, }) => {
|
|
43
43
|
const { flagInDevelopment } = useEnvironment();
|
|
44
|
-
const
|
|
44
|
+
const menuId = useUniqueId('hcl-menu');
|
|
45
45
|
const { isMidClick, elementProps: checkMidclickProps } = useCheckMidClick();
|
|
46
46
|
const [usingKeyboard, setUsingKeyboard] = useState(false);
|
|
47
47
|
const closeOnBlurTimeout = React.useRef();
|
|
48
48
|
const initialPath = React.useMemo(() => [menu.items[0].id], [menu]);
|
|
49
49
|
const [activePath, setActivePath] = useState(initialPath);
|
|
50
50
|
const [isOpen, setIsOpen] = useState(false);
|
|
51
|
-
const getItemId = React.useCallback((path) =>
|
|
51
|
+
const getItemId = React.useCallback((path) => `${menuId}-item-${path.join('-')}`, [menuId]);
|
|
52
52
|
useEffect(() => {
|
|
53
53
|
if (activePath && isOpen) {
|
|
54
54
|
const activeChild = window.document.getElementById(getItemId(activePath));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
type SnackBarMessage = {
|
|
3
|
+
message: string;
|
|
4
|
+
content?: JSX.Element;
|
|
5
|
+
id?: string;
|
|
6
|
+
};
|
|
7
|
+
type SendMessageOptions = {
|
|
8
|
+
timeout?: number;
|
|
9
|
+
wipePrevious?: boolean;
|
|
10
|
+
};
|
|
11
|
+
type SnackBarMessageWithId = Omit<SnackBarMessage, 'id'> & {
|
|
12
|
+
id: string;
|
|
13
|
+
};
|
|
14
|
+
type AddMessage = (message: SnackBarMessage, options?: SendMessageOptions) => void;
|
|
15
|
+
type SnackBarContextType = {
|
|
16
|
+
addMessage: AddMessage;
|
|
17
|
+
removeMessage: (id: string) => void;
|
|
18
|
+
messages: SnackBarMessageWithId[];
|
|
19
|
+
previousMessageCount: number;
|
|
20
|
+
};
|
|
21
|
+
export declare const SnackBarProvider: React.FC<React.PropsWithChildren>;
|
|
22
|
+
export declare const useSnackBar: () => SnackBarContextType;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState, } from 'react';
|
|
3
|
+
const DEFAULT_TIMEOUT = 10000;
|
|
4
|
+
const SnackBarContext = createContext({
|
|
5
|
+
addMessage: () => { },
|
|
6
|
+
removeMessage: () => { },
|
|
7
|
+
previousMessageCount: 0,
|
|
8
|
+
messages: [],
|
|
9
|
+
});
|
|
10
|
+
export const SnackBarProvider = ({ children, }) => {
|
|
11
|
+
const [messages, setMessages] = useState([]);
|
|
12
|
+
const removeMessageTimeouts = useRef([]);
|
|
13
|
+
const previousMessageCount = useRef(0);
|
|
14
|
+
const removeMessage = useCallback((id) => {
|
|
15
|
+
setMessages((messages) => {
|
|
16
|
+
previousMessageCount.current = messages.length;
|
|
17
|
+
return messages.filter((m) => m.id !== id);
|
|
18
|
+
});
|
|
19
|
+
}, []);
|
|
20
|
+
const addMessage = useCallback((message, options = {}) => {
|
|
21
|
+
const newRandomId = Math.random().toString(36).substring(7);
|
|
22
|
+
setMessages((messages) => {
|
|
23
|
+
previousMessageCount.current = options.wipePrevious
|
|
24
|
+
? 0
|
|
25
|
+
: messages.length;
|
|
26
|
+
let newMessages = options.wipePrevious ? [] : [...messages];
|
|
27
|
+
newMessages = newMessages.filter((m) => m.id !== message.id);
|
|
28
|
+
newMessages.push(Object.assign(Object.assign({}, message), { id: message.id || newRandomId }));
|
|
29
|
+
if (newMessages.length > 3) {
|
|
30
|
+
newMessages.shift();
|
|
31
|
+
}
|
|
32
|
+
return newMessages;
|
|
33
|
+
});
|
|
34
|
+
const removeMessageTimeout = setTimeout(() => {
|
|
35
|
+
removeMessage(newRandomId);
|
|
36
|
+
}, options.timeout || DEFAULT_TIMEOUT);
|
|
37
|
+
removeMessageTimeouts.current.push(removeMessageTimeout);
|
|
38
|
+
}, [removeMessage]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
return () => {
|
|
41
|
+
removeMessageTimeouts.current.forEach((timeout) => clearTimeout(timeout));
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
return (_jsx(SnackBarContext.Provider, Object.assign({ value: {
|
|
45
|
+
messages,
|
|
46
|
+
removeMessage,
|
|
47
|
+
previousMessageCount: previousMessageCount.current,
|
|
48
|
+
addMessage,
|
|
49
|
+
} }, { children: children })));
|
|
50
|
+
};
|
|
51
|
+
export const useSnackBar = () => {
|
|
52
|
+
return useContext(SnackBarContext);
|
|
53
|
+
};
|
|
@@ -7,7 +7,9 @@ import { FontLoader } from '../../FontLoader';
|
|
|
7
7
|
import { GlobalStyles } from '../../theme/GlobalStyles';
|
|
8
8
|
import { DialogsProvider } from './dialogs';
|
|
9
9
|
import { MediaSizeProvider } from './media';
|
|
10
|
+
import { SnackBarProvider } from './snackBar';
|
|
11
|
+
import { UniqueIdProvider } from './uniqueIds';
|
|
10
12
|
export const UiProvider = ({ env, components, alertsConfig, children, includeTheme = true, loadFonts, loadGlobalStyles, }) => {
|
|
11
|
-
const core = (_jsxs(EnvironmentProvider, Object.assign({ env: env }, { children: [_jsx(MediaSizeProvider, { children: _jsx(ComponentConfigProvider, Object.assign({ config: components || {} }, { children: _jsx(DialogsProvider, { children: _jsx(AlertsProvider, Object.assign({}, alertsConfig, { children: children })) }) })) }), loadGlobalStyles && _jsx(GlobalStyles, {}), loadFonts && _jsx(FontLoader, {})] })));
|
|
13
|
+
const core = (_jsxs(EnvironmentProvider, Object.assign({ env: env }, { children: [_jsx(MediaSizeProvider, { children: _jsx(ComponentConfigProvider, Object.assign({ config: components || {} }, { children: _jsx(UniqueIdProvider, { children: _jsx(SnackBarProvider, { children: _jsx(DialogsProvider, { children: _jsx(AlertsProvider, Object.assign({}, alertsConfig, { children: children })) }) }) }) })) }), loadGlobalStyles && _jsx(GlobalStyles, {}), loadFonts && _jsx(FontLoader, {})] })));
|
|
12
14
|
return includeTheme ? _jsx(ThemeProvider, { children: core }) : core;
|
|
13
15
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo, useRef } from 'react';
|
|
3
|
+
const UniqueIdContext = createContext({});
|
|
4
|
+
export const UniqueIdProvider = ({ children, }) => {
|
|
5
|
+
const countIndexRef = useRef({});
|
|
6
|
+
return (_jsx(UniqueIdContext.Provider, Object.assign({ value: countIndexRef.current }, { children: children })));
|
|
7
|
+
};
|
|
8
|
+
export const useUniqueId = (prefix) => {
|
|
9
|
+
const countIndex = useContext(UniqueIdContext);
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
var _a;
|
|
12
|
+
const idForPrefix = ((_a = countIndex[prefix]) === null || _a === void 0 ? void 0 : _a.count) || 1;
|
|
13
|
+
if (!countIndex[prefix]) {
|
|
14
|
+
countIndex[prefix] = {
|
|
15
|
+
count: 2,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
countIndex[prefix].count += 1;
|
|
20
|
+
}
|
|
21
|
+
return `${prefix}-${idForPrefix}`;
|
|
22
|
+
}, []);
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { UniqueIdProvider, useUniqueId } from './uniqueIds';
|
|
4
|
+
const ExampleInner = () => {
|
|
5
|
+
const uniqueId1 = useUniqueId('test-1');
|
|
6
|
+
const uniqueId2 = useUniqueId('test-1');
|
|
7
|
+
const uniqueId3 = useUniqueId('test-2');
|
|
8
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { children: uniqueId1 }), _jsx("div", { children: uniqueId2 }), _jsx("div", { children: uniqueId3 })] }));
|
|
9
|
+
};
|
|
10
|
+
const ExampleOuter = () => {
|
|
11
|
+
return (_jsxs(UniqueIdProvider, { children: [_jsx(ExampleInner, {}), _jsx(ExampleInner, {}), _jsx(ExampleInner, {})] }));
|
|
12
|
+
};
|
|
13
|
+
describe('UniqueIdProvider', () => {
|
|
14
|
+
it('should generate unique ids', () => {
|
|
15
|
+
const { getByText } = render(_jsx(ExampleOuter, {}));
|
|
16
|
+
expect(getByText('test-1-1')).toBeInTheDocument();
|
|
17
|
+
expect(getByText('test-1-2')).toBeInTheDocument();
|
|
18
|
+
expect(getByText('test-2-1')).toBeInTheDocument();
|
|
19
|
+
expect(getByText('test-1-3')).toBeInTheDocument();
|
|
20
|
+
expect(getByText('test-1-4')).toBeInTheDocument();
|
|
21
|
+
expect(getByText('test-2-2')).toBeInTheDocument();
|
|
22
|
+
expect(getByText('test-1-5')).toBeInTheDocument();
|
|
23
|
+
expect(getByText('test-1-6')).toBeInTheDocument();
|
|
24
|
+
expect(getByText('test-2-3')).toBeInTheDocument();
|
|
25
|
+
});
|
|
26
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { theme, ThemeProvider, useTheme } from './theme';
|
|
2
|
+
export type { StylesProp } from './theme';
|
|
2
3
|
export { COLOR } from './theme/colors';
|
|
3
4
|
export { TYPOGRAPHY_TYPE, FONT, FONT_SIZE, FONT_WEIGHT, LINE_HEIGHT, } from './theme/typography';
|
|
4
5
|
export { GlobalStyles } from './theme/GlobalStyles';
|
|
@@ -28,14 +29,21 @@ export { ReadMore } from './components/elements/text/ReadMore';
|
|
|
28
29
|
export { Icon } from './components/elements/Icon';
|
|
29
30
|
export { Spinner, SPINNER_SIZE } from './components/elements/Spinner';
|
|
30
31
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
32
|
+
export { Table, TableColumn } from './components/elements/Table';
|
|
33
|
+
export { TabList, Tab } from './components/elements/TabList';
|
|
31
34
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
35
|
+
export { SnackBar } from './components/composites/SnackBar';
|
|
32
36
|
export { NavMenu } from './components/composites/NavMenu';
|
|
33
37
|
export { EmptyState, EMPTY_STATE_SIZE, } from './components/composites/EmptyState';
|
|
34
38
|
export { DropdownLinks } from './components/composites/DropdownLinks';
|
|
35
39
|
export { Modal } from './components/composites/Modal';
|
|
40
|
+
export { DragDropList, DragHandle } from './components/composites/DragDropList';
|
|
41
|
+
export { Seo } from './components/composites/Seo';
|
|
36
42
|
export { UiProvider } from './components/providers/ui';
|
|
37
43
|
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
44
|
+
export { SnackBarProvider, useSnackBar } from './components/providers/snackBar';
|
|
38
45
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
|
39
46
|
export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
|
|
40
47
|
export { DialogsProvider, useDialog } from './components/providers/dialogs';
|
|
48
|
+
export { useUniqueId } from './components/providers/uniqueIds';
|
|
41
49
|
export { useHover } from './utils/hooks/useHover';
|
package/dist/index.js
CHANGED
|
@@ -28,14 +28,21 @@ export { ReadMore } from './components/elements/text/ReadMore';
|
|
|
28
28
|
export { Icon } from './components/elements/Icon';
|
|
29
29
|
export { Spinner, SPINNER_SIZE } from './components/elements/Spinner';
|
|
30
30
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
31
|
+
export { Table, TableColumn } from './components/elements/Table';
|
|
32
|
+
export { TabList, Tab } from './components/elements/TabList';
|
|
31
33
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
34
|
+
export { SnackBar } from './components/composites/SnackBar';
|
|
32
35
|
export { NavMenu } from './components/composites/NavMenu';
|
|
33
36
|
export { EmptyState, EMPTY_STATE_SIZE, } from './components/composites/EmptyState';
|
|
34
37
|
export { DropdownLinks } from './components/composites/DropdownLinks';
|
|
35
38
|
export { Modal } from './components/composites/Modal';
|
|
39
|
+
export { DragDropList, DragHandle } from './components/composites/DragDropList';
|
|
40
|
+
export { Seo } from './components/composites/Seo';
|
|
36
41
|
export { UiProvider } from './components/providers/ui';
|
|
37
42
|
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
43
|
+
export { SnackBarProvider, useSnackBar } from './components/providers/snackBar';
|
|
38
44
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
|
39
45
|
export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
|
|
40
46
|
export { DialogsProvider, useDialog } from './components/providers/dialogs';
|
|
47
|
+
export { useUniqueId } from './components/providers/uniqueIds';
|
|
41
48
|
export { useHover } from './utils/hooks/useHover';
|
|
@@ -156,11 +156,10 @@ const globalStyles = css `
|
|
|
156
156
|
@font-face {
|
|
157
157
|
font-family: GPCMed;
|
|
158
158
|
font-display: swap;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
format('truetype');
|
|
159
|
+
url('https://static.nd.edu/fonts/gp-min/gpc-medium.woff2') format('woff2'),
|
|
160
|
+
url('https://static.nd.edu/fonts/gp-min/gpc-medium.woff') format('woff'),
|
|
161
|
+
url('https://static.nd.edu/fonts/gp-min/gpc-medium.ttf')
|
|
162
|
+
format('truetype');
|
|
164
163
|
}
|
|
165
164
|
`;
|
|
166
165
|
export const GlobalStyles = () => {
|