@rainersoft/utils 1.0.0
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/README.md +176 -0
- package/dist/date/index.d.mts +9 -0
- package/dist/date/index.d.ts +9 -0
- package/dist/date/index.js +105 -0
- package/dist/date/index.js.map +1 -0
- package/dist/date/index.mjs +99 -0
- package/dist/date/index.mjs.map +1 -0
- package/dist/index.d.mts +108 -0
- package/dist/index.d.ts +108 -0
- package/dist/index.js +846 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +797 -0
- package/dist/index.mjs.map +1 -0
- package/dist/number/index.d.mts +11 -0
- package/dist/number/index.d.ts +11 -0
- package/dist/number/index.js +61 -0
- package/dist/number/index.js.map +1 -0
- package/dist/number/index.mjs +53 -0
- package/dist/number/index.mjs.map +1 -0
- package/dist/status/index.d.mts +8 -0
- package/dist/status/index.d.ts +8 -0
- package/dist/status/index.js +126 -0
- package/dist/status/index.js.map +1 -0
- package/dist/status/index.mjs +122 -0
- package/dist/status/index.mjs.map +1 -0
- package/dist/string/index.d.mts +9 -0
- package/dist/string/index.d.ts +9 -0
- package/dist/string/index.js +35 -0
- package/dist/string/index.js.map +1 -0
- package/dist/string/index.mjs +27 -0
- package/dist/string/index.mjs.map +1 -0
- package/dist/types-tUMATEGI.d.mts +10 -0
- package/dist/types-tUMATEGI.d.ts +10 -0
- package/package.json +87 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var DEFAULT_LOCALE = "pt-BR";
|
|
3
|
+
|
|
4
|
+
// src/status/index.ts
|
|
5
|
+
var STATUS_TRANSLATIONS = {
|
|
6
|
+
"pt-BR": {
|
|
7
|
+
// Estados de conteúdo
|
|
8
|
+
DRAFT: "Rascunho",
|
|
9
|
+
PUBLISHED: "Publicado",
|
|
10
|
+
ARCHIVED: "Arquivado",
|
|
11
|
+
SCHEDULED: "Agendado",
|
|
12
|
+
DELETED: "Exclu\xEDdo",
|
|
13
|
+
// Estados de processo
|
|
14
|
+
PENDING: "Pendente",
|
|
15
|
+
ACTIVE: "Ativo",
|
|
16
|
+
INACTIVE: "Inativo",
|
|
17
|
+
COMPLETED: "Conclu\xEDdo",
|
|
18
|
+
CANCELLED: "Cancelado",
|
|
19
|
+
// Estados de aprovação
|
|
20
|
+
APPROVED: "Aprovado",
|
|
21
|
+
REJECTED: "Rejeitado",
|
|
22
|
+
// Estados de pedido/pagamento
|
|
23
|
+
PROCESSING: "Processando",
|
|
24
|
+
PAID: "Pago",
|
|
25
|
+
UNPAID: "N\xE3o Pago",
|
|
26
|
+
REFUNDED: "Reembolsado",
|
|
27
|
+
FAILED: "Falhou",
|
|
28
|
+
// Estados de usuário
|
|
29
|
+
VERIFIED: "Verificado",
|
|
30
|
+
UNVERIFIED: "N\xE3o Verificado",
|
|
31
|
+
BANNED: "Banido",
|
|
32
|
+
SUSPENDED: "Suspenso"
|
|
33
|
+
},
|
|
34
|
+
"en-US": {
|
|
35
|
+
DRAFT: "Draft",
|
|
36
|
+
PUBLISHED: "Published",
|
|
37
|
+
ARCHIVED: "Archived",
|
|
38
|
+
SCHEDULED: "Scheduled",
|
|
39
|
+
DELETED: "Deleted",
|
|
40
|
+
PENDING: "Pending",
|
|
41
|
+
ACTIVE: "Active",
|
|
42
|
+
INACTIVE: "Inactive",
|
|
43
|
+
COMPLETED: "Completed",
|
|
44
|
+
CANCELLED: "Cancelled",
|
|
45
|
+
APPROVED: "Approved",
|
|
46
|
+
REJECTED: "Rejected",
|
|
47
|
+
PROCESSING: "Processing",
|
|
48
|
+
PAID: "Paid",
|
|
49
|
+
UNPAID: "Unpaid",
|
|
50
|
+
REFUNDED: "Refunded",
|
|
51
|
+
FAILED: "Failed",
|
|
52
|
+
VERIFIED: "Verified",
|
|
53
|
+
UNVERIFIED: "Unverified",
|
|
54
|
+
BANNED: "Banned",
|
|
55
|
+
SUSPENDED: "Suspended"
|
|
56
|
+
},
|
|
57
|
+
"es-ES": {
|
|
58
|
+
DRAFT: "Borrador",
|
|
59
|
+
PUBLISHED: "Publicado",
|
|
60
|
+
ARCHIVED: "Archivado",
|
|
61
|
+
SCHEDULED: "Programado",
|
|
62
|
+
DELETED: "Eliminado",
|
|
63
|
+
PENDING: "Pendiente",
|
|
64
|
+
ACTIVE: "Activo",
|
|
65
|
+
INACTIVE: "Inactivo",
|
|
66
|
+
COMPLETED: "Completado",
|
|
67
|
+
CANCELLED: "Cancelado",
|
|
68
|
+
APPROVED: "Aprobado",
|
|
69
|
+
REJECTED: "Rechazado",
|
|
70
|
+
PROCESSING: "Procesando",
|
|
71
|
+
PAID: "Pagado",
|
|
72
|
+
UNPAID: "No Pagado",
|
|
73
|
+
REFUNDED: "Reembolsado",
|
|
74
|
+
FAILED: "Fallido",
|
|
75
|
+
VERIFIED: "Verificado",
|
|
76
|
+
UNVERIFIED: "No Verificado",
|
|
77
|
+
BANNED: "Bloqueado",
|
|
78
|
+
SUSPENDED: "Suspendido"
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function translateStatus(status, locale = DEFAULT_LOCALE) {
|
|
82
|
+
const normalized = status.toUpperCase();
|
|
83
|
+
return STATUS_TRANSLATIONS[locale][normalized] || status;
|
|
84
|
+
}
|
|
85
|
+
function getStatusColor(status) {
|
|
86
|
+
const normalized = status.toUpperCase();
|
|
87
|
+
const colorMap = {
|
|
88
|
+
DRAFT: "text-gray-600",
|
|
89
|
+
PENDING: "text-yellow-600",
|
|
90
|
+
PUBLISHED: "text-green-600",
|
|
91
|
+
ACTIVE: "text-green-600",
|
|
92
|
+
INACTIVE: "text-gray-600",
|
|
93
|
+
ARCHIVED: "text-orange-600",
|
|
94
|
+
DELETED: "text-red-600",
|
|
95
|
+
SCHEDULED: "text-blue-600",
|
|
96
|
+
COMPLETED: "text-green-600",
|
|
97
|
+
CANCELLED: "text-red-600",
|
|
98
|
+
APPROVED: "text-green-600",
|
|
99
|
+
REJECTED: "text-red-600",
|
|
100
|
+
FAILED: "text-red-600",
|
|
101
|
+
VERIFIED: "text-green-600",
|
|
102
|
+
BANNED: "text-red-600"
|
|
103
|
+
};
|
|
104
|
+
return colorMap[normalized] || "text-gray-600";
|
|
105
|
+
}
|
|
106
|
+
function getStatusVariant(status) {
|
|
107
|
+
const normalized = status.toUpperCase();
|
|
108
|
+
if (["PUBLISHED", "ACTIVE", "COMPLETED", "APPROVED", "VERIFIED"].includes(normalized)) {
|
|
109
|
+
return "default";
|
|
110
|
+
}
|
|
111
|
+
if (["DELETED", "CANCELLED", "REJECTED", "FAILED", "BANNED"].includes(normalized)) {
|
|
112
|
+
return "destructive";
|
|
113
|
+
}
|
|
114
|
+
if (["DRAFT", "INACTIVE", "ARCHIVED"].includes(normalized)) {
|
|
115
|
+
return "secondary";
|
|
116
|
+
}
|
|
117
|
+
return "outline";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { getStatusColor, getStatusVariant, translateStatus };
|
|
121
|
+
//# sourceMappingURL=index.mjs.map
|
|
122
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts","../../src/status/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Types & Constants\r\n *\r\n * Tipos e constantes compartilhadas entre módulos.\r\n *\r\n * @module @rainersoft/utils/types\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Idiomas suportados\r\n */\r\nexport type Locale = 'pt-BR' | 'en-US' | 'es-ES';\r\n\r\n/**\r\n * Configuração de localização\r\n */\r\nexport interface LocaleConfig {\r\n locale: Locale;\r\n currency?: string;\r\n dateFormat?: 'short' | 'long' | 'full';\r\n}\r\n\r\n/**\r\n * Locale padrão\r\n */\r\nexport const DEFAULT_LOCALE: Locale = 'pt-BR';\r\n\r\n/**\r\n * Mapeamento de moedas por locale\r\n */\r\nexport const CURRENCY_MAP: Record<Locale, string> = {\r\n 'pt-BR': 'BRL',\r\n 'en-US': 'USD',\r\n 'es-ES': 'EUR',\r\n} as const;\r\n","/**\r\n * Status Utilities\r\n *\r\n * Utilitários para tradução e manipulação de status.\r\n * Agnóstico de domínio - pode ser usado para posts, pedidos, tarefas, etc.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/status\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport type { Locale } from '../types';\r\nimport { DEFAULT_LOCALE } from '../types';\r\n\r\n/**\r\n * Status genéricos de entidades\r\n */\r\nexport type GenericStatus =\r\n | 'DRAFT'\r\n | 'PENDING'\r\n | 'PUBLISHED'\r\n | 'ACTIVE'\r\n | 'INACTIVE'\r\n | 'ARCHIVED'\r\n | 'DELETED'\r\n | 'SCHEDULED'\r\n | 'COMPLETED'\r\n | 'CANCELLED'\r\n | 'APPROVED'\r\n | 'REJECTED';\r\n\r\n/**\r\n * Traduções de status por idioma\r\n */\r\nconst STATUS_TRANSLATIONS: Record<Locale, Record<string, string>> = {\r\n 'pt-BR': {\r\n // Estados de conteúdo\r\n DRAFT: 'Rascunho',\r\n PUBLISHED: 'Publicado',\r\n ARCHIVED: 'Arquivado',\r\n SCHEDULED: 'Agendado',\r\n DELETED: 'Excluído',\r\n \r\n // Estados de processo\r\n PENDING: 'Pendente',\r\n ACTIVE: 'Ativo',\r\n INACTIVE: 'Inativo',\r\n COMPLETED: 'Concluído',\r\n CANCELLED: 'Cancelado',\r\n \r\n // Estados de aprovação\r\n APPROVED: 'Aprovado',\r\n REJECTED: 'Rejeitado',\r\n \r\n // Estados de pedido/pagamento\r\n PROCESSING: 'Processando',\r\n PAID: 'Pago',\r\n UNPAID: 'Não Pago',\r\n REFUNDED: 'Reembolsado',\r\n FAILED: 'Falhou',\r\n \r\n // Estados de usuário\r\n VERIFIED: 'Verificado',\r\n UNVERIFIED: 'Não Verificado',\r\n BANNED: 'Banido',\r\n SUSPENDED: 'Suspenso',\r\n },\r\n 'en-US': {\r\n DRAFT: 'Draft',\r\n PUBLISHED: 'Published',\r\n ARCHIVED: 'Archived',\r\n SCHEDULED: 'Scheduled',\r\n DELETED: 'Deleted',\r\n PENDING: 'Pending',\r\n ACTIVE: 'Active',\r\n INACTIVE: 'Inactive',\r\n COMPLETED: 'Completed',\r\n CANCELLED: 'Cancelled',\r\n APPROVED: 'Approved',\r\n REJECTED: 'Rejected',\r\n PROCESSING: 'Processing',\r\n PAID: 'Paid',\r\n UNPAID: 'Unpaid',\r\n REFUNDED: 'Refunded',\r\n FAILED: 'Failed',\r\n VERIFIED: 'Verified',\r\n UNVERIFIED: 'Unverified',\r\n BANNED: 'Banned',\r\n SUSPENDED: 'Suspended',\r\n },\r\n 'es-ES': {\r\n DRAFT: 'Borrador',\r\n PUBLISHED: 'Publicado',\r\n ARCHIVED: 'Archivado',\r\n SCHEDULED: 'Programado',\r\n DELETED: 'Eliminado',\r\n PENDING: 'Pendiente',\r\n ACTIVE: 'Activo',\r\n INACTIVE: 'Inactivo',\r\n COMPLETED: 'Completado',\r\n CANCELLED: 'Cancelado',\r\n APPROVED: 'Aprobado',\r\n REJECTED: 'Rechazado',\r\n PROCESSING: 'Procesando',\r\n PAID: 'Pagado',\r\n UNPAID: 'No Pagado',\r\n REFUNDED: 'Reembolsado',\r\n FAILED: 'Fallido',\r\n VERIFIED: 'Verificado',\r\n UNVERIFIED: 'No Verificado',\r\n BANNED: 'Bloqueado',\r\n SUSPENDED: 'Suspendido',\r\n },\r\n} as const;\r\n\r\n/**\r\n * Traduz status com suporte a idiomas\r\n *\r\n * @param status - Status em inglês (uppercase)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Status traduzido\r\n *\r\n * @example\r\n * translateStatus('DRAFT') // 'Rascunho' (pt-BR)\r\n * translateStatus('DRAFT', 'en-US') // 'Draft'\r\n * translateStatus('DRAFT', 'es-ES') // 'Borrador'\r\n */\r\nexport function translateStatus(status: string, locale: Locale = DEFAULT_LOCALE): string {\r\n const normalized = status.toUpperCase();\r\n return STATUS_TRANSLATIONS[locale][normalized] || status;\r\n}\r\n\r\n/**\r\n * Obtém cor baseada no status\r\n *\r\n * @param status - Status\r\n * @returns Classe Tailwind de cor\r\n *\r\n * @example\r\n * getStatusColor('PUBLISHED') // 'text-green-600'\r\n * getStatusColor('DRAFT') // 'text-gray-600'\r\n */\r\nexport function getStatusColor(status: string): string {\r\n const normalized = status.toUpperCase();\r\n \r\n const colorMap: Record<string, string> = {\r\n DRAFT: 'text-gray-600',\r\n PENDING: 'text-yellow-600',\r\n PUBLISHED: 'text-green-600',\r\n ACTIVE: 'text-green-600',\r\n INACTIVE: 'text-gray-600',\r\n ARCHIVED: 'text-orange-600',\r\n DELETED: 'text-red-600',\r\n SCHEDULED: 'text-blue-600',\r\n COMPLETED: 'text-green-600',\r\n CANCELLED: 'text-red-600',\r\n APPROVED: 'text-green-600',\r\n REJECTED: 'text-red-600',\r\n FAILED: 'text-red-600',\r\n VERIFIED: 'text-green-600',\r\n BANNED: 'text-red-600',\r\n };\r\n \r\n return colorMap[normalized] || 'text-gray-600';\r\n}\r\n\r\n/**\r\n * Obtém badge variant baseado no status\r\n *\r\n * @param status - Status\r\n * @returns Variant do badge\r\n *\r\n * @example\r\n * getStatusVariant('PUBLISHED') // 'success'\r\n * getStatusVariant('DRAFT') // 'secondary'\r\n */\r\nexport function getStatusVariant(status: string): 'default' | 'secondary' | 'destructive' | 'outline' {\r\n const normalized = status.toUpperCase();\r\n \r\n if (['PUBLISHED', 'ACTIVE', 'COMPLETED', 'APPROVED', 'VERIFIED'].includes(normalized)) {\r\n return 'default'; // Verde/sucesso\r\n }\r\n \r\n if (['DELETED', 'CANCELLED', 'REJECTED', 'FAILED', 'BANNED'].includes(normalized)) {\r\n return 'destructive'; // Vermelho/erro\r\n }\r\n \r\n if (['DRAFT', 'INACTIVE', 'ARCHIVED'].includes(normalized)) {\r\n return 'secondary'; // Cinza/neutro\r\n }\r\n \r\n return 'outline'; // Padrão\r\n}\r\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare function textToSlug(text: string): string;
|
|
2
|
+
declare function capitalize(text: string): string;
|
|
3
|
+
declare function truncate(text: string, maxLength: number, suffix?: string): string;
|
|
4
|
+
declare function removeAccents(text: string): string;
|
|
5
|
+
declare function getInitials(name: string, maxInitials?: number): string;
|
|
6
|
+
declare function isEmpty(text: string | null | undefined): boolean;
|
|
7
|
+
declare function wordCount(text: string): number;
|
|
8
|
+
|
|
9
|
+
export { capitalize, getInitials, isEmpty, removeAccents, textToSlug, truncate, wordCount };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare function textToSlug(text: string): string;
|
|
2
|
+
declare function capitalize(text: string): string;
|
|
3
|
+
declare function truncate(text: string, maxLength: number, suffix?: string): string;
|
|
4
|
+
declare function removeAccents(text: string): string;
|
|
5
|
+
declare function getInitials(name: string, maxInitials?: number): string;
|
|
6
|
+
declare function isEmpty(text: string | null | undefined): boolean;
|
|
7
|
+
declare function wordCount(text: string): number;
|
|
8
|
+
|
|
9
|
+
export { capitalize, getInitials, isEmpty, removeAccents, textToSlug, truncate, wordCount };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/string/index.ts
|
|
4
|
+
function textToSlug(text) {
|
|
5
|
+
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
6
|
+
}
|
|
7
|
+
function capitalize(text) {
|
|
8
|
+
return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
9
|
+
}
|
|
10
|
+
function truncate(text, maxLength, suffix = "...") {
|
|
11
|
+
if (text.length <= maxLength) return text;
|
|
12
|
+
return text.slice(0, maxLength - suffix.length) + suffix;
|
|
13
|
+
}
|
|
14
|
+
function removeAccents(text) {
|
|
15
|
+
return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
16
|
+
}
|
|
17
|
+
function getInitials(name, maxInitials = 2) {
|
|
18
|
+
return name.split(" ").filter((word) => word.length > 0).map((word) => word[0]).join("").toUpperCase().slice(0, maxInitials);
|
|
19
|
+
}
|
|
20
|
+
function isEmpty(text) {
|
|
21
|
+
return !text || text.trim().length === 0;
|
|
22
|
+
}
|
|
23
|
+
function wordCount(text) {
|
|
24
|
+
return text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.capitalize = capitalize;
|
|
28
|
+
exports.getInitials = getInitials;
|
|
29
|
+
exports.isEmpty = isEmpty;
|
|
30
|
+
exports.removeAccents = removeAccents;
|
|
31
|
+
exports.textToSlug = textToSlug;
|
|
32
|
+
exports.truncate = truncate;
|
|
33
|
+
exports.wordCount = wordCount;
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/string/index.ts"],"names":[],"mappings":";;;AAoBO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,aAAY,CACZ,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA,CAC9B,OAAA,CAAQ,aAAa,EAAE,CAAA,CACvB,MAAK,CACL,OAAA,CAAQ,QAAQ,GAAG,CAAA,CACnB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AACvB;AAWO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,aAAY,CACZ,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,UAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,KAAgB,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,CACxD,KAAK,GAAG,CAAA;AACb;AAaO,SAAS,QAAA,CAAS,IAAA,EAAc,SAAA,EAAmB,MAAA,GAAS,KAAA,EAAe;AAChF,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,SAAA,EAAW,OAAO,IAAA;AACrC,EAAA,OAAO,KAAK,KAAA,CAAM,CAAA,EAAG,SAAA,GAAY,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA;AACpD;AAWO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,KAAK,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AAC7D;AAaO,SAAS,WAAA,CAAY,IAAA,EAAc,WAAA,GAAc,CAAA,EAAW;AACjE,EAAA,OAAO,IAAA,CACJ,MAAM,GAAG,CAAA,CACT,OAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAC9B,GAAA,CAAI,UAAQ,IAAA,CAAK,CAAC,CAAC,CAAA,CACnB,IAAA,CAAK,EAAE,EACP,WAAA,EAAY,CACZ,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA;AACzB;AAQO,SAAS,QAAQ,IAAA,EAA0C;AAChE,EAAA,OAAO,CAAC,IAAA,IAAQ,IAAA,CAAK,IAAA,GAAO,MAAA,KAAW,CAAA;AACzC;AAQO,SAAS,UAAU,IAAA,EAAsB;AAC9C,EAAA,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAAE,MAAA;AAClE","file":"index.js","sourcesContent":["/**\r\n * String Utilities\r\n *\r\n * Utilitários para manipulação e formatação de strings.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/string\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Converte texto para slug URL-friendly\r\n *\r\n * @param text - Texto para converter\r\n * @returns Slug normalizado\r\n *\r\n * @example\r\n * textToSlug('Meu Post Incrível!') // 'meu-post-incrivel'\r\n * textToSlug('São Paulo - SP') // 'sao-paulo-sp'\r\n */\r\nexport function textToSlug(text: string): string {\r\n return text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .replace(/[^\\w\\s-]/g, '')\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/-+/g, '-');\r\n}\r\n\r\n/**\r\n * Capitaliza primeira letra de cada palavra\r\n *\r\n * @param text - Texto para capitalizar\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * capitalize('rainer teixeira') // 'Rainer Teixeira'\r\n */\r\nexport function capitalize(text: string): string {\r\n return text\r\n .toLowerCase()\r\n .split(' ')\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\r\n .join(' ');\r\n}\r\n\r\n/**\r\n * Trunca texto com ellipsis\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * truncate('Texto muito longo', 10) // 'Texto muit...'\r\n */\r\nexport function truncate(text: string, maxLength: number, suffix = '...'): string {\r\n if (text.length <= maxLength) return text;\r\n return text.slice(0, maxLength - suffix.length) + suffix;\r\n}\r\n\r\n/**\r\n * Remove acentos de texto\r\n *\r\n * @param text - Texto com acentos\r\n * @returns Texto sem acentos\r\n *\r\n * @example\r\n * removeAccents('São Paulo') // 'Sao Paulo'\r\n */\r\nexport function removeAccents(text: string): string {\r\n return text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\r\n}\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxInitials - Máximo de iniciais (padrão: 2)\r\n * @returns Iniciais em maiúsculas\r\n *\r\n * @example\r\n * getInitials('Rainer Teixeira') // 'RT'\r\n * getInitials('João da Silva Santos', 3) // 'JSS'\r\n */\r\nexport function getInitials(name: string, maxInitials = 2): string {\r\n return name\r\n .split(' ')\r\n .filter(word => word.length > 0)\r\n .map(word => word[0])\r\n .join('')\r\n .toUpperCase()\r\n .slice(0, maxInitials);\r\n}\r\n\r\n/**\r\n * Valida se string é vazia ou apenas espaços\r\n *\r\n * @param text - Texto para validar\r\n * @returns true se vazio, false caso contrário\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || text.trim().length === 0;\r\n}\r\n\r\n/**\r\n * Conta palavras em um texto\r\n *\r\n * @param text - Texto para contar\r\n * @returns Número de palavras\r\n */\r\nexport function wordCount(text: string): number {\r\n return text.trim().split(/\\s+/).filter(word => word.length > 0).length;\r\n}\r\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/string/index.ts
|
|
2
|
+
function textToSlug(text) {
|
|
3
|
+
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
4
|
+
}
|
|
5
|
+
function capitalize(text) {
|
|
6
|
+
return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
7
|
+
}
|
|
8
|
+
function truncate(text, maxLength, suffix = "...") {
|
|
9
|
+
if (text.length <= maxLength) return text;
|
|
10
|
+
return text.slice(0, maxLength - suffix.length) + suffix;
|
|
11
|
+
}
|
|
12
|
+
function removeAccents(text) {
|
|
13
|
+
return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
14
|
+
}
|
|
15
|
+
function getInitials(name, maxInitials = 2) {
|
|
16
|
+
return name.split(" ").filter((word) => word.length > 0).map((word) => word[0]).join("").toUpperCase().slice(0, maxInitials);
|
|
17
|
+
}
|
|
18
|
+
function isEmpty(text) {
|
|
19
|
+
return !text || text.trim().length === 0;
|
|
20
|
+
}
|
|
21
|
+
function wordCount(text) {
|
|
22
|
+
return text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { capitalize, getInitials, isEmpty, removeAccents, textToSlug, truncate, wordCount };
|
|
26
|
+
//# sourceMappingURL=index.mjs.map
|
|
27
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/string/index.ts"],"names":[],"mappings":";AAoBO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,aAAY,CACZ,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA,CAC9B,OAAA,CAAQ,aAAa,EAAE,CAAA,CACvB,MAAK,CACL,OAAA,CAAQ,QAAQ,GAAG,CAAA,CACnB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AACvB;AAWO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,aAAY,CACZ,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,UAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,KAAgB,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,CACxD,KAAK,GAAG,CAAA;AACb;AAaO,SAAS,QAAA,CAAS,IAAA,EAAc,SAAA,EAAmB,MAAA,GAAS,KAAA,EAAe;AAChF,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,SAAA,EAAW,OAAO,IAAA;AACrC,EAAA,OAAO,KAAK,KAAA,CAAM,CAAA,EAAG,SAAA,GAAY,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA;AACpD;AAWO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,KAAK,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AAC7D;AAaO,SAAS,WAAA,CAAY,IAAA,EAAc,WAAA,GAAc,CAAA,EAAW;AACjE,EAAA,OAAO,IAAA,CACJ,MAAM,GAAG,CAAA,CACT,OAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAC9B,GAAA,CAAI,UAAQ,IAAA,CAAK,CAAC,CAAC,CAAA,CACnB,IAAA,CAAK,EAAE,EACP,WAAA,EAAY,CACZ,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA;AACzB;AAQO,SAAS,QAAQ,IAAA,EAA0C;AAChE,EAAA,OAAO,CAAC,IAAA,IAAQ,IAAA,CAAK,IAAA,GAAO,MAAA,KAAW,CAAA;AACzC;AAQO,SAAS,UAAU,IAAA,EAAsB;AAC9C,EAAA,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAAE,MAAA;AAClE","file":"index.mjs","sourcesContent":["/**\r\n * String Utilities\r\n *\r\n * Utilitários para manipulação e formatação de strings.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/string\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Converte texto para slug URL-friendly\r\n *\r\n * @param text - Texto para converter\r\n * @returns Slug normalizado\r\n *\r\n * @example\r\n * textToSlug('Meu Post Incrível!') // 'meu-post-incrivel'\r\n * textToSlug('São Paulo - SP') // 'sao-paulo-sp'\r\n */\r\nexport function textToSlug(text: string): string {\r\n return text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .replace(/[^\\w\\s-]/g, '')\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/-+/g, '-');\r\n}\r\n\r\n/**\r\n * Capitaliza primeira letra de cada palavra\r\n *\r\n * @param text - Texto para capitalizar\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * capitalize('rainer teixeira') // 'Rainer Teixeira'\r\n */\r\nexport function capitalize(text: string): string {\r\n return text\r\n .toLowerCase()\r\n .split(' ')\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\r\n .join(' ');\r\n}\r\n\r\n/**\r\n * Trunca texto com ellipsis\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * truncate('Texto muito longo', 10) // 'Texto muit...'\r\n */\r\nexport function truncate(text: string, maxLength: number, suffix = '...'): string {\r\n if (text.length <= maxLength) return text;\r\n return text.slice(0, maxLength - suffix.length) + suffix;\r\n}\r\n\r\n/**\r\n * Remove acentos de texto\r\n *\r\n * @param text - Texto com acentos\r\n * @returns Texto sem acentos\r\n *\r\n * @example\r\n * removeAccents('São Paulo') // 'Sao Paulo'\r\n */\r\nexport function removeAccents(text: string): string {\r\n return text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\r\n}\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxInitials - Máximo de iniciais (padrão: 2)\r\n * @returns Iniciais em maiúsculas\r\n *\r\n * @example\r\n * getInitials('Rainer Teixeira') // 'RT'\r\n * getInitials('João da Silva Santos', 3) // 'JSS'\r\n */\r\nexport function getInitials(name: string, maxInitials = 2): string {\r\n return name\r\n .split(' ')\r\n .filter(word => word.length > 0)\r\n .map(word => word[0])\r\n .join('')\r\n .toUpperCase()\r\n .slice(0, maxInitials);\r\n}\r\n\r\n/**\r\n * Valida se string é vazia ou apenas espaços\r\n *\r\n * @param text - Texto para validar\r\n * @returns true se vazio, false caso contrário\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || text.trim().length === 0;\r\n}\r\n\r\n/**\r\n * Conta palavras em um texto\r\n *\r\n * @param text - Texto para contar\r\n * @returns Número de palavras\r\n */\r\nexport function wordCount(text: string): number {\r\n return text.trim().split(/\\s+/).filter(word => word.length > 0).length;\r\n}\r\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Locale = 'pt-BR' | 'en-US' | 'es-ES';
|
|
2
|
+
interface LocaleConfig {
|
|
3
|
+
locale: Locale;
|
|
4
|
+
currency?: string;
|
|
5
|
+
dateFormat?: 'short' | 'long' | 'full';
|
|
6
|
+
}
|
|
7
|
+
declare const DEFAULT_LOCALE: Locale;
|
|
8
|
+
declare const CURRENCY_MAP: Record<Locale, string>;
|
|
9
|
+
|
|
10
|
+
export { CURRENCY_MAP as C, DEFAULT_LOCALE as D, type Locale as L, type LocaleConfig as a };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Locale = 'pt-BR' | 'en-US' | 'es-ES';
|
|
2
|
+
interface LocaleConfig {
|
|
3
|
+
locale: Locale;
|
|
4
|
+
currency?: string;
|
|
5
|
+
dateFormat?: 'short' | 'long' | 'full';
|
|
6
|
+
}
|
|
7
|
+
declare const DEFAULT_LOCALE: Locale;
|
|
8
|
+
declare const CURRENCY_MAP: Record<Locale, string>;
|
|
9
|
+
|
|
10
|
+
export { CURRENCY_MAP as C, DEFAULT_LOCALE as D, type Locale as L, type LocaleConfig as a };
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rainersoft/utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Utilitários universais para formatação, conversão e manipulação de dados - Web, Desktop e Mobile",
|
|
5
|
+
"packageManager": "pnpm@9.0.0",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Rainer Teixeira",
|
|
8
|
+
"email": "suporte@rainersoft.com.br"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"utils",
|
|
13
|
+
"utilities",
|
|
14
|
+
"formatters",
|
|
15
|
+
"date",
|
|
16
|
+
"string",
|
|
17
|
+
"number",
|
|
18
|
+
"currency",
|
|
19
|
+
"slug",
|
|
20
|
+
"status",
|
|
21
|
+
"typescript"
|
|
22
|
+
],
|
|
23
|
+
"main": "dist/index.js",
|
|
24
|
+
"module": "dist/index.mjs",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.mjs",
|
|
30
|
+
"require": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./date": {
|
|
33
|
+
"types": "./dist/date/index.d.ts",
|
|
34
|
+
"import": "./dist/date/index.mjs",
|
|
35
|
+
"require": "./dist/date/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./string": {
|
|
38
|
+
"types": "./dist/string/index.d.ts",
|
|
39
|
+
"import": "./dist/string/index.mjs",
|
|
40
|
+
"require": "./dist/string/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./number": {
|
|
43
|
+
"types": "./dist/number/index.d.ts",
|
|
44
|
+
"import": "./dist/number/index.mjs",
|
|
45
|
+
"require": "./dist/number/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./status": {
|
|
48
|
+
"types": "./dist/status/index.d.ts",
|
|
49
|
+
"import": "./dist/status/index.mjs",
|
|
50
|
+
"require": "./dist/status/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./package.json": "./package.json"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"dist",
|
|
56
|
+
"README.md",
|
|
57
|
+
"LICENSE"
|
|
58
|
+
],
|
|
59
|
+
"scripts": {
|
|
60
|
+
"dev": "tsup --watch",
|
|
61
|
+
"build": "tsup",
|
|
62
|
+
"test": "jest",
|
|
63
|
+
"test:watch": "jest --watch",
|
|
64
|
+
"test:coverage": "jest --coverage",
|
|
65
|
+
"lint": "eslint src --ext .ts",
|
|
66
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
67
|
+
"typecheck": "tsc --noEmit"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/jest": "^29.5.12",
|
|
77
|
+
"@types/node": "^20.19.25",
|
|
78
|
+
"@typescript-eslint/eslint-plugin": "^7.0.1",
|
|
79
|
+
"@typescript-eslint/parser": "^7.0.1",
|
|
80
|
+
"eslint": "^8.56.0",
|
|
81
|
+
"jest": "^29.7.0",
|
|
82
|
+
"prettier": "^3.2.5",
|
|
83
|
+
"ts-jest": "^29.1.2",
|
|
84
|
+
"tsup": "^8.5.1",
|
|
85
|
+
"typescript": "^5.9.3"
|
|
86
|
+
}
|
|
87
|
+
}
|