rl-core-front 0.18.8 → 0.18.9

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.18.8",
3
+ "version": "0.18.9",
4
4
  "description": "Telas e componentes Next.js do core: login com 2FA, usuários, RBAC, auditoria, logs e listagens com filtro dinâmico",
5
5
  "author": "Rodrigo Liberti",
6
6
  "license": "MIT",
@@ -50,6 +50,17 @@ export interface ComboboxProps {
50
50
  onCreate?: (text: string) => void;
51
51
  /** Texto da linha de criação. Ausente, `Criar "{text}"`. */
52
52
  createLabel?: (text: string) => string;
53
+ /**
54
+ * No modo múltiplo, fecha sozinho depois de tantos milissegundos sem
55
+ * interação — contados a partir da última marcação.
56
+ *
57
+ * O painel múltiplo fica aberto de propósito para marcar vários de uma vez,
58
+ * mas quem marcou o que queria e parou de mexer está esperando ele sumir.
59
+ * Digitar, andar com as setas, mover o mouse sobre a lista ou marcar outro
60
+ * item reinicia a contagem; abrir e só olhar não a inicia. Ausente, o
61
+ * painel só fecha no clique fora ou no Esc.
62
+ */
63
+ idleCloseMs?: number;
53
64
  }
54
65
 
55
66
  /** Id da linha de criação na lista apontável — nenhuma opção real o usa. */
@@ -93,9 +104,37 @@ export function Combobox({
93
104
  creatable = false,
94
105
  onCreate,
95
106
  createLabel,
107
+ idleCloseMs,
96
108
  }: ComboboxProps): JSX.Element {
97
109
  const { t } = useI18n();
98
110
  const [open, setOpen] = useState(false);
111
+ /* O cronômetro do fechamento por inatividade; só corre depois de uma marcação. */
112
+ const ocioso = useRef<ReturnType<typeof setTimeout> | null>(null);
113
+
114
+ const pararContagem = (): void => {
115
+ if (ocioso.current) {
116
+ clearTimeout(ocioso.current);
117
+ ocioso.current = null;
118
+ }
119
+ };
120
+
121
+ /* Reinicia a contagem — se ela já estava correndo. Quem a inicia é o `alternar`. */
122
+ const registrarInteracao = (): void => {
123
+ if (!ocioso.current) {
124
+ return;
125
+ }
126
+
127
+ pararContagem();
128
+ ocioso.current = setTimeout(() => setOpen(false), idleCloseMs);
129
+ };
130
+
131
+ useEffect(() => {
132
+ if (!open) {
133
+ pararContagem();
134
+ }
135
+
136
+ return pararContagem;
137
+ }, [open]);
99
138
  const [search, setSearch] = useState("");
100
139
  /**
101
140
  * O item que o teclado aponta. Nulo é "o primeiro que a busca deixou".
@@ -172,6 +211,11 @@ export function Combobox({
172
211
  ? value.filter((atual) => atual !== id)
173
212
  : [...value, id],
174
213
  );
214
+
215
+ if (idleCloseMs) {
216
+ pararContagem();
217
+ ocioso.current = setTimeout(() => setOpen(false), idleCloseMs);
218
+ }
175
219
  };
176
220
 
177
221
  useEffect(() => {
@@ -298,6 +342,8 @@ export function Combobox({
298
342
  * compõe os handlers com o de fora primeiro, e desiste do seu quando o
299
343
  * evento já foi tratado: o `preventDefault` daqui é o que o desarma.
300
344
  */
345
+ onPointerMove={registrarInteracao}
346
+ onKeyDownCapture={registrarInteracao}
301
347
  onKeyDown={(event) => {
302
348
  // Tecla nascida na busca já foi tratada lá.
303
349
  if (