@lumx/react 3.10.0 → 3.10.1-alpha.0

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 (101) hide show
  1. package/_internal/index.d.ts +1 -1
  2. package/index.d.ts +13 -5
  3. package/index.js +217 -202
  4. package/index.js.map +1 -1
  5. package/package.json +3 -3
  6. package/src/components/autocomplete/Autocomplete.test.tsx +9 -2
  7. package/src/components/autocomplete/Autocomplete.tsx +3 -1
  8. package/src/components/autocomplete/AutocompleteMultiple.test.tsx +9 -2
  9. package/src/components/autocomplete/AutocompleteMultiple.tsx +3 -1
  10. package/src/components/avatar/Avatar.test.tsx +14 -4
  11. package/src/components/avatar/Avatar.tsx +3 -2
  12. package/src/components/button/Button.test.tsx +9 -3
  13. package/src/components/button/Button.tsx +3 -2
  14. package/src/components/button/IconButton.test.tsx +9 -3
  15. package/src/components/button/IconButton.tsx +13 -2
  16. package/src/components/checkbox/Checkbox.test.tsx +9 -3
  17. package/src/components/checkbox/Checkbox.tsx +4 -4
  18. package/src/components/chip/Chip.test.tsx +14 -4
  19. package/src/components/chip/Chip.tsx +3 -2
  20. package/src/components/comment-block/CommentBlock.test.tsx +9 -3
  21. package/src/components/comment-block/CommentBlock.tsx +3 -2
  22. package/src/components/date-picker/DatePickerField.test.tsx +9 -3
  23. package/src/components/dialog/Dialog.test.tsx +17 -4
  24. package/src/components/dialog/Dialog.tsx +61 -58
  25. package/src/components/divider/Divider.test.tsx +9 -3
  26. package/src/components/divider/Divider.tsx +4 -4
  27. package/src/components/drag-handle/DragHandle.test.tsx +38 -0
  28. package/src/components/drag-handle/DragHandle.tsx +3 -1
  29. package/src/components/expansion-panel/ExpansionPanel.test.tsx +12 -3
  30. package/src/components/expansion-panel/ExpansionPanel.tsx +4 -4
  31. package/src/components/flag/Flag.test.tsx +14 -4
  32. package/src/components/flag/Flag.tsx +4 -4
  33. package/src/components/icon/Icon.test.tsx +13 -4
  34. package/src/components/icon/Icon.tsx +13 -1
  35. package/src/components/image-block/ImageBlock.test.tsx +12 -4
  36. package/src/components/image-block/ImageBlock.tsx +3 -2
  37. package/src/components/input-helper/InputHelper.test.tsx +14 -4
  38. package/src/components/input-helper/InputHelper.tsx +3 -2
  39. package/src/components/input-label/InputLabel.test.tsx +14 -4
  40. package/src/components/input-label/InputLabel.tsx +4 -4
  41. package/src/components/lightbox/Lightbox.test.tsx +17 -6
  42. package/src/components/lightbox/Lightbox.tsx +8 -5
  43. package/src/components/link-preview/LinkPreview.test.tsx +9 -3
  44. package/src/components/link-preview/LinkPreview.tsx +3 -2
  45. package/src/components/mosaic/Mosaic.test.tsx +9 -3
  46. package/src/components/mosaic/Mosaic.tsx +4 -4
  47. package/src/components/navigation/Navigation.test.tsx +18 -9
  48. package/src/components/navigation/Navigation.tsx +13 -5
  49. package/src/components/navigation/NavigationItem.tsx +3 -3
  50. package/src/components/navigation/NavigationSection.tsx +4 -4
  51. package/src/components/notification/Notification.tsx +3 -2
  52. package/src/components/popover/Popover.test.tsx +18 -4
  53. package/src/components/popover/Popover.tsx +2 -1
  54. package/src/components/post-block/PostBlock.test.tsx +9 -3
  55. package/src/components/post-block/PostBlock.tsx +3 -2
  56. package/src/components/progress/Progress.tsx +3 -2
  57. package/src/components/progress/ProgressCircular.test.tsx +9 -16
  58. package/src/components/progress/ProgressCircular.tsx +3 -2
  59. package/src/components/progress/ProgressLinear.test.tsx +13 -18
  60. package/src/components/progress/ProgressLinear.tsx +4 -4
  61. package/src/components/radio-button/RadioButton.test.tsx +9 -3
  62. package/src/components/radio-button/RadioButton.tsx +4 -4
  63. package/src/components/select/Select.test.tsx +9 -3
  64. package/src/components/select/Select.tsx +27 -23
  65. package/src/components/select/SelectMultiple.test.tsx +9 -3
  66. package/src/components/select/SelectMultiple.tsx +109 -103
  67. package/src/components/select/WithSelectContext.tsx +8 -6
  68. package/src/components/side-navigation/SideNavigation.tsx +3 -1
  69. package/src/components/skeleton/SkeletonCircle.test.tsx +9 -3
  70. package/src/components/skeleton/SkeletonCircle.tsx +4 -4
  71. package/src/components/skeleton/SkeletonRectangle.test.tsx +9 -3
  72. package/src/components/skeleton/SkeletonRectangle.tsx +3 -2
  73. package/src/components/skeleton/SkeletonTypography.test.tsx +9 -3
  74. package/src/components/skeleton/SkeletonTypography.tsx +4 -4
  75. package/src/components/slider/Slider.test.tsx +9 -3
  76. package/src/components/slider/Slider.tsx +3 -2
  77. package/src/components/slideshow/Slides.tsx +3 -1
  78. package/src/components/slideshow/Slideshow.test.tsx +9 -3
  79. package/src/components/slideshow/Slideshow.tsx +3 -2
  80. package/src/components/slideshow/SlideshowControls.tsx +3 -2
  81. package/src/components/switch/Switch.test.tsx +9 -3
  82. package/src/components/switch/Switch.tsx +3 -2
  83. package/src/components/table/Table.test.tsx +9 -3
  84. package/src/components/table/Table.tsx +4 -4
  85. package/src/components/tabs/TabList.test.tsx +9 -3
  86. package/src/components/tabs/TabList.tsx +11 -2
  87. package/src/components/text-field/TextField.test.tsx +9 -3
  88. package/src/components/text-field/TextField.tsx +3 -2
  89. package/src/components/thumbnail/Thumbnail.test.tsx +9 -3
  90. package/src/components/thumbnail/Thumbnail.tsx +3 -2
  91. package/src/components/uploader/Uploader.test.tsx +9 -3
  92. package/src/components/uploader/Uploader.tsx +13 -2
  93. package/src/components/user-block/UserBlock.test.tsx +9 -3
  94. package/src/components/user-block/UserBlock.tsx +3 -2
  95. package/src/index.ts +1 -0
  96. package/src/testing/utils/ThemeSentinel.tsx +11 -0
  97. package/src/testing/utils/commonTestsSuiteRTL.tsx +190 -0
  98. package/src/utils/theme/ThemeContext.ts +16 -0
  99. package/src/utils/theme/invertTheme.ts +4 -0
  100. package/src/testing/utils/commonTestsSuiteRTL.ts +0 -64
  101. package/src/utils/ThemeContext.ts +0 -4
@@ -3,6 +3,7 @@ import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
3
3
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
4
4
  import classNames from 'classnames';
5
5
  import React, { forwardRef, ReactNode } from 'react';
6
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
6
7
 
7
8
  /**
8
9
  * Defines the props of the component.
@@ -29,9 +30,7 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
29
30
  /**
30
31
  * Component default props.
31
32
  */
32
- const DEFAULT_PROPS: Partial<InputLabelProps> = {
33
- theme: Theme.light,
34
- };
33
+ const DEFAULT_PROPS: Partial<InputLabelProps> = {};
35
34
 
36
35
  /**
37
36
  * InputLabel component.
@@ -41,7 +40,8 @@ const DEFAULT_PROPS: Partial<InputLabelProps> = {
41
40
  * @return React element.
42
41
  */
43
42
  export const InputLabel: Comp<InputLabelProps, HTMLLabelElement> = forwardRef((props, ref) => {
44
- const { children, className, htmlFor, isRequired, theme, ...forwardedProps } = props;
43
+ const defaultTheme = useTheme() || Theme.light;
44
+ const { children, className, htmlFor, isRequired, theme = defaultTheme, ...forwardedProps } = props;
45
45
 
46
46
  return (
47
47
  <label
@@ -1,18 +1,24 @@
1
1
  import React from 'react';
2
2
 
3
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
4
4
  import { queryByClassName } from '@lumx/react/testing/utils/queries';
5
- import { render } from '@testing-library/react';
5
+ import { render, screen } from '@testing-library/react';
6
+ import { ThemeSentinel } from '@lumx/react/testing/utils/ThemeSentinel';
6
7
 
7
8
  import { Lightbox, LightboxProps } from './Lightbox';
8
9
 
9
10
  const CLASSNAME = Lightbox.className as string;
10
11
 
11
- const setup = (props: Partial<LightboxProps> = {}) => {
12
- const propsOverride = { isOpen: true, ...props } as any;
13
- const { container } = render(<Lightbox {...propsOverride} />);
12
+ const setup = (props: Partial<LightboxProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
13
+ const propsOverride = {
14
+ isOpen: true,
15
+ children: <ThemeSentinel />,
16
+ ...props,
17
+ } as any;
18
+ const { container } = render(<Lightbox {...propsOverride} />, { wrapper });
14
19
  const lightbox = queryByClassName(document.body, CLASSNAME);
15
- return { props, container, lightbox };
20
+ const themeSentinel = screen.queryByTestId(ThemeSentinel.testId);
21
+ return { props, container, lightbox, themeSentinel };
16
22
  };
17
23
 
18
24
  describe(`<${Lightbox.displayName}>`, () => {
@@ -22,5 +28,10 @@ describe(`<${Lightbox.displayName}>`, () => {
22
28
  forwardClassName: 'lightbox',
23
29
  forwardAttributes: 'lightbox',
24
30
  forwardRef: 'lightbox',
31
+ applyTheme: {
32
+ affects: [{ not: { element: 'themeSentinel' } }],
33
+ viaProp: true,
34
+ viaContext: true,
35
+ },
25
36
  });
26
37
  });
@@ -15,6 +15,7 @@ import { ClickAwayProvider } from '@lumx/react/utils/ClickAwayProvider';
15
15
  import { mergeRefs } from '@lumx/react/utils/mergeRefs';
16
16
  import { useCallbackOnEscape } from '@lumx/react/hooks/useCallbackOnEscape';
17
17
  import { useTransitionVisibility } from '@lumx/react/hooks/useTransitionVisibility';
18
+ import { ThemeProvider } from '@lumx/react/utils/theme/ThemeContext';
18
19
 
19
20
  /**
20
21
  * Defines the props of the component.
@@ -158,11 +159,13 @@ export const Lightbox: Comp<LightboxProps, HTMLDivElement> = forwardRef((props,
158
159
  />
159
160
  </div>
160
161
  )}
161
- <ClickAwayProvider callback={!preventAutoClose && onClose} childrenRefs={clickAwayRefs}>
162
- <div ref={childrenRef} className={`${CLASSNAME}__wrapper`} role="presentation">
163
- {children}
164
- </div>
165
- </ClickAwayProvider>
162
+ <ThemeProvider value={undefined}>
163
+ <ClickAwayProvider callback={!preventAutoClose && onClose} childrenRefs={clickAwayRefs}>
164
+ <div ref={childrenRef} className={`${CLASSNAME}__wrapper`} role="presentation">
165
+ {children}
166
+ </div>
167
+ </ClickAwayProvider>
168
+ </ThemeProvider>
166
169
  </div>,
167
170
  document.body,
168
171
  );
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
4
4
  import { Thumbnail } from '@lumx/react';
5
5
  import { render, screen, within } from '@testing-library/react';
6
6
  import { getByClassName, queryByClassName, queryAllByClassName } from '@lumx/react/testing/utils/queries';
@@ -15,10 +15,10 @@ type SetupProps = Partial<LinkPreviewProps>;
15
15
  /**
16
16
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
17
17
  */
18
- const setup = (propsOverride: SetupProps = {}) => {
18
+ const setup = (propsOverride: SetupProps = {}, { wrapper }: SetupRenderOptions = {}) => {
19
19
  const props: any = { ...propsOverride };
20
20
 
21
- render(<LinkPreview {...props} />);
21
+ render(<LinkPreview {...props} />, { wrapper });
22
22
  const linkPreview = getByClassName(document.body, CLASSNAME);
23
23
  const thumbnail = queryByClassName(linkPreview, Thumbnail.className as string);
24
24
  const title = queryByClassName(linkPreview, `${CLASSNAME}__title`);
@@ -97,5 +97,11 @@ describe(`<${LinkPreview.displayName}>`, () => {
97
97
  forwardClassName: 'linkPreview',
98
98
  forwardAttributes: 'linkPreview',
99
99
  forwardRef: 'linkPreview',
100
+ applyTheme: {
101
+ affects: [{ element: 'linkPreview' }],
102
+ viaProp: true,
103
+ viaContext: true,
104
+ defaultTheme: 'light',
105
+ },
100
106
  });
101
107
  });
@@ -16,6 +16,7 @@ import {
16
16
 
17
17
  import { Comp, GenericProps, HeadingElement, HasTheme } from '@lumx/react/utils/type';
18
18
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
19
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
19
20
 
20
21
  /**
21
22
  * Defines the props of the component.
@@ -54,7 +55,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
54
55
  */
55
56
  const DEFAULT_PROPS = {
56
57
  size: Size.regular,
57
- theme: Theme.light,
58
58
  titleHeading: 'h2',
59
59
  } as const;
60
60
 
@@ -66,6 +66,7 @@ const DEFAULT_PROPS = {
66
66
  * @return React element.
67
67
  */
68
68
  export const LinkPreview: Comp<LinkPreviewProps, HTMLDivElement> = forwardRef((props, ref) => {
69
+ const defaultTheme = useTheme() || Theme.light;
69
70
  const {
70
71
  className,
71
72
  description,
@@ -73,7 +74,7 @@ export const LinkPreview: Comp<LinkPreviewProps, HTMLDivElement> = forwardRef((p
73
74
  linkAs,
74
75
  linkProps,
75
76
  size,
76
- theme,
77
+ theme = defaultTheme,
77
78
  thumbnailProps,
78
79
  title,
79
80
  titleHeading,
@@ -4,14 +4,14 @@ import { Mosaic, MosaicProps } from '@lumx/react/components/mosaic/Mosaic';
4
4
  import { render, screen, within } from '@testing-library/react';
5
5
  import { getByClassName, queryAllByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
6
6
  import { Thumbnail } from '@lumx/react';
7
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
7
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
8
8
  import range from 'lodash/range';
9
9
  import userEvent from '@testing-library/user-event';
10
10
 
11
11
  const CLASSNAME = Mosaic.className as string;
12
12
 
13
- const setup = (props: Partial<MosaicProps> = {}) => {
14
- render(<Mosaic thumbnails={[]} {...props} />);
13
+ const setup = (props: Partial<MosaicProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
14
+ render(<Mosaic thumbnails={[]} {...props} />, { wrapper });
15
15
  const mosaic = getByClassName(document.body, CLASSNAME);
16
16
  const thumbnails = queryAllByClassName(mosaic, Thumbnail.className as string);
17
17
  const overlay = queryByClassName(mosaic, `${CLASSNAME}__overlay`);
@@ -69,5 +69,11 @@ describe(`<${Mosaic.displayName}>`, () => {
69
69
  forwardClassName: 'mosaic',
70
70
  forwardAttributes: 'mosaic',
71
71
  forwardRef: 'mosaic',
72
+ applyTheme: {
73
+ affects: [{ element: 'mosaic' }, { element: 'thumbnails' }],
74
+ viaProp: true,
75
+ viaContext: true,
76
+ defaultTheme: 'light',
77
+ },
72
78
  });
73
79
  });
@@ -5,6 +5,7 @@ import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
5
5
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
6
6
  import classNames from 'classnames';
7
7
  import take from 'lodash/take';
8
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
8
9
 
9
10
  /**
10
11
  * Defines the props of the component.
@@ -29,9 +30,7 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
29
30
  /**
30
31
  * Component default props.
31
32
  */
32
- const DEFAULT_PROPS: Partial<MosaicProps> = {
33
- theme: Theme.light,
34
- };
33
+ const DEFAULT_PROPS: Partial<MosaicProps> = {};
35
34
 
36
35
  /**
37
36
  * Mosaic component.
@@ -41,7 +40,8 @@ const DEFAULT_PROPS: Partial<MosaicProps> = {
41
40
  * @return React element.
42
41
  */
43
42
  export const Mosaic: Comp<MosaicProps, HTMLDivElement> = forwardRef((props, ref) => {
44
- const { className, theme, thumbnails, onImageClick, ...forwardedProps } = props;
43
+ const defaultTheme = useTheme() || Theme.light;
44
+ const { className, theme = defaultTheme, thumbnails, onImageClick, ...forwardedProps } = props;
45
45
  const handleImageClick = useMemo(() => {
46
46
  if (!onImageClick) return undefined;
47
47
 
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
 
3
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
4
4
  import { render } from '@testing-library/react';
5
- import { getByClassName } from '@lumx/react/testing/utils/queries';
5
+ import { getAllByClassName, getByClassName } from '@lumx/react/testing/utils/queries';
6
6
  import { Navigation, NavigationProps } from '.';
7
7
  import { Orientation } from '..';
8
8
 
@@ -14,7 +14,7 @@ type SetupProps = Partial<NavigationProps>;
14
14
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
15
15
  */
16
16
 
17
- const setup = (propsOverride: SetupProps = {}) => {
17
+ const setup = (propsOverride: SetupProps = {}, { wrapper }: SetupRenderOptions = {}) => {
18
18
  const props = { 'aria-label': 'navigation', ...propsOverride } as any;
19
19
  const { container } = render(
20
20
  <Navigation {...props}>
@@ -22,13 +22,12 @@ const setup = (propsOverride: SetupProps = {}) => {
22
22
  <Navigation.Item label="A link" as="button" />
23
23
  <Navigation.Item label="A link" href="" />
24
24
  </Navigation>,
25
+ { wrapper },
25
26
  );
26
27
 
27
- return {
28
- container,
29
- element: getByClassName(container, CLASSNAME),
30
- props,
31
- };
28
+ const element = getByClassName(container, CLASSNAME);
29
+ const items = getAllByClassName(element, Navigation.Item.className as string);
30
+ return { container, element, items, props };
32
31
  };
33
32
 
34
33
  describe(`<${Navigation.displayName}>`, () => {
@@ -54,5 +53,15 @@ describe(`<${Navigation.displayName}>`, () => {
54
53
  });
55
54
 
56
55
  // Common tests suite.
57
- commonTestsSuiteRTL(setup, { baseClassName: CLASSNAME, forwardClassName: 'element', forwardAttributes: 'element' });
56
+ commonTestsSuiteRTL(setup, {
57
+ baseClassName: CLASSNAME,
58
+ forwardClassName: 'element',
59
+ forwardAttributes: 'element',
60
+ applyTheme: {
61
+ affects: [{ element: 'element' }, { element: 'items' }],
62
+ viaProp: true,
63
+ viaContext: true,
64
+ defaultTheme: 'light',
65
+ },
66
+ });
58
67
  });
@@ -3,7 +3,7 @@ import classNames from 'classnames';
3
3
  import { HasAriaLabelOrLabelledBy, HasClassName, HasTheme } from '@lumx/react/utils/type';
4
4
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
5
5
  import { Orientation, Theme } from '@lumx/react';
6
- import { ThemeContext } from '@lumx/react/utils/ThemeContext';
6
+ import { ThemeProvider, useTheme } from '@lumx/react/utils/theme/ThemeContext';
7
7
  import { NavigationSection } from './NavigationSection';
8
8
  import { NavigationItem } from './NavigationItem';
9
9
  import { NavigationContext } from './context';
@@ -26,12 +26,20 @@ const COMPONENT_NAME = 'Navigation';
26
26
  */
27
27
  const CLASSNAME = getRootClassName(COMPONENT_NAME);
28
28
 
29
+ /**
30
+ * Component default props
31
+ */
32
+ const DEFAULT_PROPS = {
33
+ orientation: Orientation.vertical,
34
+ };
35
+
29
36
  export const Navigation = Object.assign(
30
37
  // eslint-disable-next-line react/display-name
31
38
  forwardRef<HTMLElement, NavigationProps>((props, ref) => {
32
- const { children, className, theme, orientation, ...forwardedProps } = props;
39
+ const defaultTheme = useTheme() || Theme.light;
40
+ const { children, className, theme = defaultTheme, orientation, ...forwardedProps } = props;
33
41
  return (
34
- <ThemeContext.Provider value={theme}>
42
+ <ThemeProvider value={theme}>
35
43
  <nav
36
44
  className={classNames(
37
45
  className,
@@ -48,13 +56,13 @@ export const Navigation = Object.assign(
48
56
  <ul className={`${CLASSNAME}__list`}>{children}</ul>
49
57
  </NavigationContext.Provider>
50
58
  </nav>
51
- </ThemeContext.Provider>
59
+ </ThemeProvider>
52
60
  );
53
61
  }),
54
62
  {
55
63
  displayName: COMPONENT_NAME,
56
64
  className: CLASSNAME,
57
- defaultProps: { theme: Theme.light, orientation: Orientation.vertical },
65
+ defaultProps: DEFAULT_PROPS,
58
66
  // Sub components
59
67
  Section: NavigationSection,
60
68
  Item: NavigationItem,
@@ -1,10 +1,10 @@
1
- import React, { ElementType, ReactNode, useContext } from 'react';
1
+ import React, { ElementType, ReactNode } from 'react';
2
2
  import { Icon, Placement, Size, Tooltip, Text } from '@lumx/react';
3
3
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
4
4
  import { ComponentRef, HasClassName, HasPolymorphicAs, HasTheme } from '@lumx/react/utils/type';
5
5
  import classNames from 'classnames';
6
6
  import { forwardRefPolymorphic } from '@lumx/react/utils/forwardRefPolymorphic';
7
- import { ThemeContext } from '@lumx/react/utils/ThemeContext';
7
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
8
8
  import { useOverflowTooltipLabel } from '@lumx/react/hooks/useOverflowTooltipLabel';
9
9
 
10
10
  type BaseNavigationItemProps = {
@@ -41,7 +41,7 @@ export const CLASSNAME = getRootClassName(COMPONENT_NAME);
41
41
  export const NavigationItem = Object.assign(
42
42
  forwardRefPolymorphic(<E extends ElementType = 'a'>(props: NavigationItemProps<E>, ref: ComponentRef<E>) => {
43
43
  const { className, icon, label, isCurrentPage, as: Element = 'a', ...forwardedProps } = props;
44
- const theme = useContext(ThemeContext);
44
+ const theme = useTheme();
45
45
  const { tooltipLabel, labelRef } = useOverflowTooltipLabel();
46
46
 
47
47
  const buttonProps = Element === 'button' ? { type: 'button' } : {};
@@ -5,7 +5,7 @@ import { Icon, Size, Text, Orientation, Popover, Placement, Theme } from '@lumx/
5
5
  import classNames from 'classnames';
6
6
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
7
  import { HasClassName } from '@lumx/react/utils/type';
8
- import { ThemeContext } from '@lumx/react/utils/ThemeContext';
8
+ import { ThemeProvider, useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
9
  import { useId } from '@lumx/react/hooks/useId';
10
10
 
11
11
  import { CLASSNAME as ITEM_CLASSNAME } from './NavigationItem';
@@ -37,7 +37,7 @@ export const NavigationSection = Object.assign(
37
37
  const buttonRef = useRef<HTMLButtonElement>(null);
38
38
  const sectionId = useId();
39
39
  const { orientation } = useContext(NavigationContext) || {};
40
- const theme = useContext(ThemeContext);
40
+ const theme = useTheme();
41
41
  const isDropdown = orientation === Orientation.horizontal;
42
42
  return (
43
43
  <li
@@ -87,13 +87,13 @@ export const NavigationSection = Object.assign(
87
87
  onClose={() => setIsOpen(false)}
88
88
  zIndex={996}
89
89
  >
90
- <ThemeContext.Provider value={Theme.light}>
90
+ <ThemeProvider value={Theme.light}>
91
91
  <ul className={`${CLASSNAME}__drawer--popover`} id={sectionId}>
92
92
  <NavigationContext.Provider value={{ orientation: Orientation.vertical }}>
93
93
  {children}
94
94
  </NavigationContext.Provider>
95
95
  </ul>
96
- </ThemeContext.Provider>
96
+ </ThemeProvider>
97
97
  </Popover>
98
98
  ) : (
99
99
  <ul className={`${CLASSNAME}__drawer`} id={sectionId}>
@@ -14,6 +14,7 @@ import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/classNam
14
14
 
15
15
  import { useTransitionVisibility } from '@lumx/react/hooks/useTransitionVisibility';
16
16
  import { mergeRefs } from '@lumx/react/utils/mergeRefs';
17
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
17
18
 
18
19
  /**
19
20
  * Defines the props of the component.
@@ -51,7 +52,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
51
52
  * Component default props.
52
53
  */
53
54
  const DEFAULT_PROPS: Partial<NotificationProps> = {
54
- theme: Theme.light,
55
55
  zIndex: 9999,
56
56
  usePortal: true,
57
57
  };
@@ -65,6 +65,7 @@ const DEFAULT_PROPS: Partial<NotificationProps> = {
65
65
  * @return React element.
66
66
  */
67
67
  export const Notification: Comp<NotificationProps, HTMLDivElement> = forwardRef((props, ref) => {
68
+ const defaultTheme = useTheme() || Theme.light;
68
69
  const {
69
70
  actionLabel,
70
71
  className,
@@ -72,7 +73,7 @@ export const Notification: Comp<NotificationProps, HTMLDivElement> = forwardRef(
72
73
  isOpen,
73
74
  onActionClick,
74
75
  onClick,
75
- theme,
76
+ theme = defaultTheme,
76
77
  type,
77
78
  zIndex,
78
79
  usePortal,
@@ -1,18 +1,27 @@
1
1
  import React from 'react';
2
2
 
3
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
4
4
  import { render, screen } from '@testing-library/react';
5
+ import { ThemeSentinel } from '@lumx/react/testing/utils/ThemeSentinel';
5
6
  import { Popover, PopoverProps } from './Popover';
6
7
 
7
8
  const CLASSNAME = Popover.className as string;
8
9
 
9
- const setup = (props: Partial<PopoverProps> = {}) => {
10
+ const setup = (props: Partial<PopoverProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
10
11
  const { container } = render(
11
12
  <Popover isOpen anchorRef={{ current: null }} usePortal={false} {...props} data-testid="popover">
12
- {props.children || 'Popover content'}
13
+ {props.children || (
14
+ <>
15
+ Popover content
16
+ <ThemeSentinel />
17
+ </>
18
+ )}
13
19
  </Popover>,
20
+ { wrapper },
14
21
  );
15
- return { props, container, element: screen.getByTestId('popover') };
22
+ const element = screen.getByTestId('popover');
23
+ const themeSentinel = screen.getByTestId(ThemeSentinel.testId);
24
+ return { props, container, element, themeSentinel };
16
25
  };
17
26
 
18
27
  describe(`<${Popover.displayName}>`, () => {
@@ -41,5 +50,10 @@ describe(`<${Popover.displayName}>`, () => {
41
50
  baseClassName: CLASSNAME,
42
51
  forwardClassName: 'element',
43
52
  forwardAttributes: 'element',
53
+ applyTheme: {
54
+ affects: [{ element: 'element' }, { not: { element: 'themeSentinel' } }],
55
+ viaProp: true,
56
+ viaContext: false,
57
+ },
44
58
  });
45
59
  });
@@ -13,6 +13,7 @@ import { useMergeRefs } from '@lumx/react/utils/mergeRefs';
13
13
  import { useFocusTrap } from '@lumx/react/hooks/useFocusTrap';
14
14
  import { skipRender } from '@lumx/react/utils/skipRender';
15
15
 
16
+ import { ThemeProvider } from '@lumx/react/utils/theme/ThemeContext';
16
17
  import { useRestoreFocusOnClose } from './useRestoreFocusOnClose';
17
18
  import { usePopoverStyle } from './usePopoverStyle';
18
19
  import { Elevation, FitAnchorWidth, Offset, Placement, POPOVER_ZINDEX } from './constants';
@@ -179,7 +180,7 @@ const _InnerPopover: Comp<PopoverProps, HTMLDivElement> = forwardRef((props, ref
179
180
  </svg>
180
181
  </div>
181
182
  )}
182
- {children}
183
+ <ThemeProvider value={undefined}>{children}</ThemeProvider>
183
184
  </ClickAwayProvider>
184
185
  </Component>,
185
186
  usePortal,
@@ -1,14 +1,14 @@
1
1
  import React from 'react';
2
2
 
3
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
4
4
  import { render } from '@testing-library/react';
5
5
  import { queryByClassName } from '@lumx/react/testing/utils/queries';
6
6
  import { PostBlock, PostBlockProps } from './PostBlock';
7
7
 
8
8
  const CLASSNAME = PostBlock.className as string;
9
9
 
10
- const setup = (props: Partial<PostBlockProps> = {}) => {
11
- render(<PostBlock {...(props as any)} />);
10
+ const setup = (props: Partial<PostBlockProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
11
+ render(<PostBlock {...(props as any)} />, { wrapper });
12
12
  const postBlock = queryByClassName(document.body, CLASSNAME);
13
13
  return { props, postBlock };
14
14
  };
@@ -19,5 +19,11 @@ describe(`<${PostBlock.displayName}>`, () => {
19
19
  baseClassName: CLASSNAME,
20
20
  forwardClassName: 'postBlock',
21
21
  forwardAttributes: 'postBlock',
22
+ applyTheme: {
23
+ affects: [{ element: 'postBlock' }],
24
+ viaProp: true,
25
+ viaContext: true,
26
+ defaultTheme: 'light',
27
+ },
22
28
  });
23
29
  });
@@ -8,6 +8,7 @@ import { Orientation, Theme, Thumbnail, ThumbnailProps, ThumbnailVariant } from
8
8
 
9
9
  import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
10
10
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
11
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
11
12
 
12
13
  /**
13
14
  * Defines the props of the component.
@@ -50,7 +51,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
50
51
  */
51
52
  const DEFAULT_PROPS: Partial<PostBlockProps> = {
52
53
  orientation: Orientation.horizontal,
53
- theme: Theme.light,
54
54
  };
55
55
 
56
56
  /**
@@ -61,6 +61,7 @@ const DEFAULT_PROPS: Partial<PostBlockProps> = {
61
61
  * @return React element.
62
62
  */
63
63
  export const PostBlock: Comp<PostBlockProps, HTMLDivElement> = forwardRef((props, ref) => {
64
+ const defaultTheme = useTheme() || Theme.light;
64
65
  const {
65
66
  actions,
66
67
  attachments,
@@ -71,7 +72,7 @@ export const PostBlock: Comp<PostBlockProps, HTMLDivElement> = forwardRef((props
71
72
  orientation,
72
73
  tags,
73
74
  text,
74
- theme,
75
+ theme = defaultTheme,
75
76
  thumbnailProps,
76
77
  title,
77
78
  ...forwardedProps
@@ -6,6 +6,7 @@ import { Theme } from '@lumx/react';
6
6
 
7
7
  import { Comp, GenericProps, HasTheme, ValueOf } from '@lumx/react/utils/type';
8
8
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
10
  import { ProgressLinear } from './ProgressLinear';
10
11
  import { ProgressCircular } from './ProgressCircular';
11
12
 
@@ -37,7 +38,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
37
38
  * Component default props.
38
39
  */
39
40
  const DEFAULT_PROPS: Partial<ProgressProps> = {
40
- theme: Theme.light,
41
41
  variant: ProgressVariant.circular,
42
42
  };
43
43
 
@@ -50,7 +50,8 @@ const DEFAULT_PROPS: Partial<ProgressProps> = {
50
50
  * @return React element.
51
51
  */
52
52
  export const Progress: Comp<ProgressProps, HTMLDivElement> = forwardRef((props, ref) => {
53
- const { className, theme, variant, ...forwardedProps } = props;
53
+ const defaultTheme = useTheme() || Theme.light;
54
+ const { className, theme = defaultTheme, variant, ...forwardedProps } = props;
54
55
 
55
56
  return (
56
57
  <div
@@ -1,9 +1,8 @@
1
1
  import React from 'react';
2
2
 
3
3
  import { getByClassName } from '@lumx/react/testing/utils/queries';
4
- import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
4
+ import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
5
5
  import { render } from '@testing-library/react';
6
- import { Theme } from '@lumx/react';
7
6
 
8
7
  import { ProgressCircular, ProgressCircularProps } from './ProgressCircular';
9
8
 
@@ -12,8 +11,8 @@ const CLASSNAME = ProgressCircular.className as string;
12
11
  /**
13
12
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
14
13
  */
15
- const setup = (props: Partial<ProgressCircularProps> = {}) => {
16
- const { container } = render(<ProgressCircular {...(props as any)} />);
14
+ const setup = (props: Partial<ProgressCircularProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
15
+ const { container } = render(<ProgressCircular {...(props as any)} />, { wrapper });
17
16
  const element = getByClassName(container, CLASSNAME);
18
17
  return { container, element, props };
19
18
  };
@@ -21,23 +20,11 @@ const setup = (props: Partial<ProgressCircularProps> = {}) => {
21
20
  describe(`<${ProgressCircular.displayName}>`, () => {
22
21
  it('should render default', () => {
23
22
  const { element } = setup();
24
- expect(element).toBeInTheDocument();
25
- expect(element).toHaveClass(CLASSNAME);
26
- expect(element).toHaveClass(`${CLASSNAME}--theme-light`);
27
23
  expect(element).toHaveClass(`${CLASSNAME}--size-m`);
28
24
  });
29
25
 
30
- it('should render dark theme', () => {
31
- const { element } = setup({ theme: Theme.dark });
32
- expect(element).toBeInTheDocument();
33
- expect(element).toHaveClass(CLASSNAME);
34
- expect(element).toHaveClass(`${CLASSNAME}--theme-dark`);
35
- });
36
-
37
26
  it('should render size xs', () => {
38
27
  const { element } = setup({ size: 'xs' });
39
- expect(element).toBeInTheDocument();
40
- expect(element).toHaveClass(CLASSNAME);
41
28
  expect(element).toHaveClass(`${CLASSNAME}--size-xs`);
42
29
  });
43
30
 
@@ -45,5 +32,11 @@ describe(`<${ProgressCircular.displayName}>`, () => {
45
32
  baseClassName: CLASSNAME,
46
33
  forwardClassName: 'element',
47
34
  forwardAttributes: 'element',
35
+ applyTheme: {
36
+ affects: [{ element: 'element' }],
37
+ viaProp: true,
38
+ viaContext: true,
39
+ defaultTheme: 'light',
40
+ },
48
41
  });
49
42
  });
@@ -6,6 +6,7 @@ import { Theme, Size } from '@lumx/react';
6
6
 
7
7
  import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
8
8
  import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
10
 
10
11
  /**
11
12
  * Progress sizes.
@@ -34,7 +35,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
34
35
  * Component default props.
35
36
  */
36
37
  const DEFAULT_PROPS: Partial<ProgressCircularProps> = {
37
- theme: Theme.light,
38
38
  size: Size.m,
39
39
  };
40
40
 
@@ -46,7 +46,8 @@ const DEFAULT_PROPS: Partial<ProgressCircularProps> = {
46
46
  * @return React element.
47
47
  */
48
48
  export const ProgressCircular: Comp<ProgressCircularProps, HTMLDivElement> = forwardRef((props, ref) => {
49
- const { className, theme, size, ...forwardedProps } = props;
49
+ const defaultTheme = useTheme() || Theme.light;
50
+ const { className, theme = defaultTheme, size, ...forwardedProps } = props;
50
51
 
51
52
  return (
52
53
  <div