rl-core-front 0.10.0 → 0.10.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rl-core-front",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "Telas e componentes Next.js do core: login com 2FA, usu\u00e1rios, RBAC, auditoria, logs e listagens com filtro din\u00e2mico",
5
5
  "author": "Rodrigo Liberti",
6
6
  "license": "MIT",
@@ -9,10 +9,12 @@ import { Button } from "#core/components/ui/button";
9
9
  import {
10
10
  DropdownMenu,
11
11
  DropdownMenuContent,
12
+ DropdownMenuItem,
12
13
  DropdownMenuTrigger,
13
14
  } from "#core/components/ui/dropdown-menu";
14
15
  import { Input } from "#core/components/ui/input";
15
16
  import { useI18n } from "#core/contexts";
17
+ import { cn } from "#core/lib/utils";
16
18
 
17
19
  /** O mínimo para desenhar uma opção: o que identifica e o que se lê. */
18
20
  export interface ComboboxOption {
@@ -158,17 +160,23 @@ export function Combobox({
158
160
 
159
161
  <DropdownMenuContent
160
162
  /*
161
- * Cara de select: mesma largura do campo e aberto **por cima** dele.
163
+ * Largura do campo sempre; sobreposto quando é de um valor só.
162
164
  *
163
165
  * A largura precisa de `var(...)` por extenso — o atalho
164
- * `w-[--variavel]` era do Tailwind 3 e não gera CSS na 4. A margem
165
- * negativa é o que sobrepõe: com `sideOffset` zero o painel encosta na
166
- * borda do campo, e subir a altura dele cobre o campo. O `data-[side]`
167
- * cuida da abertura para cima, quando não espaço embaixo.
166
+ * `w-[--variavel]` era do Tailwind 3 e não gera CSS na 4.
167
+ *
168
+ * Escolhendo um valor, cobrir o campo cara de select e o painel
169
+ * fecha em seguida. No modo múltiplo o campo é onde ficam os itens já
170
+ * escolhidos: cobri-lo esconderia justamente o que se acabou de marcar,
171
+ * e o painel continua aberto para marcar o próximo.
168
172
  */
169
- className="max-h-72 w-(--radix-dropdown-menu-trigger-width) overflow-y-auto p-1 data-[side=bottom]:-mt-(--radix-dropdown-menu-trigger-height) data-[side=top]:-mb-(--radix-dropdown-menu-trigger-height)"
173
+ className={cn(
174
+ "max-h-72 w-(--radix-dropdown-menu-trigger-width) overflow-y-auto p-1",
175
+ !multiple &&
176
+ "data-[side=bottom]:-mt-(--radix-dropdown-menu-trigger-height) data-[side=top]:-mb-(--radix-dropdown-menu-trigger-height)",
177
+ )}
170
178
  align="start"
171
- sideOffset={0}
179
+ sideOffset={multiple ? 4 : 0}
172
180
  >
173
181
  <div className="p-1">
174
182
  <Input
@@ -176,14 +184,22 @@ export function Combobox({
176
184
  value={search}
177
185
  placeholder={searchPlaceholder ?? t("common.search")}
178
186
  onChange={(event) => setSearch(event.target.value)}
179
- // O menu do Radix tem busca por digitação própria: sem parar o
180
- // evento aqui, digitar "c" pularia o foco para o item "Chase" em
181
- // vez de escrever no campo.
187
+ /*
188
+ * o que é texto fica preso no campo.
189
+ *
190
+ * O menu do Radix tem busca por digitação própria: sem parar essas
191
+ * teclas, digitar "c" pularia o foco para o item "Chase" em vez de
192
+ * escrever. Mas parar **tudo** — como estava — leva junto as setas,
193
+ * e aí não há como percorrer a lista pelo teclado.
194
+ */
182
195
  onKeyDown={(event) => {
183
- event.stopPropagation();
196
+ if (event.key.length === 1) {
197
+ event.stopPropagation();
198
+ }
184
199
  if (event.key !== "Enter") {
185
200
  return;
186
201
  }
202
+ event.stopPropagation();
187
203
  // Enter escolhe o que a busca deixou na tela — sem isto, filtrar
188
204
  // pelo teclado ainda terminaria no mouse.
189
205
  event.preventDefault();
@@ -195,15 +211,20 @@ export function Combobox({
195
211
  </div>
196
212
 
197
213
  {visiveis.map((option) => (
198
- <button
214
+ <DropdownMenuItem
199
215
  key={option.id}
200
- type="button"
201
- className="flex w-full items-center justify-between rounded-sm px-2 py-1.5 text-sm hover:bg-accent"
202
- onClick={() => alternar(option.id)}
216
+ className="flex w-full items-center justify-between"
217
+ // Escolher **não** fecha por conta do Radix: no modo múltiplo,
218
+ // fechar a cada marcação obrigaria a reabrir para o próximo. Quem
219
+ // fecha é o `alternar`, e só quando é de um valor só.
220
+ onSelect={(event) => {
221
+ event.preventDefault();
222
+ alternar(option.id);
223
+ }}
203
224
  >
204
225
  <span className="truncate">{option.name}</span>
205
226
  {value.includes(option.id) && <Check className="h-4 w-4" />}
206
- </button>
227
+ </DropdownMenuItem>
207
228
  ))}
208
229
 
209
230
  {visiveis.length === 0 && (