@sankhyalabs/core 1.0.40 → 1.0.42

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.
Files changed (154) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +34 -0
  3. package/README.md +54 -54
  4. package/dist/application/Application.d.ts +8 -0
  5. package/dist/application/Application.js +19 -0
  6. package/dist/application/Application.js.map +1 -0
  7. package/dist/dataunit/DataUnit.d.ts +82 -82
  8. package/dist/dataunit/DataUnit.js +278 -278
  9. package/dist/dataunit/DataUnit.js.map +1 -1
  10. package/dist/dataunit/metadata/DataType.d.ts +9 -9
  11. package/dist/dataunit/metadata/DataType.js +36 -36
  12. package/dist/dataunit/metadata/DataType.js.map +1 -1
  13. package/dist/dataunit/metadata/UnitMetadata.d.ts +71 -71
  14. package/dist/dataunit/metadata/UnitMetadata.js +31 -31
  15. package/dist/dataunit/state/HistReducer.d.ts +10 -10
  16. package/dist/dataunit/state/HistReducer.js +27 -27
  17. package/dist/dataunit/state/HistReducer.js.map +1 -1
  18. package/dist/dataunit/state/StateManager.d.ts +57 -57
  19. package/dist/dataunit/state/StateManager.js +96 -96
  20. package/dist/dataunit/state/action/DataUnitAction.d.ts +28 -28
  21. package/dist/dataunit/state/action/DataUnitAction.js +33 -33
  22. package/dist/dataunit/state/slice/AddedRecordsSlice.d.ts +11 -11
  23. package/dist/dataunit/state/slice/AddedRecordsSlice.js +25 -25
  24. package/dist/dataunit/state/slice/AddedRecordsSlice.js.map +1 -1
  25. package/dist/dataunit/state/slice/ChangesSlice.d.ts +12 -12
  26. package/dist/dataunit/state/slice/ChangesSlice.js +72 -72
  27. package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
  28. package/dist/dataunit/state/slice/CurrentRecordsSlice.d.ts +11 -11
  29. package/dist/dataunit/state/slice/CurrentRecordsSlice.js +45 -45
  30. package/dist/dataunit/state/slice/CurrentRecordsSlice.js.map +1 -1
  31. package/dist/dataunit/state/slice/RecordsSlice.d.ts +10 -10
  32. package/dist/dataunit/state/slice/RecordsSlice.js +43 -43
  33. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  34. package/dist/dataunit/state/slice/RemovedRecordsSlice.d.ts +9 -9
  35. package/dist/dataunit/state/slice/RemovedRecordsSlice.js +24 -24
  36. package/dist/dataunit/state/slice/RemovedRecordsSlice.js.map +1 -1
  37. package/dist/dataunit/state/slice/SelectionSlice.d.ts +11 -11
  38. package/dist/dataunit/state/slice/SelectionSlice.js +111 -111
  39. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  40. package/dist/dataunit/state/slice/UnitMetadataSlice.d.ts +11 -11
  41. package/dist/dataunit/state/slice/UnitMetadataSlice.js +20 -20
  42. package/dist/dataunit/state/slice/UnitMetadataSlice.js.map +1 -1
  43. package/dist/http/AuthorizedServiceCaller.d.ts +11 -11
  44. package/dist/http/AuthorizedServiceCaller.js +53 -53
  45. package/dist/http/AuthorizedServiceCaller.js.map +1 -1
  46. package/dist/http/HttpProvider.d.ts +25 -25
  47. package/dist/http/HttpProvider.js +73 -73
  48. package/dist/http/HttpProvider.js.map +1 -1
  49. package/dist/http/RequestMetadata.d.ts +30 -30
  50. package/dist/http/RequestMetadata.js +24 -24
  51. package/dist/http/SkwHttpProvider.d.ts +9 -9
  52. package/dist/http/SkwHttpProvider.js +66 -67
  53. package/dist/http/SkwHttpProvider.js.map +1 -1
  54. package/dist/http/data-fetcher/HttpFetcher.d.ts +14 -0
  55. package/dist/http/data-fetcher/HttpFetcher.js +164 -0
  56. package/dist/http/data-fetcher/HttpFetcher.js.map +1 -0
  57. package/dist/http/data-fetcher/default/DefaultGraphQL.d.ts +3 -0
  58. package/dist/http/data-fetcher/default/DefaultGraphQL.js +18 -0
  59. package/dist/http/data-fetcher/default/DefaultGraphQL.js.map +1 -0
  60. package/dist/http/data-fetcher/default/application-config-fetcher.d.ts +6 -0
  61. package/dist/http/data-fetcher/default/application-config-fetcher.js +21 -0
  62. package/dist/http/data-fetcher/default/application-config-fetcher.js.map +1 -0
  63. package/dist/http/data-fetcher/default/data-unit-graphql.d.ts +3 -0
  64. package/dist/http/data-fetcher/default/data-unit-graphql.js +18 -0
  65. package/dist/http/data-fetcher/default/data-unit-graphql.js.map +1 -0
  66. package/dist/http/data-fetcher/default/dataunit-executor.d.ts +10 -0
  67. package/dist/http/data-fetcher/default/dataunit-executor.js +56 -0
  68. package/dist/http/data-fetcher/default/dataunit-executor.js.map +1 -0
  69. package/dist/http/data-fetcher/default/dataunit-fetcher.d.ts +9 -0
  70. package/dist/http/data-fetcher/default/dataunit-fetcher.js +69 -0
  71. package/dist/http/data-fetcher/default/dataunit-fetcher.js.map +1 -0
  72. package/dist/http/data-fetcher/default/form-config-fetcher.d.ts +2 -0
  73. package/dist/http/data-fetcher/default/form-config-fetcher.js +3 -0
  74. package/dist/http/data-fetcher/default/form-config-fetcher.js.map +1 -0
  75. package/dist/http/data-fetcher/default/grid-config-fetcher.d.ts +2 -0
  76. package/dist/http/data-fetcher/default/grid-config-fetcher.js +3 -0
  77. package/dist/http/data-fetcher/default/grid-config-fetcher.js.map +1 -0
  78. package/dist/http/data-fetcher/default/index.d.ts +0 -0
  79. package/dist/http/data-fetcher/default/index.js +2 -0
  80. package/dist/http/data-fetcher/default/index.js.map +1 -0
  81. package/dist/http/data-fetcher/default/sankhya-graphql.d.ts +3 -0
  82. package/dist/http/data-fetcher/default/sankhya-graphql.js +8 -0
  83. package/dist/http/data-fetcher/default/sankhya-graphql.js.map +1 -0
  84. package/dist/http/data-fetcher/graphql/DefaultGraphQl.d.ts +3 -0
  85. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js +18 -0
  86. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js.map +1 -0
  87. package/dist/http/data-fetcher/state/LoadStateManager.d.ts +23 -0
  88. package/dist/http/data-fetcher/state/LoadStateManager.js +78 -0
  89. package/dist/http/data-fetcher/state/LoadStateManager.js.map +1 -0
  90. package/dist/index.d.ts +16 -16
  91. package/dist/index.js +17 -17
  92. package/dist/index.js.map +1 -1
  93. package/dist/ui/FloatingManager.d.ts +24 -24
  94. package/dist/ui/FloatingManager.js +122 -123
  95. package/dist/ui/FloatingManager.js.map +1 -1
  96. package/dist/utils/ApplicationContext.d.ts +5 -5
  97. package/dist/utils/ApplicationContext.js +16 -16
  98. package/dist/utils/CriteriaModel.d.ts +109 -109
  99. package/dist/utils/CriteriaModel.js +173 -173
  100. package/dist/utils/CriteriaParameter.d.ts +69 -69
  101. package/dist/utils/CriteriaParameter.js +82 -84
  102. package/dist/utils/CriteriaParameter.js.map +1 -1
  103. package/dist/utils/DateUtils.d.ts +5 -5
  104. package/dist/utils/DateUtils.js +42 -42
  105. package/dist/utils/DateUtils.js.map +1 -1
  106. package/dist/utils/MaskFormatter.d.ts +126 -126
  107. package/dist/utils/MaskFormatter.js +275 -275
  108. package/dist/utils/NumberUtils.d.ts +53 -53
  109. package/dist/utils/NumberUtils.js +141 -146
  110. package/dist/utils/NumberUtils.js.map +1 -1
  111. package/dist/utils/StringUtils.d.ts +18 -18
  112. package/dist/utils/StringUtils.js +53 -53
  113. package/dist/utils/TimeFormatter.d.ts +33 -33
  114. package/dist/utils/TimeFormatter.js +97 -97
  115. package/dist/utils/TimeFormatter.js.map +1 -1
  116. package/jest.config.ts +16 -13
  117. package/mock/http/XMLHttpRequest-mock.js +25 -25
  118. package/package.json +37 -31
  119. package/src/dataunit/DataUnit.ts +356 -356
  120. package/src/dataunit/metadata/DataType.ts +37 -37
  121. package/src/dataunit/metadata/UnitMetadata.ts +82 -82
  122. package/src/dataunit/state/HistReducer.ts +33 -33
  123. package/src/dataunit/state/StateManager.ts +141 -141
  124. package/src/dataunit/state/action/DataUnitAction.ts +50 -50
  125. package/src/dataunit/state/slice/AddedRecordsSlice.ts +32 -32
  126. package/src/dataunit/state/slice/ChangesSlice.ts +90 -90
  127. package/src/dataunit/state/slice/CurrentRecordsSlice.ts +53 -53
  128. package/src/dataunit/state/slice/RecordsSlice.ts +56 -56
  129. package/src/dataunit/state/slice/RemovedRecordsSlice.ts +29 -29
  130. package/src/dataunit/state/slice/SelectionSlice.ts +130 -130
  131. package/src/dataunit/state/slice/UnitMetadataSlice.ts +29 -29
  132. package/src/http/AuthorizedServiceCaller.ts +58 -57
  133. package/src/http/HttpProvider.ts +93 -93
  134. package/src/http/RequestMetadata.ts +41 -41
  135. package/src/http/SkwHttpProvider.ts +77 -77
  136. package/src/index.ts +44 -44
  137. package/src/ui/FloatingManager.ts +165 -165
  138. package/src/utils/ApplicationContext.ts +18 -18
  139. package/src/utils/CriteriaModel.ts +207 -207
  140. package/src/utils/CriteriaParameter.ts +107 -107
  141. package/src/utils/DateUtils.ts +52 -52
  142. package/src/utils/MaskFormatter.ts +322 -322
  143. package/src/utils/NumberUtils.ts +175 -175
  144. package/src/utils/StringUtils.ts +60 -60
  145. package/src/utils/TimeFormatter.ts +97 -97
  146. package/test/http/HttpProvider.spec.ts +34 -34
  147. package/test/http/SkwHttpProvider.ts.spec.ts +33 -33
  148. package/test/util/CriteriaModel.spec.ts +231 -231
  149. package/test/util/CriteriaParameter.spec.ts +51 -51
  150. package/test/util/MaskFormatter.spec.ts +138 -138
  151. package/test/util/NumberUtils.spec.ts +156 -156
  152. package/test/util/StringUtils.spec.ts +43 -43
  153. package/test/util/TimeFormatter.spec.ts +25 -25
  154. package/tsconfig.json +15 -15
@@ -1,323 +1,323 @@
1
- /**
2
- * `MaskFormatter` é usado para formatar strings. Seu comportamento
3
- * é controlado pela formato do atributo `mask` que especifica quais
4
- * caracteres são válidos e onde devem estar posicionados, intercalando-os
5
- * com eventuais caracteres literais expressados no padrão informado.
6
- * Sua implementação é inspirada pela implementação em Java do [MaskFormatter](https://docs.oracle.com/javase/7/docs/api/javax/swing/text/MaskFormatter.html).
7
- *
8
- * Para o padrão da máscara podem ser usados os seguintes caracteres especiais:
9
- *
10
- * | Caractere | Comportamento |
11
- * |:---------:|-------------------------------------------------------------------------------------------------------------|
12
- * | # | Qualquer número |
13
- * | ' | "Escapa" o caractere que vem na sequência. Útil quando desejamos converter um caractere especial em literal.|
14
- * | U | Qualquer letra. Transforma letras maiúsculas em maiúsculas. |
15
- * | L | Qualquer letra. Transforma letras maiúsculas em minúsculas. |
16
- * | A | Qualquer letra ou número. |
17
- * | ? | Qualquer letra. Preserva maiúsculas e minúsculas. |
18
- * | * | Qualquer caractere. |
19
- *
20
- * Os demais caracteres presentes no padrão serão tratados como literais, isto é,
21
- * serão apenas inseridos naquela posição.
22
- *
23
- * Quando o o valor a ser formatado é menor que a máscara um 'placeHolder'
24
- * será inserido em cada posição ausente, completando a formatação.
25
- * Por padrão será usado um espaço em branco como 'placeHolder' mas
26
- * esse valor pode ser alterado.
27
- *
28
- * For por exemplo:
29
- * '''
30
- * const formatter: MaskFormatter = new MaskFormatter("###-####");
31
- * formatter.placeholder = '_';
32
- * console.log(formatter.format("123"));
33
- * '''
34
- * resultaria na string '123-____'.
35
- *
36
- * ##Veja mais alguns exemplos:
37
- * |Padrão |Máscara |Entrada |Saída |
38
- * |----------------|------------------|--------------|------------------|
39
- * |Telefone |(##) ####-#### |3432192515 |(34) 3219-2515 |
40
- * |CPF |###.###.###-## |12345678901 |123.456.789-01 |
41
- * |CNPJ |##.###.###/####-##|12345678901234|12.345.678/9012-34|
42
- * |CEP |##.###-### |12345678 |12.345-678 |
43
- * |PLACA (veículo) |UUU-#### |abc1234 |ABC-1234 |
44
- * |Cor RGB |'#AAAAAA |00000F0 |#0000F0 |
45
- *
46
- */
47
- export class MaskFormatter {
48
-
49
- private static DIGIT_KEY: string = "#";
50
- private static LITERAL_KEY: string = "'";
51
- private static UPPERCASE_KEY: string = "U";
52
- private static LOWERCASE_KEY: string = "L";
53
- private static ALPHA_NUMERIC_KEY: string = "A";
54
- private static CHARACTER_KEY: string = "?";
55
- private static ANYTHING_KEY: string = "*";
56
-
57
- private _mask: string = '';
58
- private _maskChars: Array<MaskFormatter.MaskCharacter> = new Array<MaskFormatter.MaskCharacter>();
59
-
60
- /**
61
- * Determina qual caractere será usado dos caracteres não presentes no valor
62
- * ou seja, aqueles que o usuário ainda não informou. Por padrão usamos um espaço
63
- */
64
- public placeholder: string = ' ';
65
-
66
- /**
67
- * Setter para mask. Trata-se do padrão que se espera ao formatar o texto.
68
- */
69
- public set mask(mask: string) {
70
- this._mask = mask;
71
- this.updateInternalMask();
72
- }
73
-
74
- /**
75
- * Getter para mask
76
- *
77
- * @return A última máscara informada.
78
- */
79
- public get mask(): string {
80
- return this._mask;
81
- }
82
-
83
- constructor(mask: string) {
84
- this.mask = mask;
85
- }
86
-
87
- /**
88
- * Formata a string passada baseada na máscara definda pelo atributo mask.
89
- *
90
- * @param value Valor a ser formatado
91
- * @return O valor processado de acordo com o padrão
92
- */
93
- public format(value: string): string {
94
- let result: string = '';
95
- const index: Array<number> = [0];
96
-
97
- let counter: number = 0;
98
- const maxCounter: number = this._maskChars.length;
99
- while (counter < maxCounter) {
100
- result = this._maskChars[counter].append(result, value, index);
101
- counter++;
102
- }
103
-
104
- return result;
105
- }
106
-
107
- /**
108
- * Preparamos a formatação internamente de acordo com o padrão.
109
- */
110
- private updateInternalMask(): void {
111
-
112
- this._maskChars.length = 0;
113
-
114
- if (this.mask != null) {
115
- let counter: number = 0;
116
- const maxCounter: number = this.mask.length;
117
- while (counter < maxCounter) {
118
-
119
- let maskChar: string = this.mask.charAt(counter);
120
-
121
- switch (maskChar) {
122
- case MaskFormatter.DIGIT_KEY:
123
- this._maskChars.push(new MaskFormatter.DigitMaskCharacter(this, maskChar));
124
- break;
125
- case MaskFormatter.LITERAL_KEY:
126
- if (++counter < maxCounter) {
127
- maskChar = this.mask.charAt(counter);
128
- this._maskChars.push(new MaskFormatter.LiteralCharacter(this, maskChar));
129
- }
130
- break;
131
- case MaskFormatter.UPPERCASE_KEY:
132
- this._maskChars.push(new MaskFormatter.UpperCaseCharacter(this, maskChar));
133
- break;
134
- case MaskFormatter.LOWERCASE_KEY:
135
- this._maskChars.push(new MaskFormatter.LowerCaseCharacter(this, maskChar));
136
- break;
137
- case MaskFormatter.ALPHA_NUMERIC_KEY:
138
- this._maskChars.push(new MaskFormatter.AlphaNumericCharacter(this, maskChar));
139
- break;
140
- case MaskFormatter.CHARACTER_KEY:
141
- this._maskChars.push(new MaskFormatter.CharCharacter(this, maskChar));
142
- break;
143
- case MaskFormatter.ANYTHING_KEY:
144
- this._maskChars.push(new MaskFormatter.MaskCharacter(this, maskChar));
145
- break;
146
- default:
147
- this._maskChars.push(new MaskFormatter.LiteralCharacter(this, maskChar));
148
- break;
149
- }
150
- counter++;
151
- }
152
- }
153
- }
154
-
155
- //
156
- // Classes internas usadas para representar a máscara.
157
- //
158
- public static MaskCharacter = class {
159
-
160
- public maskFormatter: MaskFormatter;
161
- public type: string;
162
-
163
- constructor(maskFormatter: MaskFormatter, type: string) {
164
- this.maskFormatter = maskFormatter;
165
- this.type = type;
166
- }
167
- /**
168
- * Cada subclasse deve sobrescrever o retornando true, caso represente
169
- * um caractere literal. Por padrão o retorno é false.
170
- */
171
- public isLiteral(): boolean {
172
- return false;
173
- }
174
-
175
- /**
176
- * Returns true if <code>aChar</code> is a valid reprensentation of
177
- * the receiver. The default implementation returns true if the
178
- * receiver represents a literal character and <code>getChar</code>
179
- * == aChar. Otherwise, this will return true is <code>aChar</code>
180
- * is contained in the valid characters and not contained
181
- * in the invalid characters.
182
- */
183
- public isValidCharacter(aChar: string): boolean {
184
- if (this.isLiteral()) {
185
- return (this.getChar(aChar) == aChar);
186
- }
187
-
188
- aChar = this.getChar(aChar);
189
-
190
- return true;
191
- }
192
-
193
- /**
194
- * Returns the character to insert for <code>aChar</code>. The
195
- * default implementation returns <code>aChar</code>. Subclasses
196
- * that wish to do some sort of mapping, perhaps lower case to upper
197
- * case should override this and do the necessary mapping.
198
- */
199
- public getChar(aChar: string): string {
200
- return aChar;
201
- }
202
-
203
- /**
204
- * Appends the necessary character in <code>formatting</code> at
205
- * <code>index</code> to <code>buff</code>.
206
- */
207
- public append(result: string, formatting: string, index: Array<number>): string {
208
-
209
- const inString: boolean = index[0] < formatting.length;
210
- const aChar: string = inString ? formatting.charAt(index[0]) : '';
211
-
212
- if (this.isLiteral()) {
213
- const literal: string = this.getChar(aChar);
214
- result += literal;
215
- if(literal === aChar){
216
- index[0] = index[0] + 1;
217
- }
218
- } else if (index[0] >= formatting.length) {
219
- result += this.maskFormatter.placeholder;
220
- index[0] = index[0] + 1;
221
- } else if (this.isValidCharacter(aChar)) {
222
- result += this.getChar(aChar);
223
- index[0] = index[0] + 1;
224
- } else {
225
- throw new Error(`Valor inválido: "${aChar}". Na posição ${index[0] + 1} espera-se ${this.getFormatMessage()}.`);
226
- }
227
-
228
- return result;
229
- }
230
-
231
- public getFormatMessage(): string{
232
- let message: string;
233
- switch(this.type){
234
- case MaskFormatter.UPPERCASE_KEY:
235
- case MaskFormatter.LOWERCASE_KEY:
236
- case MaskFormatter.CHARACTER_KEY:
237
- message = 'uma letra';
238
- break;
239
- case MaskFormatter.DIGIT_KEY:
240
- message = 'um número';
241
- break;
242
- case MaskFormatter.ALPHA_NUMERIC_KEY:
243
- message = 'uma letra ou um número';
244
- break;
245
- default:
246
- message = ''
247
- }
248
- return message;
249
- }
250
- }
251
-
252
- private static LiteralCharacter = class extends MaskFormatter.MaskCharacter {
253
-
254
- private _fixedChar: string;
255
-
256
- constructor(maskFormatter: MaskFormatter, fixedChar: string) {
257
- super(maskFormatter, fixedChar);
258
- this._fixedChar = fixedChar;
259
- }
260
-
261
- public isLiteral(): boolean {
262
- return true;
263
- }
264
-
265
- public getChar(aChar: string): string {
266
- aChar;
267
- return this._fixedChar;
268
- }
269
- }
270
-
271
- private static DigitMaskCharacter = class extends MaskFormatter.MaskCharacter {
272
-
273
- public isValidCharacter(aChar: string): boolean {
274
- return (this.isDigit(aChar) && super.isValidCharacter(aChar));
275
- }
276
-
277
- private isDigit(char: string): boolean {
278
- return char >= '0' && char <= '9'
279
- }
280
- }
281
-
282
- private static UpperCaseCharacter = class extends MaskFormatter.MaskCharacter {
283
- public isValidCharacter(aChar: string): boolean {
284
- return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
285
- }
286
-
287
- public getChar(aChar: string): string {
288
- return aChar.toUpperCase();
289
- }
290
- }
291
-
292
- private static LowerCaseCharacter = class extends MaskFormatter.MaskCharacter {
293
-
294
- public isValidCharacter(aChar: string): boolean {
295
- return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
296
- }
297
-
298
- public getChar(aChar: string): string {
299
- return aChar.toLocaleLowerCase();
300
- }
301
- }
302
-
303
- private static AlphaNumericCharacter = class extends MaskFormatter.MaskCharacter {
304
-
305
- public isValidCharacter(aChar: string): boolean {
306
- //FIXME: talvez seja problema usar regex aqui... avaliar se existe forma mais barata
307
- return (/[a-z0-9]/i.test(aChar)) && super.isValidCharacter(aChar);
308
- }
309
- }
310
-
311
- private static CharCharacter = class extends MaskFormatter.MaskCharacter {
312
- public isValidCharacter(aChar: string): boolean {
313
- //FIXME: talvez seja problema usar regex aqui... avaliar se existe forma mais barata
314
- return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
315
- }
316
-
317
- }
318
-
319
- }
320
-
321
- export namespace MaskFormatter {
322
- export type MaskCharacter = InstanceType<typeof MaskFormatter.MaskCharacter>;
1
+ /**
2
+ * `MaskFormatter` é usado para formatar strings. Seu comportamento
3
+ * é controlado pela formato do atributo `mask` que especifica quais
4
+ * caracteres são válidos e onde devem estar posicionados, intercalando-os
5
+ * com eventuais caracteres literais expressados no padrão informado.
6
+ * Sua implementação é inspirada pela implementação em Java do [MaskFormatter](https://docs.oracle.com/javase/7/docs/api/javax/swing/text/MaskFormatter.html).
7
+ *
8
+ * Para o padrão da máscara podem ser usados os seguintes caracteres especiais:
9
+ *
10
+ * | Caractere | Comportamento |
11
+ * |:---------:|-------------------------------------------------------------------------------------------------------------|
12
+ * | # | Qualquer número |
13
+ * | ' | "Escapa" o caractere que vem na sequência. Útil quando desejamos converter um caractere especial em literal.|
14
+ * | U | Qualquer letra. Transforma letras maiúsculas em maiúsculas. |
15
+ * | L | Qualquer letra. Transforma letras maiúsculas em minúsculas. |
16
+ * | A | Qualquer letra ou número. |
17
+ * | ? | Qualquer letra. Preserva maiúsculas e minúsculas. |
18
+ * | * | Qualquer caractere. |
19
+ *
20
+ * Os demais caracteres presentes no padrão serão tratados como literais, isto é,
21
+ * serão apenas inseridos naquela posição.
22
+ *
23
+ * Quando o o valor a ser formatado é menor que a máscara um 'placeHolder'
24
+ * será inserido em cada posição ausente, completando a formatação.
25
+ * Por padrão será usado um espaço em branco como 'placeHolder' mas
26
+ * esse valor pode ser alterado.
27
+ *
28
+ * For por exemplo:
29
+ * '''
30
+ * const formatter: MaskFormatter = new MaskFormatter("###-####");
31
+ * formatter.placeholder = '_';
32
+ * console.log(formatter.format("123"));
33
+ * '''
34
+ * resultaria na string '123-____'.
35
+ *
36
+ * ##Veja mais alguns exemplos:
37
+ * |Padrão |Máscara |Entrada |Saída |
38
+ * |----------------|------------------|--------------|------------------|
39
+ * |Telefone |(##) ####-#### |3432192515 |(34) 3219-2515 |
40
+ * |CPF |###.###.###-## |12345678901 |123.456.789-01 |
41
+ * |CNPJ |##.###.###/####-##|12345678901234|12.345.678/9012-34|
42
+ * |CEP |##.###-### |12345678 |12.345-678 |
43
+ * |PLACA (veículo) |UUU-#### |abc1234 |ABC-1234 |
44
+ * |Cor RGB |'#AAAAAA |00000F0 |#0000F0 |
45
+ *
46
+ */
47
+ export class MaskFormatter {
48
+
49
+ private static DIGIT_KEY: string = "#";
50
+ private static LITERAL_KEY: string = "'";
51
+ private static UPPERCASE_KEY: string = "U";
52
+ private static LOWERCASE_KEY: string = "L";
53
+ private static ALPHA_NUMERIC_KEY: string = "A";
54
+ private static CHARACTER_KEY: string = "?";
55
+ private static ANYTHING_KEY: string = "*";
56
+
57
+ private _mask: string = '';
58
+ private _maskChars: Array<MaskFormatter.MaskCharacter> = new Array<MaskFormatter.MaskCharacter>();
59
+
60
+ /**
61
+ * Determina qual caractere será usado dos caracteres não presentes no valor
62
+ * ou seja, aqueles que o usuário ainda não informou. Por padrão usamos um espaço
63
+ */
64
+ public placeholder: string = ' ';
65
+
66
+ /**
67
+ * Setter para mask. Trata-se do padrão que se espera ao formatar o texto.
68
+ */
69
+ public set mask(mask: string) {
70
+ this._mask = mask;
71
+ this.updateInternalMask();
72
+ }
73
+
74
+ /**
75
+ * Getter para mask
76
+ *
77
+ * @return A última máscara informada.
78
+ */
79
+ public get mask(): string {
80
+ return this._mask;
81
+ }
82
+
83
+ constructor(mask: string) {
84
+ this.mask = mask;
85
+ }
86
+
87
+ /**
88
+ * Formata a string passada baseada na máscara definda pelo atributo mask.
89
+ *
90
+ * @param value Valor a ser formatado
91
+ * @return O valor processado de acordo com o padrão
92
+ */
93
+ public format(value: string): string {
94
+ let result: string = '';
95
+ const index: Array<number> = [0];
96
+
97
+ let counter: number = 0;
98
+ const maxCounter: number = this._maskChars.length;
99
+ while (counter < maxCounter) {
100
+ result = this._maskChars[counter].append(result, value, index);
101
+ counter++;
102
+ }
103
+
104
+ return result;
105
+ }
106
+
107
+ /**
108
+ * Preparamos a formatação internamente de acordo com o padrão.
109
+ */
110
+ private updateInternalMask(): void {
111
+
112
+ this._maskChars.length = 0;
113
+
114
+ if (this.mask != null) {
115
+ let counter: number = 0;
116
+ const maxCounter: number = this.mask.length;
117
+ while (counter < maxCounter) {
118
+
119
+ let maskChar: string = this.mask.charAt(counter);
120
+
121
+ switch (maskChar) {
122
+ case MaskFormatter.DIGIT_KEY:
123
+ this._maskChars.push(new MaskFormatter.DigitMaskCharacter(this, maskChar));
124
+ break;
125
+ case MaskFormatter.LITERAL_KEY:
126
+ if (++counter < maxCounter) {
127
+ maskChar = this.mask.charAt(counter);
128
+ this._maskChars.push(new MaskFormatter.LiteralCharacter(this, maskChar));
129
+ }
130
+ break;
131
+ case MaskFormatter.UPPERCASE_KEY:
132
+ this._maskChars.push(new MaskFormatter.UpperCaseCharacter(this, maskChar));
133
+ break;
134
+ case MaskFormatter.LOWERCASE_KEY:
135
+ this._maskChars.push(new MaskFormatter.LowerCaseCharacter(this, maskChar));
136
+ break;
137
+ case MaskFormatter.ALPHA_NUMERIC_KEY:
138
+ this._maskChars.push(new MaskFormatter.AlphaNumericCharacter(this, maskChar));
139
+ break;
140
+ case MaskFormatter.CHARACTER_KEY:
141
+ this._maskChars.push(new MaskFormatter.CharCharacter(this, maskChar));
142
+ break;
143
+ case MaskFormatter.ANYTHING_KEY:
144
+ this._maskChars.push(new MaskFormatter.MaskCharacter(this, maskChar));
145
+ break;
146
+ default:
147
+ this._maskChars.push(new MaskFormatter.LiteralCharacter(this, maskChar));
148
+ break;
149
+ }
150
+ counter++;
151
+ }
152
+ }
153
+ }
154
+
155
+ //
156
+ // Classes internas usadas para representar a máscara.
157
+ //
158
+ public static MaskCharacter = class {
159
+
160
+ public maskFormatter: MaskFormatter;
161
+ public type: string;
162
+
163
+ constructor(maskFormatter: MaskFormatter, type: string) {
164
+ this.maskFormatter = maskFormatter;
165
+ this.type = type;
166
+ }
167
+ /**
168
+ * Cada subclasse deve sobrescrever o retornando true, caso represente
169
+ * um caractere literal. Por padrão o retorno é false.
170
+ */
171
+ public isLiteral(): boolean {
172
+ return false;
173
+ }
174
+
175
+ /**
176
+ * Returns true if <code>aChar</code> is a valid reprensentation of
177
+ * the receiver. The default implementation returns true if the
178
+ * receiver represents a literal character and <code>getChar</code>
179
+ * == aChar. Otherwise, this will return true is <code>aChar</code>
180
+ * is contained in the valid characters and not contained
181
+ * in the invalid characters.
182
+ */
183
+ public isValidCharacter(aChar: string): boolean {
184
+ if (this.isLiteral()) {
185
+ return (this.getChar(aChar) == aChar);
186
+ }
187
+
188
+ aChar = this.getChar(aChar);
189
+
190
+ return true;
191
+ }
192
+
193
+ /**
194
+ * Returns the character to insert for <code>aChar</code>. The
195
+ * default implementation returns <code>aChar</code>. Subclasses
196
+ * that wish to do some sort of mapping, perhaps lower case to upper
197
+ * case should override this and do the necessary mapping.
198
+ */
199
+ public getChar(aChar: string): string {
200
+ return aChar;
201
+ }
202
+
203
+ /**
204
+ * Appends the necessary character in <code>formatting</code> at
205
+ * <code>index</code> to <code>buff</code>.
206
+ */
207
+ public append(result: string, formatting: string, index: Array<number>): string {
208
+
209
+ const inString: boolean = index[0] < formatting.length;
210
+ const aChar: string = inString ? formatting.charAt(index[0]) : '';
211
+
212
+ if (this.isLiteral()) {
213
+ const literal: string = this.getChar(aChar);
214
+ result += literal;
215
+ if(literal === aChar){
216
+ index[0] = index[0] + 1;
217
+ }
218
+ } else if (index[0] >= formatting.length) {
219
+ result += this.maskFormatter.placeholder;
220
+ index[0] = index[0] + 1;
221
+ } else if (this.isValidCharacter(aChar)) {
222
+ result += this.getChar(aChar);
223
+ index[0] = index[0] + 1;
224
+ } else {
225
+ throw new Error(`Valor inválido: "${aChar}". Na posição ${index[0] + 1} espera-se ${this.getFormatMessage()}.`);
226
+ }
227
+
228
+ return result;
229
+ }
230
+
231
+ public getFormatMessage(): string{
232
+ let message: string;
233
+ switch(this.type){
234
+ case MaskFormatter.UPPERCASE_KEY:
235
+ case MaskFormatter.LOWERCASE_KEY:
236
+ case MaskFormatter.CHARACTER_KEY:
237
+ message = 'uma letra';
238
+ break;
239
+ case MaskFormatter.DIGIT_KEY:
240
+ message = 'um número';
241
+ break;
242
+ case MaskFormatter.ALPHA_NUMERIC_KEY:
243
+ message = 'uma letra ou um número';
244
+ break;
245
+ default:
246
+ message = ''
247
+ }
248
+ return message;
249
+ }
250
+ }
251
+
252
+ private static LiteralCharacter = class extends MaskFormatter.MaskCharacter {
253
+
254
+ private _fixedChar: string;
255
+
256
+ constructor(maskFormatter: MaskFormatter, fixedChar: string) {
257
+ super(maskFormatter, fixedChar);
258
+ this._fixedChar = fixedChar;
259
+ }
260
+
261
+ public isLiteral(): boolean {
262
+ return true;
263
+ }
264
+
265
+ public getChar(aChar: string): string {
266
+ aChar;
267
+ return this._fixedChar;
268
+ }
269
+ }
270
+
271
+ private static DigitMaskCharacter = class extends MaskFormatter.MaskCharacter {
272
+
273
+ public isValidCharacter(aChar: string): boolean {
274
+ return (this.isDigit(aChar) && super.isValidCharacter(aChar));
275
+ }
276
+
277
+ private isDigit(char: string): boolean {
278
+ return char >= '0' && char <= '9'
279
+ }
280
+ }
281
+
282
+ private static UpperCaseCharacter = class extends MaskFormatter.MaskCharacter {
283
+ public isValidCharacter(aChar: string): boolean {
284
+ return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
285
+ }
286
+
287
+ public getChar(aChar: string): string {
288
+ return aChar.toUpperCase();
289
+ }
290
+ }
291
+
292
+ private static LowerCaseCharacter = class extends MaskFormatter.MaskCharacter {
293
+
294
+ public isValidCharacter(aChar: string): boolean {
295
+ return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
296
+ }
297
+
298
+ public getChar(aChar: string): string {
299
+ return aChar.toLocaleLowerCase();
300
+ }
301
+ }
302
+
303
+ private static AlphaNumericCharacter = class extends MaskFormatter.MaskCharacter {
304
+
305
+ public isValidCharacter(aChar: string): boolean {
306
+ //FIXME: talvez seja problema usar regex aqui... avaliar se existe forma mais barata
307
+ return (/[a-z0-9]/i.test(aChar)) && super.isValidCharacter(aChar);
308
+ }
309
+ }
310
+
311
+ private static CharCharacter = class extends MaskFormatter.MaskCharacter {
312
+ public isValidCharacter(aChar: string): boolean {
313
+ //FIXME: talvez seja problema usar regex aqui... avaliar se existe forma mais barata
314
+ return (/[a-z]/i.test(aChar) && super.isValidCharacter(aChar));
315
+ }
316
+
317
+ }
318
+
319
+ }
320
+
321
+ export namespace MaskFormatter {
322
+ export type MaskCharacter = InstanceType<typeof MaskFormatter.MaskCharacter>;
323
323
  }