@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.
Files changed (30) hide show
  1. package/dist/components/composites/EmptyState/EmptyState.stories.d.ts +1 -0
  2. package/dist/components/composites/EmptyState/EmptyState.stories.js +8 -2
  3. package/dist/components/composites/EmptyState/EmptyState.test.js +1 -1
  4. package/dist/components/composites/EmptyState/index.d.ts +1 -0
  5. package/dist/components/composites/EmptyState/index.js +2 -2
  6. package/dist/components/composites/Modal/Modal.stories.d.ts +6 -0
  7. package/dist/components/composites/Modal/Modal.stories.js +33 -0
  8. package/dist/components/composites/Modal/index.d.ts +17 -0
  9. package/dist/components/composites/Modal/index.js +52 -0
  10. package/dist/components/elements/Button/index.js +1 -1
  11. package/dist/components/elements/Fields/CheckboxGroup/CheckboxGroup.stories.d.ts +1 -0
  12. package/dist/components/elements/Fields/CheckboxGroup/CheckboxGroup.stories.js +3 -0
  13. package/dist/components/elements/Fields/CheckboxGroup/index.d.ts +3 -1
  14. package/dist/components/elements/Fields/CheckboxGroup/index.js +29 -14
  15. package/dist/components/elements/Fields/Select/index.d.ts +3 -3
  16. package/dist/components/elements/text/ReadMore/index.js +1 -1
  17. package/dist/components/providers/componentConfig.d.ts +3 -0
  18. package/dist/components/providers/componentConfig.js +3 -0
  19. package/dist/components/providers/dialogs.d.ts +9 -0
  20. package/dist/components/providers/dialogs.js +32 -0
  21. package/dist/components/providers/media.d.ts +8 -0
  22. package/dist/components/providers/media.js +43 -0
  23. package/dist/components/providers/ui.js +3 -2
  24. package/dist/index.d.ts +4 -2
  25. package/dist/index.js +4 -2
  26. package/dist/theme/custom.d.ts +2 -1
  27. package/dist/theme/custom.js +1 -0
  28. package/package.json +3 -1
  29. package/dist/utils/hooks/useMediaQuery.d.ts +0 -4
  30. package/dist/utils/hooks/useMediaQuery.js +0 -29
@@ -6,4 +6,5 @@ type Story = StoryObj<typeof EmptyState>;
6
6
  export declare const Default: Story;
7
7
  export declare const Small: Story;
8
8
  export declare const CustomMessage: Story;
9
+ export declare const JsxMessage: Story;
9
10
  export declare const CustomIcon: Story;
@@ -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, { message: "Custom message" }),
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, { message: TEST_MESSAGE }));
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', () => {
@@ -6,6 +6,7 @@ export declare enum EMPTY_STATE_SIZE {
6
6
  }
7
7
  type EmptyStateProps = StyledElementProps<HTMLDivElement, {
8
8
  icon?: React.FC;
9
+ omitIcon?: boolean;
9
10
  size?: EMPTY_STATE_SIZE;
10
11
  message?: string;
11
12
  }>;
@@ -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, message, size: sizeProp, sx } = _a, rest = __rest(_a, ["icon", "message", "size", "sx"]);
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: message || DEFAULT_MESSAGE })) }))] })));
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,6 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Modal } from '.';
3
+ declare const meta: Meta<typeof Modal>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Modal>;
6
+ export declare const Default: Story;
@@ -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
+ };
@@ -88,7 +88,7 @@ export const Button = React.forwardRef((_a, ref) => {
88
88
  }
89
89
  if (type === BUTTON_TYPE.OUTLINE) {
90
90
  bg = COLOR.BACKGROUND;
91
- textColor = color || COLOR.PRIMARY;
91
+ textColor = color || COLOR.TEXT;
92
92
  borderColor = textColor;
93
93
  }
94
94
  if (textColorParam) {
@@ -4,3 +4,4 @@ declare const meta: Meta<typeof CheckboxGroup>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof CheckboxGroup>;
6
6
  export declare const Default: Story;
7
+ export declare const Columns: Story;
@@ -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
- return (_jsx(Column, Object.assign({}, rest, { children: options.map((option) => (_jsx(Group, Object.assign({ type: GROUP_TYPE.RAW }, { children: ({ labelTargetId }) => (_jsxs(Row, Object.assign({ sx: {
23
- mb: 3,
24
- alignItems: 'center',
25
- } }, { children: [_jsx(Checkbox, { onChange: (checked) => {
26
- const updatedSet = new Set(checkedOptions || []);
27
- if (checked) {
28
- updatedSet.add(option.value);
29
- }
30
- else {
31
- updatedSet.delete(option.value);
32
- }
33
- onChange(updatedSet);
34
- }, 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.PARAGRAPH_MEDIUM)) }, { children: option.label }))] }))) }), option.value))) })));
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: string;
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: RenderOption<Value, Option>;
14
- renderOptionLabel: RenderOptionLabel<Option>;
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 '../../../../utils/hooks/useMediaQuery';
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,9 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ export declare const DialogsProvider: React.FC<PropsWithChildren>;
3
+ export declare const useDialog: (id: string) => {
4
+ open: () => void;
5
+ close: () => void;
6
+ state: {
7
+ isOpen: boolean;
8
+ };
9
+ };
@@ -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
- console.log('here');
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';
@@ -5,5 +5,6 @@ export declare enum BOX_SHADOW {
5
5
  export declare enum Z_INDEX {
6
6
  NORMAL = 1,
7
7
  LABEL = 2,
8
- DROPDOWN = 3
8
+ DROPDOWN = 3,
9
+ MODAL = 4
9
10
  }
@@ -9,4 +9,5 @@ export var Z_INDEX;
9
9
  Z_INDEX[Z_INDEX["NORMAL"] = 1] = "NORMAL";
10
10
  Z_INDEX[Z_INDEX["LABEL"] = 2] = "LABEL";
11
11
  Z_INDEX[Z_INDEX["DROPDOWN"] = 3] = "DROPDOWN";
12
+ Z_INDEX[Z_INDEX["MODAL"] = 4] = "MODAL";
12
13
  })(Z_INDEX || (Z_INDEX = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndlib/component-library",
3
- "version": "0.0.35",
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,4 +0,0 @@
1
- export declare const useMediaQuery: () => {
2
- screenSize: number;
3
- breakpoint: number | undefined;
4
- };
@@ -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
- };