@stack-spot/citric-react 0.36.0 → 0.37.1-beta.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 (186) hide show
  1. package/dist/citric.css +2844 -2832
  2. package/dist/components/Accordion.d.ts +1 -1
  3. package/dist/components/Accordion.js +1 -1
  4. package/dist/components/Alert.d.ts +1 -1
  5. package/dist/components/Alert.js +1 -1
  6. package/dist/components/AsyncContent.d.ts +1 -1
  7. package/dist/components/AsyncContent.js +1 -1
  8. package/dist/components/Avatar.d.ts +1 -1
  9. package/dist/components/Avatar.js +1 -1
  10. package/dist/components/AvatarGroup.d.ts +1 -1
  11. package/dist/components/AvatarGroup.js +1 -1
  12. package/dist/components/Badge.d.ts +1 -1
  13. package/dist/components/Badge.js +1 -1
  14. package/dist/components/Blockquote.d.ts +1 -1
  15. package/dist/components/Blockquote.js +1 -1
  16. package/dist/components/Breadcrumb.d.ts +1 -1
  17. package/dist/components/Breadcrumb.js +1 -1
  18. package/dist/components/Button.d.ts +1 -1
  19. package/dist/components/Button.js +1 -1
  20. package/dist/components/ButtonLink.d.ts +1 -1
  21. package/dist/components/ButtonLink.js +1 -1
  22. package/dist/components/Card.d.ts +1 -1
  23. package/dist/components/Card.js +1 -1
  24. package/dist/components/Checkbox.d.ts +1 -1
  25. package/dist/components/Checkbox.js +1 -1
  26. package/dist/components/CheckboxGroup.d.ts +1 -1
  27. package/dist/components/CheckboxGroup.js +1 -1
  28. package/dist/components/Circle.d.ts +1 -1
  29. package/dist/components/Circle.js +1 -1
  30. package/dist/components/Divider.d.ts +1 -1
  31. package/dist/components/Divider.js +1 -1
  32. package/dist/components/ErrorBoundary.d.ts +1 -1
  33. package/dist/components/ErrorBoundary.js +1 -1
  34. package/dist/components/ErrorMessage.d.ts +1 -1
  35. package/dist/components/ErrorMessage.js +1 -1
  36. package/dist/components/FallbackBoundary.d.ts +1 -1
  37. package/dist/components/FallbackBoundary.js +1 -1
  38. package/dist/components/Favorite.d.ts +1 -1
  39. package/dist/components/Favorite.js +1 -1
  40. package/dist/components/FieldGroup.d.ts +1 -1
  41. package/dist/components/FieldGroup.js +1 -1
  42. package/dist/components/Form.d.ts +2 -2
  43. package/dist/components/Form.js +1 -1
  44. package/dist/components/FormGroup.d.ts +1 -1
  45. package/dist/components/FormGroup.js +1 -1
  46. package/dist/components/Icon.d.ts +1 -1
  47. package/dist/components/Icon.js +1 -1
  48. package/dist/components/IconBox.d.ts +3 -3
  49. package/dist/components/IconBox.js +1 -1
  50. package/dist/components/ImageBox.d.ts +3 -3
  51. package/dist/components/ImageBox.js +1 -1
  52. package/dist/components/ImageWithFallback.d.ts +1 -1
  53. package/dist/components/ImageWithFallback.js +1 -1
  54. package/dist/components/Input.d.ts +1 -1
  55. package/dist/components/Input.js +1 -1
  56. package/dist/components/Link.d.ts +1 -1
  57. package/dist/components/Link.js +1 -1
  58. package/dist/components/LoadingPanel.d.ts +1 -1
  59. package/dist/components/LoadingPanel.js +1 -1
  60. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  61. package/dist/components/MenuOverlay/Menu.js +1 -1
  62. package/dist/components/MenuOverlay/index.d.ts +1 -1
  63. package/dist/components/MenuOverlay/index.js +1 -1
  64. package/dist/components/Overlay/index.d.ts +1 -1
  65. package/dist/components/Overlay/index.js +1 -1
  66. package/dist/components/Pagination.d.ts +1 -1
  67. package/dist/components/Pagination.js +1 -1
  68. package/dist/components/ProgressBar.d.ts +1 -1
  69. package/dist/components/ProgressBar.js +1 -1
  70. package/dist/components/ProgressCircular.d.ts +1 -1
  71. package/dist/components/ProgressCircular.js +1 -1
  72. package/dist/components/RadioGroup.d.ts +1 -1
  73. package/dist/components/RadioGroup.js +1 -1
  74. package/dist/components/Rating.d.ts +17 -3
  75. package/dist/components/Rating.d.ts.map +1 -1
  76. package/dist/components/Rating.js +11 -3
  77. package/dist/components/Rating.js.map +1 -1
  78. package/dist/components/Select/MultiSelect.d.ts +1 -1
  79. package/dist/components/Select/MultiSelect.js +1 -1
  80. package/dist/components/Select/RichSelect.d.ts +1 -1
  81. package/dist/components/Select/RichSelect.js +1 -1
  82. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  83. package/dist/components/Select/SimpleSelect.js +1 -1
  84. package/dist/components/Select/index.d.ts +1 -1
  85. package/dist/components/Select/index.js +1 -1
  86. package/dist/components/SelectBox.d.ts +1 -1
  87. package/dist/components/SelectBox.js +1 -1
  88. package/dist/components/Skeleton.d.ts +1 -1
  89. package/dist/components/Skeleton.js +1 -1
  90. package/dist/components/Slider.d.ts +1 -1
  91. package/dist/components/Slider.js +1 -1
  92. package/dist/components/SmartTable.d.ts +1 -1
  93. package/dist/components/SmartTable.js +1 -1
  94. package/dist/components/Stepper.d.ts +1 -1
  95. package/dist/components/Stepper.js +1 -1
  96. package/dist/components/Table.d.ts +3 -3
  97. package/dist/components/Table.js +1 -1
  98. package/dist/components/Tabs/index.d.ts +1 -1
  99. package/dist/components/Tabs/index.js +1 -1
  100. package/dist/components/Textarea.d.ts +1 -1
  101. package/dist/components/Textarea.js +1 -1
  102. package/dist/components/Tooltip.d.ts +1 -1
  103. package/dist/components/Tooltip.js +1 -1
  104. package/dist/context/CitricProvider.d.ts +1 -1
  105. package/dist/context/CitricProvider.js +1 -1
  106. package/dist/overlay.js +1 -1
  107. package/dist/theme.css +415 -415
  108. package/package.json +2 -2
  109. package/scripts/build-css.ts +49 -49
  110. package/src/components/Accordion.tsx +130 -130
  111. package/src/components/Alert.tsx +24 -24
  112. package/src/components/AsyncContent.tsx +70 -70
  113. package/src/components/Avatar.tsx +45 -45
  114. package/src/components/AvatarGroup.tsx +49 -49
  115. package/src/components/Badge.tsx +47 -47
  116. package/src/components/Blockquote.tsx +18 -18
  117. package/src/components/Breadcrumb.tsx +33 -33
  118. package/src/components/Button.tsx +105 -105
  119. package/src/components/ButtonLink.tsx +45 -45
  120. package/src/components/Card.tsx +68 -68
  121. package/src/components/Checkbox.tsx +51 -51
  122. package/src/components/CheckboxGroup.tsx +152 -152
  123. package/src/components/Circle.tsx +43 -43
  124. package/src/components/CitricComponent.ts +47 -47
  125. package/src/components/Divider.tsx +24 -24
  126. package/src/components/ErrorBoundary.tsx +75 -75
  127. package/src/components/ErrorMessage.tsx +11 -11
  128. package/src/components/FallbackBoundary.tsx +40 -40
  129. package/src/components/Favorite.tsx +57 -57
  130. package/src/components/FieldGroup.tsx +46 -46
  131. package/src/components/Form.tsx +36 -36
  132. package/src/components/FormGroup.tsx +57 -57
  133. package/src/components/Icon.tsx +35 -35
  134. package/src/components/IconBox.tsx +134 -134
  135. package/src/components/ImageBox.tsx +125 -125
  136. package/src/components/ImageWithFallback.tsx +65 -65
  137. package/src/components/Input.tsx +49 -49
  138. package/src/components/Link.tsx +55 -55
  139. package/src/components/LoadingPanel.tsx +8 -8
  140. package/src/components/MenuOverlay/Menu.tsx +158 -158
  141. package/src/components/MenuOverlay/context.ts +20 -20
  142. package/src/components/MenuOverlay/index.tsx +55 -55
  143. package/src/components/MenuOverlay/keyboard.ts +60 -60
  144. package/src/components/MenuOverlay/types.ts +171 -171
  145. package/src/components/Overlay/context.ts +10 -10
  146. package/src/components/Overlay/index.tsx +164 -164
  147. package/src/components/Overlay/types.ts +70 -70
  148. package/src/components/Pagination.tsx +113 -113
  149. package/src/components/ProgressBar.tsx +45 -45
  150. package/src/components/ProgressCircular.tsx +45 -45
  151. package/src/components/RadioGroup.tsx +146 -146
  152. package/src/components/Rating.tsx +98 -35
  153. package/src/components/Select/MultiSelect.tsx +346 -217
  154. package/src/components/Select/RichSelect.tsx +128 -128
  155. package/src/components/Select/SimpleSelect.tsx +73 -73
  156. package/src/components/Select/hooks.ts +133 -133
  157. package/src/components/Select/index.tsx +35 -35
  158. package/src/components/Select/types.ts +134 -134
  159. package/src/components/SelectBox.tsx +167 -167
  160. package/src/components/Skeleton.tsx +53 -53
  161. package/src/components/Slider.tsx +89 -89
  162. package/src/components/SmartTable.tsx +227 -227
  163. package/src/components/Stepper.tsx +163 -163
  164. package/src/components/Table.tsx +234 -234
  165. package/src/components/Tabs/TabController.ts +54 -54
  166. package/src/components/Tabs/index.tsx +87 -87
  167. package/src/components/Tabs/types.ts +54 -54
  168. package/src/components/Tabs/utils.ts +6 -6
  169. package/src/components/Text.ts +111 -111
  170. package/src/components/Textarea.tsx +27 -27
  171. package/src/components/Tooltip.tsx +72 -72
  172. package/src/components/layout.tsx +101 -101
  173. package/src/context/CitricContext.tsx +4 -4
  174. package/src/context/CitricProvider.tsx +14 -14
  175. package/src/context/hooks.ts +6 -6
  176. package/src/index.ts +58 -58
  177. package/src/overlay.ts +341 -341
  178. package/src/types.ts +216 -216
  179. package/src/utils/ValueController.ts +28 -28
  180. package/src/utils/acessibility.ts +92 -92
  181. package/src/utils/checkbox.ts +121 -121
  182. package/src/utils/css.ts +119 -119
  183. package/src/utils/options.ts +9 -9
  184. package/src/utils/radio.ts +93 -93
  185. package/src/utils/react.ts +6 -6
  186. 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
+ }