@lumx/react 3.10.0 → 3.10.1-alpha.1
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/_internal/index.d.ts +1 -1
- package/index.d.ts +24 -16
- package/index.js +313 -293
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/alert-dialog/AlertDialog.tsx +3 -4
- package/src/components/autocomplete/Autocomplete.test.tsx +9 -2
- package/src/components/autocomplete/Autocomplete.tsx +7 -4
- package/src/components/autocomplete/AutocompleteMultiple.test.tsx +9 -2
- package/src/components/autocomplete/AutocompleteMultiple.tsx +10 -7
- package/src/components/avatar/Avatar.test.tsx +14 -4
- package/src/components/avatar/Avatar.tsx +7 -5
- package/src/components/badge/Badge.tsx +7 -4
- package/src/components/badge/BadgeWrapper.tsx +7 -4
- package/src/components/button/Button.test.tsx +9 -3
- package/src/components/button/Button.tsx +8 -5
- package/src/components/button/ButtonGroup.tsx +4 -3
- package/src/components/button/ButtonRoot.tsx +4 -3
- package/src/components/button/IconButton.test.tsx +9 -3
- package/src/components/button/IconButton.tsx +16 -5
- package/src/components/checkbox/Checkbox.test.tsx +9 -3
- package/src/components/checkbox/Checkbox.tsx +8 -7
- package/src/components/chip/Chip.test.tsx +14 -4
- package/src/components/chip/Chip.tsx +11 -11
- package/src/components/chip/ChipGroup.tsx +5 -4
- package/src/components/comment-block/CommentBlock.test.tsx +9 -3
- package/src/components/comment-block/CommentBlock.tsx +7 -6
- package/src/components/date-picker/DatePicker.tsx +5 -3
- package/src/components/date-picker/DatePickerControlled.tsx +6 -3
- package/src/components/date-picker/DatePickerField.test.tsx +9 -3
- package/src/components/date-picker/DatePickerField.tsx +4 -3
- package/src/components/dialog/Dialog.test.tsx +17 -4
- package/src/components/dialog/Dialog.tsx +65 -61
- package/src/components/divider/Divider.test.tsx +9 -3
- package/src/components/divider/Divider.tsx +8 -7
- package/src/components/drag-handle/DragHandle.test.tsx +38 -0
- package/src/components/drag-handle/DragHandle.tsx +7 -4
- package/src/components/dropdown/Dropdown.tsx +4 -3
- package/src/components/expansion-panel/ExpansionPanel.test.tsx +12 -3
- package/src/components/expansion-panel/ExpansionPanel.tsx +8 -7
- package/src/components/flag/Flag.test.tsx +14 -4
- package/src/components/flag/Flag.tsx +9 -7
- package/src/components/flex-box/FlexBox.tsx +8 -5
- package/src/components/generic-block/GenericBlock.tsx +4 -1
- package/src/components/grid/Grid.tsx +4 -3
- package/src/components/grid/GridItem.tsx +4 -3
- package/src/components/grid-column/GridColumn.tsx +5 -5
- package/src/components/heading/Heading.tsx +8 -4
- package/src/components/icon/Icon.test.tsx +13 -4
- package/src/components/icon/Icon.tsx +18 -5
- package/src/components/image-block/ImageBlock.test.tsx +12 -4
- package/src/components/image-block/ImageBlock.tsx +7 -5
- package/src/components/image-lightbox/ImageLightbox.tsx +4 -3
- package/src/components/inline-list/InlineList.tsx +4 -3
- package/src/components/input-helper/InputHelper.test.tsx +14 -4
- package/src/components/input-helper/InputHelper.tsx +10 -6
- package/src/components/input-label/InputLabel.test.tsx +14 -4
- package/src/components/input-label/InputLabel.tsx +11 -8
- package/src/components/lightbox/Lightbox.test.tsx +17 -6
- package/src/components/lightbox/Lightbox.tsx +12 -8
- package/src/components/link/Link.tsx +4 -3
- package/src/components/link-preview/LinkPreview.test.tsx +9 -3
- package/src/components/link-preview/LinkPreview.tsx +7 -5
- package/src/components/list/List.tsx +7 -5
- package/src/components/list/ListDivider.tsx +4 -3
- package/src/components/list/ListItem.tsx +4 -3
- package/src/components/list/ListSubheader.tsx +4 -3
- package/src/components/message/Message.tsx +7 -4
- package/src/components/mosaic/Mosaic.test.tsx +9 -3
- package/src/components/mosaic/Mosaic.tsx +11 -9
- package/src/components/navigation/Navigation.test.tsx +18 -9
- package/src/components/navigation/Navigation.tsx +13 -5
- package/src/components/navigation/NavigationItem.tsx +4 -4
- package/src/components/navigation/NavigationSection.test.tsx +19 -6
- package/src/components/navigation/NavigationSection.tsx +4 -4
- package/src/components/notification/Notification.tsx +7 -8
- package/src/components/popover/Popover.test.tsx +18 -4
- package/src/components/popover/Popover.tsx +5 -3
- package/src/components/popover-dialog/PopoverDialog.tsx +5 -3
- package/src/components/post-block/PostBlock.test.tsx +9 -3
- package/src/components/post-block/PostBlock.tsx +7 -8
- package/src/components/progress/Progress.tsx +8 -6
- package/src/components/progress/ProgressCircular.test.tsx +9 -16
- package/src/components/progress/ProgressCircular.tsx +7 -6
- package/src/components/progress/ProgressLinear.test.tsx +13 -18
- package/src/components/progress/ProgressLinear.tsx +8 -8
- package/src/components/progress-tracker/ProgressTracker.tsx +5 -3
- package/src/components/progress-tracker/ProgressTrackerStep.tsx +5 -5
- package/src/components/progress-tracker/ProgressTrackerStepPanel.tsx +24 -24
- package/src/components/radio-button/RadioButton.test.tsx +9 -3
- package/src/components/radio-button/RadioButton.tsx +8 -8
- package/src/components/radio-button/RadioGroup.tsx +4 -3
- package/src/components/select/Select.test.tsx +9 -3
- package/src/components/select/Select.tsx +30 -28
- package/src/components/select/SelectMultiple.test.tsx +9 -3
- package/src/components/select/SelectMultiple.tsx +112 -108
- package/src/components/select/WithSelectContext.tsx +8 -6
- package/src/components/side-navigation/SideNavigation.tsx +7 -5
- package/src/components/side-navigation/SideNavigationItem.tsx +4 -5
- package/src/components/skeleton/SkeletonCircle.test.tsx +9 -3
- package/src/components/skeleton/SkeletonCircle.tsx +9 -7
- package/src/components/skeleton/SkeletonRectangle.test.tsx +9 -3
- package/src/components/skeleton/SkeletonRectangle.tsx +8 -5
- package/src/components/skeleton/SkeletonTypography.test.tsx +9 -3
- package/src/components/skeleton/SkeletonTypography.tsx +9 -7
- package/src/components/slider/Slider.test.tsx +9 -3
- package/src/components/slider/Slider.tsx +7 -7
- package/src/components/slideshow/Slides.tsx +9 -5
- package/src/components/slideshow/Slideshow.test.tsx +9 -3
- package/src/components/slideshow/Slideshow.tsx +8 -5
- package/src/components/slideshow/SlideshowControls.tsx +7 -5
- package/src/components/slideshow/SlideshowItem.tsx +4 -3
- package/src/components/slideshow/SlideshowItemGroup.tsx +5 -4
- package/src/components/switch/Switch.test.tsx +9 -3
- package/src/components/switch/Switch.tsx +7 -7
- package/src/components/table/Table.test.tsx +9 -3
- package/src/components/table/Table.tsx +8 -8
- package/src/components/table/TableBody.tsx +4 -3
- package/src/components/table/TableCell.tsx +5 -5
- package/src/components/table/TableHeader.tsx +4 -3
- package/src/components/table/TableRow.tsx +4 -3
- package/src/components/tabs/Tab.tsx +4 -3
- package/src/components/tabs/TabList.test.tsx +9 -3
- package/src/components/tabs/TabList.tsx +18 -6
- package/src/components/tabs/TabPanel.tsx +7 -5
- package/src/components/text/Text.tsx +6 -4
- package/src/components/text-field/TextField.test.tsx +9 -3
- package/src/components/text-field/TextField.tsx +7 -5
- package/src/components/thumbnail/Thumbnail.test.tsx +9 -3
- package/src/components/thumbnail/Thumbnail.tsx +8 -7
- package/src/components/toolbar/Toolbar.tsx +4 -3
- package/src/components/tooltip/Tooltip.tsx +4 -3
- package/src/components/uploader/Uploader.test.tsx +9 -3
- package/src/components/uploader/Uploader.tsx +18 -5
- package/src/components/user-block/UserBlock.test.tsx +9 -3
- package/src/components/user-block/UserBlock.tsx +9 -6
- package/src/index.ts +1 -0
- package/src/testing/utils/ThemeSentinel.tsx +11 -0
- package/src/testing/utils/commonTestsSuiteRTL.tsx +191 -0
- package/src/utils/react/forwardRef.ts +10 -0
- package/src/utils/react/forwardRefPolymorphic.ts +10 -0
- package/src/utils/theme/ThemeContext.ts +16 -0
- package/src/utils/theme/invertTheme.ts +4 -0
- package/src/testing/utils/commonTestsSuiteRTL.ts +0 -64
- package/src/utils/ThemeContext.ts +0 -4
- package/src/utils/forwardRefPolymorphic.ts +0 -9
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import isEmpty from 'lodash/isEmpty';
|
|
2
|
+
|
|
3
|
+
import { GenericProps } from '@lumx/react/utils/type';
|
|
4
|
+
import { queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { Theme } from '@lumx/react';
|
|
7
|
+
import { RenderOptions } from '@testing-library/react';
|
|
8
|
+
import { ThemeProvider } from '@lumx/react/utils/theme/ThemeContext';
|
|
9
|
+
import castArray from 'lodash/castArray';
|
|
10
|
+
import { invertTheme } from '@lumx/react/utils/theme/invertTheme';
|
|
11
|
+
|
|
12
|
+
interface CommonSetup {
|
|
13
|
+
props: GenericProps;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type AffectConfig<E> = { element: E; classModifier?: 'color' | 'theme'; inverted?: boolean };
|
|
17
|
+
type Not<E> = { not: E };
|
|
18
|
+
|
|
19
|
+
interface Options<S extends CommonSetup> {
|
|
20
|
+
baseClassName: string;
|
|
21
|
+
forwardClassName?: keyof S;
|
|
22
|
+
forwardAttributes?: keyof S;
|
|
23
|
+
forwardRef?: keyof S;
|
|
24
|
+
applyTheme?: {
|
|
25
|
+
/** Element(s) to which we apply the theme class */
|
|
26
|
+
affects: Array<AffectConfig<keyof S> | Not<AffectConfig<keyof S>>>;
|
|
27
|
+
/** Apply theme via theme prop */
|
|
28
|
+
viaProp: boolean;
|
|
29
|
+
/** Apply theme via theme context */
|
|
30
|
+
viaContext: boolean;
|
|
31
|
+
/** Apply a default theme if no prop or context was provided */
|
|
32
|
+
defaultTheme?: Theme;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type RenderWrapper = RenderOptions['wrapper'];
|
|
37
|
+
export type SetupRenderOptions = { wrapper?: RenderWrapper };
|
|
38
|
+
export type SetupFunction<S extends CommonSetup> = (
|
|
39
|
+
props?: GenericProps,
|
|
40
|
+
options?: SetupRenderOptions,
|
|
41
|
+
) => S | Promise<S>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Common tests on components
|
|
45
|
+
* - Check base class name and class name forwarding
|
|
46
|
+
* - Check props forwarding
|
|
47
|
+
*/
|
|
48
|
+
export function commonTestsSuiteRTL<S extends CommonSetup>(setup: SetupFunction<S>, options: Options<S>): void {
|
|
49
|
+
if (isEmpty(options)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const { baseClassName, forwardClassName, forwardAttributes, forwardRef, applyTheme } = options;
|
|
53
|
+
describe('Common tests suite', () => {
|
|
54
|
+
it('should render with base class name', async () => {
|
|
55
|
+
await setup();
|
|
56
|
+
expect(queryByClassName(document.body, baseClassName)).toBeInTheDocument();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (forwardClassName) {
|
|
60
|
+
it('should forward any CSS class', async () => {
|
|
61
|
+
const modifiedProps = {
|
|
62
|
+
className: 'component component--is-tested',
|
|
63
|
+
};
|
|
64
|
+
const wrappers = await setup(modifiedProps);
|
|
65
|
+
expect(wrappers[forwardClassName]).toHaveClass(modifiedProps.className);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (forwardAttributes) {
|
|
70
|
+
it('should forward any other prop', async () => {
|
|
71
|
+
const modifiedProps = {
|
|
72
|
+
winter: 'is coming',
|
|
73
|
+
};
|
|
74
|
+
const wrappers = await setup(modifiedProps);
|
|
75
|
+
expect(wrappers[forwardAttributes]).toHaveAttribute('winter', modifiedProps.winter);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (forwardRef) {
|
|
80
|
+
it('should forward ref', async () => {
|
|
81
|
+
const ref = React.createRef();
|
|
82
|
+
const wrappers = await setup({ ref });
|
|
83
|
+
expect(ref.current).toBe(wrappers[forwardRef]);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (applyTheme) {
|
|
88
|
+
describe('theme', () => {
|
|
89
|
+
const { affects, defaultTheme, viaProp, viaContext } = applyTheme;
|
|
90
|
+
const testElements = affects.map((configOrNot) => {
|
|
91
|
+
let shouldHaveModifier: boolean = true;
|
|
92
|
+
let config: AffectConfig<any>;
|
|
93
|
+
if ('not' in configOrNot) {
|
|
94
|
+
shouldHaveModifier = false;
|
|
95
|
+
config = configOrNot.not;
|
|
96
|
+
} else config = configOrNot;
|
|
97
|
+
|
|
98
|
+
const {
|
|
99
|
+
element,
|
|
100
|
+
classModifier = 'theme',
|
|
101
|
+
inverted = false,
|
|
102
|
+
}: AffectConfig<any> = typeof config === 'object' ? config : { element: config };
|
|
103
|
+
return {
|
|
104
|
+
element,
|
|
105
|
+
getExpectedClassModifier: (theme: Theme) =>
|
|
106
|
+
`--${classModifier}-${inverted ? invertTheme(theme) : theme}`,
|
|
107
|
+
shouldHaveModifier,
|
|
108
|
+
apply: shouldHaveModifier ? 'apply' : 'not apply',
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const expectTheme = (
|
|
113
|
+
wrappers: any,
|
|
114
|
+
{ element, getExpectedClassModifier, shouldHaveModifier }: any,
|
|
115
|
+
theme: Theme,
|
|
116
|
+
override: { shouldHaveModifier?: boolean } = {},
|
|
117
|
+
) => {
|
|
118
|
+
for (const wrapper of castArray(wrappers[element])) {
|
|
119
|
+
let expected: any = expect(wrapper.className);
|
|
120
|
+
if (override.shouldHaveModifier === false || !shouldHaveModifier) {
|
|
121
|
+
expected = expected.not;
|
|
122
|
+
}
|
|
123
|
+
expected.toContain(getExpectedClassModifier(theme));
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (defaultTheme) {
|
|
128
|
+
it.each(testElements)(
|
|
129
|
+
`should $apply default theme (${defaultTheme}) to \`$element\``,
|
|
130
|
+
async (affectedElement) => {
|
|
131
|
+
const wrappers = await setup();
|
|
132
|
+
expectTheme(wrappers, affectedElement, defaultTheme);
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Only the elements that are affected by theme
|
|
138
|
+
const affectedElements = testElements.filter((e) => e.shouldHaveModifier);
|
|
139
|
+
if (!defaultTheme && affectedElements.length) {
|
|
140
|
+
it.each(affectedElements)(
|
|
141
|
+
`should not apply default theme (${defaultTheme}) to \`$element\``,
|
|
142
|
+
async (affectedElement) => {
|
|
143
|
+
const wrappers = await setup();
|
|
144
|
+
expectTheme(wrappers, affectedElement, Theme.light, { shouldHaveModifier: false });
|
|
145
|
+
expectTheme(wrappers, affectedElement, Theme.dark, { shouldHaveModifier: false });
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (viaProp) {
|
|
151
|
+
const theme = invertTheme(defaultTheme || Theme.light);
|
|
152
|
+
it.each(testElements)(
|
|
153
|
+
`should $apply prop theme=${theme} to \`$element\``,
|
|
154
|
+
async (affectedElement) => {
|
|
155
|
+
const wrappers = await setup({ theme });
|
|
156
|
+
expectTheme(wrappers, affectedElement, theme);
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const contextTheme = invertTheme(defaultTheme || Theme.light);
|
|
162
|
+
it.each(testElements)(
|
|
163
|
+
`should $apply context theme=${contextTheme} to \`$element\``,
|
|
164
|
+
async (affectedElement) => {
|
|
165
|
+
const Wrapper = ({ children }: any) => (
|
|
166
|
+
<ThemeProvider value={contextTheme}>{children}</ThemeProvider>
|
|
167
|
+
);
|
|
168
|
+
const wrappers = await setup({}, { wrapper: Wrapper });
|
|
169
|
+
expectTheme(wrappers, affectedElement, contextTheme, {
|
|
170
|
+
shouldHaveModifier: !viaContext ? false : undefined,
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (viaProp && viaContext) {
|
|
176
|
+
const propTheme = invertTheme(contextTheme);
|
|
177
|
+
it.each(testElements)(
|
|
178
|
+
`should $apply prop theme=${propTheme} to \`$element\` overriding the context theme=${contextTheme}`,
|
|
179
|
+
async (affectedElement) => {
|
|
180
|
+
const Wrapper = ({ children }: any) => (
|
|
181
|
+
<ThemeProvider value={contextTheme}>{children}</ThemeProvider>
|
|
182
|
+
);
|
|
183
|
+
const wrappers = await setup({ theme: propTheme }, { wrapper: Wrapper });
|
|
184
|
+
expectTheme(wrappers, affectedElement, propTheme);
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React, { type ReactNode, type ForwardedRef } from 'react';
|
|
2
|
+
import type { Comp } from '../type';
|
|
3
|
+
|
|
4
|
+
type ForwardRef = <P, T = HTMLElement>(render: (props: P, ref: ForwardedRef<T>) => ReactNode) => Comp<P, T>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* React.forwardRef but re-typed to attach some custom metadata on our components.
|
|
8
|
+
*/
|
|
9
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
10
|
+
export const forwardRef = React.forwardRef as ForwardRef;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React, { type ElementType } from 'react';
|
|
2
|
+
import type { ComponentRef } from '@lumx/react/utils/type';
|
|
3
|
+
|
|
4
|
+
type ForwardRefPolymorphic = <E extends ElementType, P extends { as?: E }>(
|
|
5
|
+
render: (props: P, ref: ComponentRef<E>) => React.ReactNode,
|
|
6
|
+
) => (props: P & { ref?: ComponentRef<E> }) => React.ReactNode;
|
|
7
|
+
|
|
8
|
+
/** Same as `React.forwardRef` but inferring Ref type from the `as` prop. */
|
|
9
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
10
|
+
export const forwardRefPolymorphic = React.forwardRef as ForwardRefPolymorphic;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Theme } from '@lumx/react';
|
|
3
|
+
|
|
4
|
+
type ThemeContextValue = Theme | undefined;
|
|
5
|
+
export const ThemeContext = React.createContext<ThemeContextValue>(undefined);
|
|
6
|
+
|
|
7
|
+
/** Provide a theme context to all children. */
|
|
8
|
+
export const ThemeProvider = ThemeContext.Provider as React.FC<{
|
|
9
|
+
value: ThemeContextValue;
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
/** Get the theme in the current context. */
|
|
14
|
+
export function useTheme(): ThemeContextValue {
|
|
15
|
+
return React.useContext(ThemeContext);
|
|
16
|
+
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import isEmpty from 'lodash/isEmpty';
|
|
2
|
-
|
|
3
|
-
import { GenericProps } from '@lumx/react/utils/type';
|
|
4
|
-
import { queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
|
|
7
|
-
interface CommonSetup {
|
|
8
|
-
props: GenericProps;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface Options<S extends CommonSetup> {
|
|
12
|
-
baseClassName: string;
|
|
13
|
-
forwardClassName?: keyof S;
|
|
14
|
-
forwardAttributes?: keyof S;
|
|
15
|
-
forwardRef?: keyof S;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type SetupFunction<S extends CommonSetup> = (props?: GenericProps) => S | Promise<S>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Common tests on components
|
|
22
|
-
* - Check base class name and class name forwarding
|
|
23
|
-
* - Check props forwarding
|
|
24
|
-
*/
|
|
25
|
-
export function commonTestsSuiteRTL<S extends CommonSetup>(setup: SetupFunction<S>, options: Options<S>): void {
|
|
26
|
-
if (isEmpty(options)) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const { baseClassName, forwardClassName, forwardAttributes, forwardRef } = options;
|
|
30
|
-
describe('Common tests suite', () => {
|
|
31
|
-
it('should render with base class name', async () => {
|
|
32
|
-
await setup();
|
|
33
|
-
expect(queryByClassName(document.body, baseClassName)).toBeInTheDocument();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (forwardClassName) {
|
|
37
|
-
it('should forward any CSS class', async () => {
|
|
38
|
-
const modifiedProps = {
|
|
39
|
-
className: 'component component--is-tested',
|
|
40
|
-
};
|
|
41
|
-
const wrappers = await setup(modifiedProps);
|
|
42
|
-
expect(wrappers[forwardClassName]).toHaveClass(modifiedProps.className);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (forwardAttributes) {
|
|
47
|
-
it('should forward any other prop', async () => {
|
|
48
|
-
const modifiedProps = {
|
|
49
|
-
winter: 'is coming',
|
|
50
|
-
};
|
|
51
|
-
const wrappers = await setup(modifiedProps);
|
|
52
|
-
expect(wrappers[forwardAttributes]).toHaveAttribute('winter', modifiedProps.winter);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (forwardRef) {
|
|
57
|
-
it('should forward ref', async () => {
|
|
58
|
-
const ref = React.createRef();
|
|
59
|
-
const wrappers = await setup({ ref });
|
|
60
|
-
expect(ref.current).toBe(wrappers[forwardRef]);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React, { ElementType } from 'react';
|
|
2
|
-
import { ComponentRef } from '@lumx/react/utils/type';
|
|
3
|
-
|
|
4
|
-
/** Same as `React.forwardRef` but inferring Ref type from the `as` prop. */
|
|
5
|
-
export function forwardRefPolymorphic<E extends ElementType, P extends { as?: E }>(
|
|
6
|
-
render: (props: P, ref: ComponentRef<E>) => React.ReactElement | null,
|
|
7
|
-
): (props: P & { ref?: ComponentRef<E> }) => React.ReactElement | null {
|
|
8
|
-
return React.forwardRef(render as any) as any;
|
|
9
|
-
}
|