@stack-spot/citric-react 0.37.1 → 0.39.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 (189) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/citric.css +2844 -2844
  3. package/dist/components/Accordion.d.ts +1 -1
  4. package/dist/components/Accordion.js +1 -1
  5. package/dist/components/Alert.d.ts +1 -1
  6. package/dist/components/Alert.js +1 -1
  7. package/dist/components/AsyncContent.d.ts +1 -1
  8. package/dist/components/AsyncContent.js +1 -1
  9. package/dist/components/Avatar.d.ts +1 -1
  10. package/dist/components/Avatar.js +1 -1
  11. package/dist/components/AvatarGroup.d.ts +1 -1
  12. package/dist/components/AvatarGroup.js +1 -1
  13. package/dist/components/Badge.d.ts +1 -1
  14. package/dist/components/Badge.js +1 -1
  15. package/dist/components/Blockquote.d.ts +1 -1
  16. package/dist/components/Blockquote.js +1 -1
  17. package/dist/components/Breadcrumb.d.ts +1 -1
  18. package/dist/components/Breadcrumb.js +1 -1
  19. package/dist/components/Button.d.ts +1 -1
  20. package/dist/components/Button.js +1 -1
  21. package/dist/components/ButtonLink.d.ts +1 -1
  22. package/dist/components/ButtonLink.js +1 -1
  23. package/dist/components/Card.d.ts +1 -1
  24. package/dist/components/Card.js +1 -1
  25. package/dist/components/Checkbox.d.ts +1 -1
  26. package/dist/components/Checkbox.js +1 -1
  27. package/dist/components/CheckboxGroup.d.ts +1 -1
  28. package/dist/components/CheckboxGroup.d.ts.map +1 -1
  29. package/dist/components/CheckboxGroup.js +2 -2
  30. package/dist/components/CheckboxGroup.js.map +1 -1
  31. package/dist/components/Circle.d.ts +1 -1
  32. package/dist/components/Circle.js +1 -1
  33. package/dist/components/Divider.d.ts +1 -1
  34. package/dist/components/Divider.js +1 -1
  35. package/dist/components/ErrorBoundary.d.ts +1 -1
  36. package/dist/components/ErrorBoundary.js +1 -1
  37. package/dist/components/ErrorMessage.d.ts +1 -1
  38. package/dist/components/ErrorMessage.js +1 -1
  39. package/dist/components/FallbackBoundary.d.ts +1 -1
  40. package/dist/components/FallbackBoundary.js +1 -1
  41. package/dist/components/Favorite.d.ts +1 -1
  42. package/dist/components/Favorite.js +1 -1
  43. package/dist/components/FieldGroup.d.ts +1 -1
  44. package/dist/components/FieldGroup.js +1 -1
  45. package/dist/components/Form.d.ts +2 -2
  46. package/dist/components/Form.js +1 -1
  47. package/dist/components/FormGroup.d.ts +1 -1
  48. package/dist/components/FormGroup.js +1 -1
  49. package/dist/components/Icon.d.ts +1 -1
  50. package/dist/components/Icon.js +1 -1
  51. package/dist/components/IconBox.d.ts +3 -3
  52. package/dist/components/IconBox.js +1 -1
  53. package/dist/components/ImageBox.d.ts +3 -3
  54. package/dist/components/ImageBox.js +1 -1
  55. package/dist/components/ImageWithFallback.d.ts +1 -1
  56. package/dist/components/ImageWithFallback.js +1 -1
  57. package/dist/components/Input.d.ts +1 -1
  58. package/dist/components/Input.js +1 -1
  59. package/dist/components/Link.d.ts +1 -1
  60. package/dist/components/Link.js +1 -1
  61. package/dist/components/LoadingPanel.d.ts +1 -1
  62. package/dist/components/LoadingPanel.js +1 -1
  63. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  64. package/dist/components/MenuOverlay/Menu.js +1 -1
  65. package/dist/components/MenuOverlay/index.d.ts +1 -1
  66. package/dist/components/MenuOverlay/index.js +1 -1
  67. package/dist/components/Overlay/index.d.ts +4 -1
  68. package/dist/components/Overlay/index.d.ts.map +1 -1
  69. package/dist/components/Overlay/index.js +4 -1
  70. package/dist/components/Overlay/index.js.map +1 -1
  71. package/dist/components/Pagination.d.ts +1 -1
  72. package/dist/components/Pagination.js +1 -1
  73. package/dist/components/ProgressBar.d.ts +1 -1
  74. package/dist/components/ProgressBar.js +1 -1
  75. package/dist/components/ProgressCircular.d.ts +1 -1
  76. package/dist/components/ProgressCircular.js +1 -1
  77. package/dist/components/RadioGroup.d.ts +1 -1
  78. package/dist/components/RadioGroup.js +1 -1
  79. package/dist/components/Rating.d.ts +1 -1
  80. package/dist/components/Rating.js +1 -1
  81. package/dist/components/Select/MultiSelect.d.ts +1 -1
  82. package/dist/components/Select/MultiSelect.js +1 -1
  83. package/dist/components/Select/RichSelect.d.ts +1 -1
  84. package/dist/components/Select/RichSelect.js +1 -1
  85. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  86. package/dist/components/Select/SimpleSelect.js +1 -1
  87. package/dist/components/Select/index.d.ts +1 -1
  88. package/dist/components/Select/index.js +1 -1
  89. package/dist/components/SelectBox.d.ts +1 -1
  90. package/dist/components/SelectBox.js +1 -1
  91. package/dist/components/Skeleton.d.ts +1 -1
  92. package/dist/components/Skeleton.js +1 -1
  93. package/dist/components/Slider.d.ts +1 -1
  94. package/dist/components/Slider.js +1 -1
  95. package/dist/components/SmartTable.d.ts +1 -1
  96. package/dist/components/SmartTable.js +1 -1
  97. package/dist/components/Stepper.d.ts +1 -1
  98. package/dist/components/Stepper.js +1 -1
  99. package/dist/components/Table.d.ts +3 -3
  100. package/dist/components/Table.js +1 -1
  101. package/dist/components/Tabs/index.d.ts +1 -1
  102. package/dist/components/Tabs/index.js +1 -1
  103. package/dist/components/Textarea.d.ts +1 -1
  104. package/dist/components/Textarea.js +1 -1
  105. package/dist/components/Tooltip.d.ts +1 -1
  106. package/dist/components/Tooltip.js +1 -1
  107. package/dist/context/CitricProvider.d.ts +1 -1
  108. package/dist/context/CitricProvider.js +1 -1
  109. package/dist/overlay.js +1 -1
  110. package/dist/theme.css +415 -415
  111. package/package.json +2 -1
  112. package/scripts/build-css.ts +49 -49
  113. package/src/components/Accordion.tsx +130 -130
  114. package/src/components/Alert.tsx +24 -24
  115. package/src/components/AsyncContent.tsx +70 -70
  116. package/src/components/Avatar.tsx +45 -45
  117. package/src/components/AvatarGroup.tsx +49 -49
  118. package/src/components/Badge.tsx +47 -47
  119. package/src/components/Blockquote.tsx +18 -18
  120. package/src/components/Breadcrumb.tsx +33 -33
  121. package/src/components/Button.tsx +105 -105
  122. package/src/components/ButtonLink.tsx +45 -45
  123. package/src/components/Card.tsx +68 -68
  124. package/src/components/Checkbox.tsx +51 -51
  125. package/src/components/CheckboxGroup.tsx +153 -152
  126. package/src/components/Circle.tsx +43 -43
  127. package/src/components/CitricComponent.ts +47 -47
  128. package/src/components/Divider.tsx +24 -24
  129. package/src/components/ErrorBoundary.tsx +75 -75
  130. package/src/components/ErrorMessage.tsx +11 -11
  131. package/src/components/FallbackBoundary.tsx +40 -40
  132. package/src/components/Favorite.tsx +57 -57
  133. package/src/components/FieldGroup.tsx +46 -46
  134. package/src/components/Form.tsx +36 -36
  135. package/src/components/FormGroup.tsx +57 -57
  136. package/src/components/Icon.tsx +35 -35
  137. package/src/components/IconBox.tsx +134 -134
  138. package/src/components/ImageBox.tsx +125 -125
  139. package/src/components/ImageWithFallback.tsx +65 -65
  140. package/src/components/Input.tsx +49 -49
  141. package/src/components/Link.tsx +55 -55
  142. package/src/components/LoadingPanel.tsx +8 -8
  143. package/src/components/MenuOverlay/Menu.tsx +158 -158
  144. package/src/components/MenuOverlay/context.ts +20 -20
  145. package/src/components/MenuOverlay/index.tsx +55 -55
  146. package/src/components/MenuOverlay/keyboard.ts +60 -60
  147. package/src/components/MenuOverlay/types.ts +171 -171
  148. package/src/components/Overlay/context.ts +10 -10
  149. package/src/components/Overlay/index.tsx +167 -164
  150. package/src/components/Overlay/types.ts +70 -70
  151. package/src/components/Pagination.tsx +133 -133
  152. package/src/components/ProgressBar.tsx +45 -45
  153. package/src/components/ProgressCircular.tsx +45 -45
  154. package/src/components/RadioGroup.tsx +146 -146
  155. package/src/components/Rating.tsx +98 -98
  156. package/src/components/Select/MultiSelect.tsx +217 -217
  157. package/src/components/Select/RichSelect.tsx +128 -128
  158. package/src/components/Select/SimpleSelect.tsx +73 -73
  159. package/src/components/Select/hooks.ts +133 -133
  160. package/src/components/Select/index.tsx +35 -35
  161. package/src/components/Select/types.ts +134 -134
  162. package/src/components/SelectBox.tsx +167 -167
  163. package/src/components/Skeleton.tsx +53 -53
  164. package/src/components/Slider.tsx +89 -89
  165. package/src/components/SmartTable.tsx +227 -227
  166. package/src/components/Stepper.tsx +163 -163
  167. package/src/components/Table.tsx +234 -234
  168. package/src/components/Tabs/TabController.ts +54 -54
  169. package/src/components/Tabs/index.tsx +87 -87
  170. package/src/components/Tabs/types.ts +54 -54
  171. package/src/components/Tabs/utils.ts +6 -6
  172. package/src/components/Text.ts +111 -111
  173. package/src/components/Textarea.tsx +27 -27
  174. package/src/components/Tooltip.tsx +72 -72
  175. package/src/components/layout.tsx +101 -101
  176. package/src/context/CitricContext.tsx +4 -4
  177. package/src/context/CitricProvider.tsx +14 -14
  178. package/src/context/hooks.ts +6 -6
  179. package/src/index.ts +58 -58
  180. package/src/overlay.ts +341 -341
  181. package/src/types.ts +216 -216
  182. package/src/utils/ValueController.ts +28 -28
  183. package/src/utils/acessibility.ts +92 -92
  184. package/src/utils/checkbox.ts +121 -121
  185. package/src/utils/css.ts +119 -119
  186. package/src/utils/options.ts +9 -9
  187. package/src/utils/radio.ts +93 -93
  188. package/src/utils/react.ts +6 -6
  189. package/tsconfig.json +10 -10
@@ -1,234 +1,234 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
- import { useEffect, useRef } from 'react'
4
- import { applyCSSVariable } from '../utils/css'
5
- import { withRef } from '../utils/react'
6
- import { CitricComponent } from './CitricComponent'
7
-
8
- export interface BaseTableProps {
9
- /**
10
- * The overall table's appearance. Includes a default configuration for every other styling related prop.
11
- *
12
- * @default 'spaced'
13
- */
14
- appearance?: 'stripped' | 'spaced',
15
- /**
16
- * Whether or not to color each row a different color. Only valid when appearance is "spaced".
17
- *
18
- * @default false
19
- */
20
- stripped?: boolean,
21
- /**
22
- * If true, there's no spacing between rows. Only valid when appearance is "spaced".
23
- *
24
- * @default false
25
- */
26
- compressed?: boolean,
27
- /**
28
- * Shows an outer border for the whole table.
29
- *
30
- * @default "true if appearance is 'stripped', false otherwise"
31
- */
32
- showBorders?: boolean,
33
- /**
34
- * Shows borders in each of the rows.
35
- *
36
- * @default false
37
- */
38
- showRowBorders?: boolean,
39
- /**
40
- * Shows borders in the header.
41
- *
42
- * @default "false if appearance is 'stripped', true otherwise"
43
- */
44
- showHeaderBorders?: boolean,
45
- /**
46
- * Whether or not the table borders are rounded.
47
- *
48
- * @default true
49
- */
50
- rounded?: boolean,
51
- /**
52
- * Whether or not each row in the table have rounded borders.
53
- *
54
- * @default "false if appearance is 'stripped', true otherwise"
55
- */
56
- roundedRows?: boolean,
57
- /**
58
- * If true, all headers are uppercase.
59
- *
60
- * @default false
61
- */
62
- uppercaseHeader?: boolean,
63
- /**
64
- * Allows rows to act as accordions. To create an accordion row, use `<tbody>` to group two `<tr>` elements, where the first is the actual
65
- * row and the second is the collapsible content of the row. The row with the collapsible content must be defined as `<Tr accordion>`.
66
- *
67
- * @default false
68
- */
69
- accordionRows?: boolean,
70
- }
71
-
72
- export type SortingDirection = 'asc' | 'desc'
73
-
74
- interface BaseThProps {
75
- /**
76
- * Which is the current direction of the sorting? Only relevant if 'onSort' is set.
77
- *
78
- * @default 'desc'
79
- */
80
- direction?: SortingDirection,
81
- /**
82
- * What to do when the header is clicked (sorting).
83
- */
84
- onSort?: (value: SortingDirection | undefined) => void,
85
- }
86
-
87
- interface BaseTrProps {
88
- /**
89
- * True if this table is an accordion, false otherwise.
90
- *
91
- * @default false
92
- */
93
- accordion?: boolean,
94
- /**
95
- * If the next row is an accordion, what should make it expand or contract? A click on a button in the last column or a click anywhere in
96
- * the row?
97
- *
98
- * @default 'button'
99
- */
100
- accordionTrigger?: 'button' | 'row',
101
- /**
102
- * Sets the maximum height of this accordion. Only valid if `accordion` is true.
103
- *
104
- * @default '200px'
105
- */
106
- accordionMaxHeight?: string,
107
- }
108
-
109
- export type TableProps = React.JSX.IntrinsicElements['table'] & BaseTableProps
110
- export type ThProps = React.JSX.IntrinsicElements['th'] & BaseThProps
111
- export type TrProps = React.JSX.IntrinsicElements['tr'] & BaseTrProps
112
-
113
- /**
114
- * Renders an HTML table. Use its props for customizing the appearance.
115
- *
116
- * - If you need to use Accordion rows, use `<Tr>`instead of `<tr>`.
117
- * - If you need to sort columns, use `<Th>`instead of `<th>`.
118
- *
119
- * This works exactly like the HTML tag "table".
120
- *
121
- * Attention: prefer using the component "SmartTable". Use this only if you need full control over the table.
122
- */
123
- export const Table = withRef(({
124
- appearance, stripped, compressed, showBorders, showHeaderBorders, showRowBorders, rounded, roundedRows, uppercaseHeader, className,
125
- children, accordionRows, ...props
126
- }: TableProps) => {
127
- const classes = listToClass([
128
- className,
129
- stripped && 'stripped',
130
- compressed && 'compressed',
131
- showBorders && 'bordered',
132
- showHeaderBorders === false && 'borderless-header',
133
- showRowBorders && 'bordered-rows',
134
- rounded === false && 'square',
135
- roundedRows === false && 'square-rows',
136
- uppercaseHeader && 'uppercase-header',
137
- accordionRows && 'accordion-rows',
138
- ])
139
- return (
140
- <CitricComponent tag="table" component="table" data-appearance={appearance} className={classes} {...props}>
141
- {children}
142
- </CitricComponent>
143
- )
144
- })
145
-
146
- export const Th = withRef(({ direction, onSort, children, className, ...props }: ThProps) => {
147
- const t = useTranslate(dictionary)
148
- let tip: string | undefined
149
- const label = typeof children === 'string' ? children : undefined
150
- if (onSort && !direction) tip = label ? `${label}. ${t.sortAscending}` : t.sortAscending
151
- if (onSort && direction === 'asc') tip = label ? `${label}. ${t.sortDescending}` : t.sortDescending
152
- if (onSort && direction === 'desc') tip = label ? `${label}. ${t.sortNone}` : t.sortNone
153
-
154
- function handleSort() {
155
- if (!direction) onSort?.('asc')
156
- else if (direction === 'asc') onSort?.('desc')
157
- else onSort?.(undefined)
158
- }
159
-
160
- return (
161
- <th
162
- className={listToClass([onSort && 'sortable', direction, className])}
163
- onClick={onSort? handleSort : undefined}
164
- onKeyDown={onSort ? (e => e.key === 'Enter' && handleSort()) : undefined}
165
- aria-label={tip}
166
- tabIndex={onSort ? 0 : undefined}
167
- {...props}
168
- >
169
- {children}
170
- </th>
171
- )
172
- })
173
-
174
- export const Tr = withRef(
175
- ({
176
- ref: outerRef, accordion, accordionTrigger, accordionMaxHeight, children, className, style, onClick, ...props
177
- }: TrProps) => {
178
- const innerRef = useRef<HTMLTableRowElement | null>(null)
179
- const ref = outerRef as React.MutableRefObject<HTMLTableRowElement | null> ?? innerRef
180
-
181
- useEffect(() => {
182
- if (!accordion) return
183
- const checkbox = ref.current?.closest('tbody')?.querySelector('td:last-child input[aria-controls]')
184
- if (checkbox instanceof HTMLElement) {
185
- const onChange = (e: Event) => {
186
- if (!ref.current || !(e.target instanceof HTMLInputElement)) return
187
- if (e.target.checked) {
188
- ref.current.setAttribute('aria-hidden', 'false')
189
- ref.current.removeAttribute('inert')
190
- } else {
191
- ref.current.setAttribute('aria-hidden', 'true')
192
- ref.current.setAttribute('inert', 'true')
193
- }
194
- }
195
- checkbox.addEventListener('change', onChange)
196
- return () => checkbox.removeEventListener('change', onChange)
197
- }
198
- }, [ref.current])
199
-
200
- return (
201
- <tr
202
- ref={ref}
203
- {...props}
204
- className={listToClass([className, accordion && 'accordion', (accordionTrigger === 'row' || onClick) && 'clickable'])}
205
- onClick={accordionTrigger === 'row'
206
- ? (e) => {
207
- const checkbox = ref.current?.querySelector('td:last-child input[aria-controls]')
208
- if (checkbox instanceof HTMLInputElement && e.target !== checkbox) checkbox.click()
209
- onClick?.(e)
210
- }
211
- : onClick
212
- }
213
- style={applyCSSVariable(style, 'max-height', accordionMaxHeight)}
214
- aria-hidden={accordion}
215
- {...(accordion ? { inert: 'true' } : {})}
216
- >
217
- {children}
218
- </tr>
219
- )
220
- },
221
- )
222
-
223
- const dictionary = {
224
- en: {
225
- sortAscending: 'Click to sort in ascending order.',
226
- sortDescending: 'Click to sort in descending order.',
227
- sortNone: 'Click to remove sorting.',
228
- },
229
- pt: {
230
- sortAscending: 'Clique para ordenar em ordem crescente.',
231
- sortDescending: 'Clique para ordenar em ordem decrescente.',
232
- sortNone: 'Clique para remover a ordenação.',
233
- },
234
- } satisfies Dictionary
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
3
+ import { useEffect, useRef } from 'react'
4
+ import { applyCSSVariable } from '../utils/css'
5
+ import { withRef } from '../utils/react'
6
+ import { CitricComponent } from './CitricComponent'
7
+
8
+ export interface BaseTableProps {
9
+ /**
10
+ * The overall table's appearance. Includes a default configuration for every other styling related prop.
11
+ *
12
+ * @default 'spaced'
13
+ */
14
+ appearance?: 'stripped' | 'spaced',
15
+ /**
16
+ * Whether or not to color each row a different color. Only valid when appearance is "spaced".
17
+ *
18
+ * @default false
19
+ */
20
+ stripped?: boolean,
21
+ /**
22
+ * If true, there's no spacing between rows. Only valid when appearance is "spaced".
23
+ *
24
+ * @default false
25
+ */
26
+ compressed?: boolean,
27
+ /**
28
+ * Shows an outer border for the whole table.
29
+ *
30
+ * @default "true if appearance is 'stripped', false otherwise"
31
+ */
32
+ showBorders?: boolean,
33
+ /**
34
+ * Shows borders in each of the rows.
35
+ *
36
+ * @default false
37
+ */
38
+ showRowBorders?: boolean,
39
+ /**
40
+ * Shows borders in the header.
41
+ *
42
+ * @default "false if appearance is 'stripped', true otherwise"
43
+ */
44
+ showHeaderBorders?: boolean,
45
+ /**
46
+ * Whether or not the table borders are rounded.
47
+ *
48
+ * @default true
49
+ */
50
+ rounded?: boolean,
51
+ /**
52
+ * Whether or not each row in the table have rounded borders.
53
+ *
54
+ * @default "false if appearance is 'stripped', true otherwise"
55
+ */
56
+ roundedRows?: boolean,
57
+ /**
58
+ * If true, all headers are uppercase.
59
+ *
60
+ * @default false
61
+ */
62
+ uppercaseHeader?: boolean,
63
+ /**
64
+ * Allows rows to act as accordions. To create an accordion row, use `<tbody>` to group two `<tr>` elements, where the first is the actual
65
+ * row and the second is the collapsible content of the row. The row with the collapsible content must be defined as `<Tr accordion>`.
66
+ *
67
+ * @default false
68
+ */
69
+ accordionRows?: boolean,
70
+ }
71
+
72
+ export type SortingDirection = 'asc' | 'desc'
73
+
74
+ interface BaseThProps {
75
+ /**
76
+ * Which is the current direction of the sorting? Only relevant if 'onSort' is set.
77
+ *
78
+ * @default 'desc'
79
+ */
80
+ direction?: SortingDirection,
81
+ /**
82
+ * What to do when the header is clicked (sorting).
83
+ */
84
+ onSort?: (value: SortingDirection | undefined) => void,
85
+ }
86
+
87
+ interface BaseTrProps {
88
+ /**
89
+ * True if this table is an accordion, false otherwise.
90
+ *
91
+ * @default false
92
+ */
93
+ accordion?: boolean,
94
+ /**
95
+ * If the next row is an accordion, what should make it expand or contract? A click on a button in the last column or a click anywhere in
96
+ * the row?
97
+ *
98
+ * @default 'button'
99
+ */
100
+ accordionTrigger?: 'button' | 'row',
101
+ /**
102
+ * Sets the maximum height of this accordion. Only valid if `accordion` is true.
103
+ *
104
+ * @default '200px'
105
+ */
106
+ accordionMaxHeight?: string,
107
+ }
108
+
109
+ export type TableProps = React.JSX.IntrinsicElements['table'] & BaseTableProps
110
+ export type ThProps = React.JSX.IntrinsicElements['th'] & BaseThProps
111
+ export type TrProps = React.JSX.IntrinsicElements['tr'] & BaseTrProps
112
+
113
+ /**
114
+ * Renders an HTML table. Use its props for customizing the appearance.
115
+ *
116
+ * - If you need to use Accordion rows, use `<Tr>`instead of `<tr>`.
117
+ * - If you need to sort columns, use `<Th>`instead of `<th>`.
118
+ *
119
+ * This works exactly like the HTML tag "table".
120
+ *
121
+ * Attention: prefer using the component "SmartTable". Use this only if you need full control over the table.
122
+ */
123
+ export const Table = withRef(({
124
+ appearance, stripped, compressed, showBorders, showHeaderBorders, showRowBorders, rounded, roundedRows, uppercaseHeader, className,
125
+ children, accordionRows, ...props
126
+ }: TableProps) => {
127
+ const classes = listToClass([
128
+ className,
129
+ stripped && 'stripped',
130
+ compressed && 'compressed',
131
+ showBorders && 'bordered',
132
+ showHeaderBorders === false && 'borderless-header',
133
+ showRowBorders && 'bordered-rows',
134
+ rounded === false && 'square',
135
+ roundedRows === false && 'square-rows',
136
+ uppercaseHeader && 'uppercase-header',
137
+ accordionRows && 'accordion-rows',
138
+ ])
139
+ return (
140
+ <CitricComponent tag="table" component="table" data-appearance={appearance} className={classes} {...props}>
141
+ {children}
142
+ </CitricComponent>
143
+ )
144
+ })
145
+
146
+ export const Th = withRef(({ direction, onSort, children, className, ...props }: ThProps) => {
147
+ const t = useTranslate(dictionary)
148
+ let tip: string | undefined
149
+ const label = typeof children === 'string' ? children : undefined
150
+ if (onSort && !direction) tip = label ? `${label}. ${t.sortAscending}` : t.sortAscending
151
+ if (onSort && direction === 'asc') tip = label ? `${label}. ${t.sortDescending}` : t.sortDescending
152
+ if (onSort && direction === 'desc') tip = label ? `${label}. ${t.sortNone}` : t.sortNone
153
+
154
+ function handleSort() {
155
+ if (!direction) onSort?.('asc')
156
+ else if (direction === 'asc') onSort?.('desc')
157
+ else onSort?.(undefined)
158
+ }
159
+
160
+ return (
161
+ <th
162
+ className={listToClass([onSort && 'sortable', direction, className])}
163
+ onClick={onSort? handleSort : undefined}
164
+ onKeyDown={onSort ? (e => e.key === 'Enter' && handleSort()) : undefined}
165
+ aria-label={tip}
166
+ tabIndex={onSort ? 0 : undefined}
167
+ {...props}
168
+ >
169
+ {children}
170
+ </th>
171
+ )
172
+ })
173
+
174
+ export const Tr = withRef(
175
+ ({
176
+ ref: outerRef, accordion, accordionTrigger, accordionMaxHeight, children, className, style, onClick, ...props
177
+ }: TrProps) => {
178
+ const innerRef = useRef<HTMLTableRowElement | null>(null)
179
+ const ref = outerRef as React.MutableRefObject<HTMLTableRowElement | null> ?? innerRef
180
+
181
+ useEffect(() => {
182
+ if (!accordion) return
183
+ const checkbox = ref.current?.closest('tbody')?.querySelector('td:last-child input[aria-controls]')
184
+ if (checkbox instanceof HTMLElement) {
185
+ const onChange = (e: Event) => {
186
+ if (!ref.current || !(e.target instanceof HTMLInputElement)) return
187
+ if (e.target.checked) {
188
+ ref.current.setAttribute('aria-hidden', 'false')
189
+ ref.current.removeAttribute('inert')
190
+ } else {
191
+ ref.current.setAttribute('aria-hidden', 'true')
192
+ ref.current.setAttribute('inert', 'true')
193
+ }
194
+ }
195
+ checkbox.addEventListener('change', onChange)
196
+ return () => checkbox.removeEventListener('change', onChange)
197
+ }
198
+ }, [ref.current])
199
+
200
+ return (
201
+ <tr
202
+ ref={ref}
203
+ {...props}
204
+ className={listToClass([className, accordion && 'accordion', (accordionTrigger === 'row' || onClick) && 'clickable'])}
205
+ onClick={accordionTrigger === 'row'
206
+ ? (e) => {
207
+ const checkbox = ref.current?.querySelector('td:last-child input[aria-controls]')
208
+ if (checkbox instanceof HTMLInputElement && e.target !== checkbox) checkbox.click()
209
+ onClick?.(e)
210
+ }
211
+ : onClick
212
+ }
213
+ style={applyCSSVariable(style, 'max-height', accordionMaxHeight)}
214
+ aria-hidden={accordion}
215
+ {...(accordion ? { inert: 'true' } : {})}
216
+ >
217
+ {children}
218
+ </tr>
219
+ )
220
+ },
221
+ )
222
+
223
+ const dictionary = {
224
+ en: {
225
+ sortAscending: 'Click to sort in ascending order.',
226
+ sortDescending: 'Click to sort in descending order.',
227
+ sortNone: 'Click to remove sorting.',
228
+ },
229
+ pt: {
230
+ sortAscending: 'Clique para ordenar em ordem crescente.',
231
+ sortDescending: 'Clique para ordenar em ordem decrescente.',
232
+ sortNone: 'Clique para remover a ordenação.',
233
+ },
234
+ } satisfies Dictionary
@@ -1,54 +1,54 @@
1
- import { ValueController } from '../../utils/ValueController'
2
-
3
- export class TabController<Key extends string> extends ValueController<Key> {
4
- private tabOrder: Key[]
5
-
6
- constructor(tabOrder: Key[], value: Key) {
7
- super(value)
8
- this.tabOrder = tabOrder
9
- }
10
-
11
- private getCurrentIndex() {
12
- return this.tabOrder.findIndex(t => t === this.value)
13
- }
14
-
15
- /**
16
- * @returns true if there's another tab after the one currently selected. False otherwise.
17
- */
18
- hasNext(): boolean {
19
- const current = this.getCurrentIndex()
20
- return current > -1 && current + 1 < this.tabOrder.length
21
- }
22
-
23
- /**
24
- * @returns true if there's a tab before the one currently selected. False otherwise.
25
- */
26
- hasPrevious(): boolean {
27
- const current = this.getCurrentIndex()
28
- return current > -1 && current - 1 >= 0
29
- }
30
-
31
- /**
32
- * Selects the tab on the right of the one currently selected. If there's no next tab, nothing happens.
33
- * @returns true if the tab is changed, false otherwise.
34
- */
35
- next(): boolean {
36
- if (this.hasNext()) {
37
- this.setValue(this.tabOrder[this.getCurrentIndex() + 1])
38
- return true
39
- }
40
- return false
41
- }
42
-
43
- /**
44
- * Selects the tab on the left of the one currently selected. If there's no previous tab, nothing happens.
45
- * @returns true if the tab is changed, false otherwise.
46
- */
47
- previous(): boolean {
48
- if (this.hasPrevious()) {
49
- this.setValue(this.tabOrder[this.getCurrentIndex() - 1])
50
- return true
51
- }
52
- return false
53
- }
54
- }
1
+ import { ValueController } from '../../utils/ValueController'
2
+
3
+ export class TabController<Key extends string> extends ValueController<Key> {
4
+ private tabOrder: Key[]
5
+
6
+ constructor(tabOrder: Key[], value: Key) {
7
+ super(value)
8
+ this.tabOrder = tabOrder
9
+ }
10
+
11
+ private getCurrentIndex() {
12
+ return this.tabOrder.findIndex(t => t === this.value)
13
+ }
14
+
15
+ /**
16
+ * @returns true if there's another tab after the one currently selected. False otherwise.
17
+ */
18
+ hasNext(): boolean {
19
+ const current = this.getCurrentIndex()
20
+ return current > -1 && current + 1 < this.tabOrder.length
21
+ }
22
+
23
+ /**
24
+ * @returns true if there's a tab before the one currently selected. False otherwise.
25
+ */
26
+ hasPrevious(): boolean {
27
+ const current = this.getCurrentIndex()
28
+ return current > -1 && current - 1 >= 0
29
+ }
30
+
31
+ /**
32
+ * Selects the tab on the right of the one currently selected. If there's no next tab, nothing happens.
33
+ * @returns true if the tab is changed, false otherwise.
34
+ */
35
+ next(): boolean {
36
+ if (this.hasNext()) {
37
+ this.setValue(this.tabOrder[this.getCurrentIndex() + 1])
38
+ return true
39
+ }
40
+ return false
41
+ }
42
+
43
+ /**
44
+ * Selects the tab on the left of the one currently selected. If there's no previous tab, nothing happens.
45
+ * @returns true if the tab is changed, false otherwise.
46
+ */
47
+ previous(): boolean {
48
+ if (this.hasPrevious()) {
49
+ this.setValue(this.tabOrder[this.getCurrentIndex() - 1])
50
+ return true
51
+ }
52
+ return false
53
+ }
54
+ }