rl-core-front 0.14.2 → 0.14.4
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
|
@@ -4,22 +4,79 @@ import * as React from "react";
|
|
|
4
4
|
|
|
5
5
|
import { cn } from "#core/lib/utils";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
/**
|
|
8
|
+
* O `prefix` sai do tipo base de propósito: o React o declara como `string`
|
|
9
|
+
* porque existe um `prefix` de RDFa em todo elemento HTML — atributo que
|
|
10
|
+
* ninguém escreve num `<input>`, e cujo tipo impediria passar um ícone aqui.
|
|
11
|
+
*/
|
|
12
|
+
export interface InputProps
|
|
13
|
+
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "prefix"> {
|
|
14
|
+
/**
|
|
15
|
+
* Marca fixa colada à esquerda do campo — `R$`, `@`, `https://`.
|
|
16
|
+
*
|
|
17
|
+
* Dentro da borda, e não num rótulo acima: a unidade é do valor, e lida
|
|
18
|
+
* longe dele ela vira decoração que some quando o formulário fica cheio. É
|
|
19
|
+
* também o que evita quem digita repetir a marca no próprio texto.
|
|
20
|
+
*/
|
|
21
|
+
prefix?: React.ReactNode;
|
|
22
|
+
/** Mesma ideia à direita — `%`, `kg`, `/mês`. */
|
|
23
|
+
suffix?: React.ReactNode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A marca não é campo: não recebe clique nem foco, e o cursor vai para o input. */
|
|
27
|
+
const Affix = ({
|
|
28
|
+
children,
|
|
29
|
+
className,
|
|
30
|
+
}: {
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
className?: string;
|
|
33
|
+
}): React.JSX.Element => (
|
|
34
|
+
<span
|
|
35
|
+
aria-hidden
|
|
36
|
+
className={cn(
|
|
37
|
+
"pointer-events-none absolute inset-y-0 flex items-center text-sm text-muted-foreground",
|
|
38
|
+
className,
|
|
39
|
+
)}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
</span>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
46
|
+
({ className, type, prefix, suffix, ...props }, ref) => {
|
|
47
|
+
const campo = (
|
|
48
|
+
<input
|
|
49
|
+
type={type}
|
|
50
|
+
className={cn(
|
|
51
|
+
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
|
|
52
|
+
// Abre espaço para a marca em vez de deixar o texto passar por baixo
|
|
53
|
+
// dela. Largura fixa e não `w-auto`: a marca é curta por definição, e
|
|
54
|
+
// medir a real exigiria ler o DOM a cada render.
|
|
55
|
+
prefix && "pl-10",
|
|
56
|
+
suffix && "pr-10",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
ref={ref}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Sem marca o `<input>` volta a ser o elemento raiz: envolver todo campo
|
|
65
|
+
// do produto num `div` mudaria a largura de quem já usa `Input` dentro de
|
|
66
|
+
// um flex, e a maioria não tem marca nenhuma.
|
|
67
|
+
if (!prefix && !suffix) {
|
|
68
|
+
return campo;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className="relative w-full">
|
|
73
|
+
{prefix && <Affix className="left-3">{prefix}</Affix>}
|
|
74
|
+
{campo}
|
|
75
|
+
{suffix && <Affix className="right-3">{suffix}</Affix>}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
);
|
|
23
80
|
Input.displayName = "Input";
|
|
24
81
|
|
|
25
82
|
export { Input };
|
|
@@ -49,6 +49,19 @@ export interface UseConfirmResult {
|
|
|
49
49
|
options: ConfirmedActionOptions,
|
|
50
50
|
action: () => Promise<unknown>,
|
|
51
51
|
) => Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* O caso mais comum, com os textos prontos: `Excluir “Cartão Inter”?` mais o
|
|
54
|
+
* aviso de que não há volta, o botão vermelho e o rótulo "Excluir".
|
|
55
|
+
*
|
|
56
|
+
* Existe para a tela não repetir cinco campos a cada lixeira — era o que
|
|
57
|
+
* fazia cada projeto embrulhar o `confirm` num hook próprio e acabar com
|
|
58
|
+
* duas perguntas de excluir diferentes no mesmo produto.
|
|
59
|
+
*
|
|
60
|
+
* O texto **não** menciona recuperação, mesmo onde a exclusão é lógica:
|
|
61
|
+
* lixeira por baixo é rede de segurança do dado, não promessa ao usuário, e
|
|
62
|
+
* prometer desfazer convida ao clique sem cuidado.
|
|
63
|
+
*/
|
|
64
|
+
confirmDelete: (name: string, note?: string) => Promise<boolean>;
|
|
52
65
|
/** Enquanto a ação confirmada roda — para travar a tabela que ela muda. */
|
|
53
66
|
acting: boolean;
|
|
54
67
|
/** Renderize no final da tela — é o modal em si. */
|
|
@@ -86,6 +99,18 @@ export function useConfirm(): UseConfirmResult {
|
|
|
86
99
|
[pending],
|
|
87
100
|
);
|
|
88
101
|
|
|
102
|
+
const confirmDelete = useCallback(
|
|
103
|
+
(name: string, note?: string): Promise<boolean> =>
|
|
104
|
+
confirm({
|
|
105
|
+
title: t("common.deleteTitle", { name }),
|
|
106
|
+
description: t("common.deleteWarning"),
|
|
107
|
+
note,
|
|
108
|
+
confirmLabel: t("common.delete"),
|
|
109
|
+
destructive: true,
|
|
110
|
+
}),
|
|
111
|
+
[confirm, t],
|
|
112
|
+
);
|
|
113
|
+
|
|
89
114
|
const confirmAndRun = useCallback(
|
|
90
115
|
async (
|
|
91
116
|
options: ConfirmedActionOptions,
|
|
@@ -127,5 +152,5 @@ export function useConfirm(): UseConfirmResult {
|
|
|
127
152
|
/>
|
|
128
153
|
);
|
|
129
154
|
|
|
130
|
-
return { confirm, confirmAndRun, acting, confirmDialog };
|
|
155
|
+
return { confirm, confirmDelete, confirmAndRun, acting, confirmDialog };
|
|
131
156
|
}
|
package/src/i18n/messages/en.ts
CHANGED
|
@@ -195,6 +195,9 @@ export const en: Messages = {
|
|
|
195
195
|
cancel: "Cancel",
|
|
196
196
|
edit: "Edit",
|
|
197
197
|
delete: "Delete",
|
|
198
|
+
deleteTitle: "Delete “{name}”?",
|
|
199
|
+
deleteWarning:
|
|
200
|
+
"This action cannot be undone. The record leaves the lists and stops appearing in the system.",
|
|
198
201
|
create: "Create",
|
|
199
202
|
confirm: "Confirm",
|
|
200
203
|
send: "Send",
|
package/src/i18n/messages/pt.ts
CHANGED
|
@@ -197,6 +197,9 @@ export const pt = {
|
|
|
197
197
|
cancel: "Cancelar",
|
|
198
198
|
edit: "Editar",
|
|
199
199
|
delete: "Excluir",
|
|
200
|
+
deleteTitle: "Excluir “{name}”?",
|
|
201
|
+
deleteWarning:
|
|
202
|
+
"Esta ação não pode ser desfeita. O registro sai das listas e deixa de aparecer no sistema.",
|
|
200
203
|
create: "Criar",
|
|
201
204
|
confirm: "Confirmar",
|
|
202
205
|
send: "Enviar",
|