@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 ADDED
@@ -0,0 +1,176 @@
1
+ # @rainersoft/utils
2
+
3
+ > Biblioteca universal de utilitários para formatação, conversão e manipulação de dados.
4
+
5
+ [![npm version](https://badge.fury.io/js/@rainersoft%2Futils.svg)](https://www.npmjs.com/package/@rainersoft/utils)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## 🎯 Características
9
+
10
+ - ✅ **Universal**: Funciona em Web, Desktop e Mobile
11
+ - ✅ **TypeScript**: Totalmente tipado
12
+ - ✅ **Tree-shakeable**: Importações otimizadas
13
+ - ✅ **Zero dependências**: Leve e rápido
14
+ - ✅ **Multi-idioma**: Suporte para pt-BR, en-US, es-ES
15
+ - ✅ **Helpers pt-BR**: Funções pré-configuradas para português
16
+ - ✅ **Modular**: Importe apenas o que precisa
17
+
18
+ ## 📦 Instalação
19
+
20
+ ```bash
21
+ npm install @rainersoft/utils
22
+ # ou
23
+ pnpm add @rainersoft/utils
24
+ # ou
25
+ yarn add @rainersoft/utils
26
+ ```
27
+
28
+ ## 🚀 Uso
29
+
30
+ ### String Utilities
31
+
32
+ ```typescript
33
+ import { textToSlug, capitalize, truncate, getInitials } from '@rainersoft/utils/string';
34
+
35
+ textToSlug('Meu Post Incrível!'); // 'meu-post-incrivel'
36
+ capitalize('rainer teixeira'); // 'Rainer Teixeira'
37
+ truncate('Texto muito longo', 10); // 'Texto muit...'
38
+ getInitials('Rainer Teixeira'); // 'RT'
39
+ ```
40
+
41
+ ### Date Utilities
42
+
43
+ ```typescript
44
+ import { formatDate, formatDateTime, formatRelativeDate } from '@rainersoft/utils/date';
45
+
46
+ formatDate('2025-11-26'); // '26 de novembro de 2025'
47
+ formatDate('2025-11-26', 'short'); // '26/11/2025'
48
+ formatDateTime('2025-11-26T14:30:00'); // '26 de novembro de 2025 às 14:30'
49
+ formatRelativeDate(yesterday); // 'há 1 dia'
50
+ ```
51
+
52
+ ### Number Utilities
53
+
54
+ ```typescript
55
+ import { formatCurrency, formatPercent, formatNumber, formatCompact } from '@rainersoft/utils/number';
56
+
57
+ formatCurrency(1234.56); // 'R$ 1.234,56'
58
+ formatPercent(0.1234, 2); // '12,34%'
59
+ formatNumber(1234567); // '1.234.567'
60
+ formatCompact(1234567); // '1,2 mi'
61
+ ```
62
+
63
+ ### Status Utilities
64
+
65
+ ```typescript
66
+ import { translateStatus, getStatusColor, getStatusVariant } from '@rainersoft/utils/status';
67
+
68
+ translateStatus('DRAFT'); // 'Rascunho'
69
+ translateStatus('PUBLISHED'); // 'Publicado'
70
+ getStatusColor('PUBLISHED'); // 'text-green-600'
71
+ getStatusVariant('DRAFT'); // 'secondary'
72
+ ```
73
+
74
+ ### Import Tudo
75
+
76
+ ```typescript
77
+ import {
78
+ textToSlug,
79
+ formatDate,
80
+ formatCurrency,
81
+ translateStatus
82
+ } from '@rainersoft/utils';
83
+ ```
84
+
85
+ ### Helpers pt-BR (Recomendado para Português)
86
+
87
+ ```typescript
88
+ // Importação simplificada - já vem em pt-BR
89
+ import { ptBR } from '@rainersoft/utils';
90
+
91
+ ptBR.formatDate('2025-11-26'); // '26 de novembro de 2025'
92
+ ptBR.formatCurrency(1234.56); // 'R$ 1.234,56'
93
+ ptBR.translateStatus('DRAFT'); // 'Rascunho'
94
+
95
+ // Ou importe funções individuais
96
+ import { formatDate, formatCurrency } from '@rainersoft/utils/pt-br';
97
+ ```
98
+
99
+ ### Suporte Multi-idioma
100
+
101
+ ```typescript
102
+ import { formatDate, formatCurrency, translateStatus } from '@rainersoft/utils';
103
+
104
+ // Português (padrão)
105
+ formatDate('2025-11-26'); // '26 de novembro de 2025'
106
+ formatCurrency(1234.56); // 'R$ 1.234,56'
107
+
108
+ // Inglês
109
+ formatDate('2025-11-26', 'long', 'en-US'); // 'November 26, 2025'
110
+ formatCurrency(1234.56, 'en-US'); // '$1,234.56'
111
+
112
+ // Espanhol
113
+ formatDate('2025-11-26', 'long', 'es-ES'); // '26 de noviembre de 2025'
114
+ formatCurrency(1234.56, 'es-ES'); // '1.234,56 €'
115
+ ```
116
+
117
+ ## 📚 Módulos
118
+
119
+ ### String (`@rainersoft/utils/string`)
120
+ - `textToSlug()` - Converte texto para slug
121
+ - `capitalize()` - Capitaliza palavras
122
+ - `truncate()` - Trunca texto
123
+ - `removeAccents()` - Remove acentos
124
+ - `getInitials()` - Extrai iniciais
125
+ - `isEmpty()` - Valida string vazia
126
+ - `wordCount()` - Conta palavras
127
+
128
+ ### Date (`@rainersoft/utils/date`)
129
+ - `formatDate()` - Formata data (pt-BR)
130
+ - `formatDateTime()` - Formata data e hora
131
+ - `formatRelativeDate()` - Data relativa (há X dias)
132
+ - `toISOString()` - Converte para ISO
133
+ - `isValidDate()` - Valida data
134
+
135
+ ### Number (`@rainersoft/utils/number`)
136
+ - `formatCurrency()` - Formata moeda (BRL)
137
+ - `formatPercent()` - Formata percentual
138
+ - `formatNumber()` - Formata número
139
+ - `formatCompact()` - Formato compacto (1K, 1M)
140
+ - `parseCurrency()` - Parse de moeda
141
+ - `round()` - Arredondamento
142
+ - `clamp()` - Limita valor
143
+
144
+ ### Status (`@rainersoft/utils/status`)
145
+ - `translateStatus()` - Traduz status
146
+ - `getStatusColor()` - Cor do status
147
+ - `getStatusVariant()` - Variant do badge
148
+
149
+ ## 🛠️ Desenvolvimento
150
+
151
+ ```bash
152
+ # Instalar dependências
153
+ pnpm install
154
+
155
+ # Desenvolvimento com watch
156
+ pnpm dev
157
+
158
+ # Build
159
+ pnpm build
160
+
161
+ # Testes
162
+ pnpm test
163
+
164
+ # Lint
165
+ pnpm lint
166
+ ```
167
+
168
+ ## 📄 Licença
169
+
170
+ MIT © Rainer Teixeira
171
+
172
+ ## 🔗 Ecossistema Rainersoft
173
+
174
+ - [@rainersoft/design-tokens](https://www.npmjs.com/package/@rainersoft/design-tokens) - Sistema de design tokens
175
+ - [@rainersoft/ui](https://www.npmjs.com/package/@rainersoft/ui) - Componentes UI
176
+ - [@rainersoft/utils](https://www.npmjs.com/package/@rainersoft/utils) - Utilitários universais
@@ -0,0 +1,9 @@
1
+ import { L as Locale } from '../types-tUMATEGI.mjs';
2
+
3
+ declare function formatDate(date: string | Date, format?: 'short' | 'long' | 'full', locale?: Locale): string;
4
+ declare function formatDateTime(date: string | Date, locale?: Locale): string;
5
+ declare function formatRelativeDate(date: string | Date, locale?: Locale): string;
6
+ declare function toISOString(date: Date): string;
7
+ declare function isValidDate(date: unknown): date is Date;
8
+
9
+ export { formatDate, formatDateTime, formatRelativeDate, isValidDate, toISOString };
@@ -0,0 +1,9 @@
1
+ import { L as Locale } from '../types-tUMATEGI.js';
2
+
3
+ declare function formatDate(date: string | Date, format?: 'short' | 'long' | 'full', locale?: Locale): string;
4
+ declare function formatDateTime(date: string | Date, locale?: Locale): string;
5
+ declare function formatRelativeDate(date: string | Date, locale?: Locale): string;
6
+ declare function toISOString(date: Date): string;
7
+ declare function isValidDate(date: unknown): date is Date;
8
+
9
+ export { formatDate, formatDateTime, formatRelativeDate, isValidDate, toISOString };
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+
3
+ // src/types.ts
4
+ var DEFAULT_LOCALE = "pt-BR";
5
+
6
+ // src/date/index.ts
7
+ var RELATIVE_TEXTS = {
8
+ "pt-BR": {
9
+ now: "agora",
10
+ minute: (n) => `h\xE1 ${n} ${n === 1 ? "minuto" : "minutos"}`,
11
+ hour: (n) => `h\xE1 ${n} ${n === 1 ? "hora" : "horas"}`,
12
+ day: (n) => `h\xE1 ${n} ${n === 1 ? "dia" : "dias"}`,
13
+ month: (n) => `h\xE1 ${n} ${n === 1 ? "m\xEAs" : "meses"}`,
14
+ year: (n) => `h\xE1 ${n} ${n === 1 ? "ano" : "anos"}`
15
+ },
16
+ "en-US": {
17
+ now: "now",
18
+ minute: (n) => `${n} ${n === 1 ? "minute" : "minutes"} ago`,
19
+ hour: (n) => `${n} ${n === 1 ? "hour" : "hours"} ago`,
20
+ day: (n) => `${n} ${n === 1 ? "day" : "days"} ago`,
21
+ month: (n) => `${n} ${n === 1 ? "month" : "months"} ago`,
22
+ year: (n) => `${n} ${n === 1 ? "year" : "years"} ago`
23
+ },
24
+ "es-ES": {
25
+ now: "ahora",
26
+ minute: (n) => `hace ${n} ${n === 1 ? "minuto" : "minutos"}`,
27
+ hour: (n) => `hace ${n} ${n === 1 ? "hora" : "horas"}`,
28
+ day: (n) => `hace ${n} ${n === 1 ? "d\xEDa" : "d\xEDas"}`,
29
+ month: (n) => `hace ${n} ${n === 1 ? "mes" : "meses"}`,
30
+ year: (n) => `hace ${n} ${n === 1 ? "a\xF1o" : "a\xF1os"}`
31
+ }
32
+ };
33
+ function formatDate(date, format = "long", locale = DEFAULT_LOCALE) {
34
+ const d = typeof date === "string" ? new Date(date) : date;
35
+ const options = {
36
+ day: "numeric",
37
+ month: format === "short" ? "2-digit" : "long",
38
+ year: "numeric",
39
+ ...format === "full" && { weekday: "long" }
40
+ };
41
+ if (format === "short") {
42
+ return d.toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
43
+ }
44
+ return d.toLocaleDateString(locale, options);
45
+ }
46
+ function formatDateTime(date, locale = DEFAULT_LOCALE) {
47
+ const d = typeof date === "string" ? new Date(date) : date;
48
+ return d.toLocaleString(locale, {
49
+ day: "numeric",
50
+ month: "long",
51
+ year: "numeric",
52
+ hour: "2-digit",
53
+ minute: "2-digit"
54
+ });
55
+ }
56
+ function formatRelativeDate(date, locale = DEFAULT_LOCALE) {
57
+ const d = typeof date === "string" ? new Date(date) : date;
58
+ if (!(d instanceof Date) || Number.isNaN(d.getTime())) {
59
+ return "";
60
+ }
61
+ const now = /* @__PURE__ */ new Date();
62
+ const diffMs = now.getTime() - d.getTime();
63
+ const diffSec = Math.floor(diffMs / 1e3);
64
+ const diffMin = Math.floor(diffSec / 60);
65
+ const diffHour = Math.floor(diffMin / 60);
66
+ const diffDay = Math.floor(diffHour / 24);
67
+ const diffMonth = Math.floor(diffDay / 30.4375);
68
+ const diffYear = Math.floor(diffDay / 365);
69
+ const texts = RELATIVE_TEXTS[locale];
70
+ if (diffSec < 10) {
71
+ if (locale === "pt-BR") return "agora mesmo";
72
+ if (locale === "en-US") return "just now";
73
+ if (locale === "es-ES") return "ahora mismo";
74
+ }
75
+ if (diffSec < 60) return texts.now;
76
+ if (diffMin < 60) return texts.minute(diffMin);
77
+ if (diffHour < 24) return texts.hour(diffHour);
78
+ if (diffDay === 1) {
79
+ if (locale === "pt-BR") return "ontem";
80
+ if (locale === "en-US") return "yesterday";
81
+ if (locale === "es-ES") return "ayer";
82
+ }
83
+ if (diffDay === 2) {
84
+ if (locale === "pt-BR") return "anteontem";
85
+ if (locale === "en-US") return "the day before yesterday";
86
+ if (locale === "es-ES") return "anteayer";
87
+ }
88
+ if (diffDay < 30) return texts.day(diffDay);
89
+ if (diffMonth < 12) return texts.month(diffMonth);
90
+ return texts.year(diffYear);
91
+ }
92
+ function toISOString(date) {
93
+ return date.toISOString();
94
+ }
95
+ function isValidDate(date) {
96
+ return date instanceof Date && !isNaN(date.getTime());
97
+ }
98
+
99
+ exports.formatDate = formatDate;
100
+ exports.formatDateTime = formatDateTime;
101
+ exports.formatRelativeDate = formatRelativeDate;
102
+ exports.isValidDate = isValidDate;
103
+ exports.toISOString = toISOString;
104
+ //# sourceMappingURL=index.js.map
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts","../../src/date/index.ts"],"names":[],"mappings":"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","file":"index.js","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 * Date Utilities\r\n *\r\n * Utilitários para formatação e manipulação de datas.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/date\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 * Textos relativos por idioma\r\n */\r\nconst RELATIVE_TEXTS = {\r\n 'pt-BR': {\r\n now: 'agora',\r\n minute: (n: number) => `há ${n} ${n === 1 ? 'minuto' : 'minutos'}`,\r\n hour: (n: number) => `há ${n} ${n === 1 ? 'hora' : 'horas'}`,\r\n day: (n: number) => `há ${n} ${n === 1 ? 'dia' : 'dias'}`,\r\n month: (n: number) => `há ${n} ${n === 1 ? 'mês' : 'meses'}`,\r\n year: (n: number) => `há ${n} ${n === 1 ? 'ano' : 'anos'}`,\r\n },\r\n 'en-US': {\r\n now: 'now',\r\n minute: (n: number) => `${n} ${n === 1 ? 'minute' : 'minutes'} ago`,\r\n hour: (n: number) => `${n} ${n === 1 ? 'hour' : 'hours'} ago`,\r\n day: (n: number) => `${n} ${n === 1 ? 'day' : 'days'} ago`,\r\n month: (n: number) => `${n} ${n === 1 ? 'month' : 'months'} ago`,\r\n year: (n: number) => `${n} ${n === 1 ? 'year' : 'years'} ago`,\r\n },\r\n 'es-ES': {\r\n now: 'ahora',\r\n minute: (n: number) => `hace ${n} ${n === 1 ? 'minuto' : 'minutos'}`,\r\n hour: (n: number) => `hace ${n} ${n === 1 ? 'hora' : 'horas'}`,\r\n day: (n: number) => `hace ${n} ${n === 1 ? 'día' : 'días'}`,\r\n month: (n: number) => `hace ${n} ${n === 1 ? 'mes' : 'meses'}`,\r\n year: (n: number) => `hace ${n} ${n === 1 ? 'año' : 'años'}`,\r\n },\r\n} as const;\r\n\r\n/**\r\n * Formata data com suporte a múltiplos idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param format - Formato ('short' | 'long' | 'full')\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Data formatada\r\n *\r\n * @example\r\n * formatDate('2025-11-26') // '26 de novembro de 2025' (pt-BR)\r\n * formatDate('2025-11-26', 'short') // '26/11/2025'\r\n * formatDate('2025-11-26', 'long', 'en-US') // 'November 26, 2025'\r\n * formatDate('2025-11-26', 'long', 'es-ES') // '26 de noviembre de 2025'\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long',\r\n locale: Locale = DEFAULT_LOCALE\r\n): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n \r\n // Usar Intl.DateTimeFormat para suporte multi-idioma\r\n const options: Intl.DateTimeFormatOptions = {\r\n day: 'numeric',\r\n month: format === 'short' ? '2-digit' : 'long',\r\n year: 'numeric',\r\n ...(format === 'full' && { weekday: 'long' }),\r\n };\r\n\r\n if (format === 'short') {\r\n return d.toLocaleDateString(locale, { day: '2-digit', month: '2-digit', year: 'numeric' });\r\n }\r\n\r\n return d.toLocaleDateString(locale, options);\r\n}\r\n\r\n/**\r\n * Formata data e hora com suporte a múltiplos idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Data e hora formatadas\r\n *\r\n * @example\r\n * formatDateTime('2025-11-26T14:30:00') // '26 de novembro de 2025, 14:30' (pt-BR)\r\n * formatDateTime('2025-11-26T14:30:00', 'en-US') // 'November 26, 2025, 2:30 PM'\r\n */\r\nexport function formatDateTime(date: string | Date, locale: Locale = DEFAULT_LOCALE): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n \r\n return d.toLocaleString(locale, {\r\n day: 'numeric',\r\n month: 'long',\r\n year: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n });\r\n}\r\n\r\n/**\r\n * Formata data relativa (há X dias/horas) com suporte a idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Texto relativo\r\n *\r\n * @example\r\n * formatRelativeDate(new Date()) // 'agora' (pt-BR)\r\n * formatRelativeDate(yesterday, 'en-US') // '1 day ago'\r\n * formatRelativeDate(yesterday, 'es-ES') // 'hace 1 día'\r\n */\r\nexport function formatRelativeDate(date: string | Date, locale: Locale = DEFAULT_LOCALE): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n\r\n // Proteger contra datas inválidas (evita 'há NaN anos')\r\n if (!(d instanceof Date) || Number.isNaN(d.getTime())) {\r\n return '';\r\n }\r\n const now = new Date();\r\n const diffMs = now.getTime() - d.getTime();\r\n const diffSec = Math.floor(diffMs / 1000);\r\n const diffMin = Math.floor(diffSec / 60);\r\n const diffHour = Math.floor(diffMin / 60);\r\n const diffDay = Math.floor(diffHour / 24);\r\n // Usar média de dias por mês mais próxima da realidade para não arredondar cedo demais para 1 ano\r\n const diffMonth = Math.floor(diffDay / 30.4375); // 365 / 12\r\n const diffYear = Math.floor(diffDay / 365);\r\n\r\n const texts = RELATIVE_TEXTS[locale];\r\n\r\n // Regras especiais por idioma (mais naturais)\r\n if (diffSec < 10) {\r\n if (locale === 'pt-BR') return 'agora mesmo';\r\n if (locale === 'en-US') return 'just now';\r\n if (locale === 'es-ES') return 'ahora mismo';\r\n }\r\n\r\n if (diffSec < 60) return texts.now;\r\n if (diffMin < 60) return texts.minute(diffMin);\r\n if (diffHour < 24) return texts.hour(diffHour);\r\n\r\n // Dias específicos\r\n if (diffDay === 1) {\r\n if (locale === 'pt-BR') return 'ontem';\r\n if (locale === 'en-US') return 'yesterday';\r\n if (locale === 'es-ES') return 'ayer';\r\n }\r\n\r\n if (diffDay === 2) {\r\n if (locale === 'pt-BR') return 'anteontem';\r\n if (locale === 'en-US') return 'the day before yesterday';\r\n if (locale === 'es-ES') return 'anteayer';\r\n }\r\n\r\n if (diffDay < 30) return texts.day(diffDay);\r\n if (diffMonth < 12) return texts.month(diffMonth);\r\n return texts.year(diffYear);\r\n}\r\n\r\n/**\r\n * Converte data para ISO string\r\n *\r\n * @param date - Data\r\n * @returns String ISO\r\n */\r\nexport function toISOString(date: Date): string {\r\n return date.toISOString();\r\n}\r\n\r\n/**\r\n * Verifica se data é válida\r\n *\r\n * @param date - Data para validar\r\n * @returns true se válida\r\n */\r\nexport function isValidDate(date: unknown): date is Date {\r\n return date instanceof Date && !isNaN(date.getTime());\r\n}\r\n"]}
@@ -0,0 +1,99 @@
1
+ // src/types.ts
2
+ var DEFAULT_LOCALE = "pt-BR";
3
+
4
+ // src/date/index.ts
5
+ var RELATIVE_TEXTS = {
6
+ "pt-BR": {
7
+ now: "agora",
8
+ minute: (n) => `h\xE1 ${n} ${n === 1 ? "minuto" : "minutos"}`,
9
+ hour: (n) => `h\xE1 ${n} ${n === 1 ? "hora" : "horas"}`,
10
+ day: (n) => `h\xE1 ${n} ${n === 1 ? "dia" : "dias"}`,
11
+ month: (n) => `h\xE1 ${n} ${n === 1 ? "m\xEAs" : "meses"}`,
12
+ year: (n) => `h\xE1 ${n} ${n === 1 ? "ano" : "anos"}`
13
+ },
14
+ "en-US": {
15
+ now: "now",
16
+ minute: (n) => `${n} ${n === 1 ? "minute" : "minutes"} ago`,
17
+ hour: (n) => `${n} ${n === 1 ? "hour" : "hours"} ago`,
18
+ day: (n) => `${n} ${n === 1 ? "day" : "days"} ago`,
19
+ month: (n) => `${n} ${n === 1 ? "month" : "months"} ago`,
20
+ year: (n) => `${n} ${n === 1 ? "year" : "years"} ago`
21
+ },
22
+ "es-ES": {
23
+ now: "ahora",
24
+ minute: (n) => `hace ${n} ${n === 1 ? "minuto" : "minutos"}`,
25
+ hour: (n) => `hace ${n} ${n === 1 ? "hora" : "horas"}`,
26
+ day: (n) => `hace ${n} ${n === 1 ? "d\xEDa" : "d\xEDas"}`,
27
+ month: (n) => `hace ${n} ${n === 1 ? "mes" : "meses"}`,
28
+ year: (n) => `hace ${n} ${n === 1 ? "a\xF1o" : "a\xF1os"}`
29
+ }
30
+ };
31
+ function formatDate(date, format = "long", locale = DEFAULT_LOCALE) {
32
+ const d = typeof date === "string" ? new Date(date) : date;
33
+ const options = {
34
+ day: "numeric",
35
+ month: format === "short" ? "2-digit" : "long",
36
+ year: "numeric",
37
+ ...format === "full" && { weekday: "long" }
38
+ };
39
+ if (format === "short") {
40
+ return d.toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
41
+ }
42
+ return d.toLocaleDateString(locale, options);
43
+ }
44
+ function formatDateTime(date, locale = DEFAULT_LOCALE) {
45
+ const d = typeof date === "string" ? new Date(date) : date;
46
+ return d.toLocaleString(locale, {
47
+ day: "numeric",
48
+ month: "long",
49
+ year: "numeric",
50
+ hour: "2-digit",
51
+ minute: "2-digit"
52
+ });
53
+ }
54
+ function formatRelativeDate(date, locale = DEFAULT_LOCALE) {
55
+ const d = typeof date === "string" ? new Date(date) : date;
56
+ if (!(d instanceof Date) || Number.isNaN(d.getTime())) {
57
+ return "";
58
+ }
59
+ const now = /* @__PURE__ */ new Date();
60
+ const diffMs = now.getTime() - d.getTime();
61
+ const diffSec = Math.floor(diffMs / 1e3);
62
+ const diffMin = Math.floor(diffSec / 60);
63
+ const diffHour = Math.floor(diffMin / 60);
64
+ const diffDay = Math.floor(diffHour / 24);
65
+ const diffMonth = Math.floor(diffDay / 30.4375);
66
+ const diffYear = Math.floor(diffDay / 365);
67
+ const texts = RELATIVE_TEXTS[locale];
68
+ if (diffSec < 10) {
69
+ if (locale === "pt-BR") return "agora mesmo";
70
+ if (locale === "en-US") return "just now";
71
+ if (locale === "es-ES") return "ahora mismo";
72
+ }
73
+ if (diffSec < 60) return texts.now;
74
+ if (diffMin < 60) return texts.minute(diffMin);
75
+ if (diffHour < 24) return texts.hour(diffHour);
76
+ if (diffDay === 1) {
77
+ if (locale === "pt-BR") return "ontem";
78
+ if (locale === "en-US") return "yesterday";
79
+ if (locale === "es-ES") return "ayer";
80
+ }
81
+ if (diffDay === 2) {
82
+ if (locale === "pt-BR") return "anteontem";
83
+ if (locale === "en-US") return "the day before yesterday";
84
+ if (locale === "es-ES") return "anteayer";
85
+ }
86
+ if (diffDay < 30) return texts.day(diffDay);
87
+ if (diffMonth < 12) return texts.month(diffMonth);
88
+ return texts.year(diffYear);
89
+ }
90
+ function toISOString(date) {
91
+ return date.toISOString();
92
+ }
93
+ function isValidDate(date) {
94
+ return date instanceof Date && !isNaN(date.getTime());
95
+ }
96
+
97
+ export { formatDate, formatDateTime, formatRelativeDate, isValidDate, toISOString };
98
+ //# sourceMappingURL=index.mjs.map
99
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts","../../src/date/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 * Date Utilities\r\n *\r\n * Utilitários para formatação e manipulação de datas.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/date\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 * Textos relativos por idioma\r\n */\r\nconst RELATIVE_TEXTS = {\r\n 'pt-BR': {\r\n now: 'agora',\r\n minute: (n: number) => `há ${n} ${n === 1 ? 'minuto' : 'minutos'}`,\r\n hour: (n: number) => `há ${n} ${n === 1 ? 'hora' : 'horas'}`,\r\n day: (n: number) => `há ${n} ${n === 1 ? 'dia' : 'dias'}`,\r\n month: (n: number) => `há ${n} ${n === 1 ? 'mês' : 'meses'}`,\r\n year: (n: number) => `há ${n} ${n === 1 ? 'ano' : 'anos'}`,\r\n },\r\n 'en-US': {\r\n now: 'now',\r\n minute: (n: number) => `${n} ${n === 1 ? 'minute' : 'minutes'} ago`,\r\n hour: (n: number) => `${n} ${n === 1 ? 'hour' : 'hours'} ago`,\r\n day: (n: number) => `${n} ${n === 1 ? 'day' : 'days'} ago`,\r\n month: (n: number) => `${n} ${n === 1 ? 'month' : 'months'} ago`,\r\n year: (n: number) => `${n} ${n === 1 ? 'year' : 'years'} ago`,\r\n },\r\n 'es-ES': {\r\n now: 'ahora',\r\n minute: (n: number) => `hace ${n} ${n === 1 ? 'minuto' : 'minutos'}`,\r\n hour: (n: number) => `hace ${n} ${n === 1 ? 'hora' : 'horas'}`,\r\n day: (n: number) => `hace ${n} ${n === 1 ? 'día' : 'días'}`,\r\n month: (n: number) => `hace ${n} ${n === 1 ? 'mes' : 'meses'}`,\r\n year: (n: number) => `hace ${n} ${n === 1 ? 'año' : 'años'}`,\r\n },\r\n} as const;\r\n\r\n/**\r\n * Formata data com suporte a múltiplos idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param format - Formato ('short' | 'long' | 'full')\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Data formatada\r\n *\r\n * @example\r\n * formatDate('2025-11-26') // '26 de novembro de 2025' (pt-BR)\r\n * formatDate('2025-11-26', 'short') // '26/11/2025'\r\n * formatDate('2025-11-26', 'long', 'en-US') // 'November 26, 2025'\r\n * formatDate('2025-11-26', 'long', 'es-ES') // '26 de noviembre de 2025'\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long',\r\n locale: Locale = DEFAULT_LOCALE\r\n): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n \r\n // Usar Intl.DateTimeFormat para suporte multi-idioma\r\n const options: Intl.DateTimeFormatOptions = {\r\n day: 'numeric',\r\n month: format === 'short' ? '2-digit' : 'long',\r\n year: 'numeric',\r\n ...(format === 'full' && { weekday: 'long' }),\r\n };\r\n\r\n if (format === 'short') {\r\n return d.toLocaleDateString(locale, { day: '2-digit', month: '2-digit', year: 'numeric' });\r\n }\r\n\r\n return d.toLocaleDateString(locale, options);\r\n}\r\n\r\n/**\r\n * Formata data e hora com suporte a múltiplos idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Data e hora formatadas\r\n *\r\n * @example\r\n * formatDateTime('2025-11-26T14:30:00') // '26 de novembro de 2025, 14:30' (pt-BR)\r\n * formatDateTime('2025-11-26T14:30:00', 'en-US') // 'November 26, 2025, 2:30 PM'\r\n */\r\nexport function formatDateTime(date: string | Date, locale: Locale = DEFAULT_LOCALE): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n \r\n return d.toLocaleString(locale, {\r\n day: 'numeric',\r\n month: 'long',\r\n year: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n });\r\n}\r\n\r\n/**\r\n * Formata data relativa (há X dias/horas) com suporte a idiomas\r\n *\r\n * @param date - Data (string ISO ou Date)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Texto relativo\r\n *\r\n * @example\r\n * formatRelativeDate(new Date()) // 'agora' (pt-BR)\r\n * formatRelativeDate(yesterday, 'en-US') // '1 day ago'\r\n * formatRelativeDate(yesterday, 'es-ES') // 'hace 1 día'\r\n */\r\nexport function formatRelativeDate(date: string | Date, locale: Locale = DEFAULT_LOCALE): string {\r\n const d = typeof date === 'string' ? new Date(date) : date;\r\n\r\n // Proteger contra datas inválidas (evita 'há NaN anos')\r\n if (!(d instanceof Date) || Number.isNaN(d.getTime())) {\r\n return '';\r\n }\r\n const now = new Date();\r\n const diffMs = now.getTime() - d.getTime();\r\n const diffSec = Math.floor(diffMs / 1000);\r\n const diffMin = Math.floor(diffSec / 60);\r\n const diffHour = Math.floor(diffMin / 60);\r\n const diffDay = Math.floor(diffHour / 24);\r\n // Usar média de dias por mês mais próxima da realidade para não arredondar cedo demais para 1 ano\r\n const diffMonth = Math.floor(diffDay / 30.4375); // 365 / 12\r\n const diffYear = Math.floor(diffDay / 365);\r\n\r\n const texts = RELATIVE_TEXTS[locale];\r\n\r\n // Regras especiais por idioma (mais naturais)\r\n if (diffSec < 10) {\r\n if (locale === 'pt-BR') return 'agora mesmo';\r\n if (locale === 'en-US') return 'just now';\r\n if (locale === 'es-ES') return 'ahora mismo';\r\n }\r\n\r\n if (diffSec < 60) return texts.now;\r\n if (diffMin < 60) return texts.minute(diffMin);\r\n if (diffHour < 24) return texts.hour(diffHour);\r\n\r\n // Dias específicos\r\n if (diffDay === 1) {\r\n if (locale === 'pt-BR') return 'ontem';\r\n if (locale === 'en-US') return 'yesterday';\r\n if (locale === 'es-ES') return 'ayer';\r\n }\r\n\r\n if (diffDay === 2) {\r\n if (locale === 'pt-BR') return 'anteontem';\r\n if (locale === 'en-US') return 'the day before yesterday';\r\n if (locale === 'es-ES') return 'anteayer';\r\n }\r\n\r\n if (diffDay < 30) return texts.day(diffDay);\r\n if (diffMonth < 12) return texts.month(diffMonth);\r\n return texts.year(diffYear);\r\n}\r\n\r\n/**\r\n * Converte data para ISO string\r\n *\r\n * @param date - Data\r\n * @returns String ISO\r\n */\r\nexport function toISOString(date: Date): string {\r\n return date.toISOString();\r\n}\r\n\r\n/**\r\n * Verifica se data é válida\r\n *\r\n * @param date - Data para validar\r\n * @returns true se válida\r\n */\r\nexport function isValidDate(date: unknown): date is Date {\r\n return date instanceof Date && !isNaN(date.getTime());\r\n}\r\n"]}
@@ -0,0 +1,108 @@
1
+ import { L as Locale } from './types-tUMATEGI.mjs';
2
+ export { C as CURRENCY_MAP, D as DEFAULT_LOCALE, a as LocaleConfig } from './types-tUMATEGI.mjs';
3
+ export { textToSlug } from './string/index.mjs';
4
+ export { formatDate, formatDateTime, formatRelativeDate, isValidDate, toISOString } from './date/index.mjs';
5
+ export { formatCurrency } from './number/index.mjs';
6
+ export { GenericStatus, getStatusColor, getStatusVariant, translateStatus } from './status/index.mjs';
7
+
8
+ declare function extractInitials(name: string | null | undefined, maxChars?: number): string;
9
+ declare function generateUniqueId(text: string, prefix?: string, suffix?: string): string;
10
+ declare function truncateText(text: string, maxLength: number, suffix?: string): string;
11
+ declare function capitalize(text: string, options?: {
12
+ firstWordOnly?: boolean;
13
+ lowerRest?: boolean;
14
+ }): string;
15
+ declare function cleanText(text: string, allowSpaces?: boolean): string;
16
+ declare function countWords(text: string): number;
17
+ declare function isEmpty(text: string | null | undefined): boolean;
18
+ declare function normalizeSpaces(text: string, options?: {
19
+ newlines?: boolean;
20
+ }): string;
21
+
22
+ interface ValidationResult {
23
+ isValid: boolean;
24
+ errors?: string[];
25
+ }
26
+ declare function validateEmail(email: string, locale?: Locale): ValidationResult;
27
+ declare function validatePassword(password: string, options?: {
28
+ minLength?: number;
29
+ requireUppercase?: boolean;
30
+ requireLowercase?: boolean;
31
+ requireNumbers?: boolean;
32
+ requireSpecialChars?: boolean;
33
+ }, locale?: Locale): ValidationResult;
34
+ declare function validateUrl(url: string, locale?: Locale): ValidationResult;
35
+ declare function validatePhone(phone: string, locale?: Locale): ValidationResult;
36
+ declare function validateUsername(username: string, options?: {
37
+ minLength?: number;
38
+ maxLength?: number;
39
+ allowSpecialChars?: boolean;
40
+ }, locale?: Locale): ValidationResult;
41
+ declare function validateSlug(slug: string, options?: {
42
+ minLength?: number;
43
+ maxLength?: number;
44
+ }, locale?: Locale): ValidationResult;
45
+ declare function validateText(text: string, options?: {
46
+ minLength?: number;
47
+ maxLength?: number;
48
+ fieldName?: string;
49
+ }, locale?: Locale): ValidationResult;
50
+
51
+ declare function prefersReducedMotion(): boolean;
52
+ declare function onReducedMotionChange(callback: (prefersReduced: boolean) => void): () => void;
53
+ declare function scrollToPosition(x?: number, y?: number, options?: {
54
+ smooth?: boolean;
55
+ behavior?: ScrollBehavior;
56
+ }): void;
57
+ declare function scrollToTop(smooth?: boolean): void;
58
+ declare function smoothScrollTo(x: number, y: number, duration?: number): void;
59
+ declare function scrollToElement(element: string | Element, options?: {
60
+ smooth?: boolean;
61
+ offset?: number;
62
+ behavior?: ScrollBehavior;
63
+ }): void;
64
+ declare function isElementVisible(element: string | Element, threshold?: number): boolean;
65
+ declare function getElementPosition(element: string | Element): {
66
+ x: number;
67
+ y: number;
68
+ } | null;
69
+ declare function isMobile(): boolean;
70
+ declare function isDarkMode(): boolean;
71
+ declare function onDarkModeChange(callback: (isDark: boolean) => void): () => void;
72
+ declare function copyToClipboard(text: string): Promise<boolean>;
73
+ declare function downloadFile(blob: Blob, filename: string): void;
74
+
75
+ declare function formatNumber$1(num: number): string;
76
+ declare function calculateChange(current: number, previous: number): number;
77
+ declare function formatPercentage(value: number, options?: {
78
+ showSign?: boolean;
79
+ decimals?: number;
80
+ }): string;
81
+ declare function generateMockChartData(days: number, locale?: string): Array<Record<string, any>>;
82
+ declare function groupDataByPeriod<T extends Record<string, any>>(data: T[]): T[];
83
+ declare function calculateMovingAverage(data: number[], window: number): number[];
84
+ declare function findMinMax<T extends Record<string, any>>(data: T[], field: keyof T): {
85
+ min: number;
86
+ max: number;
87
+ };
88
+
89
+ declare function formatDate(date: string | Date, format?: 'short' | 'long' | 'full'): string;
90
+ declare function formatDateTime(date: string | Date): string;
91
+ declare function formatRelativeDate(date: string | Date): string;
92
+ declare function formatCurrency(value: number, options?: Intl.NumberFormatOptions): string;
93
+ declare function formatNumber(value: number, decimals?: number): string;
94
+ declare function formatCompact(value: number, decimals?: number): string;
95
+ declare function translateStatus(status: string): string;
96
+
97
+ declare const ptBr_formatCompact: typeof formatCompact;
98
+ declare const ptBr_formatCurrency: typeof formatCurrency;
99
+ declare const ptBr_formatDate: typeof formatDate;
100
+ declare const ptBr_formatDateTime: typeof formatDateTime;
101
+ declare const ptBr_formatNumber: typeof formatNumber;
102
+ declare const ptBr_formatRelativeDate: typeof formatRelativeDate;
103
+ declare const ptBr_translateStatus: typeof translateStatus;
104
+ declare namespace ptBr {
105
+ export { ptBr_formatCompact as formatCompact, ptBr_formatCurrency as formatCurrency, ptBr_formatDate as formatDate, ptBr_formatDateTime as formatDateTime, ptBr_formatNumber as formatNumber, ptBr_formatRelativeDate as formatRelativeDate, ptBr_translateStatus as translateStatus };
106
+ }
107
+
108
+ export { Locale, type ValidationResult, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatNumber$1 as formatNumber, formatPercentage, generateMockChartData, generateUniqueId, getElementPosition, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, ptBr as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };