@ndlib/component-library 0.0.35 → 0.0.37
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/EmptyState/EmptyState.stories.d.ts +1 -0
- package/dist/components/composites/EmptyState/EmptyState.stories.js +8 -2
- package/dist/components/composites/EmptyState/EmptyState.test.js +1 -1
- package/dist/components/composites/EmptyState/index.d.ts +1 -0
- package/dist/components/composites/EmptyState/index.js +2 -2
- package/dist/components/composites/Modal/Modal.stories.d.ts +6 -0
- package/dist/components/composites/Modal/Modal.stories.js +33 -0
- package/dist/components/composites/Modal/index.d.ts +17 -0
- package/dist/components/composites/Modal/index.js +52 -0
- package/dist/components/elements/Button/index.js +1 -1
- package/dist/components/elements/Fields/CheckboxGroup/CheckboxGroup.stories.d.ts +1 -0
- package/dist/components/elements/Fields/CheckboxGroup/CheckboxGroup.stories.js +3 -0
- package/dist/components/elements/Fields/CheckboxGroup/index.d.ts +3 -1
- package/dist/components/elements/Fields/CheckboxGroup/index.js +29 -14
- package/dist/components/elements/Fields/Select/index.d.ts +3 -3
- package/dist/components/elements/text/ReadMore/index.js +1 -1
- package/dist/components/providers/componentConfig.d.ts +3 -0
- package/dist/components/providers/componentConfig.js +3 -0
- package/dist/components/providers/dialogs.d.ts +9 -0
- package/dist/components/providers/dialogs.js +32 -0
- package/dist/components/providers/media.d.ts +8 -0
- package/dist/components/providers/media.js +43 -0
- package/dist/components/providers/ui.js +3 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/theme/custom.d.ts +2 -1
- package/dist/theme/custom.js +1 -0
- package/package.json +3 -1
- package/dist/utils/hooks/useMediaQuery.d.ts +0 -4
- package/dist/utils/hooks/useMediaQuery.js +0 -29
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { EMPTY_STATE_SIZE, EmptyState } from '.';
|
|
3
3
|
import NotInterestedIcon from '@mui/icons-material/NotInterested';
|
|
4
|
+
import { Link } from '../../elements/Link';
|
|
5
|
+
import { FONT_SIZE } from '../../../theme/typography';
|
|
4
6
|
const meta = {
|
|
5
7
|
title: 'Composites/EmptyState',
|
|
6
8
|
component: EmptyState,
|
|
@@ -16,7 +18,11 @@ export const Small = {
|
|
|
16
18
|
args: {},
|
|
17
19
|
};
|
|
18
20
|
export const CustomMessage = {
|
|
19
|
-
render: () => _jsx(EmptyState, {
|
|
21
|
+
render: () => _jsx(EmptyState, { children: "Custom message" }),
|
|
22
|
+
args: {},
|
|
23
|
+
};
|
|
24
|
+
export const JsxMessage = {
|
|
25
|
+
render: () => (_jsxs(EmptyState, { children: ["Something is wrong.", ' ', _jsx(Link, Object.assign({ to: "/", sx: { fontSize: FONT_SIZE.MD } }, { children: "Click here to fix." }))] })),
|
|
20
26
|
args: {},
|
|
21
27
|
};
|
|
22
28
|
export const CustomIcon = {
|
|
@@ -6,7 +6,7 @@ const MOCK_ICON_TEST_ID = 'mock-icon';
|
|
|
6
6
|
const MockIcon = () => _jsx("div", { "data-testid": MOCK_ICON_TEST_ID });
|
|
7
7
|
describe('EmptyState', () => {
|
|
8
8
|
it('renders passed message', () => {
|
|
9
|
-
const { getByText } = render(_jsx(EmptyState, {
|
|
9
|
+
const { getByText } = render(_jsx(EmptyState, { children: TEST_MESSAGE }));
|
|
10
10
|
expect(getByText(TEST_MESSAGE)).toBeDefined();
|
|
11
11
|
});
|
|
12
12
|
it('renders default message if no message passed', () => {
|
|
@@ -26,7 +26,7 @@ export var EMPTY_STATE_SIZE;
|
|
|
26
26
|
})(EMPTY_STATE_SIZE || (EMPTY_STATE_SIZE = {}));
|
|
27
27
|
export const DEFAULT_MESSAGE = 'No results found.';
|
|
28
28
|
export const EmptyState = (_a) => {
|
|
29
|
-
var { icon,
|
|
29
|
+
var { omitIcon, icon, children, size: sizeProp, sx } = _a, rest = __rest(_a, ["omitIcon", "icon", "children", "size", "sx"]);
|
|
30
30
|
const size = sizeProp || EMPTY_STATE_SIZE.LG;
|
|
31
|
-
return (_jsxs(Column, Object.assign({ sx: Object.assign({ width: '100%', alignItems: 'center', justifyContent: 'center', mt: size === EMPTY_STATE_SIZE.SM ? 3 : 5 }, sx) }, rest, { children: [_jsx(Row, { children: _jsx(Icon, { icon: icon || SearchOffIcon, size: size === EMPTY_STATE_SIZE.SM ? FONT_SIZE.ML : FONT_SIZE.XL, color: COLOR.GRAY }) }), _jsx(Row, Object.assign({ sx: { mt: size === EMPTY_STATE_SIZE.SM ? 0 : 1 } }, { children: _jsx(Paragraph, Object.assign({ sx: { color: COLOR.GRAY }, size: size === EMPTY_STATE_SIZE.SM ? PARAGRAPH_SIZE.MD : PARAGRAPH_SIZE.LG }, { children:
|
|
31
|
+
return (_jsxs(Column, Object.assign({ sx: Object.assign({ width: '100%', alignItems: 'center', justifyContent: 'center', mt: size === EMPTY_STATE_SIZE.SM ? 3 : 5 }, sx) }, rest, { children: [_jsx(Row, { children: omitIcon ? null : (_jsx(Icon, { icon: icon || SearchOffIcon, size: size === EMPTY_STATE_SIZE.SM ? FONT_SIZE.ML : FONT_SIZE.XL, color: COLOR.GRAY })) }), _jsx(Row, Object.assign({ sx: { mt: size === EMPTY_STATE_SIZE.SM ? 0 : 1 } }, { children: _jsx(Paragraph, Object.assign({ sx: { color: COLOR.GRAY }, size: size === EMPTY_STATE_SIZE.SM ? PARAGRAPH_SIZE.MD : PARAGRAPH_SIZE.LG }, { children: children || DEFAULT_MESSAGE })) }))] })));
|
|
32
32
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Modal } from '.';
|
|
3
|
+
import { Button } from '../../elements/Button';
|
|
4
|
+
import { Paragraph } from '../../elements/text/Paragraph';
|
|
5
|
+
import { useDialog } from '../../providers/dialogs';
|
|
6
|
+
import { useTheme } from '../../../theme';
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Composites/Modal',
|
|
9
|
+
component: Modal,
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
const ModalExample = () => {
|
|
14
|
+
const modalId = 'modal-example';
|
|
15
|
+
const { open, close, state } = useDialog(modalId);
|
|
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: [
|
|
18
|
+
{
|
|
19
|
+
label: 'Secondary',
|
|
20
|
+
isPrimary: false,
|
|
21
|
+
onClick: () => { },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'Primary',
|
|
25
|
+
isPrimary: true,
|
|
26
|
+
onClick: () => { },
|
|
27
|
+
},
|
|
28
|
+
] }, { children: _jsx(Paragraph, { children: "Modal body goes here" }) }))] }));
|
|
29
|
+
};
|
|
30
|
+
export const Default = {
|
|
31
|
+
render: () => _jsx(ModalExample, {}),
|
|
32
|
+
args: {},
|
|
33
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyledElementProps } from '../../../theme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
type ModalProps = StyledElementProps<HTMLDivElement, {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
close: () => void;
|
|
6
|
+
heading: string;
|
|
7
|
+
hideHeading?: boolean;
|
|
8
|
+
footer?: React.ReactNode;
|
|
9
|
+
actions?: ModalAction[];
|
|
10
|
+
}>;
|
|
11
|
+
type ModalAction = {
|
|
12
|
+
label: string;
|
|
13
|
+
isPrimary?: boolean;
|
|
14
|
+
onClick: () => void;
|
|
15
|
+
};
|
|
16
|
+
export declare const Modal: React.FC<ModalProps>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
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 _ReactModal from 'react-modal';
|
|
14
|
+
import { importedDefaultComponentShim } from '../../../utils/misc';
|
|
15
|
+
import { useTheme } from '../../../theme';
|
|
16
|
+
import { GROUP_TYPE, Group } from '../../elements/Group';
|
|
17
|
+
import { Row } from '../../elements/layout/Row';
|
|
18
|
+
import { HEADING_SIZE, Heading } from '../../elements/text/Heading';
|
|
19
|
+
import { BUTTON_TYPE, Button } from '../../elements/Button';
|
|
20
|
+
import { COLOR } from '../../../theme/colors';
|
|
21
|
+
import { TYPOGRAPHY_TYPE } from '../../../theme/typography';
|
|
22
|
+
import { useMediaQuery } from '../../providers/media';
|
|
23
|
+
import { useComponentConfig } from '../../providers/componentConfig';
|
|
24
|
+
const ReactModal = importedDefaultComponentShim(_ReactModal);
|
|
25
|
+
export const Modal = (_a) => {
|
|
26
|
+
var { children, heading, hideHeading, isOpen, footer, actions, close } = _a, props = __rest(_a, ["children", "heading", "hideHeading", "isOpen", "footer", "actions", "close"]);
|
|
27
|
+
const { breakpoint } = useMediaQuery();
|
|
28
|
+
const { modal } = useComponentConfig();
|
|
29
|
+
const theme = useTheme();
|
|
30
|
+
return (_jsx(ReactModal, Object.assign({ isOpen: isOpen, shouldFocusAfterRender: true, appElement: modal.appElement, onRequestClose: close }, props, { style: {
|
|
31
|
+
overlay: {
|
|
32
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
33
|
+
zIndex: theme.zIndex.MODAL,
|
|
34
|
+
},
|
|
35
|
+
content: {
|
|
36
|
+
padding: 0,
|
|
37
|
+
minWidth: breakpoint === 0 ? 'calc(100% - 1rem)' : '500px',
|
|
38
|
+
top: '50%',
|
|
39
|
+
left: '50%',
|
|
40
|
+
right: 'auto',
|
|
41
|
+
bottom: 'auto',
|
|
42
|
+
marginRight: '-50%',
|
|
43
|
+
transform: 'translate(-50%, -50%)',
|
|
44
|
+
},
|
|
45
|
+
} }, { children: _jsxs(Group, Object.assign({ type: GROUP_TYPE.REGION, sx: { my: 0 } }, { children: [!hideHeading && (_jsxs(Row, Object.assign({ justify: "space-between", align: "center", sx: {
|
|
46
|
+
p: 3,
|
|
47
|
+
borderBottom: 'solid 1px',
|
|
48
|
+
borderColor: COLOR.LIGHT_GRAY,
|
|
49
|
+
} }, { children: [_jsx(Heading, Object.assign({ size: HEADING_SIZE.SM, typography: TYPOGRAPHY_TYPE.CONTROL_MEDIUM }, { children: heading })), _jsx(Button, Object.assign({ type: BUTTON_TYPE.TEXT, onClick: close }, { children: "Close" }))] }))), _jsx(Row, Object.assign({ sx: { p: 3 } }, { children: children })), _jsxs(Row, Object.assign({ sx: { borderTop: 'solid 1px', borderColor: COLOR.LIGHT_GRAY, p: 3 } }, { children: [footer, actions !== undefined && (_jsx(Row, Object.assign({ sx: { width: '100%', justifyContent: 'flex-end' } }, { children: actions.map((action, index) => (_jsx(Button, Object.assign({ type: action.isPrimary ? BUTTON_TYPE.DEFAULT : BUTTON_TYPE.OUTLINE, onClick: action.onClick, sx: {
|
|
50
|
+
mr: index < actions.length - 1 ? 1 : 0,
|
|
51
|
+
} }, { children: action.label }), index))) })))] }))] })) })));
|
|
52
|
+
};
|
|
@@ -21,3 +21,6 @@ const StatefulCheckboxGroup = (props) => {
|
|
|
21
21
|
export const Default = {
|
|
22
22
|
render: () => (_jsx(Row, { children: _jsx(StatefulCheckboxGroup, {}) })),
|
|
23
23
|
};
|
|
24
|
+
export const Columns = {
|
|
25
|
+
render: () => (_jsx(Row, { children: _jsx(StatefulCheckboxGroup, { columns: 2 }) })),
|
|
26
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyledElementProps } from '../../../../theme';
|
|
2
|
+
import { StyledElementProps, StylesProp } from '../../../../theme';
|
|
3
3
|
import { Key } from '../option';
|
|
4
4
|
type Option = {
|
|
5
5
|
value: Key;
|
|
@@ -9,6 +9,8 @@ type CheckboxGroupProps = StyledElementProps<HTMLDivElement, {
|
|
|
9
9
|
onChange: (value: Set<Key>) => void;
|
|
10
10
|
options: Option[];
|
|
11
11
|
checkedOptions?: Set<Key>;
|
|
12
|
+
columnStyles: StylesProp;
|
|
13
|
+
columns?: number;
|
|
12
14
|
}, string>;
|
|
13
15
|
export declare const CheckboxGroup: React.FC<CheckboxGroupProps>;
|
|
14
16
|
export {};
|
|
@@ -10,6 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { useMemo } from 'react';
|
|
13
14
|
import { Row } from '../../layout/Row';
|
|
14
15
|
import { Checkbox } from '../Checkbox';
|
|
15
16
|
import { Label } from '../../text/Label';
|
|
@@ -18,18 +19,32 @@ import { GROUP_TYPE } from '../../Group';
|
|
|
18
19
|
import { Column } from '../../layout/Column';
|
|
19
20
|
import { TYPOGRAPHY_TYPE, getTypographyStyles, } from '../../../../theme/typography';
|
|
20
21
|
export const CheckboxGroup = (_a) => {
|
|
21
|
-
var { options, checkedOptions, onChange } = _a, rest = __rest(_a, ["options", "checkedOptions", "onChange"]);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
var { options, checkedOptions, columns: columnsProp, columnStyles, onChange } = _a, rest = __rest(_a, ["options", "checkedOptions", "columns", "columnStyles", "onChange"]);
|
|
23
|
+
const columns = columnsProp || 1;
|
|
24
|
+
const optionsByColumn = useMemo(() => {
|
|
25
|
+
// place first i/n items into first column, next i/n items into second column, etc.
|
|
26
|
+
const optionsByColumn = [];
|
|
27
|
+
for (let i = 0; i < options.length; i++) {
|
|
28
|
+
const maxPerColumn = Math.ceil(options.length / columns);
|
|
29
|
+
const columnIndex = Math.floor(i / maxPerColumn);
|
|
30
|
+
if (optionsByColumn[columnIndex] === undefined) {
|
|
31
|
+
optionsByColumn[columnIndex] = [];
|
|
32
|
+
}
|
|
33
|
+
optionsByColumn[columnIndex].push(options[i]);
|
|
34
|
+
}
|
|
35
|
+
return optionsByColumn;
|
|
36
|
+
}, [options, columns]);
|
|
37
|
+
return (_jsx(Row, Object.assign({}, rest, { children: optionsByColumn.map((options, index) => (_jsx(Column, Object.assign({ grow: 1, sx: Object.assign({ mr: 4 }, columnStyles) }, { children: options.map((option) => (_jsx(Group, Object.assign({ type: GROUP_TYPE.RAW }, { children: ({ labelTargetId }) => (_jsxs(Row, Object.assign({ sx: {
|
|
38
|
+
mb: 3,
|
|
39
|
+
alignItems: 'center',
|
|
40
|
+
} }, { children: [_jsx(Checkbox, { onChange: (checked) => {
|
|
41
|
+
const updatedSet = new Set(checkedOptions || []);
|
|
42
|
+
if (checked) {
|
|
43
|
+
updatedSet.add(option.value);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
updatedSet.delete(option.value);
|
|
47
|
+
}
|
|
48
|
+
onChange(updatedSet);
|
|
49
|
+
}, checked: !!(checkedOptions === null || checkedOptions === void 0 ? void 0 : checkedOptions.has(option.value)), id: labelTargetId, sx: { mr: 2 } }), _jsx(Label, Object.assign({ sx: Object.assign({ cursor: 'pointer' }, getTypographyStyles(TYPOGRAPHY_TYPE.CONDENSED_TEXT_MEDIUM)) }, { children: option.label }))] }))) }), option.value))) }), index))) })));
|
|
35
50
|
};
|
|
@@ -3,15 +3,15 @@ import { StyledElementProps } from '../../../../theme';
|
|
|
3
3
|
import { INPUT_SIZE } from '../TextInput';
|
|
4
4
|
import { BasicOption, Key, RenderOption, RenderOptionLabel } from '../option';
|
|
5
5
|
type SelectProps<Value extends Key, Option extends BasicOption<Value>> = StyledElementProps<HTMLSelectElement, {
|
|
6
|
-
placeholder
|
|
6
|
+
placeholder?: string;
|
|
7
7
|
size?: INPUT_SIZE;
|
|
8
8
|
leftIcon?: React.FC<any>;
|
|
9
9
|
value: Value;
|
|
10
10
|
label?: string;
|
|
11
11
|
onSelectOption: (value: Value) => void;
|
|
12
12
|
options: Option[];
|
|
13
|
-
renderOption
|
|
14
|
-
renderOptionLabel
|
|
13
|
+
renderOption?: RenderOption<Value, Option>;
|
|
14
|
+
renderOptionLabel?: RenderOptionLabel<Option>;
|
|
15
15
|
}, string>;
|
|
16
16
|
export declare function Select<Value extends Key, Option extends BasicOption<Value>>({ size: sizeParam, placeholder, leftIcon, value, label, onSelectOption, options, renderOption, renderOptionLabel: renderOptionLabelParam, sx, }: SelectProps<Value, Option>): import("react/jsx-runtime").JSX.Element;
|
|
17
17
|
export {};
|
|
@@ -15,7 +15,7 @@ import React, { useState } from 'react';
|
|
|
15
15
|
import { useTheme } from '../../../../theme';
|
|
16
16
|
import { COLOR, colors } from '../../../../theme/colors';
|
|
17
17
|
import { getTypographyStyles, } from '../../../../theme/typography';
|
|
18
|
-
import { useMediaQuery } from '
|
|
18
|
+
import { useMediaQuery } from '../../../providers/media';
|
|
19
19
|
const ReadMoreLink = (props) => {
|
|
20
20
|
// const theme = useTheme()
|
|
21
21
|
const bg = colors[props.bg || COLOR.BACKGROUND];
|
|
@@ -8,6 +8,9 @@ export type ComponentConfig = {
|
|
|
8
8
|
internalLinkComponent: React.FC<LinkComponentProps>;
|
|
9
9
|
externalLinkComponent: React.FC<LinkComponentProps>;
|
|
10
10
|
};
|
|
11
|
+
modal: {
|
|
12
|
+
appElement: HTMLElement | undefined;
|
|
13
|
+
};
|
|
11
14
|
};
|
|
12
15
|
export type ComponentConfigParam = DeepPartial<ComponentConfig>;
|
|
13
16
|
export type LinkComponentProps = StyledElementProps<HTMLAnchorElement, {
|
|
@@ -25,6 +25,9 @@ const defaultComponentConfig = {
|
|
|
25
25
|
internalLinkComponent: DefaultLink,
|
|
26
26
|
externalLinkComponent: DefaultLink,
|
|
27
27
|
},
|
|
28
|
+
modal: {
|
|
29
|
+
appElement: undefined,
|
|
30
|
+
},
|
|
28
31
|
};
|
|
29
32
|
export const ComponentConfigContext = createContext(defaultComponentConfig);
|
|
30
33
|
export const useComponentConfig = () => useContext(ComponentConfigContext);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
const DialogContext = React.createContext({
|
|
4
|
+
open: () => { },
|
|
5
|
+
close: () => { },
|
|
6
|
+
dialogs: {},
|
|
7
|
+
});
|
|
8
|
+
export const DialogsProvider = ({ children }) => {
|
|
9
|
+
const [dialogs, setDialogs] = React.useState({});
|
|
10
|
+
const open = (key) => {
|
|
11
|
+
setDialogs(Object.assign(Object.assign({}, dialogs), { [key]: { isOpen: true } }));
|
|
12
|
+
};
|
|
13
|
+
const close = (key) => {
|
|
14
|
+
setDialogs(Object.assign(Object.assign({}, dialogs), { [key]: { isOpen: false } }));
|
|
15
|
+
};
|
|
16
|
+
return (_jsx(DialogContext.Provider, Object.assign({ value: {
|
|
17
|
+
dialogs,
|
|
18
|
+
open,
|
|
19
|
+
close,
|
|
20
|
+
} }, { children: children })));
|
|
21
|
+
};
|
|
22
|
+
export const useDialog = (id) => {
|
|
23
|
+
const dialogs = React.useContext(DialogContext);
|
|
24
|
+
const open = () => dialogs.open(id);
|
|
25
|
+
const close = () => dialogs.close(id);
|
|
26
|
+
const state = dialogs.dialogs[id] || { isOpen: false };
|
|
27
|
+
return {
|
|
28
|
+
open,
|
|
29
|
+
close,
|
|
30
|
+
state,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
type MediaContextType = {
|
|
3
|
+
screenSize: number;
|
|
4
|
+
breakpoint: number;
|
|
5
|
+
};
|
|
6
|
+
export declare const MediaSizeProvider: React.FC<PropsWithChildren>;
|
|
7
|
+
export declare const useMediaQuery: () => MediaContextType;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo, useState, } from 'react';
|
|
3
|
+
import { useTheme } from '../../theme';
|
|
4
|
+
const MediaContext = createContext({
|
|
5
|
+
screenSize: -1,
|
|
6
|
+
breakpoint: -1,
|
|
7
|
+
});
|
|
8
|
+
export const MediaSizeProvider = ({ children, }) => {
|
|
9
|
+
const [renderCount, setRenderCount] = useState(0);
|
|
10
|
+
const theme = useTheme();
|
|
11
|
+
const breakpoints = theme.breakpoints.map((bp) => parseInt(bp.slice(0, -2)), [theme]);
|
|
12
|
+
const { screenSize, breakpoint } = useMemo(() => {
|
|
13
|
+
if (typeof window === 'undefined') {
|
|
14
|
+
return {
|
|
15
|
+
screenSize: -1,
|
|
16
|
+
breakpoint: -1,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const screenSize = window.innerWidth;
|
|
20
|
+
const closestBreakpoint = breakpoints.findIndex((bp) => screenSize < bp);
|
|
21
|
+
const breakpoint = closestBreakpoint === -1 ? breakpoints.length : closestBreakpoint;
|
|
22
|
+
return {
|
|
23
|
+
screenSize,
|
|
24
|
+
breakpoint,
|
|
25
|
+
};
|
|
26
|
+
}, [renderCount, breakpoints]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (typeof window === 'undefined')
|
|
29
|
+
return;
|
|
30
|
+
const rerenderOnResize = () => {
|
|
31
|
+
setRenderCount((renderCount) => renderCount + 1);
|
|
32
|
+
};
|
|
33
|
+
window.addEventListener('resize', rerenderOnResize);
|
|
34
|
+
return () => {
|
|
35
|
+
window.removeEventListener('resize', rerenderOnResize);
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
return (_jsx(MediaContext.Provider, Object.assign({ value: {
|
|
39
|
+
breakpoint,
|
|
40
|
+
screenSize,
|
|
41
|
+
} }, { children: children })));
|
|
42
|
+
};
|
|
43
|
+
export const useMediaQuery = () => useContext(MediaContext);
|
|
@@ -5,7 +5,8 @@ import { ThemeProvider } from '../../theme/';
|
|
|
5
5
|
import { AlertsProvider } from './alerts';
|
|
6
6
|
import { FontLoader } from '../../FontLoader';
|
|
7
7
|
import { GlobalStyles } from '../../theme/GlobalStyles';
|
|
8
|
+
import { DialogsProvider } from './dialogs';
|
|
9
|
+
import { MediaSizeProvider } from './media';
|
|
8
10
|
export const UiProvider = ({ env, components, alertsConfig, children, loadFonts, loadGlobalStyles, }) => {
|
|
9
|
-
|
|
10
|
-
return (_jsxs(EnvironmentProvider, Object.assign({ env: env }, { children: [_jsx(ComponentConfigProvider, Object.assign({ config: components || {} }, { children: _jsx(ThemeProvider, { children: _jsx(AlertsProvider, Object.assign({}, alertsConfig, { children: children })) }) })), loadGlobalStyles && _jsx(GlobalStyles, {}), loadFonts && _jsx(FontLoader, {})] })));
|
|
11
|
+
return (_jsxs(EnvironmentProvider, Object.assign({ env: env }, { children: [_jsx(ThemeProvider, { 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, {})] })));
|
|
11
12
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -30,10 +30,12 @@ export { Spinner, SPINNER_SIZE } from './components/elements/Spinner';
|
|
|
30
30
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
31
31
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
32
32
|
export { NavMenu } from './components/composites/NavMenu';
|
|
33
|
-
export { EmptyState } from './components/composites/EmptyState';
|
|
33
|
+
export { EmptyState, EMPTY_STATE_SIZE, } from './components/composites/EmptyState';
|
|
34
34
|
export { DropdownLinks } from './components/composites/DropdownLinks';
|
|
35
|
+
export { Modal } from './components/composites/Modal';
|
|
35
36
|
export { UiProvider } from './components/providers/ui';
|
|
36
37
|
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
37
38
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
|
39
|
+
export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
|
|
40
|
+
export { DialogsProvider, useDialog } from './components/providers/dialogs';
|
|
38
41
|
export { useHover } from './utils/hooks/useHover';
|
|
39
|
-
export { useMediaQuery } from './utils/hooks/useMediaQuery';
|
package/dist/index.js
CHANGED
|
@@ -30,10 +30,12 @@ export { Spinner, SPINNER_SIZE } from './components/elements/Spinner';
|
|
|
30
30
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
31
31
|
export { Card, CARD_SIZE, CARD_LAYOUT } from './components/composites/Card';
|
|
32
32
|
export { NavMenu } from './components/composites/NavMenu';
|
|
33
|
-
export { EmptyState } from './components/composites/EmptyState';
|
|
33
|
+
export { EmptyState, EMPTY_STATE_SIZE, } from './components/composites/EmptyState';
|
|
34
34
|
export { DropdownLinks } from './components/composites/DropdownLinks';
|
|
35
|
+
export { Modal } from './components/composites/Modal';
|
|
35
36
|
export { UiProvider } from './components/providers/ui';
|
|
36
37
|
export { MenuProvider, useMenu } from './components/providers/menu';
|
|
37
38
|
export { useAlerts, AlertsProvider, ALERT_DOMAIN, } from './components/providers/alerts';
|
|
39
|
+
export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
|
|
40
|
+
export { DialogsProvider, useDialog } from './components/providers/dialogs';
|
|
38
41
|
export { useHover } from './utils/hooks/useHover';
|
|
39
|
-
export { useMediaQuery } from './utils/hooks/useMediaQuery';
|
package/dist/theme/custom.d.ts
CHANGED
package/dist/theme/custom.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ndlib/component-library",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.37",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@types/react": "^18.0.28",
|
|
55
55
|
"@types/react-datepicker": "^4.15.0",
|
|
56
56
|
"@types/react-dom": "^18.0.11",
|
|
57
|
+
"@types/react-modal": "^3.16.0",
|
|
57
58
|
"@types/sanitize-html": "^2.9.0",
|
|
58
59
|
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
|
59
60
|
"@typescript-eslint/parser": "^5.57.1",
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"@floating-ui/react": "^0.24.5",
|
|
83
84
|
"react-datepicker": "^4.16.0",
|
|
84
85
|
"react-markdown": "^8.0.7",
|
|
86
|
+
"react-modal": "^3.16.1",
|
|
85
87
|
"rehype-raw": "^6.1.1",
|
|
86
88
|
"sanitize-html": "^2.11.0"
|
|
87
89
|
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { useTheme } from '../../theme';
|
|
3
|
-
export const useMediaQuery = () => {
|
|
4
|
-
const [screenSize, setScreenSize] = useState(typeof window !== 'undefined' ? window.innerWidth : 0);
|
|
5
|
-
const [breakpoint, setBreakpoint] = useState(undefined);
|
|
6
|
-
const theme = useTheme();
|
|
7
|
-
const breakpoints = theme.breakpoints.map((bp) => parseInt(bp.slice(0, -2)), [theme]);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
if (typeof window === 'undefined')
|
|
10
|
-
return;
|
|
11
|
-
const handleResize = () => {
|
|
12
|
-
const screenSize = window.innerWidth;
|
|
13
|
-
let closestBreakpoint = breakpoints.findIndex((bp) => screenSize < bp);
|
|
14
|
-
closestBreakpoint =
|
|
15
|
-
closestBreakpoint === -1 ? breakpoints.length : closestBreakpoint;
|
|
16
|
-
setBreakpoint(closestBreakpoint);
|
|
17
|
-
setScreenSize(screenSize);
|
|
18
|
-
};
|
|
19
|
-
window.addEventListener('resize', handleResize);
|
|
20
|
-
handleResize();
|
|
21
|
-
return () => {
|
|
22
|
-
window.removeEventListener('resize', handleResize);
|
|
23
|
-
};
|
|
24
|
-
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
25
|
-
return {
|
|
26
|
-
screenSize,
|
|
27
|
-
breakpoint,
|
|
28
|
-
};
|
|
29
|
-
};
|