@stack-spot/citric-react 0.12.0 → 0.13.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 (199) hide show
  1. package/dist/components/Accordion.d.ts.map +1 -1
  2. package/dist/components/Accordion.js +3 -2
  3. package/dist/components/Accordion.js.map +1 -1
  4. package/dist/components/Alert.d.ts.map +1 -1
  5. package/dist/components/Alert.js +2 -1
  6. package/dist/components/Alert.js.map +1 -1
  7. package/dist/components/AsyncContent.d.ts.map +1 -1
  8. package/dist/components/AsyncContent.js +3 -2
  9. package/dist/components/AsyncContent.js.map +1 -1
  10. package/dist/components/Avatar.d.ts.map +1 -1
  11. package/dist/components/Avatar.js +3 -2
  12. package/dist/components/Avatar.js.map +1 -1
  13. package/dist/components/AvatarGroup.d.ts.map +1 -1
  14. package/dist/components/AvatarGroup.js +3 -2
  15. package/dist/components/AvatarGroup.js.map +1 -1
  16. package/dist/components/Badge.d.ts +2 -1
  17. package/dist/components/Badge.d.ts.map +1 -1
  18. package/dist/components/Badge.js +3 -1
  19. package/dist/components/Badge.js.map +1 -1
  20. package/dist/components/Blockquote.d.ts.map +1 -1
  21. package/dist/components/Blockquote.js +2 -1
  22. package/dist/components/Blockquote.js.map +1 -1
  23. package/dist/components/Breadcrumb.d.ts.map +1 -1
  24. package/dist/components/Breadcrumb.js +3 -2
  25. package/dist/components/Breadcrumb.js.map +1 -1
  26. package/dist/components/Button.d.ts.map +1 -1
  27. package/dist/components/Button.js +3 -2
  28. package/dist/components/Button.js.map +1 -1
  29. package/dist/components/Card.d.ts.map +1 -1
  30. package/dist/components/Card.js +2 -1
  31. package/dist/components/Card.js.map +1 -1
  32. package/dist/components/Checkbox.d.ts.map +1 -1
  33. package/dist/components/Checkbox.js +3 -2
  34. package/dist/components/Checkbox.js.map +1 -1
  35. package/dist/components/CheckboxGroup.d.ts +3 -1
  36. package/dist/components/CheckboxGroup.d.ts.map +1 -1
  37. package/dist/components/CheckboxGroup.js +3 -1
  38. package/dist/components/CheckboxGroup.js.map +1 -1
  39. package/dist/components/Circle.d.ts.map +1 -1
  40. package/dist/components/Circle.js +2 -1
  41. package/dist/components/Circle.js.map +1 -1
  42. package/dist/components/CitricComponent.d.ts +1 -0
  43. package/dist/components/CitricComponent.d.ts.map +1 -1
  44. package/dist/components/CitricComponent.js.map +1 -1
  45. package/dist/components/Divider.d.ts.map +1 -1
  46. package/dist/components/Divider.js +2 -1
  47. package/dist/components/Divider.js.map +1 -1
  48. package/dist/components/Favorite.d.ts +1 -1
  49. package/dist/components/Favorite.d.ts.map +1 -1
  50. package/dist/components/Favorite.js +2 -1
  51. package/dist/components/Favorite.js.map +1 -1
  52. package/dist/components/FieldGroup.d.ts.map +1 -1
  53. package/dist/components/FieldGroup.js +2 -1
  54. package/dist/components/FieldGroup.js.map +1 -1
  55. package/dist/components/Form.d.ts.map +1 -1
  56. package/dist/components/Form.js +2 -1
  57. package/dist/components/Form.js.map +1 -1
  58. package/dist/components/FormGroup.d.ts.map +1 -1
  59. package/dist/components/FormGroup.js +2 -1
  60. package/dist/components/FormGroup.js.map +1 -1
  61. package/dist/components/IconBox.d.ts +6 -3
  62. package/dist/components/IconBox.d.ts.map +1 -1
  63. package/dist/components/IconBox.js +10 -6
  64. package/dist/components/IconBox.js.map +1 -1
  65. package/dist/components/ImageBox.d.ts +8 -5
  66. package/dist/components/ImageBox.d.ts.map +1 -1
  67. package/dist/components/ImageBox.js +9 -5
  68. package/dist/components/ImageBox.js.map +1 -1
  69. package/dist/components/Input.d.ts +3 -1
  70. package/dist/components/Input.d.ts.map +1 -1
  71. package/dist/components/Input.js +3 -1
  72. package/dist/components/Input.js.map +1 -1
  73. package/dist/components/Link.d.ts.map +1 -1
  74. package/dist/components/Link.js +3 -2
  75. package/dist/components/Link.js.map +1 -1
  76. package/dist/components/MenuOverlay/Menu.d.ts.map +1 -1
  77. package/dist/components/MenuOverlay/Menu.js.map +1 -1
  78. package/dist/components/Pagination.d.ts +1 -1
  79. package/dist/components/Pagination.d.ts.map +1 -1
  80. package/dist/components/Pagination.js +3 -2
  81. package/dist/components/Pagination.js.map +1 -1
  82. package/dist/components/ProgressBar.d.ts.map +1 -1
  83. package/dist/components/ProgressBar.js +2 -1
  84. package/dist/components/ProgressBar.js.map +1 -1
  85. package/dist/components/ProgressCircular.d.ts.map +1 -1
  86. package/dist/components/ProgressCircular.js +2 -1
  87. package/dist/components/ProgressCircular.js.map +1 -1
  88. package/dist/components/RadioGroup.d.ts +3 -1
  89. package/dist/components/RadioGroup.d.ts.map +1 -1
  90. package/dist/components/RadioGroup.js +3 -1
  91. package/dist/components/RadioGroup.js.map +1 -1
  92. package/dist/components/Rating.d.ts.map +1 -1
  93. package/dist/components/Rating.js +2 -1
  94. package/dist/components/Rating.js.map +1 -1
  95. package/dist/components/Select/RichSelect.d.ts +3 -1
  96. package/dist/components/Select/RichSelect.d.ts.map +1 -1
  97. package/dist/components/Select/RichSelect.js +5 -2
  98. package/dist/components/Select/RichSelect.js.map +1 -1
  99. package/dist/components/Select/SimpleSelect.d.ts +2 -1
  100. package/dist/components/Select/SimpleSelect.d.ts.map +1 -1
  101. package/dist/components/Select/SimpleSelect.js +4 -2
  102. package/dist/components/Select/SimpleSelect.js.map +1 -1
  103. package/dist/components/Select/index.d.ts +2 -1
  104. package/dist/components/Select/index.d.ts.map +1 -1
  105. package/dist/components/Select/index.js +3 -1
  106. package/dist/components/Select/index.js.map +1 -1
  107. package/dist/components/Select/types.d.ts +3 -1
  108. package/dist/components/Select/types.d.ts.map +1 -1
  109. package/dist/components/SelectBox.d.ts +2 -1
  110. package/dist/components/SelectBox.d.ts.map +1 -1
  111. package/dist/components/SelectBox.js +3 -1
  112. package/dist/components/SelectBox.js.map +1 -1
  113. package/dist/components/Skeleton.d.ts.map +1 -1
  114. package/dist/components/Skeleton.js +2 -1
  115. package/dist/components/Skeleton.js.map +1 -1
  116. package/dist/components/Slider.d.ts.map +1 -1
  117. package/dist/components/Slider.js +3 -2
  118. package/dist/components/Slider.js.map +1 -1
  119. package/dist/components/SmartTable.d.ts +2 -1
  120. package/dist/components/SmartTable.d.ts.map +1 -1
  121. package/dist/components/SmartTable.js +3 -1
  122. package/dist/components/SmartTable.js.map +1 -1
  123. package/dist/components/Stepper.d.ts +3 -1
  124. package/dist/components/Stepper.d.ts.map +1 -1
  125. package/dist/components/Stepper.js +3 -1
  126. package/dist/components/Stepper.js.map +1 -1
  127. package/dist/components/Switch.d.ts.map +1 -1
  128. package/dist/components/Switch.js +3 -2
  129. package/dist/components/Switch.js.map +1 -1
  130. package/dist/components/Table.d.ts +1 -1
  131. package/dist/components/Table.d.ts.map +1 -1
  132. package/dist/components/Table.js +9 -7
  133. package/dist/components/Table.js.map +1 -1
  134. package/dist/components/Tabs/index.d.ts +3 -1
  135. package/dist/components/Tabs/index.d.ts.map +1 -1
  136. package/dist/components/Tabs/index.js +3 -1
  137. package/dist/components/Tabs/index.js.map +1 -1
  138. package/dist/components/Text.d.ts +2 -1
  139. package/dist/components/Text.d.ts.map +1 -1
  140. package/dist/components/Text.js +3 -1
  141. package/dist/components/Text.js.map +1 -1
  142. package/dist/components/Textarea.d.ts +3 -0
  143. package/dist/components/Textarea.d.ts.map +1 -1
  144. package/dist/components/Textarea.js +3 -1
  145. package/dist/components/Textarea.js.map +1 -1
  146. package/dist/components/layout.d.ts +7 -3
  147. package/dist/components/layout.d.ts.map +1 -1
  148. package/dist/components/layout.js +7 -3
  149. package/dist/components/layout.js.map +1 -1
  150. package/dist/utils/react.d.ts +2 -0
  151. package/dist/utils/react.d.ts.map +1 -0
  152. package/dist/utils/react.js +6 -0
  153. package/dist/utils/react.js.map +1 -0
  154. package/package.json +1 -1
  155. package/src/components/Accordion.tsx +3 -2
  156. package/src/components/Alert.tsx +3 -2
  157. package/src/components/AsyncContent.tsx +3 -2
  158. package/src/components/Avatar.tsx +3 -2
  159. package/src/components/AvatarGroup.tsx +3 -2
  160. package/src/components/Badge.tsx +4 -1
  161. package/src/components/Blockquote.tsx +3 -2
  162. package/src/components/Breadcrumb.tsx +3 -2
  163. package/src/components/Button.tsx +3 -2
  164. package/src/components/Card.tsx +3 -2
  165. package/src/components/Checkbox.tsx +3 -2
  166. package/src/components/CheckboxGroup.tsx +4 -1
  167. package/src/components/Circle.tsx +3 -2
  168. package/src/components/CitricComponent.ts +1 -0
  169. package/src/components/Divider.tsx +3 -2
  170. package/src/components/Favorite.tsx +5 -3
  171. package/src/components/FieldGroup.tsx +3 -2
  172. package/src/components/Form.tsx +3 -2
  173. package/src/components/FormGroup.tsx +3 -2
  174. package/src/components/IconBox.tsx +11 -8
  175. package/src/components/ImageBox.tsx +12 -7
  176. package/src/components/Input.tsx +4 -1
  177. package/src/components/Link.tsx +3 -2
  178. package/src/components/MenuOverlay/Menu.tsx +3 -3
  179. package/src/components/Pagination.tsx +4 -3
  180. package/src/components/ProgressBar.tsx +4 -2
  181. package/src/components/ProgressCircular.tsx +4 -2
  182. package/src/components/RadioGroup.tsx +4 -1
  183. package/src/components/Rating.tsx +3 -2
  184. package/src/components/Select/RichSelect.tsx +9 -3
  185. package/src/components/Select/SimpleSelect.tsx +11 -5
  186. package/src/components/Select/index.tsx +4 -1
  187. package/src/components/Select/types.ts +3 -1
  188. package/src/components/SelectBox.tsx +4 -1
  189. package/src/components/Skeleton.tsx +4 -2
  190. package/src/components/Slider.tsx +3 -3
  191. package/src/components/SmartTable.tsx +4 -1
  192. package/src/components/Stepper.tsx +4 -1
  193. package/src/components/Switch.tsx +3 -2
  194. package/src/components/Table.tsx +46 -42
  195. package/src/components/Tabs/index.tsx +4 -1
  196. package/src/components/Text.ts +4 -1
  197. package/src/components/Textarea.tsx +6 -1
  198. package/src/components/layout.tsx +8 -3
  199. package/src/utils/react.ts +6 -0
@@ -7,7 +7,7 @@ import { IconButton } from '../IconBox'
7
7
  import { useOverlayController } from '../Overlay/context'
8
8
  import { MenuProvider, useMenuController, useMenuState } from './context'
9
9
  import { keyboardNavigation } from './keyboard'
10
- import { MenuAction, MenuCollapsible, MenuItem, MenuProps, MenuSection, MenuState } from './types'
10
+ import { MenuAction as MenuActionI, MenuCollapsible, MenuItem, MenuProps, MenuSection as MenuSectionI, MenuState } from './types'
11
11
 
12
12
  // Arbitrary time (ms) to wait before running a function that needs the view to be updated with the next state value.
13
13
  const RENDER_DELAY = 20
@@ -38,7 +38,7 @@ function Submenu({ children, label, className, icon, iconRight, style }: MenuCol
38
38
  )
39
39
  }
40
40
 
41
- function MenuSection({ children, label, className, style }: MenuSection) {
41
+ function MenuSection({ children, label, className, style }: MenuSectionI) {
42
42
  return (
43
43
  <section className={className} style={style}>
44
44
  {label && <h6>{label}</h6>}
@@ -50,7 +50,7 @@ function MenuSection({ children, label, className, style }: MenuSection) {
50
50
  )
51
51
  }
52
52
 
53
- function MenuAction({ label, active, href, icon, iconRight, className, onClick, ...props }: MenuAction) {
53
+ function MenuAction({ label, active, href, icon, iconRight, className, onClick, ...props }: MenuActionI) {
54
54
  const overlayController = useOverlayController()
55
55
  const children = <>
56
56
  {icon}
@@ -1,5 +1,6 @@
1
1
  import { Dictionary, interpolate, useTranslate } from '@stack-spot/portal-translate'
2
2
  import { useMemo } from 'react'
3
+ import { withRef } from '../utils/react'
3
4
  import { CitricComponent } from './CitricComponent'
4
5
  import { IconButton } from './IconBox'
5
6
 
@@ -28,9 +29,9 @@ export interface BasePaginationProps {
28
29
  onChange: (page: number, size: number) => void,
29
30
  }
30
31
 
31
- export type PaginationProps = React.JSX.IntrinsicElements['div'] & BasePaginationProps
32
+ export type PaginationProps = Omit<React.JSX.IntrinsicElements['div'], 'onChange'> & BasePaginationProps
32
33
 
33
- export const Pagination = (
34
+ export const Pagination = withRef((
34
35
  { pageSizeOptions = [10, 20, 30], pageSize, totalPages, page, onChange, ...props }: PaginationProps,
35
36
  ) => {
36
37
  const t = useTranslate(dictionary)
@@ -73,7 +74,7 @@ export const Pagination = (
73
74
  </div>
74
75
  </CitricComponent>
75
76
  )
76
- }
77
+ })
77
78
 
78
79
  const dictionary = {
79
80
  en: {
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { isNil } from 'lodash'
3
3
  import { WithColorPalette, WithColorScheme } from '../types'
4
4
  import { applyCSSVariable } from '../utils/css'
5
+ import { withRef } from '../utils/react'
5
6
  import { CitricComponent } from './CitricComponent'
6
7
 
7
8
  export interface BaseProgressBarProps extends WithColorScheme, WithColorPalette {
@@ -15,11 +16,12 @@ export interface BaseProgressBarProps extends WithColorScheme, WithColorPalette
15
16
 
16
17
  export type ProgressBarProps = React.JSX.IntrinsicElements['div'] & BaseProgressBarProps
17
18
 
18
- export const ProgressBar = ({ progress, style, className, ...props }: ProgressBarProps) =>
19
+ export const ProgressBar = withRef(({ progress, style, className, ...props }: ProgressBarProps) =>
19
20
  <CitricComponent
20
21
  tag="div"
21
22
  component="progress-bar"
22
23
  className={listToClass([className, isNil(progress) && 'indeterminate'])}
23
24
  style={progress === undefined ? style : applyCSSVariable(style, 'progress', progress)}
24
25
  {...props}
25
- />
26
+ />,
27
+ )
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { isNil } from 'lodash'
3
3
  import { WithColorPalette, WithColorScheme } from '../types'
4
4
  import { applyCSSVariable } from '../utils/css'
5
+ import { withRef } from '../utils/react'
5
6
  import { CitricComponent } from './CitricComponent'
6
7
 
7
8
  export interface BaseProgressCircularProps extends WithColorScheme, WithColorPalette {
@@ -19,11 +20,12 @@ export interface BaseProgressCircularProps extends WithColorScheme, WithColorPal
19
20
 
20
21
  export type ProgressCircularProps = React.JSX.IntrinsicElements['div'] & BaseProgressCircularProps
21
22
 
22
- export const ProgressCircular = ({ progress, size, style, className, ...props }: ProgressCircularProps) =>
23
+ export const ProgressCircular = withRef(({ progress, size, style, className, ...props }: ProgressCircularProps) =>
23
24
  <CitricComponent
24
25
  tag="div"
25
26
  component="progress-circular"
26
27
  className={listToClass([size, className, isNil(progress) && 'indeterminate'])}
27
28
  style={progress === undefined ? style : applyCSSVariable(style, 'progress', progress)}
28
29
  {...props}
29
- />
30
+ />,
31
+ )
@@ -2,6 +2,7 @@ import { isNil } from 'lodash'
2
2
  import { useMemo } from 'react'
3
3
  import { WithColorScheme } from '../types'
4
4
  import { defaultRenderKey, defaultRenderLabel } from '../utils/options'
5
+ import { withRef } from '../utils/react'
5
6
  import { CitricComponent } from './CitricComponent'
6
7
  import { Column } from './layout'
7
8
 
@@ -52,7 +53,7 @@ export interface BaseRadioGroupProps<T> extends WithColorScheme {
52
53
 
53
54
  export type RadioGroupProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseRadioGroupProps<T>
54
55
 
55
- export function RadioGroup<T>({
56
+ function _RadioGroup<T>({
56
57
  name,
57
58
  value,
58
59
  options,
@@ -85,3 +86,5 @@ export function RadioGroup<T>({
85
86
  }, [options, value, name, colorScheme])
86
87
  return <Column {...props} style={{ gap: '8px', ...style }}>{items}</Column>
87
88
  }
89
+
90
+ export const RadioGroup = withRef(_RadioGroup)
@@ -1,3 +1,4 @@
1
+ import { withRef } from '../utils/react'
1
2
  import { CitricComponent } from './CitricComponent'
2
3
 
3
4
  export type RatingValue = 1 | 2 | 3 | 4 | 5
@@ -13,7 +14,7 @@ export interface BaseRatingProps {
13
14
 
14
15
  export type RatingProps = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseRatingProps
15
16
 
16
- export const Rating = ({ value, onChange, name, ...props }: RatingProps) => (
17
+ export const Rating = withRef(({ value, onChange, name, ...props }: RatingProps) => (
17
18
  <CitricComponent tag="div" component="rating" {...props}>
18
19
  <input type="radio" value="1" name={name} checked={value === 5} onChange={() => onChange(5)} />
19
20
  <input type="radio" value="2" name={name} checked={value === 4} onChange={() => onChange(4)} />
@@ -21,4 +22,4 @@ export const Rating = ({ value, onChange, name, ...props }: RatingProps) => (
21
22
  <input type="radio" value="4" name={name} checked={value === 2} onChange={() => onChange(2)} />
22
23
  <input type="radio" value="5" name={name} checked={value === 1} onChange={() => onChange(1)} />
23
24
  </CitricComponent>
24
- )
25
+ ))
@@ -3,13 +3,15 @@ import { useTranslate } from '@stack-spot/portal-translate'
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
4
4
  import { applyCSSVariable } from '../../utils/css'
5
5
  import { defaultRenderKey, defaultRenderLabel } from '../../utils/options'
6
+ import { withRef } from '../../utils/react'
6
7
  import { CitricComponent } from '../CitricComponent'
7
8
  import { Input } from '../Input'
8
9
  import { ProgressCircular } from '../ProgressCircular'
9
10
  import { SimpleSelect } from './SimpleSelect'
10
11
  import { SelectProps } from './types'
11
12
 
12
- export function RichSelect<T>({
13
+ function _RichSelect<T>({
14
+ ref,
13
15
  options,
14
16
  value,
15
17
  onChange,
@@ -28,9 +30,11 @@ export function RichSelect<T>({
28
30
  onBlur,
29
31
  showArrow,
30
32
  ...props
31
- }: SelectProps<T> & { type?: 'rich' }) {
33
+ }: SelectProps<T> & { type?: 'rich' },
34
+ ) {
32
35
  const [search, setSearch] = useState('')
33
- const element = useRef<HTMLDivElement | null>(null)
36
+ const _element = useRef<HTMLDivElement | null>(null)
37
+ const element = ref ?? _element
34
38
  const [open, setOpen] = useState(false)
35
39
  const [focused, setFocused] = useState(false)
36
40
  const t = useTranslate(dictionary)
@@ -213,3 +217,5 @@ const dictionary = {
213
217
  empty: 'Vazio',
214
218
  },
215
219
  }
220
+
221
+ export const RichSelect = withRef(_RichSelect)
@@ -1,10 +1,12 @@
1
- import { useCallback, useMemo } from 'react'
1
+ import { MutableRefObject, useCallback, useMemo } from 'react'
2
2
  import { defaultRenderKey, defaultRenderLabel } from '../../utils/options'
3
+ import { withRef } from '../../utils/react'
3
4
  import { CitricComponent } from '../CitricComponent'
4
5
  import { ProgressCircular } from '../ProgressCircular'
5
6
  import { SelectProps } from './types'
6
7
 
7
- export function SimpleSelect<T>({
8
+ export function _SimpleSelect<T>({
9
+ ref,
8
10
  options,
9
11
  value,
10
12
  onChange,
@@ -17,7 +19,8 @@ export function SimpleSelect<T>({
17
19
  onFocus,
18
20
  wrap,
19
21
  ...props
20
- }: SelectProps<T> & { wrap?: boolean }) {
22
+ }: SelectProps<T> & { wrap?: boolean },
23
+ ) {
21
24
  const handleChange = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
22
25
  const selectedIndex = e.target.options.selectedIndex - (e.target.options.length > options.length ? 1 : 0)
23
26
  onChange?.(selectedIndex >= 0 ? options[selectedIndex] : undefined)
@@ -38,10 +41,11 @@ export function SimpleSelect<T>({
38
41
 
39
42
  return wrap === false ? (
40
43
  <CitricComponent
44
+ tag="select"
45
+ ref={ref as MutableRefObject<HTMLSelectElement | null>}
41
46
  required={required}
42
47
  onChange={handleChange}
43
48
  disabled={disabled || loading}
44
- tag="select"
45
49
  component="select"
46
50
  onFocus={onFocus}
47
51
  onBlur={onBlur}
@@ -50,7 +54,7 @@ export function SimpleSelect<T>({
50
54
  {renderedOptions}
51
55
  </CitricComponent>
52
56
  ) : (
53
- <CitricComponent tag="div" component="select" aria-busy={loading} {...props}>
57
+ <CitricComponent ref={ref as MutableRefObject<HTMLDivElement | null>} tag="div" component="select" aria-busy={loading} {...props}>
54
58
  <select
55
59
  value={value ? renderKey(value) : undefined}
56
60
  required={required}
@@ -65,3 +69,5 @@ export function SimpleSelect<T>({
65
69
  </CitricComponent>
66
70
  )
67
71
  }
72
+
73
+ export const SimpleSelect = withRef(_SimpleSelect)
@@ -1,8 +1,11 @@
1
+ import { withRef } from '../../utils/react'
1
2
  import { RichSelect } from './RichSelect'
2
3
  import { SimpleSelect } from './SimpleSelect'
3
4
  import { SelectProps } from './types'
4
5
  export type * from './types'
5
6
 
6
- export function Select<T>(props: SelectProps<T>) {
7
+ export function _Select<T>(props: SelectProps<T>) {
7
8
  return props.type === 'simple' ? <SimpleSelect {...props} /> : <RichSelect {...props} />
8
9
  }
10
+
11
+ export const Select = withRef(_Select)
@@ -77,6 +77,7 @@ interface CommonSelectProps<T> extends WithColorScheme {
77
77
 
78
78
  export interface SimpleSelectProps<T> extends CommonSelectProps<T> {
79
79
  type: 'simple',
80
+ ref?: React.MutableRefObject<HTMLDivElement | HTMLSelectElement>,
80
81
  }
81
82
 
82
83
  export interface RichSelectProps<T> extends CommonSelectProps<T> {
@@ -114,8 +115,9 @@ export interface RichSelectProps<T> extends CommonSelectProps<T> {
114
115
  * @default true
115
116
  */
116
117
  showArrow?: boolean,
118
+ ref?: React.MutableRefObject<HTMLDivElement>,
117
119
  }
118
120
 
119
121
  export type BaseSelectProps<T> = SimpleSelectProps<T> | RichSelectProps<T>
120
122
 
121
- export type SelectProps<T> = React.JSX.IntrinsicElements['div'] & BaseSelectProps<T>
123
+ export type SelectProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'ref' | 'onChange'> & BaseSelectProps<T>
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { useMemo } from 'react'
3
3
  import { WithColorPalette, WithColorScheme } from '../types'
4
4
  import { defaultRenderKey, defaultRenderLabel } from '../utils/options'
5
+ import { withRef } from '../utils/react'
5
6
  import { CitricComponent } from './CitricComponent'
6
7
  import { layout } from './layout'
7
8
 
@@ -72,7 +73,7 @@ export type BaseSelectBoxProps<T> = RadioProps<T> | CheckboxProps<T>
72
73
 
73
74
  export type SelectBoxProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseSelectBoxProps<T>
74
75
 
75
- export function SelectBox<T>({
76
+ function _SelectBox<T>({
76
77
  multiple,
77
78
  name,
78
79
  value,
@@ -132,3 +133,5 @@ export function SelectBox<T>({
132
133
  </div>
133
134
  )
134
135
  }
136
+
137
+ export const SelectBox = withRef(_SelectBox)
@@ -1,4 +1,5 @@
1
1
  import { listToClass } from '@stack-spot/portal-theme'
2
+ import { withRef } from '../utils/react'
2
3
  import { CitricComponent } from './CitricComponent'
3
4
 
4
5
  export interface BaseSkeletonProps {
@@ -30,11 +31,12 @@ export interface BaseSkeletonProps {
30
31
 
31
32
  export type SkeletonProps = React.JSX.IntrinsicElements['div'] & BaseSkeletonProps
32
33
 
33
- export const Skeleton = ({ appearance, className, style, width, height, bgLevel, ...props }: SkeletonProps) =>
34
+ export const Skeleton = withRef(({ appearance, className, style, width, height, bgLevel, ...props }: SkeletonProps) =>
34
35
  <CitricComponent
35
36
  tag="div"
36
37
  component="skeleton"
37
38
  className={listToClass([appearance, bgLevel && `bg-${bgLevel}`, className])}
38
39
  style={{ width, height, ...style }}
39
40
  {...props}
40
- />
41
+ />,
42
+ )
@@ -1,6 +1,7 @@
1
1
  import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { ControlledInput, WithColorPalette, WithColorScheme } from '../types'
3
3
  import { applyCSSVariable } from '../utils/css'
4
+ import { withRef } from '../utils/react'
4
5
  import { CitricComponent } from './CitricComponent'
5
6
 
6
7
  export interface BaseSliderProps extends WithColorScheme, WithColorPalette {
@@ -34,7 +35,7 @@ export interface BaseSliderProps extends WithColorScheme, WithColorPalette {
34
35
 
35
36
  export type SliderProps = ControlledInput & BaseSliderProps
36
37
 
37
- export const Slider = (
38
+ export const Slider = withRef((
38
39
  { value, onChange, min, max, style, showValue, renderValue, colorPalette, colorScheme, className, ...props }: SliderProps,
39
40
  ) => {
40
41
  const percent = Math.floor((value / ((max ?? 100) - (min ?? 0))) * 100)
@@ -73,5 +74,4 @@ export const Slider = (
73
74
  </div>
74
75
  </CitricComponent>
75
76
  )
76
- }
77
-
77
+ })
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react'
2
+ import { withRef } from '../utils/react'
2
3
  import { BaseTableProps, SortingDirection, Table, TableProps, Th, Tr } from './Table'
3
4
 
4
5
  export type TableColumn<T> = {
@@ -88,7 +89,7 @@ export type BaseSmartTableProps<T extends Record<string, any>> = BaseTableProps
88
89
 
89
90
  export type SmartTableProps<T extends Record<string, any>> = Omit<TableProps, 'children'> & ExtraSmartTableProps<T>
90
91
 
91
- export function SmartTable<T extends Record<string, any>>(
92
+ function _SmartTable<T extends Record<string, any>>(
92
93
  { data, keygen, columns, renderAccordion, accordionTrigger, accordionMaxHeight, id, ...props }: SmartTableProps<T>,
93
94
  ) {
94
95
  id = useMemo(() => id || `${Math.random()}`, [id])
@@ -146,3 +147,5 @@ export function SmartTable<T extends Record<string, any>>(
146
147
  </Table>
147
148
  )
148
149
  }
150
+
151
+ export const SmartTable = withRef(_SmartTable)
@@ -1,6 +1,7 @@
1
1
  import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
3
  import { useCallback, useEffect, useMemo, useState } from 'react'
4
+ import { withRef } from '../utils/react'
4
5
  import { Button } from './Button'
5
6
  import { Column, Row } from './layout'
6
7
  import { Tabs } from './Tabs'
@@ -64,7 +65,7 @@ function getTabsWithDisabled<Key extends string>(tabs: Tab<Key>[], value: Key |
64
65
  return tabs.map((t, i) => ({ ...t, disabled: i > index }))
65
66
  }
66
67
 
67
- export function Stepper<Key extends string>(
68
+ function _Stepper<Key extends string>(
68
69
  { tabs: initialTabs, controller: ctrl, value, onChange, buttons = true, className, ...props }: StepperProps<Key>,
69
70
  ) {
70
71
  const controller = useMemo(
@@ -139,3 +140,5 @@ const dictionary = {
139
140
  finish: 'Finalizar',
140
141
  },
141
142
  } satisfies Dictionary
143
+
144
+ export const Stepper = withRef(_Stepper)
@@ -1,4 +1,5 @@
1
1
  import { ControlledInput, WithColorScheme } from '../types'
2
+ import { withRef } from '../utils/react'
2
3
  import { CitricComponent } from './CitricComponent'
3
4
 
4
5
  interface Props extends WithColorScheme {
@@ -9,7 +10,7 @@ interface Props extends WithColorScheme {
9
10
 
10
11
  export type SwitchProps = ControlledInput & Props
11
12
 
12
- export const Switch = ({ value, onChange, children, className, style, ...props }: SwitchProps) => {
13
+ export const Switch = withRef(({ value, onChange, children, className, style, ...props }: SwitchProps) => {
13
14
  const handleChange = onChange ? () => onChange(!value) : undefined
14
15
  return children ? (
15
16
  <CitricComponent tag="label" component="switch-row" style={style} className={className}>
@@ -26,4 +27,4 @@ export const Switch = ({ value, onChange, children, className, style, ...props }
26
27
  style={style}
27
28
  {...props}
28
29
  />
29
- }
30
+ })
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
3
  import { useEffect, useRef } from 'react'
4
4
  import { applyCSSVariable } from '../utils/css'
5
+ import { withRef } from '../utils/react'
5
6
  import { CitricComponent } from './CitricComponent'
6
7
 
7
8
  export interface BaseTableProps {
@@ -109,7 +110,7 @@ export type TableProps = React.JSX.IntrinsicElements['table'] & BaseTableProps
109
110
  export type ThProps = React.JSX.IntrinsicElements['th'] & BaseThProps
110
111
  export type TrProps = React.JSX.IntrinsicElements['tr'] & BaseTrProps
111
112
 
112
- export const Table = ({
113
+ export const Table = withRef(({
113
114
  appearance, stripped, compressed, showBorders, showHeaderBorders, showRowBorders, rounded, roundedRows, uppercaseHeader, className,
114
115
  children, accordionRows, ...props
115
116
  }: TableProps) => {
@@ -130,9 +131,9 @@ export const Table = ({
130
131
  {children}
131
132
  </CitricComponent>
132
133
  )
133
- }
134
+ })
134
135
 
135
- export const Th = ({ direction, onSort, children, className, ...props }: ThProps) => {
136
+ export const Th = withRef(({ direction, onSort, children, className, ...props }: ThProps) => {
136
137
  const t = useTranslate(dictionary)
137
138
  let tip: string | undefined
138
139
  const label = typeof children === 'string' ? children : undefined
@@ -158,51 +159,54 @@ export const Th = ({ direction, onSort, children, className, ...props }: ThProps
158
159
  {children}
159
160
  </th>
160
161
  )
161
- }
162
+ })
162
163
 
163
- export const Tr = ({ accordion, accordionTrigger, accordionMaxHeight, children, className, style, onClick, ...props }: TrProps) => {
164
- const ref = useRef<HTMLTableRowElement | null>(null)
164
+ export const Tr = withRef(
165
+ ({ ref: outerRef, accordion, accordionTrigger, accordionMaxHeight, children, className, style, onClick, ...props }: TrProps) => {
166
+ const innerRef = useRef<HTMLTableRowElement | null>(null)
167
+ const ref = outerRef as React.MutableRefObject<HTMLTableRowElement | null> ?? innerRef
165
168
 
166
- useEffect(() => {
167
- if (!accordion) return
168
- const checkbox = ref.current?.closest('tbody')?.querySelector('td:last-child input[aria-controls]')
169
- if (checkbox instanceof HTMLElement) {
170
- const onChange = (e: Event) => {
171
- if (!ref.current || !(e.target instanceof HTMLInputElement)) return
172
- if (e.target.checked) {
173
- ref.current.setAttribute('aria-hidden', 'false')
174
- ref.current.removeAttribute('inert')
175
- } else {
176
- ref.current.setAttribute('aria-hidden', 'true')
177
- ref.current.setAttribute('inert', 'true')
169
+ useEffect(() => {
170
+ if (!accordion) return
171
+ const checkbox = ref.current?.closest('tbody')?.querySelector('td:last-child input[aria-controls]')
172
+ if (checkbox instanceof HTMLElement) {
173
+ const onChange = (e: Event) => {
174
+ if (!ref.current || !(e.target instanceof HTMLInputElement)) return
175
+ if (e.target.checked) {
176
+ ref.current.setAttribute('aria-hidden', 'false')
177
+ ref.current.removeAttribute('inert')
178
+ } else {
179
+ ref.current.setAttribute('aria-hidden', 'true')
180
+ ref.current.setAttribute('inert', 'true')
181
+ }
178
182
  }
183
+ checkbox.addEventListener('change', onChange)
184
+ return () => checkbox.removeEventListener('change', onChange)
179
185
  }
180
- checkbox.addEventListener('change', onChange)
181
- return () => checkbox.removeEventListener('change', onChange)
182
- }
183
- }, [ref.current])
186
+ }, [ref.current])
184
187
 
185
- return (
186
- <tr
187
- ref={ref}
188
- {...props}
189
- className={listToClass([className, accordion && 'accordion', accordionTrigger === 'row' && 'clickable'])}
190
- onClick={accordionTrigger === 'row'
191
- ? (e) => {
192
- const checkbox = ref.current?.querySelector('td:last-child input[aria-controls]')
193
- if (checkbox instanceof HTMLInputElement && e.target !== checkbox) checkbox.click()
194
- onClick?.(e)
188
+ return (
189
+ <tr
190
+ ref={ref}
191
+ {...props}
192
+ className={listToClass([className, accordion && 'accordion', accordionTrigger === 'row' && 'clickable'])}
193
+ onClick={accordionTrigger === 'row'
194
+ ? (e) => {
195
+ const checkbox = ref.current?.querySelector('td:last-child input[aria-controls]')
196
+ if (checkbox instanceof HTMLInputElement && e.target !== checkbox) checkbox.click()
197
+ onClick?.(e)
198
+ }
199
+ : onClick
195
200
  }
196
- : onClick
197
- }
198
- style={applyCSSVariable(style, 'max-height', accordionMaxHeight)}
199
- aria-hidden={accordion}
200
- {...(accordion ? { inert: 'true' } : {})}
201
- >
202
- {children}
203
- </tr>
204
- )
205
- }
201
+ style={applyCSSVariable(style, 'max-height', accordionMaxHeight)}
202
+ aria-hidden={accordion}
203
+ {...(accordion ? { inert: 'true' } : {})}
204
+ >
205
+ {children}
206
+ </tr>
207
+ )
208
+ },
209
+ )
206
210
 
207
211
  const dictionary = {
208
212
  en: {
@@ -1,5 +1,6 @@
1
1
  import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
2
2
  import { createContext, Suspense, useContext, useEffect, useMemo, useState } from 'react'
3
+ import { withRef } from '../../utils/react'
3
4
  import { CitricComponent } from '../CitricComponent'
4
5
  import { ErrorBoundary } from '../ErrorBoundary'
5
6
  import { ProgressCircular } from '../ProgressCircular'
@@ -10,7 +11,7 @@ import { findSelectedIndex } from './utils'
10
11
 
11
12
  const ctx = createContext<TabController<any> | undefined>(undefined)
12
13
 
13
- export function Tabs<Key extends string>({ tabs, value, onChange, controller: ctrl, ...props }: TabsProps<Key>) {
14
+ function _Tabs<Key extends string>({ tabs, value, onChange, controller: ctrl, ...props }: TabsProps<Key>) {
14
15
  const controller = useMemo(() => ctrl ?? new TabController<Key>(tabs.map(t => t.key), value || tabs[0]?.key), [])
15
16
  const t = useTranslate(dictionary)
16
17
  const [selectedIndex, setSelectedIndex] = useState(findSelectedIndex(tabs, controller.getValue()))
@@ -62,3 +63,5 @@ const dictionary = {
62
63
  error: 'Ocorreu um erro ao carregar a aba.',
63
64
  },
64
65
  } satisfies Dictionary
66
+
67
+ export const Tabs = withRef(_Tabs)
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { createElement } from 'react'
3
3
  import { HTMLTag, TextAppearance, WithColor } from '../types'
4
4
  import { applyColor, applyTextAppearance } from '../utils/css'
5
+ import { withRef } from '../utils/react'
5
6
 
6
7
  type SupportedTags = 'span' | 'small' | 'p' | `h${1|2|3|4|5|6}` | 'pre'
7
8
 
@@ -72,7 +73,7 @@ const appearanceToTag: Record<TextAppearance, SupportedTags> = {
72
73
  subtitle4: 'p',
73
74
  }
74
75
 
75
- export function Text<T extends SupportedTags>(
76
+ function _Text<T extends SupportedTags>(
76
77
  { tag, appearance, color, showMargins, weight, align, nowrapEllipsis, style, className, children, ...props }: TextProps<T>,
77
78
  ) {
78
79
  const renderedTag = tag || appearanceToTag[appearance || 'body2']
@@ -91,3 +92,5 @@ export function Text<T extends SupportedTags>(
91
92
  children,
92
93
  )
93
94
  }
95
+
96
+ export const Text = withRef(_Text)
@@ -1,12 +1,17 @@
1
+ import React from 'react'
1
2
  import { ControlledTextarea, WithColorScheme } from '../types'
3
+ import { withRef } from '../utils/react'
2
4
  import { CitricComponent } from './CitricComponent'
3
5
 
4
6
  export interface BaseTextareaProps extends WithColorScheme {
5
7
  value?: string,
6
8
  onChange?: (value: string) => void,
9
+ ref?: React.MutableRefObject<HTMLTextAreaElement | null>,
7
10
  }
8
11
 
9
12
  export type TextareaProps = ControlledTextarea & BaseTextareaProps
10
13
 
11
- export const Textarea = ({ value, onChange, ...props }: TextareaProps) =>
14
+ export const _Textarea = ({ value, onChange, ...props }: TextareaProps) =>
12
15
  <CitricComponent tag="textarea" component="textarea" value={value} onChange={e => onChange?.(e.target.value)} {...props} />
16
+
17
+ export const Textarea = withRef(_Textarea)
@@ -2,6 +2,7 @@ import { listToClass } from '@stack-spot/portal-theme'
2
2
  import { createElement } from 'react'
3
3
  import { HTMLTag, WithStyleShortcuts } from '../types'
4
4
  import { applyStyles } from '../utils/css'
5
+ import { withRef } from '../utils/react'
5
6
 
6
7
  export const layout = {
7
8
  center: 'center',
@@ -40,14 +41,18 @@ export type CenterProps<T extends keyof HTMLTag> = HTMLTag[T] & BaseLayoutProps<
40
41
  export type RowProps<T extends keyof HTMLTag> = HTMLTag[T] & BaseRowProps<T>
41
42
  export type ColumnProps<T extends keyof HTMLTag> = HTMLTag[T] & BaseColumnProps<T>
42
43
 
43
- export function Center<T extends keyof HTMLTag = 'div'>({ tag, className, ...props }: CenterProps<T>) {
44
+ function _Center<T extends keyof HTMLTag = 'div'>({ tag, className, ...props }: CenterProps<T>) {
44
45
  return createElement(tag || 'div', { className: listToClass(['center', className]), ...applyStyles(props) })
45
46
  }
46
47
 
47
- export function Row<T extends keyof HTMLTag = 'div'>({ tag, className, center, ...props }: RowProps<T>) {
48
+ function _Row<T extends keyof HTMLTag = 'div'>({ tag, className, center, ...props }: RowProps<T>) {
48
49
  return createElement(tag || 'div', { className: listToClass(['row', center === false && 'no-center', className]), ...applyStyles(props) })
49
50
  }
50
51
 
51
- export function Column<T extends keyof HTMLTag = 'div'>({ tag, className, center, ...props }: ColumnProps<T>) {
52
+ function _Column<T extends keyof HTMLTag = 'div'>({ tag, className, center, ...props }: ColumnProps<T>) {
52
53
  return createElement(tag || 'div', { className: listToClass(['column', center && 'center', className]), ...applyStyles(props) })
53
54
  }
55
+
56
+ export const Center = withRef(_Center)
57
+ export const Row = withRef(_Row)
58
+ export const Column = withRef(_Column)
@@ -0,0 +1,6 @@
1
+ /* eslint-disable react/display-name */
2
+ import { forwardRef } from 'react'
3
+
4
+ export function withRef<T extends (...args: any[]) => any>(fc: T): T {
5
+ return forwardRef((props, ref) => fc({ ...props, ref })) as any
6
+ }