@stack-spot/citric-react 0.42.0-beta.0 → 0.43.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 (209) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/citric.css +2926 -2920
  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/Autocomplete.d.ts +370 -0
  10. package/dist/components/Autocomplete.d.ts.map +1 -0
  11. package/dist/components/{Autocomplete/Autocomplete.js → Autocomplete.js} +163 -98
  12. package/dist/components/Autocomplete.js.map +1 -0
  13. package/dist/components/Avatar.d.ts +1 -1
  14. package/dist/components/Avatar.js +1 -1
  15. package/dist/components/AvatarGroup.d.ts +1 -1
  16. package/dist/components/AvatarGroup.js +1 -1
  17. package/dist/components/Badge.d.ts +1 -1
  18. package/dist/components/Badge.js +1 -1
  19. package/dist/components/Blockquote.d.ts +1 -1
  20. package/dist/components/Blockquote.js +1 -1
  21. package/dist/components/Breadcrumb.d.ts +1 -1
  22. package/dist/components/Breadcrumb.js +1 -1
  23. package/dist/components/Button.d.ts +1 -1
  24. package/dist/components/Button.js +1 -1
  25. package/dist/components/ButtonLink.d.ts +1 -1
  26. package/dist/components/ButtonLink.js +1 -1
  27. package/dist/components/Card.d.ts +1 -1
  28. package/dist/components/Card.js +1 -1
  29. package/dist/components/Checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox.js +2 -2
  32. package/dist/components/Checkbox.js.map +1 -1
  33. package/dist/components/CheckboxGroup.d.ts +1 -1
  34. package/dist/components/CheckboxGroup.js +1 -1
  35. package/dist/components/Circle.d.ts +1 -1
  36. package/dist/components/Circle.js +1 -1
  37. package/dist/components/Divider.d.ts +1 -1
  38. package/dist/components/Divider.js +1 -1
  39. package/dist/components/ErrorBoundary.d.ts +1 -1
  40. package/dist/components/ErrorBoundary.js +1 -1
  41. package/dist/components/ErrorMessage.d.ts +1 -1
  42. package/dist/components/ErrorMessage.js +1 -1
  43. package/dist/components/FallbackBoundary.d.ts +1 -1
  44. package/dist/components/FallbackBoundary.js +1 -1
  45. package/dist/components/Favorite.d.ts +1 -1
  46. package/dist/components/Favorite.js +1 -1
  47. package/dist/components/FieldGroup.d.ts +1 -1
  48. package/dist/components/FieldGroup.js +1 -1
  49. package/dist/components/Form.d.ts +2 -2
  50. package/dist/components/Form.js +1 -1
  51. package/dist/components/FormGroup.d.ts +1 -1
  52. package/dist/components/FormGroup.js +1 -1
  53. package/dist/components/Icon.d.ts +1 -1
  54. package/dist/components/Icon.js +1 -1
  55. package/dist/components/IconBox.d.ts +3 -3
  56. package/dist/components/IconBox.js +1 -1
  57. package/dist/components/ImageBox.d.ts +3 -3
  58. package/dist/components/ImageBox.js +1 -1
  59. package/dist/components/ImageWithFallback.d.ts +1 -1
  60. package/dist/components/ImageWithFallback.js +1 -1
  61. package/dist/components/Input.d.ts +1 -1
  62. package/dist/components/Input.js +1 -1
  63. package/dist/components/Link.d.ts +1 -1
  64. package/dist/components/Link.js +1 -1
  65. package/dist/components/LoadingPanel.d.ts +1 -1
  66. package/dist/components/LoadingPanel.js +1 -1
  67. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  68. package/dist/components/MenuOverlay/Menu.js +1 -1
  69. package/dist/components/MenuOverlay/index.d.ts +1 -1
  70. package/dist/components/MenuOverlay/index.js +1 -1
  71. package/dist/components/Overlay/index.d.ts +1 -1
  72. package/dist/components/Overlay/index.js +1 -1
  73. package/dist/components/Pagination.d.ts +1 -1
  74. package/dist/components/Pagination.js +1 -1
  75. package/dist/components/ProgressBar.d.ts +1 -1
  76. package/dist/components/ProgressBar.js +1 -1
  77. package/dist/components/ProgressCircular.d.ts +1 -1
  78. package/dist/components/ProgressCircular.js +1 -1
  79. package/dist/components/RadioGroup.d.ts +1 -1
  80. package/dist/components/RadioGroup.js +1 -1
  81. package/dist/components/Rating.d.ts +1 -1
  82. package/dist/components/Rating.js +1 -1
  83. package/dist/components/Select/MultiSelect.d.ts +1 -1
  84. package/dist/components/Select/MultiSelect.js +1 -1
  85. package/dist/components/Select/RichSelect.d.ts +1 -1
  86. package/dist/components/Select/RichSelect.js +1 -1
  87. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  88. package/dist/components/Select/SimpleSelect.js +1 -1
  89. package/dist/components/Select/index.d.ts +1 -1
  90. package/dist/components/Select/index.js +1 -1
  91. package/dist/components/SelectBox.d.ts +9 -1
  92. package/dist/components/SelectBox.d.ts.map +1 -1
  93. package/dist/components/SelectBox.js +6 -5
  94. package/dist/components/SelectBox.js.map +1 -1
  95. package/dist/components/Skeleton.d.ts +1 -1
  96. package/dist/components/Skeleton.js +1 -1
  97. package/dist/components/Slider.d.ts +1 -1
  98. package/dist/components/Slider.js +1 -1
  99. package/dist/components/SmartTable.d.ts +1 -1
  100. package/dist/components/SmartTable.js +1 -1
  101. package/dist/components/Stepper.d.ts +1 -1
  102. package/dist/components/Stepper.js +1 -1
  103. package/dist/components/Table.d.ts +3 -3
  104. package/dist/components/Table.js +1 -1
  105. package/dist/components/Tabs/index.d.ts +1 -1
  106. package/dist/components/Tabs/index.js +1 -1
  107. package/dist/components/Textarea.d.ts +1 -1
  108. package/dist/components/Textarea.js +1 -1
  109. package/dist/components/Tooltip.d.ts +1 -1
  110. package/dist/components/Tooltip.js +1 -1
  111. package/dist/context/CitricProvider.d.ts +1 -1
  112. package/dist/context/CitricProvider.js +1 -1
  113. package/dist/index.d.ts +2 -1
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +2 -1
  116. package/dist/index.js.map +1 -1
  117. package/dist/overlay.js +1 -1
  118. package/dist/theme.css +415 -415
  119. package/dist/utils/css.js +1 -1
  120. package/dist/utils/css.js.map +1 -1
  121. package/package.json +1 -1
  122. package/scripts/build-css.ts +49 -49
  123. package/src/components/Accordion.tsx +130 -130
  124. package/src/components/Alert.tsx +24 -24
  125. package/src/components/AsyncContent.tsx +75 -75
  126. package/src/components/{Autocomplete/Autocomplete.tsx → Autocomplete.tsx} +403 -159
  127. package/src/components/Avatar.tsx +45 -45
  128. package/src/components/AvatarGroup.tsx +49 -49
  129. package/src/components/Badge.tsx +47 -47
  130. package/src/components/Blockquote.tsx +18 -18
  131. package/src/components/Breadcrumb.tsx +33 -33
  132. package/src/components/Button.tsx +105 -105
  133. package/src/components/ButtonLink.tsx +45 -45
  134. package/src/components/Card.tsx +68 -68
  135. package/src/components/Checkbox.tsx +51 -52
  136. package/src/components/CheckboxGroup.tsx +153 -153
  137. package/src/components/Circle.tsx +43 -43
  138. package/src/components/CitricComponent.ts +47 -47
  139. package/src/components/Divider.tsx +24 -24
  140. package/src/components/ErrorBoundary.tsx +75 -75
  141. package/src/components/ErrorMessage.tsx +11 -11
  142. package/src/components/FallbackBoundary.tsx +40 -40
  143. package/src/components/Favorite.tsx +57 -57
  144. package/src/components/FieldGroup.tsx +46 -46
  145. package/src/components/Form.tsx +36 -36
  146. package/src/components/FormGroup.tsx +57 -57
  147. package/src/components/Icon.tsx +35 -35
  148. package/src/components/IconBox.tsx +134 -134
  149. package/src/components/ImageBox.tsx +125 -125
  150. package/src/components/ImageWithFallback.tsx +65 -65
  151. package/src/components/Input.tsx +49 -49
  152. package/src/components/Link.tsx +55 -55
  153. package/src/components/LoadingPanel.tsx +12 -12
  154. package/src/components/MenuOverlay/Menu.tsx +158 -158
  155. package/src/components/MenuOverlay/context.ts +20 -20
  156. package/src/components/MenuOverlay/index.tsx +55 -55
  157. package/src/components/MenuOverlay/keyboard.ts +60 -60
  158. package/src/components/MenuOverlay/types.ts +171 -171
  159. package/src/components/Overlay/context.ts +10 -10
  160. package/src/components/Overlay/index.tsx +182 -182
  161. package/src/components/Overlay/types.ts +75 -75
  162. package/src/components/Pagination.tsx +133 -133
  163. package/src/components/ProgressBar.tsx +45 -45
  164. package/src/components/ProgressCircular.tsx +45 -45
  165. package/src/components/RadioGroup.tsx +147 -147
  166. package/src/components/Rating.tsx +98 -98
  167. package/src/components/Select/MultiSelect.tsx +217 -217
  168. package/src/components/Select/RichSelect.tsx +128 -128
  169. package/src/components/Select/SimpleSelect.tsx +73 -73
  170. package/src/components/Select/hooks.ts +133 -133
  171. package/src/components/Select/index.tsx +35 -35
  172. package/src/components/Select/types.ts +134 -134
  173. package/src/components/SelectBox.tsx +181 -167
  174. package/src/components/Skeleton.tsx +53 -53
  175. package/src/components/Slider.tsx +89 -89
  176. package/src/components/SmartTable.tsx +227 -227
  177. package/src/components/Stepper.tsx +163 -163
  178. package/src/components/Table.tsx +234 -234
  179. package/src/components/Tabs/TabController.ts +54 -54
  180. package/src/components/Tabs/index.tsx +106 -106
  181. package/src/components/Tabs/types.ts +67 -67
  182. package/src/components/Tabs/utils.ts +6 -6
  183. package/src/components/Text.ts +111 -111
  184. package/src/components/Textarea.tsx +27 -27
  185. package/src/components/Tooltip.tsx +83 -83
  186. package/src/components/layout.tsx +101 -101
  187. package/src/context/CitricContext.tsx +4 -4
  188. package/src/context/CitricProvider.tsx +14 -14
  189. package/src/context/hooks.ts +6 -6
  190. package/src/index.ts +59 -59
  191. package/src/overlay.ts +348 -348
  192. package/src/types.ts +235 -235
  193. package/src/utils/ValueController.ts +28 -28
  194. package/src/utils/acessibility.ts +92 -92
  195. package/src/utils/checkbox.ts +121 -121
  196. package/src/utils/css.ts +119 -119
  197. package/src/utils/options.ts +9 -9
  198. package/src/utils/radio.ts +93 -93
  199. package/src/utils/react.ts +6 -6
  200. package/src/utils/time.ts +5 -5
  201. package/tsconfig.json +10 -10
  202. package/dist/components/Autocomplete/Autocomplete.d.ts +0 -211
  203. package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
  204. package/dist/components/Autocomplete/Autocomplete.js.map +0 -1
  205. package/dist/components/Autocomplete/index.d.ts +0 -3
  206. package/dist/components/Autocomplete/index.d.ts.map +0 -1
  207. package/dist/components/Autocomplete/index.js +0 -2
  208. package/dist/components/Autocomplete/index.js.map +0 -1
  209. package/src/components/Autocomplete/index.ts +0 -3
@@ -1,217 +1,217 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { useTranslate } from '@stack-spot/portal-translate'
3
- import { useEffect, useMemo, useRef, useState } from 'react'
4
- import { useCheckboxGroupControls } from '../../utils/checkbox'
5
- import { applyCSSVariable } from '../../utils/css'
6
- import { defaultRenderKey, defaultRenderLabel } from '../../utils/options'
7
- import { withRef } from '../../utils/react'
8
- import { Checkbox } from '../Checkbox'
9
- import { CheckboxGroup } from '../CheckboxGroup'
10
- import { CitricComponent } from '../CitricComponent'
11
- import { Input } from '../Input'
12
- import { Row } from '../layout'
13
- import { ProgressCircular } from '../ProgressCircular'
14
- import { useDisabledEffect, useFocusEffect, useOpenPanelEffect } from './hooks'
15
- import { RichSelectProps } from './types'
16
-
17
- export interface BaseMultiSelectProps<T> extends
18
- Omit<RichSelectProps<T>, 'value' | 'onChange' | 'renderHeader' | 'renderLabel' | 'renderOption' | 'required' | 'onFocus' | 'onBlur'> {
19
- value: T[],
20
- onChange: (value: T[]) => void,
21
- /**
22
- * A function to render the option in the selectable list.
23
- *
24
- * The `renderLabel` function is used if this is not provided.
25
- * @param value the option.
26
- * @returns the React Node.
27
- */
28
- renderOption?: (option: T) => React.ReactNode,
29
- /**
30
- * A function to render the selected options in the header.
31
- *
32
- * The `renderOption` function is used if this is not provided.
33
- * @param value the option.
34
- * @returns the React Node.
35
- */
36
- renderHeader?: (value: T[]) => React.ReactNode,
37
- /**
38
- * A function to render the item label.
39
- * @example
40
- * `(option) => option.name`
41
- * @default "the item's toString() result."
42
- * @param option the item to render.
43
- * @returns a React Node to render.
44
- */
45
- renderLabel?: (option: T) => string,
46
- /**
47
- * Whether or not to show a checkbox to select all or remove the selection.
48
- *
49
- * @default false
50
- */
51
- showSelectAll?: boolean,
52
- }
53
-
54
- export type MultiSelectProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'ref' | 'onChange' | 'onFocus' | 'onBlur'> &
55
- BaseMultiSelectProps<T>
56
-
57
- /**
58
- * A component that looks like a Select and behaves like a CheckboxGroup. This is a component that lets the user select multiple options
59
- * in a list.
60
- *
61
- * Differently than then the component Select, this does not render the native select of the browser. Instead, it renders a series of
62
- * checkboxes.
63
- *
64
- * @example
65
- *
66
- * ```
67
- * const options = useMemo(() => [
68
- * { id: 1, name: 'Option 1' },
69
- * { id: 2, name: 'Option 2' },
70
- * { id: 3, name: 'Option 3' },
71
- * ], [])
72
- *
73
- * const [value, setValue] = useState<typeof options>([])
74
- *
75
- * return <MultiSelect options={options} renderLabel={o => o.name} renderKey={o => o.id} value={value} setValue={setValue} />
76
- * ```
77
- */
78
- export const MultiSelect = withRef(
79
- function MultiSelect<T>({
80
- ref,
81
- options,
82
- value = [],
83
- onChange,
84
- renderLabel = defaultRenderLabel,
85
- renderKey = defaultRenderKey,
86
- disabled,
87
- loading,
88
- renderOption,
89
- renderHeader,
90
- searchable,
91
- maxHeight,
92
- style,
93
- className,
94
- showArrow,
95
- placeholder,
96
- showSelectAll,
97
- ...props
98
- }: MultiSelectProps<T>,
99
- ) {
100
- const t = useTranslate(dictionary)
101
- const _element = useRef<HTMLDivElement | null>(null)
102
- const element = ref ?? _element
103
- const [open, setOpen] = useState(false)
104
- const [focused, setFocused] = useState(false)
105
- const controls = useCheckboxGroupControls({
106
- options,
107
- renderKey,
108
- initialValue: value,
109
- onChange,
110
- applyFilter: (filter, option) => renderLabel(option).toLocaleLowerCase().includes(filter.toLocaleLowerCase()),
111
- })
112
-
113
- useOpenPanelEffect({ open, setOpen, setSearch: controls.setFilter, element, searchable })
114
- useFocusEffect({ element, focused, setFocused, setOpen })
115
- useDisabledEffect({ disabled, setOpen, setFocused })
116
-
117
- useEffect(() => {
118
- if (value !== controls.value) controls.setValue(value)
119
- }, [value.map(renderKey).join(',')])
120
-
121
- const header = useMemo(() => {
122
- if (value.length === 0) return <span className="placeholder header-text">{placeholder}</span>
123
- const reversed = [...value].reverse()
124
- return (
125
- (renderHeader?.(reversed)
126
- ?? (renderOption
127
- ? <Row className="header-text">{reversed.map(renderOption)}</Row>
128
- : <span className="header-text">{reversed.map(renderLabel).join(', ')}</span>
129
- )
130
- ) || <span></span>
131
- )}, [value, placeholder])
132
-
133
- return (
134
- <CitricComponent
135
- tag="div"
136
- component="multi-select"
137
- style={maxHeight ? applyCSSVariable(style, 'max-height', `${maxHeight}px`) : style}
138
- className={listToClass([
139
- className,
140
- showArrow === false && 'hide-arrow',
141
- open && 'open',
142
- focused && 'focused',
143
- disabled && 'disabled',
144
- ])}
145
- ref={element}
146
- aria-busy={loading}
147
- {...props}
148
- >
149
- <header
150
- onClick={() => {
151
- if (disabled) return
152
- setFocused(true)
153
- setOpen(true)
154
- }}
155
- onFocus={() => setFocused(true)}
156
- aria-label={t.accessibilityHelp}
157
- tabIndex={disabled ? undefined : 0}
158
- className={renderHeader ? 'custom' : undefined}
159
- >
160
- {header}
161
- {loading && <ProgressCircular size="xs" className="loader" />}
162
- </header>
163
- <div className="selection-panel" aria-hidden={!open} {...(open ? {} : { inert: 'true' })}>
164
- {searchable && <div className="search-bar">
165
- <div data-citric="field-group" className="auto">
166
- <i data-citric="icon-box" className="citric-icon outline Search"></i>
167
- <Input type="search" value={controls.filter} onChange={controls.setFilter} aria-label={t.searchAccessibility} />
168
- </div>
169
- </div>}
170
- {showSelectAll && (
171
- <Checkbox
172
- className="select-all"
173
- onChange={checked => checked ? controls.selectAll() : controls.removeSelection()}
174
- value={controls.isAllSelected}
175
- >
176
- {controls.isAllSelected ? t.removeSelection : t.selectAll}
177
- </Checkbox>
178
- )}
179
- <CheckboxGroup
180
- className="options"
181
- gap="0"
182
- options={controls.options}
183
- onChange={controls.setValue}
184
- value={controls.value}
185
- renderKey={controls.renderKey}
186
- focusable={false}
187
- renderItem={(checkbox, option) => (
188
- <CitricComponent
189
- component="checkbox-row"
190
- tag="label"
191
- className={listToClass(['option', controls.isUnfilteredButChecked(option) && 'unfiltered'])}
192
- >
193
- {checkbox}
194
- {renderOption?.(option) ?? renderLabel(option)}
195
- </CitricComponent>
196
- )}
197
- />
198
- </div>
199
- </CitricComponent>
200
- )
201
- },
202
- )
203
-
204
- const dictionary = {
205
- en: {
206
- accessibilityHelp: 'Press the arrow down to select multiple options',
207
- searchAccessibility: 'Filter the options',
208
- removeSelection: 'Remove selection',
209
- selectAll: 'Select all',
210
- },
211
- pt: {
212
- accessibilityHelp: 'Pressione a seta para baixo para selecionar múltiplas opções',
213
- searchAccessibility: 'Filtre as opções',
214
- removeSelection: 'Remover seleção',
215
- selectAll: 'Selecionar todos',
216
- },
217
- }
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { useTranslate } from '@stack-spot/portal-translate'
3
+ import { useEffect, useMemo, useRef, useState } from 'react'
4
+ import { useCheckboxGroupControls } from '../../utils/checkbox'
5
+ import { applyCSSVariable } from '../../utils/css'
6
+ import { defaultRenderKey, defaultRenderLabel } from '../../utils/options'
7
+ import { withRef } from '../../utils/react'
8
+ import { Checkbox } from '../Checkbox'
9
+ import { CheckboxGroup } from '../CheckboxGroup'
10
+ import { CitricComponent } from '../CitricComponent'
11
+ import { Input } from '../Input'
12
+ import { Row } from '../layout'
13
+ import { ProgressCircular } from '../ProgressCircular'
14
+ import { useDisabledEffect, useFocusEffect, useOpenPanelEffect } from './hooks'
15
+ import { RichSelectProps } from './types'
16
+
17
+ export interface BaseMultiSelectProps<T> extends
18
+ Omit<RichSelectProps<T>, 'value' | 'onChange' | 'renderHeader' | 'renderLabel' | 'renderOption' | 'required' | 'onFocus' | 'onBlur'> {
19
+ value: T[],
20
+ onChange: (value: T[]) => void,
21
+ /**
22
+ * A function to render the option in the selectable list.
23
+ *
24
+ * The `renderLabel` function is used if this is not provided.
25
+ * @param value the option.
26
+ * @returns the React Node.
27
+ */
28
+ renderOption?: (option: T) => React.ReactNode,
29
+ /**
30
+ * A function to render the selected options in the header.
31
+ *
32
+ * The `renderOption` function is used if this is not provided.
33
+ * @param value the option.
34
+ * @returns the React Node.
35
+ */
36
+ renderHeader?: (value: T[]) => React.ReactNode,
37
+ /**
38
+ * A function to render the item label.
39
+ * @example
40
+ * `(option) => option.name`
41
+ * @default "the item's toString() result."
42
+ * @param option the item to render.
43
+ * @returns a React Node to render.
44
+ */
45
+ renderLabel?: (option: T) => string,
46
+ /**
47
+ * Whether or not to show a checkbox to select all or remove the selection.
48
+ *
49
+ * @default false
50
+ */
51
+ showSelectAll?: boolean,
52
+ }
53
+
54
+ export type MultiSelectProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'ref' | 'onChange' | 'onFocus' | 'onBlur'> &
55
+ BaseMultiSelectProps<T>
56
+
57
+ /**
58
+ * A component that looks like a Select and behaves like a CheckboxGroup. This is a component that lets the user select multiple options
59
+ * in a list.
60
+ *
61
+ * Differently than then the component Select, this does not render the native select of the browser. Instead, it renders a series of
62
+ * checkboxes.
63
+ *
64
+ * @example
65
+ *
66
+ * ```
67
+ * const options = useMemo(() => [
68
+ * { id: 1, name: 'Option 1' },
69
+ * { id: 2, name: 'Option 2' },
70
+ * { id: 3, name: 'Option 3' },
71
+ * ], [])
72
+ *
73
+ * const [value, setValue] = useState<typeof options>([])
74
+ *
75
+ * return <MultiSelect options={options} renderLabel={o => o.name} renderKey={o => o.id} value={value} setValue={setValue} />
76
+ * ```
77
+ */
78
+ export const MultiSelect = withRef(
79
+ function MultiSelect<T>({
80
+ ref,
81
+ options,
82
+ value = [],
83
+ onChange,
84
+ renderLabel = defaultRenderLabel,
85
+ renderKey = defaultRenderKey,
86
+ disabled,
87
+ loading,
88
+ renderOption,
89
+ renderHeader,
90
+ searchable,
91
+ maxHeight,
92
+ style,
93
+ className,
94
+ showArrow,
95
+ placeholder,
96
+ showSelectAll,
97
+ ...props
98
+ }: MultiSelectProps<T>,
99
+ ) {
100
+ const t = useTranslate(dictionary)
101
+ const _element = useRef<HTMLDivElement | null>(null)
102
+ const element = ref ?? _element
103
+ const [open, setOpen] = useState(false)
104
+ const [focused, setFocused] = useState(false)
105
+ const controls = useCheckboxGroupControls({
106
+ options,
107
+ renderKey,
108
+ initialValue: value,
109
+ onChange,
110
+ applyFilter: (filter, option) => renderLabel(option).toLocaleLowerCase().includes(filter.toLocaleLowerCase()),
111
+ })
112
+
113
+ useOpenPanelEffect({ open, setOpen, setSearch: controls.setFilter, element, searchable })
114
+ useFocusEffect({ element, focused, setFocused, setOpen })
115
+ useDisabledEffect({ disabled, setOpen, setFocused })
116
+
117
+ useEffect(() => {
118
+ if (value !== controls.value) controls.setValue(value)
119
+ }, [value.map(renderKey).join(',')])
120
+
121
+ const header = useMemo(() => {
122
+ if (value.length === 0) return <span className="placeholder header-text">{placeholder}</span>
123
+ const reversed = [...value].reverse()
124
+ return (
125
+ (renderHeader?.(reversed)
126
+ ?? (renderOption
127
+ ? <Row className="header-text">{reversed.map(renderOption)}</Row>
128
+ : <span className="header-text">{reversed.map(renderLabel).join(', ')}</span>
129
+ )
130
+ ) || <span></span>
131
+ )}, [value, placeholder])
132
+
133
+ return (
134
+ <CitricComponent
135
+ tag="div"
136
+ component="multi-select"
137
+ style={maxHeight ? applyCSSVariable(style, 'max-height', `${maxHeight}px`) : style}
138
+ className={listToClass([
139
+ className,
140
+ showArrow === false && 'hide-arrow',
141
+ open && 'open',
142
+ focused && 'focused',
143
+ disabled && 'disabled',
144
+ ])}
145
+ ref={element}
146
+ aria-busy={loading}
147
+ {...props}
148
+ >
149
+ <header
150
+ onClick={() => {
151
+ if (disabled) return
152
+ setFocused(true)
153
+ setOpen(true)
154
+ }}
155
+ onFocus={() => setFocused(true)}
156
+ aria-label={t.accessibilityHelp}
157
+ tabIndex={disabled ? undefined : 0}
158
+ className={renderHeader ? 'custom' : undefined}
159
+ >
160
+ {header}
161
+ {loading && <ProgressCircular size="xs" className="loader" />}
162
+ </header>
163
+ <div className="selection-panel" aria-hidden={!open} {...(open ? {} : { inert: 'true' })}>
164
+ {searchable && <div className="search-bar">
165
+ <div data-citric="field-group" className="auto">
166
+ <i data-citric="icon-box" className="citric-icon outline Search"></i>
167
+ <Input type="search" value={controls.filter} onChange={controls.setFilter} aria-label={t.searchAccessibility} />
168
+ </div>
169
+ </div>}
170
+ {showSelectAll && (
171
+ <Checkbox
172
+ className="select-all"
173
+ onChange={checked => checked ? controls.selectAll() : controls.removeSelection()}
174
+ value={controls.isAllSelected}
175
+ >
176
+ {controls.isAllSelected ? t.removeSelection : t.selectAll}
177
+ </Checkbox>
178
+ )}
179
+ <CheckboxGroup
180
+ className="options"
181
+ gap="0"
182
+ options={controls.options}
183
+ onChange={controls.setValue}
184
+ value={controls.value}
185
+ renderKey={controls.renderKey}
186
+ focusable={false}
187
+ renderItem={(checkbox, option) => (
188
+ <CitricComponent
189
+ component="checkbox-row"
190
+ tag="label"
191
+ className={listToClass(['option', controls.isUnfilteredButChecked(option) && 'unfiltered'])}
192
+ >
193
+ {checkbox}
194
+ {renderOption?.(option) ?? renderLabel(option)}
195
+ </CitricComponent>
196
+ )}
197
+ />
198
+ </div>
199
+ </CitricComponent>
200
+ )
201
+ },
202
+ )
203
+
204
+ const dictionary = {
205
+ en: {
206
+ accessibilityHelp: 'Press the arrow down to select multiple options',
207
+ searchAccessibility: 'Filter the options',
208
+ removeSelection: 'Remove selection',
209
+ selectAll: 'Select all',
210
+ },
211
+ pt: {
212
+ accessibilityHelp: 'Pressione a seta para baixo para selecionar múltiplas opções',
213
+ searchAccessibility: 'Filtre as opções',
214
+ removeSelection: 'Remover seleção',
215
+ selectAll: 'Selecionar todos',
216
+ },
217
+ }