@kigi/components 1.63.2-beta.1 → 1.63.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kigi/components",
3
- "version": "1.63.2-beta.1",
3
+ "version": "1.63.3-beta.1",
4
4
  "description": "@kigi/components",
5
5
  "main": "src/components/index.ts",
6
6
  "scripts": {
@@ -32,7 +32,6 @@
32
32
  "@firebase/remote-config": "^0.1.25",
33
33
  "@firebase/storage": "^0.3.39",
34
34
  "@firebase/util": "^0.2.50",
35
- "@kigi/components": "^1.63.1-beta.1",
36
35
  "@syncfusion/ej2-base": "^17.4.43",
37
36
  "@syncfusion/ej2-buttons": "^17.4.43",
38
37
  "@syncfusion/ej2-documenteditor": "^17.4.43",
@@ -101,4 +100,4 @@
101
100
  "webpack": "^2.5.1",
102
101
  "webpack-dev-server": "^2.6.1"
103
102
  }
104
- }
103
+ }
@@ -2,20 +2,6 @@
2
2
  ng-if="$ctrl.props"
3
3
  mbg-autocomplete-off>
4
4
  <input type="text"
5
- ng-if="$ctrl.allowAlphanumeric"
6
- ng-model="$ctrl.ngModel"
7
- ng-change="$ctrl.onChange()"
8
- placeholder="{{ $ctrl.props.placeholder }}"
9
- ng-required="$ctrl.ngRequired"
10
- ng-disabled="$ctrl.ngDisabled"
11
- ng-blur="$ctrl.ngBlur({ $event })"
12
- ng-focus="$ctrl.ngFocus({ $event })"
13
- ng-keyup="$ctrl.ngKeyup({ $event })"
14
- ng-keypress="$ctrl.ngKeypress({ $event })"
15
- ng-keydown="$ctrl.ngKeydown({ $event })"
16
- mbg-alphanumeric-cnpj-mask />
17
- <input type="text"
18
- ng-if="!$ctrl.allowAlphanumeric"
19
5
  ng-model="$ctrl.ngModel"
20
6
  ng-change="$ctrl.onChange()"
21
7
  placeholder="{{ $ctrl.props.placeholder }}"
@@ -1,76 +1,82 @@
1
1
  import './mbg-input-cnpj.scss'
2
2
  import template from './mbg-input-cnpj.html'
3
- import {
4
- normalizeAlphanumericCnpj,
5
- formatAlphanumericCnpj,
6
- isValidAlphanumericCnpj,
7
- mbgDocumentMaskDirective,
8
- } from '../../helpers/mbg-document-mask-directive'
9
- import { isValidCnpj } from '../../helpers/cnpj-validador'
10
3
 
11
4
  class MbgInputCnpjController {
12
- private ngChange
13
- private ngModel
14
- private ngRequired
15
- private ngDisabled
16
- private props
17
- private allowAlphanumeric: boolean
18
- public valid = true
5
+ private ngChange
6
+ private ngModel
7
+ private ngRequired
8
+ private ngDisabled
9
+ private props
10
+ public valid = true
19
11
 
20
- constructor(
21
- public $scope,
22
- public $element,
23
- public $attrs,
24
- ) {
25
- if ($attrs.ngRequired === '') {
26
- this.ngRequired = true
12
+ constructor(public $scope, public $element, public $attrs) {
13
+ if ($attrs.ngRequired === '') {
14
+ this.ngRequired = true
15
+ }
16
+ if ($attrs.ngDisabled === '') {
17
+ this.ngDisabled = true
18
+ }
19
+ this.props = {
20
+ placeholder: $attrs.placeholder || '',
21
+ }
27
22
  }
28
- if ($attrs.ngDisabled === '') {
29
- this.ngDisabled = true
30
- }
31
- this.props = {
32
- placeholder: $attrs.placeholder || '',
33
- }
34
- }
35
23
 
36
- $onInit() {
37
- this.allowAlphanumeric = this.allowAlphanumeric === true
38
- }
24
+ ngBlur(evt) {
25
+ this.valid = this.validaCnpj(evt.$event.target.value)
26
+ }
39
27
 
40
- ngBlur(evt) {
41
- const raw = evt.$event.target.value
42
- const clean = normalizeAlphanumericCnpj(raw)
28
+ validaCnpj(value) {
29
+ let original = value
30
+ let firstNumbers = value.substr(0, 12)
31
+ let firstCalc = this.CalcDigits(firstNumbers, 5)
32
+ let secondCalc = this.CalcDigits(firstCalc, 6)
33
+ if (secondCalc === original) {
34
+ return true
35
+ }
36
+ return false
37
+ }
43
38
 
44
- if (clean.length === 14) {
45
- this.valid = isValidAlphanumericCnpj(clean)
46
- } else {
47
- this.valid = isValidCnpj(clean)
39
+ CalcDigits(digits, positions = 10, sumDigits = 0) {
40
+ digits = digits.toString()
41
+ for (let i = 0; i < digits.length; i++) {
42
+ sumDigits = sumDigits + (digits[i] * positions)
43
+ positions--
44
+ if (positions < 2) {
45
+ positions = 9
46
+ }
47
+ }
48
+ sumDigits = sumDigits % 11
49
+ if (sumDigits < 2) {
50
+ sumDigits = 0
51
+ } else {
52
+ sumDigits = 11 - sumDigits
53
+ }
54
+ let cnpj = digits + sumDigits
55
+ return cnpj
48
56
  }
49
- }
50
57
 
51
- onChange() {
52
- if (this.ngChange) {
53
- this.ngChange({})
58
+ onChange() {
59
+ if (this.ngChange) {
60
+ this.ngChange({})
61
+ }
54
62
  }
55
- }
56
63
  }
57
64
  MbgInputCnpjController.$inject = ['$scope', '$element', '$attrs']
58
65
 
59
66
  const mbgInputCnpj = {
60
- bindings: {
61
- ngModel: '=',
62
- ngChange: '&?',
63
- ngRequired: '=?',
64
- ngDisabled: '=?',
65
- ngBlur: '&?',
66
- ngFocus: '&?',
67
- ngKeyup: '&?',
68
- ngKeypress: '&?',
69
- ngKeydown: '&?',
70
- allowAlphanumeric: '<?',
71
- },
72
- template,
73
- controller: MbgInputCnpjController,
67
+ bindings: {
68
+ ngModel: '=',
69
+ ngChange: '&?',
70
+ ngRequired: '=?',
71
+ ngDisabled: '=?',
72
+ ngBlur: '&?',
73
+ ngFocus: '&?',
74
+ ngKeyup: '&?',
75
+ ngKeypress: '&?',
76
+ ngKeydown: '&?',
77
+ },
78
+ template,
79
+ controller: MbgInputCnpjController,
74
80
  }
75
81
 
76
- export { mbgInputCnpj, mbgDocumentMaskDirective }
82
+ export { mbgInputCnpj }
@@ -1,10 +1,9 @@
1
1
  import * as angular from 'angular'
2
- import { mbgInputCpfCnpj, mbgDocumentMaskDirective } from './mbg-input-cpfcnpj'
2
+ import { mbgInputCpfCnpj } from './mbg-input-cpfcnpj'
3
3
 
4
4
  const mbgInputCpfCnpjModule = angular
5
5
  .module('mbg.components.mbgInputCpfCnpj', [])
6
6
  .component('mbgInputCpfCnpj', mbgInputCpfCnpj)
7
- .directive('mbgAlphanumericCnpjMask', mbgDocumentMaskDirective)
8
7
  .name
9
8
 
10
9
  export { mbgInputCpfCnpjModule }
@@ -1,32 +1,16 @@
1
1
  <div class="mbg-input-wrapper mb-input-cpfcnpj-wrapper"
2
2
  ng-if="$ctrl.props"
3
3
  mbg-autocomplete-off>
4
- <input type="text"
5
- ng-if="$ctrl.allowAlphanumeric"
6
- ng-model="$ctrl.ngModel"
7
- name="{{$ctrl.name}}"
8
- ng-change="$ctrl.onChange()"
9
- placeholder="{{ $ctrl.props.placeholder }}"
10
- ng-required="$ctrl.ngRequired"
11
- ng-disabled="$ctrl.ngDisabled"
12
- ng-blur="$ctrl.ngBlur({ $event })"
13
- ng-focus="$ctrl.ngFocus({ $event })"
14
- ng-keyup="$ctrl.ngKeyup({ $event })"
15
- ng-keypress="$ctrl.ngKeypress({ $event })"
16
- ng-keydown="$ctrl.ngKeydown({ $event })"
17
- mbg-alphanumeric-cnpj-mask />
18
- <input type="text"
19
- ng-if="!$ctrl.allowAlphanumeric"
20
- ng-model="$ctrl.ngModel"
21
- name="{{$ctrl.name}}"
22
- ng-change="$ctrl.onChange()"
23
- placeholder="{{ $ctrl.props.placeholder }}"
24
- ng-required="$ctrl.ngRequired"
25
- ng-disabled="$ctrl.ngDisabled"
26
- ng-blur="$ctrl.ngBlur({ $event })"
27
- ng-focus="$ctrl.ngFocus({ $event })"
28
- ng-keyup="$ctrl.ngKeyup({ $event })"
29
- ng-keypress="$ctrl.ngKeypress({ $event })"
30
- ng-keydown="$ctrl.ngKeydown({ $event })"
31
- ui-br-cpfcnpj-mask />
32
- </div>
4
+ <input type="text"
5
+ ng-model="$ctrl.ngModel"
6
+ ng-change="$ctrl.onChange()"
7
+ placeholder="{{ $ctrl.props.placeholder }}"
8
+ ng-required="$ctrl.ngRequired"
9
+ ng-disabled="$ctrl.ngDisabled"
10
+ ng-blur="$ctrl.ngBlur({ $event })"
11
+ ng-focus="$ctrl.ngFocus({ $event })"
12
+ ng-keyup="$ctrl.ngKeyup({ $event })"
13
+ ng-keypress="$ctrl.ngKeypress({ $event })"
14
+ ng-keydown="$ctrl.ngKeydown({ $event })"
15
+ ui-br-cpfcnpj-mask />
16
+ </div>
@@ -1,100 +1,99 @@
1
1
  import './mbg-input-cpfcnpj.scss'
2
2
  import template from './mbg-input-cpfcnpj.html'
3
- import { mbgDocumentMaskDirective } from '../../helpers/mbg-document-mask-directive'
4
- import { isValidCnpj } from '../../helpers/cnpj-validador'
5
-
6
- // ---------------------------------------------------------------------------
7
- // Directive: mbg-document-mask-directive
8
- // (lógica movida para o helper, re-exportada via import acima)
9
- // ---------------------------------------------------------------------------
10
-
11
- // ---------------------------------------------------------------------------
12
- // Component: mbg-input-cpfcnpj
13
- // ---------------------------------------------------------------------------
14
3
 
15
4
  class MbgInputCpfCnpjController {
16
- private ngChange
17
- private ngModel
18
- private ngRequired
19
- private ngDisabled
20
- private allowAlphanumeric: boolean
21
- private name
22
- private props
23
- public valid
5
+ private ngChange
6
+ private ngModel
7
+ private ngRequired
8
+ private ngDisabled
9
+ private props
10
+ public valid
24
11
 
25
- constructor(
26
- public $scope,
27
- public $element,
28
- public $attrs,
29
- ) {
30
- if ($attrs.ngRequired === '') {
31
- this.ngRequired = true
32
- }
33
- if ($attrs.ngDisabled === '') {
34
- this.ngDisabled = true
35
- }
36
- this.props = {
37
- placeholder: $attrs.placeholder || '',
12
+ constructor(public $scope, public $element, public $attrs) {
13
+ if ($attrs.ngRequired === '') { this.ngRequired = true }
14
+ if ($attrs.ngDisabled === '') { this.ngDisabled = true }
15
+ this.props = {
16
+ placeholder: $attrs.placeholder || '',
17
+ }
38
18
  }
39
- }
40
19
 
41
- $onInit() {
42
- this.allowAlphanumeric = this.allowAlphanumeric === true
43
- }
20
+ ngBlur(evt) {
21
+ this.valid = evt.$event.target.value
22
+ this.valid = this.valid.toString()
23
+ this.valid = this.valid.replace(/[^0-9]/g, '')
24
+ if (this.valid.length === 11) {
25
+ this.validCpf(this.valid)
26
+ }
27
+ if (this.valid.length === 14) {
28
+ this.validCnpj(this.valid)
29
+ } else {
30
+ return false
31
+ }
32
+ }
44
33
 
45
- ngBlur(evt) {
46
- const raw = `${evt.$event.target.value || ''}`.replace(/[^A-Za-z0-9]/g, '').toUpperCase()
47
- if (raw.length === 11) {
48
- this.valid = this.validCpf(raw)
49
- } else if (raw.length === 14) {
50
- this.valid = isValidCnpj(raw)
51
- } else {
52
- this.valid = false
34
+ CalcDigits(digits, positions = 10, sumDigits = 0) {
35
+ digits = digits.toString()
36
+ for (let i = 0; i < digits.length; i++) {
37
+ sumDigits = sumDigits + (digits[i] * positions)
38
+ positions--
39
+ if (positions < 2) {
40
+ positions = 9
41
+ }
42
+ }
43
+ sumDigits = sumDigits % 11
44
+ if (sumDigits < 2) {
45
+ sumDigits = 0
46
+ } else {
47
+ sumDigits = 11 - sumDigits
48
+ }
49
+ let cnpj = digits + sumDigits
50
+ return cnpj
53
51
  }
54
- }
55
52
 
56
- CalcDigits(digits, positions = 10, sumDigits = 0) {
57
- digits = digits.toString()
58
- for (let i = 0; i < digits.length; i++) {
59
- sumDigits += digits[i] * positions
60
- positions--
61
- if (positions < 2) positions = 9
53
+ validCpf(value) {
54
+ let digits = value.substr(0, 9)
55
+ let firstCalc = this.CalcDigits(digits)
56
+ let newCpf = this.CalcDigits(firstCalc, 11)
57
+ if (newCpf === value) {
58
+ return true
59
+ } else {
60
+ return false
61
+ }
62
62
  }
63
- sumDigits = sumDigits % 11
64
- if (sumDigits < 2) sumDigits = 0
65
- else sumDigits = 11 - sumDigits
66
- return digits + sumDigits
67
- }
68
63
 
69
- validCpf(value) {
70
- const digits = value.substr(0, 9)
71
- const firstCalc = this.CalcDigits(digits)
72
- const newCpf = this.CalcDigits(firstCalc, 11)
73
- return newCpf === value
74
- }
64
+ validCnpj(value) {
65
+ let original = value
66
+ let firstNumbers = value.substr(0, 12)
67
+ let firstCalc = this.CalcDigits(firstNumbers, 5)
68
+ let secondCalc = this.CalcDigits(firstCalc, 6)
69
+ if (secondCalc === original) {
70
+ return true
71
+ }
72
+ return false
73
+ }
75
74
 
76
- onChange() {
77
- if (this.ngChange) this.ngChange({})
78
- }
75
+ onChange() {
76
+ if (this.ngChange) {
77
+ this.ngChange({})
78
+ }
79
+ }
79
80
  }
80
81
  MbgInputCpfCnpjController.$inject = ['$scope', '$element', '$attrs']
81
82
 
82
83
  const mbgInputCpfCnpj = {
83
- bindings: {
84
- ngModel: '=',
85
- ngChange: '&?',
86
- ngRequired: '=?',
87
- ngDisabled: '=?',
88
- ngBlur: '&?',
89
- ngFocus: '&?',
90
- ngKeyup: '&?',
91
- ngKeypress: '&?',
92
- ngKeydown: '&?',
93
- allowAlphanumeric: '<?',
94
- name: '@?',
95
- },
96
- template,
97
- controller: MbgInputCpfCnpjController,
84
+ bindings: {
85
+ ngModel: '=',
86
+ ngChange: '&?',
87
+ ngRequired: '=?',
88
+ ngDisabled: '=?',
89
+ ngBlur: '&?',
90
+ ngFocus: '&?',
91
+ ngKeyup: '&?',
92
+ ngKeypress: '&?',
93
+ ngKeydown: '&?',
94
+ },
95
+ template,
96
+ controller: MbgInputCpfCnpjController,
98
97
  }
99
98
 
100
- export { mbgInputCpfCnpj, mbgDocumentMaskDirective }
99
+ export { mbgInputCpfCnpj }
@@ -1,12 +1,12 @@
1
1
  <div class="mbg-input-wrapper mbg-input-name-wrapper"
2
2
  ng-if="$ctrl.props">
3
3
  <input type="text"
4
- ng-if="$ctrl.state == 'TO' || $ctrl.state == 'MT' || $ctrl.state == 'AL' || $ctrl.state == 'GO'"
4
+ ng-if="$ctrl.state == 'TO' || $ctrl.state == 'MT' || $ctrl.state == 'AL' || $ctrl.state == 'GO' || $ctrl.state == 'MS' || $ctrl.state == 'RS'"
5
5
  mbg-mask-ie
6
6
  ng-model="$ctrl.ngModel"
7
7
  name="{{$ctrl.name}}"
8
8
  ng-init="$ctrl.onInit()"
9
- ng-change="$ctrl.onChangeTO()"
9
+ ng-change="$ctrl.onChange()"
10
10
  ng-required="$ctrl.ngRequired"
11
11
  ng-disabled="$ctrl.ngDisabled"
12
12
  ng-blur="$ctrl.ngBlur({ $event })"
@@ -17,7 +17,7 @@
17
17
  placeholder="{{ $ctrl.props.placeholder }}" />
18
18
 
19
19
  <input type="text"
20
- ng-if="!$ctrl.state || ($ctrl.state != 'TO' && $ctrl.state != 'MT' && $ctrl.state != 'AL' && $ctrl.state != 'GO')"
20
+ ng-if="!$ctrl.state || ($ctrl.state != 'TO' && $ctrl.state != 'MT' && $ctrl.state != 'AL' && $ctrl.state != 'GO' && $ctrl.state != 'MS' && $ctrl.state != 'RS')"
21
21
  ng-model="$ctrl.ngModel"
22
22
  name="{{$ctrl.name}}"
23
23
  ng-init="$ctrl.onInit()"
@@ -21,22 +21,25 @@ export class NgMaskIe {
21
21
  }
22
22
 
23
23
  link(scope, elm, attrs, ngModelController) {
24
+ const getState = () => (scope.$ctrl ? scope.$ctrl.state : null)
25
+
24
26
  scope.$watch(attrs.ngModel, (data) => {
25
- const state =
26
- scope.$parent && scope.$parent.$parent && scope.$parent.$parent.$ctrl
27
- ? scope.$parent.$parent.$ctrl.state
28
- : null
27
+ const state = getState()
29
28
  const valid = this.validate(data, state)
29
+ console.log('[mbg-mask-ie] watch — data:', data, '| state:', state, '| valid:', valid)
30
+
31
+ ngModelController.$setValidity('ie', !!valid)
32
+
30
33
  const form = elm.closest('form')
31
34
  const formName = form.attr('name')
32
35
  const formScope = form.scope()
33
36
  if (formName && formScope) {
34
37
  this.setIeValidate(elm, valid)
35
- if (!valid) {
36
- elm.addClass('mbg-error')
37
- } else {
38
- elm.removeClass('mbg-error')
39
- }
38
+ }
39
+ if (!valid) {
40
+ elm.addClass('mbg-error')
41
+ } else {
42
+ elm.removeClass('mbg-error')
40
43
  }
41
44
  })
42
45
 
@@ -48,8 +51,15 @@ export class NgMaskIe {
48
51
  return value.replace(/\D/g, '').replace(/^(\d{10})(\d{1}).*/, '$1-$2')
49
52
  }
50
53
 
54
+ const maskIeRS = (value) => {
55
+ return value.replace(/\D/g, '').replace(/^(\d{3})(\d{1,7})$/, '$1/$2')
56
+ }
57
+
51
58
  const maskViewParser = (value) => {
52
- if (value.length <= 9) {
59
+ const state = getState()
60
+ if (state === 'RS') {
61
+ ngModelController.$viewValue = maskIeRS(value)
62
+ } else if (value.length <= 9) {
53
63
  ngModelController.$viewValue = maskIe9(value)
54
64
  } else {
55
65
  ngModelController.$viewValue = maskIe11(value)
@@ -59,6 +69,7 @@ export class NgMaskIe {
59
69
  }
60
70
 
61
71
  const formatterView = (value) => {
72
+ if (getState() === 'RS') return maskIeRS(value || '')
62
73
  return (value || '').length <= 9 ? maskIe9(value) : maskIe11(value)
63
74
  }
64
75
 
@@ -71,6 +82,7 @@ export class NgMaskIe {
71
82
  }
72
83
 
73
84
  validate(ngModel, state) {
85
+ console.log('[mbg-mask-ie] validate — ngModel:', ngModel, '| state:', state)
74
86
  switch (state) {
75
87
  case 'TO':
76
88
  return this.validateTO(ngModel)
@@ -80,6 +92,12 @@ export class NgMaskIe {
80
92
  return this.validateAL(ngModel)
81
93
  case 'GO':
82
94
  return this.validateGO(ngModel)
95
+ case 'MS':
96
+ return this.validateMS(ngModel)
97
+ case 'RS':
98
+ return this.validateRS(ngModel)
99
+ default:
100
+ return true
83
101
  }
84
102
  }
85
103
 
@@ -181,6 +199,44 @@ export class NgMaskIe {
181
199
  }
182
200
  }
183
201
 
202
+ validateMS(ie) {
203
+ const digits = (ie || '').replace(/\D/g, '')
204
+ if (digits.length !== 9) return false
205
+ if (!/^(28|50)/.test(digits)) return false
206
+ const weights = [9, 8, 7, 6, 5, 4, 3, 2]
207
+ let sum = 0
208
+ for (let i = 0; i < weights.length; i++) {
209
+ sum += parseInt(digits[i]) * weights[i]
210
+ }
211
+ const remainder = sum % 11
212
+ const dv = remainder === 0 || remainder === 1 ? 0 : 11 - remainder
213
+ return dv === parseInt(digits[8])
214
+ }
215
+
216
+ validateRS(ie) {
217
+ console.log('[validateRS] ie recebido:', ie)
218
+ const digits = (ie || '').replace(/\D/g, '')
219
+ console.log('[validateRS] digits (só números):', digits, '| length:', digits.length)
220
+ const padded = digits.length === 9 ? '0' + digits : digits
221
+ console.log('[validateRS] padded:', padded, '| length:', padded.length)
222
+ if (padded.length !== 10) {
223
+ console.log('[validateRS] INVÁLIDO — length esperado 10, recebido:', padded.length)
224
+ return false
225
+ }
226
+ const weights = [2, 9, 8, 7, 6, 5, 4, 3, 2]
227
+ let sum = 0
228
+ for (let i = 0; i < weights.length; i++) {
229
+ const partial = parseInt(padded[i]) * weights[i]
230
+ console.log(`[validateRS] i=${i} dígito=${padded[i]} peso=${weights[i]} parcial=${partial}`)
231
+ sum += partial
232
+ }
233
+ const remainder = sum % 11
234
+ const dv = remainder < 2 ? 0 : 11 - remainder
235
+ const dvIe = parseInt(padded[9])
236
+ console.log('[validateRS] soma:', sum, '| resto:', remainder, '| dv calculado:', dv, '| dv do IE:', dvIe, '| VÁLIDO:', dv === dvIe)
237
+ return dv === dvIe
238
+ }
239
+
184
240
  setIeValidate(elm, valid) {
185
241
  const form = elm.closest('form')
186
242
  const formName = form.attr('name')
@@ -1,38 +0,0 @@
1
- // Single source of truth for CNPJ normalization and validation.
2
-
3
- // Strips punctuation/spaces, uppercases letters, truncates to 14 chars.
4
- // Preserves letters — safe for both numeric and alphanumeric CNPJs.
5
- export function normalizeCnpj(value: string): string {
6
- const clean = `${value || ''}`.replace(/[^A-Za-z0-9]/g, '').toUpperCase()
7
- return clean.substring(0, 14)
8
- }
9
-
10
- const WEIGHTS_D1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
11
- const WEIGHTS_D2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
12
-
13
- function charToValue(char: string): number {
14
- return char.charCodeAt(0) - 48
15
- }
16
-
17
- function calcDigit(base: string, weights: number[]): number {
18
- let sum = 0
19
- for (let i = 0; i < base.length; i++) {
20
- sum += charToValue(base[i]) * weights[i]
21
- }
22
- const r = sum % 11
23
- return r < 2 ? 0 : 11 - r
24
- }
25
-
26
- // Accepts raw or pre-normalized input (with or without punctuation/mask).
27
- // Validates numeric and alphanumeric CNPJs (Receita Federal 2026).
28
- export function isValidCnpj(value: string): boolean {
29
- const cnpj = normalizeCnpj(value)
30
-
31
- if (!/^[A-Z0-9]{12}[0-9]{2}$/.test(cnpj)) return false
32
- if (/^\d{14}$/.test(cnpj) && /^(\d)\1+$/.test(cnpj)) return false
33
-
34
- const base = cnpj.slice(0, 12)
35
- const d1 = calcDigit(base, WEIGHTS_D1)
36
- const d2 = calcDigit(`${base}${d1}`, WEIGHTS_D2)
37
- return cnpj.slice(12) === `${d1}${d2}`
38
- }
@@ -1,160 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Shared utilities: Alphanumeric CNPJ mask, formatting and validation
3
- // Used by: mbg-input-cpfcnpj, mbg-input-cnpj
4
- // ---------------------------------------------------------------------------
5
-
6
- import { isValidCnpj, normalizeCnpj } from './cnpj-validador'
7
- export { isValidCnpj as isValidAlphanumericCnpj }
8
- export { normalizeCnpj as normalizeAlphanumericCnpj }
9
-
10
- const CNPJ_MASK = '##.###.###/####-##'
11
- const CPF_MASK = '###.###.###-##'
12
-
13
- export function hasLetters(value: string): boolean {
14
- return /[A-Za-z]/.test(value)
15
- }
16
-
17
- export function formatCpf(clean: string): string {
18
- const digits = clean.replace(/[^0-9]/g, '').substring(0, 11)
19
- const result: string[] = []
20
- let digitIdx = 0
21
- for (let i = 0; i < CPF_MASK.length && digitIdx < digits.length; i++) {
22
- if (CPF_MASK[i] === '#') result.push(digits[digitIdx++])
23
- else result.push(CPF_MASK[i])
24
- }
25
- return result.join('')
26
- }
27
-
28
- function smartFormat(clean: string): string {
29
- if (!clean) return ''
30
- if (hasLetters(clean)) return formatAlphanumericCnpj(clean)
31
- if (clean.length <= 11) return formatCpf(clean)
32
- return formatAlphanumericCnpj(clean)
33
- }
34
-
35
- export function formatAlphanumericCnpj(clean: string): string {
36
- const safe = clean.substring(0, 14)
37
- const result: string[] = []
38
- let cleanIndex = 0
39
-
40
- for (let i = 0; i < CNPJ_MASK.length && cleanIndex < safe.length; i++) {
41
- const maskChar = CNPJ_MASK[i]
42
-
43
- if (maskChar === '#') {
44
- const char = safe[cleanIndex]
45
- const isCheckDigitPosition = cleanIndex >= 12
46
-
47
- if (isCheckDigitPosition) {
48
- if (/[0-9]/.test(char)) result.push(char)
49
- cleanIndex++
50
- } else {
51
- if (/[A-Z0-9]/.test(char)) result.push(char)
52
- cleanIndex++
53
- }
54
- } else {
55
- result.push(maskChar)
56
- }
57
- }
58
-
59
- return result.join('')
60
- }
61
-
62
- export function isCnpjCandidate(value: string): boolean {
63
- return value.length > 11 || hasLetters(value)
64
- }
65
-
66
- export function isCpfCandidate(value: string): boolean {
67
- return /^\d*$/.test(value) && value.length <= 11
68
- }
69
-
70
- function isRepeatedNumeric(value: string): boolean {
71
- return /^(\d)\1+$/.test(value)
72
- }
73
-
74
- function calculateCpfDigit(base: string, startWeight: number): number {
75
- let sum = 0
76
- for (let i = 0; i < base.length; i++) {
77
- sum += Number(base[i]) * (startWeight - i)
78
- }
79
- const remainder = sum % 11
80
- return remainder < 2 ? 0 : 11 - remainder
81
- }
82
-
83
- export function isValidCpf(value: string): boolean {
84
- if (!/^\d{11}$/.test(value) || isRepeatedNumeric(value)) return false
85
- const firstDigit = calculateCpfDigit(value.slice(0, 9), 10)
86
- const secondDigit = calculateCpfDigit(`${value.slice(0, 9)}${firstDigit}`, 11)
87
- return value === `${value.slice(0, 9)}${firstDigit}${secondDigit}`
88
- }
89
-
90
- function isDocumentValid(value: string): boolean {
91
- if (!value) return true
92
- if (isCpfCandidate(value)) {
93
- if (value.length < 11) return true
94
- return isValidCpf(value)
95
- }
96
- if (isCnpjCandidate(value)) {
97
- if (value.length < 14) {
98
- if (hasLetters(value)) return false
99
- return true
100
- }
101
- if (value.length > 14) return false
102
- return isValidCnpj(value)
103
- }
104
- return false
105
- }
106
-
107
- // ---------------------------------------------------------------------------
108
- // AngularJS directive factory — reusable in any module
109
- // ---------------------------------------------------------------------------
110
-
111
- class MbgDocumentMaskDirective {
112
- static $inject = []
113
-
114
- require = 'ngModel'
115
- restrict = 'A'
116
-
117
- link = (_scope, _element, _attrs, ngModel) => {
118
- ngModel.$parsers.push((viewValue: string) => {
119
- const clean = normalizeCnpj(viewValue || '')
120
- const formatted = smartFormat(clean)
121
-
122
- if ((viewValue || '') !== formatted) {
123
- ngModel.$setViewValue(formatted)
124
- ngModel.$render()
125
- }
126
-
127
- return clean
128
- })
129
-
130
- ngModel.$formatters.push((modelValue: string) => {
131
- return smartFormat(normalizeCnpj(modelValue || ''))
132
- })
133
-
134
- ngModel.$validators.cpf = (modelValue: string) => {
135
- const clean = normalizeCnpj(modelValue || '')
136
- if (!clean || !isCpfCandidate(clean)) return true
137
- if (clean.length < 11) return true
138
- return isValidCpf(clean)
139
- }
140
-
141
- ngModel.$validators.cnpj = (modelValue: string) => {
142
- const clean = normalizeCnpj(modelValue || '')
143
- if (!clean || !isCnpjCandidate(clean)) return true
144
- if (clean.length < 14) {
145
- if (hasLetters(clean)) return false
146
- if (clean.length >= 12 && /[A-Z]/.test(clean.slice(12))) return false
147
- return true
148
- }
149
- if (clean.length > 14) return false
150
- return isValidCnpj(clean)
151
- }
152
-
153
- ngModel.$validators.cpfcnpj = (modelValue: string) => {
154
- const clean = normalizeCnpj(modelValue || '')
155
- return isDocumentValid(clean)
156
- }
157
- }
158
- }
159
-
160
- export const mbgDocumentMaskDirective = () => new MbgDocumentMaskDirective()