Skip to content

👺 Máscaras para seus inputs de uma maneira fácil, rápida e performática.

License

Notifications You must be signed in to change notification settings

MauMuller/valisk

Repository files navigation

Warpnet

Valisk

É uma biblioteca feita para campos UNCONTROLLED e CONTROLLED, incluindo várias máscaras para serem utilizadas de uma maneira muito fácil e performática.

EXTRA: Quando integrada ao react-hook-form, ela consegue trabalhar da melhor forma possivel, misturando as validações e controles dos campos, ás máscaras com personalização e sem renderizações desnecessárias.


GitHub package.json version GitHub Workflow Status GitHub GitHub code size in bytes


Tipos de uso
UNCONTROLLED | CONTROLLED | REACT-HOOK-FORMS

Linguagens
JAVASCRIPT | TYPESCRIPT


Introdução

A ideia da construção da biblioteca já existia a muito tempo, porém, apenas depois de adquirir conhecimento das técnologias da modernidade que fui capaz de realiza-lá.

Valisk trabalha com campos CONTROLLED e UNCONTROLLED, ou seja, te dando a possiblidade de controllar a renderização sem se precoupar com a usabilidade do usuário, essa responsabilidade é da lib.

A biblitoeca disponibiliza métodos e tipos, apenas o necessário para o desenvolvimento. Qualquer dúvida, basta navegar até a sessão -> API de Referência e procurar pela questão em especial ou ainda, mandar uma issue.

Agora segue abaixo o menu para um roadmap de refencia sobre a Lib:

Mapa da documentação


Instalação

Para sua utilização é necessário a instalação do pacote, para isso existem algumas possibilidades até o momento, entre elas:


Casos de uso

Aqui iremos entrar em alguns exemplos de uso, porém o foco é apenas a apresentação da lib com algumas ilustrações.

Obeservação: Todos exemplos abaixos conterão typescript, caso queira utilizar com javascript, basta remover as tipagens.

  • Uncontrolled

    Iniciando com campos uncontrolled

    Nesse exemplo será utilizado uma demonstração apenas com o _masks, _getValues, com as propriedades cpf e money.

    import { CSSProperties, FormEvent } from "react";
    import { useValisk } from "@libsdomau/valisk";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "flex-start",
      alignItems: "center",
      gap: "1rem",
      color: "#fff",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`Renderizou ${++renderCounter}`);
    
      interface Inputs {
        campo1: string;
        campo2: string;
      }
    
      const { _masks, _getValues } = useValisk<Inputs>({
        cpf: { name: "campo1" },
        money: { name: "campo2", typeMoney: "real", explictMask: true },
      });
    
      const showValues = (data: Inputs) => {
        evt.preventDefault();
        console.log(data);
      };
    
      return (
        <form style={globalStyle} onSubmit={_getValues(showValues)}>
          <input type="text" {..._masks("campo1")} />
          <input type="text" {..._masks("campo2")} />
          <button>Mostrar</button>
        </form>
      );
    }
    
    export default App;

    Output:

    123.124.123-51 0,52 Mostrar

    Console:

      1 Renderização!
      {campo1: '123.124.123-51', campo2: '0,52'}
    Utilizando o _forceUpdate para mostrar valor do password

    Neste caso, iremos alterar o valor do campo para mostrar o valor normal apenas com o método _forceUpdate e um estado do button, fazendo assim alterar de escondido para o valor normal, tudo de forma uncontrolled.

    import { CSSProperties, useEffect, useState } from "react";
    import { useValisk } from "@libsdomau/valisk";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "center",
      flexDirection: "column",
      alignItems: "flex-start",
      gap: "1rem",
      color: "#fff",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`${++renderCounter} Renderização`);
      const [hideValue, setHideValue] = useState(true);
    
      interface Inputs {
        passwordInput: string;
      }
    
      const { _masks, _forceUpdate } = useValisk<Inputs>({
        password: { name: "passwordInput", hideValue: hideValue },
      });
    
      const textButton = hideValue ? "Mostrar" : "Esconder";
    
      useEffect(() => {
        _forceUpdate({ inputName: "passwordInput", inputType: "uncontrolled" });
      }, [hideValue]);
    
      return (
        <form style={globalStyle} onSubmit={(evt) => evt.preventDefault()}>
          <input type="text" {..._masks("passwordInput")} />
          <button onClick={() => setHideValue(!hideValue)}>{textButton}</button>
        </form>
      );
    }
    
    export default App;

    Output:

    123456789 Esconder

    Console:

      1 Renderização!
      2 Renderização!

  • Controlled

    Iniciando com campos controlled

    Aqui foi utilizado apenas o _masks e a propriedade phone, com renderização no campo para alterar a lista.

    import { CSSProperties, useState } from "react";
    import { useValisk } from "@libsdomau/valisk";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "center",
      flexDirection: "column",
      alignItems: "flex-start",
      gap: "1rem",
      color: "#fff",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`${++renderCounter} Renderização!`);
    
      interface Inputs {
        phoneInput: string;
      }
    
      const randomNumbers = [...Array(10)].map(
        () => `+${Math.round(Math.random() * 100000000)}`
      );
    
      const [data] = useState(randomNumbers);
      const [phoneInput, setPhoneInput] = useState("");
    
      const filtredPhones = data.filter((number) => number.includes(phoneInput));
    
      const { _masks } = useValisk<Inputs>({
        phone: { name: "phoneInput", typePhone: "phoneMovel", showDDD: true },
      });
    
      return (
        <div style={globalStyle}>
          <form>
            <input
              type="text"
              id="cnpj1"
              value={phoneInput}
              onChange={(evt) => setPhoneInput(evt.target.value)}
              {..._masks("phoneInput")}
            />
          </form>
    
          <ul>
            {filtredPhones.map((numbers, indNumbers) => (
              <li key={indNumbers}>{numbers}</li>
            ))}
          </ul>
        </div>
      );
    }
    
    export default App;

    Output:

    +64
    • +64044127
    • +64203623

    Console:

    1 Renderização!
    2 Renderização!
    3 Renderização!
    Utilizando multiplos campos com o mesmo tipo de máscara

    Aqui foi utilizado o _masks e as propriedades cep e cnpj, possibilidando utilizar múltiplas vezes o mesmo tipo de valor.

    import { CSSProperties, useState } from "react";
    import { useValisk } from "@libsdomau/valisk";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "center",
      flexDirection: "column",
      alignItems: "flex-start",
      gap: "1rem",
      color: "#fff",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`${++renderCounter} Renderização`);
    
      interface Inputs {
        cnpj1: string;
        cnpj2: string;
        cep1: string;
        cep2: string;
      }
    
      const [inputs, setInputs] = useState([
        { id: "cnpj1", value: "" },
        { id: "cnpj2", value: "" },
        { id: "cep1", value: "" },
        { id: "cep2", value: "" },
      ]);
    
      const { _masks } = useValisk<Inputs>({
        cnpj: [{ name: "cnpj1", explictMask: true }, { name: "cnpj2" }],
        cep: [{ name: "cep1", explictMask: true }, { name: "cep2" }],
      });
    
      const objectInput = (id: keyof Inputs) => inputs.find((obj) => obj.id === id);
      const changeInputValue = (value: string, id: keyof Inputs) => {
        setInputs((prev) =>
          prev.map((obj) => (obj.id === id ? { ...obj, value } : obj))
        );
      };
    
      return (
        <form style={globalStyle}>
          <label htmlFor="cnpj1">cnpj1</label>
          <input
            type="text"
            id="cnpj1"
            value={objectInput("cnpj1")?.value}
            onChange={(evt) => changeInputValue(evt.target.value, "cnpj1")}
            {..._masks("cnpj1")}
          />
    
          <label htmlFor="cnpj1">cnpj2</label>
          <input
            type="text"
            id="cnpj2"
            value={objectInput("cnpj2")?.value}
            onChange={(evt) => changeInputValue(evt.target.value, "cnpj2")}
            {..._masks("cnpj2")}
          />
    
          <label htmlFor="cep1">cep1</label>
          <input
            type="text"
            id="cep1"
            value={objectInput("cep1")?.value}
            onChange={(evt) => changeInputValue(evt.target.value, "cep1")}
            {..._masks("cep1")}
          />
    
          <label htmlFor="cep1">cep2</label>
          <input
            type="text"
            id="cep2"
            value={objectInput("cep2")?.value}
            onChange={(evt) => changeInputValue(evt.target.value, "cep2")}
            {..._masks("cep2")}
          />
        </form>
      );
    }
    
    export default App;

    Output:

    cnpj1 cnpj2 cep1 cep2
    12.__.__/___-__ 12.341.23 67786-___ 23334-5

    Console:

      1 Renderização
      2 Renderização
      3 Renderização
      ...
      10 Renderização
      12 Renderização
      ...
      22 Renderização

  • React-Hook-Form

    Integração + Valores iniciais

    Nesse exemplo, iremos apenas integrar a lib com o react-hook-form colocando um valor inicial.

    import { CSSProperties, useEffect } from "react";
    import { useValisk } from "@libsdomau/valisk";
    import { useForm } from "react-hook-form";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "center",
      flexDirection: "column",
      alignItems: "flex-start",
      gap: "1rem",
      color: "#fff",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`${++renderCounter} Renderização`);
    
      interface Inputs {
        firstInput: string;
        secondInput: string;
      }
    
      const { register, setValue } = useForm<Inputs>({
        defaultValues: { firstInput: "123", secondInput: "456" },
      });
    
      const { _masks, _forceUpdate } = useValisk<Inputs>({
        phone: [
          {
            name: "firstInput",
            typePhone: "phoneFixo",
            explictMask: true,
            showDDD: true,
          },
          {
            name: "secondInput",
            typePhone: "phoneMovel",
            showDDD: true,
            showPrefix: true,
          },
        ],
      });
    
      useEffect(() => {
        _forceUpdate([
          {
            inputName: "firstInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
          {
            inputName: "secondInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
        ]);
      }, []);
    
      return (
        <form style={globalStyle} onSubmit={(evt) => evt.preventDefault()}>
          <input
            type="text"
            {...register("firstInput")}
            {..._masks("firstInput")}
          />
    
          <input
            type="text"
            {...register("secondInput")}
            {..._masks("secondInput")}
          />
        </form>
      );
    }
    
    export default App;

    Output:

    +12 3___-____ +45 6

    Console:

    1 Renderização
    Utilização do método _cleanVal e todas outras variações dos campos
    import { CSSProperties, useEffect, useState } from "react";
    import { useValisk } from "@libsdomau/valisk";
    import { useForm, SubmitHandler } from "react-hook-form";
    
    const globalStyle: CSSProperties = {
      display: "flex",
      width: "100%",
      height: "100vh",
      margin: "0",
      justifyContent: "center",
      flexDirection: "column",
      alignItems: "flex-start",
      gap: "1rem",
      color: "#fff",
    };
    
    const formStyle: CSSProperties = {
      display: "flex",
      flexDirection: "column",
      gap: "1rem",
    };
    
    let renderCounter = 0;
    
    function App() {
      console.log(`${++renderCounter} Renderização`);
      const [hideValue, setHideValue] = useState(false);
    
      interface Inputs {
        firstInput: string;
        secondInput: string;
        thirtyInput: string;
        fourtyInput: string;
        fiftyInput: string;
      }
    
      const { register, setValue, handleSubmit } = useForm<Inputs>({
        defaultValues: { firstInput: "123", secondInput: "456" },
      });
    
      const { _masks, _forceUpdate, _cleanVal } = useValisk<Inputs>({
        phone: [
          {
            name: "firstInput",
            typePhone: "phoneFixo",
            explictMask: true,
            showDDD: true,
          },
          {
            name: "secondInput",
            typePhone: "phoneMovel",
            showDDD: true,
            showPrefix: true,
          },
        ],
        password: {
          name: "thirtyInput",
          hideValue: hideValue,
        },
        money: [
          {
            name: "fourtyInput",
            typeMoney: "real",
            explictMask: true,
            explictSimbol: true,
          },
          {
            name: "fiftyInput",
            typeMoney: "dollar",
            explictMask: true,
            explictSimbol: false,
          },
        ],
      });
    
      const showValues: SubmitHandler<Inputs> = (data) => {
        console.log(data);
        console.log(_cleanVal(data));
      };
    
      useEffect(() => {
        _forceUpdate([
          {
            inputName: "firstInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
          {
            inputName: "secondInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
          {
            inputName: "fourtyInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
          {
            inputName: "fiftyInput",
            inputType: "react_hook_form",
            dispatchSetValue: setValue,
          },
        ]);
      }, []);
    
      useEffect(() => {
        _forceUpdate({
          inputName: "thirtyInput",
          inputType: "react_hook_form",
          dispatchSetValue: setValue,
        });
      }, [hideValue]);
    
      return (
        <div style={globalStyle}>
          <form onSubmit={handleSubmit(showValues)} style={formStyle}>
            <input
              type="text"
              {...register("firstInput")}
              {..._masks("firstInput")}
            />
    
            <input
              type="text"
              {...register("secondInput")}
              {..._masks("secondInput")}
            />
    
            <input
              type="text"
              {...register("thirtyInput")}
              {..._masks("thirtyInput")}
            />
    
            <input
              type="text"
              {...register("fourtyInput")}
              {..._masks("fourtyInput")}
            />
    
            <input
              type="text"
              {...register("fiftyInput")}
              {..._masks("fiftyInput")}
            />
    
            <button>Mostrar Valores</button>
          </form>
    
          <button onClick={() => setHideValue(!hideValue)}>
            {hideValue ? "Mostrar" : "Ocultar"} Senha
          </button>
        </div>
      );
    }
    
    export default App;

    Output:

    +12 3323-444_ +45 61 2 •••••••••• R$ 0,00 1,234.12 Mostrar Valores Mostrar Senha

    Console:

    1 Renderização
    2 Renderização
    
    {
      fiftyInput: "1,234.12",
      firstInput: "+12 3323-444_",
      fourtyInput: "R$ 44,55",
      secondInput: "+45 61 2",
      thirtyInput: "1255555563"
    }
    
    {
      fiftyInput: "123412",
      firstInput: "123323444",
      fourtyInput: "4455",
      secondInput: "45612",
      thirtyInput: "1255555563"
    }

  • Outros Exemplos novo

    MUI - Material UI

    Aqui será usado apenas o componente TextField do Material UI, porém o mesmo vale para todos outros.

    OBS: Caso você tenha percebido, ao utilizar o componente do MUI, é necessário passar o _masks da seguinte forma:

    InputProps: { inputsProps: { ..._masks(...) } }

    Isso é necessário pois caso passe o _masks apenas para o primeiro inputProps, não acontecerá nada em tela, mas no console você verá a mensagem de erro da sessão abaixo.

    Mensagem de erro + V-check

    O motivo disso é devido a tipo de elemento na qual o masks está sendo colocado, nesse caso, seria uma Div, invés de um Input, por conta disso é necessário essa utilização redundante.

    import { useEffect, useState, FC, ReactNode } from "react";
    import { TextField, IconButton } from "@mui/material";
    import { useValisk } from "@libsdomau/valisk";
    
    const Form: FC<ReactNode> = (children) => {
      return <>{children}</>
    }
    
    function App() {
      const [hideValue, setHideValue] = useState(true);
    
      type Inputs = {
        campo1: string;
      };
    
      const methodsValisk = useValisk<Inputs>({
        password: { name: "campo1", hideValue },
      });
    
      console.log("1 Renderização");
    
      const { _masks, _cleanValues, _forceUpdate, _getValues } = methodsValisk;
    
      useEffect(() => {
        _forceUpdate({
          inputName: "campo1",
          inputType: "uncontrolled",
        });
      }, [hideValue]);
    
      return (
        <div className="border border-red-600 h-screen items-center justify-center flex">
          <Form>
            <TextField
              label="teste"
              defaultValue="bah"
              InputProps={{
                inputProps: { ..._masks("campo1") },
                endAdornment: (
                  <IconButton onClick={() => setHideValue(!hideValue)}> O </IconButton>
                ),
              }}
            />
          </Form>
        </div>
      );
    }
    
    export default App;

    Output:

    *** O

    Console:

    1 Renderização

V-Check | Checagem de Elemento nova sessão

Antes de partir para as referências, é importante entender do que se trata esse atributo.

_:"v-check" é um atributo encontrado em todos os elementos que receberam o _masks("..."), ele serve como uma identificação dentro do body da página.

Ele não possui nenhuma outra utilidade, apenas serve para mostrar quais elementos receberam o método mencionado acima.

Sua criação é justamente para previr qualquer tipo de inserção em algum elemento que não seja um campo de texto.

Então, caso a máscara não esteja funcionando do campo de texto em específico, recomendo que verifique se o v-check está incluido nesse input, caso não esteja, provavelmente seu componente possui algum elemento superior.

Mas não fique precoupado, será informado no console caso o elemento que possui o _masks("...") não seja um campo de texto, por isso, fique de olho no console.

Error


API de Referência

Nessa sessão você poderá tirar todas suas dúvidas quanto a parametros ou retornos dos métodos, assim como ententer os tipos e até mesmo verificar a sintaxe de utilização para variados casos de uso.

Antes de continuar com a referência, lembre-se que é possível trabalhar de diversas formas com a lib, isso para atender aos mais variados casos de uso, porém, ela foi projetada para ser integrada ao react-hook-form, isso pois essa lib já resolve de forma muito eficiênte validações e controle sobre os campos, por isso, valisk realmente brilha com a sua utilização em conjunto.

Mesmo, a lib sendo incrivelmente poderosa com o react-hook-forms, ela pode ser utilizada sozinha da mesma forma, um exemplo disso é o método _getValues, na qual faz a mesma coisa que o onSubmit do react-hook-form, justamente para ser utilizado em conjunto com o _cleanValues, obtendo assim, todos os valores de forma limpa.

Por baixo dos panos, a lib realiza de forma uncontrolled a colocação da mascára nos campos, utilizando evento padrões do Javascript e eficiêntes códigos para gerar as máscarás.

Agora, vamos para os métodos.


@ Types

Aqui você poderá encontrar a finalidade e retorno dos tipos, mas é importante saber que os nomes foram colocados de forma intuitiva para lembrarmos justamente disso.

  • Parâmetros

    Nomes Valor do tipo
    ValiskEntryType<Campos> Array<...> | { cep: {...}, cpf: {...}, cnpj: {...}, password: {...}, money: {...}, phone: {...} }
    ConfigEntryType<Campos> { name: keyof Campos, props?: ListWithoutNameProp<Campos> }
    ForceUpdateEntryType<Campos> Array<...> | { inputName: '...', inputType: "controlled", dispatchSetValue: function }
  • Métodos

    Nomes Valor do tipo
    CleanValuesType<Campos> (props: Campos) => Campos
    ForceUpdateType<Campos> (props: ForceUpdateEntryType<Campos>) => void;
    GetValuesType<Campos> (func: (data: Campos) => void) => (evt: React.FormEvent<HTMLFormElement>) => React.FormEvent<HTMLFormElement>;
    MasksType<Campos> (key: keyof Campos) => DetailsHTML;

@ useValisk

Hook que será utilizado para informar quais serão as máscaras e quais métodos de retorno serão necessários.

  • Entrada


    Caso você esteja utilizando javascript, pode ignorar essa parte, ela será apenas importante para typescript. Agora, caso seja este o caso, é importante enter a funcionalidade abaixo.

    • useValisk<campos>

    Essa declaração é necessária para que o typescript possa utilizar os nomes dos campo de texto e assim, deixar de maneira explicita qual será o campo a possuir a máscara.

    Sintaxe:

    interface Inputs {
      teste1: string;
      teste2: string;
    }
    
    const { ... } = useValisk /* Aqui -> */<Inputs>(...)

    Assim como o react-hook-form, o Valisk também precisa desses de entrada, ou seja, é possivel utilizar essa mesma tipagem para ambas bibliotecas.

    Após colocar como entrada do hook a tipagem dos campos, você já irá notar que todos os parâmetros e propriedades que precisam do nome do campo, irão retornar todos os campos, facilitando o processo de escolher qual nome do campo que precisa de tal máscara.

    Sabendo disso, apenas informe sempre os tipos dos campos e deixe que o typescript e o valisk façam esse trabalho por você!


  • Parâmetros


    Aqui estára todas as possibilidades de máscaras para serem inseridas, em breve terão mais outras para serem incluidas.

    • CPF

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //000.000.000-00
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          cpf: {
            name: "...", //nome do campo
            explictMask: false
          },
      
          // ou
      
          cpf: [
            {
              name: "...",
              explictMask: false
            },
            {
              name: "...",
              explictMask: false
            }
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      explictMask boolean / undefined false Não Utilização da máscara de forma explicita

    • CNPJ

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //00.000.000/0000-00
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          cnpj: {
            name: "...", //nome do campo
            explictMask: false
          },
      
          // ou
      
          cnpj: [
            {
              name: "...",
              explictMask: false
            },
            {
              name: "...",
              explictMask: false
            }
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      explictMask boolean / undefined false Não Utilização da máscara de forma explicita

    • CEP

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //00000-000
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          cep: {
            name: "...", //nome do campo
            explictMask: false
          },
      
          // ou
      
          cep: [
            {
              name: "...",
              explictMask: false
            },
            {
              name: "...",
              explictMask: false
            }
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      explictMask boolean / undefined false Não Utilização da máscara de forma explicita

    • MONEY

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //R$ 0,00 - Com Simbolo
      //0,00
      
      //US$ 0.00 - Com Simbolo
      //0.00
      
      //€ 0.00 - Com Simbolo
      //0.00
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          money: {
            name: "...", //nome do campo
            typeMoney: "real",
            explictMask: true,
            explictSimbol: true,
          },
      
          // ou
      
          cep: [
            {
              name: "...",
              typeMoney: "real",
              explictMask: true,
              explictSimbol: true,
            },
            {
              name: "...",
              typeMoney: "real",
              explictMask: true,
              explictSimbol: true,
            },
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      typeMoney "real" | "dollar" | "euro" "real" Sim Tipo de moeda para máscara
      explictMask boolean / undefined false Não Utilização da máscara de forma explicita
      explictSimbol boolean / undefined false Não Mostra o simbolo da moeda escolhida ao lado esquerdo

    • PHONE

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //Celular Completo
      //+00 (00) 0 0000-0000
      
      //Celular Com Prefixo
      //(00) 0 0000-0000
      
      //Celular Com DDD
      //+00 0 0000-0000
      
      //Celular
      //0 0000-0000
      
      //Telefone Completo
      //+00 (00) 0000-0000
      
      //Telefone Com Prefixo
      //(00) 0000-0000
      
      //Telefone Com DDD
      //+00 0000-0000
      
      //Telefone
      //0000-0000
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          phone: {
            name: "...", //nome do campo
            typePhone: "phoneMovel",
            explictMask: false,
            showDDD: false,
            showPrefix: false
          },
      
          // ou
      
          phone: [
            {
              name: "...", //nome do campo
              typePhone: "phoneMovel",
              explictMask: false,
              showDDD: false,
              showPrefix: false
            },
            {
              name: "...", //nome do campo
              typePhone: "phoneMovel",
              explictMask: false,
              showDDD: false,
              showPrefix: false
            },
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      typePhone "phoneMovel" | "phoneFixo" "phoneMovel" Sim Seleciona o tipo de fone que será o campo
      explictMask boolean / undefined false Não Utilização da máscara de forma explicita
      showDDD boolean / undefined false Não Fará o papel de mostrar ou esconder o DDD
      showPrefix boolean / undefined false Não Mostra ou esconde o Prefixo do campo

    • PASSWORD

      • Máscara Válida;
      • Possibilidade de personalização;
      • CTRL-C / CTRL-V com ou sem máscara;
      • Incremento mesmo com Autocomplete dos navegadores;
      Definições:
      Template
      //••••••••••••
      //ou
      //123241231254
      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        const { _masks, _forceUpdate, _cleanVal, _getValues } = useValisk({
          password: {
            name: "...", //nome do campo
            hideValue: true
          },
      
          // ou
      
          password: [
            {
              name: "...", //nome do campo
              hideValue: true
            },
            {
              name: "...", //nome do campo
              hideValue: true
            },
          ]
        });
      Propriedades
      Propriedades Tipos Valores Padrões Obrigatório Descrição
      name Campos "" Sim Nome do campo
      hideValue boolean / undefined true Não Opção de mostrar ou esconder o valor

  • Retornos


    Métodos que serão desestruturados para serem utilizados para diversas funcionalidades.

    • _masks

      • Utilizado por todos campos;
      • Necessario ser usado de forma única em cada campo;
      • Não causa uma renderização por sua utilização`;
      • Insere de forma automática a tag name caso não o elemento não possua;
      Definições:
      Sobre

      Este é sem sombra de dúvidas o método mais importante da biblioteca, sendo ele o responsavel por gerar a máscara para cada um dos campos, por isso é necessário utilizar do operador rest para funcionar as máscaras.

      Além disso, assim como o register do react-hook-form, o _masks também precisa receber o nome do campo que irá receber a máscara configurada no hook.

      Assim facilitando muito o aprendizado para quem já utilizava a outra biblioteca.

      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
        interface Campos {
          campo1: string;
          campo2: string;
        }
      
      
        const { _masks } = useValisk<Campos>({...});
      
        return (
          <>
            <input type="text" {...masks("campo1")}/>
          </>
        );
      Funcionalidades
      Opções Tipo Descrição
      Propriedade keyof <Campos> Sendo preciso escolher somente um para cada _masks
      Retorno DetailsHTML Propriedades do elemento Input, utilizando assim algumas tag do próprio elemento

    • _forceUpdate

      • Os campos que precisam desse efeito, precisam ser declaros de forma clara;
      • Pode ser usados quantas vezes forem necessárias com diversos campo em uma atualização ou apenas um;
      • Não causa uma renderização por sua utilização;
      • É usado na maioria da vezes em conjunto com o useEffect nativo do react.
      • Usado para trocar o valor da senha ou para carregar todas os campos com máscara como valor inicial.
      Definições:
      Sobre

      Esse método possui a função de atualizar o valor de todos os campo inseridos, ele faz isso por meio de eventos e funcionalidades internas do campo, ou seja, ele não causa nenhuma renderização, para mudar o valor de forma defitiva é necessário carregar o componente novamente com as propriedades já alteradas, por conta disso, ele é normalmente utilizado com o useEffect do react, pois, assim que o componente é carregado novamente, ele captura todos os valores alterados e realiza as mudaças sem precisar realizar uma nova renderização.

      Em seus parametros é necessário indicar algumas props, para que a lib possa fazer a atualização do campo sem causar uma nova renderização.

      Sintaxe
        import { useEffect } from "react";
        import { useValisk } from "@libsdomau/valisk";
        import { useForm } from "react-hook-form";
        ...
      
        interface Campos {
          campo1: string;
          campo2: string;
        }
      
        const [hideValue, setHideValue] = useState(false);
        const { register, setValue } = useForm<Campos>();
        const { _masks _forceUpdate } = useValisk<Campos>({...});
      
        useEffect(() => {
          _forceUpdate({
            inputName: "campo2"
            inputType: "uncontrolled"
          })
        }, []);
      
        useEffect(() => {
          _forceUpdate({
            inputName: "campo1"
            inputType: "react-hook-form",
            dispatchSetValue: setValue,
          })
        }, [hideValue]);
      
      
        return (
          <>
            <input type="text" {...register("campo1")} {...masks("campo1")}/>
          </>
        );
      Funcionalidades
      Opções Tipo Descrição
      Propriedade { inputName: keyof <Campos>, inputType: "controlled" | "uncontrolled" | "react-hook-form", dispatchSetValue: Function } Aqui é preciso informar de forma exata os campos que serão atualizados, mesmo que não cause uma renderização, é importante colocar apenas aquele que necessitam de uma alguma atualização de valor. Lembrando que é possível inserir um array de objetos, além de apenas um objeto.
      Retorno void Esse método não retorna nenhum tipo de valor, apenas realiza seus processos.

    • _cleanValues

      • Mostra todos os valores em forma de objeto da mesma maneira que foram declarados;
      • Necessita receber os dados e realiza a conversão deles para dados sem máscaras, apenas em formato de números e letras;
      • Todos valores que não foram configurados para possuirem máscara serão retornados sem alteração;
      • Pode ser usado com o handleSubmit do react-hook-form para mostrar tudo sem máscara.
      Definições:
      Sobre

      Este é método que limpa o valor de todos as propriedades do objeto que possuem algum tipo de máscara e foram indicados nas configurações da lib, ele apenas remove tudo o que não seja letra ou número do valor.

      Já os campos que não possuem a configuração, são retornados igualmente, porém, sem nenhum tipo de remoção.

      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        interface Campos {
          campo1: string;
        }
      
        const showValues: Campos = (data) => {
          console.log(_cleanVal(data));
        };
      
        const { _masks, _cleanValues, _getValues } = useValisk<Campos>({...});
      
        return (
          <form onSubmit={_getValues(showValues)}>
            <input type="text" {...masks("campo1")}/>
          </form>
        );
      Funcionalidades
      Opções Tipo Descrição
      Propriedade <Campos> Aqui é preciso informar a data obtida através do onSubmit, sendo pelo _getValues ou pelo handleSubmit
      Retorno <Campos> (Formatado) O retorno desse método é básicamente o mesmo objeto passado porém, com remoções de máscaras caso algum campo tenha sido registrado no hook, caso o contrário, apenas é retornado da maneira que é passado.

    • _getValues

      • Captura o valor de todos os campos dentro do form.
      • Os campos não precisam possuir o _masks, porém precisam estar declarados no Tipo de Entrada;
      • Ele retorna um objeto com todos o valores dos campos, essa tipagem é a mesma de entrada no hook;
      • Funciona igual o handleSubmit do react-hook-form, precisando passar um função dentro e ela possuirá os valores retornados.
      Definições:
      Sobre

      Este método funciona como um auxiliar, uma função que captura todos valores dos campos que são exclusivamente filhos do Form. Após pegar os valores, ela converte eles em um objeto utilizando o nome do campo como key e o valor como value.

      É necessário passar uma outra função para dentro desse método, ela que irá receber o valor dos campos em formato de objeto atráves do parâmetro.

      Caso você tenha utilizado o react-hook-form, ela funciona igual o handleSubmit.

      Sintaxe
        import { useValisk } from "@libsdomau/valisk";
      
        ...
      
        interface Campos {
          campo1: string;
        }
      
      
        const { _masks, _getValues } = useValisk<Campos>({...});
        const showValues: Campos = (data) => console.log(data);
      
        return (
          <form onSubmit={_getValues(showValues)}>
            <input type="text" {...masks("campo1")}/>
          </form>
        );
      
        <!-- Ou -->
      
        return (
          <form onSubmit={_getValues((data) => console.log(data))}>
            <input type="text" {...masks("campo1")}/>
          </form>
        );
      Funcionalidades
      Opções Tipo Descrição
      Propriedade Função Essa função será executada recebendo por parâmetro o objeto com todos os valores dos campos, ela precisa ser do tipo void, ou seja, sem retorno.
      Retorno FormEvent É retornado o evento para que seja possível capturar o evento do submit.

@ useConfigEntry novo

Este hook fará o trabalho pesado para você, caso precise organizar os dados dos campos de uma maneira diferente da forma que o useValisk pede, é só utilizar este hook, a finalidade dele é organizar, independente da estrutura as máscaras para os campo corretos.

OBSERVAÇÃO: É necessário utilizar o tipo <ConfigEntryType> no lugar onde será declarado a máscara e o nome do campo, porém é possivel criar todas outras estruturas ao redor da maneira que achar melhor.

  • Entrada


    Essa declaração é necessária para que o typescript possa utilizar os nomes dos campo de texto e assim, deixar de maneira explicita qual será o campo a possuir a máscara.

    Sintaxe:

    interface Inputs {
      teste1: string;
      teste2: string;
    }
    
    const { ... } = useConfigEntry /* Aqui -> */<Inputs>(...)

  • Parâmetros


    Aqui estára todas as possibilidades de máscaras para serem inseridas, em breve terão mais outras para serem incluidas.

    • Any

      • Fará a conversão de uma estrutura de dados para outra;
      • Não altera nenhum dado;
      Definições:
      Observações

      O principal motivo desse método receber any é porque ele literalmente aceita qualquer estutura de dados.

      Desde um array com vários arrays dentro, até apenas um único objeto. Todas essa possibilidades fazem o método ser muito versatil.

      Porém é necessário a utilização do tipo ConfigEntryType caso não crie o objeto diretamente no parâmetro.

      Isso porque a ideia principal desse hook é converter a estrutura de dados que será utilizado como fonte para o hook useValisk para algo que o próprio possa aceitar, ou seja, você acaba tendo liberdade para criar vários tipos de estruturas, mas com a obrigação de incluir um objeto do tipo ConfigEntryType.

      Sintaxe

      Vamos ao exemplo da sua utilização, nela existe uma estrutura de uma array com um array e assim o nosso objeto que precisamos, assim declaramos e como podemos ver, a opção props não é obrigatória, isso funciona muito bem pois o valisk não irá gerar erro mesmo que não exista uma configuração de mascará para um nome de campo, ele apenas irá colocar o name no campo e não irá informar erro algum.

        import { useValisk, useConfigEntry, ConfigEntryType } from "@libsdomau/valisk";
      
        ...
      
        interface Inputs {
          campo1: string;
          campo2: string;
          campo3: string;
        }
      
        type Dados = Array<
          Array<React.HTMLAttributes<HTMLInputElement> & /* Aqui é usado --> */ConfigEntryType<Inputs>>
        >;
      
        const dados: Dados = [
          [
            {
              name: "campo1",
              id: "campo1",
              defaultValue: "aaaa",
              props: { money: { typeMoney: "real", explictMask: true }, cpf: { explictMask: true } /* <-- Isso aqui não irá funcionar, ele pega apenas o primeiro  */ },
            },
            {
              name: "campo2",
              placeholder: "teste1",
            },
          ],
          [
            {
              name: "campo3",
              props: { cnpj: { explictMask: true } },
            },
          ],
        ];
      
        const configMasks = useConfigEntry<Inputs>(dados);
        const methodsValisk = useValisk<Inputs>(configMasks);

  • Retornos


    Métodos que serão desestruturados para serem utilizados para diversas funcionalidades.

    • ValiskEntryType

      O retorno do hook será sempre o parâmetro de entrada do useValisk, isso porque ele serve de auxiliar para uma estrutura diferente de dados.

      Usando o mesmo exemplo anteriores teriamos a seguinte resposta:

        const configMasks = useConfigEntry<Inputs>(dados);
        const methodsValisk = useValisk<Inputs>(configMasks);
      
        console.log(configMasks);
      
        /*
            cnpj:{
                "name": "campo3",
                "explictMask": true
            },
      
            money:{
                "name": "campo1",
                "typeMoney": "real",
                "explictMask": true
            }
         */

@ ValiskProvider novo

Inspirado no FormProvider do react-hook-form, o ValiskProvider tem a funcionalidade de reutilização dos métodos do useValisk. É necessário apenas envolver esse componente entorno dos campos que precisam utilizar os métodos.

  • Parâmetros


    Ao utilizar o componente, é necessário passar um valor, esse é obtido através da utilização do método useValisk, assim, basta passar o valor retornado para dentro do componente pela destruturação.


    • Sintaxe:

      const methodsValisk = useValisk<Inputs>(...);
      const { _masks, _forceUpdate, _getValues, _cleanValues } = methodsValisk;
      
      <ValiskProvider {...methodsValisk}>
        ...
      </ValiskProvider>

@ useValiskContext novo

  • Entrada


    Essa declaração é necessária para que o typescript possa utilizar os nomes dos campo de texto e assim, deixar de maneira explicita qual será o campo a possuir a máscara.

    Sintaxe:

    interface Inputs {
      teste1: string;
      teste2: string;
    }
    
    const { ... } = useValiskContext /* Aqui -> */<Inputs>()

  • Retornos


    Todos os métodos que são retornados serão a partir do valor do ValiskProvider, ou seja, serão os mesmo métodos do hook useValisk.


    • Sintaxe:

      ...
      
      type Inputs = {
        campo1: string;
        campo2: string;
        campo3: string;
        campo4: string;
      }
      
      ...
      
      return (
        <ValiskProvider {...methodsValisk}>
          <InputComponent />
        </ValiskProvider>
      );
      
      
      const InputComponent = () => {
        const { _masks, _forceUpdate, _cleanValues, _getValues } = useValiskContext<Inputs>();
        return <input {..._masks('...')}/>
      }

Erros Comuns nova sessão

Essa sessão foi criada para mostrar todos os erros comuns que podem acontecer com o uso da biblioteca, porém, caso sua dúvida não esteja aqui, faça uma issue, agradeço.

Utilizei o _masks(...), porém a máscara não está sendo inserida.

Existe uma grande chance de, neste caso, o problema estar no elemento superior, isso acontece normalmente com componentes que possuem algum campo de texto.

O problema aqui é que o elemento que está recebendo o método _masks(...) não é o campo de texto, mas sim algum outro elemento dentro do componente (caso seja um componente).

Para identificar isso, basta procurar pelos elemento que possuem o atributo v-check dentro do inspecionar da página, caso algum elemento não seja um campo de texto, ele não funcionará.

Nesse caso, também haverá uma mensagem no console falando qual elemento está recebendo o método em específico.


Dúvidas

Aqui estão as melhores maneiras de contribuir com o projeto, caso tenha alguma coisa não explicada com as dúvidas abaixo, entre em contato.

Issue: https://github.com/MauMuller/valisk/issues/new

Pull Request: https://github.com/MauMuller/valisk/pulls

Dúvidas no uso da lib? Opa, ta com dúvidas? Só fazer uma issue com o tema em específico, assim que der, eu respondo.
Encontrou algum problema? Opa, achou algum problema com a lib ou algo não está funcionando? Só fazer uma issue com o tema em específico, assim que der, eu respondo.
Tem algumas ideias para contribuir? Cara que daora, bom, aqui tu tem duas opções:
  1. Tu pode fazer um PR para o código com essa ideia, com isso eu irei fazer um code review para avaliar.
  2. Tu também pode criar uma Issue com a ideia, assim que der, a gente consegue trocar uma ideia.
Ta afim de contribuir codando? Ta afim de ajudar a codar? da um fork no projeto e manda uma PR.