@lumx/react 3.19.0 → 3.19.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.
Files changed (142) hide show
  1. package/index.d.ts +201 -117
  2. package/index.js +456 -464
  3. package/index.js.map +1 -1
  4. package/package.json +3 -3
  5. package/src/components/alert-dialog/AlertDialog.tsx +1 -1
  6. package/src/components/autocomplete/Autocomplete.tsx +1 -1
  7. package/src/components/autocomplete/AutocompleteMultiple.tsx +1 -1
  8. package/src/components/avatar/Avatar.tsx +1 -1
  9. package/src/components/badge/Badge.tsx +1 -1
  10. package/src/components/badge/BadgeWrapper.tsx +1 -1
  11. package/src/components/button/Button.test.tsx +5 -5
  12. package/src/components/button/Button.tsx +1 -1
  13. package/src/components/button/ButtonGroup.tsx +1 -1
  14. package/src/components/button/ButtonRoot.tsx +7 -37
  15. package/src/components/button/IconButton.tsx +1 -1
  16. package/src/components/checkbox/Checkbox.tsx +1 -1
  17. package/src/components/chip/Chip.tsx +2 -2
  18. package/src/components/chip/ChipGroup.tsx +2 -2
  19. package/src/components/comment-block/CommentBlock.tsx +1 -1
  20. package/src/components/date-picker/DatePickerControlled.tsx +1 -1
  21. package/src/components/date-picker/constants.ts +1 -1
  22. package/src/components/dialog/Dialog.tsx +1 -1
  23. package/src/components/divider/Divider.tsx +1 -1
  24. package/src/components/drag-handle/DragHandle.tsx +1 -1
  25. package/src/components/dropdown/Dropdown.tsx +1 -1
  26. package/src/components/expansion-panel/ExpansionPanel.tsx +1 -1
  27. package/src/components/flag/Flag.tsx +1 -1
  28. package/src/components/flex-box/FlexBox.tsx +2 -3
  29. package/src/components/generic-block/GenericBlock.tsx +1 -1
  30. package/src/components/grid/Grid.tsx +1 -1
  31. package/src/components/grid/GridItem.tsx +1 -1
  32. package/src/components/grid-column/GridColumn.tsx +1 -1
  33. package/src/components/heading/Heading.tsx +1 -1
  34. package/src/components/heading/constants.ts +1 -1
  35. package/src/components/icon/Icon.tsx +1 -1
  36. package/src/components/image-block/ImageBlock.tsx +1 -1
  37. package/src/components/image-lightbox/constants.ts +1 -1
  38. package/src/components/inline-list/InlineList.tsx +1 -1
  39. package/src/components/input-helper/InputHelper.tsx +1 -1
  40. package/src/components/input-label/InputLabel.test.tsx +1 -1
  41. package/src/components/input-label/InputLabel.tsx +1 -1
  42. package/src/components/lightbox/Lightbox.tsx +1 -1
  43. package/src/components/link/Link.test.tsx +8 -6
  44. package/src/components/link/Link.tsx +10 -21
  45. package/src/components/link-preview/LinkPreview.stories.tsx +1 -1
  46. package/src/components/link-preview/LinkPreview.test.tsx +1 -1
  47. package/src/components/link-preview/LinkPreview.tsx +1 -1
  48. package/src/components/list/List.tsx +1 -1
  49. package/src/components/list/ListDivider.tsx +1 -1
  50. package/src/components/list/ListItem.test.tsx +1 -3
  51. package/src/components/list/ListItem.tsx +20 -33
  52. package/src/components/list/ListSubheader.tsx +1 -1
  53. package/src/components/message/Message.tsx +1 -1
  54. package/src/components/mosaic/Mosaic.tsx +1 -1
  55. package/src/components/navigation/Navigation.test.tsx +1 -1
  56. package/src/components/navigation/Navigation.tsx +1 -1
  57. package/src/components/navigation/NavigationItem.tsx +7 -11
  58. package/src/components/navigation/NavigationSection.test.tsx +2 -1
  59. package/src/components/navigation/NavigationSection.tsx +5 -4
  60. package/src/components/navigation/context.tsx +2 -1
  61. package/src/components/notification/Notification.tsx +1 -1
  62. package/src/components/popover/Popover.tsx +1 -1
  63. package/src/components/popover-dialog/PopoverDialog.tsx +1 -1
  64. package/src/components/post-block/PostBlock.tsx +1 -1
  65. package/src/components/progress/Progress.tsx +1 -1
  66. package/src/components/progress/ProgressCircular.tsx +1 -1
  67. package/src/components/progress/ProgressLinear.tsx +1 -1
  68. package/src/components/progress-tracker/ProgressTracker.tsx +1 -1
  69. package/src/components/progress-tracker/ProgressTrackerStep.tsx +1 -1
  70. package/src/components/progress-tracker/ProgressTrackerStepPanel.tsx +1 -1
  71. package/src/components/radio-button/RadioButton.tsx +1 -1
  72. package/src/components/radio-button/RadioGroup.tsx +1 -1
  73. package/src/components/select/Select.test.tsx +1 -1
  74. package/src/components/select/Select.tsx +2 -2
  75. package/src/components/select/SelectMultiple.test.tsx +1 -1
  76. package/src/components/select/SelectMultiple.tsx +2 -2
  77. package/src/components/select/WithSelectContext.tsx +2 -2
  78. package/src/components/side-navigation/SideNavigation.tsx +1 -1
  79. package/src/components/side-navigation/SideNavigationItem.tsx +23 -28
  80. package/src/components/skeleton/SkeletonCircle.tsx +1 -1
  81. package/src/components/skeleton/SkeletonRectangle.tsx +1 -1
  82. package/src/components/skeleton/SkeletonTypography.tsx +1 -1
  83. package/src/components/slider/Slider.tsx +1 -1
  84. package/src/components/slideshow/Slides.tsx +1 -1
  85. package/src/components/slideshow/SlideshowControls.tsx +1 -1
  86. package/src/components/slideshow/SlideshowItem.tsx +1 -1
  87. package/src/components/slideshow/SlideshowItemGroup.tsx +1 -1
  88. package/src/components/switch/Switch.tsx +1 -1
  89. package/src/components/table/Table.tsx +1 -1
  90. package/src/components/table/TableBody.tsx +1 -1
  91. package/src/components/table/TableCell.tsx +1 -1
  92. package/src/components/table/TableHeader.tsx +1 -1
  93. package/src/components/table/TableRow.tsx +1 -1
  94. package/src/components/tabs/Tab.tsx +1 -1
  95. package/src/components/tabs/TabList.tsx +1 -1
  96. package/src/components/tabs/TabPanel.tsx +1 -1
  97. package/src/components/text/Text.tsx +1 -1
  98. package/src/components/text-field/TextField.test.tsx +1 -1
  99. package/src/components/text-field/TextField.tsx +1 -1
  100. package/src/components/thumbnail/Thumbnail.test.tsx +28 -4
  101. package/src/components/thumbnail/Thumbnail.tsx +11 -12
  102. package/src/components/thumbnail/useFocusPointStyle.tsx +1 -1
  103. package/src/components/toolbar/Toolbar.tsx +1 -1
  104. package/src/components/tooltip/Tooltip.tsx +1 -1
  105. package/src/components/uploader/Uploader.tsx +1 -1
  106. package/src/components/user-block/UserBlock.tsx +1 -1
  107. package/src/hooks/useCallbackOnEscape.ts +1 -1
  108. package/src/index.ts +3 -1
  109. package/src/utils/partitionMulti.ts +2 -1
  110. package/src/utils/react/RawClickable.test.tsx +153 -0
  111. package/src/utils/react/RawClickable.tsx +65 -0
  112. package/src/utils/type/HasRequiredLinkHref.ts +1 -0
  113. package/src/utils/type/index.ts +3 -13
  114. package/src/components/index.ts +0 -160
  115. package/src/utils/browser/event.ts +0 -1
  116. package/src/utils/className/fontColorClass.test.ts +0 -15
  117. package/src/utils/className/fontColorClass.ts +0 -12
  118. package/src/utils/className/getBasicClass.test.ts +0 -20
  119. package/src/utils/className/getRootClassName.test.ts +0 -11
  120. package/src/utils/className/getRootClassName.ts +0 -24
  121. package/src/utils/className/getTypographyClassName.test.ts +0 -7
  122. package/src/utils/className/getTypographyClassName.ts +0 -9
  123. package/src/utils/className/handleBasicClasses.test.ts +0 -28
  124. package/src/utils/className/index.ts +0 -5
  125. package/src/utils/className/resolveColorWithVariants.test.ts +0 -33
  126. package/src/utils/className/resolveColorWithVariants.ts +0 -11
  127. package/src/utils/react/renderButtonOrLink.tsx +0 -16
  128. package/src/utils/react/renderLink.tsx +0 -17
  129. package/src/utils/type/Callback.ts +0 -4
  130. package/src/utils/type/Falsy.ts +0 -5
  131. package/src/utils/type/GenericProps.ts +0 -11
  132. package/src/utils/type/HasAriaLabelOrLabelledBy.ts +0 -19
  133. package/src/utils/type/HasClassName.ts +0 -6
  134. package/src/utils/type/HasCloseMode.ts +0 -7
  135. package/src/utils/type/HasTheme.ts +0 -8
  136. package/src/utils/type/HeadingElement.ts +0 -2
  137. package/src/utils/type/Point.ts +0 -4
  138. package/src/utils/type/Predicate.ts +0 -2
  139. package/src/utils/type/RectSize.ts +0 -4
  140. package/src/utils/type/TextElement.ts +0 -4
  141. package/src/utils/type/ValueOf.ts +0 -2
  142. package/src/utils/type/color/index.ts +0 -43
@@ -6,11 +6,10 @@ import isEmpty from 'lodash/isEmpty';
6
6
  import { mdiChevronDown, mdiChevronUp } from '@lumx/icons';
7
7
  import { Emphasis, Icon, Size, IconButton, IconButtonProps } from '@lumx/react';
8
8
  import { GenericProps, HasCloseMode, isComponent } from '@lumx/react/utils/type';
9
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
10
- import { renderLink } from '@lumx/react/utils/react/renderLink';
11
- import { renderButtonOrLink } from '@lumx/react/utils/react/renderButtonOrLink';
9
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
12
10
  import { useId } from '@lumx/react/hooks/useId';
13
11
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
12
+ import { RawClickable } from '@lumx/react/utils/react/RawClickable';
14
13
 
15
14
  /**
16
15
  * Defines the props of the component.
@@ -113,17 +112,15 @@ export const SideNavigationItem = forwardRef<SideNavigationItemProps, HTMLLIElem
113
112
  >
114
113
  {shouldSplitActions ? (
115
114
  <div className={`${CLASSNAME}__wrapper`}>
116
- {renderLink(
117
- {
118
- linkAs,
119
- ...linkProps,
120
- className: `${CLASSNAME}__link`,
121
- onClick,
122
- tabIndex: 0,
123
- },
124
- icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,
125
- <span>{label}</span>,
126
- )}
115
+ <RawClickable
116
+ as={linkAs || (linkProps?.href ? 'a' : 'button')}
117
+ {...(linkProps as any)}
118
+ className={`${CLASSNAME}__link`}
119
+ onClick={onClick}
120
+ >
121
+ {icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />}
122
+ <span>{label}</span>
123
+ </RawClickable>
127
124
 
128
125
  <IconButton
129
126
  {...toggleButtonProps}
@@ -136,25 +133,23 @@ export const SideNavigationItem = forwardRef<SideNavigationItemProps, HTMLLIElem
136
133
  />
137
134
  </div>
138
135
  ) : (
139
- renderButtonOrLink(
140
- {
141
- linkAs,
142
- ...linkProps,
143
- className: `${CLASSNAME}__link`,
144
- tabIndex: 0,
145
- onClick,
146
- ...ariaProps,
147
- },
148
- icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />,
149
- <span>{label}</span>,
150
- hasContent && (
136
+ <RawClickable
137
+ as={linkAs || (linkProps?.href ? 'a' : 'button')}
138
+ {...linkProps}
139
+ className={`${CLASSNAME}__link`}
140
+ onClick={onClick}
141
+ {...ariaProps}
142
+ >
143
+ {icon && <Icon className={`${CLASSNAME}__icon`} icon={icon} size={Size.xs} />}
144
+ <span>{label}</span>
145
+ {hasContent && (
151
146
  <Icon
152
147
  className={`${CLASSNAME}__chevron`}
153
148
  icon={isOpen ? mdiChevronUp : mdiChevronDown}
154
149
  size={Size.xs}
155
150
  />
156
- ),
157
- )
151
+ )}
152
+ </RawClickable>
158
153
  )}
159
154
 
160
155
  {(closeMode === 'hide' || showChildren) && (
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
 
5
5
  import { GlobalSize, Theme, ColorPalette } from '@lumx/react';
6
6
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
7
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
8
8
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
 
5
5
  import { AspectRatio, GlobalSize, Theme, ColorPalette } from '@lumx/react';
6
6
  import { GenericProps, HasTheme, ValueOf } from '@lumx/react/utils/type';
7
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
8
8
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
 
5
5
  import { Theme, TypographyInterface, ColorPalette } from '@lumx/react';
6
6
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
7
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
8
8
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
@@ -6,7 +6,7 @@ import classNames from 'classnames';
6
6
  import { InputHelper, InputLabel, Theme } from '@lumx/react';
7
7
  import useEventCallback from '@lumx/react/hooks/useEventCallback';
8
8
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
9
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
10
10
  import { clamp } from '@lumx/react/utils/number/clamp';
11
11
  import { useId } from '@lumx/react/hooks/useId';
12
12
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
@@ -5,7 +5,7 @@ import classNames from 'classnames';
5
5
 
6
6
  import { FULL_WIDTH_PERCENT } from '@lumx/react/components/slideshow/constants';
7
7
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
8
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
10
10
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
11
11
 
@@ -6,7 +6,7 @@ import range from 'lodash/range';
6
6
  import { mdiChevronLeft, mdiChevronRight, mdiPlayCircleOutline, mdiPauseCircleOutline } from '@lumx/icons';
7
7
  import { Emphasis, IconButton, IconButtonProps, Theme } from '@lumx/react';
8
8
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
9
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
10
10
  import { WINDOW } from '@lumx/react/constants';
11
11
  import { useSlideshowControls, DEFAULT_OPTIONS } from '@lumx/react/hooks/useSlideshowControls';
12
12
  import { useRovingTabIndex } from '@lumx/react/hooks/useRovingTabIndex';
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName } from '@lumx/react/utils/className';
6
+ import { getRootClassName } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
 
9
9
  /**
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import classNames from 'classnames';
4
4
  import { mergeRefs } from '@lumx/react/utils/react/mergeRefs';
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName } from '@lumx/react/utils/className';
6
+ import { getRootClassName } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
  import { useSlideFocusManagement } from './useSlideFocusManagement';
9
9
 
@@ -5,7 +5,7 @@ import isEmpty from 'lodash/isEmpty';
5
5
 
6
6
  import { Alignment, InputHelper, InputLabel, Theme } from '@lumx/react';
7
7
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
8
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { useId } from '@lumx/react/hooks/useId';
10
10
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
11
11
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
 
5
5
  import { Theme } from '@lumx/react';
6
6
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
7
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
8
8
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName } from '@lumx/react/utils/className';
6
+ import { getRootClassName } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
 
9
9
  /**
@@ -5,7 +5,7 @@ import classNames from 'classnames';
5
5
  import { mdiArrowDown, mdiArrowUp } from '@lumx/icons';
6
6
  import { Icon, Size } from '@lumx/react';
7
7
  import { GenericProps, ValueOf } from '@lumx/react/utils/type';
8
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
11
11
  /**
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName } from '@lumx/react/utils/className';
6
+ import { getRootClassName } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
 
9
9
  /**
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
6
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
  import { useDisableStateProps } from '@lumx/react/utils/disabled/useDisableStateProps';
9
9
 
@@ -5,7 +5,7 @@ import classNames from 'classnames';
5
5
  import { Icon, IconProps, Size, Text } from '@lumx/react';
6
6
  import { CSS_PREFIX } from '@lumx/react/constants';
7
7
  import { GenericProps } from '@lumx/react/utils/type';
8
- import { handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
10
10
 
11
11
  import { useDisableStateProps } from '@lumx/react/utils/disabled/useDisableStateProps';
@@ -5,7 +5,7 @@ import classNames from 'classnames';
5
5
  import { Alignment, Theme } from '@lumx/react';
6
6
  import { CSS_PREFIX } from '@lumx/react/constants';
7
7
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
8
- import { handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { mergeRefs } from '@lumx/react/utils/react/mergeRefs';
10
10
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
11
11
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
@@ -6,7 +6,7 @@ import { forwardRef } from '@lumx/react/utils/react/forwardRef';
6
6
  import { useTabProviderContext } from '@lumx/react/components/tabs/state';
7
7
  import { CSS_PREFIX } from '@lumx/react/constants';
8
8
  import { GenericProps } from '@lumx/react/utils/type';
9
- import { handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { handleBasicClasses } from '@lumx/core/js/utils/className';
10
10
 
11
11
  /**
12
12
  * Defines the props of the component.
@@ -9,7 +9,7 @@ import {
9
9
  getRootClassName,
10
10
  handleBasicClasses,
11
11
  getTypographyClassName,
12
- } from '@lumx/react/utils/className';
12
+ } from '@lumx/core/js/utils/className';
13
13
  import { useOverflowTooltipLabel } from '@lumx/react/hooks/useOverflowTooltipLabel';
14
14
  import { useMergeRefs } from '@lumx/react/utils/react/mergeRefs';
15
15
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import camelCase from 'lodash/camelCase';
4
4
 
5
5
  import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
6
- import { getBasicClass } from '@lumx/react/utils/className';
6
+ import { getBasicClass } from '@lumx/core/js/utils/className';
7
7
  import { render } from '@testing-library/react';
8
8
  import {
9
9
  getByClassName,
@@ -17,7 +17,7 @@ import {
17
17
  Theme,
18
18
  } from '@lumx/react';
19
19
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
20
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
20
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
21
21
  import { mergeRefs } from '@lumx/react/utils/react/mergeRefs';
22
22
  import { useId } from '@lumx/react/hooks/useId';
23
23
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { DisabledStateProvider } from '@lumx/react/utils';
4
4
  import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
5
5
  import { queryByClassName } from '@lumx/react/testing/utils/queries';
6
- import { fireEvent, render } from '@testing-library/react';
6
+ import { fireEvent, render, screen } from '@testing-library/react';
7
7
  import { Thumbnail, ThumbnailProps } from './Thumbnail';
8
8
 
9
9
  const CLASSNAME = Thumbnail.className as string;
@@ -28,8 +28,19 @@ describe(`<${Thumbnail.displayName}>`, () => {
28
28
  },
29
29
  });
30
30
 
31
- describe('disabled state', () => {
32
- it('should not be clickable when disabled from context', () => {
31
+ describe('clickable button', () => {
32
+ it('should render clickable button', async () => {
33
+ const onClick = jest.fn();
34
+ const { thumbnail } = setup({ onClick, alt: 'Name' });
35
+ const button = screen.getByRole('button', { name: 'Name' });
36
+ expect(button).toBe(thumbnail);
37
+ expect(button).toHaveAttribute('type', 'button');
38
+
39
+ fireEvent.click(thumbnail as HTMLElement);
40
+ expect(onClick).toHaveBeenCalled();
41
+ });
42
+
43
+ it('should not render button in disabled context', () => {
33
44
  const onClick = jest.fn();
34
45
  const { thumbnail, container } = setup(
35
46
  { onClick, 'aria-label': 'thumbnail' },
@@ -47,8 +58,21 @@ describe(`<${Thumbnail.displayName}>`, () => {
47
58
  fireEvent.click(thumbnail as HTMLElement);
48
59
  expect(onClick).not.toHaveBeenCalled();
49
60
  });
61
+ });
62
+
63
+ describe('clickable link', () => {
64
+ it('should render clickable link', async () => {
65
+ const onClick = jest.fn((evt) => evt.preventDefault());
66
+ const { thumbnail } = setup({ linkProps: { href: '#' }, onClick, alt: 'Name' });
67
+ const link = screen.getByRole('link', { name: 'Name' });
68
+ expect(link).toBe(thumbnail);
69
+ expect(link).toHaveAttribute('href', '#');
70
+
71
+ fireEvent.click(thumbnail as HTMLElement);
72
+ expect(onClick).toHaveBeenCalled();
73
+ });
50
74
 
51
- it('should have no href when disabled from context', () => {
75
+ it('should not render link in disabled context', () => {
52
76
  const { container, thumbnail } = setup(
53
77
  { linkAs: 'a', linkProps: { href: '#' }, 'aria-label': 'thumbnail' },
54
78
  {
@@ -13,7 +13,7 @@ import classNames from 'classnames';
13
13
 
14
14
  import { AspectRatio, HorizontalAlignment, Icon, Size, Theme, ThumbnailObjectFit } from '@lumx/react';
15
15
  import { Falsy, GenericProps, HasTheme } from '@lumx/react/utils/type';
16
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
16
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
17
17
  import { mdiImageBroken } from '@lumx/icons';
18
18
  import { useMergeRefs } from '@lumx/react/utils/react/mergeRefs';
19
19
  import { useImageLoad } from '@lumx/react/components/thumbnail/useImageLoad';
@@ -22,6 +22,7 @@ import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
22
22
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
23
23
 
24
24
  import { useDisableStateProps } from '@lumx/react/utils/disabled';
25
+ import { RawClickable } from '@lumx/react/utils/react/RawClickable';
25
26
  import { FocusPoint, ThumbnailSize, ThumbnailVariant } from './types';
26
27
 
27
28
  type ImgHTMLProps = ImgHTMLAttributes<HTMLImageElement>;
@@ -100,7 +101,7 @@ const DEFAULT_PROPS: Partial<ThumbnailProps> = {
100
101
  * @return React element.
101
102
  */
102
103
  export const Thumbnail = forwardRef<ThumbnailProps>((props, ref) => {
103
- const { isAnyDisabled, otherProps } = useDisableStateProps(props);
104
+ const { isAnyDisabled, otherProps, disabledStateProps } = useDisableStateProps(props);
104
105
  const defaultTheme = useTheme() || Theme.light;
105
106
  const {
106
107
  align,
@@ -150,18 +151,16 @@ export const Thumbnail = forwardRef<ThumbnailProps>((props, ref) => {
150
151
  imageErrorStyle.display = 'none';
151
152
  }
152
153
 
153
- const isLink = Boolean(linkProps?.href || linkAs);
154
- const isButton = !!forwardedProps.onClick;
155
- const isClickable = !isAnyDisabled && (isButton || isLink);
154
+ const isLink = linkProps?.href || linkAs;
155
+ const isClickable = !isAnyDisabled && (isLink || forwardedProps.onClick);
156
156
 
157
- let Wrapper: any = 'div';
157
+ const Wrapper: any = isClickable ? RawClickable : 'div';
158
158
  const wrapperProps = { ...forwardedProps };
159
- if (!isAnyDisabled && isLink) {
160
- Wrapper = linkAs || 'a';
161
- Object.assign(wrapperProps, linkProps);
162
- } else if (!isAnyDisabled && isButton) {
163
- Wrapper = 'button';
164
- wrapperProps.type = forwardedProps.type || 'button';
159
+ if (isClickable) {
160
+ Object.assign(wrapperProps, { as: linkAs || (linkProps?.href ? 'a' : 'button') }, disabledStateProps);
161
+ if (isLink) {
162
+ Object.assign(wrapperProps, linkProps);
163
+ }
165
164
  wrapperProps['aria-label'] = forwardedProps['aria-label'] || alt;
166
165
  }
167
166
 
@@ -1,5 +1,5 @@
1
1
  import { CSSProperties, useEffect, useMemo, useState } from 'react';
2
- import { AspectRatio } from '@lumx/react/components';
2
+ import { AspectRatio } from '@lumx/core/js/constants';
3
3
  import { ThumbnailProps } from '@lumx/react/components/thumbnail/Thumbnail';
4
4
  import { RectSize } from '@lumx/react/utils/type';
5
5
 
@@ -3,7 +3,7 @@ import React, { ReactNode } from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
5
  import { GenericProps } from '@lumx/react/utils/type';
6
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
6
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
7
7
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
8
8
 
9
9
  /**
@@ -5,7 +5,7 @@ import classNames from 'classnames';
5
5
 
6
6
  import { DOCUMENT, VISUALLY_HIDDEN } from '@lumx/react/constants';
7
7
  import { GenericProps, HasCloseMode } from '@lumx/react/utils/type';
8
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
9
9
  import { useMergeRefs } from '@lumx/react/utils/react/mergeRefs';
10
10
  import { Placement } from '@lumx/react/components/popover';
11
11
  import { TooltipContextProvider } from '@lumx/react/components/tooltip/context';
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
 
5
5
  import { AspectRatio, Icon, Size, Theme } from '@lumx/react';
6
6
  import { GenericProps, HasTheme, ValueOf } from '@lumx/react/utils/type';
7
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
8
8
  import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
9
9
  import { useId } from '@lumx/react/hooks/useId';
10
10
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
@@ -6,7 +6,7 @@ import set from 'lodash/set';
6
6
 
7
7
  import { Avatar, ColorPalette, Link, Orientation, Size, Theme } from '@lumx/react';
8
8
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
9
- import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
9
+ import { getRootClassName, handleBasicClasses } from '@lumx/core/js/utils/className';
10
10
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
11
11
 
12
12
  import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
@@ -1,6 +1,6 @@
1
1
  import { DOCUMENT } from '@lumx/react/constants';
2
2
  import { Callback } from '@lumx/react/utils/type';
3
- import { onEscapePressed } from '@lumx/react/utils/browser/event';
3
+ import { onEscapePressed } from '@lumx/core/js/utils';
4
4
  import { useEffect } from 'react';
5
5
  import { Listener, makeListenerTowerContext } from '@lumx/react/utils/function/makeListenerTowerContext';
6
6
 
package/src/index.ts CHANGED
@@ -2,7 +2,9 @@
2
2
  * Components listed here will be exposed to NPM in '@lumx/react'.
3
3
  */
4
4
 
5
- export * from './components';
5
+ export * from '@lumx/core/js/constants';
6
+ export * from '@lumx/core/js/types';
7
+
6
8
  export * from './components/alert-dialog';
7
9
  export * from './components/autocomplete';
8
10
  export * from './components/avatar';
@@ -3,7 +3,8 @@ import dropRight from 'lodash/dropRight';
3
3
  import last from 'lodash/last';
4
4
  import partition from 'lodash/partition';
5
5
  import reduce from 'lodash/reduce';
6
- import { Predicate } from './type';
6
+
7
+ import { Predicate } from '@lumx/core/js/types';
7
8
 
8
9
  /**
9
10
  * Similar to lodash `partition` function but working with multiple predicates.
@@ -0,0 +1,153 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { RawClickable, RawClickableProps } from './RawClickable';
5
+ import { CustomLink } from '../../stories/utils/CustomLink';
6
+
7
+ /**
8
+ * Mounts the component and returns common DOM elements / data needed in multiple tests.
9
+ */
10
+ const setup = (props: RawClickableProps<any>) => {
11
+ render(<RawClickable {...props} data-testid="raw-element" />);
12
+ const element = screen.getByTestId('raw-element');
13
+ return { props, element };
14
+ };
15
+
16
+ describe(`<RawClickable>`, () => {
17
+ describe('as a button', () => {
18
+ it('should render a button by default', () => {
19
+ const { element } = setup({ as: 'button', children: 'Click me' });
20
+ expect(element.tagName).toBe('BUTTON');
21
+ expect(element).toHaveAttribute('type', 'button');
22
+ expect(screen.getByRole('button', { name: 'Click me' })).toBe(element);
23
+ });
24
+
25
+ it('should trigger onClick', async () => {
26
+ const onClick = jest.fn();
27
+ const { element } = setup({ as: 'button', children: 'Click me', onClick });
28
+ await userEvent.click(element);
29
+ expect(onClick).toHaveBeenCalledTimes(1);
30
+ });
31
+
32
+ it('should be disabled with `disabled` prop', async () => {
33
+ const onClick = jest.fn();
34
+ const { element } = setup({ as: 'button', children: 'Click me', onClick, disabled: true });
35
+ expect(element).toBeDisabled();
36
+ await userEvent.click(element);
37
+ expect(onClick).not.toHaveBeenCalled();
38
+ });
39
+
40
+ it('should be disabled with `isDisabled` prop', async () => {
41
+ const onClick = jest.fn();
42
+ const { element } = setup({ as: 'button', children: 'Click me', onClick, isDisabled: true });
43
+ expect(element).toBeDisabled();
44
+ await userEvent.click(element);
45
+ expect(onClick).not.toHaveBeenCalled();
46
+ });
47
+
48
+ it('should be aria-disabled with `aria-disabled` prop', async () => {
49
+ const onClick = jest.fn();
50
+ const { element } = setup({ as: 'button', children: 'Click me', onClick, 'aria-disabled': true });
51
+ expect(element).not.toBeDisabled();
52
+ expect(element).toHaveAttribute('aria-disabled', 'true');
53
+ await userEvent.click(element);
54
+ expect(onClick).not.toHaveBeenCalled();
55
+ });
56
+ });
57
+
58
+ describe('as a link', () => {
59
+ const href = 'https://example.com';
60
+
61
+ it('should render a link with `href` prop', () => {
62
+ const { element } = setup({ as: 'a', children: 'Click me', href });
63
+ expect(element.tagName).toBe('A');
64
+ expect(element).toHaveAttribute('href', href);
65
+ expect(screen.getByRole('link', { name: 'Click me' })).toBe(element);
66
+ });
67
+
68
+ it('should trigger onClick', async () => {
69
+ const onClick = jest.fn((evt) => evt.preventDefault());
70
+ const { element } = setup({ as: 'a', children: 'Click me', href, onClick });
71
+ await userEvent.click(element);
72
+ expect(onClick).toHaveBeenCalledTimes(1);
73
+ });
74
+
75
+ it('should be disabled with `disabled` prop', async () => {
76
+ const onClick = jest.fn();
77
+ const { element } = setup({ as: 'a', children: 'Click me', href, onClick, disabled: true });
78
+ expect(element).toHaveAttribute('aria-disabled', 'true');
79
+ expect(element).toHaveAttribute('tabindex', '-1');
80
+ await userEvent.click(element);
81
+ expect(onClick).not.toHaveBeenCalled();
82
+ });
83
+
84
+ it('should be disabled with `isDisabled` prop', async () => {
85
+ const onClick = jest.fn();
86
+ const { element } = setup({ as: 'a', children: 'Click me', href, onClick, isDisabled: true });
87
+ expect(element).toHaveAttribute('aria-disabled', 'true');
88
+ expect(element).toHaveAttribute('tabindex', '-1');
89
+ await userEvent.click(element);
90
+ expect(onClick).not.toHaveBeenCalled();
91
+ });
92
+
93
+ it('should be aria-disabled with `aria-disabled` prop', async () => {
94
+ const onClick = jest.fn();
95
+ const { element } = setup({ as: 'a', children: 'Click me', href, onClick, 'aria-disabled': true });
96
+ expect(element).toHaveAttribute('aria-disabled', 'true');
97
+ await userEvent.click(element);
98
+ expect(onClick).not.toHaveBeenCalled();
99
+ });
100
+ });
101
+
102
+ describe('as a custom component', () => {
103
+ it('should render a custom component with `linkAs` prop', () => {
104
+ const { element } = setup({ as: CustomLink, children: 'Click me' });
105
+ expect(element).toHaveAttribute('data-custom-link');
106
+ });
107
+
108
+ it('should trigger onClick', async () => {
109
+ const onClick = jest.fn();
110
+ const { element } = setup({ as: CustomLink, children: 'Click me', onClick });
111
+ expect(element).toHaveAttribute('data-custom-link');
112
+ await userEvent.click(element);
113
+ expect(onClick).toHaveBeenCalledTimes(1);
114
+ });
115
+
116
+ it('should be disabled with `disabled` prop', async () => {
117
+ const onClick = jest.fn();
118
+ const { element } = setup({ as: CustomLink, children: 'Click me', onClick, disabled: true });
119
+ expect(element).toHaveAttribute('data-custom-link');
120
+ expect(element).toHaveAttribute('aria-disabled', 'true');
121
+ expect(element).toHaveAttribute('tabindex', '-1');
122
+ await userEvent.click(element);
123
+ expect(onClick).not.toHaveBeenCalled();
124
+ });
125
+ });
126
+
127
+ describe('prop forwarding', () => {
128
+ it('should forward className', () => {
129
+ const { element } = setup({ as:'button', className: 'foo bar' });
130
+ expect(element).toHaveClass('foo bar');
131
+ });
132
+
133
+ it('should forward ref and override type in button', () => {
134
+ const ref = React.createRef<HTMLButtonElement>();
135
+ const { element } = setup({ as: 'button', ref, type: 'submit' });
136
+ expect(element).toHaveAttribute('type', 'submit');
137
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
138
+ });
139
+
140
+ it('should forward ref and override tabindex in link', () => {
141
+ const ref = React.createRef<HTMLAnchorElement>();
142
+ const { element } = setup({ as: 'a', ref, href: '#', tabIndex: -1 });
143
+ expect(ref.current).toBeInstanceOf(HTMLAnchorElement);
144
+ expect(element).toHaveAttribute('tabindex', '-1');
145
+ });
146
+
147
+ it('should forward ref to custom component', () => {
148
+ const ref = React.createRef<HTMLAnchorElement>();
149
+ setup({ as: CustomLink, ref });
150
+ expect(ref.current).toBeInstanceOf(HTMLAnchorElement);
151
+ });
152
+ });
153
+ });