Full Code of Tinkoff/maskito for AI

main f79688db8ac1 cached
757 files
1.6 MB
432.2k tokens
503 symbols
1 requests
Download .txt
Showing preview only (1,898K chars total). Download the full file or copy to clipboard to get everything.
Repository: Tinkoff/maskito
Branch: main
Commit: f79688db8ac1
Files: 757
Total size: 1.6 MB

Directory structure:
gitextract_lbehwmqa/

├── .cspell.json
├── .editorconfig
├── .firebaserc
├── .github/
│   ├── CODEOWNERS
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug-report.yml
│   │   ├── 2-feature-request.yml
│   │   └── 3-documentation.yml
│   ├── renovate.json
│   └── workflows/
│       ├── assign-author.yml
│       ├── auto-merge.yml
│       ├── build.yml
│       ├── deploy-preview.yml
│       ├── deploy.yml
│       ├── e2e.yml
│       ├── lint.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .husky/
│   ├── commit-msg
│   └── pre-commit
├── .npmrc
├── .release-it.js
├── .ws-context
├── CHANGELOG.md
├── LICENSE
├── README.md
├── codecov.yml
├── eslint.config.ts
├── firebase.json
├── jest.config.ts
├── jest.preset.js
├── nx.json
├── package.json
├── projects/
│   ├── angular/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── ng-package.json
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   ├── maskito.directive.ts
│   │   │   │   ├── maskito.pipe.ts
│   │   │   │   ├── pattern.directive.ts
│   │   │   │   └── tests/
│   │   │   │       ├── maskito.directive.spec.ts
│   │   │   │       └── maskito.spec.ts
│   │   │   └── test-setup.ts
│   │   └── tsconfig.lib.prod.json
│   ├── core/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── classes/
│   │           │   ├── index.ts
│   │           │   ├── mask-history.ts
│   │           │   └── mask-model/
│   │           │       ├── mask-model.ts
│   │           │       ├── tests/
│   │           │       │   ├── dynamic-mask.spec.ts
│   │           │       │   └── mask-model-fixed-characters.spec.ts
│   │           │       └── utils/
│   │           │           ├── apply-overwrite-mode.ts
│   │           │           ├── calibrate-value-by-mask.ts
│   │           │           ├── get-leading-fixed-characters.ts
│   │           │           ├── guess-valid-value-by-pattern.ts
│   │           │           ├── guess-valid-value-by-reg-exp.ts
│   │           │           ├── is-fixed-character.ts
│   │           │           ├── remove-fixed-mask-characters.ts
│   │           │           └── validate-value-with-mask.ts
│   │           ├── constants/
│   │           │   ├── default-element-predicate.ts
│   │           │   ├── default-options.ts
│   │           │   └── index.ts
│   │           ├── mask.ts
│   │           ├── plugins/
│   │           │   ├── broken-prevent-default.plugin.ts
│   │           │   ├── change-event-plugin.ts
│   │           │   ├── double-space.plugin.ts
│   │           │   ├── index.ts
│   │           │   ├── initial-calibration-plugin.ts
│   │           │   └── strict-composition-plugin.ts
│   │           ├── types/
│   │           │   ├── element-predicate.ts
│   │           │   ├── element-state.ts
│   │           │   ├── index.ts
│   │           │   ├── mask-options.ts
│   │           │   ├── mask-processors.ts
│   │           │   ├── mask.ts
│   │           │   ├── maskito-element.ts
│   │           │   ├── plugin.ts
│   │           │   ├── selection-range.ts
│   │           │   └── typed-input-event.ts
│   │           └── utils/
│   │               ├── content-editable.ts
│   │               ├── dom/
│   │               │   ├── event-listener.ts
│   │               │   ├── get-content-editable-selection.ts
│   │               │   ├── history-events.ts
│   │               │   ├── hotkey.ts
│   │               │   ├── set-content-editable-selection.ts
│   │               │   └── update-element.ts
│   │               ├── element-states-equality.ts
│   │               ├── get-line-selection.ts
│   │               ├── get-not-empty-selection.ts
│   │               ├── get-word-selection.ts
│   │               ├── index.ts
│   │               ├── pipe.ts
│   │               ├── test/
│   │               │   ├── get-not-empty-selection.spec.ts
│   │               │   ├── get-word-selection.spec.ts
│   │               │   ├── pipe.spec.ts
│   │               │   └── transform.spec.ts
│   │               └── transform.ts
│   ├── demo/
│   │   ├── .gitignore
│   │   ├── esbuild-plugins/
│   │   │   ├── maskito-as-taiga-ui-dep.plugin.js
│   │   │   └── vue-esm.plugin.js
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── app/
│   │   │   │   ├── app.component.html
│   │   │   │   ├── app.component.spec.ts
│   │   │   │   ├── app.component.ts
│   │   │   │   ├── app.config.ts
│   │   │   │   ├── app.routes.ts
│   │   │   │   ├── app.style.less
│   │   │   │   ├── constants/
│   │   │   │   │   ├── demo-path.ts
│   │   │   │   │   ├── doc-example-primary-tab.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── modules/
│   │   │   │   │   ├── example-primary-tabs-icons/
│   │   │   │   │   │   ├── angular-logo.component.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── javascript-logo.component.ts
│   │   │   │   │   │   ├── react-logo.component.ts
│   │   │   │   │   │   └── vue-logo.component.ts
│   │   │   │   │   └── logo/
│   │   │   │   │       ├── logo.component.ts
│   │   │   │   │       ├── logo.style.less
│   │   │   │   │       └── logo.template.html
│   │   │   │   ├── server-error-handler.ts
│   │   │   │   └── utils/
│   │   │   │       ├── add-default-tabs-processor/
│   │   │   │       │   ├── add-default-tabs-processor.ts
│   │   │   │       │   └── default-tabs/
│   │   │   │       │       ├── angular-default-tab.ts
│   │   │   │       │       ├── js-default-tab.ts
│   │   │   │       │       ├── react-default-tab.ts
│   │   │   │       │       └── vue-default-tab.ts
│   │   │   │       └── index.ts
│   │   │   ├── assets/
│   │   │   │   └── manifest.webmanifest
│   │   │   ├── environments/
│   │   │   │   ├── environment.prod.ts
│   │   │   │   └── environment.ts
│   │   │   ├── index.html
│   │   │   ├── main.server.ts
│   │   │   ├── main.ts
│   │   │   ├── pages/
│   │   │   │   ├── documentation/
│   │   │   │   │   ├── browser-support/
│   │   │   │   │   │   ├── browser-support.component.ts
│   │   │   │   │   │   └── browser-support.template.html
│   │   │   │   │   ├── core-concepts-overview/
│   │   │   │   │   │   ├── core-concepts-overview.component.ts
│   │   │   │   │   │   ├── core-concepts-overview.styles.less
│   │   │   │   │   │   ├── core-concepts-overview.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── maskito-public-api-demo.md
│   │   │   │   │   ├── element-state/
│   │   │   │   │   │   ├── element-state.component.ts
│   │   │   │   │   │   ├── element-state.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── element-state-demo.md
│   │   │   │   │   ├── mask-expression/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── basic-time-example.md
│   │   │   │   │   │   │   ├── dynamic-mask-expression-demo.md
│   │   │   │   │   │   │   └── reg-exp-mask-expression-demo.md
│   │   │   │   │   │   ├── mask-expression.component.ts
│   │   │   │   │   │   └── mask-expression.template.html
│   │   │   │   │   ├── maskito-libraries/
│   │   │   │   │   │   ├── maskito-libraries.component.ts
│   │   │   │   │   │   └── maskito-libraries.template.html
│   │   │   │   │   ├── next-steps/
│   │   │   │   │   │   ├── next-steps.component.ts
│   │   │   │   │   │   └── next-steps.template.html
│   │   │   │   │   ├── overwrite-mode/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── dynamic/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── replace/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── shift/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── overwrite-mode.component.ts
│   │   │   │   │   │   └── overwrite-mode.template.html
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-initial-calibration/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   ├── index.md
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-strict-composition/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-change-event/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── oversimplified-number-mask.md
│   │   │   │   │   │   │   └── pads-zero-plugin.ts
│   │   │   │   │   │   ├── plugins.component.ts
│   │   │   │   │   │   ├── plugins.style.less
│   │   │   │   │   │   └── plugins.template.html
│   │   │   │   │   ├── processors/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── postprocessor-in-action.md
│   │   │   │   │   │   │   ├── preprocessor-first-arg-demo.md
│   │   │   │   │   │   │   ├── preprocessor-in-action-demo.md
│   │   │   │   │   │   │   └── processor-second-arg-demo.md
│   │   │   │   │   │   ├── processors.component.ts
│   │   │   │   │   │   └── processors.template.html
│   │   │   │   │   ├── real-world-form/
│   │   │   │   │   │   ├── index.html
│   │   │   │   │   │   ├── index.less
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── supported-input-types/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── password/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── search/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── tel/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── text/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── url/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── supported-input-types.component.ts
│   │   │   │   │   │   └── supported-input-types.template.html
│   │   │   │   │   ├── transformer/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   └── utility-in-action-demo.md
│   │   │   │   │   │   ├── transformer.component.ts
│   │   │   │   │   │   └── transformer.template.html
│   │   │   │   │   └── what-is-maskito/
│   │   │   │   │       ├── what-is-maskito.component.ts
│   │   │   │   │       ├── what-is-maskito.style.less
│   │   │   │   │       └── what-is-maskito.template.html
│   │   │   │   ├── frameworks/
│   │   │   │   │   ├── angular/
│   │   │   │   │   │   ├── angular-doc.component.ts
│   │   │   │   │   │   ├── angular-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-nested/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 2-nested/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 3-programmatically/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 4-pipe/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 5-custom-unmask-handler/
│   │   │   │   │   │       │   ├── index.html
│   │   │   │   │   │       │   ├── index.ts
│   │   │   │   │   │       │   └── unmask.directive.ts
│   │   │   │   │   │       ├── 6-pattern/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── basic-directive-approach.md
│   │   │   │   │   │       ├── custom-input-example.md
│   │   │   │   │   │       └── import-maskito.md
│   │   │   │   │   ├── react/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-use-maskito-basic-usage/
│   │   │   │   │   │   │   │   ├── example.component.tsx
│   │   │   │   │   │   │   │   └── useMaskitoBasicUsage.tsx
│   │   │   │   │   │   │   ├── 2-element-predicate/
│   │   │   │   │   │   │   │   ├── awesomeInput.tsx
│   │   │   │   │   │   │   │   ├── example.component.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── 3-merge-ref/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── 3-react-hook-form/
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── with-maskito-register.ts
│   │   │   │   │   │   │   ├── best-bad-practice.md
│   │   │   │   │   │   │   ├── controlled-input.md
│   │   │   │   │   │   │   └── merge-ref.md
│   │   │   │   │   │   ├── react-doc.component.ts
│   │   │   │   │   │   ├── react-doc.style.less
│   │   │   │   │   │   └── react-doc.template.html
│   │   │   │   │   └── vue/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── best-bad-practice.md
│   │   │   │   │       │   ├── query-nested-input.md
│   │   │   │   │       │   ├── use-maskito-basic-usage.md
│   │   │   │   │       │   └── vue-1/
│   │   │   │   │       │       └── component.ts
│   │   │   │   │       ├── vue-doc.component.ts
│   │   │   │   │       └── vue-doc.template.html
│   │   │   │   ├── kit/
│   │   │   │   │   ├── date/
│   │   │   │   │   │   ├── date-mask-doc.component.ts
│   │   │   │   │   │   ├── date-mask-doc.style.less
│   │   │   │   │   │   ├── date-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── maskito-parse-stringify-date-demo.md
│   │   │   │   │   ├── date-range/
│   │   │   │   │   │   ├── date-range-mask-doc.component.ts
│   │   │   │   │   │   ├── date-range-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-date-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 3-min-max-length/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── 4-range-separator/
│   │   │   │   │   │           ├── component.ts
│   │   │   │   │   │           └── mask.ts
│   │   │   │   │   ├── date-time/
│   │   │   │   │   │   ├── date-time-mask-doc.component.ts
│   │   │   │   │   │   ├── date-time-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-date-time-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-date-time-separator/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 3-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 4-time-step/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 5-am-pm/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── maskito-parse-stringify-date-time-demo.md
│   │   │   │   │   ├── number/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-high-precision/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-separators/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-postfix/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 4-decimal-zero-padding/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 5-custom-minus-sign/
│   │   │   │   │   │   │   │   ├── components.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 6-minus-before-prefix/
│   │   │   │   │   │   │   │   ├── components.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 7-dynamic-decimal-zero-padding/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 8-thousand-separator-pattern/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 9-thousand-separator-pattern-intl/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── helpers/
│   │   │   │   │   │   │   ├── parse-number-as-bigint-type.md
│   │   │   │   │   │   │   ├── parse-number-as-number-type.md
│   │   │   │   │   │   │   ├── parse-number-invalid-usage.md
│   │   │   │   │   │   │   └── stringify-number.md
│   │   │   │   │   │   ├── number-mask-doc.component.ts
│   │   │   │   │   │   └── number-mask-doc.template.html
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-selection-handler/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-caret-guard/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-event-handlers/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 4-reject/
│   │   │   │   │   │   │       ├── animation.css
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       ├── index.md
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── kit-plugins-doc.component.ts
│   │   │   │   │   │   └── kit-plugins-doc.template.html
│   │   │   │   │   └── time/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── 1-modes/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 2-am-pm/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 3-step/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 4-affixes/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 5-time-segments-min-max/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   └── maskito-parse-stringify-time-demo.md
│   │   │   │   │       ├── time-mask-doc.component.ts
│   │   │   │   │       ├── time-mask-doc.style.less
│   │   │   │   │       └── time-mask-doc.template.html
│   │   │   │   ├── pages.ts
│   │   │   │   ├── phone/
│   │   │   │   │   ├── examples/
│   │   │   │   │   │   ├── 1-basic/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 2-validation/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 3-non-strict/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 4-lazy-metadata/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── simple.md
│   │   │   │   │   │   ├── 5-focus-blur-events/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   └── 6-national-format/
│   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │       └── mask.ts
│   │   │   │   │   ├── phone-doc.component.ts
│   │   │   │   │   ├── phone-doc.style.less
│   │   │   │   │   └── phone-doc.template.html
│   │   │   │   ├── recipes/
│   │   │   │   │   ├── card/
│   │   │   │   │   │   ├── card-doc.component.ts
│   │   │   │   │   │   ├── card-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── 1-basic/
│   │   │   │   │   │           ├── component.ts
│   │   │   │   │   │           ├── style.less
│   │   │   │   │   │           └── template.html
│   │   │   │   │   ├── content-editable/
│   │   │   │   │   │   ├── content-editable-doc.component.ts
│   │   │   │   │   │   ├── content-editable-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-time/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-multi-line/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── maskito-with-content-editable.md
│   │   │   │   │   │       └── vanilla-js-tab.md
│   │   │   │   │   ├── network-address/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-ipv6/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-ipv4/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 3-mac/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── network-address-doc.component.ts
│   │   │   │   │   │   └── network-address-doc.template.html
│   │   │   │   │   ├── phone/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-us-phone/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-kz-phone/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       ├── mask.ts
│   │   │   │   │   │   │       └── template.html
│   │   │   │   │   │   ├── phone-doc.component.ts
│   │   │   │   │   │   └── phone-doc.template.html
│   │   │   │   │   ├── placeholder/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-cvc-code/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-phone/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 3-date/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── placeholder-doc.component.ts
│   │   │   │   │   │   └── placeholder-doc.template.html
│   │   │   │   │   ├── postfix/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-pattern-mask/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-postprocessor/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── postfix-doc.component.ts
│   │   │   │   │   │   └── postfix-doc.template.html
│   │   │   │   │   ├── prefix/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-pattern-mask/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-postprocessor/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── prefix-doc.component.ts
│   │   │   │   │   │   └── prefix-doc.template.html
│   │   │   │   │   └── textarea/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── 1-latin/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   └── maskito-with-textarea.md
│   │   │   │   │       ├── textarea-doc.component.ts
│   │   │   │   │       └── textarea-doc.template.html
│   │   │   │   └── stackblitz/
│   │   │   │       ├── components/
│   │   │   │       │   ├── stackblitz-edit-button/
│   │   │   │       │   │   ├── stackblitz-edit-button.component.ts
│   │   │   │       │   │   └── stackblitz-edit-button.style.less
│   │   │   │       │   └── stackblitz-starter/
│   │   │   │       │       ├── stackblitz-starter.component.ts
│   │   │   │       │       └── stackblitz-starter.style.less
│   │   │   │       ├── files/
│   │   │   │       │   ├── example.ts.md
│   │   │   │       │   ├── starter.ts.md
│   │   │   │       │   └── styles.css
│   │   │   │       ├── index.ts
│   │   │   │       └── stackblitz.service.ts
│   │   │   ├── server.ts
│   │   │   ├── styles.less
│   │   │   ├── test-setup.ts
│   │   │   └── typings.d.ts
│   │   ├── tsconfig.app.json
│   │   └── tsconfig.typecheck.json
│   ├── demo-integrations/
│   │   ├── cypress-react.config.ts
│   │   ├── cypress.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── fixtures/
│   │   │   │   └── example.json
│   │   │   ├── plugins/
│   │   │   │   └── index.js
│   │   │   ├── support/
│   │   │   │   ├── assertions/
│   │   │   │   │   ├── have-ng-control-value.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── commands/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── paste.ts
│   │   │   │   │   └── smart-tick.ts
│   │   │   │   ├── component-index.html
│   │   │   │   ├── component-react.ts
│   │   │   │   ├── component.ts
│   │   │   │   ├── constants/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── real-events-support.ts
│   │   │   │   └── e2e.ts
│   │   │   └── tests/
│   │   │       ├── addons/
│   │   │       │   └── phone/
│   │   │       │       ├── phone-basic.cy.ts
│   │   │       │       ├── phone-national-trunk-prefix.cy.ts
│   │   │       │       ├── phone-non-strict.cy.ts
│   │   │       │       ├── phone-separator.cy.ts
│   │   │       │       └── phone-strict.cy.ts
│   │   │       ├── angular/
│   │   │       │   ├── form-control-changes.cy.ts
│   │   │       │   └── unmask-handler.cy.ts
│   │   │       ├── component-testing/
│   │   │       │   ├── angular/
│   │   │       │   │   ├── disable-mask-on-null.cy.ts
│   │   │       │   │   └── pattern.cy.ts
│   │   │       │   ├── angular-predicate/
│   │   │       │   │   ├── angular-predicate.cy.ts
│   │   │       │   │   └── multi-test.component.ts
│   │   │       │   ├── change-event-plugin/
│   │   │       │   │   └── change-event-plugin.cy.ts
│   │   │       │   ├── initial-calibration-plugin/
│   │   │       │   │   └── dispatch-event.cy.ts
│   │   │       │   ├── multi-character-date-segment-separator/
│   │   │       │   │   └── multi-character-date-segment-separator.cy.ts
│   │   │       │   ├── native-max-length/
│   │   │       │   │   └── native-maxlength-attribute.cy.ts
│   │   │       │   ├── native-select-method/
│   │   │       │   │   └── native-select-method.cy.ts
│   │   │       │   ├── number/
│   │   │       │   │   ├── alone-decimal-separator.cy.ts
│   │   │       │   │   ├── min-max-bigint.cy.ts
│   │   │       │   │   ├── mirrored-prefix-postfix.cy.ts
│   │   │       │   │   ├── mirrored-value-postfix.cy.ts
│   │   │       │   │   ├── multi-character-prefix.cy.ts
│   │   │       │   │   ├── overwrite-selection-range.cy.ts
│   │   │       │   │   ├── postfix-multi-character.cy.ts
│   │   │       │   │   ├── postfix-with-point.cy.ts
│   │   │       │   │   ├── runtime-postfix-changes/
│   │   │       │   │   │   ├── runtime-postfix-changes.cy.ts
│   │   │       │   │   │   └── sandbox.component.ts
│   │   │       │   │   └── with-initial-value.cy.ts
│   │   │       │   ├── overwrite-mode/
│   │   │       │   │   └── overwrite-mode-replace.cy.ts
│   │   │       │   ├── paste/
│   │   │       │   │   └── cy-paste-utility.cy.ts
│   │   │       │   ├── phone/
│   │   │       │   │   ├── phone-national-format.cy.ts
│   │   │       │   │   └── phone-with-initial-value.cy.ts
│   │   │       │   ├── placeholder/
│   │   │       │   │   ├── placeholder-dispatch-input-events.cy.ts
│   │   │       │   │   ├── placeholder-has-same-characters-as-textfield.cy.ts
│   │   │       │   │   └── placeholder-partial-removal-on-blur.cy.ts
│   │   │       │   ├── react/
│   │   │       │   │   ├── async-predicate-options-race/
│   │   │       │   │   │   ├── reactApp.tsx
│   │   │       │   │   │   └── reactAsyncPredicateOptionsRace.cy.tsx
│   │   │       │   │   ├── async-predicates-race/
│   │   │       │   │   │   ├── reactApp.tsx
│   │   │       │   │   │   └── reactAsyncPredicatesRace.cy.tsx
│   │   │       │   │   ├── awesomeInput.tsx
│   │   │       │   │   └── change-event/
│   │   │       │   │       └── changeEvent.cy.tsx
│   │   │       │   └── utils.ts
│   │   │       ├── kit/
│   │   │       │   ├── date/
│   │   │       │   │   ├── date-basic.cy.ts
│   │   │       │   │   ├── date-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-min-max.cy.ts
│   │   │       │   │   ├── date-mode.cy.ts
│   │   │       │   │   ├── date-segments-zero-padding.cy.ts
│   │   │       │   │   └── date-separator.cy.ts
│   │   │       │   ├── date-range/
│   │   │       │   │   ├── date-range-basic.cy.ts
│   │   │       │   │   ├── date-range-custom-range-separator.cy.ts
│   │   │       │   │   ├── date-range-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-range-min-max-length.cy.ts
│   │   │       │   │   ├── date-range-min-max.cy.ts
│   │   │       │   │   ├── date-range-mode.cy.ts
│   │   │       │   │   ├── date-range-segments-zero-padding.cy.ts
│   │   │       │   │   └── date-range-separator.cy.ts
│   │   │       │   ├── date-time/
│   │   │       │   │   ├── date-time-basic.cy.ts
│   │   │       │   │   ├── date-time-date-time-separator.cy.ts
│   │   │       │   │   ├── date-time-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-time-meridiem.cy.ts
│   │   │       │   │   ├── date-time-min-max.cy.ts
│   │   │       │   │   ├── date-time-mode.cy.ts
│   │   │       │   │   ├── date-time-separator.cy.ts
│   │   │       │   │   └── date-time-time-step.cy.ts
│   │   │       │   ├── number/
│   │   │       │   │   ├── number-basic.cy.ts
│   │   │       │   │   ├── number-bigint.cy.ts
│   │   │       │   │   ├── number-decimal-separator.cy.ts
│   │   │       │   │   ├── number-decimal-zero-padding.cy.ts
│   │   │       │   │   ├── number-examples.cy.ts
│   │   │       │   │   ├── number-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── number-max-validation.cy.ts
│   │   │       │   │   ├── number-min-validation.cy.ts
│   │   │       │   │   ├── number-minus-before-prefix.cy.ts
│   │   │       │   │   ├── number-minus-sign.cy.ts
│   │   │       │   │   ├── number-precision.cy.ts
│   │   │       │   │   ├── number-prefix-postfix.cy.ts
│   │   │       │   │   ├── number-thousand-separator.cy.ts
│   │   │       │   │   ├── number-zero-integer-part.cy.ts
│   │   │       │   │   └── utils.ts
│   │   │       │   └── time/
│   │   │       │       ├── time-affixes.cy.ts
│   │   │       │       ├── time-basic.cy.ts
│   │   │       │       ├── time-fullwidth-to-halfwidth.cy.ts
│   │   │       │       ├── time-meridiem.cy.ts
│   │   │       │       ├── time-mode.cy.ts
│   │   │       │       ├── time-segment-max-values.cy.ts
│   │   │       │       └── time-step.cy.ts
│   │   │       ├── react/
│   │   │       │   └── element-predicate.cy.ts
│   │   │       ├── recipes/
│   │   │       │   ├── card/
│   │   │       │   │   └── card.cy.ts
│   │   │       │   ├── content-editable/
│   │   │       │   │   ├── multi-line.cy.ts
│   │   │       │   │   └── single-line-time-mask.cy.ts
│   │   │       │   ├── network-address/
│   │   │       │   │   ├── ipv4.cy.ts
│   │   │       │   │   ├── ipv6.cy.ts
│   │   │       │   │   └── mac.cy.ts
│   │   │       │   ├── phone/
│   │   │       │   │   └── phone.cy.ts
│   │   │       │   ├── placeholder/
│   │   │       │   │   ├── date.cy.ts
│   │   │       │   │   ├── us-phone.cy.ts
│   │   │       │   │   └── сvc-code.cy.ts
│   │   │       │   ├── plugins/
│   │   │       │   │   └── reject.cy.ts
│   │   │       │   ├── postfix/
│   │   │       │   │   ├── percentage.cy.ts
│   │   │       │   │   └── postprocessor.cy.ts
│   │   │       │   ├── prefix/
│   │   │       │   │   ├── dynamic-pattern-mask-expression.cy.ts
│   │   │       │   │   └── postprocessor.cy.ts
│   │   │       │   └── textarea/
│   │   │       │       └── textarea-latin-letters-digits.cy.ts
│   │   │       ├── ssr/
│   │   │       │   └── ssr.cy.ts
│   │   │       ├── utils.ts
│   │   │       └── vue/
│   │   │           └── vue.cy.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── kit/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── constants/
│   │           │   ├── date-segment-max-values.ts
│   │           │   ├── default-decimal-pseudo-separators.ts
│   │           │   ├── default-min-max-dates.ts
│   │           │   ├── default-pseudo-minuses.ts
│   │           │   ├── default-time-segment-bounds.ts
│   │           │   ├── index.ts
│   │           │   ├── meridiem.ts
│   │           │   ├── time-fixed-characters.ts
│   │           │   ├── time-segment-value-lengths.ts
│   │           │   └── unicode-characters.ts
│   │           ├── masks/
│   │           │   ├── date/
│   │           │   │   ├── date-mask.ts
│   │           │   │   ├── date-params.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── tests/
│   │           │   │   │   └── date-mask.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── index.ts
│   │           │   │       ├── parse-date.ts
│   │           │   │       ├── stringify-date.ts
│   │           │   │       ├── tests/
│   │           │   │       │   ├── parse-date.spec.ts
│   │           │   │       │   └── stringify-date.spec.ts
│   │           │   │       └── to-date-segments.ts
│   │           │   ├── date-range/
│   │           │   │   ├── constants.ts
│   │           │   │   ├── date-range-mask.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── processors/
│   │           │   │   │   ├── min-max-range-length-postprocessor.ts
│   │           │   │   │   └── swap-dates-postprocessor.ts
│   │           │   │   └── tests/
│   │           │   │       ├── date-segments-zero-padding.spec.ts
│   │           │   │       └── pseudo-range-separators.spec.ts
│   │           │   ├── date-time/
│   │           │   │   ├── constants/
│   │           │   │   │   ├── date-time-separator.ts
│   │           │   │   │   └── index.ts
│   │           │   │   ├── date-time-mask.ts
│   │           │   │   ├── date-time-params.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── postprocessors/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   └── min-max-date-time-postprocessor.ts
│   │           │   │   ├── preprocessors/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   └── valid-date-time-preprocessor.ts
│   │           │   │   ├── tests/
│   │           │   │   │   ├── date-segments-zero-padding.spec.ts
│   │           │   │   │   ├── date-time-separator.spec.ts
│   │           │   │   │   └── pseudo-date-end-separator.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── index.ts
│   │           │   │       ├── is-date-time-string-complete.ts
│   │           │   │       ├── parse-date-time.ts
│   │           │   │       ├── split-date-time-string.ts
│   │           │   │       ├── stringify-date-time.ts
│   │           │   │       └── tests/
│   │           │   │           ├── parse-date-time.spec.ts
│   │           │   │           ├── split-date-time-string.spec.ts
│   │           │   │           └── stringify-date-time.spec.ts
│   │           │   ├── number/
│   │           │   │   ├── index.ts
│   │           │   │   ├── number-mask.ts
│   │           │   │   ├── number-params.ts
│   │           │   │   ├── plugins/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   ├── leading-zeroes-validation.plugin.ts
│   │           │   │   │   ├── min-max.plugin.ts
│   │           │   │   │   └── not-empty-integer.plugin.ts
│   │           │   │   ├── processors/
│   │           │   │   │   ├── affixes-filter-preprocessor.ts
│   │           │   │   │   ├── decimal-zero-padding-postprocessor.ts
│   │           │   │   │   ├── empty-postprocessor.ts
│   │           │   │   │   ├── index.ts
│   │           │   │   │   ├── initialization-only-preprocessor.ts
│   │           │   │   │   ├── leading-minus-deletion-preprocessor.ts
│   │           │   │   │   ├── leading-zeroes-validation-postprocessor.ts
│   │           │   │   │   ├── min-max-postprocessor.ts
│   │           │   │   │   ├── non-removable-chars-deletion-preprocessor.ts
│   │           │   │   │   ├── not-empty-integer-part-preprocessor.ts
│   │           │   │   │   ├── number-prefix-postprocessor.ts
│   │           │   │   │   ├── pseudo-character-preprocessor.ts
│   │           │   │   │   ├── repeated-decimal-separator-preprocessor.ts
│   │           │   │   │   ├── tests/
│   │           │   │   │   │   ├── leading-zeroes-validation-postprocessor.spec.ts
│   │           │   │   │   │   └── not-empty-integer-part-preprocessor.spec.ts
│   │           │   │   │   ├── thousand-separator-postprocessor.ts
│   │           │   │   │   └── zero-precision-preprocessor.ts
│   │           │   │   ├── tests/
│   │           │   │   │   └── number-mask.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── extract-affixes.ts
│   │           │   │       ├── generate-mask-expression.ts
│   │           │   │       ├── index.ts
│   │           │   │       ├── number-parts.ts
│   │           │   │       ├── parse-number.ts
│   │           │   │       ├── stringify-number-without-exp.ts
│   │           │   │       ├── stringify-number.ts
│   │           │   │       ├── tests/
│   │           │   │       │   ├── parse-number.spec.ts
│   │           │   │       │   ├── stringify-number-without-exp.spec.ts
│   │           │   │       │   ├── stringify-number.spec.ts
│   │           │   │       │   ├── to-number-parts.spec.ts
│   │           │   │       │   └── validate-decimal-pseudo-separators.spec.ts
│   │           │   │       ├── validate-decimal-pseudo-separators.ts
│   │           │   │       └── with-number-defaults.ts
│   │           │   └── time/
│   │           │       ├── index.ts
│   │           │       ├── time-mask.ts
│   │           │       ├── time-params.ts
│   │           │       └── utils/
│   │           │           ├── index.ts
│   │           │           ├── parse-time.ts
│   │           │           ├── stringify-time.ts
│   │           │           └── tests/
│   │           │               ├── parse-time.spec.ts
│   │           │               └── stringify-time.spec.ts
│   │           ├── plugins/
│   │           │   ├── add-on-focus.ts
│   │           │   ├── caret-guard.ts
│   │           │   ├── event-handler.ts
│   │           │   ├── index.ts
│   │           │   ├── reject-event.ts
│   │           │   ├── remove-on-blur.ts
│   │           │   ├── selection-change.ts
│   │           │   └── time/
│   │           │       ├── meridiem-stepping.ts
│   │           │       └── time-segments-stepping.ts
│   │           ├── processors/
│   │           │   ├── colon-convert-preprocessor.ts
│   │           │   ├── date-segments-zero-padding-postprocessor.ts
│   │           │   ├── first-date-end-separator-preprocessor.ts
│   │           │   ├── fullwidth-to-halfwidth-preprocessor.ts
│   │           │   ├── index.ts
│   │           │   ├── invalid-time-segment-insertion-preprocessor.ts
│   │           │   ├── meridiem-processors.ts
│   │           │   ├── min-max-date-postprocessor.ts
│   │           │   ├── normalize-date-preprocessor.ts
│   │           │   ├── postfix-postprocessor.ts
│   │           │   ├── prefix-postprocessor.ts
│   │           │   ├── tests/
│   │           │   │   ├── first-date-end-separator-preprocessor.spec.ts
│   │           │   │   ├── normalize-date-preprocessor.spec.ts
│   │           │   │   ├── postfix-postprocessor.spec.ts
│   │           │   │   ├── prefix-postprocessor.spec.ts
│   │           │   │   ├── valid-date-preprocessor.spec.ts
│   │           │   │   └── with-placeholder.spec.ts
│   │           │   ├── valid-date-preprocessor.ts
│   │           │   ├── with-placeholder.ts
│   │           │   └── zero-placeholders-preprocessor.ts
│   │           ├── types/
│   │           │   ├── date-mode.ts
│   │           │   ├── date-segments.ts
│   │           │   ├── index.ts
│   │           │   ├── time-mode.ts
│   │           │   └── time-segments.ts
│   │           └── utils/
│   │               ├── clamp.ts
│   │               ├── count-digits.ts
│   │               ├── date/
│   │               │   ├── append-date.ts
│   │               │   ├── date-segment-value-length.ts
│   │               │   ├── date-to-segments.ts
│   │               │   ├── get-date-segments-order.ts
│   │               │   ├── get-first-complete-date.ts
│   │               │   ├── is-date-string-complete.ts
│   │               │   ├── parse-date-range-string.ts
│   │               │   ├── parse-date-string.ts
│   │               │   ├── raise-segment-value-to-min.ts
│   │               │   ├── segments-to-date.ts
│   │               │   ├── tests/
│   │               │   │   ├── append-date.spec.ts
│   │               │   │   ├── get-date-segment-value-length.spec.ts
│   │               │   │   └── parse-date-range-string.spec.ts
│   │               │   ├── to-date-string.ts
│   │               │   └── validate-date-string.ts
│   │               ├── dummy.ts
│   │               ├── escape-reg-exp.ts
│   │               ├── find-common-beginning-substr.ts
│   │               ├── index.ts
│   │               ├── is-empty.ts
│   │               ├── pad-with-zeroes-until-valid.ts
│   │               ├── tests/
│   │               │   ├── clamp.spec.ts
│   │               │   ├── escape-reg-exp.spec.ts
│   │               │   ├── find-common-beginning-substr.spec.ts
│   │               │   ├── get-first-complete-date.spec.ts
│   │               │   ├── is-empty.spec.ts
│   │               │   ├── to-half-width-colon.spec.ts
│   │               │   └── to-half-width-number.spec.ts
│   │               ├── time/
│   │               │   ├── create-time-mask-expression.ts
│   │               │   ├── enrich-time-segments-with-zeroes.ts
│   │               │   ├── index.ts
│   │               │   ├── pad-end-time-segments.ts
│   │               │   ├── pad-start-time-segments.ts
│   │               │   ├── pad-time-segments.ts
│   │               │   ├── parse-time-string.ts
│   │               │   ├── tests/
│   │               │   │   ├── enrich-time-segments-with-zeroes.spec.ts
│   │               │   │   ├── parse-time-string.spec.ts
│   │               │   │   └── to-time-string.spec.ts
│   │               │   └── to-time-string.ts
│   │               ├── to-half-width-colon.ts
│   │               └── to-half-width-number.ts
│   ├── phone/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           └── masks/
│   │               ├── index.ts
│   │               └── phone/
│   │                   ├── constants/
│   │                   │   ├── index.ts
│   │                   │   └── template-filler.ts
│   │                   ├── index.ts
│   │                   ├── phone-mask-non-strict.ts
│   │                   ├── phone-mask-strict.ts
│   │                   ├── phone-mask.ts
│   │                   ├── processors/
│   │                   │   ├── browser-autofill-preprocessor.ts
│   │                   │   ├── cut-init-country-code-preprocessor.ts
│   │                   │   ├── index.ts
│   │                   │   ├── paste-non-strict-phone-preprocessor.ts
│   │                   │   ├── paste-strict-phone-preprocessor.ts
│   │                   │   ├── phone-length-postprocessor.ts
│   │                   │   └── sanitize-phone-preprocessor.ts
│   │                   ├── tests/
│   │                   │   ├── get-phone-template.spec.ts
│   │                   │   └── phone-mask.spec.ts
│   │                   └── utils/
│   │                       ├── cut-phone-by-valid-length.ts
│   │                       ├── generate-phone-mask.ts
│   │                       ├── get-country-from-number.ts
│   │                       ├── get-phone-template.ts
│   │                       ├── index.ts
│   │                       └── select-template.ts
│   ├── react/
│   │   ├── .babelrc
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── adaptControlledElement.tsx
│   │           ├── tests/
│   │           │   ├── controlledInput.spec.tsx
│   │           │   ├── elementPredicate.spec.tsx
│   │           │   └── useMaskito.spec.tsx
│   │           ├── useIsomorphicLayoutEffect.tsx
│   │           └── useMaskito.tsx
│   └── vue/
│       ├── README.md
│       ├── jest.config.ts
│       ├── package.json
│       ├── project.json
│       └── src/
│           ├── index.ts
│           └── lib/
│               ├── maskito.spec.ts
│               └── maskito.ts
├── tsconfig.build.json
├── tsconfig.json
└── tsconfig.spec.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .cspell.json
================================================
{
    "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json",
    "import": ["@taiga-ui/cspell-config"],
    "files": ["*/*.*"],
    "ignorePaths": [
        ".git",
        ".gitignore",
        ".npmrc",
        ".cspell.json",
        "**/dist/**",
        "**/assets/**",
        "**/node_modules/**",
        "**/demo/server.ts",
        "**/demo-integrations/src/tests/**",
        "*.{log,svg,snap,png,ogv,yml}",
        "**/package.json",
        "**/tsconfig*.json"
    ],
    "ignoreWords": ["Acpekt", "WHATWG", "prebundle"]
}


================================================
FILE: .editorconfig
================================================
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false


================================================
FILE: .firebaserc
================================================
{
  "projects": {
    "default": "maskito"
  }
}


================================================
FILE: .github/CODEOWNERS
================================================
* @taiga-family/core-team


================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making
participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education,
socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take
appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
project or its community. Examples of representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed representative at an online or offline
event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project at
opensource@acpekt.ru. All complaints will be reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to
the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing

> Thank you for considering contributing to our project. Your help if very welcome!

When contributing, it's better to first discuss the change you wish to make via issue, email, or any other method with
the owners of this repository before making a change.

All members of our community are expected to follow our [Code of Conduct](.github/CODE_OF_CONDUCT.md). Please make sure
you are welcoming and friendly in all of our spaces.

## Getting started

In order to make your contribution please make a fork of the repository. After you've pulled the code, follow these
steps to kick-start the development:

1. Run `npm ci` to install dependencies
2. Run `npm start` to launch demo project where you could test your changes
3. Use following commands to ensure code quality

```bash
npm run lint
npm run build
npm run test
npm run cy:run
```

## Pull Request Process

1. We follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) in our commit messages, i.e.
   `feat(core): improve typing`
2. Update [demo](projects/demo) application to reflect changes related to public API and everything relevant
3. Make sure you cover all code changes with unit tests and/or [Cypress](https://www.cypress.io) tests
4. When you are ready, create Pull Request of your fork into original repository


================================================
FILE: .github/ISSUE_TEMPLATE/1-bug-report.yml
================================================
name: '🐞 - Bug Report'
title: '🐞 - '
description: Report a bug in the Maskito
labels: ['bug']
type: Bug

body:
  - type: dropdown
    id: affected-packages
    attributes:
      label: Which package(s) are the source of the bug?
      options:
        - '@maskito/core'
        - '@maskito/kit'
        - '@maskito/phone'
        - '@maskito/angular'
        - '@maskito/react'
        - '@maskito/vue'
        - Don't known / other
      multiple: true
    validations:
      required: true

  - type: input
    id: playground-link
    attributes:
      label: Playground Link
      description: |
        Link to an isolated reproduction in our [StackBlitz playground](https://maskito.dev/stackblitz).

        If either of the following holds true:
        - You can't reproduce the issue in the playground
        - Your issue requires some complex setup - such as multiple files or a specific folder structure.

        So you can use any link that might help for reproduction bug: github repo, demo url, etc.

        ***Help us to help you!***
      placeholder: https://stackblitz.com/edit/...
    validations:
      required: true

  - type: textarea
    id: description
    attributes:
      label: Description
      placeholder: |
        Please provide the exception or error you saw.
        How do you trigger this bug?
        Please walk us through it step by step.
        Please provide a screenshot if possible.
    validations:
      required: true

  - type: input
    id: maskito-version
    attributes:
      label: Maskito version
      placeholder: x.y.z
    validations:
      required: true

  - type: checkboxes
    id: browser-specific
    attributes:
      label: Which browsers have you used?
      description: You may select more than one.
      options:
        - label: Chrome
        - label: Firefox
        - label: Safari
        - label: Edge

  - type: checkboxes
    id: operating-systems
    attributes:
      label: Which operating systems have you used?
      description: You may select more than one.
      options:
        - label: macOS
        - label: Windows
        - label: Linux
        - label: iOS
        - label: Android


================================================
FILE: .github/ISSUE_TEMPLATE/2-feature-request.yml
================================================
name: '🚀 - Feature Request'
title: '🚀 - '
description: Suggest a feature for Maskito
labels: ['feature']
type: Feature

body:
  - type: dropdown
    id: affected-packages
    attributes:
      label: Which package(s) are relevant/related to the feature request?
      options:
        - '@maskito/core'
        - '@maskito/kit'
        - '@maskito/phone'
        - '@maskito/angular'
        - '@maskito/react'
        - '@maskito/vue'
        - Don't known / other
      multiple: true

  - type: textarea
    id: description
    attributes:
      label: Description
      placeholder: |
        Proposed solution.
        Alternatives considered.
    validations:
      required: true


================================================
FILE: .github/ISSUE_TEMPLATE/3-documentation.yml
================================================
name: '📚 - Documentation'
title: '📚 - '
description: Report an issue in Maskito's documentation
labels: ['documentation']
type: Documentation

body:
  - type: input
    id: affected-url
    attributes:
      label: What is the affected URL?

  - type: textarea
    id: description
    attributes:
      label: Description
      placeholder: |
        How do you trigger this bug?
        Please walk us through it step by step.
        Please provide a screenshot if possible.
    validations:
      required: true

  - type: checkboxes
    id: browser-specific
    attributes:
      label: Which browsers have you used?
      description: You may select more than one.
      options:
        - label: Chrome
        - label: Firefox
        - label: Safari
        - label: Edge

  - type: checkboxes
    id: operating-systems
    attributes:
      label: Which operating systems have you used?
      description: You may select more than one.
      options:
        - label: macOS
        - label: Windows
        - label: Linux
        - label: iOS
        - label: Android


================================================
FILE: .github/renovate.json
================================================
{
    "$schema": "https://docs.renovatebot.com/renovate-schema.json",
    "extends": ["github>taiga-family/renovate-config"],
    "packageRules": [
        {
            "enabled": false,
            "matchPackageNames": [
                "/^@nx.*/",
                "/^nx$/",
                "cypress"
            ]
        },
        {
            "enabled": false,
            "matchPackageNames": ["jest-preset-angular"]
        }
    ]
}


================================================
FILE: .github/workflows/assign-author.yml
================================================
name: 🤖 PR author as an assignee
on:
  pull_request:
    types: [opened]

jobs:
  assign:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: toshimaru/auto-author-assign@v3.0.1
        continue-on-error: true

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/auto-merge.yml
================================================
name: 🤖 PR auto merge
on:
  pull_request:

env:
  PR_JOBS_NAME: '[ "Packages", "Demo", "Firebase", "Lint result", "tests", "E2E result" ]'

jobs:
  setup:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.matrix.outputs.value }}
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - id: matrix
        run: echo "value=$PR_JOBS_NAME" >> $GITHUB_OUTPUT

  wait:
    needs: [setup]
    runs-on: ubuntu-latest
    strategy:
      fail-fast: true
      matrix:
        value: ${{ fromJSON(needs.setup.outputs.matrix) }}
    steps:
      - uses: taiga-family/ci/actions/run/wait-job@v1.201.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          job: ${{ matrix.value }}

  approve:
    needs: [wait]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/auto/approve/double@v1.201.0
        if: env.IS_TAIGA_FAMILY_BOT_PR_AUTHOR == 'true'
        with:
          token1: ${{ secrets.GITHUB_TOKEN }}
          token2: ${{ secrets.TAIGA_FAMILY_APPROVE_BOT_PAT }}
      - uses: taiga-family/ci/actions/run/merge@v1.201.0
        if: env.IS_TAIGA_FAMILY_BOT_PR_AUTHOR == 'true'
        with:
          token: ${{ secrets.TAIGA_FAMILY_BOT_PAT }}

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/build.yml
================================================
name: Build
on:
  pull_request:
  push:
    branches: [main]

jobs:
  build-packages:
    name: Packages
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npx nx run-many --target build --all --exclude=demo

  build-demo:
    name: Demo
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npx nx build-gh-pages

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/deploy-preview.yml
================================================
name: Deploy / preview

on: pull_request

jobs:
  build_and_preview:
    name: Firebase
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npx nx run-many --target build --all --exclude=demo
      - run: npx nx run demo:build:typecheck

      - name: Debug output
        run: tree dist/demo/browser -P '*.html'
      - name: Deploy preview
        uses: FirebaseExtended/action-hosting-deploy@v0.10.0
        if: env.IS_OWNER_MODE == 'true'
        with:
          repoToken: ${{ secrets.GITHUB_TOKEN }}
          firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_MASKITO }}
          projectId: maskito
          expires: 1d

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/deploy.yml
================================================
name: Deploy
on:
  workflow_dispatch:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, 'chore(release)') }}
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npx nx build-gh-pages
      - uses: JamesIves/github-pages-deploy-action@v4.8.0
        with:
          branch: gh-pages
          folder: dist/demo/browser
          silent: false
          clean: true

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/e2e.yml
================================================
name: E2E
on: [pull_request]

env:
  CACHE_DIST_KEY: dist-${{ github.ref }}-${{ github.sha }}
  CYPRESS_CACHE_FOLDER: ./node_modules/cache-cypress
  UNIVERSAL_SERVER: http://localhost:4000
  STATIC_SERVER: http://localhost:8080

jobs:
  build-demo:
    name: Build demo
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 10

      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npx tsc --project projects/demo-integrations/tsconfig.json

      - name: Mark demo-app directory for persist in cache
        uses: actions/cache@v5
        with:
          path: dist/demo
          key: ${{ env.CACHE_DIST_KEY }}

      - name: Build demo
        # --optimization false to keep `window.ng` inside Cypress tests
        run: npm run build -- --optimization false

  e2e-kit:
    needs: [build-demo]
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        project: [date, date-range, date-time, number, time]
    name: Kit / ${{ matrix.project }}
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - uses: taiga-family/ci/actions/setup/cypress@v1.201.0

      - name: Download demo build from cache
        uses: actions/cache@v5
        with:
          path: dist/demo
          key: ${{ env.CACHE_DIST_KEY }}

      - name: Serving SSR server
        run: |
          npm run serve:ssr -- --ci & sleep 5
          curl -X GET -I -f "${{ env.UNIVERSAL_SERVER }}"

      - name: Run Cypress tests
        run:
          npx nx e2e demo-integrations --spec="**/kit/${{ matrix.project }}/**/*.cy.ts" --baseUrl=${{
          env.UNIVERSAL_SERVER}}

  e2e-recipes:
    needs: [build-demo]
    runs-on: ubuntu-latest
    name: Recipes
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - uses: taiga-family/ci/actions/setup/cypress@v1.201.0

      - name: Download demo build from cache
        uses: actions/cache@v5
        with:
          path: dist/demo
          key: ${{ env.CACHE_DIST_KEY }}

      - name: Serving SSR server
        run: |
          npm run serve:ssr -- --ci & sleep 5
          curl -X GET -I -f "${{ env.UNIVERSAL_SERVER }}"

      - name: Run Cypress tests
        run: npx nx e2e demo-integrations --spec="**/recipes/**/*.cy.ts" --baseUrl=${{ env.UNIVERSAL_SERVER}}

  e2e-others:
    needs: [build-demo]
    runs-on: ubuntu-latest
    name: Others
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - uses: taiga-family/ci/actions/setup/cypress@v1.201.0

      - name: Download demo build from cache
        uses: actions/cache@v5
        with:
          path: dist/demo
          key: ${{ env.CACHE_DIST_KEY }}

      - name: Serving SSR server
        run: |
          npm run serve:ssr -- --ci & sleep 5
          curl -X GET -I -f "${{ env.UNIVERSAL_SERVER }}"

      - name: Run Cypress tests
        # Replace with npm run cy:run -- --spec "**/!(kit|recipes)/*.cy.ts" --config baseUrl="${{ env.UNIVERSAL_SERVER }}"
        # After this issue fix: https://github.com/cypress-io/cypress/issues/22407
        run:
          npx nx e2e demo-integrations --spec="**/(angular|react|ssr|addons|others)/**/*.cy.ts" --baseUrl=${{
          env.UNIVERSAL_SERVER}}

  component-testing:
    runs-on: ubuntu-latest
    name: Component Testing
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - uses: taiga-family/ci/actions/setup/cypress@v1.201.0

      - name: Run Cypress tests
        run:
          npx nx component-test demo-integrations --browser=chrome && npx nx ct-react demo-integrations --browser=chrome

  result:
    needs: [build-demo, e2e-kit, e2e-recipes, e2e-others, component-testing]
    runs-on: ubuntu-latest
    name: E2E result
    steps:
      - run: echo "Success"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint
on: [pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npm run typecheck

  cspell:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npm run cspell -- --no-progress

  prettier:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          persist-credentials: false
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npm run prettier ${{ env.SUPPORT_AUTO_PUSH == 'true' && '-- --write' || '-- --check' }}
      - uses: taiga-family/ci/actions/auto/push@v1.201.0
        with:
          token: ${{ secrets.TAIGA_FAMILY_BOT_PAT }}

  stylelint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          persist-credentials: false
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npm run stylelint ${{ env.SUPPORT_AUTO_PUSH == 'true' && '-- --fix' || '' }}
      - uses: taiga-family/ci/actions/auto/push@v1.201.0
        with:
          token: ${{ secrets.TAIGA_FAMILY_BOT_PAT }}

  eslint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          persist-credentials: false
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - run: npm run lint ${{ env.SUPPORT_AUTO_PUSH == 'true' && '-- --fix' || '' }}
      - uses: taiga-family/ci/actions/auto/push@v1.201.0
        with:
          token: ${{ secrets.TAIGA_FAMILY_BOT_PAT }}

  result:
    needs: [typecheck, cspell, prettier, stylelint, eslint]
    runs-on: ubuntu-latest
    name: Lint result
    steps:
      - run: echo "Success"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/release.yml
================================================
name: ⚠️ Release

on:
  workflow_dispatch:
    inputs:
      mode:
        type: choice
        description: Bump version as requested
        required: true
        options:
          - patch
          - minor
          - alpha
          - major

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0
      - uses: taiga-family/ci/actions/run/release-it@v1.201.0
        id: release-it
        with:
          ref: ${{ github.ref }}
          mode: ${{ github.event.inputs.mode }}
          npmToken: ${{ secrets.NPM_TOKEN }}
          githubToken: ${{ secrets.TAIGA_FAMILY_BOT_PAT }}

      - uses: taiga-family/ci/actions/run/read-package-json@v1.201.0
        id: info

      - name: Announce to Telegram
        if: steps.release-it.outputs.released == 'true'
        uses: taiga-family/ci/actions/messenger/telegram/announce@v1.201.0
        with:
          chatId: ${{ secrets.TAIGA_TELEGRAM_CHAT_ID }}
          topicId: ${{ secrets.TAIGA_TELEGRAM_CHAT_THREAD_ID }}
          token: ${{ secrets.TAIGA_TELEGRAM_BOT_TOKEN }}
          version: v${{ steps.info.outputs.version }}
          textLink: '@maskito/core'

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .github/workflows/test.yml
================================================
name: Tests

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: taiga-family/ci/actions/setup/variables@v1.201.0
      - uses: taiga-family/ci/actions/setup/node@v1.201.0

      - name: Run tests
        run: npx nx run-many --target test --all --coverage

      - name: Archive coverage artifacts
        uses: actions/upload-artifact@v7.0.1
        with:
          name: coverage-${{ github.workflow }}-${{ github.run_id }}
          path: coverage

  codecov:
    name: Collect coverage
    needs: [tests]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
      - uses: actions/download-artifact@v8.0.1
        with:
          name: coverage-${{ github.workflow }}-${{ github.run_id }}
          path: coverage

      - name: Display structure of coverage files
        run: tree -L 2 ./coverage -P 'lcov.info'

      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/core/
          flags: summary,core
          name: core
      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/kit/
          flags: summary,kit
          name: kit
      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/phone/
          flags: summary,phone
          name: phone
      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/angular/
          flags: summary,angular
          name: angular
      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/react/
          flags: summary,react
          name: react
      - uses: codecov/codecov-action@v6.0.0
        with:
          directory: ./coverage/vue/
          flags: summary,vue
          name: vue

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


================================================
FILE: .gitignore
================================================
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out

# dependencies
**/node_modules/

# profiling files
chrome-profiler-events.json
speed-measure-plugin.json

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
*.iml
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# misc
/.angular/cache
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db

# cypress
**/cypress/**/screenshots/**
projects/demo-integrations/cypress

.nx
.ssl
RELEASE_BODY.md
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md
.rollup.cache


================================================
FILE: .husky/commit-msg
================================================
npx --no -- commitlint --edit $1


================================================
FILE: .husky/pre-commit
================================================
npx lint-staged
npm run typecheck


================================================
FILE: .npmrc
================================================
engine-strict=true
loglevel=error


================================================
FILE: .release-it.js
================================================
module.exports = require('@taiga-ui/release-it-config');


================================================
FILE: .ws-context
================================================
{
    "framework": "angular",
    "projects/vue/**": {
        "framework": "vue"
    },
    "projects/react/**": {
        "framework": "react"
    }
}


================================================
FILE: CHANGELOG.md
================================================
### [5.2.2](https://github.com/taiga-family/maskito/compare/v5.2.1...v5.2.2) (2026-03-31)

### 🐞 Bug Fixes

- **kit**: `Number` with `negativePattern=minusFirst` + `prefix` has unexpected caret shift on minus insertion (#2616)
  [(1d7bc77)](https://github.com/taiga-family/maskito/commit/1d7bc7761f1e4c7dad3b01b6c651295dd6d31bc4)
- **kit**: `Number` should ignore digits in affixes for `min`/`max` validation (#2615)
  [(227a860)](https://github.com/taiga-family/maskito/commit/227a860453b4d0cee42a96e8ef06d155a44cce06)

### [5.2.1](https://github.com/taiga-family/maskito/compare/v5.2.0...v5.2.1) (2026-03-27)

### 🐞 Bug Fixes

- **react**: omitted `d.ts` files (#2607)
  [(a10e118)](https://github.com/taiga-family/maskito/commit/a10e1187c81cfd4af8935edd7d459c3e6b5c6cc4)
- **kit**: `maskitoParseNumber` incorrectly parses postfix containing digits (#2600)
  [(4805166)](https://github.com/taiga-family/maskito/commit/48051666d3235fe72c5bc90d83405175905ec7fa)

### [5.2.0](https://github.com/taiga-family/maskito/compare/v5.1.2...v5.2.0) (2026-03-25)

### 🚀 Features

- **kit**: `Number` supports `thousandSeparatorPattern` (#2584)
  [(f4e1340)](https://github.com/taiga-family/maskito/commit/f4e1340ddedd8abf04c181c8db31edf420564845)

### 🐞 Bug Fixes

- **kit**: validate digit count in time segment for `maskitoParseDateTime` (#2581)
  [(9c3e9bc)](https://github.com/taiga-family/maskito/commit/9c3e9bccc046be9e9a91ea05255bf55985144df1)

### [5.1.2](https://github.com/taiga-family/maskito/compare/v5.1.1...v5.1.2) (2026-03-13)

### 🐞 Bug Fixes

- **kit**: `maskitoParseDate` & `maskitoParseDateTime` supports parsing of dates in formats `mm/dd`, `dd/mm` (#2577)
  [(a0f073b)](https://github.com/taiga-family/maskito/commit/a0f073b26b3be0d6bf776d970adc65c745cb3d41)
- **kit**: `maskitoParseDate` should return `null` for invalid `Date` string (#2561)
  [(cf2b5f2)](https://github.com/taiga-family/maskito/commit/cf2b5f206a6679d2171bfd25fdc969ffee6dad7f)

### [5.1.1](https://github.com/taiga-family/maskito/compare/v5.1.0...v5.1.1) (2026-02-16)

### 🐞 Bug Fixes

- **kit**: `maskitoStringifyDate` incorrectly formats year with leading zeroes (#2538)
  [(9817f08)](https://github.com/taiga-family/maskito/commit/9817f084dd34628afd1bebe8070189edf8f3fd1f)
- **kit**: `Number` deletes the previous non-selected character on the first deletion (#2537)
  [(40ef2e0)](https://github.com/taiga-family/maskito/commit/40ef2e03b8ecaf564a1d4f055b8d629ba8932370)
- **phone**: `Phone` preserves previously entered digits on new digits paste (#2481)
  [(f836f4f)](https://github.com/taiga-family/maskito/commit/f836f4f5ec94d865a2bcb44960161cfe25fe3a64)

## [5.1.0](https://github.com/taiga-family/maskito/compare/v5.0.1...v5.1.0) (2026-01-22)

### 🚀 Features

- **phone:** `Phone` supports national format ([#2461](https://github.com/taiga-family/maskito/issues/2461))
  ([c90bca2](https://github.com/taiga-family/maskito/commit/c90bca2c2f0f3bc3746a2559fc84bd688075c1be))

### 🐞Bug Fixes

- **kit:** `Number` fails to dynamically change postfix ([#2501](https://github.com/taiga-family/maskito/issues/2501))
  ([cd73d6a](https://github.com/taiga-family/maskito/commit/cd73d6a729068e4b301509b12def6e149a7b5d66))
- **kit:** `Number` throws `Failed to parse String to BigInt` error
  ([#2509](https://github.com/taiga-family/maskito/issues/2509))
  ([7b80f79](https://github.com/taiga-family/maskito/commit/7b80f79140740462d3d924ba49993e1376d2b6e3))
- **react:** `useMaskito` should destroy Maskito instance if element is detached from the DOM
  ([#2507](https://github.com/taiga-family/maskito/issues/2507))
  ([1cdb203](https://github.com/taiga-family/maskito/commit/1cdb20359aaf4fa479420638d76bc7b238a6cb4c))

### [5.0.1](https://github.com/taiga-family/maskito/compare/v5.0.0...v5.0.1) (2025-12-26)

### 🐞 Bug Fixes

- **phone**: `Phone` removes last digit if pasted without '+' (#2480)
  [(5d709ca)](https://github.com/taiga-family/maskito/commit/5d709ca9c2e4a8abbe99a38c47551a9e6b2d8d36)
- **kit**: `maskitoStringifyNumber` supports extremal exponent values (#2463)
  [(1340257)](https://github.com/taiga-family/maskito/commit/1340257486a86499f94c96dbe67949ada32ebae4)
- **phone**: `Phone` with initial value has problems with the first time delete action (#2455)
  [(fa596fa)](https://github.com/taiga-family/maskito/commit/fa596fa101333b519bc3d760d6f4969151178e1a)

## [5.0.0](https://github.com/taiga-family/maskito/compare/v4.0.1...v5.0.0) (2025-12-03)

### ⚠ BREAKING CHANGES

- Bump Safari browser support (#2439)

  |                | < 5.0.0 | ≥ 5.0.0 |
  | -------------- | ------- | ------- |
  | Safari Desktop | 13.1+   | 14.1+   |
  | Safari Mobile  | 13.4+   | 14.5+   |

- **kit**: `Number` supports `BigInt` (#2431)
  [(2d2f86d)](https://github.com/taiga-family/maskito/commit/2d2f86dafb1524528305908af27b4df37d9e1330)

  New default values for `maskitoNumberOptionsGenerator` / `maskitoStringifyNumber`:

  | MaskitoNumberParams | < 5.0.0                   | ≥ 5.0.0     |
  | ------------------- | ------------------------- | ----------- |
  | `min`               | `Number.MIN_SAFE_INTEGER` | `-Infinity` |
  | `max`               | `Number.MAX_SAFE_INTEGER` | `Infinity`  |

### [4.0.1](https://github.com/taiga-family/maskito/compare/v4.0.0...v4.0.1) (2025-11-14)

### 🐞 Bug Fixes

- **kit**: `Time` with `[step]` ignores `timeSegmentMinValues` on arrow stepping (#2420)
  [(398a5c1)](https://github.com/taiga-family/maskito/commit/398a5c163d03502d413ca15c8756f41891b75197)
- **kit**: `DateRange` with `[minLength]` & `[maxLength]` incorrectly appends month in backward direction (#2369)
  [(3c80959)](https://github.com/taiga-family/maskito/commit/3c80959773a4c44b29e70a420bc1fc6e074030b9)

## [4.0.0](https://github.com/taiga-family/maskito/compare/v3.11.1...v4.0.0) (2025-10-13)

### ⚠ BREAKING CHANGES

- **kit**: delete deprecated `precision` & `decimalZeroPadding` parameters from `Number` mask (#2354)

  **Previous behavior:**

  ```ts
  import {maskitoNumberOptionsGenerator} from '@maskito/kit';

  const options = maskitoNumberOptionsGenerator({
    precision: 2, // ---> Use `maximumFractionDigits` instead
    decimalZeroPadding: true, // ---> Use `minimumFractionDigits` instead
  });
  ```

  <p align="center">⬇️ </p>

  **New behavior**:

  ```ts
  import {maskitoNumberOptionsGenerator} from '@maskito/kit';

  const options = maskitoNumberOptionsGenerator({
    maximumFractionDigits: 2,
    minimumFractionDigits: 2,
  });
  ```

- **kit**: `maskitoParseNumber` accepts only `MaskitoNumberParams` as the 2nd argument (#2355)

  **Previous behavior:**

  ```ts
  import {maskitoParseNumber} from '@maskito/kit';

  maskitoParseNumber(
    '0,42',
    ',', // decimalSeparator
  );
  ```

  <p align="center">⬇️ </p>

  **New behavior**:

  ```ts
  import {maskitoParseNumber} from '@maskito/kit';

  maskitoParseNumber(
    '0,42',
    {decimalSeparator: ','}, // MaskitoNumberParams
  );
  ```

- **kit**: remove invalid `MM.SS.MSS` type from `MaskitoTimeMode` (use `MM:SS.MSS` instead) (#2365)
- **angular**: bump minimum required Angular version (16+ => 19+) (#2347) (#2348) (#2349)
- **angular**: `MaskitoDirective` uses model inputs (#2363)

### [3.11.1](https://github.com/taiga-family/maskito/compare/v3.11.0...v3.11.1) (2025-09-30)

### 🐞 Bug Fixes

- **kit**: resolve circular dependencies inside `Number` mask (#2344)
  [(efb3039)](https://github.com/taiga-family/maskito/commit/efb303980905c33bfe58e0163b74c72da5f83fcd)
- **kit**: `Number` fails to clear initial value (by selecting all + Backspace/Delete) (#2343)
  [(63f6e72)](https://github.com/taiga-family/maskito/commit/63f6e725af215dc492ddca02d30123de0dd026de)
- **kit**: `Number` has broken support for postfix with leading point (#2337)
  [(e9a3598)](https://github.com/taiga-family/maskito/commit/e9a3598c9ce7f5c39f932d4e6b3c0ffabcde3741)

### [3.11.0](https://github.com/taiga-family/maskito/compare/v3.10.3...v3.11.0) (2025-09-23)

### 🚀 Features

- **kit**: `Number` supports minus before prefix (#2281)
  [(480c1fd)](https://github.com/taiga-family/maskito/commit/480c1fde7693b62df768364c0df00fc7328cb4e6)
- **kit**: `Number` uses `toNumberParts` / `fromNumberParts` approach (#2270)
  [(891780a)](https://github.com/taiga-family/maskito/commit/891780a8f179345a49dbe8b8036e639ae0a98cbd)

### 🐞 Bug Fixes

- **kit**: `PostfixPostprocessor` duplicates postfix on paste of value with incompleted postfix (#2267)
  [(2707771)](https://github.com/taiga-family/maskito/commit/27077719ffc8628758664638e802e1ad3c9f8e27)
- **kit**: `maskitoStringifyTime` and `maskitoParseTime` should support `AM` / `PM` formats (#2260)
  [(a0aea6f)](https://github.com/taiga-family/maskito/commit/a0aea6f741fea3139f4e7d7c8f84ce46c1738c26)
- **angular**: use `@Input` setters instead of `ngOnChanges` to handle programmatic changes (#2257)
  [(cb8c129)](https://github.com/taiga-family/maskito/commit/cb8c129f1afd196a38f87dd4b36328ddea3b60a5)

### [3.10.3](https://github.com/taiga-family/maskito/compare/v3.10.2...v3.10.3) (2025-08-06)

### 🐞 Bug Fixes

- **kit**: `DateRange` + `minLength` / `maxLength` has incorrect limits (#2210)
  [(e8917e0)](https://github.com/taiga-family/maskito/commit/e8917e0a124b26ffc9806f74c5c70016084f5280)
- **kit**: `maskitoStringifyNumber` fails to stringify number with exponential notation (#2224)
  [(9fe0b08)](https://github.com/taiga-family/maskito/commit/9fe0b080b2703a72674a25b8ce352486cc274663)

### [3.10.2](https://github.com/taiga-family/maskito/compare/v3.10.1...v3.10.2) (2025-07-28)

### 🐞 Bug Fixes

- **kit**: `Number` with `input[maxlength]` is incompatible with `document.execCommand('delete')` (#2217)
  [(2604d2c)](https://github.com/taiga-family/maskito/commit/2604d2ce8dc60e16f464a3fc4328f907bef58d55)

### [3.10.1](https://github.com/taiga-family/maskito/compare/v3.10.0...v3.10.1) (2025-07-18)

### 🐞 Bug Fixes

- **core**: dynamic mask switching to mask without fixed character fails on new character insertion (#2207)
  [(50e68d4)](https://github.com/taiga-family/maskito/commit/50e68d4bb8f6e5330bda76c67806514a7fa53294)

### [3.10.0](https://github.com/taiga-family/maskito/compare/v3.9.1...v3.10.0) (2025-07-04)

### 🚀 Features

- **kit**: `Time` supports `prefix` & `postfix` parameters (#2185)
  [(2cc7462)](https://github.com/taiga-family/maskito/commit/2cc7462583a2fe372d0cad312fb5f0d90ca0fe8e)

### 🐞 Bug Fixes

- **core**: invalid behavior of dynamic mask expression with trailing fixed characters (#2184)
  [(cecf9d6)](https://github.com/taiga-family/maskito/commit/cecf9d69468e56de8ff4f39af7ebc07d5a686fe8)
- **core**: do not insert fixed character on attempt to enter invalid character at its position (#2181)
  [(7a51702)](https://github.com/taiga-family/maskito/commit/7a51702361237a41cd9bbdcdbb8e46d0bfa2e4bc)
- **kit**: date-related mask with month-first mode has incorrect zero-padding logic (#2166)
  [(26294e8)](https://github.com/taiga-family/maskito/commit/26294e8250591c727f99ccec563e8492df7c1068)

### [3.9.1](https://github.com/taiga-family/maskito/compare/v3.9.0...v3.9.1) (2025-06-23)

### 🐞 Bug Fixes

- **kit**: `Number` with custom `minusSign` has broken `min`/`max` behavior (#2164)
  [(52ed25d)](https://github.com/taiga-family/maskito/commit/52ed25debaa2838a0b360983a508a3d627c78277)
- **core**: Android with Microsoft SwiftKey Keyboard ignores `preventDefault()` for `beforeinput` event on backspace
  (#2163) [(722d9af)](https://github.com/taiga-family/maskito/commit/722d9afc265df8392613c770759df3bb8955e08e)

### [3.9.0](https://github.com/taiga-family/maskito/compare/v3.8.0...v3.9.0) (2025-06-05)

### 🚀 Features

- **react**: add support for React-specific `onChange` event handler (#2153)
  [(e941847)](https://github.com/taiga-family/maskito/commit/e941847990662835343c4e25d3f2b2e64ab54345)

### 🐞 Bug Fixes

- **core**: do not unnecessarily trigger element's `value` setter on every keystroke (#2152)
  [(fd3449b)](https://github.com/taiga-family/maskito/commit/fd3449b69f88dbcab5b06b03ff19273b511bcd64)

### [3.8.0](https://github.com/taiga-family/maskito/compare/v3.7.2...v3.8.0) (2025-05-13)

### 🚀 Features

- **angular**: new `MaskitoPattern` directive (#2081)
  [(c3f7142)](https://github.com/taiga-family/maskito/commit/c3f7142245b603af9136541de9d181189e01a7a3)

### 🐞 Bug Fixes

- **kit**: update the first digit zero-padding logic for date-related mask (#2117)
  [(b5b2598)](https://github.com/taiga-family/maskito/commit/b5b2598f455f3ad3438c3bd89b81009aca82f17c)
- **core**: incorrect handle of paste event for `&lt;input /&gt;` with `maxlength` attribute (#2090)
  [(e20e50b)](https://github.com/taiga-family/maskito/commit/e20e50bb92aca9d70bc483f9fc66904264a64c35)
- **kit**: `Number` should support non-erasable minus (as `prefix`) for `max &lt;= 0` (#2087)
  [(3910914)](https://github.com/taiga-family/maskito/commit/39109144075d58734d1545be888cbd03c5b6286e)

### [3.7.2](https://github.com/taiga-family/maskito/compare/v3.7.1...v3.7.2) (2025-04-22)

### 🐞 Bug Fixes

- **kit**: missing export of `maskitoParseDateTime` & `maskitoStringifyDateTime` utilities (#2074)
  [(6aa34aa)](https://github.com/taiga-family/maskito/commit/6aa34aa610cf140248bc7a691beb5aaba1f0e0cd)

### [3.7.1](https://github.com/taiga-family/maskito/compare/v3.7.0...v3.7.1) (2025-04-16)

### 🐞 Bug Fixes

- **core**: updated selection range (even if textfield value is untouched) should not be ignored (#2069)
  [(9276117)](https://github.com/taiga-family/maskito/commit/927611775e8d23eb89663150cd84e7981b12d2e7)

### [3.7.0](https://github.com/taiga-family/maskito/compare/v3.6.0...v3.7.0) (2025-04-15)

### 🚀 Features

- **kit**: new `maskitoParseDateTime` and `maskitoStringifyDateTime` helpers (#2055)
  [(5028084)](https://github.com/taiga-family/maskito/commit/5028084f9be876cf8b1dc2607956cd4906285c43)

### 🐞 Bug Fixes

- **core**: add possibility to overwrites `selection` property in processors (#2053)
  [(de354f4)](https://github.com/taiga-family/maskito/commit/de354f4fbeed7a632e23c0e1d00809effbb0229b)

### [3.6.0](https://github.com/taiga-family/maskito/compare/v3.5.0...v3.6.0) (2025-04-08)

### 🚀 Features

- **kit**: `Number` supports new properties `minimumFractionDigits` & `maximumFractionDigits` (#2022)
  [(8719b9e)](https://github.com/taiga-family/maskito/commit/8719b9e30d6463deff4aed213cba774189ddd305)

### 🐞 Bug Fixes

- **core**: double space bar removes characters (#2040)
  [(ccbebd8)](https://github.com/taiga-family/maskito/commit/ccbebd878ae7ba92da0a8d25d5b9d0b5c3ed3bcf)

### [3.5.0](https://github.com/taiga-family/maskito/compare/v3.4.0...v3.5.0) (2025-03-21)

### 🚀 Features

- **kit**: `Time` supports `MM:SS` mode (#2008)
  [(b93ad1e)](https://github.com/taiga-family/maskito/commit/b93ad1ecc71f608dd68de01b43487153b8e89d95)

### 🐞 Bug Fixes

- **kit**: `maskitoParseDate` should return `null` for incompleted date string (#2009)
  [(9eec35b)](https://github.com/taiga-family/maskito/commit/9eec35b878411a79fec84986cbea94fbdc9f24d8)

### [3.4.0](https://github.com/taiga-family/maskito/compare/v3.3.0...v3.4.0) (2025-03-10)

### 🚀 Features

- **kit**: new `maskitoStringifyNumber` helper (#1987)
  [(cbfd4bc)](https://github.com/taiga-family/maskito/commit/cbfd4bc4bb6ca56bf12667bb3626c55ae1b04c48)

### 🐞 Bug Fixes

- **phone**: `Phone` should accept incomplete phone number of selected country (even with `strict=true`) (#1982)
  [(965d735)](https://github.com/taiga-family/maskito/commit/965d7358ad39888d3844c121dd6934ee66cdc541)

### [3.3.0](https://github.com/taiga-family/maskito/compare/v3.2.1...v3.3.0) (2025-02-28)

### 🚀 Features

- **kit**: new `maskitoParseDate` and `maskitoStringifyDate` helpers (#1973)
  [(208a4ab)](https://github.com/taiga-family/maskito/commit/208a4abc8018b368d3154ebc26a81504b6abec3d)
- **kit**: `Date` supports `dd/mm` and `mm/dd` modes (#1939)
  [(bc290af)](https://github.com/taiga-family/maskito/commit/bc290affdcdc1cd6e088a32a60dc5e74fd00a1d8)

### 🐞 Bug Fixes

- **kit**: `SelectionChangeHandler` does not work for Safari after programmatic update of textfield value (#1930)
  [(34c11d0)](https://github.com/taiga-family/maskito/commit/34c11d0ee88b861ab21d54113aff21f3091a053f)

### [3.2.1](https://github.com/taiga-family/maskito/compare/v3.2.0...v3.2.1) (2024-12-26)

### 🚀 Features

- **kit**: remove circular import (#1861)
  [(15ff0b8)](https://github.com/taiga-family/maskito/commit/15ff0b8558bc954ac6eda07bdb13d087fc2f3491)

### 🐞 Bug Fixes

- **kit**: `Number` should ignore `[decimalSeparator]` value if `[precision]=0` (#1908)
  [(19effe2)](https://github.com/taiga-family/maskito/commit/19effe2c7218646335b2f08c53a1ed3c3f0d89a1)
- **kit**: `Number` + postfix (with leading space) adds unnecessary spaces on paste value with trailing spaces (#1865)
  [(c37b1d6)](https://github.com/taiga-family/maskito/commit/c37b1d636fefee1cba17b4aa07ccdd30edc5ff66)
- **kit**: `DateRange` should accept single character date segment paste even if date and range separators are equal
  (#1796) [(be6a4c3)](https://github.com/taiga-family/maskito/commit/be6a4c3c57132cf320ec462372fd8536dca4781a)

### [3.2.0](https://github.com/taiga-family/maskito/compare/v3.1.2...v3.2.0) (2024-10-29)

### 🚀 Features

- **kit**: new `maskitoSelectionChangeHandler` plugin (#1794)
  [(c6e9a4d)](https://github.com/taiga-family/maskito/commit/c6e9a4d9b1a2e75bc44aaecbda840b84f786d065)

### [3.1.2](https://github.com/taiga-family/maskito/compare/v3.1.1...v3.1.2) (2024-10-22)

### 🐞 Bug Fixes

- **kit**: `Time` & `DateTime` has conflicts between `step` & `AM/PM` features (#1791)
  [(805f70b)](https://github.com/taiga-family/maskito/commit/805f70b74e04fb3b8613f89d84e771c734438dab)
- **kit**: `Number` incorrectly shift caret for 1st time insertion into textfield with initial value (#1792)
  [(0049d91)](https://github.com/taiga-family/maskito/commit/0049d91a0a498977bb5f4cba9fbf9f02cb74dae9)

### [3.1.1](https://github.com/taiga-family/maskito/compare/v3.1.0...v3.1.1) (2024-10-17)

### 🐞 Bug Fixes

- **kit**: `Number` fails to prevent user insertion of extra spaces on invalid positions (#1789)
  [(a40445c)](https://github.com/taiga-family/maskito/commit/a40445cf4d852328a9310a55cf38801e17525476)
- **kit**: `DateTime` fails to process value without any separators (paste from clipboard) (#1779)
  [(1733422)](https://github.com/taiga-family/maskito/commit/1733422b803fda3de9b40a9fa675ef6bb8b5195e)

### [3.1.0](https://github.com/taiga-family/maskito/compare/v3.0.3...v3.1.0) (2024-10-09)

### 🚀 Features

- **kit**: `Time` & `DateTime` support `AM` / `PM` formats (#1708)
  [(98ce35e)](https://github.com/taiga-family/maskito/commit/98ce35e8fd3318a750959d840f36caaf427fe8f0)
- **kit**: simplify some code logic for `Time` mask (#1688)
  [(8c608b8)](https://github.com/taiga-family/maskito/commit/8c608b8cb5eaeca1166b78c6691d38303eb67c6c)

### 🐞 Bug Fixes

- **core**: `overwriteMode: replace` has incorrect behavior on attempt to insert invalid characters (#1772)
  [(5aeb074)](https://github.com/taiga-family/maskito/commit/5aeb0741fa82ad6e43e862059a17b2e78ee9831b)

### [3.0.3](https://github.com/taiga-family/maskito/compare/v3.0.2...v3.0.3) (2024-09-25)

### 🐞 Bug Fixes

- **angular**: race condition when `[maskitoOptions]` are changed before long element predicate is resolved (#1696)
  [(9f9bad3)](https://github.com/taiga-family/maskito/commit/9f9bad3036774fa51350c3c8402cf57f15e789d6)
- **kit**: `Time` has invalid segment separator for `MM:SS.MSS` mode (#1687)
  [(93972be)](https://github.com/taiga-family/maskito/commit/93972be370e1abf4278497b11f61d3c923ae5caa)
- **core**: incorrect behavior of `overwriteMode = replace` if selection contains several characters (#1685)
  [(67c3c10)](https://github.com/taiga-family/maskito/commit/67c3c10704f62efff4c47f1ad802859d54257752)
- **react**: race condition when `options` are changed before long element predicate is resolved (#1651)
  [(f2932ce)](https://github.com/taiga-family/maskito/commit/f2932ce10ec80a1080befaee9e5c235bc41a1b16)

### [3.0.2](https://github.com/taiga-family/maskito/compare/v3.0.1...v3.0.2) (2024-09-20)

### 🐞 Bug Fixes

- **core:** `Time` with `[step]` has unexpected cursor jump to the next segment on `ArrowUp`/`ArrowDown`
  ([#1478](https://github.com/taiga-family/maskito/issues/1478))
  ([59a5927](https://github.com/taiga-family/maskito/commit/59a5927822e2c20691dc0948c438d67d497b6381))
- **core:** fix scroll for masked narrow textfields ([#1645](https://github.com/taiga-family/maskito/issues/1645))
  ([c6d2828](https://github.com/taiga-family/maskito/commit/c6d282873f10892ecb3536b878d919fc57f5c921))

### [3.0.1](https://github.com/taiga-family/maskito/compare/v3.0.0...v3.0.1) (2024-08-19)

### 🐞 Bug Fixes

- **kit:** `maskitoStringifyTime` was adding `0` on the wrong side
  ([#1401](https://github.com/taiga-family/maskito/issues/1401))
  ([b28ee12](https://github.com/taiga-family/maskito/commit/b28ee12f923b86eb3a8c32d17cd401e9222cfc30))
- **kit:** `Placeholder` should support partial programmatic removal of placeholder's characters
  ([#1441](https://github.com/taiga-family/maskito/issues/1441))
  ([146a557](https://github.com/taiga-family/maskito/commit/146a55723ec4a1ac8b9cfba254056b84173326c9))
- **kit:** `Time` incorrectly validates value if `timeSegmentMaxValues` includes single digit
  ([#1402](https://github.com/taiga-family/maskito/issues/1402))
  ([26670f4](https://github.com/taiga-family/maskito/commit/26670f4dbdfb84495ea0faa127868185d7bb0765))

## [3.0.0](https://github.com/taiga-family/maskito/compare/v2.5.0...v3.0.0) (2024-07-18)

### ⚠ BREAKING CHANGES

- **phone:** remove built-in `RemoveOnBlur` / `AddOnFocus` plugins from `@maskito/phone`
  ([#1352](https://github.com/taiga-family/maskito/issues/1352))

  Learn more: https://maskito.dev/addons/phone#focus-blur

- **angular:** bump minimum required Angular version (15+ => 16+)
  ([#1328](https://github.com/taiga-family/maskito/issues/1328))

- **angular:** delete deprecated `MaskitoModule` & `MaskitoCVA`
  ([#1391](https://github.com/taiga-family/maskito/issues/1391))

### 🚀 Features

- **core:** new built-in `maskitoChangeEventPlugin` ([#1338](https://github.com/taiga-family/maskito/issues/1338))

  Learn more: https://maskito.dev/core-concepts/plugins#change-event

## [2.5.0](https://github.com/taiga-family/maskito/compare/v2.4.0...v2.5.0) (2024-06-24)

### 🚀 Features

- **kit:** new `maskitoParseTime` and `maskitoStringifyTime` utils
  ([#1302](https://github.com/taiga-family/maskito/issues/1302))
  ([d0f9b13](https://github.com/taiga-family/maskito/commit/d0f9b1331f3bb18403691ac7c513c31f5123cf78))

### 🐞 Bug Fixes

- **core:** correct handling of browser autofill/suggestion in Firefox
  ([#1326](https://github.com/taiga-family/maskito/issues/1326))
  ([a049207](https://github.com/taiga-family/maskito/commit/a049207b355da72092948a8c556020062fb7c819))
- **kit:** `Date`, `DateRange`, `DateTime` supports multi-character date segments separator
  ([#1306](https://github.com/taiga-family/maskito/issues/1306))
  ([cdf2fae](https://github.com/taiga-family/maskito/commit/cdf2faee4c16cd3963557a511d4ec053e2d41fc0))
- **kit:** move caret after attempt to erase fixed character in a mask with `Placeholder`
  ([#1307](https://github.com/taiga-family/maskito/issues/1307))
  ([87ae431](https://github.com/taiga-family/maskito/commit/87ae431ded798e3c31d6247f965a00c27ddad3f1))

## [2.4.0](https://github.com/taiga-family/maskito/compare/v2.3.2...v2.4.0) (2024-06-03)

### 🚀 Features

- **kit:** `Time` & `DateTime` support increment / decrement of time segment via `ArrowUp` / `ArrowDown`
  ([#1223](https://github.com/taiga-family/maskito/issues/1223))
  ([af961b8](https://github.com/taiga-family/maskito/commit/af961b84f8765e7d2147c80210e3a8ac6ed30597))
- **kit:** `Time` supports `SS.MSS` & `MM.SS.MSS` modes ([#1224](https://github.com/taiga-family/maskito/issues/1224))
  ([7bed4bc](https://github.com/taiga-family/maskito/commit/7bed4bcaac14908e7e445b277f5b4b6e5b0fd281))

### 🐞 Bug Fixes

- **core:** add `.select()`-method support for `MaskitoElement`
  ([#1268](https://github.com/taiga-family/maskito/issues/1268))
  ([51f5934](https://github.com/taiga-family/maskito/commit/51f5934f382b7862a6653412b687c46fd318b0bb))
- **kit:** `Number` should support float `min`/`max`-parameters in range -1 < x < 1
  ([#1280](https://github.com/taiga-family/maskito/issues/1280))
  ([b44013e](https://github.com/taiga-family/maskito/commit/b44013e0a45ffcfa69564f13d634a79d45b4d926))

### [2.3.2](https://github.com/taiga-family/maskito/compare/v2.3.1...v2.3.2) (2024-05-16)

### 🐞 Bug Fixes

- **kit:** `Number` pads integer part with zero if user selects all and then types decimal separator
  ([#1220](https://github.com/taiga-family/maskito/issues/1220))
  ([8371e45](https://github.com/taiga-family/maskito/commit/8371e45767150ebc4db03a2b74c68afd6fe1e593))
- **phone:** revert mistakenly fixated `libphonenumber-js` peer-dependency to just `>=1.0.0`
  ([#1234](https://github.com/taiga-family/maskito/issues/1234))
  ([27ee4a1](https://github.com/taiga-family/maskito/commit/27ee4a1264c0a70a5a06427368b8d18ed0e25bd4))
- **react:** revert mistakenly fixated `react` & `react-demo` peer-dependencies to just `>=16.8`
  ([#1231](https://github.com/taiga-family/maskito/issues/1231))
  ([ae89d6f](https://github.com/taiga-family/maskito/commit/ae89d6ff549dfb21d7db56b26e3c1f3a7044a817))
- **vue:** revert mistakenly fixated `vue` peer-dependency to just `>=3.0.0`
  ([#1232](https://github.com/taiga-family/maskito/issues/1232))
  ([22d84e2](https://github.com/taiga-family/maskito/commit/22d84e2f731ae8798f457466be7c9538d2f40fd9))

### [2.3.1](https://github.com/taiga-family/maskito/compare/v2.3.0...v2.3.1) (2024-04-23)

### 🐞 Bug Fixes

- **kit:** `Number` should drop decimal separator if all digits are erased
  ([#1211](https://github.com/taiga-family/maskito/issues/1211))
  ([5836c96](https://github.com/taiga-family/maskito/commit/5836c965d6ce5ad497aaa59118204adc3e8625d8))
- **kit:** `Number` with `decimalZeroPadding=true` should erase everything on `.00`
  ([#1207](https://github.com/taiga-family/maskito/issues/1207))
  ([d72f225](https://github.com/taiga-family/maskito/commit/d72f2257cec1a023aa81bb7de62e9543404630bd))
- **kit:** `Placeholder` can have now the same character as textfield's value
  ([#1209](https://github.com/taiga-family/maskito/issues/1209))
  ([ed06936](https://github.com/taiga-family/maskito/commit/ed06936c41297cbd2e8ed308558914e9ad6c2eda))

## [2.3.0](https://github.com/taiga-family/maskito/compare/v2.2.0...v2.3.0) (2024-04-16)

### 🚀 Features

- **core:** add `contenteditable` support ([#1039](https://github.com/taiga-family/maskito/issues/1039))
  ([0d5bb31](https://github.com/taiga-family/maskito/commit/0d5bb319225fb61f3ac7643c21208122b4a2a2ae))
- **kit:** `DateTime` supports configurable parameter `dateTimeSeparator`
  ([#1143](https://github.com/taiga-family/maskito/issues/1143))
  ([ec86284](https://github.com/taiga-family/maskito/commit/ec8628467814cff7dfae22668370236f402d8146))

### 🐞 Bug Fixes

- **kit:** `Date` formatting errors for `mm/yyyy`, `yyyy/mm`, `mm/yy` modes
  ([#1177](https://github.com/taiga-family/maskito/issues/1177))
  ([948a350](https://github.com/taiga-family/maskito/commit/948a35098da2233bc78793eb7e83b7c5136becbd))

## [2.2.0](https://github.com/taiga-family/maskito/compare/v2.1.0...v2.2.0) (2024-03-07)

### 🚀 Features

- **kit:** `Number` supports new configurable parameter `minusSign`
  ([#1118](https://github.com/taiga-family/maskito/issues/1118))
  ([a7bec35](https://github.com/taiga-family/maskito/commit/a7bec35f19d7dfa4023ad83fa36a935b2d636fc7))

### 🐞 Bug Fixes

- totally disable `Maskito` if nullable options are passed inside `@maskito/{angular,react,vue}`
  ([#1117](https://github.com/taiga-family/maskito/issues/1117))
  ([8cbadcf](https://github.com/taiga-family/maskito/commit/8cbadcfdf9af283dc687b131361f7bb19a7f9b02))

## [2.1.0](https://github.com/taiga-family/maskito/compare/v2.0.2...v2.1.0) (2024-03-04)

### 🚀 Features

- **kit:** `Date` & `DateRange` & `DateTime` has improved zero-padding support for browser autofill & IME composition
  ([#1027](https://github.com/taiga-family/maskito/issues/1027))
  ([77ac01c](https://github.com/taiga-family/maskito/commit/77ac01ca0b5e61d36dc3240a35c3dc93ce5fe93c))
- **kit:** add full-width numbers support for `Time`, `Date`, `DateTime`, `DateRange`
  ([#1043](https://github.com/taiga-family/maskito/issues/1043))
  ([434c9c5](https://github.com/taiga-family/maskito/commit/434c9c5f349ab3c19e11722e95313c5763203b08))

### 🐞 Bug Fixes

- **kit:** `maskitoParseNumber` should interpret japanese prolonged sound mark as pseudo minus
  ([#1115](https://github.com/taiga-family/maskito/issues/1115))
  ([b152698](https://github.com/taiga-family/maskito/commit/b152698fda8ac671286eb5f4a29de62562934fa2))

### [2.0.2](https://github.com/taiga-family/maskito/compare/v2.0.1...v2.0.2) (2024-02-01)

### 🐞 Bug Fixes

- **kit:** `Number` with initial value has problems with the first time input
  ([#986](https://github.com/taiga-family/maskito/issues/986))
  ([e40d3ff](https://github.com/taiga-family/maskito/commit/e40d3ff93c668c8afa60cd347faa7ebec76d0e6a))
- **react:** `@maskito/react` includes again missing `cjs` module format
  ([#991](https://github.com/taiga-family/maskito/issues/991))
  ([18e3e0c](https://github.com/taiga-family/maskito/commit/18e3e0cf8911fa764a73e2e937081186f1dcde79))

### [2.0.1](https://github.com/taiga-family/maskito/compare/v2.0.0...v2.0.1) (2024-01-31)

### 🐞 Bug Fixes

- **core:** `maskitoUpdateElement` should not dispatch `InputEvent` if value is not changed
  ([#977](https://github.com/taiga-family/maskito/issues/977))
  ([2410b64](https://github.com/taiga-family/maskito/commit/2410b6478c88f4d530b4469d7d50b1e4663d1572))
- **core:** don't execute `setSelectionRange` if element is not focused
  ([#937](https://github.com/taiga-family/maskito/issues/937))
  ([92f288b](https://github.com/taiga-family/maskito/commit/92f288b677dbe77f7978308dd7b1612d6bfd68fb))
- **kit:** `Number` rejects the first time input of full width digits
  ([#955](https://github.com/taiga-family/maskito/issues/955))
  ([c416884](https://github.com/taiga-family/maskito/commit/c41688488630e83d69eba795580916145e5fe17c))
- **react:** `@maskito/react` library should not include `core-js` imports
  ([#962](https://github.com/taiga-family/maskito/issues/962))
  ([3b7e401](https://github.com/taiga-family/maskito/commit/3b7e4014029fae206020723c18762f08e92b8c41))

## [2.0.0](https://github.com/taiga-family/maskito/compare/v1.9.0...v2.0.0) (2024-01-22)

### ⚠ BREAKING CHANGES

- **core:** merge `MaskitoElementPredicate` & `MaskitoElementPredicateAsync` into single type
  ([#757](https://github.com/taiga-family/maskito/issues/757))
- **core:** remove value's calibration on initialization + new `maskitoInitialCalibrationPlugin`
  ([#778](https://github.com/taiga-family/maskito/issues/778))
- **core:** bump Firefox browser support (55+ => 87+) ([#876](https://github.com/taiga-family/maskito/issues/876)) and
  drop legacy fallbacks for `Firefox` ([#756](https://github.com/taiga-family/maskito/issues/756))
- **kit:** delete deprecated `separator` for `DateRange` (use `dateSeparator` instead)
  ([#790](https://github.com/taiga-family/maskito/issues/790))
- **angular:** bump minimum required Angular version (12+ => 15+)
  ([#710](https://github.com/taiga-family/maskito/issues/710))
  ([#720](https://github.com/taiga-family/maskito/issues/720))
  ([#725](https://github.com/taiga-family/maskito/issues/725))
- **angular:** deprecate `MaskitoModule` (use standalone `MaskitoDirective`, `MaskitoCVA`, `MaskitoPipe`)
  ([#754](https://github.com/taiga-family/maskito/issues/754))

### 🚀 More features

- **core:** new built-in `maskitoStrictCompositionPlugin` ([#881](https://github.com/taiga-family/maskito/issues/881))
- **kit:** `Number` allows to enter full width numbers ([#864](https://github.com/taiga-family/maskito/issues/864))

### 🐞 Bug Fixes

- **core:** drop some excess dispatches of `Input`-event ([#882](https://github.com/taiga-family/maskito/issues/882))
- **kit:** add `{bubbles:true}` for `input` events inside all built-in plugins to support `ReactSyntheticEvent`
  ([#806](https://github.com/taiga-family/maskito/issues/806))
- **kit:** `Number` has problems when prefix/postfix includes `decimalSeparator` symbol
  ([#874](https://github.com/taiga-family/maskito/issues/874))
  ([#816](https://github.com/taiga-family/maskito/issues/816))
  ([#921](https://github.com/taiga-family/maskito/issues/921))
- **kit:** `Placeholder` is not compatible with `maskitoEventHandler` + `focus`/`blur` events
  ([#928](https://github.com/taiga-family/maskito/pull/928))

## [1.9.0](https://github.com/taiga-family/maskito/compare/v1.8.2...v1.9.0) (2023-11-23)

### 🚀 Features

- **phone:** add ability to configure the separator ([#685](https://github.com/taiga-family/maskito/issues/685))
  ([ab6bb11](https://github.com/taiga-family/maskito/commit/ab6bb11b1b40e069d31598b676c04456329aaf64))

### [1.8.2](https://github.com/taiga-family/maskito/compare/v1.8.1...v1.8.2) (2023-11-16)

### 🐞 Bug Fixes

- **kit:** `PrefixPostprocessor` has problems with multi-character prefix
  ([#669](https://github.com/taiga-family/maskito/issues/669))
  ([be459e5](https://github.com/taiga-family/maskito/commit/be459e51f3cbf028fa36b1b6a57e47d7fe8482a3))

### [1.8.1](https://github.com/taiga-family/maskito/compare/v1.8.0...v1.8.1) (2023-10-19)

### 🐞 Bug Fixes

- **kit:** `Date` accept single character date segment during paste
  ([#610](https://github.com/taiga-family/maskito/issues/610))
  ([e493198](https://github.com/taiga-family/maskito/commit/e4931987c2fad37894ea07f658f08e35152040df))

## [1.8.0](https://github.com/taiga-family/maskito/compare/v1.7.0...v1.8.0) (2023-10-18)

### 🚀 Features

- **angular:** allow nullable options ([#605](https://github.com/taiga-family/maskito/issues/605))
  ([21eaa7c](https://github.com/taiga-family/maskito/commit/21eaa7c0c0e7d5173c6f070f5222ba6492e196a6))

### 🐞 Bug Fixes

- **kit:** `Number` has broken zero padding when `decimalSeparator` equals to non-default value
  ([#586](https://github.com/taiga-family/maskito/issues/586))
  ([7241761](https://github.com/taiga-family/maskito/commit/72417614dd4974c22854dfacc2ee35044c080074))

## [1.7.0](https://github.com/taiga-family/maskito/compare/v1.6.0...v1.7.0) (2023-09-15)

### 🚀 Features

New `@maskito/phone` library ([#425](https://github.com/taiga-family/maskito/pull/425))
([#482](https://github.com/taiga-family/maskito/issues/482))

Learn more: https://maskito.dev/addons/phone

## [1.6.0](https://github.com/taiga-family/maskito/compare/v1.5.1...v1.6.0) (2023-09-15)

### 🚀 Features

- **react:** `elementPredicate` can accept asynchronous predicate
  ([#502](https://github.com/taiga-family/maskito/issues/502))
  ([4bbf758](https://github.com/taiga-family/maskito/commit/4bbf758107ed4b2fdbde5a241f22c0f363c22104))

### 🐞 Bug Fixes

- **kit:** `Number` should accept all types of spaces as interchangeable characters for `thousandSeparator`
  ([#505](https://github.com/taiga-family/maskito/issues/505))
  ([73975bb](https://github.com/taiga-family/maskito/commit/73975bbc676487330359056c367f73e32ea6eaf4))

### [1.5.1](https://github.com/taiga-family/maskito/compare/v1.5.0...v1.5.1) (2023-09-08)

### 🐞 Bug Fixes

- **vue:** `elementPredicate` should accept `MaskitoElementPredicateAsync` type
  ([#487](https://github.com/taiga-family/maskito/issues/487))
  ([fe7e9dc](https://github.com/taiga-family/maskito/commit/fe7e9dcb468bf3ab30978c947d8fa21cc0e51a75))

## [1.5.0](https://github.com/taiga-family/maskito/compare/v1.4.0...v1.5.0) (2023-09-04)

### 🚀 Features

- **core:** add IME composition support ([#467](https://github.com/taiga-family/maskito/issues/467))
  ([e7d664b](https://github.com/taiga-family/maskito/commit/e7d664b66a008a742c0a532e341b0e0bb0a0f759))
- **demo:** documentation is now available at https://maskito.dev
  ([#392](https://github.com/taiga-family/maskito/issues/392))
  ([355f87f](https://github.com/taiga-family/maskito/commit/355f87fd536758bc2db59f760ed114d28264122a))

### 🐞 Bug Fixes

- **kit:** `maskitoCaretGuard` doesn't work after focus on `<select />`
  ([#462](https://github.com/taiga-family/maskito/issues/462))
  ([9f456da](https://github.com/taiga-family/maskito/commit/9f456dad7f7f9d02db4eb5993ecb5fb5aabfe613))
- **kit:** `Number` should drop items from `decimalPseudoSeparators` if any is equal to `thousandSeparator`
  ([#390](https://github.com/taiga-family/maskito/issues/390))
  ([2107adc](https://github.com/taiga-family/maskito/commit/2107adc445ed26ce1507c5e0c534b668d7ae5b12))

## [1.4.0](https://github.com/taiga-family/maskito/compare/v1.3.0...v1.4.0) (2023-07-27)

### 🚀 Features

- **kit:** `Date` & `DateRange` support new modes `yyyy`, `mm/yyyy`, `yyyy/mm`
  ([#384](https://github.com/taiga-family/maskito/issues/384))
  ([7886d50](https://github.com/taiga-family/maskito/commit/7886d50012a76fec872816b6d5e2b7e67c931dd7))
- **kit:** `Time` supports new mode `HH` ([#385](https://github.com/taiga-family/maskito/issues/385))
  ([3c7a3f6](https://github.com/taiga-family/maskito/commit/3c7a3f65a0013152473ba57af8da28012cb58f32))

## [1.3.0](https://github.com/taiga-family/maskito/compare/v1.2.2...v1.3.0) (2023-07-24)

### 🚀 Features

- **kit:** `DateRange` add configurable parameter `rangeSeparator`
  ([#376](https://github.com/taiga-family/maskito/issues/376))
  ([d904842](https://github.com/taiga-family/maskito/commit/d90484214da76f4c73ad925eef5fe391a154c499))

### 🐞 Bug Fixes

- **kit:** `Number` has problems with run-time updates of postfix
  ([#380](https://github.com/taiga-family/maskito/issues/380))
  ([8210896](https://github.com/taiga-family/maskito/commit/8210896d2095a44e79a27a38e4c8745e2beccdb7))

### [1.2.2](https://github.com/taiga-family/maskito/compare/v1.2.1...v1.2.2) (2023-07-19)

### 🐞 Bug Fixes

- **kit:** `maskitoCaretGuard` should wait for `mouseup` before execution
  ([#372](https://github.com/taiga-family/maskito/issues/372))
  ([8554fea](https://github.com/taiga-family/maskito/commit/8554fead2a2474104f0674fb597cf86467274943))
- **kit:** `Number` should remove repeated leading zeroes for integer part only on `blur`-event
  ([#373](https://github.com/taiga-family/maskito/issues/373))
  ([7cf4938](https://github.com/taiga-family/maskito/commit/7cf4938853ccbd049b89482f8eb22ab4e71fe01f))

### [1.2.1](https://github.com/taiga-family/maskito/compare/v1.2.0...v1.2.1) (2023-07-11)

### 🐞 Bug Fixes

- **kit:** `Number` with `postfix` should be compatible with `decimalZeroPadding`
  ([#364](https://github.com/taiga-family/maskito/issues/364))
  ([501cf9c](https://github.com/taiga-family/maskito/commit/501cf9c747229d1776fb62cc04fbc8879990c617))
- **kit:** `Prefix`/`Postfix` is incompatible if they end/start with the same character
  ([#366](https://github.com/taiga-family/maskito/issues/366))
  ([06afbcb](https://github.com/taiga-family/maskito/commit/06afbcb4a2c5c15e2ef9dc81db4309adf01aa8ef))

## [1.2.0](https://github.com/taiga-family/maskito/compare/v1.1.1...v1.2.0) (2023-07-03)

### 🚀 Features

- **kit:** `maskitoCaretGuard`'s function has the 2nd argument with current selection range
  ([#358](https://github.com/taiga-family/maskito/issues/358))
  ([eedc4d6](https://github.com/taiga-family/maskito/commit/eedc4d610efaf36b98a4049f5c5334561b5b21c5))

### 🐞 Bug Fixes

- **kit:** `maskitoCaretGuard` incorrectly validates the left side of constraints
  ([#356](https://github.com/taiga-family/maskito/issues/356))
  ([17ee90f](https://github.com/taiga-family/maskito/commit/17ee90fe055f6a8370d6ea75ff2b236fd498441e))
- **kit:** `Number` should skip min/max validation if value does not contain any digits
  ([#359](https://github.com/taiga-family/maskito/issues/359))
  ([ed8221e](https://github.com/taiga-family/maskito/commit/ed8221e14eca62334af41b4c8e571eb86ed68247))

### [1.1.1](https://github.com/taiga-family/maskito/compare/v1.1.0...v1.1.1) (2023-06-29)

### 🐞 Bug Fixes

- **core:** don't ignore native attribute `maxlength` ([#350](https://github.com/taiga-family/maskito/issues/350))
  ([8504f49](https://github.com/taiga-family/maskito/commit/8504f497152931da06dd745763be2505587f97b4))
- **kit:** `Number` should ignore new typed decimal separator if it already exists in text field
  ([#351](https://github.com/taiga-family/maskito/issues/351))
  ([4ccfdc8](https://github.com/taiga-family/maskito/commit/4ccfdc86ff08bcebfd18c04403aa9c9c83cbbd02))

## [1.1.0](https://github.com/taiga-family/maskito/compare/v1.0.0...v1.1.0) (2023-06-23)

### 🚀 Features

- **kit:** `maskitoEventHandler` accepts `AddEventListenerOptions` as the 3d optional argument
  ([#346](https://github.com/taiga-family/maskito/issues/346))
  ([1d5866e](https://github.com/taiga-family/maskito/commit/1d5866efa5e0e4736dd735ae006e027e9bd01e31))
- **kit:** use capturing phase for `focus`/`blur` events in plugins
  ([#347](https://github.com/taiga-family/maskito/issues/347))
  ([ef539e1](https://github.com/taiga-family/maskito/commit/ef539e160f601023e513036d704f7daff9689286))

### 🐞 Bug Fixes

- **kit:** `Date` allows to replace the whole selection range with zero
  ([#345](https://github.com/taiga-family/maskito/issues/345))
  ([98fd21d](https://github.com/taiga-family/maskito/commit/98fd21d50899db365b864faf597fad9a21a3db06))

## [1.0.0](https://github.com/taiga-family/maskito/compare/v0.16.0...v1.0.0) (2023-06-21)

### ⚠ BREAKING CHANGES

- **core:** delete deprecated `preprocessor` & `postprocessor` from `MaskitoOptions`
  ([#337](https://github.com/taiga-family/maskito/issues/337))
  ([0b6aad2](https://github.com/taiga-family/maskito/commit/0b6aad2622ed152d12c91f8ca64b767709ecdbc2))
- **kit:** delete deprecated `isNegativeAllowed` parameter from `Number` mask
  ([#338](https://github.com/taiga-family/maskito/issues/338))
  ([9fd3005](https://github.com/taiga-family/maskito/commit/9fd30055b3157072076f7a8567045fac05b6af9e))

## [0.16.0](https://github.com/taiga-family/maskito/compare/v0.15.0...v0.16.0) (2023-06-20)

### 🚀 Features

- **vue:** support async predicate ([#336](https://github.com/taiga-family/maskito/issues/336))
  ([d1452b5](https://github.com/taiga-family/maskito/commit/d1452b5f1b2f8a252dfd05a5c1eb04ba971a1970))

### 🐞 Bug Fixes

- **kit:** `Number` fails to parse small number on blur (exponential notation problem)
  ([#339](https://github.com/taiga-family/maskito/issues/339))
  ([7f83a7f](https://github.com/taiga-family/maskito/commit/7f83a7f170906c1911eb4444da2d636c0338ed4a))

## [0.15.0](https://github.com/taiga-family/maskito/compare/v0.14.0...v0.15.0) (2023-06-14)

### 🚀 Features

- **core:** add new parameters `preprocessors` & `postprocessors` and deprecate `preprocessor` & `postprocessor`
  ([#333](https://github.com/taiga-family/maskito/issues/333))
  ([0137775](https://github.com/taiga-family/maskito/commit/01377751a9875143257930934b1e2a9143b6da03))

### 🐞 Bug Fixes

- **kit:** `maskitoParseNumber` should return `NaN` for all strings with no digits
  ([#331](https://github.com/taiga-family/maskito/issues/331))
  ([d1ebcec](https://github.com/taiga-family/maskito/commit/d1ebceceedf418b21a68082f7350002d09159ebf))
- **kit:** `Number` incorrectly implements `min`/`max` behaviour
  ([#334](https://github.com/taiga-family/maskito/issues/334))
  ([9876d88](https://github.com/taiga-family/maskito/commit/9876d885f98f86d18db04d723460b468bca3837d))

## [0.14.0](https://github.com/taiga-family/maskito/compare/v0.13.0...v0.14.0) (2023-06-09)

### 🚀 Features

- **angular:** `[maskitoElement]` can accept asynchronous predicate
  ([#316](https://github.com/taiga-family/maskito/issues/316))
  ([3d8949e](https://github.com/taiga-family/maskito/commit/3d8949e878e644079b7f5404cb9ebf6c5eadab86))
- **kit:** `Number` pads empty integer part with zero on blur (if decimal part exists)
  ([#328](https://github.com/taiga-family/maskito/issues/328))
  ([bd01967](https://github.com/taiga-family/maskito/commit/bd01967fba38be26a3c8f0d2f23c0ced12d3b1c2))

## [0.13.0](https://github.com/taiga-family/maskito/compare/v0.12.1...v0.13.0) (2023-06-02)

### 🚀 Features

- **core:** better layout-independent way to detect `Undo` and `Redo`
  ([#320](https://github.com/taiga-family/maskito/issues/320))
  ([4c5a7f6](https://github.com/taiga-family/maskito/commit/4c5a7f64b9a8ac209584c75e17ec022674b87c1b))
- **vue:** add dedicated Vue package ([#321](https://github.com/taiga-family/maskito/issues/321))
  ([f6ffb24](https://github.com/taiga-family/maskito/commit/f6ffb24eca5f1a1a57a93103b9e74cdf410e4132))

### [0.12.1](https://github.com/taiga-family/maskito/compare/v0.12.0...v0.12.1) (2023-05-25)

### 🐞 Bug Fixes

- **kit:** `DateTime` validate min / max if date is complete
  ([#314](https://github.com/taiga-family/maskito/issues/314))
  ([5783e76](https://github.com/taiga-family/maskito/commit/5783e766a657abcf0fc7f8a8d12ac1bf412dc18a))
- **kit:** `Time` & `DateTime` should accept time segment separator typed by user
  ([#317](https://github.com/taiga-family/maskito/issues/317))
  ([3bcac7f](https://github.com/taiga-family/maskito/commit/3bcac7f6566043991a9211f04db744a5ec6f019f))

## [0.12.0](https://github.com/taiga-family/maskito/compare/v0.11.1...v0.12.0) (2023-05-19)

### 🚀 Features

- **core:** add `plugins` to `MaskitoOptions` ([#305](https://github.com/taiga-family/maskito/issues/305))
  ([b512ae2](https://github.com/taiga-family/maskito/commit/b512ae2c64b2a2c6560e2e5c68d8c72952474c71))
- **core:** expose `MaskitoMask`, `MaskitoPreprocessor`, `MaskitoPostprocessor` and `MaskitoPlugin`
  ([#307](https://github.com/taiga-family/maskito/issues/307))
  ([9315a9f](https://github.com/taiga-family/maskito/commit/9315a9f4620b3be86cf3b7af993861664f281a19))
- **kit:** new `maskitoWithPlaceholder` utility ([#299](https://github.com/taiga-family/maskito/issues/299))
  ([21eb69c](https://github.com/taiga-family/maskito/commit/21eb69cfeb73bbe645d5a5879659ab8b6aadbf0c))

### [0.11.1](https://github.com/taiga-family/maskito/compare/v0.11.0...v0.11.1) (2023-05-11)

### 🐞 Bug Fixes

- **core:** `insertFromDrop` action behaves now in the same way as `insertFromPaste`
  ([#291](https://github.com/taiga-family/maskito/issues/291))
  ([58e0fcc](https://github.com/taiga-family/maskito/commit/58e0fccb7ddd3c741ffa3c8b99efbcf4571aab37))
- **kit:** `Time` doesn't validate time segments on `drop` event
  ([#289](https://github.com/taiga-family/maskito/issues/289))
  ([0c6d1b9](https://github.com/taiga-family/maskito/commit/0c6d1b9917d0c86a98c0d215c38a0e2076ff5680))

## [0.11.0](https://github.com/taiga-family/maskito/compare/v0.10.0...v0.11.0) (2023-05-02)

### 🚀 Features

- **react:** new library `@maskito/react` ([#273](https://github.com/taiga-family/maskito/issues/273))
  ([4c2f755](https://github.com/taiga-family/maskito/commit/4c2f755bac9513689964af7fdb7f4deec56bfb52))

## [0.10.0](https://github.com/taiga-family/maskito/compare/v0.9.0...v0.10.0) (2023-04-25)

### 🚀 Features

- **kit:** `Number` keeps untouched decimal part if `precision: Infinity`
  ([#253](https://github.com/taiga-family/maskito/issues/253))
  ([261779e](https://github.com/taiga-family/maskito/commit/261779ead327397a61b27e634bc827ee70b718f4))
- **kit:** `Number` supports new `prefix` & `postfix` parameters
  ([#264](https://github.com/taiga-family/maskito/issues/264))
  ([6e78581](https://github.com/taiga-family/maskito/commit/6e785818dabcde623d8c1c40a584166a0a66f5b6))
- **kit:** new `maskitoPostfixPostprocessorGenerator` ([#257](https://github.com/taiga-family/maskito/issues/257))
  ([fdc86db](https://github.com/taiga-family/maskito/commit/fdc86dbad368bfc17efd1047b7d68d9622968bb0))

### 🐞 Bug Fixes

- **kit:** `Number` fails to trim leading zeroes after deleting of leading digit
  ([#268](https://github.com/taiga-family/maskito/issues/268))
  ([4ae0010](https://github.com/taiga-family/maskito/commit/4ae0010ef2149694d22d7ae9eb8c9880120c8c75))
- **kit:** `Number` should trim redundant thousand separators
  ([#267](https://github.com/taiga-family/maskito/issues/267))
  ([100b793](https://github.com/taiga-family/maskito/commit/100b79317a420103ca98a3b43fe646a6f77d19d5))
- **kit:** fix first zero in short-format date-mask ([#251](https://github.com/taiga-family/maskito/issues/251))
  ([08bdfd2](https://github.com/taiga-family/maskito/commit/08bdfd26727777c3a6fc870e433003be2b64cc0e))

## [0.9.0](https://github.com/taiga-family/maskito/compare/v0.8.1...v0.9.0) (2023-03-31)

### 🚀 Features

- **kit:** new `maskitoPrefixPostprocessorGenerator` ([#235](https://github.com/taiga-family/maskito/issues/235))
  ([50f0d58](https://github.com/taiga-family/maskito/commit/50f0d58ccbfa22d15174d76479a9d642687db099))

### 🐞 Bug Fixes

- **angular:** Jest throws `Class constructor DefaultValueAccessor cannot be invoked without 'new'`
  ([#232](https://github.com/taiga-family/maskito/issues/232))
  ([5089612](https://github.com/taiga-family/maskito/commit/508961288898a5fdd21cc0e26b23ecc8845f9068))

### [0.8.1](https://github.com/taiga-family/maskito/compare/v0.8.0...v0.8.1) (2023-03-27)

### 🐞 Bug Fixes

- `@maskito/core` & `@maskito/kit` now include both `UMD` and `ESM` module formats
  ([#227](https://github.com/taiga-family/maskito/issues/227))
  ([fa1c514](https://github.com/taiga-family/maskito/commit/fa1c514a5753e3bca20e8b0994e4bf9f1c0ab6a4))

## [0.8.0](https://github.com/taiga-family/maskito/compare/v0.7.2...v0.8.0) (2023-03-23)

### 🚀 Features

- **kit:** `DateRange` swaps dates if the 2nd date is less than the 1st one
  ([#212](https://github.com/taiga-family/maskito/issues/212))
  ([3efbb42](https://github.com/taiga-family/maskito/commit/3efbb42f2dd5c4e43ff514da7a82abfc7c4b3a38))

### 🐞 Bug Fixes

- **core:** incorrect order of actions during update of native element
  ([#225](https://github.com/taiga-family/maskito/issues/225))
  ([394d5d9](https://github.com/taiga-family/maskito/commit/394d5d996bdb9d21229ea0301eb3f776bee05d30))

### [0.7.2](https://github.com/taiga-family/maskito/compare/v0.7.1...v0.7.2) (2023-03-23)

### 🐞 Bug Fixes

- **angular:** `@maskito/angular` should not depend on `@maskito/kit`
  ([#221](https://github.com/taiga-family/maskito/issues/221))
  ([0ae7b20](https://github.com/taiga-family/maskito/commit/0ae7b2089ec0436caa8dbb14d5c696ae93e9e7ed))
- **angular:** `npm i @maskito/angular` throws `unable to resolve dependency tree`
  ([#220](https://github.com/taiga-family/maskito/issues/220))
  ([8b4d6e6](https://github.com/taiga-family/maskito/commit/8b4d6e6186db47f97d328186b7afd9af75a3889b))

### [0.7.1](https://github.com/taiga-family/maskito/compare/v0.7.0...v0.7.1) (2023-03-22)

### 🐞 Bug Fixes

- **angular:** use `@nrwl/angular:package` executor instead of `@nrwl/angular:ng-packagr-lite`
  ([#216](https://github.com/taiga-family/maskito/issues/216))
  ([164d015](https://github.com/taiga-family/maskito/commit/164d015c2f18a279e195b45329e84c0d023c9483))
- **kit:** `Number` broken `Delete`-button navigation if `decimalZeroPadding=true`
  ([#211](https://github.com/taiga-family/maskito/issues/211))
  ([1b750d1](https://github.com/taiga-family/maskito/commit/1b750d135ebd53bfeda2ca734425de08a808b1af))

## [0.7.0](https://github.com/taiga-family/maskito/compare/v0.6.0...v0.7.0) (2023-03-20)

### 🚀 Features

- **core:** add `deleteSoftLineBackward` & `deleteSoftLineForward` support
  ([#207](https://github.com/taiga-family/maskito/issues/207))
  ([cbd5479](https://github.com/taiga-family/maskito/commit/cbd5479c04c07113804eee6ea6c9838ee8681597))
- **kit:** use 1 as min segment value in `Date`-related masks
  ([#197](https://github.com/taiga-family/maskito/issues/197))
  ([c85ca23](https://github.com/taiga-family/maskito/commit/c85ca2355cb0b6fcef73f3e7497f7c31fa82c87c))

### 🐞 Bug Fixes

- **core:** `Maskito` losses valid characters on invalid insertion (`overwriteMode: replace`)
  ([#208](https://github.com/taiga-family/maskito/issues/208))
  ([ef183b4](https://github.com/taiga-family/maskito/commit/ef183b454e4a7db5b2cb48cbe26129bf303f676a))
- **kit:** `Number` should drop leading zeroes for negative numbers
  ([#204](https://github.com/taiga-family/maskito/issues/204))
  ([6e9adf7](https://github.com/taiga-family/maskito/commit/6e9adf758aa585944ee08f2e2aff81a5664adefd))

## [0.6.0](https://github.com/taiga-family/maskito/compare/v0.5.0...v0.6.0) (2023-03-15)

### 🚀 Features

- **angular:** add CVA and pipe ([#187](https://github.com/taiga-family/maskito/issues/187))
  ([a099257](https://github.com/taiga-family/maskito/commit/a099257a16b569444cdae9276ce66e9a806f531e))
- **core:** add `deleteWordBackward` & `deleteWordForward` support
  ([#193](https://github.com/taiga-family/maskito/issues/193))
  ([24b761c](https://github.com/taiga-family/maskito/commit/24b761c84d0947df5e4c78a2114f1de8f6ca20f4))

### 🐞 Bug Fixes

- **core:** show trailing fixed characters + duplicated fixed character on `Drop`
  ([#185](https://github.com/taiga-family/maskito/issues/185))
  ([c7f6a1b](https://github.com/taiga-family/maskito/commit/c7f6a1bb8098b5641ed8c6921c2ebc86c6135b58))
- **kit:** `maskitoParseNumber` incorrectly parses negative numbers
  ([#190](https://github.com/taiga-family/maskito/issues/190))
  ([d713bd1](https://github.com/taiga-family/maskito/commit/d713bd143e5090870a406ea14498cb99843bb9d0))
- **kit:** `Number` should drop decimal part on paste from clipboard if `precision=0`
  ([#195](https://github.com/taiga-family/maskito/issues/195))
  ([ba85c38](https://github.com/taiga-family/maskito/commit/ba85c38ec0c81a22ff758f4ba386d045ac49ffd5))

## [0.5.0](https://github.com/taiga-family/maskito/compare/v0.4.0...v0.5.0) (2023-03-09)

### 🚀 Features

- **core:** new utility `maskitoTransform(value, maskitoOptions)`
  ([#177](https://github.com/taiga-family/maskito/issues/177))
  ([20316f1](https://github.com/taiga-family/maskito/commit/20316f15e153bfeeb45eda6406b8792e00f3238f))
- **kit:** new utility `maskitoParseNumber` ([#178](https://github.com/taiga-family/maskito/issues/178))
  ([fc58141](https://github.com/taiga-family/maskito/commit/fc58141625ecbdc7d804aa382a69b38bf7146fc4))

### 🐞 Bug Fixes

- **kit:** `Number` mask throws an error on empty string in `thousandSeparator`
  ([#176](https://github.com/taiga-family/maskito/issues/176))
  ([cd52fad](https://github.com/taiga-family/maskito/commit/cd52fad80bc278f171dafa1709c54cba3f8fbc81))

## [0.4.0](https://github.com/taiga-family/maskito/compare/v0.3.0...v0.4.0) (2023-03-02)

### 🚀 Features

- **angular:** `maskitoElement` add new input ([#164](https://github.com/taiga-family/maskito/issues/164))
  ([407c131](https://github.com/taiga-family/maskito/commit/407c131d2d8f8514173ad7a5e248759e2d4f8abc))

### 🐞 Bug Fixes

- **kit:** `Number` pads empty integer part when paste from clipboard
  ([#168](https://github.com/taiga-family/maskito/issues/168))
  ([d043a82](https://github.com/taiga-family/maskito/commit/d043a82561cbed94b19d59d174fa6da7f08d49d4))

## [0.3.0](https://github.com/taiga-family/maskito/compare/v0.2.0...v0.3.0) (2023-03-01)

### 🚀 Features

- **angular:** add other maskito packages to `ng-update.packageGroup` of `package.json`
  ([#161](https://github.com/taiga-family/maskito/issues/161))
  ([bdecdaa](https://github.com/taiga-family/maskito/commit/bdecdaa9cac2681e35191cabd2d5d853eb97a09d))

### 🐞 Bug Fixes

- **kit:** `Date`-mask fix wrong year that appears using the min property
  ([#157](https://github.com/taiga-family/maskito/issues/157))
  ([544e891](https://github.com/taiga-family/maskito/commit/544e8912d2752e0fc8f77757e935070b94823f65))

## [0.2.0](https://github.com/taiga-family/maskito/compare/v0.1.1...v0.2.0) (2023-02-28)

### 🚀 Features

- **kit:** new `DateTime` mask ([#146](https://github.com/taiga-family/maskito/issues/146))
  ([6d6b2c1](https://github.com/taiga-family/maskito/commit/6d6b2c17b5c0f62bc804451524cd4b2ce3e50660))

### 🐞 Bug Fixes

- **kit:** `Number` is now replacing hyphen, en-dash and em-dash with minus sign
  ([#153](https://github.com/taiga-family/maskito/issues/153))
  ([1f21f11](https://github.com/taiga-family/maskito/commit/1f21f1159baadcef65e49bacaec77eba3b6f36d8))

### [0.1.1](https://github.com/taiga-family/maskito/compare/v0.1.0...v0.1.1) (2023-02-15)

### 🐞 Bug Fixes

- **core:** `Module parse failed: 'import' and 'export' may appear only with 'sourceType: module'`
  ([#131](https://github.com/taiga-family/maskito/issues/131))
  ([41e05c0](https://github.com/taiga-family/maskito/commit/41e05c09e41ed611e0c2b9aa07a953dfbe049da7))

## 0.1.0 (2023-02-14)

This release introduces the first publishing of the following packages:

- `@maskito/core` <br /> It is the main zero-dependency and framework-agnostic package. It can be used alone in Vanilla
  JavaScript project. It listens `beforeinput` and `input` events to validate and calibrate textfield's value. <br />
  Read more: https://maskito.dev/core-concepts/overview
- `@maskito/kit` <br /> The optional framework-agnostic package. It contains ready-to-use masks with configurable
  parameters. This release introduces the following masks:
  - [Number](https://maskito.dev/kit/number)
  - [Time](https://maskito.dev/kit/time)
  - [Date](https://maskito.dev/kit/date)
  - [DateRange](https://maskito.dev/kit/date-range)
- `@maskito/angular`<br /> The Angular-specific library. It provides two convenient ways of using Maskito:
  - Basic directive approach (when developer has direct access to native input element).
  - Dependency Injection approach (when native input element is hidden somewhere deep inside another component).


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   Copyright 2024 Acpekt

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: README.md
================================================
# Maskito

[![npm version](https://img.shields.io/npm/v/@maskito/core.svg)](https://npmjs.com/package/@maskito/core)
[![All packages CI](https://github.com/taiga-family/maskito/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/taiga-family/maskito/actions/workflows/build.yml)

<p align="center">
    <img src="projects/demo/src/assets/icons/maskito.svg" alt="Maskito logo" width="120px">
</p>

<p align="center">
    <a href="https://maskito.dev">Documentation</a> •
    <a href="https://github.com/taiga-family/maskito/issues/new/choose">Submit an Issue</a> •
    <a href="https://t.me/taiga_ui/10600">Contact Us</a>
</p>

**Maskito** is a collection of libraries, built with TypeScript. It helps you to create an input mask which ensures that
users type values according to predefined format.

## Why Maskito

- **Maskito** supports all user’s interactions with text fields: basic typing and deleting via keyboard, pasting,
  dropping text inside with a pointer, browser autofill, predictive text from mobile native keyboard.

- **Maskito** is robust. The whole project is developed with strict TypeScript mode. Our code is covered by hundreds of
  [Cypress](https://www.cypress.io) tests.

- Server Side Rendering and Shadow DOM support.

- You can use it with `HTMLInputElement` or `HTMLTextAreaElement` or even with `[contenteditable]` element.

- **Maskito** core is zero-dependency package. You can mask input in your vanilla JavaScript project. However, we have
  separate packages for Angular, React and Vue as well.

- **Maskito** includes optional framework-agnostic package with configurable ready-to-use masks.

No text field with invalid value! Use Maskito. **Mask it!** Learn more about the library in our
[documentation](https://maskito.dev).

## Contributing

If you have suggestions for how **Maskito** could be improved, or want to report a bug, open an issue! We'd love all and
any contributions.

For more, check out the [Contributing Guide](CONTRIBUTING.md).

## Maintained

Maskito is a part of [Taiga UI](https://github.com/taiga-family/taiga-ui) libraries family which is backed and used by a
large enterprise. This means you can rely on timely support and continuous development.

| **Package**                                                    | **Downloads**                                                                                     |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| [@maskito/core](https://npmjs.com/package/@maskito/core)       | [![](https://img.shields.io/npm/dw/@maskito/core)](https://npmjs.com/package/@maskito/core)       |
| [@maskito/kit](https://npmjs.com/package/@maskito/kit)         | [![](https://img.shields.io/npm/dw/@maskito/kit)](https://npmjs.com/package/@maskito/kit)         |
| [@maskito/react](https://npmjs.com/package/@maskito/react)     | [![](https://img.shields.io/npm/dw/@maskito/react)](https://npmjs.com/package/@maskito/react)     |
| [@maskito/angular](https://npmjs.com/package/@maskito/angular) | [![](https://img.shields.io/npm/dw/@maskito/angular)](https://npmjs.com/package/@maskito/angular) |
| [@maskito/vue](https://npmjs.com/package/@maskito/vue)         | [![](https://img.shields.io/npm/dw/@maskito/vue)](https://npmjs.com/package/@maskito/vue)         |
| [@maskito/phone](https://npmjs.com/package/@maskito/phone)     | [![](https://img.shields.io/npm/dw/@maskito/phone)](https://npmjs.com/package/@maskito/phone)     |

## License

🆓 Feel free to use our library in your commercial and private applications

All **Maskito** packages are covered by [Apache 2.0](/LICENSE)

Read more about this license [here](https://choosealicense.com/licenses/apache-2.0/)


================================================
FILE: codecov.yml
================================================
codecov:
  branch: main
  notify:
    require_ci_to_pass: no

coverage:
  # This value is used to customize the visible color range in Codecov.
  # The first number represents the red, and the second represents green.
  # You can change the range of colors by adjusting this configuration.
  range: 50..100 # by default 70..100
  round: down
  precision: 2

  # Disable codecov/patch check
  status:
    project:
      default:
        enabled: false
    patch:
      default:
        enabled: false


================================================
FILE: eslint.config.ts
================================================
import taiga from '@taiga-ui/eslint-plugin-experience-next';

export default [
    ...taiga.configs.recommended,
    {
        files: ['*.tsx'],
        rules: {
            'react/display-name': 'off',
            'react/react-in-jsx-scope': 'off',
            'no-irregular-whitespace': 'off',
        },
    },
    {
        files: ['*.spec.tsx'],
        rules: {
            'jest/prefer-ending-with-an-expect': [
                'error',
                {assertFunctionNames: ['expect', 'check']},
            ],
        },
    },
    // TODO: fix later
    {
        files: ['**/*'],
        rules: {
            '@typescript-eslint/no-unused-private-class-members': 'off',
            '@typescript-eslint/prefer-function-type': 'off',
            '@typescript-eslint/no-restricted-types': 'off',
            '@typescript-eslint/non-nullable-type-assertion-style': 'off',
            '@angular-eslint/template/alt-text': 'off',
            '@angular-eslint/prefer-signals': 'off',
            '@typescript-eslint/no-redundant-type-constituents': 'off',
            'no-irregular-whitespace': 'off',
            'de-morgan/no-negated-disjunction': 'off',
            '@angular-eslint/template/no-interpolation-in-attributes': 'off',
            '@typescript-eslint/no-invalid-this': 'off',
            '@angular-eslint/consistent-component-styles': 'off',
            '@typescript-eslint/no-useless-default-assignment': 'off',
            'import/consistent-type-specifier-style': 'off',
            '@typescript-eslint/no-unnecessary-type-conversion': 'off',
            '@typescript-eslint/consistent-type-exports': 'off',
            '@typescript-eslint/method-signature-style': 'off',
            '@typescript-eslint/strict-void-return': 'off',
        },
    },
];


================================================
FILE: firebase.json
================================================
{
    "hosting": {
        "public": "dist/demo/browser",
        "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
        "rewrites": [
            {
                "source": "**",
                "destination": "/index.html"
            }
        ]
    }
}


================================================
FILE: jest.config.ts
================================================
import {getJestProjectsAsync} from '@nx/jest';
import type {Config} from 'jest';

export default async (): Promise<Config> => ({projects: await getJestProjectsAsync()});


================================================
FILE: jest.preset.js
================================================
const nxPreset = require('@nx/jest/preset').default;
const {resolve} = require('node:path');

module.exports = {
    ...nxPreset,
    transform: {
        '^.+\\.(ts|tsx|js|jsx|mjs|html|svg)$': [
            'jest-preset-angular',
            {
                diagnostics: true,
                stringifyContentPathRegex: String.raw`\.html$`,
                tsconfig: resolve(__dirname, 'tsconfig.spec.json'),
            },
        ],
    },
};


================================================
FILE: nx.json
================================================
{
    "tui": {
        "enabled": false
    },
    "workspaceLayout": {
        "libsDir": "projects",
        "appsDir": "projects"
    },
    "defaultProject": "demo",
    "generators": {
        "@nx/js:library": {
            "buildable": true,
            "publishable": true,
            "strict": true,
            "linter": "none",
            "unitTestRunner": "jest",
            "config": "project"
        },
        "@nx/angular:library": {
            "linter": "none",
            "unitTestRunner": "jest",
            "buildable": true,
            "publishable": true,
            "compilationMode": "partial",
            "strict": true,
            "skipModule": true,
            "standaloneConfig": true
        },
        "@nx/angular:application": {
            "style": "less",
            "linter": "none",
            "unitTestRunner": "jest"
        },
        "@nx/angular:component": {
            "style": "less"
        },
        "@nx/react": {
            "application": {
                "babel": true
            },
            "library": {
                "linter": "eslint",
                "publishable": true,
                "bundler": "rollup",
                "style": "none",
                "strict": true,
                "unitTestRunner": "jest"
            }
        }
    },
    "$schema": "./node_modules/nx/schemas/nx-schema.json",
    "namedInputs": {
        "default": ["{projectRoot}/**/*", "sharedGlobals"],
        "sharedGlobals": [
            "{workspaceRoot}/angular.json",
            "{workspaceRoot}/nx.json",
            "{workspaceRoot}/karma.*.js",
            "{workspaceRoot}/tsconfig.*.json",
            "{workspaceRoot}/tsconfig.json",
            "{workspaceRoot}/babel.config.json"
        ],
        "production": [
            "default",
            "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
            "!{projectRoot}/tsconfig.spec.json",
            "!{projectRoot}/jest.config.[jt]s",
            "!{projectRoot}/src/test-setup.[jt]s",
            "!{projectRoot}/**/*.cy.[jt]s?(x)",
            "!{projectRoot}/cypress.config.[jt]s"
        ]
    },
    "targetDefaults": {
        "build": {
            "inputs": ["production", "^production"],
            "cache": true
        },
        "lint": {
            "cache": true
        },
        "@nx/jest:jest": {
            "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
            "cache": true,
            "options": {
                "passWithNoTests": true
            },
            "configurations": {
                "ci": {
                    "ci": true,
                    "codeCoverage": true
                }
            }
        },
        "component-test": {
            "cache": true,
            "inputs": ["default", "^production"]
        },
        "ct-react": {
            "cache": true,
            "inputs": ["default", "^production"]
        }
    },
    "parallel": 3,
    "useInferencePlugins": false,
    "defaultBase": "origin/main"
}


================================================
FILE: package.json
================================================
{
    "name": "maskito",
    "version": "5.2.2",
    "description": "Collection of libraries to create an input mask which ensures that user types value according to predefined format",
    "homepage": "https://maskito.dev",
    "bugs": "https://github.com/taiga-family/maskito/issues",
    "repository": {
        "type": "git",
        "url": "https://github.com/taiga-family/maskito.git"
    },
    "license": "Apache-2.0",
    "author": {
        "email": "nikita.s.barsukov@gmail.com",
        "name": "Nikita Barsukov",
        "url": "https://github.com/nsbarsukov"
    },
    "contributors": [
        {
            "email": "alexander@inkin.ru",
            "name": "Alex Inkin"
        },
        {
            "email": "vladimir.potekh@gmail.com",
            "name": "Vladimir Potekhin"
        },
        {
            "email": "nikita.s.barsukov@gmail.com",
            "name": "Nikita Barsukov"
        },
        {
            "email": "nextzeddicus@gmail.com",
            "name": "Georgiy Lunin"
        }
    ],
    "workspaces": [
        "projects/*"
    ],
    "scripts": {
        "build": "nx run demo:build:production",
        "cspell": "cspell --relative --dot --gitignore .",
        "cy:open": "cypress open --project ./projects/demo-integrations/",
        "cy:run": "nx e2e demo-integrations && nx component-test demo-integrations && nx ct-react demo-integrations",
        "lint": "eslint .",
        "prepare": "husky",
        "prettier": "prettier !package-lock.json . --ignore-path .gitignore",
        "release": "npx nx run-many --target publish --all",
        "release:local": "npx release-it --no-git.push --'hooks.before:release=\"echo Skip publish\"'",
        "serve:ssr": "node dist/demo/server/server.mjs",
        "start": "nx run demo:serve",
        "stylelint": "stylelint '**/*.{less,css}'",
        "test": "nx run-many --target test --all",
        "typecheck": "tsc --noEmit --skipLibCheck --incremental false --tsBuildInfoFile null --project tsconfig.spec.json && tsc -p projects/demo-integrations/tsconfig.json"
    },
    "commitlint": {
        "extends": [
            "@taiga-ui/commitlint-config"
        ]
    },
    "lint-staged": {
        "*.less": [
            "stylelint --fix"
        ],
        "*.{js,ts,html,md,less,json,svg,yml}": [
            "npm run lint -- --fix",
            "prettier --write"
        ]
    },
    "browserslist": [
        "extends @taiga-ui/browserslist-config"
    ],
    "prettier": "@taiga-ui/prettier-config",
    "stylelint": {
        "extends": [
            "@taiga-ui/stylelint-config"
        ],
        "ignoreFiles": [
            "**/dist/**",
            "**/coverage/**",
            "**/node_modules/**"
        ]
    },
    "overrides": {
        "@taiga-ui/addon-commerce": {
            "@maskito/angular": ">=4.0.0",
            "@maskito/core": ">=4.0.0",
            "@maskito/kit": ">=4.0.0",
            "@maskito/phone": ">=4.0.0"
        },
        "@taiga-ui/kit": {
            "@maskito/angular": ">=4.0.0",
            "@maskito/core": ">=4.0.0",
            "@maskito/kit": ">=4.0.0",
            "@maskito/phone": ">=4.0.0"
        }
    },
    "devDependencies": {
        "@angular-devkit/build-angular": "19.2.22",
        "@angular-devkit/core": "19.2.22",
        "@angular-devkit/schematics": "19.2.22",
        "@angular/build": "19.2.22",
        "@angular/cli": "19.2.22",
        "@angular/compiler-cli": "19.2.20",
        "@angular/core": "19.2.20",
        "@angular/platform-browser-dynamic": "19.2.20",
        "@nx/angular": "21.6.3",
        "@nx/eslint": "21.6.3",
        "@nx/jest": "21.6.3",
        "@nx/js": "21.6.3",
        "@nx/module-federation": "21.6.3",
        "@nx/react": "21.6.3",
        "@nx/rollup": "21.6.3",
        "@nx/workspace": "21.6.3",
        "@taiga-ui/configs": "0.476.0",
        "@tinkoff/eslint-config": "5.2.0",
        "@tinkoff/eslint-config-react": "5.2.0",
        "@types/highlight.js": "10.1.0",
        "@types/node": "24.10.11",
        "http-server": "14.1.1",
        "husky": "9.1.7",
        "ng-packagr": "19.2.2",
        "nx": "21.6.3",
        "postcss-preset-env": "10.6.1",
        "ts-node": "10.9.2",
        "tsutils": "3.21.0",
        "typescript": "5.8.3"
    },
    "engines": {
        "node": ">= 24",
        "npm": ">= 11",
        "yarn": "Please use npm instead of yarn to install dependencies"
    },
    "auto-changelog": {
        "prepend": true,
        "template": "templates/note.hbs"
    },
    "syncer": {
        "includePaths": [
            "./projects",
            "./package-lock.json"
        ],
        "matchPackageNames": [
            "@maskito/*",
            "maskito"
        ]
    }
}


================================================
FILE: projects/angular/README.md
================================================
# @maskito/angular

[![npm version](https://img.shields.io/npm/v/@maskito/angular.svg)](https://npmjs.com/package/@maskito/angular)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@maskito/angular)](https://bundlephobia.com/result?p=@maskito/angular)

<p align="center">
    <img src="https://raw.githubusercontent.com/taiga-family/maskito/main/projects/demo/src/assets/icons/maskito.svg" alt="Maskito logo" width="120px">
</p>

<p align="center">
    <a href="https://maskito.dev/frameworks/angular">Documentation</a> •
    <a href="https://github.com/taiga-family/maskito/issues/new/choose">Submit an Issue</a> •
    <a href="https://t.me/taiga_ui/10600">Contact Us</a>
</p>

> The Angular-specific library.<br /> It provides a convenient way to use Maskito as a directive.

## How to install

```bash
npm i @maskito/{core,angular}
```


================================================
FILE: projects/angular/jest.config.ts
================================================
export default {
    displayName: 'angular',
    preset: '../../jest.preset.js',
    setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
    coverageDirectory: '../../coverage/angular',
    transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'],
    snapshotSerializers: [
        'jest-preset-angular/build/serializers/no-ng-attributes',
        'jest-preset-angular/build/serializers/ng-snapshot',
        'jest-preset-angular/build/serializers/html-comment',
    ],
};


================================================
FILE: projects/angular/ng-package.json
================================================
{
    "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
    "dest": "../../dist/angular",
    "lib": {
        "entryFile": "src/index.ts"
    }
}


================================================
FILE: projects/angular/package.json
================================================
{
    "name": "@maskito/angular",
    "version": "5.2.2",
    "description": "The Angular-specific Maskito's library",
    "keywords": [
        "input",
        "mask",
        "inputmask",
        "input-mask",
        "text-mask",
        "format",
        "input-format",
        "input-formatting",
        "angular"
    ],
    "homepage": "https://maskito.dev",
    "bugs": "https://github.com/taiga-family/maskito/issues",
    "repository": {
        "type": "git",
        "url": "https://github.com/taiga-family/maskito.git"
    },
    "license": "Apache-2.0",
    "author": {
        "email": "nikita.s.barsukov@gmail.com",
        "name": "Nikita Barsukov",
        "url": "https://github.com/nsbarsukov"
    },
    "contributors": [
        {
            "email": "alexander@inkin.ru",
            "name": "Alex Inkin"
        },
        {
            "email": "vladimir.potekh@gmail.com",
            "name": "Vladimir Potekhin"
        },
        {
            "email": "nikita.s.barsukov@gmail.com",
            "name": "Nikita Barsukov"
        },
        {
            "email": "nextzeddicus@gmail.com",
            "name": "Georgiy Lunin"
        }
    ],
    "dependencies": {
        "tslib": "2.8.1"
    },
    "devDependencies": {
        "@angular/core": "19.2.20",
        "@angular/forms": "19.2.20"
    },
    "peerDependencies": {
        "@angular/core": ">=19.0.0",
        "@angular/forms": ">=19.0.0",
        "@maskito/core": "^5.2.2"
    },
    "ng-update": {
        "packageGroup": [
            "@maskito/core",
            "@maskito/kit"
        ]
    }
}


================================================
FILE: projects/angular/project.json
================================================
{
    "$schema": "../../node_modules/nx/schemas/project-schema.json",
    "name": "angular",
    "prefix": "maskito",
    "projectType": "library",
    "sourceRoot": "projects/angular/src",
    "tags": [],
    "targets": {
        "build": {
            "configurations": {
                "development": {},
                "production": {
                    "tsConfig": "{projectRoot}/tsconfig.lib.prod.json"
                }
            },
            "defaultConfiguration": "production",
            "dependsOn": [
                {
                    "dependencies": true,
                    "params": "forward",
                    "target": "build"
                }
            ],
            "executor": "@nx/angular:package",
            "options": {
                "project": "{projectRoot}/ng-package.json",
                "tsConfig": "tsconfig.build.json"
            },
            "outputs": ["{workspaceRoot}/dist/{projectName}"]
        },
        "publish": {
            "dependsOn": [
                {
                    "params": "ignore",
                    "target": "build"
                }
            ],
            "executor": "nx:run-commands",
            "options": {
                "command": "npm publish ./dist/{projectName} --ignore-scripts"
            }
        },
        "test": {
            "executor": "@nx/jest:jest",
            "options": {
                "jestConfig": "{projectRoot}/jest.config.ts"
            },
            "outputs": ["{workspaceRoot}/coverage/{projectName}"]
        }
    }
}


================================================
FILE: projects/angular/src/index.ts
================================================
export * from './lib/maskito.directive';
export * from './lib/maskito.pipe';
export * from './lib/pattern.directive';


================================================
FILE: projects/angular/src/lib/maskito.directive.ts
================================================
import {
    Directive,
    effect,
    ElementRef,
    inject,
    model,
    NgZone,
    type OnDestroy,
    untracked,
} from '@angular/core';
import {DefaultValueAccessor} from '@angular/forms';
import {
    Maskito,
    MASKITO_DEFAULT_ELEMENT_PREDICATE,
    type MaskitoOptions,
    maskitoTransform,
} from '@maskito/core';

@Directive({selector: '[maskito]'})
export class MaskitoDirective implements OnDestroy {
    private readonly elementRef: HTMLElement = inject(ElementRef).nativeElement;
    private readonly ngZone = inject(NgZone);
    private maskedElement: Maskito | null = null;

    protected readonly initEffect = effect(async () => {
        const options = this.options();
        const elementPredicate = this.elementPredicate();
        const {elementRef, ngZone} = this;

        this.destroy();

        if (!options) {
            return;
        }

        const predicateResult = await elementPredicate(elementRef);

        if (
            untracked(this.elementPredicate) !== elementPredicate ||
            untracked(this.options) !== options
        ) {
            // Ignore the result of the predicate if the
            // maskito element (or its options) has changed before the predicate was resolved.
            return;
        }

        ngZone.runOutsideAngular(() => {
            this.maskedElement = new Maskito(predicateResult, options);
        });
    });

    public readonly options = model<MaskitoOptions | null>(null, {alias: 'maskito'});
    public readonly elementPredicate = model(MASKITO_DEFAULT_ELEMENT_PREDICATE, {
        alias: 'maskitoElement',
    });

    constructor() {
        const accessor = inject(DefaultValueAccessor, {self: true, optional: true});

        if (accessor) {
            const original = accessor.writeValue.bind(accessor);

            accessor.writeValue = (value: unknown) => {
                const options = untracked(this.options);

                original(
                    options ? maskitoTransform(String(value ?? ''), options) : value,
                );
            };
        }
    }

    public ngOnDestroy(): void {
        this.destroy();
    }

    private destroy(): void {
        this.maskedElement?.destroy();
        this.maskedElement = null;
    }
}


================================================
FILE: projects/angular/src/lib/maskito.pipe.ts
================================================
import {Pipe, type PipeTransform} from '@angular/core';
import {
    MASKITO_DEFAULT_OPTIONS,
    type MaskitoOptions,
    maskitoTransform,
} from '@maskito/core';

@Pipe({name: 'maskito'})
export class MaskitoPipe implements PipeTransform {
    public transform(value: unknown, maskitoOptions: MaskitoOptions | null): string {
        return maskitoTransform(
            String(value ?? ''),
            maskitoOptions ?? MASKITO_DEFAULT_OPTIONS,
        );
    }
}


================================================
FILE: projects/angular/src/lib/pattern.directive.ts
================================================
import {Directive, inject} from '@angular/core';

import {MaskitoDirective} from './maskito.directive';

@Directive({
    selector: '[maskitoPattern]',
    inputs: ['maskitoPattern'],
    hostDirectives: [MaskitoDirective],
})
export class MaskitoPattern {
    private readonly maskitoDirective = inject(MaskitoDirective, {self: true});

    public set maskitoPattern(pattern: RegExp | string) {
        this.maskitoDirective.options.set({
            mask: typeof pattern === 'string' ? new RegExp(`^${pattern}$`) : pattern,
        });
    }
}


================================================
FILE: projects/angular/src/lib/tests/maskito.directive.spec.ts
================================================
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {type ComponentFixture, TestBed} from '@angular/core/testing';
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals';
import {MaskitoDirective} from '@maskito/angular';
import {
    Maskito,
    MASKITO_DEFAULT_ELEMENT_PREDICATE,
    type MaskitoElementPredicate,
    type MaskitoOptions,
} from '@maskito/core';

const DIGIT_ONLY: MaskitoOptions = {mask: /^\d*$/};

describe('MaskitoDirective — initEffect', () => {
    @Component({
        imports: [MaskitoDirective],
        template: `
            <input
                [maskito]="options()"
                [maskitoElement]="predicate()"
            />
        `,
        changeDetection: ChangeDetectionStrategy.OnPush,
    })
    class TestHostComponent {
        public readonly options = signal<MaskitoOptions | null>(null);
        public readonly predicate = signal(MASKITO_DEFAULT_ELEMENT_PREDICATE);
    }

    let fixture: ComponentFixture<TestHostComponent>;
    let destroySpy: ReturnType<typeof jest.spyOn>;

    function getDirective(): MaskitoDirective {
        return fixture.debugElement.children[0]!.injector.get(MaskitoDirective);
    }

    function getMaskedElement(): Maskito | null {
        return (getDirective() as unknown as {maskedElement: Maskito | null})
            .maskedElement;
    }

    beforeEach(() => {
        TestBed.configureTestingModule({imports: [TestHostComponent]});
        destroySpy = jest.spyOn(Maskito.prototype, 'destroy');
        fixture = TestBed.createComponent(TestHostComponent);
        fixture.detectChanges();
    });

    afterEach(() => {
        jest.restoreAllMocks();
    });

    describe('when options is null', () => {
        it('does not create a Maskito instance', async () => {
            await fixture.whenStable();

            expect(getMaskedElement()).toBeNull();
        });
    });

    describe('when options are provided', () => {
        beforeEach(async () => {
            fixture.componentInstance.options.set(DIGIT_ONLY);
            fixture.detectChanges();
            await fixture.whenStable();
        });

        it('creates a Maskito instance', () => {
            expect(getMaskedElement()).toBeInstanceOf(Maskito);
        });

        it('destroys the old instance and creates a new one when options change', async () => {
            fixture.componentInstance.options.set({mask: /^[a-z]*$/});
            fixture.detectChanges();
            await fixture.whenStable();

            expect(destroySpy).toHaveBeenCalledTimes(1);
            expect(getMaskedElement()).toBeInstanceOf(Maskito);
        });

        it('destroys the instance when options become null', async () => {
            fixture.componentInstance.options.set(null);
            fixture.detectChanges();
            await fixture.whenStable();

            expect(destroySpy).toHaveBeenCalledTimes(1);
            expect(getMaskedElement()).toBeNull();
        });

        it('destroys the instance when the directive is destroyed', () => {
            const directive = getDirective() as unknown as {
                maskedElement: Maskito | null;
            };

            fixture.destroy();

            expect(destroySpy).toHaveBeenCalledTimes(1);
            expect(directive.maskedElement).toBeNull();
        });
    });

    describe('stale async predicate', () => {
        function makeControlledPredicate(): {
            predicate: MaskitoElementPredicate;
            resolveCall: (index: number) => void;
        } {
            const resolvers: Array<() => void> = [];
            const predicate: MaskitoElementPredicate = async (el) =>
                new Promise<HTMLInputElement>((resolve) => {
                    resolvers.push(() => resolve(el as HTMLInputElement));
                });

            return {predicate, resolveCall: (i) => resolvers[i]!()};
        }

        it('ignores the result when elementPredicate changes before it resolves', async () => {
            const {predicate: slowPredicate, resolveCall} = makeControlledPredicate();

            fixture.componentInstance.options.set(DIGIT_ONLY);
            fixture.componentInstance.predicate.set(slowPredicate);
            fixture.detectChanges();
            await fixture.whenStable();

            expect(getMaskedElement()).toBeNull();

            fixture.componentInstance.predicate.set(MASKITO_DEFAULT_ELEMENT_PREDICATE);
            fixture.detectChanges();
            await fixture.whenStable();

            expect(getMaskedElement()).toBeInstanceOf(Maskito);
            expect(destroySpy).not.toHaveBeenCalled();

            resolveCall(0);
            await fixture.whenStable();

            expect(destroySpy).not.toHaveBeenCalled();
            expect(getMaskedElement()).toBeInstanceOf(Maskito);
        });

        it('ignores the result when options change before the predicate resolves', async () => {
            const {predicate: slowPredicate, resolveCall} = makeControlledPredicate();

            fixture.componentInstance.options.set(DIGIT_ONLY);
            fixture.componentInstance.predicate.set(slowPredicate);
            fixture.detectChanges();
            await fixture.whenStable();

            expect(getMaskedElement()).toBeNull();

            fixture.componentInstance.options.set({mask: /^[a-z]*$/});
            fixture.detectChanges();
            await fixture.whenStable();

            resolveCall(0);
            await fixture.whenStable();

            expect(destroySpy).not.toHaveBeenCalled();
            expect(getMaskedElement()).toBeNull();
        });
    });
});


================================================
FILE: projects/angular/src/lib/tests/maskito.spec.ts
================================================
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {type ComponentFixture, TestBed} from '@angular/core/testing';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {beforeEach, describe, expect, it} from '@jest/globals';
import {MaskitoDirective, MaskitoPipe} from '@maskito/angular';
import type {MaskitoOptions} from '@maskito/core';

describe('Maskito Angular package', () => {
    @Component({
        imports: [MaskitoDirective, MaskitoPipe, ReactiveFormsModule],
        template: `
            <div id="pipe">{{ control.value | maskito: options }}</div>
            <input
                id="input"
                [formControl]="control"
                [maskito]="options"
            />
        `,
        // eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
        changeDetection: ChangeDetectionStrategy.Default,
    })
    class TestComponent {
        public readonly control = new FormControl();
        public options: MaskitoOptions | null = {
            mask: /^\d+(,\d{0,2})?$/,
            preprocessors: [
                ({elementState, data}) => {
                    const {value, selection} = elementState;

                    return {
                        elementState: {
                            selection,
                            value: value.replace('.', ','),
                        },
                        data: data.replace('.', ','),
                    };
                },
            ],
        };
    }

    let fixture: ComponentFixture<TestComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({imports: [TestComponent]});

        fixture = TestBed.createComponent(TestComponent);
        fixture.detectChanges();
    });

    it('null is treated as empty string', () => {
        expect(getText()).toBe('');
        expect(getValue()).toBe('');
    });

    it('formats new control value', () => {
        fixture.componentInstance.control.setValue(12345.6789);
        fixture.detectChanges();

        expect(getText()).toBe('12345,67');
        expect(getValue()).toBe('12345,67');
    });

    it('disable mask formatting if options is null', () => {
        fixture.componentInstance.options = null;
        fixture.detectChanges();

        fixture.componentInstance.control.setValue(123456.9999);
        fixture.detectChanges();

        expect(getText()).toBe('123456.9999');
        expect(getValue()).toBe('123456.9999');
    });

    function getText(): string {
        return fixture.debugElement.nativeElement
            .querySelector('#pipe')
            .textContent.trim();
    }

    function getValue(): string {
        return fixture.debugElement.nativeElement.querySelector('#input').value;
    }
});


================================================
FILE: projects/angular/src/test-setup.ts
================================================
import {setupZoneTestEnv} from 'jest-preset-angular/setup-env/zone';

setupZoneTestEnv();


================================================
FILE: projects/angular/tsconfig.lib.prod.json
================================================
{
    "extends": "../../tsconfig.build.json",
    "compilerOptions": {
        "declarationMap": false
    }
}


================================================
FILE: projects/core/README.md
================================================
# @maskito/core

[![npm version](https://img.shields.io/npm/v/@maskito/core.svg)](https://npmjs.com/package/@maskito/core)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@maskito/core)](https://bundlephobia.com/result?p=@maskito/core)

<p align="center">
    <img src="https://raw.githubusercontent.com/taiga-family/maskito/main/projects/demo/src/assets/icons/maskito.svg" alt="Maskito logo" width="120px">
</p>

<p align="center">
    <a href="https://maskito.dev">Documentation</a> •
    <a href="https://github.com/taiga-family/maskito/issues/new/choose">Submit an Issue</a> •
    <a href="https://t.me/taiga_ui/10600">Contact Us</a>
</p>

> It is the main zero-dependency and framework-agnostic Maskito's package.<br />It can be used alone in
> vanilla JavaScript project.

## How to install

```bash
npm i @maskito/core
```


================================================
FILE: projects/core/jest.config.ts
================================================
export default {
    displayName: 'core',
    preset: '../../jest.preset.js',
    moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
    coverageDirectory: '../../coverage/core',
};


================================================
FILE: projects/core/package.json
================================================
{
    "name": "@maskito/core",
    "version": "5.2.2",
    "description": "The main zero-dependency and framework-agnostic Maskito's package to create an input mask",
    "keywords": [
        "input",
        "mask",
        "inputmask",
        "input-mask",
        "text-mask",
        "format",
        "input-format",
        "input-formatting",
        "javascript",
        "typescript"
    ],
    "homepage": "https://maskito.dev",
    "bugs": "https://github.com/taiga-family/maskito/issues",
    "repository": {
        "type": "git",
        "url": "https://github.com/taiga-family/maskito.git"
    },
    "license": "Apache-2.0",
    "author": {
        "email": "nikita.s.barsukov@gmail.com",
        "name": "Nikita Barsukov",
        "url": "https://github.com/nsbarsukov"
    },
    "contributors": [
        {
            "email": "alexander@inkin.ru",
            "name": "Alex Inkin"
        },
        {
            "email": "vladimir.potekh@gmail.com",
            "name": "Vladimir Potekhin"
        },
        {
            "email": "nikita.s.barsukov@gmail.com",
            "name": "Nikita Barsukov"
        },
        {
            "email": "nextzeddicus@gmail.com",
            "name": "Georgiy Lunin"
        }
    ]
}


================================================
FILE: projects/core/project.json
================================================
{
    "$schema": "../../node_modules/nx/schemas/project-schema.json",
    "name": "core",
    "projectType": "library",
    "sourceRoot": "projects/core/src",
    "tags": [],
    "targets": {
        "build": {
            "executor": "@nx/rollup:rollup",
            "options": {
                "assets": [
                    {
                        "glob": "README.md",
                        "input": "{projectRoot}",
                        "output": "."
                    }
                ],
                "compiler": "tsc",
                "external": "all",
                "format": ["esm", "cjs"],
                "main": "{projectRoot}/src/index.ts",
                "outputPath": "dist/{projectName}",
                "project": "{projectRoot}/package.json",
                "tsConfig": "tsconfig.build.json",
                "useLegacyTypescriptPlugin": false
            },
            "outputs": ["{options.outputPath}"]
        },
        "publish": {
            "dependsOn": [
                {
                    "params": "ignore",
                    "target": "build"
                }
            ],
            "executor": "nx:run-commands",
            "options": {
                "command": "npm publish ./dist/{projectName} --ignore-scripts"
            }
        },
        "test": {
            "executor": "@nx/jest:jest",
            "options": {
                "jestConfig": "{projectRoot}/jest.config.ts"
            },
            "outputs": ["{workspaceRoot}/coverage/{projectName}"]
        }
    }
}


================================================
FILE: projects/core/src/index.ts
================================================
export {
    MASKITO_DEFAULT_ELEMENT_PREDICATE,
    MASKITO_DEFAULT_OPTIONS,
} from './lib/constants';
export {Maskito} from './lib/mask';
export {
    maskitoChangeEventPlugin,
    maskitoInitialCalibrationPlugin,
    maskitoStrictCompositionPlugin,
} from './lib/plugins';
export type {
    MaskitoElement,
    MaskitoElementPredicate,
    MaskitoMask,
    MaskitoMaskExpression,
    MaskitoOptions,
    MaskitoPlugin,
    MaskitoPostprocessor,
    MaskitoPreprocessor,
} from './lib/types';
export {
    maskitoAdaptContentEditable,
    maskitoPipe,
    maskitoTransform,
    maskitoUpdateElement,
} from './lib/utils';


================================================
FILE: projects/core/src/lib/classes/index.ts
================================================
export {MaskHistory} from './mask-history';
export {MaskModel} from './mask-model/mask-model';


================================================
FILE: projects/core/src/lib/classes/mask-history.ts
================================================
import type {ElementState, TypedInputEvent} from '../types';

export abstract class MaskHistory {
    private now: ElementState | null = null;
    private readonly past: ElementState[] = [];
    private future: ElementState[] = [];

    protected abstract updateElementState(
        state: ElementState,
        eventInit: Pick<TypedInputEvent, 'data' | 'inputType'>,
    ): void;

    protected undo(): void {
        const state = this.past.pop();

        if (state && this.now) {
            this.future.push(this.now);
            this.updateElement(state, 'historyUndo');
        }
    }

    protected redo(): void {
        const state = this.future.pop();

        if (state && this.now) {
            this.past.push(this.now);
            this.updateElement(state, 'historyRedo');
        }
    }

    protected updateHistory(state: ElementState): void {
        if (!this.now) {
            this.now = state;

            return;
        }

        const isValueChanged = this.now.value !== state.value;
        const isSelectionChanged = this.now.selection.some(
            (item, index) => item !== state.selection[index],
        );

        if (!isValueChanged && !isSelectionChanged) {
            return;
        }

        if (isValueChanged) {
            this.past.push(this.now);
            this.future = [];
        }

        this.now = state;
    }

    private updateElement(
        state: ElementState,
        inputType: TypedInputEvent['inputType'],
    ): void {
        this.now = state;
        this.updateElementState(state, {inputType, data: null});
    }
}


================================================
FILE: projects/core/src/lib/classes/mask-model/mask-model.ts
================================================
import type {
    ElementState,
    MaskitoMaskExpression,
    MaskitoOptions,
    SelectionRange,
} from '../../types';
import {areElementStatesEqual} from '../../utils/element-states-equality';
import {applyOverwriteMode} from './utils/apply-overwrite-mode';
import {calibrateValueByMask} from './utils/calibrate-value-by-mask';
import {removeFixedMaskCharacters} from './utils/remove-fixed-mask-characters';

export class MaskModel implements ElementState {
    private readonly unmaskInitialState: ElementState = {value: '', selection: [0, 0]};

    public value = '';
    public selection: SelectionRange = [0, 0];

    constructor(
        initialElementState: ElementState,
        private readonly maskOptions: Required<MaskitoOptions>,
    ) {
        const expression = this.getMaskExpression(initialElementState);
        const {value, selection} = calibrateValueByMask(initialElementState, expression);

        this.unmaskInitialState = removeFixedMaskCharacters(
            {value, selection},
            expression,
        );
        this.value = value;
        this.selection = selection;
    }

    public addCharacters(newCharacters: string): void {
        const {value, selection, maskOptions} = this;
        const initialElementState = {value, selection} as const;
        const {
            selection: [from, to],
        } = applyOverwriteMode(
            initialElementState,
            newCharacters,
            maskOptions.overwriteMode,
        );
        const maskExpression = this.getMaskExpression({
            value: `${value.slice(0, from)}${newCharacters}${value.slice(to)}`,
            selection: [from + newCharacters.length, from + newCharacters.length],
        });
        const [unmaskedFrom, unmaskedTo] = applyOverwriteMode(
            this.unmaskInitialState,
            newCharacters,
            maskOptions.overwriteMode,
        ).selection;
        const newUnmaskedLeadingValuePart = `${this.unmaskInitialState.value.slice(0, unmaskedFrom)}${newCharacters}`;
        const newCaretIndex = newUnmaskedLeadingValuePart.length;
        const maskedElementState = calibrateValueByMask(
            {
                value: `${newUnmaskedLeadingValuePart}${this.unmaskInitialState.value.slice(unmaskedTo)}`,
                selection: [newCaretIndex, newCaretIndex],
            },
            maskExpression,
            initialElementState,
        );
        const prevLeadingPart = value.slice(0, from);
        const newLeadingPartState = calibrateValueByMask(
            {
                value: newUnmaskedLeadingValuePart,
                selection: [newCaretIndex, newCaretIndex],
            },
            maskExpression,
            initialElementState,
        );

        const isInvalidCharsInsertion =
            newLeadingPartState.value === prevLeadingPart ||
            (newLeadingPartState.value.length < prevLeadingPart.length &&
                removeFixedMaskCharacters(newLeadingPartState, maskExpression).value ===
                    this.unmaskInitialState.value.slice(0, unmaskedFrom));

        if (
            isInvalidCharsInsertion ||
            areElementStatesEqual(this, maskedElementState) // If typing new characters does not change value
        ) {
            throw new Error('Invalid mask value');
        }

        this.value = maskedElementState.value;
        this.selection = maskedElementState.selection;
    }

    public deleteCharacters(): void {
        const [from, to] = this.selection;

        if (from === to || !to) {
            return;
        }

        const {value} = this;
        const maskExpression = this.getMaskExpression({
            value: `${value.slice(0, from)}${value.slice(to)}`,
            selection: [from, from],
        });
        const initialElementState = {value, selection: [from, to]} as const;
        const [unmaskedFrom, unmaskedTo] = this.unmaskInitialState.selection;
        const newUnmaskedValue = `${this.unmaskInitialState.value.slice(0, unmaskedFrom)}${this.unmaskInitialState.value.slice(unmaskedTo)}`;

        const maskedElementState = calibrateValueByMask(
            {value: newUnmaskedValue, selection: [unmaskedFrom, unmaskedFrom]},
            maskExpression,
            initialElementState,
        );

        this.value = maskedElementState.value;
        this.selection = maskedElementState.selection;
    }

    private getMaskExpression(elementState: ElementState): MaskitoMaskExpression {
        const {mask} = this.maskOptions;

        return typeof mask === 'function' ? mask(elementState) : mask;
    }
}


================================================
FILE: projects/core/src/lib/classes/mask-model/tests/dynamic-mask.spec.ts
================================================
import {describe, expect, it} from '@jest/globals';
import {MASKITO_DEFAULT_OPTIONS} from '@maskito/core';

import type {ElementState, MaskitoMask, MaskitoOptions} from '../../../types';
import {MaskModel} from '../mask-model';

const EMPTY_STATE: ElementState = {
    selection: [0, 0],
    value: '',
};

describe('MaskModel | Dynamic mask', () => {
    describe('switching on the fly works', () => {
        const SHORT: MaskitoMask = Array.from<RegExp>({length: 10}).fill(/\d/);
        const MEDIUM: MaskitoMask = [
            /\d/,
            /\d/,
            /\d/,
            /\d/,
            ' ',
            /\d/,
            /\d/,
            /\d/,
            /\d/,
            ' ',
            /\d/,
            /\d/,
            /\d/,
            /\d/,
            ' ',
            /\d/,
            /\d/,
            /\d/,
            /\d/,
        ];
        const LONG: MaskitoMask = Array.from<RegExp>({length: 20}).fill(/\d/);
        const maskitoOptions: Required<MaskitoOptions> = {
            ...MASKITO_DEFAULT_OPTIONS,
            mask: ({value}) => {
                const digitsCount = value.replaceAll(/\D/g, '').length;

                if (digitsCount <= 10) {
                    return SHORT;
                }

                if (digitsCount <= 16) {
                    return MEDIUM;
                }

                return LONG;
            },
        };

        it('enable short mask if number of digits is <=10', () => {
            const maskModel = new MaskModel(EMPTY_STATE, maskitoOptions);

            maskModel.addCharacters('01234abc56789');

            expect(maskModel.value).toBe('0123456789');
            expect(maskModel.selection).toEqual([
                '0123456789'.length,
                '0123456789'.length,
            ]);
        });

        it('enable medium mask if number of digits is 10 < x <= 16', () => {
            const maskModel = new MaskModel(EMPTY_STATE, maskitoOptions);

            maskModel.addCharacters('01234abc56789123456');

            expect(maskModel.value).toBe('0123 4567 8912 3456');
            expect(maskModel.selection).toEqual([
                '0123 4567 8912 3456'.length,
                '0123 4567 8912 3456'.length,
            ]);
        });

        it('enable long mask if number of digits is >16 (by paste)', () => {
            const maskModel = new MaskModel(EMPTY_STATE, maskitoOptions);

            maskModel.addCharacters('01234abc567891234567');

            expect(maskModel.value).toBe('01234567891234567');
            expect(maskModel.selection).toEqual([
                '01234567891234567'.length,
                '01234567891234567'.length,
            ]);
        });

        it('enable long mask if number of digits is >16 (by adding new character to the previous mask)', () => {
            const initialValue = '0123 4567 8912 3456';
            const maskModel = new MaskModel(
                {
                    value: initialValue,
                    selection: [initialValue.length, initialValue.length],
                },
                maskitoOptions,
            );

            maskModel.addCharacters('7');

            expect(maskModel.value).toBe('01234567891234567');
            expect(maskModel.selection).toEqual([
                '01234567891234567'.length,
                '01234567891234567'.length,
            ]);
        });
    });
});


================================================
FILE: projects/core/src/lib/classes/mask-model/tests/mask-model-fixed-characters.spec.ts
================================================
import {describe, expect, it} from '@jest/globals';

import {MASKITO_DEFAULT_OPTIONS} from '../../../constants';
import type {MaskitoMask, MaskitoOptions} from '../../../types';
import {MaskModel} from '../mask-model';

describe('MaskModel | Fixed characters', () => {
    describe('New typed character is equal to the previous (already existing) fixed character', () => {
        const phoneMaskitoOptions: Required<MaskitoOptions> = {
            ...MASKITO_DEFAULT_OPTIONS,
            mask: [
                '+',
                '7',
                ' ',
                '(',
                /\d/,
                /\d/,
                /\d/,
                ')',
                ' ',
                /\d/,
                '0',
                /\d/,
                '-',
                /\d/,
                /\d/,
                '-',
                /\d/,
                /\d/,
            ],
        };

        const check = ({
            initialValue,
            addedCharacters,
            expectedNewValue,
        }: {
            initialValue: string;
            addedCharacters: string;
            expectedNewValue: string;
        }): void => {
            const selection: [number, number] = [
                initialValue.length,
                initialValue.length,
            ];
            const maskModel = new MaskModel(
                {
                    selection,
                    value: initialValue,
                },
                phoneMaskitoOptions,
            );

            try {
                maskModel.addCharacters(addedCharacters);
            } finally {
                expect(maskModel.value).toBe(expectedNewValue);
                expect(maskModel.selection).toEqual([
                    expectedNewValue.length,
                    expectedNewValue.length,
                ]);
            }
        };

        it('+7| => Type 7 => +7 (7', () => {
            check({
                initialValue: '+7',
                addedCharacters: '7',
                expectedNewValue: '+7 (7',
            });
        });

        it('+7| => Type 9 => +7 (9', () => {
            check({
                initialValue: '+7',
                addedCharacters: '9',
                expectedNewValue: '+7 (9',
            });
        });

        it('+7 | (space after seven) => Type 7 => +7 (7', () => {
            check({
                initialValue: '+7 ',
                addedCharacters: '7',
                expectedNewValue: '+7 (7',
            });
        });

        it('+7 (7| => Type 7 => +7 (77', () => {
            check({
                initialValue: '+7 (7',
                addedCharacters: '7',
                expectedNewValue: '+7 (77',
            });
        });

        it('+7 (900) 2| (next character is fixed character "0") => Type 1 => +7 (900) 201|', () => {
            check({
                initialValue: '+7 (900) 2',
                addedCharacters: '1',
                expectedNewValue: '+7 (900) 201',
            });
        });

        it('+7 (900) 20| => Type 0 => +7 (900) 200|', () => {
            check({
                initialValue: '+7 (900) 20',
                addedCharacters: '0',
                expectedNewValue: '+7 (900) 200',
            });
        });
    });

    describe('Attempt to insert invalid characters for `overwriteMode: replace`', () => {
        const testCases: Record<string, MaskitoMask> = {
            '["$", /d/, /d/]': ['$', /\d/, /\d/],
            'dynamic mask': ({value}) => {
                const digitsCount = value.replaceAll(/\D/g, '').length;

                return [
                    '$',
                    ...Array.from<RegExp>({length: digitsCount || 1}).fill(/\d/),
                ];
            },
        };

        Object.entries(testCases).forEach(([title, mask]) => {
            describe(`mask expression contains leading characters – ${title}`, () => {
                const options: Required<MaskitoOptions> = {
                    ...MASKITO_DEFAULT_OPTIONS,
                    mask,
                    overwriteMode: 'replace',
                };

                it('$1|2 => Type A => $1|2', () => {
                    const value = '$12';
                    const selection = [2, 2] as const;
                    const maskModel = new MaskModel({value, selection}, options);

                    expect(() => maskModel.addCharacters('q')).toThrow();
                    expect(maskModel.value).toBe(value);
                    expect(maskModel.selection).toEqual(selection);
                });

                it('$|12 => Type $ => $|12', () => {
                    const value = '$12';
                    const selection = [1, 1] as const;
                    const maskModel = new MaskModel({value, selection}, options);

                    expect(() => maskModel.addCharacters('$')).toThrow();
                    expect(maskModel.value).toBe(value);
                    expect(maskModel.selection).toEqual(selection);
                });

                it('$|12 => Type X => $|12', () => {
                    const value = '$12';
                    const selection = [1, 1] as const;
                    const maskModel = new MaskModel({value, selection}, options);

                    expect(() => maskModel.addCharacters('X')).toThrow();
                    expect(maskModel.value).toBe(value);
                    expect(maskModel.selection).toEqual(selection);
                });
            });
        });
    });

    describe('Dynamic mask expression + trailing fixed character', () => {
        const postfix = 'left';
        const timeMask: ReadonlyArray<RegExp | string> = [/\d/, /\d/, ':', /\d/, /\d/];
        const timeWithPostfixMask: Required<MaskitoOptions> = {
            ...MASKITO_DEFAULT_OPTIONS,
            mask: ({value}) => {
                let digitsCount = Math.min(value.replaceAll(/\D/g, '').length, 4);
                const afterLastDigit =
                    timeMask.findIndex((x) => typeof x !== 'string' && !--digitsCount) +
                    1;

                return afterLastDigit
                    ? timeMask.slice(0, afterLastDigit).concat(...postfix)
                    : [];
            },
            overwriteMode: 'replace',
        };

        it('adds trailing postfix on enter of digit inside empty textfield', () => {
            const maskModel = new MaskModel(
                {
                    selection: [0, 0],
                    value: '',
                },
                timeWithPostfixMask,
            );

            maskModel.addCharacters('1');

            expect(maskModel.value).toBe('1left');
            expect(maskModel.selection).toEqual([1, 1]);
        });

        it('adds trailing postfix on paste of many digits inside empty textfield', () => {
            const maskModel = new MaskModel(
                {
                    selection: [0, 0],
                    value: '',
                },
                timeWithPostfixMask,
            );

            maskModel.addCharacters('123');

            expect(maskModel.value).toBe('12:3left');
            expect(maskModel.selection).toEqual(['12:3'.length, '12:3'.length]);
        });

        it('edits digit in the middle', () => {
            const maskModel = new MaskModel(
                {
                    selection: [1, 1],
                    value: '12:3left',
                },
                timeWithPostfixMask,
            );

            maskModel.addCharacters('4');

            expect(maskModel.value).toBe('14:3left');
            expect(maskModel.selection).toEqual([3, 3]);
        });

        it('erases the last digit without losing trailing fixed characters', () => {
            const maskModel = new MaskModel(
                {
                    selection: [3, 4],
                    value: '12:3left',
                },
                timeWithPostfixMask,
            );

            maskModel.deleteCharacters();

            expect(maskModel.value).toBe('12left');
            expect(maskModel.selection).toEqual([2, 2]);
        });

        it('erases the digit in the middle without losing trailing fixed character', () => {
            const maskModel = new MaskModel(
                {
                    selection: [3, 4],
                    value: '12:34 left',
                },
                timeWithPostfixMask,
            );

            maskModel.deleteCharacters();

            expect(maskModel.value).toBe('12:4left');
            expect(maskModel.selection).toEqual([3, 3]);
        });
    });

    it('attempt to enter invalid character at the position of fixed character', () => {
        const dateMask: Required<MaskitoOptions> = {
            ...MASKITO_DEFAULT_OPTIONS,
            mask: [/\d/, /\d/, '.', /\d/, /\d/],
        };

        const selection = [2, 2] as const;
        const maskModel = new MaskModel(
            {
                selection,
                value: '12',
            },
            dateMask,
        );

        expect(() => maskModel.addCharacters('#')).toThrow();
        expect(maskModel.value).toBe('12');
        expect(maskModel.selection).toEqual(selection);
    });

    it('accepts valid character at the position of fixed character', () => {
        const dateMask: Required<MaskitoOptions> = {
            ...MASKITO_DEFAULT_OPTIONS,
            mask: [/\d/, /\d/, ':', /\d/, /\d/],
        };

        const selection = [2, 2] as const;
        const maskModel = new MaskModel(
            {
                selection,
                value: '12',
            },
            dateMask,
        );

        maskModel.addCharacters(':');

        expect(maskModel.value).toBe('12:');
        expect(maskModel.selection).toEqual(['12:'.length, '12:'.length]);
    });
});


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/apply-overwrite-mode.ts
================================================
import type {ElementState, MaskitoOptions} from '../../../types';

export function applyOverwriteMode(
    {value, selection}: ElementState,
    newCharacters: string,
    mode: MaskitoOptions['overwriteMode'],
): ElementState {
    const [from, to] = selection;
    const computedMode = typeof mode === 'function' ? mode({value, selection}) : mode;

    return {
        value,
        selection:
            computedMode === 'replace'
                ? [from, Math.max(from + newCharacters.length, to)]
                : [from, to],
    };
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts
================================================
import type {ElementState, MaskitoMaskExpression} from '../../../types';
import {guessValidValueByPattern} from './guess-valid-value-by-pattern';
import {guessValidValueByRegExp} from './guess-valid-value-by-reg-exp';
import {validateValueWithMask} from './validate-value-with-mask';

export function calibrateValueByMask(
    elementState: ElementState,
    mask: MaskitoMaskExpression,
    initialElementState: ElementState | null = null,
): ElementState {
    if (validateValueWithMask(elementState.value, mask)) {
        return elementState;
    }

    const {value, selection} = Array.isArray(mask)
        ? guessValidValueByPattern(elementState, mask, initialElementState)
        : guessValidValueByRegExp(elementState, mask);

    return {
        selection,
        value: Array.isArray(mask) ? value.slice(0, mask.length) : value,
    };
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts
================================================
import type {ElementState} from '../../../types';
import {isFixedCharacter} from './is-fixed-character';

export function getLeadingFixedCharacters(
    mask: Array<RegExp | string>,
    validatedValuePart: string,
    newCharacter: string,
    initialElementState: ElementState | null,
): string {
    let leadingFixedCharacters = '';

    for (let i = validatedValuePart.length; i < mask.length; i++) {
        const charConstraint = mask[i] || '';
        const isInitiallyExisted = initialElementState?.value[i] === charConstraint;

        if (
            !isFixedCharacter(charConstraint) ||
            (charConstraint === newCharacter && !isInitiallyExisted)
        ) {
            return leadingFixedCharacters;
        }

        leadingFixedCharacters += charConstraint;
    }

    return leadingFixedCharacters;
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts
================================================
import type {ElementState} from '../../../types';
import {getLeadingFixedCharacters} from './get-leading-fixed-characters';
import {isFixedCharacter} from './is-fixed-character';
import {validateValueWithMask} from './validate-value-with-mask';

export function guessValidValueByPattern(
    elementState: ElementState,
    mask: Array<RegExp | string>,
    initialElementState: ElementState | null,
): ElementState {
    let maskedFrom: number | null = null;
    let maskedTo: number | null = null;

    const maskedValue = Array.from(elementState.value).reduce(
        (validatedCharacters, char, charIndex) => {
            const leadingCharacters = getLeadingFixedCharacters(
                mask,
                validatedCharacters,
                char,
                initialElementState,
            );
            const newValidatedChars = `${validatedCharacters}${leadingCharacters}`;
            const charConstraint = mask[newValidatedChars.length] || '';

            if (maskedFrom === null && charIndex >= elementState.selection[0]) {
                maskedFrom = newValidatedChars.length;
            }

            if (maskedTo === null && charIndex >= elementState.selection[1]) {
                maskedTo = newValidatedChars.length;
            }

            if (isFixedCharacter(charConstraint)) {
                return `${newValidatedChars}${charConstraint}`;
            }

            if (char.match(charConstraint)) {
                return `${newValidatedChars}${char}`;
            }

            return leadingCharacters.startsWith(char)
                ? newValidatedChars
                : validatedCharacters;
        },
        '',
    );

    const trailingFixedCharacters = getLeadingFixedCharacters(
        mask,
        maskedValue,
        '',
        initialElementState,
    );

    return {
        value: validateValueWithMask(`${maskedValue}${trailingFixedCharacters}`, mask)
            ? `${maskedValue}${trailingFixedCharacters}`
            : maskedValue,
        // issues: https://github.com/typescript-eslint/typescript-eslint/issues/12069
        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
        selection: [maskedFrom ?? maskedValue.length, maskedTo ?? maskedValue.length],
    };
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-reg-exp.ts
================================================
import type {ElementState} from '../../../types';

export function guessValidValueByRegExp(
    {value, selection}: ElementState,
    maskRegExp: RegExp,
): ElementState {
    const [from, to] = selection;
    let newFrom = from;
    let newTo = to;

    const validatedValue = Array.from(value).reduce((validatedValuePart, char, i) => {
        const newPossibleValue = `${validatedValuePart}${char}`;

        if (from === i) {
            newFrom = validatedValuePart.length;
        }

        if (to === i) {
            newTo = validatedValuePart.length;
        }

        return newPossibleValue.match(maskRegExp) ? newPossibleValue : validatedValuePart;
    }, '');

    return {
        value: validatedValue,
        selection: [
            Math.min(newFrom, validatedValue.length),
            Math.min(newTo, validatedValue.length),
        ],
    };
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/is-fixed-character.ts
================================================
export function isFixedCharacter(char: RegExp | string): char is string {
    return typeof char === 'string';
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts
================================================
import type {ElementState, MaskitoMaskExpression} from '../../../types';
import {isFixedCharacter} from './is-fixed-character';

export function removeFixedMaskCharacters(
    initialElementState: ElementState,
    mask: MaskitoMaskExpression,
): ElementState {
    if (!Array.isArray(mask)) {
        return initialElementState;
    }

    const [from, to] = initialElementState.selection;
    const selection: number[] = [];

    const unmaskedValue = Array.from(initialElementState.value).reduce(
        (rawValue, char, i) => {
            const charConstraint = mask[i] || '';

            if (i === from) {
                selection.push(rawValue.length);
            }

            if (i === to) {
                selection.push(rawValue.length);
            }

            return isFixedCharacter(charConstraint) && charConstraint === char
                ? rawValue
                : `${rawValue}${char}`;
        },
        '',
    );

    if (selection.length < 2) {
        selection.push(
            ...Array.from<number>({length: 2 - selection.length}).fill(
                unmaskedValue.length,
            ),
        );
    }

    return {
        value: unmaskedValue,
        selection: [selection[0]!, selection[1]!],
    };
}


================================================
FILE: projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts
================================================
import type {MaskitoMaskExpression} from '../../../types';
import {isFixedCharacter} from './is-fixed-character';

export function validateValueWithMask(
    value: string,
    maskExpression: MaskitoMaskExpression,
): boolean {
    if (Array.isArray(maskExpression)) {
        return (
            value.length === maskExpression.length &&
            Array.from(value).every((char, i) => {
                const charConstraint = maskExpression[i] || '';

                return isFixedCharacter(charConstraint)
                    ? char === charConstraint
                    : char.match(charConstraint);
            })
        );
    }

    return maskExpression.test(value);
}


================================================
FILE: projects/core/src/lib/constants/default-element-predicate.ts
================================================
import type {MaskitoElementPredicate} from '../types';
import {maskitoAdaptContentEditable} from '../utils/content-editable';

export const MASKITO_DEFAULT_ELEMENT_PREDICATE: MaskitoElementPredicate = (e) =>
    e.isContentEditable
        ? maskitoAdaptContentEditable(e)
        : e.querySelector<HTMLInputElement | HTMLTextAreaElement>('input,textarea') ||
          (e as HTMLInputElement | HTMLTextAreaElement);


================================================
FILE: projects/core/src/lib/constants/default-options.ts
================================================
import type {MaskitoOptions} from '../types';

export const MASKITO_DEFAULT_OPTIONS: Required<MaskitoOptions> = {
    mask: /^.*$/,
    preprocessors: [],
    postprocessors: [],
    plugins: [],
    overwriteMode: 'shift',
};


================================================
FILE: projects/core/src/lib/constants/index.ts
================================================
export * from './default-element-predicate';
export * from './default-options';


================================================
FILE: projects/core/src/lib/mask.ts
================================================
import {MaskHistory, MaskModel} from './classes';
import {MASKITO_DEFAULT_OPTIONS} from './constants';
import {createBrokenDefaultPlugin, createDoubleSpacePlugin} from './plugins';
import type {
    ElementState,
    MaskitoElement,
    MaskitoOptions,
    SelectionRange,
    TypedInputEvent,
} from './types';
import {
    areElementStatesEqual,
    areElementValuesEqual,
    EventListener,
    getLineSelection,
    getNotEmptySelection,
    getWordSelection,
    isRedo,
    isUndo,
    maskitoPipe,
    maskitoTransform,
} from './utils';

const BUILT_IN_PLUGINS = [createDoubleSpacePlugin(), createBrokenDefaultPlugin()];

export class Maskito extends MaskHistory {
    private readonly isTextArea = this.element.nodeName === 'TEXTAREA';
    private readonly eventListener = new EventListener(this.element);
    private readonly options: Required<MaskitoOptions> = {
        ...MASKITO_DEFAULT_OPTIONS,
        ...this.maskitoOptions,
    };

    private upcomingElementState: ElementState | null = null;

    private readonly preprocessor = maskitoPipe(this.options.preprocessors);

    private readonly postprocessor = maskitoPipe(this.options.postprocessors);

    private readonly teardowns = this.options.plugins
        .concat(BUILT_IN_PLUGINS)
        .map((plugin) => plugin(this.element, this.options));

    constructor(
        private readonly element: MaskitoElement,
        private readonly maskitoOptions: MaskitoOptions,
    ) {
        super();
        this.updateHistory(this.elementState);

        this.eventListener.listen('keydown', (event) => {
            if (isRedo(event)) {
                event.preventDefault();

                return this.redo();
            }

            if (isUndo(event)) {
                event.preventDefault();

                return this.undo();
            }
        });

        this.eventListener.listen('beforeinput', (event) => {
            const isForward = event.inputType.includes('Forward');

            this.updateHistory(this.elementState);

            switch (event.inputType) {
                case 'deleteByCut':
                case 'deleteContentBackward':
                case 'deleteContentForward':
                    return this.handleDelete({
                        event,
                        isForward,
                        selection: getNotEmptySelection(this.elementState, isForward),
                    });
                case 'deleteHardLineBackward':
                case 'deleteHardLineForward':
                case 'deleteSoftLineBackward':
                case 'deleteSoftLineForward':
                    return this.handleDelete({
                        event,
                        isForward,
                        selection: getLineSelection(this.elementState, isForward),
                        force: true,
                    });
                case 'deleteWordBackward':
                case 'deleteWordForward':
                    return this.handleDelete({
                        event,
                        isForward,
                        selection: getWordSelection(this.elementState, isForward),
                    });
                case 'historyRedo':
                    event.preventDefault();

                    return this.redo();
                // historyUndo/historyRedo will not be triggered if value was modified programmatically
                case 'historyUndo':
                    event.preventDefault();

                    return this.undo();
                case 'insertCompositionText':
                    return; // will be handled inside `compositionend` event
                case 'insertLineBreak':
                case 'insertParagraph':
                    return this.handleEnter(event);
                case 'insertReplacementText':
                    /**
                     * According {@link https://www.w3.org/TR/input-events-2 W3C specification}:
                     * > `insertReplacementText` – insert or replace existing text by means of a spell checker,
                     * > auto-correct, writing suggestions or similar.
                     * ___
                     * Firefox emits `insertReplacementText` event for its suggestion/autofill and for spell checker.
                     * However, it is impossible to detect which part of the textfield value is going to be replaced
                     * (`selectionStart` and `selectionEnd` just equal to the last caret position).
                     * ___
                     * Chrome does not fire `beforeinput` event for its suggestion/autofill.
                     * It emits only `input` event with `inputType` and `data` set to `undefined`.
                     * ___
                     * All these browser limitations make us to validate the result value later in `input` event.
                     */
                    return;
                case 'insertFromDrop':
                case 'insertFromPaste':
                case 'insertText':
                default:
                    return this.handleInsert(
                        event,
                        event.data ??
                            // `event.data` for `contentEditable` is always `null` for paste/drop events
                            event.dataTransfer?.getData('text/plain') ??
                            '',
                    );
            }
        });

        this.eventListener.listen(
            'input',
            () => {
                if (
                    this.upcomingElementState &&
                    !areElementStatesEqual(this.upcomingElementState, this.elementState)
                ) {
                    this.updateElementState(this.upcomingElementState);
                }

                this.upcomingElementState = null;
            },
            {capture: true},
        );

        this.eventListener.listen('input', ({inputType}) => {
            if (inputType === 'insertCompositionText') {
                return; // will be handled inside `compositionend` event
            }

            this.ensureValueFitsMask();
            this.updateHistory(this.elementState);
        });

        this.eventListener.listen('compositionend', () => {
            this.ensureValueFitsMask();
            this.updateHistory(this.elementState);
        });
    }

    public destroy(): void {
        this.eventListener.destroy();
        this.teardowns.forEach((teardown) => teardown?.());
    }

    protected updateElementState(
        {value, selection}: ElementState,
        eventInit?: Pick<TypedInputEvent, 'data' | 'inputType'>,
    ): void {
        const initialValue = this.elementState.value;

        this.updateValue(value);
        this.updateSelectionRange(selection);

        if (eventInit && initialValue !== value) {
            this.dispatchInputEvent(eventInit);
        }
    }

    private get elementState(): ElementState {
        const {value, selectionStart, selectionEnd} = this.element;

        return {
            value,
            selection: [selectionStart ?? 0, selectionEnd ?? 0],
        };
    }

    private get maxLength(): number {
        const {maxLength} = this.element;

        return maxLength === -1 ? Infinity : maxLength;
    }

    private updateSelectionRange([from, to]: SelectionRange): void {
        const {element} = this;

        if (
            element.matches(':focus') &&
            (element.selectionStart !== from || element.selectionEnd !== to)
        ) {
            element.setSelectionRange(from, to);
        }
    }

    private updateValue(value: string): void {
        /**
         * Don't "disturb" unnecessarily `value`-setter
         * (i.e. it breaks React controlled input behavior)
         */
        if (this.element.value !== value || this.element.isContentEditable) {
            this.element.value = value;
        }
    }

    private ensureValueFitsMask(): void {
        this.updateElementState(maskitoTransform(this.elementState, this.options), {
            inputType: 'insertText',
            data: null,
        });
    }

    private dispatchInputEvent(
        eventInit: Pick<TypedInputEvent, 'data' | 'inputType'> = {
            inputType: 'insertText',
            data: null,
        },
    ): void {
        this.element.dispatchEvent(
            new InputEvent('input', {
                ...eventInit,
                bubbles: true,
                cancelable: false,
            }),
        );
    }

    private handleDelete({
        event,
        selection,
        isForward,
    }: {
        event: TypedInputEvent;
        selection: SelectionRange;
        isForward: boolean;
        force?: boolean;
    }): void {
        const initialState: ElementState = {
            value: this.elementState.value,
            selection,
        };
        const {elementState} = this.preprocessor(
            {
                elementState: initialState,
                data: '',
            },
            isForward ? 'deleteForward' : 'deleteBackward',
        );
        const maskModel = new MaskModel(elementState, this.options);

        maskModel.deleteCharacters();

        const newElementState = this.postprocessor(maskModel, initialState);

        if (
            areElementValuesEqual(initialState, elementState, maskModel, newElementState)
        ) {
            const [from, to] = elementState.selection;

            event.preventDefault();

            // User presses Backspace/Delete for the fixed value
            return this.updateSelectionRange(isForward ? [to, to] : [from, from]);
        }

        this.upcomingElementState = newElementState;
    }

    private handleInsert(event: TypedInputEvent, data: string): void {
        const {options, maxLength, elementState: initialElementState} = this;
        const [from, to] = initialElementState.selection;
        const {elementState, data: insertedText = data} = this.preprocessor(
            {
                data,
                elementState: initialElementState,
            },
            'insert',
        );
        const maskModel = new MaskModel(elementState, options);

        try {
            maskModel.addCharacters(insertedText);
        } catch {
            return event.preventDefault();
        }

        this.upcomingElementState = this.clampState(
            this.postprocessor(maskModel, initialElementState),
        );

        /**
         * When textfield value length is already equal to attribute `maxlength`,
         * pressing any key (even with valid value) does not emit `input` event
         * (except to the case when user replaces some characters by selection).
         */
        const noInputEventDispatch =
            initialElementState.value.length >= maxLength && from === to;

        if (noInputEventDispatch) {
            if (
                options.overwriteMode === 'replace' &&
                !areElementStatesEqual(this.upcomingElementState, initialElementState)
            ) {
                this.dispatchInputEvent({inputType: 'insertText', data});
            } else {
                /**
                 * This `beforeinput` event will not be followed by `input` event –
                 * clear computed state to avoid any possible side effect
                 * for new possible `input` event without preceding `beforeinput` event
                 * (e.g. browser autofill, `document.execCommand('delete')` etc.)
                 */
                this.upcomingElementState = null;
            }
        }
    }

    private handleEnter(event: TypedInputEvent): void {
        if (this.isTextArea || this.element.isContentEditable) {
            this.handleInsert(event, '\n');
        }
    }

    private clampState({value, selection}: ElementState): ElementState {
        const [from, to] = selection;
        const max = this.maxLength;

        return {
            value: value.slice(0, max),
            selection: [Math.min(from, max), Math.min(to, max)],
        };
    }
}


================================================
FILE: projects/core/src/lib/plugins/broken-prevent-default.plugin.ts
================================================
import type {MaskitoPlugin} from '@maskito/core';

import type {TypedInputEvent} from '../types';
import {EventListener} from '../utils';

/**
 * All `input` events with `inputType=deleteContentBackward` always follows `beforeinput` event with the same `inputType`.
 * If `beforeinput[inputType=deleteContentBackward]` is prevented, subsequent `input[inputType=deleteContentBackward]` is prevented too.
 * There is an exception – Android devices with Microsoft SwiftKey Keyboard in Mobile Chrome.
 * These devices ignores `preventDefault` for `beforeinput` event if Backspace is pressed.
 * @see https://github.com/taiga-family/maskito/issues/2135#issuecomment-2980729647
 * ___
 * TODO: track Chromium bug report and delete this plugin after bug fix
 * https://issues.chromium.org/issues/40885402
 */
export function createBrokenDefaultPlugin(): MaskitoPlugin {
    return (element) => {
        const eventListener = new EventListener(element);

        let isVirtualAndroidKeyboard = false;
        let beforeinputEvent: TypedInputEvent;
        let value = element.value;

        eventListener.listen('keydown', ({key}) => {
            isVirtualAndroidKeyboard = key === 'Unidentified';
        });

        eventListener.listen('beforeinput', (event) => {
            beforeinputEvent = event;
            value = element.value;
        });

        eventListener.listen(
            'input',
            (event) => {
                if (
                    isVirtualAndroidKeyboard &&
                    beforeinputEvent.defaultPrevented &&
                    beforeinputEvent.inputType === 'deleteContentBackward' &&
                    event.inputType === 'deleteContentBackward'
                ) {
                    element.value = value;
                }
            },
            {capture: true},
        );

        return () => eventListener.destroy();
    };
}


================================================
FILE: projects/core/src/lib/plugins/change-event-plugin.ts
================================================
import type {MaskitoPlugin} from '../types';

export function maskitoChangeEventPlugin(): MaskitoPlugin {
    return (element) => {
        if (element.isContentEditable) {
            return;
        }

        let value = element.value;

        const valueListener = (): void => {
            value = element.value;
        };
        const blurListener = (): void => {
            if (element.value !== value) {
                element.dispatchEvent(new Event('change', {bubbles: true}));
            }
        };

        element.addEventListener('focus', valueListener);
        element.addEventListener('change', valueListener);
        element.addEventListener('blur', blurListener);

        return () => {
            element.removeEventListener('focus', valueListener);
            element.removeEventListener('change', valueListener);
            element.removeEventListener('blur', blurListener);
        };
    };
}


================================================
FILE: projects/core/src/lib/plugins/double-space.plugin.ts
================================================
import type {MaskitoPlugin} from '@maskito/core';

import type {TypedInputEvent} from '../types';
import {EventListener} from '../utils';

const SPACE = ' ';

/**
 * 1. Android user (with G-board keyboard or similar) presses 1st space
 * ```
 * {type: "beforeinput", data: " ", inputType: "insertText"}
 * ```
 * 2. User presses 2nd space
 * ```
 * // Android tries to delete previously inserted space
 * {type: "beforeinput", inputType: "deleteContentBackward"}
 * {type: "beforeinput", data: ". ", inputType: "insertText"}
 * ```
 * ---------
 * 1. MacOS user presses 1st space
 * ```
 * {type: "beforeinput", data: " ", inputType: "insertText"}
 * ```
 * 2. User presses 2nd space
 * ```
 * // MacOS automatically run `element.setSelectionRange(indexBeforeSpace, indexAfterSpace)` and then
 * {type: "beforeinput", data: ". ", inputType: "insertText"}
 * ```
 * ---------
 * @see https://github.com/taiga-family/maskito/issues/2023
 */
export function createDoubleSpacePlugin(): MaskitoPlugin {
    let prevValue = '';
    let prevCaretIndex = 0;
    let prevEvent: TypedInputEvent | null = null;
    let prevRejectedSpace = false;

    return (element) => {
        const eventListener = new EventListener(element);

        eventListener.listen('beforeinput', (event) => {
            const {value, selectionStart, selectionEnd} = element;
            const rejectedSpace =
                prevEvent?.inputType === 'insertText' &&
                prevEvent.data === SPACE &&
                !value.slice(0, Number(selectionEnd)).endsWith(SPACE);

            if (event.inputType === 'insertText' && event.data === `.${SPACE}`) {
                if (
                    prevEvent?.inputType === 'deleteContentBackward' &&
                    prevRejectedSpace
                ) {
                    // Android
                    element.value = prevValue;
                    element.setSelectionRange(prevCaretIndex, prevCaretIndex);
                } else if (rejectedSpace) {
                    // Mac OS
                    element.setSelectionRange(selectionStart, selectionStart);
                }
            }

            prevRejectedSpace = rejectedSpace;
            prevEvent = event;
            prevValue = value;
            prevCaretIndex = Number(
                (rejectedSpace ? prevCaretIndex : selectionEnd) === value.length
                    ? selectionEnd
                    : selectionStart,
            );
        });

        return () => eventListener.destroy();
    };
}


================================================
FILE: projects/core/src/lib/plugins/index.ts
================================================
export * from './broken-prevent-default.plugin';
export * from './change-event-plugin';
export * from './double-space.plugin';
export * from './initial-calibration-plugin';
export * from './strict-composition-plugin';


================================================
FILE: projects/core/src/lib/plugins/initial-calibration-plugin.ts
================================================
import type {MaskitoOptions, MaskitoPlugin} from '../types';
import {maskitoTransform, maskitoUpdateElement} from '../utils';

export function maskitoInitialCalibrationPlugin(
    customOptions?: MaskitoOptions,
): MaskitoPlugin {
    return (element, options) => {
        const from = element.selectionStart ?? 0;
        const to = element.selectionEnd ?? 0;

        maskitoUpdateElement(element, {
            value: maskitoTransform(element.value, customOptions || options),
            selection: [from, to],
        });
    };
}


================================================
FILE: projects/core/src/lib/plugins/strict-composition-plugin.ts
================================================
import type {ElementState, MaskitoPlugin, TypedInputEvent} from '../types';
import {areElementStatesEqual, maskitoTransform, maskitoUpdateElement} from '../utils';

export function maskitoStrictCompositionPlugin(): MaskitoPlugin {
    return (element, maskitoOptions) => {
        const listener = (event: TypedInputEvent): void => {
            if (event.inputType !== 'insertCompositionText') {
                return;
            }

            const selection = [
                element.selectionStart ?? 0,
                element.selectionEnd ?? 0,
            ] as const;
            const elementState: ElementState = {
                selection,
                value: element.value,
            };
            const validatedState = maskitoTransform(elementState, maskitoOptions);

            if (!areElementStatesEqual(elementState, validatedState)) {
                event.preventDefault();
                maskitoUpdateElement(element, validatedState);
            }
        };

        element.addEventListener('input', listener as EventListener);

        return () => element.removeEventListener('input', listener as EventListener);
    };
}


================================================
FILE: projects/core/src/lib/types/element-predicate.ts
================================================
import type {MaskitoElement} from './maskito-element';

export type MaskitoElementPredicate = (
    element: HTMLElement,
) => MaskitoElement | Promise<MaskitoElement>;


================================================
FILE: projects/core/src/lib/types/element-state.ts
================================================
import type {SelectionRange} from './selection-range';

export interface ElementState {
    readonly value: string;
    readonly selection: SelectionRange;
}


================================================
FILE: projects/core/src/lib/types/index.ts
================================================
export * from './element-predicate';
export * from './element-state';
export * from './mask';
export * from './mask-options';
export * from './mask-processors';
export * from './maskito-element';
export * from './plugin';
export * from './selection-range';
export * from './typed-input-event';


================================================
FILE: projects/core/src/lib/types/mask-options.ts
================================================
import type {ElementState} from './element-state';
import type {MaskitoMask} from './mask';
import type {MaskitoPostprocessor, MaskitoPreprocessor} from './mask-processors';
import type {MaskitoPlugin} from './plugin';

export interface MaskitoOptions {
    readonly mask: MaskitoMask;
    readonly preprocessors?: readonly MaskitoPreprocessor[];
    readonly postprocessors?: readonly MaskitoPostprocessor[];
    readonly plugins?: readonly MaskitoPlugin[];
    readonly overwriteMode?:
        | 'replace'
        | 'shift'
        | ((elementState: ElementState) => 'replace' | 'shift');
}


================================================
FILE: projects/core/src/lib/types/mask-processors.ts
================================================
import type {ElementState} from './element-state';

export type MaskitoPreprocessor = (
    _: {
        elementState: ElementState;
        data: string;
    },
    actionType: 'deleteBackward' | 'deleteForward' | 'insert' | 'validation',
) => {
    elementState: ElementState;
    data?: string;
};

export type MaskitoPostprocessor = (
    elementState: ElementState,
    initialElementState: ElementState,
) => ElementState;


================================================
FILE: projects/core/src/lib/types/mask.ts
================================================
import type {ElementState} from './element-state';

export type MaskitoMaskExpression = Array<RegExp | string> | RegExp;

export type MaskitoMask =
    | MaskitoMaskExpression
    | ((elementState: ElementState) => MaskitoMaskExpression);


================================================
FILE: projects/core/src/lib/types/maskito-element.ts
================================================
export type TextfieldLike = Pick<
    HTMLInputElement,
    | 'maxLength'
    | 'select'
    | 'selectionEnd'
    | 'selectionStart'
    | 'setSelectionRange'
    | 'value'
>;
export type MaskitoElement = HTMLElement & TextfieldLike;


================================================
FILE: projects/core/src/lib/types/plugin.ts
================================================
import type {MaskitoOptions} from './mask-options';
import type {MaskitoElement} from './maskito-element';

export type MaskitoPlugin = (
    element: MaskitoElement,
    options: Required<MaskitoOptions>,
) => (() => void) | void;


================================================
FILE: projects/core/src/lib/types/selection-range.ts
================================================
export type SelectionRange = readonly [from: number, to: number];


================================================
FILE: projects/core/src/lib/types/typed-input-event.ts
================================================
export interface TypedInputEvent extends InputEvent {
    inputType:
        | 'deleteByCut' // Ctrl (Command) + X
        | 'deleteContentBackward' // Backspace
        | 'deleteContentForward' // Delete (Fn + Backspace)
        | 'deleteHardLineBackward' // Ctrl (Command) + Backspace
        | 'deleteHardLineForward'
        | 'deleteSoftLineBackward' // Ctrl (Command) + Backspace
        | 'deleteSoftLineForward'
        | 'deleteWordBackward' // Alt (Option) + Backspace
        | 'deleteWordForward' // Alt (Option) + Delete (Fn + Backspace)
        | 'historyRedo' // Ctrl (Command) + Shift + Z
        | 'historyUndo' // Ctrl (Command) + Z
        | 'insertCompositionText'
        | 'insertFromDrop'
        | 'insertFromPaste' // Ctrl (Command) + V
        | 'insertLineBreak'
        | 'insertParagraph'
        | 'insertReplacementText'
        | 'insertText';
}


================================================
FILE: projects/core/src/lib/utils/content-editable.ts
================================================
import type {MaskitoElement, TextfieldLike} from '../types';
import {getContentEditableSelection} from './dom/get-content-editable-selection';
import {setContentEditableSelection} from './dom/set-content-editable-selection';

class ContentEditableAdapter implements TextfieldLike {
    public maxLength = Infinity;

    constructor(private readonly element: HTMLElement) {}

    public get value(): string {
        return this.element.innerText.replace(/\n\n$/, '\n');
    }

    public set value(value) {
        // Setting into innerHTML of element with `white-space: pre;` style
        this.element.innerHTML = value.replace(/\n$/, '\n\n');
    }

    public get selectionStart(): number | null {
        return getContentEditableSelection(this.element)[0];
    }

    public get selectionEnd(): number | null {
        return getContentEditableSelection(this.element)[1];
    }

    public setSelectionRange(from: number | null, to: number | null): void {
        setContentEditableSelection(this.element, [from ?? 0, to ?? 0]);
    }

    public select(): void {
        this.setSelectionRange(0, this.value.length);
    }
}

export function maskitoAdaptContentEditable(element: HTMLElement): MaskitoElement {
    const adapter = new ContentEditableAdapter(element);

    return new Proxy(element, {
        get(target, prop: keyof HTMLElement) {
            if (prop in adapter) {
                return adapter[prop as keyof ContentEditableAdapter];
            }

            const nativeProperty = target[prop];

            return typeof nativeProperty === 'function'
                ? nativeProperty.bind(target)
                : nativeProperty;
        },
        set(target, prop: keyof HTMLElement, val, receiver) {
            return Reflect.set(prop in adapter ? adapter : target, prop, val, receiver);
        },
    }) as MaskitoElement;
}


================================================
FILE: projects/core/src/lib/utils/dom/event-listener.ts
================================================
import type {TypedInputEvent} from '../../types';

export class EventListener {
    private readonly listeners: Array<() => void> = [];

    constructor(private readonly element: HTMLElement) {}

    public listen<E extends keyof HTMLElementEventMap>(
        eventType: E,
        fn: (
            event: E extends 'beforeinput' | 'input'
                ? TypedInputEvent
                : HTMLElementEventMap[E],
        ) => unknown,
        options?: AddEventListenerOptions,
    ): void {
        const untypedFn = fn as (event: HTMLElementEventMap[E]) => unknown;

        this.element.addEventListener(eventType, untypedFn, options);
        this.listeners.push(() =>
            this.element.removeEventListener(eventType, untypedFn, options),
        );
    }

    public destroy(): void {
        this.listeners.forEach((stopListen) => stopListen());
    }
}


================================================
FILE: projects/core/src/lib/utils/dom/get-content-editable-selection.ts
================================================
import type {SelectionRange} from '../../types';

export function getContentEditableSelection(element: HTMLElement): SelectionRange {
    const {anchorOffset = 0, focusOffset = 0} =
        element.ownerDocument.getSelection() || {};

    const from = Math.min(anchorOffset, focusOffset);
    const to = Math.max(anchorOffset, focusOffset);

    return [from, to];
}


================================================
FILE: projects/core/src/lib/utils/dom/history-events.ts
================================================
import {HotkeyCode, HotkeyModifier, isHotkey} from './hotkey';

export function isRedo(event: KeyboardEvent): boolean {
    return (
        isHotkey(event, HotkeyModifier.CTRL, HotkeyCode.Y) || // Windows
        isHotkey(event, HotkeyModifier.CTRL | HotkeyModifier.SHIFT, HotkeyCode.Z) || // Windows & Android
        isHotkey(event, HotkeyModifier.META | HotkeyModifier.SHIFT, HotkeyCode.Z) // macOS & iOS
    );
}

export function isUndo(event: KeyboardEvent): boolean {
    return (
        isHotkey(event, HotkeyModifier.CTRL, HotkeyCode.Z) || // Windows & Android
        isHotkey(event, HotkeyModifier.META, HotkeyCode.Z) // macOS & iOS
    );
}


================================================
FILE: projects/core/src/lib/utils/dom/hotkey.ts
================================================
export const HotkeyModifier = {
    CTRL: 1 << 0,
    ALT: 1 << 1,
    SHIFT: 1 << 2,
    META: 1 << 3,
} as const;

// TODO add variants that can be processed correctly
export const HotkeyCode = {
    Y: 89,
    Z: 90,
} as const;

/**
 * Checks if the passed keyboard event match the required hotkey.
 *
 * @example
 * input.addEventListener('keydown', (event) => {
 *     if (isHotkey(event, HotkeyModifier.CTRL | HotkeyModifier.SHIFT, HotkeyCode.Z)) {
 *         // redo hotkey pressed
 *     }
 * })
 *
 * @return will return `true` only if the {@link HotkeyCode} matches and only the necessary
 * {@link HotkeyModifier modifiers} have been pressed
 */
export function isHotkey(
    event: KeyboardEvent,
    modifiers: (typeof HotkeyModifier)[keyof typeof HotkeyModifier],
    hotkeyCode: (typeof HotkeyCode)[keyof typeof HotkeyCode],
): boolean {
    return (
        event.ctrlKey === !!(modifiers & HotkeyModifier.CTRL) &&
        event.altKey === !!(modifiers & HotkeyModifier.ALT) &&
        event.shiftKey === !!(modifiers & HotkeyModifier.SHIFT) &&
        event.metaKey === !!(modifiers & HotkeyModifier.META) &&
        /**
         * We intentionally use legacy {@link KeyboardEvent#keyCode `keyCode`} property. It is more
         * "keyboard-layout"-independent than {@link KeyboardEvent#key `key`} or {@link KeyboardEvent#code `code`} properties.
         * @see {@link https://github.com/taiga-family/maskito/issues/315 `KeyboardEvent#code` issue}
         */
        event.keyCode === hotkeyCode
    );
}


================================================
FILE: projects/core/src/lib/utils/dom/set-content-editable-selection.ts
================================================
import type {SelectionRange} from '../../types';

export function setContentEditableSelection(
    element: HTMLElement,
    [from, to]: SelectionRange,
): void {
    const document = element.ownerDocument;
    const range = document.createRange();

    range.setStart(
        element.firstChild || element,
        Math.min(from, element.textContent?.length ?? 0),
    );
    range.setEnd(
        element.lastChild || element,
        Math.min(to, element.textContent?.length ?? 0),
    );
    const selection = document.getSelection();

    if (selection) {
        selection.removeAllRanges();
        selection.addRange(range);
    }
}


================================================
FILE: projects/core/src/lib/utils/dom/update-element.ts
================================================
import type {ElementState, MaskitoElement} from '../../types';

/**
 * Sets value to element, and dispatches input event
 * if you passed ELementState, it also sets selection range
 *
 * @example
 * maskitoUpdateElement(input, newValue);
 * maskitoUpdateElement(input, elementState);
 *
 * @see {@link https://github.com/taiga-family/maskito/issues/804 issue}
 *
 * @return void
 */
export function maskitoUpdateElement(
    element: MaskitoElement,
    valueOrElementState: ElementState | string,
): void {
    const initialValue = element.value;

    if (typeof valueOrElementState === 'string') {
        element.value = valueOrElementState;
    } else {
        const [from, to] = valueOrElementState.selection;

        element.value = valueOrElementState.value;

        if (element.matches(':focus')) {
            element.setSelectionRange(from, to);
        }
    }

    if (element.value !== initialValue) {
        element.dispatchEvent(
            new Event(
                'input',
                /**
                 * React handles this event only on bubbling phase
                 *
                 * here is the list of events that are processed in the capture stage, others are processed in the bubbling stage
                 
Download .txt
gitextract_lbehwmqa/

├── .cspell.json
├── .editorconfig
├── .firebaserc
├── .github/
│   ├── CODEOWNERS
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug-report.yml
│   │   ├── 2-feature-request.yml
│   │   └── 3-documentation.yml
│   ├── renovate.json
│   └── workflows/
│       ├── assign-author.yml
│       ├── auto-merge.yml
│       ├── build.yml
│       ├── deploy-preview.yml
│       ├── deploy.yml
│       ├── e2e.yml
│       ├── lint.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .husky/
│   ├── commit-msg
│   └── pre-commit
├── .npmrc
├── .release-it.js
├── .ws-context
├── CHANGELOG.md
├── LICENSE
├── README.md
├── codecov.yml
├── eslint.config.ts
├── firebase.json
├── jest.config.ts
├── jest.preset.js
├── nx.json
├── package.json
├── projects/
│   ├── angular/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── ng-package.json
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   ├── maskito.directive.ts
│   │   │   │   ├── maskito.pipe.ts
│   │   │   │   ├── pattern.directive.ts
│   │   │   │   └── tests/
│   │   │   │       ├── maskito.directive.spec.ts
│   │   │   │       └── maskito.spec.ts
│   │   │   └── test-setup.ts
│   │   └── tsconfig.lib.prod.json
│   ├── core/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── classes/
│   │           │   ├── index.ts
│   │           │   ├── mask-history.ts
│   │           │   └── mask-model/
│   │           │       ├── mask-model.ts
│   │           │       ├── tests/
│   │           │       │   ├── dynamic-mask.spec.ts
│   │           │       │   └── mask-model-fixed-characters.spec.ts
│   │           │       └── utils/
│   │           │           ├── apply-overwrite-mode.ts
│   │           │           ├── calibrate-value-by-mask.ts
│   │           │           ├── get-leading-fixed-characters.ts
│   │           │           ├── guess-valid-value-by-pattern.ts
│   │           │           ├── guess-valid-value-by-reg-exp.ts
│   │           │           ├── is-fixed-character.ts
│   │           │           ├── remove-fixed-mask-characters.ts
│   │           │           └── validate-value-with-mask.ts
│   │           ├── constants/
│   │           │   ├── default-element-predicate.ts
│   │           │   ├── default-options.ts
│   │           │   └── index.ts
│   │           ├── mask.ts
│   │           ├── plugins/
│   │           │   ├── broken-prevent-default.plugin.ts
│   │           │   ├── change-event-plugin.ts
│   │           │   ├── double-space.plugin.ts
│   │           │   ├── index.ts
│   │           │   ├── initial-calibration-plugin.ts
│   │           │   └── strict-composition-plugin.ts
│   │           ├── types/
│   │           │   ├── element-predicate.ts
│   │           │   ├── element-state.ts
│   │           │   ├── index.ts
│   │           │   ├── mask-options.ts
│   │           │   ├── mask-processors.ts
│   │           │   ├── mask.ts
│   │           │   ├── maskito-element.ts
│   │           │   ├── plugin.ts
│   │           │   ├── selection-range.ts
│   │           │   └── typed-input-event.ts
│   │           └── utils/
│   │               ├── content-editable.ts
│   │               ├── dom/
│   │               │   ├── event-listener.ts
│   │               │   ├── get-content-editable-selection.ts
│   │               │   ├── history-events.ts
│   │               │   ├── hotkey.ts
│   │               │   ├── set-content-editable-selection.ts
│   │               │   └── update-element.ts
│   │               ├── element-states-equality.ts
│   │               ├── get-line-selection.ts
│   │               ├── get-not-empty-selection.ts
│   │               ├── get-word-selection.ts
│   │               ├── index.ts
│   │               ├── pipe.ts
│   │               ├── test/
│   │               │   ├── get-not-empty-selection.spec.ts
│   │               │   ├── get-word-selection.spec.ts
│   │               │   ├── pipe.spec.ts
│   │               │   └── transform.spec.ts
│   │               └── transform.ts
│   ├── demo/
│   │   ├── .gitignore
│   │   ├── esbuild-plugins/
│   │   │   ├── maskito-as-taiga-ui-dep.plugin.js
│   │   │   └── vue-esm.plugin.js
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── app/
│   │   │   │   ├── app.component.html
│   │   │   │   ├── app.component.spec.ts
│   │   │   │   ├── app.component.ts
│   │   │   │   ├── app.config.ts
│   │   │   │   ├── app.routes.ts
│   │   │   │   ├── app.style.less
│   │   │   │   ├── constants/
│   │   │   │   │   ├── demo-path.ts
│   │   │   │   │   ├── doc-example-primary-tab.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── modules/
│   │   │   │   │   ├── example-primary-tabs-icons/
│   │   │   │   │   │   ├── angular-logo.component.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── javascript-logo.component.ts
│   │   │   │   │   │   ├── react-logo.component.ts
│   │   │   │   │   │   └── vue-logo.component.ts
│   │   │   │   │   └── logo/
│   │   │   │   │       ├── logo.component.ts
│   │   │   │   │       ├── logo.style.less
│   │   │   │   │       └── logo.template.html
│   │   │   │   ├── server-error-handler.ts
│   │   │   │   └── utils/
│   │   │   │       ├── add-default-tabs-processor/
│   │   │   │       │   ├── add-default-tabs-processor.ts
│   │   │   │       │   └── default-tabs/
│   │   │   │       │       ├── angular-default-tab.ts
│   │   │   │       │       ├── js-default-tab.ts
│   │   │   │       │       ├── react-default-tab.ts
│   │   │   │       │       └── vue-default-tab.ts
│   │   │   │       └── index.ts
│   │   │   ├── assets/
│   │   │   │   └── manifest.webmanifest
│   │   │   ├── environments/
│   │   │   │   ├── environment.prod.ts
│   │   │   │   └── environment.ts
│   │   │   ├── index.html
│   │   │   ├── main.server.ts
│   │   │   ├── main.ts
│   │   │   ├── pages/
│   │   │   │   ├── documentation/
│   │   │   │   │   ├── browser-support/
│   │   │   │   │   │   ├── browser-support.component.ts
│   │   │   │   │   │   └── browser-support.template.html
│   │   │   │   │   ├── core-concepts-overview/
│   │   │   │   │   │   ├── core-concepts-overview.component.ts
│   │   │   │   │   │   ├── core-concepts-overview.styles.less
│   │   │   │   │   │   ├── core-concepts-overview.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── maskito-public-api-demo.md
│   │   │   │   │   ├── element-state/
│   │   │   │   │   │   ├── element-state.component.ts
│   │   │   │   │   │   ├── element-state.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── element-state-demo.md
│   │   │   │   │   ├── mask-expression/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── basic-time-example.md
│   │   │   │   │   │   │   ├── dynamic-mask-expression-demo.md
│   │   │   │   │   │   │   └── reg-exp-mask-expression-demo.md
│   │   │   │   │   │   ├── mask-expression.component.ts
│   │   │   │   │   │   └── mask-expression.template.html
│   │   │   │   │   ├── maskito-libraries/
│   │   │   │   │   │   ├── maskito-libraries.component.ts
│   │   │   │   │   │   └── maskito-libraries.template.html
│   │   │   │   │   ├── next-steps/
│   │   │   │   │   │   ├── next-steps.component.ts
│   │   │   │   │   │   └── next-steps.template.html
│   │   │   │   │   ├── overwrite-mode/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── dynamic/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── replace/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── shift/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── overwrite-mode.component.ts
│   │   │   │   │   │   └── overwrite-mode.template.html
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-initial-calibration/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   ├── index.md
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-strict-composition/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-change-event/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── oversimplified-number-mask.md
│   │   │   │   │   │   │   └── pads-zero-plugin.ts
│   │   │   │   │   │   ├── plugins.component.ts
│   │   │   │   │   │   ├── plugins.style.less
│   │   │   │   │   │   └── plugins.template.html
│   │   │   │   │   ├── processors/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── postprocessor-in-action.md
│   │   │   │   │   │   │   ├── preprocessor-first-arg-demo.md
│   │   │   │   │   │   │   ├── preprocessor-in-action-demo.md
│   │   │   │   │   │   │   └── processor-second-arg-demo.md
│   │   │   │   │   │   ├── processors.component.ts
│   │   │   │   │   │   └── processors.template.html
│   │   │   │   │   ├── real-world-form/
│   │   │   │   │   │   ├── index.html
│   │   │   │   │   │   ├── index.less
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── supported-input-types/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── password/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── search/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── tel/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── text/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── url/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── supported-input-types.component.ts
│   │   │   │   │   │   └── supported-input-types.template.html
│   │   │   │   │   ├── transformer/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   └── utility-in-action-demo.md
│   │   │   │   │   │   ├── transformer.component.ts
│   │   │   │   │   │   └── transformer.template.html
│   │   │   │   │   └── what-is-maskito/
│   │   │   │   │       ├── what-is-maskito.component.ts
│   │   │   │   │       ├── what-is-maskito.style.less
│   │   │   │   │       └── what-is-maskito.template.html
│   │   │   │   ├── frameworks/
│   │   │   │   │   ├── angular/
│   │   │   │   │   │   ├── angular-doc.component.ts
│   │   │   │   │   │   ├── angular-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-nested/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 2-nested/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 3-programmatically/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 4-pipe/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── 5-custom-unmask-handler/
│   │   │   │   │   │       │   ├── index.html
│   │   │   │   │   │       │   ├── index.ts
│   │   │   │   │   │       │   └── unmask.directive.ts
│   │   │   │   │   │       ├── 6-pattern/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── template.html
│   │   │   │   │   │       ├── basic-directive-approach.md
│   │   │   │   │   │       ├── custom-input-example.md
│   │   │   │   │   │       └── import-maskito.md
│   │   │   │   │   ├── react/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-use-maskito-basic-usage/
│   │   │   │   │   │   │   │   ├── example.component.tsx
│   │   │   │   │   │   │   │   └── useMaskitoBasicUsage.tsx
│   │   │   │   │   │   │   ├── 2-element-predicate/
│   │   │   │   │   │   │   │   ├── awesomeInput.tsx
│   │   │   │   │   │   │   │   ├── example.component.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── 3-merge-ref/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── 3-react-hook-form/
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── with-maskito-register.ts
│   │   │   │   │   │   │   ├── best-bad-practice.md
│   │   │   │   │   │   │   ├── controlled-input.md
│   │   │   │   │   │   │   └── merge-ref.md
│   │   │   │   │   │   ├── react-doc.component.ts
│   │   │   │   │   │   ├── react-doc.style.less
│   │   │   │   │   │   └── react-doc.template.html
│   │   │   │   │   └── vue/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── best-bad-practice.md
│   │   │   │   │       │   ├── query-nested-input.md
│   │   │   │   │       │   ├── use-maskito-basic-usage.md
│   │   │   │   │       │   └── vue-1/
│   │   │   │   │       │       └── component.ts
│   │   │   │   │       ├── vue-doc.component.ts
│   │   │   │   │       └── vue-doc.template.html
│   │   │   │   ├── kit/
│   │   │   │   │   ├── date/
│   │   │   │   │   │   ├── date-mask-doc.component.ts
│   │   │   │   │   │   ├── date-mask-doc.style.less
│   │   │   │   │   │   ├── date-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── maskito-parse-stringify-date-demo.md
│   │   │   │   │   ├── date-range/
│   │   │   │   │   │   ├── date-range-mask-doc.component.ts
│   │   │   │   │   │   ├── date-range-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-date-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 3-min-max-length/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── 4-range-separator/
│   │   │   │   │   │           ├── component.ts
│   │   │   │   │   │           └── mask.ts
│   │   │   │   │   ├── date-time/
│   │   │   │   │   │   ├── date-time-mask-doc.component.ts
│   │   │   │   │   │   ├── date-time-mask-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-date-time-localization/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-date-time-separator/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 3-min-max/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 4-time-step/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 5-am-pm/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       └── maskito-parse-stringify-date-time-demo.md
│   │   │   │   │   ├── number/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-high-precision/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-separators/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-postfix/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 4-decimal-zero-padding/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 5-custom-minus-sign/
│   │   │   │   │   │   │   │   ├── components.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 6-minus-before-prefix/
│   │   │   │   │   │   │   │   ├── components.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 7-dynamic-decimal-zero-padding/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 8-thousand-separator-pattern/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 9-thousand-separator-pattern-intl/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── helpers/
│   │   │   │   │   │   │   ├── parse-number-as-bigint-type.md
│   │   │   │   │   │   │   ├── parse-number-as-number-type.md
│   │   │   │   │   │   │   ├── parse-number-invalid-usage.md
│   │   │   │   │   │   │   └── stringify-number.md
│   │   │   │   │   │   ├── number-mask-doc.component.ts
│   │   │   │   │   │   └── number-mask-doc.template.html
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-selection-handler/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-caret-guard/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 3-event-handlers/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 4-reject/
│   │   │   │   │   │   │       ├── animation.css
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       ├── index.md
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── kit-plugins-doc.component.ts
│   │   │   │   │   │   └── kit-plugins-doc.template.html
│   │   │   │   │   └── time/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── 1-modes/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 2-am-pm/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 3-step/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 4-affixes/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   ├── 5-time-segments-min-max/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   └── maskito-parse-stringify-time-demo.md
│   │   │   │   │       ├── time-mask-doc.component.ts
│   │   │   │   │       ├── time-mask-doc.style.less
│   │   │   │   │       └── time-mask-doc.template.html
│   │   │   │   ├── pages.ts
│   │   │   │   ├── phone/
│   │   │   │   │   ├── examples/
│   │   │   │   │   │   ├── 1-basic/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 2-validation/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 3-non-strict/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   ├── 4-lazy-metadata/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── simple.md
│   │   │   │   │   │   ├── 5-focus-blur-events/
│   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   └── 6-national-format/
│   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │       └── mask.ts
│   │   │   │   │   ├── phone-doc.component.ts
│   │   │   │   │   ├── phone-doc.style.less
│   │   │   │   │   └── phone-doc.template.html
│   │   │   │   ├── recipes/
│   │   │   │   │   ├── card/
│   │   │   │   │   │   ├── card-doc.component.ts
│   │   │   │   │   │   ├── card-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       └── 1-basic/
│   │   │   │   │   │           ├── component.ts
│   │   │   │   │   │           ├── style.less
│   │   │   │   │   │           └── template.html
│   │   │   │   │   ├── content-editable/
│   │   │   │   │   │   ├── content-editable-doc.component.ts
│   │   │   │   │   │   ├── content-editable-doc.template.html
│   │   │   │   │   │   └── examples/
│   │   │   │   │   │       ├── 1-time/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── 2-multi-line/
│   │   │   │   │   │       │   ├── component.ts
│   │   │   │   │   │       │   └── mask.ts
│   │   │   │   │   │       ├── maskito-with-content-editable.md
│   │   │   │   │   │       └── vanilla-js-tab.md
│   │   │   │   │   ├── network-address/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-ipv6/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-ipv4/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 3-mac/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── network-address-doc.component.ts
│   │   │   │   │   │   └── network-address-doc.template.html
│   │   │   │   │   ├── phone/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-us-phone/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-kz-phone/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       ├── mask.ts
│   │   │   │   │   │   │       └── template.html
│   │   │   │   │   │   ├── phone-doc.component.ts
│   │   │   │   │   │   └── phone-doc.template.html
│   │   │   │   │   ├── placeholder/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-cvc-code/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   ├── 2-phone/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 3-date/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── placeholder-doc.component.ts
│   │   │   │   │   │   └── placeholder-doc.template.html
│   │   │   │   │   ├── postfix/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-pattern-mask/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-postprocessor/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── postfix-doc.component.ts
│   │   │   │   │   │   └── postfix-doc.template.html
│   │   │   │   │   ├── prefix/
│   │   │   │   │   │   ├── examples/
│   │   │   │   │   │   │   ├── 1-pattern-mask/
│   │   │   │   │   │   │   │   ├── component.ts
│   │   │   │   │   │   │   │   └── mask.ts
│   │   │   │   │   │   │   └── 2-postprocessor/
│   │   │   │   │   │   │       ├── component.ts
│   │   │   │   │   │   │       └── mask.ts
│   │   │   │   │   │   ├── prefix-doc.component.ts
│   │   │   │   │   │   └── prefix-doc.template.html
│   │   │   │   │   └── textarea/
│   │   │   │   │       ├── examples/
│   │   │   │   │       │   ├── 1-latin/
│   │   │   │   │       │   │   ├── component.ts
│   │   │   │   │       │   │   └── mask.ts
│   │   │   │   │       │   └── maskito-with-textarea.md
│   │   │   │   │       ├── textarea-doc.component.ts
│   │   │   │   │       └── textarea-doc.template.html
│   │   │   │   └── stackblitz/
│   │   │   │       ├── components/
│   │   │   │       │   ├── stackblitz-edit-button/
│   │   │   │       │   │   ├── stackblitz-edit-button.component.ts
│   │   │   │       │   │   └── stackblitz-edit-button.style.less
│   │   │   │       │   └── stackblitz-starter/
│   │   │   │       │       ├── stackblitz-starter.component.ts
│   │   │   │       │       └── stackblitz-starter.style.less
│   │   │   │       ├── files/
│   │   │   │       │   ├── example.ts.md
│   │   │   │       │   ├── starter.ts.md
│   │   │   │       │   └── styles.css
│   │   │   │       ├── index.ts
│   │   │   │       └── stackblitz.service.ts
│   │   │   ├── server.ts
│   │   │   ├── styles.less
│   │   │   ├── test-setup.ts
│   │   │   └── typings.d.ts
│   │   ├── tsconfig.app.json
│   │   └── tsconfig.typecheck.json
│   ├── demo-integrations/
│   │   ├── cypress-react.config.ts
│   │   ├── cypress.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src/
│   │   │   ├── fixtures/
│   │   │   │   └── example.json
│   │   │   ├── plugins/
│   │   │   │   └── index.js
│   │   │   ├── support/
│   │   │   │   ├── assertions/
│   │   │   │   │   ├── have-ng-control-value.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── commands/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── paste.ts
│   │   │   │   │   └── smart-tick.ts
│   │   │   │   ├── component-index.html
│   │   │   │   ├── component-react.ts
│   │   │   │   ├── component.ts
│   │   │   │   ├── constants/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── real-events-support.ts
│   │   │   │   └── e2e.ts
│   │   │   └── tests/
│   │   │       ├── addons/
│   │   │       │   └── phone/
│   │   │       │       ├── phone-basic.cy.ts
│   │   │       │       ├── phone-national-trunk-prefix.cy.ts
│   │   │       │       ├── phone-non-strict.cy.ts
│   │   │       │       ├── phone-separator.cy.ts
│   │   │       │       └── phone-strict.cy.ts
│   │   │       ├── angular/
│   │   │       │   ├── form-control-changes.cy.ts
│   │   │       │   └── unmask-handler.cy.ts
│   │   │       ├── component-testing/
│   │   │       │   ├── angular/
│   │   │       │   │   ├── disable-mask-on-null.cy.ts
│   │   │       │   │   └── pattern.cy.ts
│   │   │       │   ├── angular-predicate/
│   │   │       │   │   ├── angular-predicate.cy.ts
│   │   │       │   │   └── multi-test.component.ts
│   │   │       │   ├── change-event-plugin/
│   │   │       │   │   └── change-event-plugin.cy.ts
│   │   │       │   ├── initial-calibration-plugin/
│   │   │       │   │   └── dispatch-event.cy.ts
│   │   │       │   ├── multi-character-date-segment-separator/
│   │   │       │   │   └── multi-character-date-segment-separator.cy.ts
│   │   │       │   ├── native-max-length/
│   │   │       │   │   └── native-maxlength-attribute.cy.ts
│   │   │       │   ├── native-select-method/
│   │   │       │   │   └── native-select-method.cy.ts
│   │   │       │   ├── number/
│   │   │       │   │   ├── alone-decimal-separator.cy.ts
│   │   │       │   │   ├── min-max-bigint.cy.ts
│   │   │       │   │   ├── mirrored-prefix-postfix.cy.ts
│   │   │       │   │   ├── mirrored-value-postfix.cy.ts
│   │   │       │   │   ├── multi-character-prefix.cy.ts
│   │   │       │   │   ├── overwrite-selection-range.cy.ts
│   │   │       │   │   ├── postfix-multi-character.cy.ts
│   │   │       │   │   ├── postfix-with-point.cy.ts
│   │   │       │   │   ├── runtime-postfix-changes/
│   │   │       │   │   │   ├── runtime-postfix-changes.cy.ts
│   │   │       │   │   │   └── sandbox.component.ts
│   │   │       │   │   └── with-initial-value.cy.ts
│   │   │       │   ├── overwrite-mode/
│   │   │       │   │   └── overwrite-mode-replace.cy.ts
│   │   │       │   ├── paste/
│   │   │       │   │   └── cy-paste-utility.cy.ts
│   │   │       │   ├── phone/
│   │   │       │   │   ├── phone-national-format.cy.ts
│   │   │       │   │   └── phone-with-initial-value.cy.ts
│   │   │       │   ├── placeholder/
│   │   │       │   │   ├── placeholder-dispatch-input-events.cy.ts
│   │   │       │   │   ├── placeholder-has-same-characters-as-textfield.cy.ts
│   │   │       │   │   └── placeholder-partial-removal-on-blur.cy.ts
│   │   │       │   ├── react/
│   │   │       │   │   ├── async-predicate-options-race/
│   │   │       │   │   │   ├── reactApp.tsx
│   │   │       │   │   │   └── reactAsyncPredicateOptionsRace.cy.tsx
│   │   │       │   │   ├── async-predicates-race/
│   │   │       │   │   │   ├── reactApp.tsx
│   │   │       │   │   │   └── reactAsyncPredicatesRace.cy.tsx
│   │   │       │   │   ├── awesomeInput.tsx
│   │   │       │   │   └── change-event/
│   │   │       │   │       └── changeEvent.cy.tsx
│   │   │       │   └── utils.ts
│   │   │       ├── kit/
│   │   │       │   ├── date/
│   │   │       │   │   ├── date-basic.cy.ts
│   │   │       │   │   ├── date-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-min-max.cy.ts
│   │   │       │   │   ├── date-mode.cy.ts
│   │   │       │   │   ├── date-segments-zero-padding.cy.ts
│   │   │       │   │   └── date-separator.cy.ts
│   │   │       │   ├── date-range/
│   │   │       │   │   ├── date-range-basic.cy.ts
│   │   │       │   │   ├── date-range-custom-range-separator.cy.ts
│   │   │       │   │   ├── date-range-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-range-min-max-length.cy.ts
│   │   │       │   │   ├── date-range-min-max.cy.ts
│   │   │       │   │   ├── date-range-mode.cy.ts
│   │   │       │   │   ├── date-range-segments-zero-padding.cy.ts
│   │   │       │   │   └── date-range-separator.cy.ts
│   │   │       │   ├── date-time/
│   │   │       │   │   ├── date-time-basic.cy.ts
│   │   │       │   │   ├── date-time-date-time-separator.cy.ts
│   │   │       │   │   ├── date-time-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── date-time-meridiem.cy.ts
│   │   │       │   │   ├── date-time-min-max.cy.ts
│   │   │       │   │   ├── date-time-mode.cy.ts
│   │   │       │   │   ├── date-time-separator.cy.ts
│   │   │       │   │   └── date-time-time-step.cy.ts
│   │   │       │   ├── number/
│   │   │       │   │   ├── number-basic.cy.ts
│   │   │       │   │   ├── number-bigint.cy.ts
│   │   │       │   │   ├── number-decimal-separator.cy.ts
│   │   │       │   │   ├── number-decimal-zero-padding.cy.ts
│   │   │       │   │   ├── number-examples.cy.ts
│   │   │       │   │   ├── number-fullwidth-to-halfwidth.cy.ts
│   │   │       │   │   ├── number-max-validation.cy.ts
│   │   │       │   │   ├── number-min-validation.cy.ts
│   │   │       │   │   ├── number-minus-before-prefix.cy.ts
│   │   │       │   │   ├── number-minus-sign.cy.ts
│   │   │       │   │   ├── number-precision.cy.ts
│   │   │       │   │   ├── number-prefix-postfix.cy.ts
│   │   │       │   │   ├── number-thousand-separator.cy.ts
│   │   │       │   │   ├── number-zero-integer-part.cy.ts
│   │   │       │   │   └── utils.ts
│   │   │       │   └── time/
│   │   │       │       ├── time-affixes.cy.ts
│   │   │       │       ├── time-basic.cy.ts
│   │   │       │       ├── time-fullwidth-to-halfwidth.cy.ts
│   │   │       │       ├── time-meridiem.cy.ts
│   │   │       │       ├── time-mode.cy.ts
│   │   │       │       ├── time-segment-max-values.cy.ts
│   │   │       │       └── time-step.cy.ts
│   │   │       ├── react/
│   │   │       │   └── element-predicate.cy.ts
│   │   │       ├── recipes/
│   │   │       │   ├── card/
│   │   │       │   │   └── card.cy.ts
│   │   │       │   ├── content-editable/
│   │   │       │   │   ├── multi-line.cy.ts
│   │   │       │   │   └── single-line-time-mask.cy.ts
│   │   │       │   ├── network-address/
│   │   │       │   │   ├── ipv4.cy.ts
│   │   │       │   │   ├── ipv6.cy.ts
│   │   │       │   │   └── mac.cy.ts
│   │   │       │   ├── phone/
│   │   │       │   │   └── phone.cy.ts
│   │   │       │   ├── placeholder/
│   │   │       │   │   ├── date.cy.ts
│   │   │       │   │   ├── us-phone.cy.ts
│   │   │       │   │   └── сvc-code.cy.ts
│   │   │       │   ├── plugins/
│   │   │       │   │   └── reject.cy.ts
│   │   │       │   ├── postfix/
│   │   │       │   │   ├── percentage.cy.ts
│   │   │       │   │   └── postprocessor.cy.ts
│   │   │       │   ├── prefix/
│   │   │       │   │   ├── dynamic-pattern-mask-expression.cy.ts
│   │   │       │   │   └── postprocessor.cy.ts
│   │   │       │   └── textarea/
│   │   │       │       └── textarea-latin-letters-digits.cy.ts
│   │   │       ├── ssr/
│   │   │       │   └── ssr.cy.ts
│   │   │       ├── utils.ts
│   │   │       └── vue/
│   │   │           └── vue.cy.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── kit/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── constants/
│   │           │   ├── date-segment-max-values.ts
│   │           │   ├── default-decimal-pseudo-separators.ts
│   │           │   ├── default-min-max-dates.ts
│   │           │   ├── default-pseudo-minuses.ts
│   │           │   ├── default-time-segment-bounds.ts
│   │           │   ├── index.ts
│   │           │   ├── meridiem.ts
│   │           │   ├── time-fixed-characters.ts
│   │           │   ├── time-segment-value-lengths.ts
│   │           │   └── unicode-characters.ts
│   │           ├── masks/
│   │           │   ├── date/
│   │           │   │   ├── date-mask.ts
│   │           │   │   ├── date-params.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── tests/
│   │           │   │   │   └── date-mask.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── index.ts
│   │           │   │       ├── parse-date.ts
│   │           │   │       ├── stringify-date.ts
│   │           │   │       ├── tests/
│   │           │   │       │   ├── parse-date.spec.ts
│   │           │   │       │   └── stringify-date.spec.ts
│   │           │   │       └── to-date-segments.ts
│   │           │   ├── date-range/
│   │           │   │   ├── constants.ts
│   │           │   │   ├── date-range-mask.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── processors/
│   │           │   │   │   ├── min-max-range-length-postprocessor.ts
│   │           │   │   │   └── swap-dates-postprocessor.ts
│   │           │   │   └── tests/
│   │           │   │       ├── date-segments-zero-padding.spec.ts
│   │           │   │       └── pseudo-range-separators.spec.ts
│   │           │   ├── date-time/
│   │           │   │   ├── constants/
│   │           │   │   │   ├── date-time-separator.ts
│   │           │   │   │   └── index.ts
│   │           │   │   ├── date-time-mask.ts
│   │           │   │   ├── date-time-params.ts
│   │           │   │   ├── index.ts
│   │           │   │   ├── postprocessors/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   └── min-max-date-time-postprocessor.ts
│   │           │   │   ├── preprocessors/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   └── valid-date-time-preprocessor.ts
│   │           │   │   ├── tests/
│   │           │   │   │   ├── date-segments-zero-padding.spec.ts
│   │           │   │   │   ├── date-time-separator.spec.ts
│   │           │   │   │   └── pseudo-date-end-separator.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── index.ts
│   │           │   │       ├── is-date-time-string-complete.ts
│   │           │   │       ├── parse-date-time.ts
│   │           │   │       ├── split-date-time-string.ts
│   │           │   │       ├── stringify-date-time.ts
│   │           │   │       └── tests/
│   │           │   │           ├── parse-date-time.spec.ts
│   │           │   │           ├── split-date-time-string.spec.ts
│   │           │   │           └── stringify-date-time.spec.ts
│   │           │   ├── number/
│   │           │   │   ├── index.ts
│   │           │   │   ├── number-mask.ts
│   │           │   │   ├── number-params.ts
│   │           │   │   ├── plugins/
│   │           │   │   │   ├── index.ts
│   │           │   │   │   ├── leading-zeroes-validation.plugin.ts
│   │           │   │   │   ├── min-max.plugin.ts
│   │           │   │   │   └── not-empty-integer.plugin.ts
│   │           │   │   ├── processors/
│   │           │   │   │   ├── affixes-filter-preprocessor.ts
│   │           │   │   │   ├── decimal-zero-padding-postprocessor.ts
│   │           │   │   │   ├── empty-postprocessor.ts
│   │           │   │   │   ├── index.ts
│   │           │   │   │   ├── initialization-only-preprocessor.ts
│   │           │   │   │   ├── leading-minus-deletion-preprocessor.ts
│   │           │   │   │   ├── leading-zeroes-validation-postprocessor.ts
│   │           │   │   │   ├── min-max-postprocessor.ts
│   │           │   │   │   ├── non-removable-chars-deletion-preprocessor.ts
│   │           │   │   │   ├── not-empty-integer-part-preprocessor.ts
│   │           │   │   │   ├── number-prefix-postprocessor.ts
│   │           │   │   │   ├── pseudo-character-preprocessor.ts
│   │           │   │   │   ├── repeated-decimal-separator-preprocessor.ts
│   │           │   │   │   ├── tests/
│   │           │   │   │   │   ├── leading-zeroes-validation-postprocessor.spec.ts
│   │           │   │   │   │   └── not-empty-integer-part-preprocessor.spec.ts
│   │           │   │   │   ├── thousand-separator-postprocessor.ts
│   │           │   │   │   └── zero-precision-preprocessor.ts
│   │           │   │   ├── tests/
│   │           │   │   │   └── number-mask.spec.ts
│   │           │   │   └── utils/
│   │           │   │       ├── extract-affixes.ts
│   │           │   │       ├── generate-mask-expression.ts
│   │           │   │       ├── index.ts
│   │           │   │       ├── number-parts.ts
│   │           │   │       ├── parse-number.ts
│   │           │   │       ├── stringify-number-without-exp.ts
│   │           │   │       ├── stringify-number.ts
│   │           │   │       ├── tests/
│   │           │   │       │   ├── parse-number.spec.ts
│   │           │   │       │   ├── stringify-number-without-exp.spec.ts
│   │           │   │       │   ├── stringify-number.spec.ts
│   │           │   │       │   ├── to-number-parts.spec.ts
│   │           │   │       │   └── validate-decimal-pseudo-separators.spec.ts
│   │           │   │       ├── validate-decimal-pseudo-separators.ts
│   │           │   │       └── with-number-defaults.ts
│   │           │   └── time/
│   │           │       ├── index.ts
│   │           │       ├── time-mask.ts
│   │           │       ├── time-params.ts
│   │           │       └── utils/
│   │           │           ├── index.ts
│   │           │           ├── parse-time.ts
│   │           │           ├── stringify-time.ts
│   │           │           └── tests/
│   │           │               ├── parse-time.spec.ts
│   │           │               └── stringify-time.spec.ts
│   │           ├── plugins/
│   │           │   ├── add-on-focus.ts
│   │           │   ├── caret-guard.ts
│   │           │   ├── event-handler.ts
│   │           │   ├── index.ts
│   │           │   ├── reject-event.ts
│   │           │   ├── remove-on-blur.ts
│   │           │   ├── selection-change.ts
│   │           │   └── time/
│   │           │       ├── meridiem-stepping.ts
│   │           │       └── time-segments-stepping.ts
│   │           ├── processors/
│   │           │   ├── colon-convert-preprocessor.ts
│   │           │   ├── date-segments-zero-padding-postprocessor.ts
│   │           │   ├── first-date-end-separator-preprocessor.ts
│   │           │   ├── fullwidth-to-halfwidth-preprocessor.ts
│   │           │   ├── index.ts
│   │           │   ├── invalid-time-segment-insertion-preprocessor.ts
│   │           │   ├── meridiem-processors.ts
│   │           │   ├── min-max-date-postprocessor.ts
│   │           │   ├── normalize-date-preprocessor.ts
│   │           │   ├── postfix-postprocessor.ts
│   │           │   ├── prefix-postprocessor.ts
│   │           │   ├── tests/
│   │           │   │   ├── first-date-end-separator-preprocessor.spec.ts
│   │           │   │   ├── normalize-date-preprocessor.spec.ts
│   │           │   │   ├── postfix-postprocessor.spec.ts
│   │           │   │   ├── prefix-postprocessor.spec.ts
│   │           │   │   ├── valid-date-preprocessor.spec.ts
│   │           │   │   └── with-placeholder.spec.ts
│   │           │   ├── valid-date-preprocessor.ts
│   │           │   ├── with-placeholder.ts
│   │           │   └── zero-placeholders-preprocessor.ts
│   │           ├── types/
│   │           │   ├── date-mode.ts
│   │           │   ├── date-segments.ts
│   │           │   ├── index.ts
│   │           │   ├── time-mode.ts
│   │           │   └── time-segments.ts
│   │           └── utils/
│   │               ├── clamp.ts
│   │               ├── count-digits.ts
│   │               ├── date/
│   │               │   ├── append-date.ts
│   │               │   ├── date-segment-value-length.ts
│   │               │   ├── date-to-segments.ts
│   │               │   ├── get-date-segments-order.ts
│   │               │   ├── get-first-complete-date.ts
│   │               │   ├── is-date-string-complete.ts
│   │               │   ├── parse-date-range-string.ts
│   │               │   ├── parse-date-string.ts
│   │               │   ├── raise-segment-value-to-min.ts
│   │               │   ├── segments-to-date.ts
│   │               │   ├── tests/
│   │               │   │   ├── append-date.spec.ts
│   │               │   │   ├── get-date-segment-value-length.spec.ts
│   │               │   │   └── parse-date-range-string.spec.ts
│   │               │   ├── to-date-string.ts
│   │               │   └── validate-date-string.ts
│   │               ├── dummy.ts
│   │               ├── escape-reg-exp.ts
│   │               ├── find-common-beginning-substr.ts
│   │               ├── index.ts
│   │               ├── is-empty.ts
│   │               ├── pad-with-zeroes-until-valid.ts
│   │               ├── tests/
│   │               │   ├── clamp.spec.ts
│   │               │   ├── escape-reg-exp.spec.ts
│   │               │   ├── find-common-beginning-substr.spec.ts
│   │               │   ├── get-first-complete-date.spec.ts
│   │               │   ├── is-empty.spec.ts
│   │               │   ├── to-half-width-colon.spec.ts
│   │               │   └── to-half-width-number.spec.ts
│   │               ├── time/
│   │               │   ├── create-time-mask-expression.ts
│   │               │   ├── enrich-time-segments-with-zeroes.ts
│   │               │   ├── index.ts
│   │               │   ├── pad-end-time-segments.ts
│   │               │   ├── pad-start-time-segments.ts
│   │               │   ├── pad-time-segments.ts
│   │               │   ├── parse-time-string.ts
│   │               │   ├── tests/
│   │               │   │   ├── enrich-time-segments-with-zeroes.spec.ts
│   │               │   │   ├── parse-time-string.spec.ts
│   │               │   │   └── to-time-string.spec.ts
│   │               │   └── to-time-string.ts
│   │               ├── to-half-width-colon.ts
│   │               └── to-half-width-number.ts
│   ├── phone/
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           └── masks/
│   │               ├── index.ts
│   │               └── phone/
│   │                   ├── constants/
│   │                   │   ├── index.ts
│   │                   │   └── template-filler.ts
│   │                   ├── index.ts
│   │                   ├── phone-mask-non-strict.ts
│   │                   ├── phone-mask-strict.ts
│   │                   ├── phone-mask.ts
│   │                   ├── processors/
│   │                   │   ├── browser-autofill-preprocessor.ts
│   │                   │   ├── cut-init-country-code-preprocessor.ts
│   │                   │   ├── index.ts
│   │                   │   ├── paste-non-strict-phone-preprocessor.ts
│   │                   │   ├── paste-strict-phone-preprocessor.ts
│   │                   │   ├── phone-length-postprocessor.ts
│   │                   │   └── sanitize-phone-preprocessor.ts
│   │                   ├── tests/
│   │                   │   ├── get-phone-template.spec.ts
│   │                   │   └── phone-mask.spec.ts
│   │                   └── utils/
│   │                       ├── cut-phone-by-valid-length.ts
│   │                       ├── generate-phone-mask.ts
│   │                       ├── get-country-from-number.ts
│   │                       ├── get-phone-template.ts
│   │                       ├── index.ts
│   │                       └── select-template.ts
│   ├── react/
│   │   ├── .babelrc
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   └── src/
│   │       ├── index.ts
│   │       └── lib/
│   │           ├── adaptControlledElement.tsx
│   │           ├── tests/
│   │           │   ├── controlledInput.spec.tsx
│   │           │   ├── elementPredicate.spec.tsx
│   │           │   └── useMaskito.spec.tsx
│   │           ├── useIsomorphicLayoutEffect.tsx
│   │           └── useMaskito.tsx
│   └── vue/
│       ├── README.md
│       ├── jest.config.ts
│       ├── package.json
│       ├── project.json
│       └── src/
│           ├── index.ts
│           └── lib/
│               ├── maskito.spec.ts
│               └── maskito.ts
├── tsconfig.build.json
├── tsconfig.json
└── tsconfig.spec.json
Download .txt
SYMBOL INDEX (503 symbols across 330 files)

FILE: projects/angular/src/lib/maskito.directive.ts
  class MaskitoDirective (line 20) | class MaskitoDirective implements OnDestroy {
    method constructor (line 57) | constructor() {
    method ngOnDestroy (line 73) | public ngOnDestroy(): void {
    method destroy (line 77) | private destroy(): void {

FILE: projects/angular/src/lib/maskito.pipe.ts
  class MaskitoPipe (line 9) | class MaskitoPipe implements PipeTransform {
    method transform (line 10) | public transform(value: unknown, maskitoOptions: MaskitoOptions | null...

FILE: projects/angular/src/lib/pattern.directive.ts
  class MaskitoPattern (line 10) | class MaskitoPattern {
    method maskitoPattern (line 13) | public set maskitoPattern(pattern: RegExp | string) {

FILE: projects/angular/src/lib/tests/maskito.directive.spec.ts
  constant DIGIT_ONLY (line 12) | const DIGIT_ONLY: MaskitoOptions = {mask: /^\d*$/};
  class TestHostComponent (line 15) | @Component({
  function getDirective (line 33) | function getDirective(): MaskitoDirective {
  function getMaskedElement (line 37) | function getMaskedElement(): Maskito | null {
  function makeControlledPredicate (line 103) | function makeControlledPredicate(): {

FILE: projects/angular/src/lib/tests/maskito.spec.ts
  class TestComponent (line 9) | @Component({
  function getText (line 75) | function getText(): string {
  function getValue (line 81) | function getValue(): string {

FILE: projects/core/src/lib/classes/mask-history.ts
  method undo (line 13) | protected undo(): void {
  method redo (line 22) | protected redo(): void {
  method updateHistory (line 31) | protected updateHistory(state: ElementState): void {
  method updateElement (line 55) | private updateElement(

FILE: projects/core/src/lib/classes/mask-model/mask-model.ts
  class MaskModel (line 12) | class MaskModel implements ElementState {
    method constructor (line 18) | constructor(
    method addCharacters (line 33) | public addCharacters(newCharacters: string): void {
    method deleteCharacters (line 89) | public deleteCharacters(): void {
    method getMaskExpression (line 115) | private getMaskExpression(elementState: ElementState): MaskitoMaskExpr...

FILE: projects/core/src/lib/classes/mask-model/tests/dynamic-mask.spec.ts
  constant EMPTY_STATE (line 7) | const EMPTY_STATE: ElementState = {

FILE: projects/core/src/lib/classes/mask-model/utils/apply-overwrite-mode.ts
  function applyOverwriteMode (line 3) | function applyOverwriteMode(

FILE: projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts
  function calibrateValueByMask (line 6) | function calibrateValueByMask(

FILE: projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts
  function getLeadingFixedCharacters (line 4) | function getLeadingFixedCharacters(

FILE: projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts
  function guessValidValueByPattern (line 6) | function guessValidValueByPattern(

FILE: projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-reg-exp.ts
  function guessValidValueByRegExp (line 3) | function guessValidValueByRegExp(

FILE: projects/core/src/lib/classes/mask-model/utils/is-fixed-character.ts
  function isFixedCharacter (line 1) | function isFixedCharacter(char: RegExp | string): char is string {

FILE: projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts
  function removeFixedMaskCharacters (line 4) | function removeFixedMaskCharacters(

FILE: projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts
  function validateValueWithMask (line 4) | function validateValueWithMask(

FILE: projects/core/src/lib/constants/default-options.ts
  constant MASKITO_DEFAULT_OPTIONS (line 3) | const MASKITO_DEFAULT_OPTIONS: Required<MaskitoOptions> = {

FILE: projects/core/src/lib/mask.ts
  constant BUILT_IN_PLUGINS (line 24) | const BUILT_IN_PLUGINS = [createDoubleSpacePlugin(), createBrokenDefault...
  class Maskito (line 26) | class Maskito extends MaskHistory {
    method constructor (line 44) | constructor(
    method destroy (line 170) | public destroy(): void {
    method updateElementState (line 175) | protected updateElementState(
    method elementState (line 189) | private get elementState(): ElementState {
    method maxLength (line 198) | private get maxLength(): number {
    method updateSelectionRange (line 204) | private updateSelectionRange([from, to]: SelectionRange): void {
    method updateValue (line 215) | private updateValue(value: string): void {
    method ensureValueFitsMask (line 225) | private ensureValueFitsMask(): void {
    method dispatchInputEvent (line 232) | private dispatchInputEvent(
    method handleDelete (line 247) | private handleDelete({
    method handleInsert (line 288) | private handleInsert(event: TypedInputEvent, data: string): void {
    method handleEnter (line 336) | private handleEnter(event: TypedInputEvent): void {
    method clampState (line 342) | private clampState({value, selection}: ElementState): ElementState {

FILE: projects/core/src/lib/plugins/broken-prevent-default.plugin.ts
  function createBrokenDefaultPlugin (line 16) | function createBrokenDefaultPlugin(): MaskitoPlugin {

FILE: projects/core/src/lib/plugins/change-event-plugin.ts
  function maskitoChangeEventPlugin (line 3) | function maskitoChangeEventPlugin(): MaskitoPlugin {

FILE: projects/core/src/lib/plugins/double-space.plugin.ts
  constant SPACE (line 6) | const SPACE = ' ';
  function createDoubleSpacePlugin (line 32) | function createDoubleSpacePlugin(): MaskitoPlugin {

FILE: projects/core/src/lib/plugins/initial-calibration-plugin.ts
  function maskitoInitialCalibrationPlugin (line 4) | function maskitoInitialCalibrationPlugin(

FILE: projects/core/src/lib/plugins/strict-composition-plugin.ts
  function maskitoStrictCompositionPlugin (line 4) | function maskitoStrictCompositionPlugin(): MaskitoPlugin {

FILE: projects/core/src/lib/types/element-predicate.ts
  type MaskitoElementPredicate (line 3) | type MaskitoElementPredicate = (

FILE: projects/core/src/lib/types/element-state.ts
  type ElementState (line 3) | interface ElementState {

FILE: projects/core/src/lib/types/mask-options.ts
  type MaskitoOptions (line 6) | interface MaskitoOptions {

FILE: projects/core/src/lib/types/mask-processors.ts
  type MaskitoPreprocessor (line 3) | type MaskitoPreprocessor = (
  type MaskitoPostprocessor (line 14) | type MaskitoPostprocessor = (

FILE: projects/core/src/lib/types/mask.ts
  type MaskitoMaskExpression (line 3) | type MaskitoMaskExpression = Array<RegExp | string> | RegExp;
  type MaskitoMask (line 5) | type MaskitoMask =

FILE: projects/core/src/lib/types/maskito-element.ts
  type TextfieldLike (line 1) | type TextfieldLike = Pick<
  type MaskitoElement (line 10) | type MaskitoElement = HTMLElement & TextfieldLike;

FILE: projects/core/src/lib/types/plugin.ts
  type MaskitoPlugin (line 4) | type MaskitoPlugin = (

FILE: projects/core/src/lib/types/selection-range.ts
  type SelectionRange (line 1) | type SelectionRange = readonly [from: number, to: number];

FILE: projects/core/src/lib/types/typed-input-event.ts
  type TypedInputEvent (line 1) | interface TypedInputEvent extends InputEvent {

FILE: projects/core/src/lib/utils/content-editable.ts
  class ContentEditableAdapter (line 5) | class ContentEditableAdapter implements TextfieldLike {
    method constructor (line 8) | constructor(private readonly element: HTMLElement) {}
    method value (line 10) | public get value(): string {
    method value (line 14) | public set value(value) {
    method selectionStart (line 19) | public get selectionStart(): number | null {
    method selectionEnd (line 23) | public get selectionEnd(): number | null {
    method setSelectionRange (line 27) | public setSelectionRange(from: number | null, to: number | null): void {
    method select (line 31) | public select(): void {
  function maskitoAdaptContentEditable (line 36) | function maskitoAdaptContentEditable(element: HTMLElement): MaskitoEleme...

FILE: projects/core/src/lib/utils/dom/event-listener.ts
  class EventListener (line 3) | class EventListener {
    method constructor (line 6) | constructor(private readonly element: HTMLElement) {}
    method listen (line 8) | public listen<E extends keyof HTMLElementEventMap>(
    method destroy (line 25) | public destroy(): void {

FILE: projects/core/src/lib/utils/dom/get-content-editable-selection.ts
  function getContentEditableSelection (line 3) | function getContentEditableSelection(element: HTMLElement): SelectionRan...

FILE: projects/core/src/lib/utils/dom/history-events.ts
  function isRedo (line 3) | function isRedo(event: KeyboardEvent): boolean {
  function isUndo (line 11) | function isUndo(event: KeyboardEvent): boolean {

FILE: projects/core/src/lib/utils/dom/hotkey.ts
  function isHotkey (line 27) | function isHotkey(

FILE: projects/core/src/lib/utils/dom/set-content-editable-selection.ts
  function setContentEditableSelection (line 3) | function setContentEditableSelection(

FILE: projects/core/src/lib/utils/dom/update-element.ts
  function maskitoUpdateElement (line 15) | function maskitoUpdateElement(

FILE: projects/core/src/lib/utils/element-states-equality.ts
  function areElementValuesEqual (line 3) | function areElementValuesEqual(
  function areElementStatesEqual (line 10) | function areElementStatesEqual(

FILE: projects/core/src/lib/utils/get-line-selection.ts
  function getLineSelection (line 3) | function getLineSelection(

FILE: projects/core/src/lib/utils/get-not-empty-selection.ts
  function getNotEmptySelection (line 3) | function getNotEmptySelection(

FILE: projects/core/src/lib/utils/get-word-selection.ts
  constant TRAILING_SPACES_REG (line 3) | const TRAILING_SPACES_REG = /\s+$/g;
  constant LEADING_SPACES_REG (line 4) | const LEADING_SPACES_REG = /^\s+/g;
  constant SPACE_REG (line 5) | const SPACE_REG = /\s/;
  function getWordSelection (line 7) | function getWordSelection(

FILE: projects/core/src/lib/utils/pipe.ts
  function maskitoPipe (line 20) | function maskitoPipe<State extends object, Args extends unknown[]>(

FILE: projects/core/src/lib/utils/transform.ts
  function maskitoTransform (line 12) | function maskitoTransform(

FILE: projects/demo-integrations/cypress.config.ts
  constant CYPRESS_CONFIG (line 5) | const CYPRESS_CONFIG: Cypress.ConfigOptions = {
  method setupNodeEvents (line 17) | setupNodeEvents(on, config) {

FILE: projects/demo-integrations/src/support/assertions/index.ts
  type Chainer (line 5) | interface Chainer<Subject> {

FILE: projects/demo-integrations/src/support/commands/index.ts
  type Chainable (line 8) | interface Chainable<Subject> {

FILE: projects/demo-integrations/src/support/commands/paste.ts
  function paste (line 7) | function paste<T extends Cypress.PrevSubjectMap['element']>(

FILE: projects/demo-integrations/src/support/commands/smart-tick.ts
  function smartTick (line 3) | function smartTick<T extends Cypress.PrevSubjectMap<void>[Cypress.PrevSu...

FILE: projects/demo-integrations/src/support/component.ts
  type Chainable (line 10) | interface Chainable<Subject> {

FILE: projects/demo-integrations/src/support/constants/real-events-support.ts
  constant BROWSER_SUPPORTS_REAL_EVENTS (line 9) | const BROWSER_SUPPORTS_REAL_EVENTS: Cypress.TestConfigOverrides = {

FILE: projects/demo-integrations/src/tests/addons/phone/phone-basic.cy.ts
  function openCountry (line 283) | function openCountry(code: string): void {

FILE: projects/demo-integrations/src/tests/addons/phone/phone-non-strict.cy.ts
  function openCountry (line 216) | function openCountry(code: string): void {

FILE: projects/demo-integrations/src/tests/addons/phone/phone-separator.cy.ts
  function openCountry (line 153) | function openCountry(code: string): void {

FILE: projects/demo-integrations/src/tests/component-testing/angular-predicate/angular-predicate.cy.ts
  class ComplexTextfield (line 69) | @Component({
    method constructor (line 87) | constructor() {
  class TestComponent (line 137) | @Component({
    method constructor (line 152) | constructor() {

FILE: projects/demo-integrations/src/tests/component-testing/angular-predicate/multi-test.component.ts
  class MultiTestInputComponent (line 23) | class MultiTestInputComponent {

FILE: projects/demo-integrations/src/tests/component-testing/native-max-length/native-maxlength-attribute.cy.ts
  class Sandbox (line 176) | @Component({
    method clear (line 197) | protected clear(): void {

FILE: projects/demo-integrations/src/tests/component-testing/native-select-method/native-select-method.cy.ts
  class TestComponent (line 22) | class TestComponent {

FILE: projects/demo-integrations/src/tests/component-testing/number/runtime-postfix-changes/sandbox.component.ts
  class TestPipe4 (line 17) | class TestPipe4 implements PipeTransform {
    method transform (line 18) | public transform(postfix: string): MaskitoOptions {
  class Sandbox (line 43) | class Sandbox {

FILE: projects/demo-integrations/src/tests/component-testing/phone/phone-with-initial-value.cy.ts
  function createMaskitoOptions (line 10) | function createMaskitoOptions(): MaskitoOptions {

FILE: projects/demo-integrations/src/tests/component-testing/react/async-predicate-options-race/reactApp.tsx
  constant SWITCH_OPTIONS_TIME (line 7) | const SWITCH_OPTIONS_TIME = 1_000;
  constant PREDICATE_RESOLVING_TIME (line 8) | const PREDICATE_RESOLVING_TIME = 2_000;

FILE: projects/demo-integrations/src/tests/component-testing/react/change-event/changeEvent.cy.tsx
  function App (line 13) | function App(): JSX.Element {
  function App (line 57) | function App(): JSX.Element {
  function App (line 116) | function App(): JSX.Element {

FILE: projects/demo-integrations/src/tests/component-testing/utils.ts
  class TestInput (line 28) | class TestInput {

FILE: projects/demo-integrations/src/tests/kit/number/utils.ts
  function openNumberPage (line 3) | function openNumberPage(queryParams = ''): void {

FILE: projects/demo-integrations/src/tests/utils.ts
  function range (line 3) | function range(from: number, to: number): number[] {
  function withCaretLabel (line 7) | function withCaretLabel(value: string, caretIndex: number): string {
  function repeatKey (line 11) | function repeatKey<T extends Parameters<typeof realPress>[0]>(

FILE: projects/demo/esbuild-plugins/maskito-as-taiga-ui-dep.plugin.js
  method setup (line 14) | setup(build) {

FILE: projects/demo/esbuild-plugins/vue-esm.plugin.js
  method setup (line 13) | setup(build) {

FILE: projects/demo/src/app/app.component.ts
  class App (line 48) | class App {
    method constructor (line 51) | constructor() {

FILE: projects/demo/src/app/app.config.ts
  constant APP_CONFIG (line 35) | const APP_CONFIG: ApplicationConfig = {

FILE: projects/demo/src/app/app.routes.ts
  constant ROUTES (line 7) | const ROUTES: Routes = [

FILE: projects/demo/src/app/modules/example-primary-tabs-icons/angular-logo.component.ts
  class AngularLogoComponent (line 10) | class AngularLogoComponent {}
  constant ANGULAR_LOGO (line 12) | const ANGULAR_LOGO = new PolymorpheusComponent(AngularLogoComponent);

FILE: projects/demo/src/app/modules/example-primary-tabs-icons/javascript-logo.component.ts
  class JavaScriptLogoComponent (line 10) | class JavaScriptLogoComponent {}
  constant JAVASCRIPT_LOGO (line 12) | const JAVASCRIPT_LOGO = new PolymorpheusComponent(JavaScriptLogoComponent);

FILE: projects/demo/src/app/modules/example-primary-tabs-icons/react-logo.component.ts
  class ReactLogoComponent (line 10) | class ReactLogoComponent {}
  constant REACT_LOGO (line 12) | const REACT_LOGO = new PolymorpheusComponent(ReactLogoComponent);

FILE: projects/demo/src/app/modules/example-primary-tabs-icons/vue-logo.component.ts
  class VueLogoComponent (line 10) | class VueLogoComponent {}
  constant VUE_LOGO (line 12) | const VUE_LOGO = new PolymorpheusComponent(VueLogoComponent);

FILE: projects/demo/src/app/modules/logo/logo.component.ts
  class LogoComponent (line 13) | class LogoComponent {}
  constant LOGO_CONTENT (line 15) | const LOGO_CONTENT = new PolymorpheusComponent(LogoComponent);

FILE: projects/demo/src/app/server-error-handler.ts
  constant KNOWN_ISSUES (line 4) | const KNOWN_ISSUES: ReadonlyArray<RegExp | string> = [
  class ServerErrorHandler (line 25) | class ServerErrorHandler implements ErrorHandler {
    method handleError (line 26) | public handleError(error: Error | string): void {

FILE: projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/angular-default-tab.ts
  constant ANGULAR_DEFAULT_TAB (line 1) | const ANGULAR_DEFAULT_TAB = `import {Component} from '@angular/core';

FILE: projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/js-default-tab.ts
  constant JS_DEFAULT_TAB (line 1) | const JS_DEFAULT_TAB = `import {Maskito, MaskitoOptions} from '@maskito/...

FILE: projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/react-default-tab.ts
  constant REACT_DEFAULT_TAB (line 1) | const REACT_DEFAULT_TAB = `import * as React from 'react';

FILE: projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/vue-default-tab.ts
  constant VUE_DEFAULT_TAB (line 1) | const VUE_DEFAULT_TAB = `import {createApp} from 'vue';

FILE: projects/demo/src/main.server.ts
  method getPrerenderParams (line 35) | async getPrerenderParams() {
  function withTabs (line 47) | function withTabs(path: string, tabs: string[]): ServerRoute {

FILE: projects/demo/src/pages/documentation/browser-support/browser-support.component.ts
  class BrowserSupportComponent (line 11) | class BrowserSupportComponent {

FILE: projects/demo/src/pages/documentation/core-concepts-overview/core-concepts-overview.component.ts
  class CoreConceptsOverviewDocPageComponent (line 27) | class CoreConceptsOverviewDocPageComponent {

FILE: projects/demo/src/pages/documentation/element-state/element-state.component.ts
  class ElementStateDocPageComponent (line 13) | class ElementStateDocPageComponent {

FILE: projects/demo/src/pages/documentation/mask-expression/mask-expression.component.ts
  class MaskExpressionDocPageComponent (line 15) | class MaskExpressionDocPageComponent {

FILE: projects/demo/src/pages/documentation/maskito-libraries/maskito-libraries.component.ts
  class MaskitoLibrariesDocPageComponent (line 13) | class MaskitoLibrariesDocPageComponent {

FILE: projects/demo/src/pages/documentation/next-steps/next-steps.component.ts
  class NextStepsComponent (line 13) | class NextStepsComponent {

FILE: projects/demo/src/pages/documentation/overwrite-mode/examples/dynamic/component.ts
  class OverwriteModeDocExample3 (line 31) | class OverwriteModeDocExample3 {

FILE: projects/demo/src/pages/documentation/overwrite-mode/examples/replace/component.ts
  class OverwriteModeDocExample2 (line 34) | class OverwriteModeDocExample2 {

FILE: projects/demo/src/pages/documentation/overwrite-mode/examples/shift/component.ts
  class OverwriteModeDocExample1 (line 34) | class OverwriteModeDocExample1 {

FILE: projects/demo/src/pages/documentation/overwrite-mode/overwrite-mode.component.ts
  class OverwriteModeDocPageComponent (line 26) | class OverwriteModeDocPageComponent {

FILE: projects/demo/src/pages/documentation/plugins/examples/1-initial-calibration/component.ts
  class PluginsDocExample2 (line 26) | class PluginsDocExample2 {

FILE: projects/demo/src/pages/documentation/plugins/examples/2-strict-composition/component.ts
  class PluginsDocExample3 (line 22) | class PluginsDocExample3 {

FILE: projects/demo/src/pages/documentation/plugins/examples/3-change-event/component.ts
  class PluginsDocExample4 (line 28) | class PluginsDocExample4 {
    method log (line 32) | protected log(anything: any): void {

FILE: projects/demo/src/pages/documentation/plugins/plugins.component.ts
  class PluginsDocPageComponent (line 38) | class PluginsDocPageComponent {

FILE: projects/demo/src/pages/documentation/processors/processors.component.ts
  class ProcessorsDocPageComponent (line 15) | class ProcessorsDocPageComponent {

FILE: projects/demo/src/pages/documentation/real-world-form/index.ts
  constant MONEY_AMOUNT_MASK (line 22) | const MONEY_AMOUNT_MASK = maskitoNumberOptionsGenerator({
  constant ONLY_LATIN_LETTERS_RE (line 28) | const ONLY_LATIN_LETTERS_RE = /^[a-z]+$/i;
  class RealWorldForm (line 46) | class RealWorldForm {
    method countryIsoCode (line 98) | protected get countryIsoCode(): string {
    method log (line 102) | protected log(something: any): void {

FILE: projects/demo/src/pages/documentation/supported-input-types/examples/password/component.ts
  class InputPasswordDocExample (line 35) | class InputPasswordDocExample {

FILE: projects/demo/src/pages/documentation/supported-input-types/examples/search/component.ts
  class InputSearchDocExample (line 33) | class InputSearchDocExample {

FILE: projects/demo/src/pages/documentation/supported-input-types/examples/tel/component.ts
  class InputTelDocExample (line 44) | class InputTelDocExample {

FILE: projects/demo/src/pages/documentation/supported-input-types/examples/text/component.ts
  class InputTextDocExample (line 34) | class InputTextDocExample {

FILE: projects/demo/src/pages/documentation/supported-input-types/examples/url/component.ts
  class InputURLDocExample (line 33) | class InputURLDocExample {

FILE: projects/demo/src/pages/documentation/supported-input-types/supported-input-types.component.ts
  class SupportedInputTypesDocPageComponent (line 27) | class SupportedInputTypesDocPageComponent {
    method getInput (line 58) | protected getInput(type: HTMLInputElement['type']): string {

FILE: projects/demo/src/pages/documentation/transformer/transformer.component.ts
  class TransformerDocPageComponent (line 13) | class TransformerDocPageComponent {

FILE: projects/demo/src/pages/documentation/what-is-maskito/what-is-maskito.component.ts
  class WhatIsMaskitoDocPageComponent (line 25) | class WhatIsMaskitoDocPageComponent {

FILE: projects/demo/src/pages/frameworks/angular/angular-doc.component.ts
  class AngularDocPageComponent (line 33) | class AngularDocPageComponent {

FILE: projects/demo/src/pages/frameworks/angular/examples/1-nested/component.ts
  class NestedDocExample1 (line 13) | class NestedDocExample1 {

FILE: projects/demo/src/pages/frameworks/angular/examples/2-nested/component.ts
  class NestedDocExample2 (line 13) | class NestedDocExample2 {

FILE: projects/demo/src/pages/frameworks/angular/examples/3-programmatically/component.ts
  class ProgrammaticallyDocExample3 (line 12) | class ProgrammaticallyDocExample3 {
    method setValue (line 19) | protected setValue(): void {

FILE: projects/demo/src/pages/frameworks/angular/examples/4-pipe/component.ts
  class PipeDocExample4 (line 11) | class PipeDocExample4 {

FILE: projects/demo/src/pages/frameworks/angular/examples/5-custom-unmask-handler/index.ts
  constant NUMBER_PARAMS (line 13) | const NUMBER_PARAMS: MaskitoNumberParams = {
  class UnmaskDocExample5 (line 25) | class UnmaskDocExample5 {

FILE: projects/demo/src/pages/frameworks/angular/examples/5-custom-unmask-handler/unmask.directive.ts
  class UnmaskDirective (line 11) | class UnmaskDirective implements AfterViewInit {
    method ngAfterViewInit (line 23) | public ngAfterViewInit(): void {

FILE: projects/demo/src/pages/frameworks/angular/examples/6-pattern/component.ts
  class PatternDocExample6 (line 11) | class PatternDocExample6 {

FILE: projects/demo/src/pages/frameworks/react/examples/1-use-maskito-basic-usage/example.component.tsx
  class ReactExample1 (line 15) | class ReactExample1 {
    method constructor (line 16) | constructor() {

FILE: projects/demo/src/pages/frameworks/react/examples/2-element-predicate/example.component.tsx
  class ReactExample2 (line 15) | class ReactExample2 {
    method constructor (line 16) | constructor() {

FILE: projects/demo/src/pages/frameworks/react/react-doc.component.ts
  class ReactDocPageComponent (line 26) | class ReactDocPageComponent {

FILE: projects/demo/src/pages/frameworks/vue/examples/vue-1/component.ts
  class VueExample1 (line 10) | class VueExample1 {

FILE: projects/demo/src/pages/frameworks/vue/vue-doc.component.ts
  class VueDocPageComponent (line 15) | class VueDocPageComponent {

FILE: projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts
  type GeneratorOptions (line 21) | type GeneratorOptions = Required<
  class DateRangeMaskDocComponent (line 42) | class DateRangeMaskDocComponent implements GeneratorOptions {
    method getPlaceholder (line 115) | protected getPlaceholder(
    method updateOptions (line 125) | protected updateOptions(): void {
    method updateDate (line 129) | protected updateDate(): void {

FILE: projects/demo/src/pages/kit/date-range/examples/1-date-localization/component.ts
  class DateRangeMaskDocExample1 (line 36) | class DateRangeMaskDocExample1 {
    method hint (line 47) | protected get hint(): string {

FILE: projects/demo/src/pages/kit/date-range/examples/2-min-max/component.ts
  class DateRangeMaskDocExample2 (line 33) | class DateRangeMaskDocExample2 {

FILE: projects/demo/src/pages/kit/date-range/examples/3-min-max-length/component.ts
  class DateRangeMaskDocExample3 (line 36) | class DateRangeMaskDocExample3 {

FILE: projects/demo/src/pages/kit/date-range/examples/4-range-separator/component.ts
  class DateRangeMaskDocExample4 (line 33) | class DateRangeMaskDocExample4 {

FILE: projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts
  class DateTimeMaskDocComponent (line 42) | class DateTimeMaskDocComponent implements Required<MaskitoDateTimeParams> {
    method getPlaceholder (line 117) | protected getPlaceholder(
    method updateOptions (line 126) | protected updateOptions(): void {
    method updateDate (line 130) | protected updateDate(): void {

FILE: projects/demo/src/pages/kit/date-time/examples/1-date-time-localization/component.ts
  class DateTimeMaskDocExample1 (line 33) | class DateTimeMaskDocExample1 {

FILE: projects/demo/src/pages/kit/date-time/examples/2-date-time-separator/component.ts
  class DateTimeMaskDocExample2 (line 33) | class DateTimeMaskDocExample2 {

FILE: projects/demo/src/pages/kit/date-time/examples/3-min-max/component.ts
  class DateTimeMaskDocExample3 (line 33) | class DateTimeMaskDocExample3 {

FILE: projects/demo/src/pages/kit/date-time/examples/4-time-step/component.ts
  class DateTimeMaskDocExample4 (line 33) | class DateTimeMaskDocExample4 {

FILE: projects/demo/src/pages/kit/date-time/examples/5-am-pm/component.ts
  class DateTimeMaskDocExample5 (line 32) | class DateTimeMaskDocExample5 {

FILE: projects/demo/src/pages/kit/date/date-mask-doc.component.ts
  class DateMaskDocComponent (line 35) | class DateMaskDocComponent implements Required<MaskitoDateParams> {
    method updateDate (line 83) | protected updateDate(): void {
    method updateOptions (line 89) | protected updateOptions(): void {

FILE: projects/demo/src/pages/kit/date/examples/1-localization/component.ts
  class DateMaskDocExample1 (line 33) | class DateMaskDocExample1 {

FILE: projects/demo/src/pages/kit/date/examples/2-min-max/component.ts
  class DateMaskDocExample2 (line 33) | class DateMaskDocExample2 {

FILE: projects/demo/src/pages/kit/number/examples/1-high-precision/component.ts
  class NumberMaskDocExample1 (line 28) | class NumberMaskDocExample1 {

FILE: projects/demo/src/pages/kit/number/examples/2-separators/component.ts
  class NumberMaskDocExample2 (line 27) | class NumberMaskDocExample2 {

FILE: projects/demo/src/pages/kit/number/examples/3-postfix/component.ts
  class NumberMaskDocExample3 (line 31) | class NumberMaskDocExample3 {

FILE: projects/demo/src/pages/kit/number/examples/4-decimal-zero-padding/component.ts
  class NumberMaskDocExample4 (line 26) | class NumberMaskDocExample4 {

FILE: projects/demo/src/pages/kit/number/examples/5-custom-minus-sign/components.ts
  class NumberMaskDocExample5 (line 30) | class NumberMaskDocExample5 {

FILE: projects/demo/src/pages/kit/number/examples/6-minus-before-prefix/components.ts
  class NumberMaskDocExample6 (line 30) | class NumberMaskDocExample6 {

FILE: projects/demo/src/pages/kit/number/examples/7-dynamic-decimal-zero-padding/component.ts
  class NumberMaskDocExample7 (line 44) | class NumberMaskDocExample7 {
    method getMaskOptions (line 49) | protected getMaskOptions(decimalZeroPadding: boolean): MaskitoOptions {
    method handleBeforeInput (line 53) | protected handleBeforeInput(event: Event): void {
    method getNotEmptySelection (line 72) | private getNotEmptySelection(

FILE: projects/demo/src/pages/kit/number/examples/7-dynamic-decimal-zero-padding/mask.ts
  function getMaskitoOptions (line 4) | function getMaskitoOptions(decimalZeroPadding: boolean): MaskitoOptions {

FILE: projects/demo/src/pages/kit/number/examples/8-thousand-separator-pattern/component.ts
  class NumberMaskDocExample8 (line 27) | class NumberMaskDocExample8 {

FILE: projects/demo/src/pages/kit/number/examples/9-thousand-separator-pattern-intl/component.ts
  class NumberMaskDocExample9 (line 27) | class NumberMaskDocExample9 {

FILE: projects/demo/src/pages/kit/number/number-mask-doc.component.ts
  type GeneratorParams (line 28) | type GeneratorParams = Omit<
  class NumberMaskDocComponent (line 57) | class NumberMaskDocComponent implements GeneratorParams {
    method updateOptions (line 199) | protected updateOptions(): void {
    method calculateMask (line 203) | private calculateMask(params: GeneratorParams): MaskitoOptions {

FILE: projects/demo/src/pages/kit/plugins/examples/1-selection-handler/component.ts
  class KitPluginsDocExample1 (line 29) | class KitPluginsDocExample1 {

FILE: projects/demo/src/pages/kit/plugins/examples/2-caret-guard/component.ts
  class KitPluginsDocExample2 (line 26) | class KitPluginsDocExample2 {

FILE: projects/demo/src/pages/kit/plugins/examples/3-event-handlers/component.ts
  class KitPluginsDocExample3 (line 29) | class KitPluginsDocExample3 {

FILE: projects/demo/src/pages/kit/plugins/examples/4-reject/component.ts
  class KitPluginsDocExample4 (line 27) | class KitPluginsDocExample4 {

FILE: projects/demo/src/pages/kit/plugins/kit-plugins-doc.component.ts
  class KitPluginsDocComponent (line 28) | class KitPluginsDocComponent {

FILE: projects/demo/src/pages/kit/time/examples/1-modes/component.ts
  class TimeMaskDocExample1 (line 33) | class TimeMaskDocExample1 {

FILE: projects/demo/src/pages/kit/time/examples/2-am-pm/component.ts
  class TimeMaskDocExample2 (line 32) | class TimeMaskDocExample2 {

FILE: projects/demo/src/pages/kit/time/examples/3-step/component.ts
  class TimeMaskDocExample3 (line 33) | class TimeMaskDocExample3 {

FILE: projects/demo/src/pages/kit/time/examples/4-affixes/component.ts
  class TimeMaskDocExample4 (line 32) | class TimeMaskDocExample4 {

FILE: projects/demo/src/pages/kit/time/examples/5-time-segments-min-max/component.ts
  class TimeMaskDocExample5 (line 33) | class TimeMaskDocExample5 {

FILE: projects/demo/src/pages/kit/time/time-mask-doc.component.ts
  class TimeMaskDocComponent (line 44) | class TimeMaskDocComponent implements Required<MaskitoTimeParams> {
    method updateOptions (line 119) | protected updateOptions(): void {

FILE: projects/demo/src/pages/pages.ts
  constant DEMO_PAGES (line 4) | const DEMO_PAGES: TuiDocRoutePages = [

FILE: projects/demo/src/pages/phone/examples/1-basic/component.ts
  class PhoneMaskDocExample1 (line 33) | class PhoneMaskDocExample1 {

FILE: projects/demo/src/pages/phone/examples/2-validation/component.ts
  function phoneValidator (line 19) | function phoneValidator(countryCode: CountryCode): ValidatorFn {
  class PhoneMaskDocExample2 (line 59) | class PhoneMaskDocExample2 {

FILE: projects/demo/src/pages/phone/examples/3-non-strict/component.ts
  class PhoneMaskDocExample3 (line 49) | class PhoneMaskDocExample3 {
    method countryIsoCode (line 60) | protected get countryIsoCode(): string {

FILE: projects/demo/src/pages/phone/examples/4-lazy-metadata/component.ts
  class PhoneMaskDocExample4 (line 33) | class PhoneMaskDocExample4 implements OnInit {
    method ngOnInit (line 37) | public ngOnInit(): void {

FILE: projects/demo/src/pages/phone/examples/5-focus-blur-events/component.ts
  class PhoneMaskDocExample5 (line 47) | class PhoneMaskDocExample5 {

FILE: projects/demo/src/pages/phone/examples/6-national-format/component.ts
  class PhoneMaskDocExample6 (line 47) | class PhoneMaskDocExample6 {

FILE: projects/demo/src/pages/phone/phone-doc.component.ts
  type GeneratorOptions (line 36) | type GeneratorOptions = Required<Parameters<typeof maskitoPhoneOptionsGe...
  type MetadataName (line 38) | type MetadataName = keyof typeof metadataSets;
  class PhoneDocComponent (line 61) | class PhoneDocComponent implements GeneratorOptions {
    method metadata (line 131) | public get metadata(): MetadataJson {
    method pattern (line 140) | protected get pattern(): string {
    method updateOptions (line 148) | protected updateOptions(): void {
    method computeOptions (line 152) | private computeOptions(): Required<MaskitoOptions> {

FILE: projects/demo/src/pages/recipes/card/card-doc.component.ts
  class CardDocComponent (line 15) | class CardDocComponent {

FILE: projects/demo/src/pages/recipes/card/examples/1-basic/component.ts
  class CardDocExample1 (line 16) | class CardDocExample1 {

FILE: projects/demo/src/pages/recipes/content-editable/content-editable-doc.component.ts
  class ContentEditableDocComponent (line 23) | class ContentEditableDocComponent {

FILE: projects/demo/src/pages/recipes/content-editable/examples/1-time/component.ts
  class ContentEditableDocExample1 (line 23) | class ContentEditableDocExample1 {

FILE: projects/demo/src/pages/recipes/content-editable/examples/2-multi-line/component.ts
  class ContentEditableDocExample2 (line 29) | class ContentEditableDocExample2 {

FILE: projects/demo/src/pages/recipes/network-address/examples/1-ipv6/component.ts
  class NetworkAddressDocExample1 (line 25) | class NetworkAddressDocExample1 {

FILE: projects/demo/src/pages/recipes/network-address/examples/1-ipv6/mask.ts
  constant HEX_GROUP (line 3) | const HEX_GROUP = Array.from({length: 4}, () => /[0-9A-F]/i);

FILE: projects/demo/src/pages/recipes/network-address/examples/2-ipv4/component.ts
  class NetworkAddressDocExample2 (line 26) | class NetworkAddressDocExample2 {

FILE: projects/demo/src/pages/recipes/network-address/examples/2-ipv4/mask.ts
  constant MAX_OCTET_VALUE (line 3) | const MAX_OCTET_VALUE = 255;
  constant MAX_OCTET_LENGTH (line 4) | const MAX_OCTET_LENGTH = 3;
  constant MAX_OCTETS (line 5) | const MAX_OCTETS = 4;
  constant SEPARATOR (line 6) | const SEPARATOR = '.';
  constant DIGIT (line 7) | const DIGIT = /\d/;

FILE: projects/demo/src/pages/recipes/network-address/examples/3-mac/component.ts
  class NetworkAddressDocExample3 (line 25) | class NetworkAddressDocExample3 {

FILE: projects/demo/src/pages/recipes/network-address/examples/3-mac/mask.ts
  constant HEX_GROUP (line 3) | const HEX_GROUP = Array.from({length: 2}, () => /[0-9A-F]/i);

FILE: projects/demo/src/pages/recipes/network-address/network-address-doc.component.ts
  class NetworkAddressDocComponent (line 20) | class NetworkAddressDocComponent {

FILE: projects/demo/src/pages/recipes/phone/examples/1-us-phone/component.ts
  class PhoneUSDocExample1 (line 43) | class PhoneUSDocExample1 {

FILE: projects/demo/src/pages/recipes/phone/examples/2-kz-phone/component.ts
  class PhoneKZDocExample2 (line 14) | class PhoneKZDocExample2 {

FILE: projects/demo/src/pages/recipes/phone/examples/2-kz-phone/mask.ts
  function createCompletePhoneInsertionPreprocessor (line 48) | function createCompletePhoneInsertionPreprocessor(): MaskitoPreprocessor {

FILE: projects/demo/src/pages/recipes/phone/phone-doc.component.ts
  class PhoneDocComponent (line 16) | class PhoneDocComponent {

FILE: projects/demo/src/pages/recipes/placeholder/examples/1-cvc-code/component.ts
  class PlaceholderDocExample1 (line 32) | class PlaceholderDocExample1 {

FILE: projects/demo/src/pages/recipes/placeholder/examples/2-phone/component.ts
  class PlaceholderDocExample2 (line 43) | class PlaceholderDocExample2 {

FILE: projects/demo/src/pages/recipes/placeholder/examples/2-phone/mask.ts
  constant PLACEHOLDER (line 13) | const PLACEHOLDER = '+  (   ) ___-____';

FILE: projects/demo/src/pages/recipes/placeholder/examples/3-date/component.ts
  class PlaceholderDocExample3 (line 32) | class PlaceholderDocExample3 {

FILE: projects/demo/src/pages/recipes/placeholder/examples/3-date/mask.ts
  constant PLACEHOLDER (line 4) | const PLACEHOLDER = 'dd/mm/yyyy';

FILE: projects/demo/src/pages/recipes/placeholder/placeholder-doc.component.ts
  class PlaceholderDocComponent (line 24) | class PlaceholderDocComponent {

FILE: projects/demo/src/pages/recipes/postfix/examples/1-pattern-mask/component.ts
  class PostfixDocExample1 (line 26) | class PostfixDocExample1 {

FILE: projects/demo/src/pages/recipes/postfix/examples/2-postprocessor/component.ts
  class PostfixDocExample2 (line 26) | class PostfixDocExample2 {

FILE: projects/demo/src/pages/recipes/postfix/postfix-doc.component.ts
  class PostfixDocComponent (line 23) | class PostfixDocComponent {

FILE: projects/demo/src/pages/recipes/prefix/examples/1-pattern-mask/component.ts
  class PrefixDocExample1 (line 26) | class PrefixDocExample1 {

FILE: projects/demo/src/pages/recipes/prefix/examples/2-postprocessor/component.ts
  class PrefixDocExample2 (line 26) | class PrefixDocExample2 {

FILE: projects/demo/src/pages/recipes/prefix/prefix-doc.component.ts
  class PrefixDocComponent (line 23) | class PrefixDocComponent {

FILE: projects/demo/src/pages/recipes/textarea/examples/1-latin/component.ts
  class TextareaDocExample1 (line 24) | class TextareaDocExample1 {

FILE: projects/demo/src/pages/recipes/textarea/textarea-doc.component.ts
  class TextareaDocComponent (line 15) | class TextareaDocComponent {

FILE: projects/demo/src/pages/stackblitz/components/stackblitz-edit-button/stackblitz-edit-button.component.ts
  class StackblitzEditButtonComponent (line 22) | class StackblitzEditButtonComponent {}

FILE: projects/demo/src/pages/stackblitz/components/stackblitz-starter/stackblitz-starter.component.ts
  class StackblitzStarterComponent (line 29) | class StackblitzStarterComponent implements OnInit {
    method ngOnInit (line 33) | public ngOnInit(): void {
    method openStackblitz (line 39) | protected async openStackblitz(): Promise<void> {

FILE: projects/demo/src/pages/stackblitz/stackblitz.service.ts
  class StackblitzService (line 15) | class StackblitzService implements TuiCodeEditor {
    method edit (line 29) | public async edit(
    method openStarter (line 58) | public openStarter(

FILE: projects/kit/src/lib/constants/date-segment-max-values.ts
  constant DATE_SEGMENTS_MAX_VALUES (line 3) | const DATE_SEGMENTS_MAX_VALUES: MaskitoDateSegments<number> = {

FILE: projects/kit/src/lib/constants/default-decimal-pseudo-separators.ts
  constant DEFAULT_DECIMAL_PSEUDO_SEPARATORS (line 1) | const DEFAULT_DECIMAL_PSEUDO_SEPARATORS = ['.', ',', 'б', 'ю'];

FILE: projects/kit/src/lib/constants/default-min-max-dates.ts
  constant DEFAULT_MIN_DATE (line 1) | const DEFAULT_MIN_DATE = new Date('0001-01-01T00:00');
  constant DEFAULT_MAX_DATE (line 2) | const DEFAULT_MAX_DATE = new Date('9999-12-31T23:59:59.999');

FILE: projects/kit/src/lib/constants/default-pseudo-minuses.ts
  constant DEFAULT_PSEUDO_MINUSES (line 9) | const DEFAULT_PSEUDO_MINUSES = [

FILE: projects/kit/src/lib/constants/default-time-segment-bounds.ts
  constant DEFAULT_TIME_SEGMENT_MAX_VALUES (line 3) | const DEFAULT_TIME_SEGMENT_MAX_VALUES: MaskitoTimeSegments<number> = {
  constant DEFAULT_TIME_SEGMENT_MIN_VALUES (line 10) | const DEFAULT_TIME_SEGMENT_MIN_VALUES: MaskitoTimeSegments<number> = {

FILE: projects/kit/src/lib/constants/meridiem.ts
  constant ANY_MERIDIEM_CHARACTER_RE (line 3) | const ANY_MERIDIEM_CHARACTER_RE = new RegExp(`[${CHAR_NO_BREAK_SPACE}APM...
  constant ALL_MERIDIEM_CHARACTERS_RE (line 4) | const ALL_MERIDIEM_CHARACTERS_RE = new RegExp(`${CHAR_NO_BREAK_SPACE}[AP...

FILE: projects/kit/src/lib/constants/time-fixed-characters.ts
  constant TIME_FIXED_CHARACTERS (line 1) | const TIME_FIXED_CHARACTERS = [':', '.'];

FILE: projects/kit/src/lib/constants/time-segment-value-lengths.ts
  constant TIME_SEGMENT_VALUE_LENGTHS (line 3) | const TIME_SEGMENT_VALUE_LENGTHS: MaskitoTimeSegments<number> = {

FILE: projects/kit/src/lib/constants/unicode-characters.ts
  constant CHAR_NO_BREAK_SPACE (line 4) | const CHAR_NO_BREAK_SPACE = '\u00A0';
  constant CHAR_ZERO_WIDTH_SPACE (line 9) | const CHAR_ZERO_WIDTH_SPACE = '\u200B';
  constant CHAR_EN_DASH (line 16) | const CHAR_EN_DASH = '\u2013';
  constant CHAR_EM_DASH (line 25) | const CHAR_EM_DASH = '\u2014';
  constant CHAR_HYPHEN (line 34) | const CHAR_HYPHEN = '\u002D';
  constant CHAR_MINUS (line 42) | const CHAR_MINUS = '\u2212';
  constant CHAR_JP_HYPHEN (line 48) | const CHAR_JP_HYPHEN = '\u30FC';
  constant CHAR_COLON (line 56) | const CHAR_COLON = '\u003A';
  constant CHAR_JP_COLON (line 62) | const CHAR_JP_COLON = '\uFF1A';

FILE: projects/kit/src/lib/masks/date-range/constants.ts
  constant POSSIBLE_DATE_RANGE_SEPARATOR (line 9) | const POSSIBLE_DATE_RANGE_SEPARATOR = [
  constant MIN_DAY (line 17) | const MIN_DAY = 1;
  constant MONTHS_IN_YEAR (line 19) | const MONTHS_IN_YEAR = 12;

FILE: projects/kit/src/lib/masks/date-range/date-range-mask.ts
  function maskitoDateRangeOptionsGenerator (line 19) | function maskitoDateRangeOptionsGenerator({

FILE: projects/kit/src/lib/masks/date-range/processors/min-max-range-length-postprocessor.ts
  function createMinMaxRangeLengthPostprocessor (line 18) | function createMinMaxRangeLengthPostprocessor({

FILE: projects/kit/src/lib/masks/date-range/processors/swap-dates-postprocessor.ts
  function createSwapDatesPostprocessor (line 10) | function createSwapDatesPostprocessor({

FILE: projects/kit/src/lib/masks/date-time/constants/date-time-separator.ts
  constant DATE_TIME_SEPARATOR (line 1) | const DATE_TIME_SEPARATOR = ', ';
  constant POSSIBLE_DATE_TIME_SEPARATOR (line 2) | const POSSIBLE_DATE_TIME_SEPARATOR = [',', ' '];

FILE: projects/kit/src/lib/masks/date-time/date-time-mask.ts
  function maskitoDateTimeOptionsGenerator (line 30) | function maskitoDateTimeOptionsGenerator({

FILE: projects/kit/src/lib/masks/date-time/date-time-params.ts
  type MaskitoDateTimeParams (line 3) | interface MaskitoDateTimeParams {

FILE: projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts
  function createMinMaxDateTimePostprocessor (line 17) | function createMinMaxDateTimePostprocessor({

FILE: projects/kit/src/lib/masks/date-time/preprocessors/valid-date-time-preprocessor.ts
  function createValidDateTimePreprocessor (line 8) | function createValidDateTimePreprocessor({

FILE: projects/kit/src/lib/masks/date-time/utils/is-date-time-string-complete.ts
  function isDateTimeStringComplete (line 4) | function isDateTimeStringComplete(

FILE: projects/kit/src/lib/masks/date-time/utils/parse-date-time.ts
  function maskitoParseDateTime (line 8) | function maskitoParseDateTime(

FILE: projects/kit/src/lib/masks/date-time/utils/split-date-time-string.ts
  constant NON_DIGIT_PLACEHOLDER_RE (line 1) | const NON_DIGIT_PLACEHOLDER_RE = /[^dmy]/g;
  constant LEADING_NON_DIGIT_RE (line 2) | const LEADING_NON_DIGIT_RE = /^\D*/;
  function splitDateTimeString (line 4) | function splitDateTimeString(

FILE: projects/kit/src/lib/masks/date-time/utils/stringify-date-time.ts
  function maskitoStringifyDateTime (line 8) | function maskitoStringifyDateTime(

FILE: projects/kit/src/lib/masks/date/date-mask.ts
  function maskitoDateOptionsGenerator (line 13) | function maskitoDateOptionsGenerator({

FILE: projects/kit/src/lib/masks/date/date-params.ts
  type MaskitoDateParams (line 3) | interface MaskitoDateParams {

FILE: projects/kit/src/lib/masks/date/utils/parse-date.ts
  function maskitoParseDate (line 5) | function maskitoParseDate(

FILE: projects/kit/src/lib/masks/date/utils/stringify-date.ts
  function maskitoStringifyDate (line 6) | function maskitoStringifyDate(

FILE: projects/kit/src/lib/masks/date/utils/to-date-segments.ts
  function toDateSegments (line 9) | function toDateSegments(date: Date): MaskitoDateSegments {

FILE: projects/kit/src/lib/masks/number/number-mask.ts
  function maskitoNumberOptionsGenerator (line 30) | function maskitoNumberOptionsGenerator(

FILE: projects/kit/src/lib/masks/number/number-params.ts
  type MaskitoNumberParams (line 1) | interface MaskitoNumberParams extends Pick<

FILE: projects/kit/src/lib/masks/number/plugins/leading-zeroes-validation.plugin.ts
  constant DUMMY_SELECTION (line 7) | const DUMMY_SELECTION = [0, 0] as const;
  function createLeadingZeroesValidationPlugin (line 14) | function createLeadingZeroesValidationPlugin(

FILE: projects/kit/src/lib/masks/number/plugins/min-max.plugin.ts
  function createMinMaxPlugin (line 12) | function createMinMaxPlugin(params: Required<MaskitoNumberParams>): Mask...

FILE: projects/kit/src/lib/masks/number/plugins/not-empty-integer.plugin.ts
  function createNotEmptyIntegerPlugin (line 13) | function createNotEmptyIntegerPlugin(

FILE: projects/kit/src/lib/masks/number/processors/affixes-filter-preprocessor.ts
  function createAffixesFilterPreprocessor (line 11) | function createAffixesFilterPreprocessor(

FILE: projects/kit/src/lib/masks/number/processors/decimal-zero-padding-postprocessor.ts
  function createDecimalZeroPaddingPostprocessor (line 12) | function createDecimalZeroPaddingPostprocessor(

FILE: projects/kit/src/lib/masks/number/processors/empty-postprocessor.ts
  function emptyPostprocessor (line 12) | function emptyPostprocessor(

FILE: projects/kit/src/lib/masks/number/processors/initialization-only-preprocessor.ts
  function createInitializationOnlyPreprocessor (line 16) | function createInitializationOnlyPreprocessor(

FILE: projects/kit/src/lib/masks/number/processors/leading-minus-deletion-preprocessor.ts
  function createLeadingMinusDeletionPreprocessor (line 11) | function createLeadingMinusDeletionPreprocessor(

FILE: projects/kit/src/lib/masks/number/processors/leading-zeroes-validation-postprocessor.ts
  function createLeadingZeroesValidationPostprocessor (line 14) | function createLeadingZeroesValidationPostprocessor(

FILE: projects/kit/src/lib/masks/number/processors/min-max-postprocessor.ts
  function createMinMaxPostprocessor (line 12) | function createMinMaxPostprocessor(

FILE: projects/kit/src/lib/masks/number/processors/non-removable-chars-deletion-preprocessor.ts
  function createNonRemovableCharsDeletionPreprocessor (line 12) | function createNonRemovableCharsDeletionPreprocessor({

FILE: projects/kit/src/lib/masks/number/processors/not-empty-integer-part-preprocessor.ts
  function createNotEmptyIntegerPartPreprocessor (line 11) | function createNotEmptyIntegerPartPreprocessor(

FILE: projects/kit/src/lib/masks/number/processors/number-prefix-postprocessor.ts
  function createNumberPrefixPostprocessor (line 6) | function createNumberPrefixPostprocessor({

FILE: projects/kit/src/lib/masks/number/processors/pseudo-character-preprocessor.ts
  function createPseudoCharactersPreprocessor (line 11) | function createPseudoCharactersPreprocessor({

FILE: projects/kit/src/lib/masks/number/processors/repeated-decimal-separator-preprocessor.ts
  function createRepeatedDecimalSeparatorPreprocessor (line 12) | function createRepeatedDecimalSeparatorPreprocessor(

FILE: projects/kit/src/lib/masks/number/processors/tests/leading-zeroes-validation-postprocessor.spec.ts
  constant DEFAULT_PARAMS (line 7) | const DEFAULT_PARAMS = {

FILE: projects/kit/src/lib/masks/number/processors/tests/not-empty-integer-part-preprocessor.spec.ts
  constant EMPTY_ELEMENT_STATE (line 6) | const EMPTY_ELEMENT_STATE = {
  constant DEFAULT_PARAMS (line 11) | const DEFAULT_PARAMS = {

FILE: projects/kit/src/lib/masks/number/processors/thousand-separator-postprocessor.ts
  constant SPACE_REG (line 7) | const SPACE_REG = /\s/;
  constant SPACE_GLOBAL_REG (line 8) | const SPACE_GLOBAL_REG = /\s/g;
  function createThousandSeparatorPostprocessor (line 14) | function createThousandSeparatorPostprocessor(

FILE: projects/kit/src/lib/masks/number/processors/zero-precision-preprocessor.ts
  function createZeroPrecisionPreprocessor (line 11) | function createZeroPrecisionPreprocessor(

FILE: projects/kit/src/lib/masks/number/utils/extract-affixes.ts
  function extractAffixes (line 4) | function extractAffixes(

FILE: projects/kit/src/lib/masks/number/utils/generate-mask-expression.ts
  function generateMaskExpression (line 6) | function generateMaskExpression({
  function computeAllOptionalCharsRegExp (line 53) | function computeAllOptionalCharsRegExp(str: string): string {

FILE: projects/kit/src/lib/masks/number/utils/number-parts.ts
  type NumberParts (line 5) | interface NumberParts {
  function toNumberParts (line 14) | function toNumberParts(
  function fromNumberParts (line 58) | function fromNumberParts(

FILE: projects/kit/src/lib/masks/number/utils/parse-number.ts
  function maskitoParseNumber (line 21) | function maskitoParseNumber(

FILE: projects/kit/src/lib/masks/number/utils/stringify-number-without-exp.ts
  constant LOCALE (line 4) | const LOCALE: Intl.Locale[] = [];
  constant DEFAULT (line 5) | const DEFAULT = {
  function stringifyNumberWithoutExp (line 41) | function stringifyNumberWithoutExp(value: bigint | number): string {

FILE: projects/kit/src/lib/masks/number/utils/stringify-number.ts
  function maskitoStringifyNumber (line 9) | function maskitoStringifyNumber(

FILE: projects/kit/src/lib/masks/number/utils/tests/to-number-parts.spec.ts
  constant DEFAULT_PARAMS (line 14) | const DEFAULT_PARAMS = {

FILE: projects/kit/src/lib/masks/number/utils/validate-decimal-pseudo-separators.ts
  function validateDecimalPseudoSeparators (line 3) | function validateDecimalPseudoSeparators({

FILE: projects/kit/src/lib/masks/number/utils/with-number-defaults.ts
  function withNumberDefaults (line 10) | function withNumberDefaults({

FILE: projects/kit/src/lib/masks/time/time-mask.ts
  function maskitoTimeOptionsGenerator (line 25) | function maskitoTimeOptionsGenerator({
  function cutExpression (line 98) | function cutExpression(

FILE: projects/kit/src/lib/masks/time/time-params.ts
  type MaskitoTimeParams (line 3) | interface MaskitoTimeParams {

FILE: projects/kit/src/lib/masks/time/utils/parse-time.ts
  function maskitoParseTime (line 12) | function maskitoParseTime(

FILE: projects/kit/src/lib/masks/time/utils/stringify-time.ts
  function maskitoStringifyTime (line 12) | function maskitoStringifyTime(

FILE: projects/kit/src/lib/plugins/add-on-focus.ts
  function maskitoAddOnFocusPlugin (line 5) | function maskitoAddOnFocusPlugin(value: string): MaskitoPlugin {

FILE: projects/kit/src/lib/plugins/caret-guard.ts
  function maskitoCaretGuard (line 6) | function maskitoCaretGuard(

FILE: projects/kit/src/lib/plugins/event-handler.ts
  function maskitoEventHandler (line 3) | function maskitoEventHandler(

FILE: projects/kit/src/lib/plugins/remove-on-blur.ts
  function maskitoRemoveOnBlurPlugin (line 5) | function maskitoRemoveOnBlurPlugin(value: string): MaskitoPlugin {

FILE: projects/kit/src/lib/plugins/selection-change.ts
  function maskitoSelectionChangeHandler (line 3) | function maskitoSelectionChangeHandler(

FILE: projects/kit/src/lib/plugins/time/meridiem-stepping.ts
  function createMeridiemSteppingPlugin (line 6) | function createMeridiemSteppingPlugin(meridiemStartIndex: number): Maski...

FILE: projects/kit/src/lib/plugins/time/time-segments-stepping.ts
  function createTimeSegmentsSteppingPlugin (line 6) | function createTimeSegmentsSteppingPlugin({
  function createTimeSegmentsIndexes (line 58) | function createTimeSegmentsIndexes(
  function getSegmentRange (line 69) | function getSegmentRange(mode: string, segment: string): [number, number] {
  function getActiveSegment (line 75) | function getActiveSegment({
  function updateSegmentValue (line 93) | function updateSegmentValue({
  function mod (line 113) | function mod(value: number, min: number, max: number): number {

FILE: projects/kit/src/lib/processors/colon-convert-preprocessor.ts
  function createColonConvertPreprocessor (line 8) | function createColonConvertPreprocessor(): MaskitoPreprocessor {

FILE: projects/kit/src/lib/processors/date-segments-zero-padding-postprocessor.ts
  function createDateSegmentsZeroPaddingPostprocessor (line 7) | function createDateSegmentsZeroPaddingPostprocessor({

FILE: projects/kit/src/lib/processors/first-date-end-separator-preprocessor.ts
  function createFirstDateEndSeparatorPreprocessor (line 10) | function createFirstDateEndSeparatorPreprocessor({

FILE: projects/kit/src/lib/processors/fullwidth-to-halfwidth-preprocessor.ts
  function createFullWidthToHalfWidthPreprocessor (line 8) | function createFullWidthToHalfWidthPreprocessor(): MaskitoPreprocessor {

FILE: projects/kit/src/lib/processors/invalid-time-segment-insertion-preprocessor.ts
  function createInvalidTimeSegmentInsertionPreprocessor (line 18) | function createInvalidTimeSegmentInsertionPreprocessor({

FILE: projects/kit/src/lib/processors/meridiem-processors.ts
  function createMeridiemPreprocessor (line 11) | function createMeridiemPreprocessor(
  function createMeridiemPostprocessor (line 42) | function createMeridiemPostprocessor(

FILE: projects/kit/src/lib/processors/min-max-date-postprocessor.ts
  constant LEAP_YEAR (line 15) | const LEAP_YEAR = '1972';
  function createMinMaxDatePostprocessor (line 17) | function createMinMaxDatePostprocessor({

FILE: projects/kit/src/lib/processors/normalize-date-preprocessor.ts
  function normalizeDatePreprocessor (line 5) | function normalizeDatePreprocessor({

FILE: projects/kit/src/lib/processors/postfix-postprocessor.ts
  function maskitoPostfixPostprocessorGenerator (line 5) | function maskitoPostfixPostprocessorGenerator(

FILE: projects/kit/src/lib/processors/prefix-postprocessor.ts
  function maskitoPrefixPostprocessorGenerator (line 5) | function maskitoPrefixPostprocessorGenerator(

FILE: projects/kit/src/lib/processors/tests/normalize-date-preprocessor.spec.ts
  function getCheckFunction (line 112) | function getCheckFunction(

FILE: projects/kit/src/lib/processors/tests/prefix-postprocessor.spec.ts
  type ElementState (line 6) | type ElementState = ReturnType<MaskitoPostprocessor>;

FILE: projects/kit/src/lib/processors/valid-date-preprocessor.ts
  function createValidDatePreprocessor (line 5) | function createValidDatePreprocessor({

FILE: projects/kit/src/lib/processors/with-placeholder.ts
  function maskitoWithPlaceholder (line 9) | function maskitoWithPlaceholder(

FILE: projects/kit/src/lib/processors/zero-placeholders-preprocessor.ts
  function createZeroPlaceholdersPreprocessor (line 3) | function createZeroPlaceholdersPreprocessor(postfix = ''): MaskitoPrepro...

FILE: projects/kit/src/lib/types/date-mode.ts
  type MaskitoDateMode (line 1) | type MaskitoDateMode =

FILE: projects/kit/src/lib/types/date-segments.ts
  type MaskitoDateSegments (line 1) | interface MaskitoDateSegments<T = string> {

FILE: projects/kit/src/lib/types/time-mode.ts
  type MaskitoTimeMode (line 1) | type MaskitoTimeMode =

FILE: projects/kit/src/lib/types/time-segments.ts
  type MaskitoTimeSegments (line 1) | interface MaskitoTimeSegments<T = string> {

FILE: projects/kit/src/lib/utils/clamp.ts
  function clamp (line 4) | function clamp<T extends Date | bigint | number>(
  function min (line 14) | function min<T extends Date | bigint | number>(x: T, ...values: T[]): T {
  function max (line 18) | function max<T extends Date | bigint | number>(x: T, ...values: T[]): T {

FILE: projects/kit/src/lib/utils/count-digits.ts
  function countDigits (line 1) | function countDigits(str: string): number {

FILE: projects/kit/src/lib/utils/date/append-date.ts
  function appendDate (line 4) | function appendDate(
  function getMonthDaysCount (line 65) | function getMonthDaysCount(month: number, isLeapYear: boolean): number {
  function isLeapYear (line 79) | function isLeapYear(year: number): boolean {

FILE: projects/kit/src/lib/utils/date/date-to-segments.ts
  function dateToSegments (line 3) | function dateToSegments(date: Date): MaskitoDateSegments & MaskitoTimeSe...

FILE: projects/kit/src/lib/utils/date/get-date-segments-order.ts
  constant ALL_POSSIBLE_SEGMENTS (line 3) | const ALL_POSSIBLE_SEGMENTS: ReadonlyArray<keyof MaskitoDateSegments> = [
  function getDateSegmentsOrder (line 9) | function getDateSegmentsOrder(

FILE: projects/kit/src/lib/utils/date/get-first-complete-date.ts
  function getFirstCompleteDate (line 3) | function getFirstCompleteDate(

FILE: projects/kit/src/lib/utils/date/is-date-string-complete.ts
  function isDateStringComplete (line 1) | function isDateStringComplete(

FILE: projects/kit/src/lib/utils/date/parse-date-range-string.ts
  function parseDateRangeString (line 3) | function parseDateRangeString(

FILE: projects/kit/src/lib/utils/date/parse-date-string.ts
  function parseDateString (line 3) | function parseDateString(

FILE: projects/kit/src/lib/utils/date/raise-segment-value-to-min.ts
  function raiseSegmentValueToMin (line 4) | function raiseSegmentValueToMin(

FILE: projects/kit/src/lib/utils/date/segments-to-date.ts
  function segmentsToDate (line 3) | function segmentsToDate(

FILE: projects/kit/src/lib/utils/date/to-date-string.ts
  function toDateString (line 18) | function toDateString(

FILE: projects/kit/src/lib/utils/date/validate-date-string.ts
  function validateDateString (line 8) | function validateDateString({

FILE: projects/kit/src/lib/utils/dummy.ts
  function identity (line 1) | function identity<T>(x: T): T {
  function noop (line 6) | function noop(): void {}

FILE: projects/kit/src/lib/utils/escape-reg-exp.ts
  function escapeRegExp (line 9) | function escapeRegExp(str: string): string {

FILE: projects/kit/src/lib/utils/find-common-beginning-substr.ts
  function findCommonBeginningSubstr (line 1) | function findCommonBeginningSubstr(a: string, b: string): string {

FILE: projects/kit/src/lib/utils/is-empty.ts
  function isEmpty (line 1) | function isEmpty(entity?: object | null): boolean {

FILE: projects/kit/src/lib/utils/pad-with-zeroes-until-valid.ts
  constant ALL_ZEROES_RE (line 1) | const ALL_ZEROES_RE = /^0+$/;
  function padWithZeroesUntilValid (line 3) | function padWithZeroesUntilValid(

FILE: projects/kit/src/lib/utils/time/create-time-mask-expression.ts
  function createTimeMaskExpression (line 4) | function createTimeMaskExpression(mode: MaskitoTimeMode): Array<RegExp |...

FILE: projects/kit/src/lib/utils/time/enrich-time-segments-with-zeroes.ts
  constant TRAILING_TIME_SEGMENT_SEPARATOR_REG (line 9) | const TRAILING_TIME_SEGMENT_SEPARATOR_REG = new RegExp(
  function enrichTimeSegmentsWithZeroes (line 18) | function enrichTimeSegmentsWithZeroes(

FILE: projects/kit/src/lib/utils/time/pad-end-time-segments.ts
  function padEndTimeSegments (line 12) | function padEndTimeSegments(

FILE: projects/kit/src/lib/utils/time/pad-start-time-segments.ts
  function padStartTimeSegments (line 12) | function padStartTimeSegments(

FILE: projects/kit/src/lib/utils/time/pad-time-segments.ts
  function padTimeSegments (line 14) | function padTimeSegments(

FILE: projects/kit/src/lib/utils/time/parse-time-string.ts
  constant SEGMENT_FULL_NAME (line 3) | const SEGMENT_FULL_NAME: Record<string, keyof MaskitoTimeSegments> = {
  function parseTimeString (line 13) | function parseTimeString(

FILE: projects/kit/src/lib/utils/time/to-time-string.ts
  constant LEADING_NON_DIGITS (line 3) | const LEADING_NON_DIGITS = /^\D*/;
  constant TRAILING_NON_DIGITS (line 4) | const TRAILING_NON_DIGITS = /\D*$/;
  function toTimeString (line 6) | function toTimeString({

FILE: projects/kit/src/lib/utils/to-half-width-colon.ts
  function toHalfWidthColon (line 8) | function toHalfWidthColon(fullWidthColon: string): string {

FILE: projects/kit/src/lib/utils/to-half-width-number.ts
  function toHalfWidthNumber (line 6) | function toHalfWidthNumber(fullWidthNumber: string): string {

FILE: projects/phone/src/lib/masks/phone/constants/template-filler.ts
  constant TEMPLATE_FILLER (line 1) | const TEMPLATE_FILLER = 'x';

FILE: projects/phone/src/lib/masks/phone/phone-mask-non-strict.ts
  function maskitoPhoneNonStrictOptionsGenerator (line 12) | function maskitoPhoneNonStrictOptionsGenerator({

FILE: projects/phone/src/lib/masks/phone/phone-mask-strict.ts
  function maskitoPhoneStrictOptionsGenerator (line 15) | function maskitoPhoneStrictOptionsGenerator({

FILE: projects/phone/src/lib/masks/phone/phone-mask.ts
  type MaskitoPhoneParams (line 7) | interface MaskitoPhoneParams {
  function maskitoPhoneOptionsGenerator (line 21) | function maskitoPhoneOptionsGenerator({

FILE: projects/phone/src/lib/masks/phone/processors/browser-autofill-preprocessor.ts
  function extractNumberValue (line 12) | function extractNumberValue(
  function convertToNationalFormat (line 31) | function convertToNationalFormat(
  function browserAutofillPreprocessorGenerator (line 55) | function browserAutofillPreprocessorGenerator({

FILE: projects/phone/src/lib/masks/phone/processors/cut-init-country-code-preprocessor.ts
  function cutInitCountryCodePreprocessor (line 14) | function cutInitCountryCodePreprocessor({

FILE: projects/phone/src/lib/masks/phone/processors/paste-non-strict-phone-preprocessor.ts
  function parsePhone (line 11) | function parsePhone({
  function pasteNonStrictPhonePreprocessorGenerator (line 33) | function pasteNonStrictPhonePreprocessorGenerator({

FILE: projects/phone/src/lib/masks/phone/processors/paste-strict-phone-preprocessor.ts
  function pasteStrictPhonePreprocessorGenerator (line 6) | function pasteStrictPhonePreprocessorGenerator({

FILE: projects/phone/src/lib/masks/phone/processors/phone-length-postprocessor.ts
  constant MIN_LENGTH (line 6) | const MIN_LENGTH = 3;
  function phoneLengthPostprocessorGenerator (line 7) | function phoneLengthPostprocessorGenerator(

FILE: projects/phone/src/lib/masks/phone/utils/cut-phone-by-valid-length.ts
  function cutPhoneByValidLength (line 3) | function cutPhoneByValidLength({

FILE: projects/phone/src/lib/masks/phone/utils/generate-phone-mask.ts
  function generatePhoneMask (line 5) | function generatePhoneMask({

FILE: projects/phone/src/lib/masks/phone/utils/get-country-from-number.ts
  function maskitoGetCountryFromNumber (line 3) | function maskitoGetCountryFromNumber(

FILE: projects/phone/src/lib/masks/phone/utils/get-phone-template.ts
  function getPhoneTemplate (line 10) | function getPhoneTemplate({
  function getInternationalPhoneTemplate (line 43) | function getInternationalPhoneTemplate({
  function getNationalPhoneTemplate (line 75) | function getNationalPhoneTemplate({

FILE: projects/phone/src/lib/masks/phone/utils/select-template.ts
  function selectTemplate (line 1) | function selectTemplate({

FILE: projects/react/src/lib/adaptControlledElement.tsx
  function adaptReactControlledElement (line 18) | function adaptReactControlledElement(element: MaskitoElement): MaskitoEl...
  function getPrototype (line 47) | function getPrototype(element: MaskitoElement): HTMLInputElement | HTMLT...

FILE: projects/react/src/lib/tests/controlledInput.spec.tsx
  function TestComponent (line 14) | function TestComponent({
  function App (line 85) | function App(): JSX.Element {
  function App (line 165) | function App(): JSX.Element {

FILE: projects/react/src/lib/tests/elementPredicate.spec.tsx
  function TestComponent (line 23) | function TestComponent({elementPredicate = predicate}): JSX.Element {

FILE: projects/react/src/lib/tests/useMaskito.spec.tsx
  function TestComponent (line 27) | function TestComponent({onChangeHandler}: Readonly<{onChangeHandler?: (v...
  function ConditionalInputComponent (line 38) | function ConditionalInputComponent({showInput}: Readonly<{showInput: boo...

FILE: projects/react/src/lib/useMaskito.tsx
  function isThenable (line 13) | function isThenable<T = unknown>(x: PromiseLike<T> | T): x is PromiseLik...

FILE: projects/vue/src/lib/maskito.ts
  function update (line 12) | async function update(
Condensed preview — 757 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,832K chars).
[
  {
    "path": ".cspell.json",
    "chars": 581,
    "preview": "{\n    \"$schema\": \"https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json\",\n    \"import\": "
  },
  {
    "path": ".editorconfig",
    "chars": 246,
    "preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
  },
  {
    "path": ".firebaserc",
    "chars": 49,
    "preview": "{\n  \"projects\": {\n    \"default\": \"maskito\"\n  }\n}\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 26,
    "preview": "* @taiga-family/core-team\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "chars": 3344,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 1327,
    "preview": "# Contributing\n\n> Thank you for considering contributing to our project. Your help if very welcome!\n\nWhen contributing, "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1-bug-report.yml",
    "chars": 2180,
    "preview": "name: '🐞 - Bug Report'\ntitle: '🐞 - '\ndescription: Report a bug in the Maskito\nlabels: ['bug']\ntype: Bug\n\nbody:\n  - type:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/2-feature-request.yml",
    "chars": 687,
    "preview": "name: '🚀 - Feature Request'\ntitle: '🚀 - '\ndescription: Suggest a feature for Maskito\nlabels: ['feature']\ntype: Feature\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/3-documentation.yml",
    "chars": 1077,
    "preview": "name: '📚 - Documentation'\ntitle: '📚 - '\ndescription: Report an issue in Maskito's documentation\nlabels: ['documentation'"
  },
  {
    "path": ".github/renovate.json",
    "chars": 443,
    "preview": "{\n    \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n    \"extends\": [\"github>taiga-family/renovate-conf"
  },
  {
    "path": ".github/workflows/assign-author.yml",
    "chars": 402,
    "preview": "name: 🤖 PR author as an assignee\non:\n  pull_request:\n    types: [opened]\n\njobs:\n  assign:\n    runs-on: ubuntu-latest\n   "
  },
  {
    "path": ".github/workflows/auto-merge.yml",
    "chars": 1446,
    "preview": "name: 🤖 PR auto merge\non:\n  pull_request:\n\nenv:\n  PR_JOBS_NAME: '[ \"Packages\", \"Demo\", \"Firebase\", \"Lint result\", \"tests"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 720,
    "preview": "name: Build\non:\n  pull_request:\n  push:\n    branches: [main]\n\njobs:\n  build-packages:\n    name: Packages\n    runs-on: ub"
  },
  {
    "path": ".github/workflows/deploy-preview.yml",
    "chars": 888,
    "preview": "name: Deploy / preview\n\non: pull_request\n\njobs:\n  build_and_preview:\n    name: Firebase\n    runs-on: ubuntu-latest\n    s"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "chars": 708,
    "preview": "name: Deploy\non:\n  workflow_dispatch:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    if: $"
  },
  {
    "path": ".github/workflows/e2e.yml",
    "chars": 4368,
    "preview": "name: E2E\non: [pull_request]\n\nenv:\n  CACHE_DIST_KEY: dist-${{ github.ref }}-${{ github.sha }}\n  CYPRESS_CACHE_FOLDER: ./"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 2211,
    "preview": "name: Lint\non: [pull_request]\n\njobs:\n  typecheck:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1372,
    "preview": "name: ⚠️ Release\n\non:\n  workflow_dispatch:\n    inputs:\n      mode:\n        type: choice\n        description: Bump versio"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1933,
    "preview": "name: Tests\n\non:\n  pull_request:\n  push:\n    branches:\n      - main\n\njobs:\n  tests:\n    runs-on: ubuntu-latest\n    steps"
  },
  {
    "path": ".gitignore",
    "chars": 761,
    "preview": "# compiled output\n/dist\n/tmp\n/out-tsc\n# Only exists if Bazel was run\n/bazel-out\n\n# dependencies\n**/node_modules/\n\n# prof"
  },
  {
    "path": ".husky/commit-msg",
    "chars": 33,
    "preview": "npx --no -- commitlint --edit $1\n"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 34,
    "preview": "npx lint-staged\nnpm run typecheck\n"
  },
  {
    "path": ".npmrc",
    "chars": 34,
    "preview": "engine-strict=true\nloglevel=error\n"
  },
  {
    "path": ".release-it.js",
    "chars": 57,
    "preview": "module.exports = require('@taiga-ui/release-it-config');\n"
  },
  {
    "path": ".ws-context",
    "chars": 153,
    "preview": "{\n    \"framework\": \"angular\",\n    \"projects/vue/**\": {\n        \"framework\": \"vue\"\n    },\n    \"projects/react/**\": {\n    "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 57534,
    "preview": "### [5.2.2](https://github.com/taiga-family/maskito/compare/v5.2.1...v5.2.2) (2026-03-31)\n\n### 🐞 Bug Fixes\n\n- **kit**: `"
  },
  {
    "path": "LICENSE",
    "chars": 10750,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 3803,
    "preview": "# Maskito\n\n[![npm version](https://img.shields.io/npm/v/@maskito/core.svg)](https://npmjs.com/package/@maskito/core)\n[!["
  },
  {
    "path": "codecov.yml",
    "chars": 500,
    "preview": "codecov:\n  branch: main\n  notify:\n    require_ci_to_pass: no\n\ncoverage:\n  # This value is used to customize the visible "
  },
  {
    "path": "eslint.config.ts",
    "chars": 1776,
    "preview": "import taiga from '@taiga-ui/eslint-plugin-experience-next';\n\nexport default [\n    ...taiga.configs.recommended,\n    {\n "
  },
  {
    "path": "firebase.json",
    "chars": 271,
    "preview": "{\n    \"hosting\": {\n        \"public\": \"dist/demo/browser\",\n        \"ignore\": [\"firebase.json\", \"**/.*\", \"**/node_modules/"
  },
  {
    "path": "jest.config.ts",
    "chars": 170,
    "preview": "import {getJestProjectsAsync} from '@nx/jest';\nimport type {Config} from 'jest';\n\nexport default async (): Promise<Confi"
  },
  {
    "path": "jest.preset.js",
    "chars": 448,
    "preview": "const nxPreset = require('@nx/jest/preset').default;\nconst {resolve} = require('node:path');\n\nmodule.exports = {\n    ..."
  },
  {
    "path": "nx.json",
    "chars": 3041,
    "preview": "{\n    \"tui\": {\n        \"enabled\": false\n    },\n    \"workspaceLayout\": {\n        \"libsDir\": \"projects\",\n        \"appsDir\""
  },
  {
    "path": "package.json",
    "chars": 4724,
    "preview": "{\n    \"name\": \"maskito\",\n    \"version\": \"5.2.2\",\n    \"description\": \"Collection of libraries to create an input mask whi"
  },
  {
    "path": "projects/angular/README.md",
    "chars": 853,
    "preview": "# @maskito/angular\n\n[![npm version](https://img.shields.io/npm/v/@maskito/angular.svg)](https://npmjs.com/package/@maski"
  },
  {
    "path": "projects/angular/jest.config.ts",
    "chars": 472,
    "preview": "export default {\n    displayName: 'angular',\n    preset: '../../jest.preset.js',\n    setupFilesAfterEnv: ['<rootDir>/src"
  },
  {
    "path": "projects/angular/ng-package.json",
    "chars": 164,
    "preview": "{\n    \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n    \"dest\": \"../../dist/angular\",\n    \"lib\": {\n"
  },
  {
    "path": "projects/angular/package.json",
    "chars": 1593,
    "preview": "{\n    \"name\": \"@maskito/angular\",\n    \"version\": \"5.2.2\",\n    \"description\": \"The Angular-specific Maskito's library\",\n "
  },
  {
    "path": "projects/angular/project.json",
    "chars": 1557,
    "preview": "{\n    \"$schema\": \"../../node_modules/nx/schemas/project-schema.json\",\n    \"name\": \"angular\",\n    \"prefix\": \"maskito\",\n  "
  },
  {
    "path": "projects/angular/src/index.ts",
    "chars": 118,
    "preview": "export * from './lib/maskito.directive';\nexport * from './lib/maskito.pipe';\nexport * from './lib/pattern.directive';\n"
  },
  {
    "path": "projects/angular/src/lib/maskito.directive.ts",
    "chars": 2265,
    "preview": "import {\n    Directive,\n    effect,\n    ElementRef,\n    inject,\n    model,\n    NgZone,\n    type OnDestroy,\n    untracked"
  },
  {
    "path": "projects/angular/src/lib/maskito.pipe.ts",
    "chars": 469,
    "preview": "import {Pipe, type PipeTransform} from '@angular/core';\nimport {\n    MASKITO_DEFAULT_OPTIONS,\n    type MaskitoOptions,\n "
  },
  {
    "path": "projects/angular/src/lib/pattern.directive.ts",
    "chars": 546,
    "preview": "import {Directive, inject} from '@angular/core';\n\nimport {MaskitoDirective} from './maskito.directive';\n\n@Directive({\n  "
  },
  {
    "path": "projects/angular/src/lib/tests/maskito.directive.spec.ts",
    "chars": 5655,
    "preview": "import {ChangeDetectionStrategy, Component, signal} from '@angular/core';\nimport {type ComponentFixture, TestBed} from '"
  },
  {
    "path": "projects/angular/src/lib/tests/maskito.spec.ts",
    "chars": 2785,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {type ComponentFixture, TestBed} from '@angular"
  },
  {
    "path": "projects/angular/src/test-setup.ts",
    "chars": 90,
    "preview": "import {setupZoneTestEnv} from 'jest-preset-angular/setup-env/zone';\n\nsetupZoneTestEnv();\n"
  },
  {
    "path": "projects/angular/tsconfig.lib.prod.json",
    "chars": 111,
    "preview": "{\n    \"extends\": \"../../tsconfig.build.json\",\n    \"compilerOptions\": {\n        \"declarationMap\": false\n    }\n}\n"
  },
  {
    "path": "projects/core/README.md",
    "chars": 845,
    "preview": "# @maskito/core\n\n[![npm version](https://img.shields.io/npm/v/@maskito/core.svg)](https://npmjs.com/package/@maskito/cor"
  },
  {
    "path": "projects/core/jest.config.ts",
    "chars": 181,
    "preview": "export default {\n    displayName: 'core',\n    preset: '../../jest.preset.js',\n    moduleFileExtensions: ['ts', 'tsx', 'j"
  },
  {
    "path": "projects/core/package.json",
    "chars": 1248,
    "preview": "{\n    \"name\": \"@maskito/core\",\n    \"version\": \"5.2.2\",\n    \"description\": \"The main zero-dependency and framework-agnost"
  },
  {
    "path": "projects/core/project.json",
    "chars": 1549,
    "preview": "{\n    \"$schema\": \"../../node_modules/nx/schemas/project-schema.json\",\n    \"name\": \"core\",\n    \"projectType\": \"library\",\n"
  },
  {
    "path": "projects/core/src/index.ts",
    "chars": 623,
    "preview": "export {\n    MASKITO_DEFAULT_ELEMENT_PREDICATE,\n    MASKITO_DEFAULT_OPTIONS,\n} from './lib/constants';\nexport {Maskito} "
  },
  {
    "path": "projects/core/src/lib/classes/index.ts",
    "chars": 95,
    "preview": "export {MaskHistory} from './mask-history';\nexport {MaskModel} from './mask-model/mask-model';\n"
  },
  {
    "path": "projects/core/src/lib/classes/mask-history.ts",
    "chars": 1595,
    "preview": "import type {ElementState, TypedInputEvent} from '../types';\n\nexport abstract class MaskHistory {\n    private now: Eleme"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/mask-model.ts",
    "chars": 4587,
    "preview": "import type {\n    ElementState,\n    MaskitoMaskExpression,\n    MaskitoOptions,\n    SelectionRange,\n} from '../../types';"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/tests/dynamic-mask.spec.ts",
    "chars": 3399,
    "preview": "import {describe, expect, it} from '@jest/globals';\nimport {MASKITO_DEFAULT_OPTIONS} from '@maskito/core';\n\nimport type "
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/tests/mask-model-fixed-characters.spec.ts",
    "chars": 9815,
    "preview": "import {describe, expect, it} from '@jest/globals';\n\nimport {MASKITO_DEFAULT_OPTIONS} from '../../../constants';\nimport "
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/apply-overwrite-mode.ts",
    "chars": 544,
    "preview": "import type {ElementState, MaskitoOptions} from '../../../types';\n\nexport function applyOverwriteMode(\n    {value, selec"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts",
    "chars": 852,
    "preview": "import type {ElementState, MaskitoMaskExpression} from '../../../types';\nimport {guessValidValueByPattern} from './guess"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts",
    "chars": 828,
    "preview": "import type {ElementState} from '../../../types';\nimport {isFixedCharacter} from './is-fixed-character';\n\nexport functio"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts",
    "chars": 2270,
    "preview": "import type {ElementState} from '../../../types';\nimport {getLeadingFixedCharacters} from './get-leading-fixed-character"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-reg-exp.ts",
    "chars": 867,
    "preview": "import type {ElementState} from '../../../types';\n\nexport function guessValidValueByRegExp(\n    {value, selection}: Elem"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/is-fixed-character.ts",
    "chars": 113,
    "preview": "export function isFixedCharacter(char: RegExp | string): char is string {\n    return typeof char === 'string';\n}\n"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts",
    "chars": 1249,
    "preview": "import type {ElementState, MaskitoMaskExpression} from '../../../types';\nimport {isFixedCharacter} from './is-fixed-char"
  },
  {
    "path": "projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts",
    "chars": 683,
    "preview": "import type {MaskitoMaskExpression} from '../../../types';\nimport {isFixedCharacter} from './is-fixed-character';\n\nexpor"
  },
  {
    "path": "projects/core/src/lib/constants/default-element-predicate.ts",
    "chars": 417,
    "preview": "import type {MaskitoElementPredicate} from '../types';\nimport {maskitoAdaptContentEditable} from '../utils/content-edita"
  },
  {
    "path": "projects/core/src/lib/constants/default-options.ts",
    "chars": 227,
    "preview": "import type {MaskitoOptions} from '../types';\n\nexport const MASKITO_DEFAULT_OPTIONS: Required<MaskitoOptions> = {\n    ma"
  },
  {
    "path": "projects/core/src/lib/constants/index.ts",
    "chars": 80,
    "preview": "export * from './default-element-predicate';\nexport * from './default-options';\n"
  },
  {
    "path": "projects/core/src/lib/mask.ts",
    "chars": 12015,
    "preview": "import {MaskHistory, MaskModel} from './classes';\nimport {MASKITO_DEFAULT_OPTIONS} from './constants';\nimport {createBro"
  },
  {
    "path": "projects/core/src/lib/plugins/broken-prevent-default.plugin.ts",
    "chars": 1885,
    "preview": "import type {MaskitoPlugin} from '@maskito/core';\n\nimport type {TypedInputEvent} from '../types';\nimport {EventListener}"
  },
  {
    "path": "projects/core/src/lib/plugins/change-event-plugin.ts",
    "chars": 930,
    "preview": "import type {MaskitoPlugin} from '../types';\n\nexport function maskitoChangeEventPlugin(): MaskitoPlugin {\n    return (el"
  },
  {
    "path": "projects/core/src/lib/plugins/double-space.plugin.ts",
    "chars": 2511,
    "preview": "import type {MaskitoPlugin} from '@maskito/core';\n\nimport type {TypedInputEvent} from '../types';\nimport {EventListener}"
  },
  {
    "path": "projects/core/src/lib/plugins/index.ts",
    "chars": 218,
    "preview": "export * from './broken-prevent-default.plugin';\nexport * from './change-event-plugin';\nexport * from './double-space.pl"
  },
  {
    "path": "projects/core/src/lib/plugins/initial-calibration-plugin.ts",
    "chars": 537,
    "preview": "import type {MaskitoOptions, MaskitoPlugin} from '../types';\nimport {maskitoTransform, maskitoUpdateElement} from '../ut"
  },
  {
    "path": "projects/core/src/lib/plugins/strict-composition-plugin.ts",
    "chars": 1160,
    "preview": "import type {ElementState, MaskitoPlugin, TypedInputEvent} from '../types';\nimport {areElementStatesEqual, maskitoTransf"
  },
  {
    "path": "projects/core/src/lib/types/element-predicate.ts",
    "chars": 169,
    "preview": "import type {MaskitoElement} from './maskito-element';\n\nexport type MaskitoElementPredicate = (\n    element: HTMLElement"
  },
  {
    "path": "projects/core/src/lib/types/element-state.ts",
    "chars": 158,
    "preview": "import type {SelectionRange} from './selection-range';\n\nexport interface ElementState {\n    readonly value: string;\n    "
  },
  {
    "path": "projects/core/src/lib/types/index.ts",
    "chars": 294,
    "preview": "export * from './element-predicate';\nexport * from './element-state';\nexport * from './mask';\nexport * from './mask-opti"
  },
  {
    "path": "projects/core/src/lib/types/mask-options.ts",
    "chars": 593,
    "preview": "import type {ElementState} from './element-state';\nimport type {MaskitoMask} from './mask';\nimport type {MaskitoPostproc"
  },
  {
    "path": "projects/core/src/lib/types/mask-processors.ts",
    "chars": 429,
    "preview": "import type {ElementState} from './element-state';\n\nexport type MaskitoPreprocessor = (\n    _: {\n        elementState: E"
  },
  {
    "path": "projects/core/src/lib/types/mask.ts",
    "chars": 239,
    "preview": "import type {ElementState} from './element-state';\n\nexport type MaskitoMaskExpression = Array<RegExp | string> | RegExp;"
  },
  {
    "path": "projects/core/src/lib/types/maskito-element.ts",
    "chars": 234,
    "preview": "export type TextfieldLike = Pick<\n    HTMLInputElement,\n    | 'maxLength'\n    | 'select'\n    | 'selectionEnd'\n    | 'sel"
  },
  {
    "path": "projects/core/src/lib/types/plugin.ts",
    "chars": 232,
    "preview": "import type {MaskitoOptions} from './mask-options';\nimport type {MaskitoElement} from './maskito-element';\n\nexport type "
  },
  {
    "path": "projects/core/src/lib/types/selection-range.ts",
    "chars": 66,
    "preview": "export type SelectionRange = readonly [from: number, to: number];\n"
  },
  {
    "path": "projects/core/src/lib/types/typed-input-event.ts",
    "chars": 878,
    "preview": "export interface TypedInputEvent extends InputEvent {\n    inputType:\n        | 'deleteByCut' // Ctrl (Command) + X\n     "
  },
  {
    "path": "projects/core/src/lib/utils/content-editable.ts",
    "chars": 1861,
    "preview": "import type {MaskitoElement, TextfieldLike} from '../types';\nimport {getContentEditableSelection} from './dom/get-conten"
  },
  {
    "path": "projects/core/src/lib/utils/dom/event-listener.ts",
    "chars": 871,
    "preview": "import type {TypedInputEvent} from '../../types';\n\nexport class EventListener {\n    private readonly listeners: Array<()"
  },
  {
    "path": "projects/core/src/lib/utils/dom/get-content-editable-selection.ts",
    "chars": 367,
    "preview": "import type {SelectionRange} from '../../types';\n\nexport function getContentEditableSelection(element: HTMLElement): Sel"
  },
  {
    "path": "projects/core/src/lib/utils/dom/history-events.ts",
    "chars": 654,
    "preview": "import {HotkeyCode, HotkeyModifier, isHotkey} from './hotkey';\n\nexport function isRedo(event: KeyboardEvent): boolean {\n"
  },
  {
    "path": "projects/core/src/lib/utils/dom/hotkey.ts",
    "chars": 1526,
    "preview": "export const HotkeyModifier = {\n    CTRL: 1 << 0,\n    ALT: 1 << 1,\n    SHIFT: 1 << 2,\n    META: 1 << 3,\n} as const;\n\n// "
  },
  {
    "path": "projects/core/src/lib/utils/dom/set-content-editable-selection.ts",
    "chars": 642,
    "preview": "import type {SelectionRange} from '../../types';\n\nexport function setContentEditableSelection(\n    element: HTMLElement,"
  },
  {
    "path": "projects/core/src/lib/utils/dom/update-element.ts",
    "chars": 1487,
    "preview": "import type {ElementState, MaskitoElement} from '../../types';\n\n/**\n * Sets value to element, and dispatches input event"
  },
  {
    "path": "projects/core/src/lib/utils/element-states-equality.ts",
    "chars": 562,
    "preview": "import type {ElementState} from '../types';\n\nexport function areElementValuesEqual(\n    sampleState: ElementState,\n    ."
  },
  {
    "path": "projects/core/src/lib/utils/get-line-selection.ts",
    "chars": 565,
    "preview": "import type {ElementState, SelectionRange} from '../types';\n\nexport function getLineSelection(\n    {value, selection}: E"
  },
  {
    "path": "projects/core/src/lib/utils/get-not-empty-selection.ts",
    "chars": 475,
    "preview": "import type {ElementState, SelectionRange} from '../types';\n\nexport function getNotEmptySelection(\n    {value, selection"
  },
  {
    "path": "projects/core/src/lib/utils/get-word-selection.ts",
    "chars": 1307,
    "preview": "import type {ElementState, SelectionRange} from '../types';\n\nconst TRAILING_SPACES_REG = /\\s+$/g;\nconst LEADING_SPACES_R"
  },
  {
    "path": "projects/core/src/lib/utils/index.ts",
    "chars": 473,
    "preview": "export * from './content-editable';\nexport * from './dom/event-listener';\nexport * from './dom/get-content-editable-sele"
  },
  {
    "path": "projects/core/src/lib/utils/pipe.ts",
    "chars": 690,
    "preview": "import type {MaskitoPostprocessor, MaskitoPreprocessor} from '../types';\n\n/**\n * @internal\n */\nexport function maskitoPi"
  },
  {
    "path": "projects/core/src/lib/utils/test/get-not-empty-selection.spec.ts",
    "chars": 2710,
    "preview": "import {describe, expect, it} from '@jest/globals';\n\nimport type {ElementState} from '../../types';\nimport {getNotEmptyS"
  },
  {
    "path": "projects/core/src/lib/utils/test/get-word-selection.spec.ts",
    "chars": 5371,
    "preview": "import {describe, expect, it} from '@jest/globals';\n\nimport {getWordSelection} from '../get-word-selection';\n\ndescribe('"
  },
  {
    "path": "projects/core/src/lib/utils/test/pipe.spec.ts",
    "chars": 6966,
    "preview": "import {describe, expect, it} from '@jest/globals';\n\nimport type {ElementState, MaskitoPostprocessor, MaskitoPreprocesso"
  },
  {
    "path": "projects/core/src/lib/utils/test/transform.spec.ts",
    "chars": 3514,
    "preview": "import {describe, expect, it} from '@jest/globals';\n\nimport type {MaskitoOptions} from '../../types';\nimport {maskitoTra"
  },
  {
    "path": "projects/core/src/lib/utils/transform.ts",
    "chars": 1277,
    "preview": "import {MaskModel} from '../classes';\nimport {MASKITO_DEFAULT_OPTIONS} from '../constants';\nimport type {ElementState, M"
  },
  {
    "path": "projects/demo/.gitignore",
    "chars": 554,
    "preview": "# compiled output\n/dist\n/tmp\n/out-tsc\n# Only exists if Bazel was run\n/bazel-out\n\n# dependencies\n/node_modules\n\n# profili"
  },
  {
    "path": "projects/demo/esbuild-plugins/maskito-as-taiga-ui-dep.plugin.js",
    "chars": 1259,
    "preview": "const {resolve, join} = require('node:path');\nconst {existsSync} = require('node:fs');\n\n/**\n * Maskito repo uses Taiga U"
  },
  {
    "path": "projects/demo/esbuild-plugins/vue-esm.plugin.js",
    "chars": 649,
    "preview": "const {resolve} = require('node:path');\n\n/**\n * Otherwise, demo application logs warning:\n * ```\n * Component provided t"
  },
  {
    "path": "projects/demo/jest.config.ts",
    "chars": 466,
    "preview": "export default {\n    displayName: 'demo',\n    preset: '../../jest.preset.js',\n    setupFilesAfterEnv: ['<rootDir>/src/te"
  },
  {
    "path": "projects/demo/package.json",
    "chars": 1295,
    "preview": "{\n    \"name\": \"@maskito/demo\",\n    \"private\": true,\n    \"devDependencies\": {\n        \"@angular/animations\": \"19.2.20\",\n "
  },
  {
    "path": "projects/demo/project.json",
    "chars": 6012,
    "preview": "{\n    \"$schema\": \"../../node_modules/nx/schemas/project-schema.json\",\n    \"name\": \"demo\",\n    \"prefix\": \"app\",\n    \"proj"
  },
  {
    "path": "projects/demo/src/app/app.component.html",
    "chars": 956,
    "preview": "<tui-doc-main>\n    <ng-container ngProjectAs=\"tuiDocHeader\">\n        <a\n            appearance=\"icon\"\n            href=\""
  },
  {
    "path": "projects/demo/src/app/app.component.spec.ts",
    "chars": 1283,
    "preview": "import {APP_BASE_HREF} from '@angular/common';\nimport {TestBed} from '@angular/core/testing';\nimport {RouterTestingHarne"
  },
  {
    "path": "projects/demo/src/app/app.component.ts",
    "chars": 2078,
    "preview": "import {ViewportScroller} from '@angular/common';\nimport {ChangeDetectionStrategy, Component, inject} from '@angular/cor"
  },
  {
    "path": "projects/demo/src/app/app.config.ts",
    "chars": 5650,
    "preview": "import {isPlatformBrowser, LocationStrategy, PathLocationStrategy} from '@angular/common';\nimport {provideHttpClient} fr"
  },
  {
    "path": "projects/demo/src/app/app.routes.ts",
    "chars": 6187,
    "preview": "import type {Routes} from '@angular/router';\nimport {DemoPath} from '@demo/constants';\nimport {tuiProvideRoutePageTab} f"
  },
  {
    "path": "projects/demo/src/app/app.style.less",
    "chars": 196,
    "preview": "@import '@taiga-ui/core/styles/taiga-ui-local.less';\n\n:host {\n    display: block;\n    font: var(--tui-font-text-m);\n    "
  },
  {
    "path": "projects/demo/src/app/constants/demo-path.ts",
    "chars": 1219,
    "preview": "export const DemoPath = {\n    WhatIsMaskito: 'getting-started/what-is-maskito',\n    MaskitoLibraries: 'getting-started/m"
  },
  {
    "path": "projects/demo/src/app/constants/doc-example-primary-tab.ts",
    "chars": 168,
    "preview": "export const DocExamplePrimaryTab = {\n    MaskitoOptions: 'mask',\n    JavaScript: 'JavaScript',\n    Angular: 'Angular',\n"
  },
  {
    "path": "projects/demo/src/app/constants/index.ts",
    "chars": 72,
    "preview": "export * from './demo-path';\nexport * from './doc-example-primary-tab';\n"
  },
  {
    "path": "projects/demo/src/app/modules/example-primary-tabs-icons/angular-logo.component.ts",
    "chars": 451,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {PolymorpheusComponent} from '@taiga-ui/polymor"
  },
  {
    "path": "projects/demo/src/app/modules/example-primary-tabs-icons/index.ts",
    "chars": 127,
    "preview": "export * from './angular-logo.component';\nexport * from './javascript-logo.component';\nexport * from './react-logo.compo"
  },
  {
    "path": "projects/demo/src/app/modules/example-primary-tabs-icons/javascript-logo.component.ts",
    "chars": 466,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {PolymorpheusComponent} from '@taiga-ui/polymor"
  },
  {
    "path": "projects/demo/src/app/modules/example-primary-tabs-icons/react-logo.component.ts",
    "chars": 441,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {PolymorpheusComponent} from '@taiga-ui/polymor"
  },
  {
    "path": "projects/demo/src/app/modules/example-primary-tabs-icons/vue-logo.component.ts",
    "chars": 431,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {PolymorpheusComponent} from '@taiga-ui/polymor"
  },
  {
    "path": "projects/demo/src/app/modules/logo/logo.component.ts",
    "chars": 517,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {Tu"
  },
  {
    "path": "projects/demo/src/app/modules/logo/logo.style.less",
    "chars": 411,
    "preview": "@import '@taiga-ui/core/styles/taiga-ui-local.less';\n\n:host {\n    display: flex;\n    align-items: center;\n\n    @media @t"
  },
  {
    "path": "projects/demo/src/app/modules/logo/logo.template.html",
    "chars": 243,
    "preview": "<a\n    routerLink=\"/\"\n    tuiLink\n    class=\"logo-link\"\n>\n    <span class=\"logo-name\">\n        <img\n            alt=\"Mas"
  },
  {
    "path": "projects/demo/src/app/server-error-handler.ts",
    "chars": 1523,
    "preview": "import {type ErrorHandler, Injectable} from '@angular/core';\n\n// TODO\nconst KNOWN_ISSUES: ReadonlyArray<RegExp | string>"
  },
  {
    "path": "projects/demo/src/app/utils/add-default-tabs-processor/add-default-tabs-processor.ts",
    "chars": 946,
    "preview": "import {DocExamplePrimaryTab} from '@demo/constants';\nimport type {TuiHandler} from '@taiga-ui/cdk';\n\nimport {ANGULAR_DE"
  },
  {
    "path": "projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/angular-default-tab.ts",
    "chars": 388,
    "preview": "export const ANGULAR_DEFAULT_TAB = `import {Component} from '@angular/core';\nimport {MaskitoDirective} from '@maskito/an"
  },
  {
    "path": "projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/js-default-tab.ts",
    "chars": 327,
    "preview": "export const JS_DEFAULT_TAB = `import {Maskito, MaskitoOptions} from '@maskito/core';\nimport maskitoOptions from './mask"
  },
  {
    "path": "projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/react-default-tab.ts",
    "chars": 267,
    "preview": "export const REACT_DEFAULT_TAB = `import * as React from 'react';\nimport {useMaskito} from '@maskito/react';\n\nimport opt"
  },
  {
    "path": "projects/demo/src/app/utils/add-default-tabs-processor/default-tabs/vue-default-tab.ts",
    "chars": 262,
    "preview": "export const VUE_DEFAULT_TAB = `import {createApp} from 'vue';\nimport {maskito} from '@maskito/vue';\n\nimport options fro"
  },
  {
    "path": "projects/demo/src/app/utils/index.ts",
    "chars": 73,
    "preview": "export * from './add-default-tabs-processor/add-default-tabs-processor';\n"
  },
  {
    "path": "projects/demo/src/assets/manifest.webmanifest",
    "chars": 180,
    "preview": "{\n    \"icons\": [\n        {\"src\": \"/favicon-192.png\", \"type\": \"image/png\", \"sizes\": \"192x192\"},\n        {\"src\": \"/favicon"
  },
  {
    "path": "projects/demo/src/environments/environment.prod.ts",
    "chars": 47,
    "preview": "export const environment = {production: true};\n"
  },
  {
    "path": "projects/demo/src/environments/environment.ts",
    "chars": 48,
    "preview": "export const environment = {production: false};\n"
  },
  {
    "path": "projects/demo/src/index.html",
    "chars": 1114,
    "preview": "<!doctype html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\" />\n        <meta\n            content=\"text/htm"
  },
  {
    "path": "projects/demo/src/main.server.ts",
    "chars": 2274,
    "preview": "import {type ApplicationRef, ErrorHandler, mergeApplicationConfig} from '@angular/core';\nimport {bootstrapApplication, t"
  },
  {
    "path": "projects/demo/src/main.ts",
    "chars": 235,
    "preview": "import {bootstrapApplication} from '@angular/platform-browser';\n\nimport {App} from './app/app.component';\nimport {APP_CO"
  },
  {
    "path": "projects/demo/src/pages/documentation/browser-support/browser-support.component.ts",
    "chars": 1122,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {TuiAddonDoc} from '@taiga-ui/addon-doc';\n\n@Com"
  },
  {
    "path": "projects/demo/src/pages/documentation/browser-support/browser-support.template.html",
    "chars": 1479,
    "preview": "<tui-doc-page header=\"Browser support\">\n    <h2 class=\"tui-text_h4 tui-space_top-0 tui-space_bottom-3\">Desktop</h2>\n    "
  },
  {
    "path": "projects/demo/src/pages/documentation/core-concepts-overview/core-concepts-overview.component.ts",
    "chars": 1456,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/core-concepts-overview/core-concepts-overview.styles.less",
    "chars": 371,
    "preview": "@import '@taiga-ui/core/styles/taiga-ui-local.less';\n\n.cards {\n    display: flex;\n    flex-wrap: wrap;\n    justify-conte"
  },
  {
    "path": "projects/demo/src/pages/documentation/core-concepts-overview/core-concepts-overview.template.html",
    "chars": 5294,
    "preview": "<tui-doc-page header=\"Core concepts\">\n    <section class=\"tui-space_bottom-4\">\n        <p class=\"tui-space_top-0\">\n     "
  },
  {
    "path": "projects/demo/src/pages/documentation/core-concepts-overview/examples/maskito-public-api-demo.md",
    "chars": 426,
    "preview": "```ts\nimport {Maskito, maskitoInitialCalibrationPlugin} from '@maskito/core';\n\nconst maskedInput = new Maskito(element, "
  },
  {
    "path": "projects/demo/src/pages/documentation/element-state/element-state.component.ts",
    "chars": 815,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/element-state/element-state.template.html",
    "chars": 1407,
    "preview": "<tui-doc-page header=\"Element state\">\n    <section class=\"tui-space_bottom-6\">\n        <p class=\"tui-space_top-0\">\n     "
  },
  {
    "path": "projects/demo/src/pages/documentation/element-state/examples/element-state-demo.md",
    "chars": 305,
    "preview": "```ts\ninterface ElementState {\n  // the value of a masked <input> or <textarea>\n  readonly value: string;\n  readonly sel"
  },
  {
    "path": "projects/demo/src/pages/documentation/mask-expression/examples/basic-time-example.md",
    "chars": 134,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nconst timeInput = new Maskito(element, {\n  mask: [/\\d/, /\\d/, ':', /\\d/, /"
  },
  {
    "path": "projects/demo/src/pages/documentation/mask-expression/examples/dynamic-mask-expression-demo.md",
    "chars": 213,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nlet howManyWordsAllowed = 5;\n\nconst maxWordInput = new Maskito(element, {\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/mask-expression/examples/reg-exp-mask-expression-demo.md",
    "chars": 118,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nconst onlyDigitsInput = new Maskito(element, {\n  mask: /^\\d+$/,\n});\n```\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/mask-expression/mask-expression.component.ts",
    "chars": 1005,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/mask-expression/mask-expression.template.html",
    "chars": 6769,
    "preview": "<tui-doc-page header=\"Mask expression\">\n    <div>\n        <strong>Mask expression</strong>\n        is the the main conce"
  },
  {
    "path": "projects/demo/src/pages/documentation/maskito-libraries/maskito-libraries.component.ts",
    "chars": 1019,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/maskito-libraries/maskito-libraries.template.html",
    "chars": 5357,
    "preview": "<tui-doc-page header=\"Maskito libraries\">\n    <p class=\"tui-space_top-0\">\n        <strong>Maskito</strong>\n        is a "
  },
  {
    "path": "projects/demo/src/pages/documentation/next-steps/next-steps.component.ts",
    "chars": 777,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink, RouterLinkActive} from '@angular/r"
  },
  {
    "path": "projects/demo/src/pages/documentation/next-steps/next-steps.template.html",
    "chars": 1226,
    "preview": "<section class=\"tui-space_top-12\">\n    <h2>Next steps</h2>\n\n    <p>The following sections are recommended to explore cor"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/dynamic/component.ts",
    "chars": 1174,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/dynamic/mask.ts",
    "chars": 308,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nconst maskitoOptions: MaskitoOptions = {\n    mask: /^[^а-яё]+$/i,\n  "
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/replace/component.ts",
    "chars": 1106,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/replace/mask.ts",
    "chars": 177,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nconst maskitoOptions: MaskitoOptions = {\n    mask: /^\\d+$/,\n    over"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/shift/component.ts",
    "chars": 1104,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/examples/shift/mask.ts",
    "chars": 175,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nconst maskitoOptions: MaskitoOptions = {\n    mask: /^\\d+$/,\n    over"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/overwrite-mode.component.ts",
    "chars": 1744,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/overwrite-mode/overwrite-mode.template.html",
    "chars": 2913,
    "preview": "<tui-doc-page header=\"Overwrite mode\">\n    <p class=\"tui-space_top-0\">\n        <strong>Overwrite mode</strong>\n        r"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/1-initial-calibration/component.ts",
    "chars": 815,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/1-initial-calibration/index.md",
    "chars": 395,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nimport maskitoOptions from './mask';\n\nconst element = document.querySelect"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/1-initial-calibration/mask.ts",
    "chars": 234,
    "preview": "import {maskitoInitialCalibrationPlugin, type MaskitoOptions} from '@maskito/core';\n\nconst maskitoOptions: MaskitoOption"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/2-strict-composition/component.ts",
    "chars": 744,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/2-strict-composition/mask.ts",
    "chars": 203,
    "preview": "import {type MaskitoOptions, maskitoStrictCompositionPlugin} from '@maskito/core';\n\nexport default {\n    mask: /^[0-90-9"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/3-change-event/component.ts",
    "chars": 970,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/3-change-event/mask.ts",
    "chars": 397,
    "preview": "import {maskitoChangeEventPlugin, type MaskitoOptions} from '@maskito/core';\nimport {maskitoNumberOptionsGenerator} from"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/oversimplified-number-mask.md",
    "chars": 300,
    "preview": "```ts\nimport {MaskitoOptions} from '@maskito/core';\n\nexport default {\n  /**\n   * ^ – beginning of the string\n   * \\d – a"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/examples/pads-zero-plugin.ts",
    "chars": 1051,
    "preview": "import {\n    /**\n     * HTMLElement + some common properties from:\n     * - HTMLInputElement\n     * - HTMLTextAreaElemen"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/plugins.component.ts",
    "chars": 2781,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ro"
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/plugins.style.less",
    "chars": 278,
    "preview": "@import '@taiga-ui/core/styles/taiga-ui-local.less';\n\n.cards {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 1rem;\n\n "
  },
  {
    "path": "projects/demo/src/pages/documentation/plugins/plugins.template.html",
    "chars": 10055,
    "preview": "<tui-doc-page header=\"Plugins\">\n    <ng-template pageTab=\"Documentation\">\n        <p class=\"tui-space_top-0\">\n          "
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/examples/postprocessor-in-action.md",
    "chars": 590,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nconst numberInput = new Maskito(element, {\n  mask: /^\\d+(,\\d*)?$/,\n  postp"
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/examples/preprocessor-first-arg-demo.md",
    "chars": 328,
    "preview": "```ts\ntype firstArgDemo = {\n  // current input's element state BEFORE any changes are applied\n  elementState: {\n    valu"
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/examples/preprocessor-in-action-demo.md",
    "chars": 447,
    "preview": "```ts\nimport {Maskito} from '@maskito/core';\n\nconst numberInput = new Maskito(element, {\n  mask: /^\\d+(,\\d*)?$/, // digi"
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/examples/processor-second-arg-demo.md",
    "chars": 72,
    "preview": "```ts\n'insert' | 'deleteForward' | 'deleteBackward' | 'validation';\n```\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/processors.component.ts",
    "chars": 1141,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {RouterLink} from '@angular/router';\nimport {De"
  },
  {
    "path": "projects/demo/src/pages/documentation/processors/processors.template.html",
    "chars": 7120,
    "preview": "<tui-doc-page header=\"Processors\">\n    <section class=\"tui-space_bottom-6\">\n        <p class=\"tui-space_top-0\">\n        "
  },
  {
    "path": "projects/demo/src/pages/documentation/real-world-form/index.html",
    "chars": 5123,
    "preview": "<form\n    #formElement\n    autocomplete=\"on\"\n    class=\"tui-form\"\n    [formGroup]=\"form\"\n    (ngSubmit)=\"log(form.value)"
  },
  {
    "path": "projects/demo/src/pages/documentation/real-world-form/index.less",
    "chars": 240,
    "preview": ":host {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    padding-block-start: 2rem;\n}\n\nform "
  },
  {
    "path": "projects/demo/src/pages/documentation/real-world-form/index.ts",
    "chars": 3260,
    "preview": "import {ChangeDetectionStrategy, Component, inject} from '@angular/core';\nimport {FormControl, FormGroup, ReactiveFormsM"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/password/component.ts",
    "chars": 1134,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/password/mask.ts",
    "chars": 120,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nexport default {mask: [/\\d/, /\\d/, /\\d/]} satisfies MaskitoOptions;\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/search/component.ts",
    "chars": 1037,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/search/mask.ts",
    "chars": 113,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nexport default {mask: /^[a-z]+$/i} satisfies MaskitoOptions;\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/tel/component.ts",
    "chars": 1336,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/tel/mask.ts",
    "chars": 212,
    "preview": "import {maskitoPhoneOptionsGenerator} from '@maskito/phone';\nimport metadata from 'libphonenumber-js/metadata.min.json';"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/text/component.ts",
    "chars": 1059,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/text/mask.ts",
    "chars": 120,
    "preview": "import {maskitoTimeOptionsGenerator} from '@maskito/kit';\n\nexport default maskitoTimeOptionsGenerator({mode: 'HH:MM'});\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/url/component.ts",
    "chars": 1019,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {Ma"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/examples/url/mask.ts",
    "chars": 182,
    "preview": "import type {MaskitoOptions} from '@maskito/core';\n\nexport default {\n    // oversimplified version of url mask for demo "
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/supported-input-types.component.ts",
    "chars": 2284,
    "preview": "import {ChangeDetectionStrategy, Component} from '@angular/core';\nimport {DocExamplePrimaryTab} from '@demo/constants';\n"
  },
  {
    "path": "projects/demo/src/pages/documentation/supported-input-types/supported-input-types.template.html",
    "chars": 4067,
    "preview": "<tui-doc-page header=\"Supported <input /> types\">\n    <tui-notification\n        appearance=\"warning\"\n        size=\"m\"\n  "
  },
  {
    "path": "projects/demo/src/pages/documentation/transformer/examples/utility-in-action-demo.md",
    "chars": 498,
    "preview": "```ts\nimport {maskitoTransform} from '@maskito/core';\nimport {maskitoNumberOptionsGenerator} from '@maskito/kit';\n\nconst"
  }
]

// ... and 557 more files (download for full content)

About this extraction

This page contains the full source code of the Tinkoff/maskito GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 757 files (1.6 MB), approximately 432.2k tokens, and a symbol index with 503 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!