{"id":31560961,"url":"https://github.com/guilhermeasn/mask-hooks","last_synced_at":"2025-10-05T02:18:49.860Z","repository":{"id":47344904,"uuid":"348490105","full_name":"guilhermeasn/mask-hooks","owner":"guilhermeasn","description":"Lightweight package with functions and hooks for masking data inputs and outputs for Node.JS projects","archived":false,"fork":false,"pushed_at":"2024-09-28T12:53:23.000Z","size":3124,"stargazers_count":19,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-02T11:58:55.842Z","etag":null,"topics":["hooks","input","javascript-library","lightweight","mask","react","typescript","usemask"],"latest_commit_sha":null,"homepage":"http://maskhooks.gn.dev.br/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guilhermeasn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-03-16T20:59:34.000Z","updated_at":"2024-12-12T20:43:10.000Z","dependencies_parsed_at":"2024-01-08T00:41:40.969Z","dependency_job_id":null,"html_url":"https://github.com/guilhermeasn/mask-hooks","commit_stats":{"total_commits":152,"total_committers":2,"mean_commits":76.0,"dds":0.03289473684210531,"last_synced_commit":"b1b01f61e3625ce7a1f2ee6f27aad34969ee5e4d"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/guilhermeasn/mask-hooks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guilhermeasn%2Fmask-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guilhermeasn%2Fmask-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guilhermeasn%2Fmask-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guilhermeasn%2Fmask-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guilhermeasn","download_url":"https://codeload.github.com/guilhermeasn/mask-hooks/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guilhermeasn%2Fmask-hooks/sbom","scorecard":{"id":448589,"data":{"date":"2025-08-11","repo":{"name":"github.com/guilhermeasn/mask-hooks","commit":"2baefd88dd4253f1a5422c3a2df29985e40660a6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/guilhermeasn/mask-hooks/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/guilhermeasn/mask-hooks/tests.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T07:34:02.167Z","repository_id":47344904,"created_at":"2025-08-19T07:34:02.167Z","updated_at":"2025-08-19T07:34:02.167Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278399693,"owners_count":25980333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hooks","input","javascript-library","lightweight","mask","react","typescript","usemask"],"created_at":"2025-10-05T02:18:48.120Z","updated_at":"2025-10-05T02:18:49.849Z","avatar_url":"https://github.com/guilhermeasn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mask-hooks v3\n\n[![tests](https://github.com/guilhermeasn/mask-hooks/actions/workflows/tests.yml/badge.svg)](https://github.com/guilhermeasn/mask-hooks/actions/workflows/tests.yml)\n[![pages-build-deployment](https://github.com/guilhermeasn/mask-hooks/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/guilhermeasn/mask-hooks/actions/workflows/pages/pages-build-deployment)\n[![npm](https://img.shields.io/npm/v/mask-hooks.svg)](https://www.npmjs.com/package/mask-hooks/v/latest)\n[![size](https://img.shields.io/bundlephobia/minzip/mask-hooks)](https://bundlephobia.com/package/mask-hooks)\n[![downloads](https://img.shields.io/npm/dt/mask-hooks)](https://www.npmjs.com/package/mask-hooks/)\n\nLightweight package with functions and hooks for masking data inputs and outputs for Node.JS projects.\n\n[![Demonstration](https://raw.githubusercontent.com/guilhermeasn/mask-hooks/master/mask-hooks.gif)](https://guilhermeasn.github.io/mask-hooks/)\n\n[Examples page](https://guilhermeasn.github.io/mask-hooks/)\n\n## Installation\n\nRun the command below in the terminal to install **mask-hooks** in your project\n\n```\nnpm install mask-hooks\n```\n\nOr with Yarn\n\n```\nyarn add mask-hooks\n```\n\n## Examples with React\n\n - Custom Mask - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FCustomMask.js)\n\n```js\nimport { useMask } from \"mask-hooks\";\nimport { useState } from \"react\";\n\nexport default function InputMask() {\n\n    const mask = useMask({\n        masks: '$ #,##',\n        placeholder: '0',\n        reverse: true,\n        infinity: {\n            add: '.',\n            each: 3\n        },\n        maxentries: 8\n    });\n\n    const [ value, setValue ] = useState(mask(''));\n\n    return (\n\n        \u003cinput\n            value={ value }\n            onChange={ input =\u003e setValue(mask(input.currentTarget.value)) }\n        /\u003e\n\n    );\n\n}\n```\n\n - Custom Mask with Numerical Range - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FCustomMaskNumericalRange.js)\n\n```js\nimport { useMask } from 'mask-hooks';\n\nexport default function Time() {\n\n    const time = useMask({\n        masks: '[0-23]:[0-59]:[0-59]'\n    });\n\n    return (\n        \u003cp\u003eTime: { time('71900') /* print 07:19:00 */ }\u003c/p\u003e\n    );\n\n}\n```\n\n - Preset Mask - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FPresetMask.js)\n\n```js\nimport { useMask, presets } from 'mask-hooks';\n\nexport default function MaskDocs() {\n\n    const documentMask = useMask(presets.DOCUMENT_CPF_CNPJ);\n\n    return (\n        \u003c\u003e\n            \u003cp\u003e{ documentMask('11122233345')    /* print 111.222.333-45 */     }\u003c/p\u003e\n            \u003cp\u003e{ documentMask('11222333000145') /* print 11.222.333/0001-45 */ }\u003c/p\u003e\n        \u003c/\u003e\n    );\n\n}\n```\n\n - Changed Preset Mask - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FChangedPresetMask.js)\n\n```js\nimport { useMask, getPresetMask } from 'mask-hooks';\n\nexport default function MaskProduct() {\n\n    const productKeyMask = useMask(getPresetMask('PRODUCT_KEY', { placeholder: '_' }));\n\n    return (\n        \u003cdiv\u003e\n            {\n                productKeyMask('h3pbvfhb27rjtgh')\n                /* print H3PBV-FHB27-RJTGH-_____-_____ */\n            }\n        \u003c/div\u003e\n    );\n\n}\n```\n\n - Mask verification completed - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FMaskVerificationCompleted.js)\n\n```js\nimport { useCompleteMask, presets } from \"mask-hooks\";\nimport { useState } from \"react\";\n\nexport default function InputMask() {\n\n    const maskComplete = useCompleteMask(presets.DATETIME_STAMP_LIMITED);\n    const [ data, setData ] = useState(maskComplete(''));\n\n    return (\n\n        \u003cinput\n            value={ data.result }\n            onChange={ input =\u003e setData(maskComplete(input.currentTarget.value)) }\n            style={ { color: data.completed ? \"#000000\" : \"#ff0000\" } }\n            title={ `${ data.entries } entries: ${ data.cleaned }` }\n        /\u003e\n\n    );\n\n}\n```\n\n - Mask verification completed and tested - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FMaskVerificationCompletedTested.js)\n\n```js\nimport { useCompleteMask, presets } from \"mask-hooks\";\nimport { useState } from \"react\";\n\nexport default function InputMask() {\n\n    // When filling out the mask is completed a test function\n    // is applied to check whether a valid date was entered,\n    // the result is received by the 'passing' key\n\n    const maskTest = (result) =\u003e !isNaN(Date.parse(result));\n\n    const maskComplete = useCompleteMask(presets.DATE_STAMP, maskTest);\n    const [ data, setData ] = useState(maskComplete(''));\n\n    return (\n\n        \u003cinput\n            value={ data.result }\n            onChange={ input =\u003e setData(maskComplete(input.currentTarget.value)) }\n            style={ { color: data.passing ? \"#00ff00\" : \"#ff0000\" } }\n        /\u003e\n\n    );\n\n}\n```\n\n- use mask directly - [Sandbox](https://codesandbox.io/p/sandbox/amazing-sea-2m3m8j?file=%2Fsrc%2Fexamples%2FUseMaskDirectly.js)\n\n```js\nimport { applyMask, presets } from 'mask-hooks';\n\nexport default function maskColor(target) {\n    return applyMask(target, presets.COLOR_HEX);\n}\n```\n\n## Resources\n\nResources exported by the **mask-hooks** package:\n\n - **Function `useMask`**: main resource to use package. Returns a function to use the preconfigured mask.\n\n```ts\nfunction useMask(settings: MaskProps): \u003cT extends Stringable\u003e(target: T) =\u003e string\n```\n\n - **Function `useCompleteMask`**: Returns a function to use the preconfigured mask with additional information in the result.\n\n```ts\nfunction useCompleteMask(settings: MaskProps, onComplete ?: (result : string, cleaned: string) =\u003e boolean): \u003cT extends Stringable\u003e(target: T) =\u003e { result: string, completed: boolean; entries: number; cleaned: string; passing : boolean | null; }\n```\n\n - **Function `applyMask`**: use a mask directly on the target\n\n```ts\nfunction applyMask\u003cT extends Stringable\u003e(target : T, settingsOrMasks : MaskProps | string | string[]) : string\n```\n\n - **Class `Mask`**: application mask core\n\n```ts\nclass Mask {\n\n    static defaultPatterns: {\n        '#': RegExp;\n        '@': RegExp;\n        '?': RegExp;\n    };\n    static reverser(target: string): string;\n    static transform(target: string, type: Required\u003cMaskProps\u003e['transform']): string;\n    static padding(target: string | number, length: number, char?: string, left?: boolean): string;\n\n    constructor(props: MaskProps);\n\n    get props(): Readonly\u003cRequired\u003cMaskProps\u003e\u003e;\n    get completed(): boolean;\n    get cleaned(): string;\n    get entries(): number;\n\n    apply\u003cT extends Stringable\u003e(target: T): string;\n\n}\n```\n\n - **Constant `presets`**: preconfigured masks\n\n```ts\nconst presets: { [key in PresetOption]: MaskProps; }\n```\n\n - **Function `getPresetMask`**: get a preset, optionally being able to change its settings\n\n```ts\nfunction getPresetMask(preset: PresetOption, change: Partial\u003cMaskProps\u003e = {}): MaskProps\n```\n\n## MaskProps\n\nThe useMask receives the settings parameter of type MaskProps. See available settings:\n\n|Prop|Type|Default|Details|\n|---|---|---|---|\n|**masks**|`string`\u003cbr /\u003e`Array\u003cstring\u003e`||The masks that will be applied to the target. By default the characters `?`, `#`, `@` will be replaced by letters or numbers, numbers, letters, respectively. This character pattern can be changed. You can also use a Numerical Range to limit a numeric value to be entered using the pattern [\\\u003cnumber\\\u003e-\\\u003cnumber\\\u003e]. To escape a replacement character use `\\` before it.|\n|**placeholder**|`string`|`''`|Autofill of the mask to be filled|\n|**reverse**|`boolean`|`false`|Mask fill in inverted mode|\n|**transform**|`'uppercase'`\u003cbr /\u003e`'lowercase'`\u003cbr /\u003e`'capitalize'`\u003cbr /\u003e`'capitalizeAll'`\u003cbr /\u003e`'none'`|`'none'`|Apply a transformation to the result string|\n|**infinity**|`boolean`\u003cbr /\u003e`{each:number;add:string;}`|`false`|Allows data entry indefinitely by the last mask replacement character|\n|**maxentries**|`number`\u003cbr /\u003e`null`|`null`|If specified a number will limit the amount of user entries|\n|**patterns**|`{[key in string]: RegExp}`|`{'#': /[0-9]/,'@': /[A-Za-z]/,'?': /[A-Za-z0-9]/}`|Characters to be substituted in the mask if approved by the regular expression|\n\n## Presets\n\nYou can import pre-established mask configurations. See the options:\n\n- ONLY_NUMBERS\n- ONLY_LETTERS\n- ONLY_CHARS\n- DATE_STAMP\n- DATE_PTBR\n- DATETIME_STAMP\n- DATETIME_PTBR\n- DATE_STAMP_LIMITED\n- DATE_PTBR_LIMITED\n- DATETIME_STAMP_LIMITED\n- DATETIME_PTBR_LIMITED\n- PHONE_USA\n- PHONE_BR\n- CURRENCY_POINT\n- CURRENCY_COMMA\n- CURRENCY_DOLLAR\n- CURRENCY_PTBR\n- CURRENCY_DOLLAR_LIMITED\n- CURRENCY_PTBR_LIMITED\n- DOCUMENT_CPF\n- DOCUMENT_CNPJ\n- DOCUMENT_CPF_CNPJ\n- ZIPCODE_USA\n- ZIPCODE_BR\n- PRODUCT_KEY\n- COLOR_HEX\n- CAPITALIZE_ALL\n\n## Migrating v2 to v3\n\n*The third version of the mask-hooks package now has the numerical range feature.*\n\n## Author\n\n* **Guilherme Neves** - [github](https://github.com/guilhermeasn/) - [website](https://gn.dev.br/)\n\n## License\n\nThis project is under the MIT license - see file [LICENSE](https://github.com/guilhermeasn/mask-hooks/blob/master/LICENSE) for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguilhermeasn%2Fmask-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguilhermeasn%2Fmask-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguilhermeasn%2Fmask-hooks/lists"}