@rainersoft/utils 1.0.0 → 1.0.2
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/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -13
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,10 @@ export { formatCurrency } from './number/index.mjs';
|
|
|
6
6
|
export { GenericStatus, getStatusColor, getStatusVariant, translateStatus } from './status/index.mjs';
|
|
7
7
|
|
|
8
8
|
declare function extractInitials(name: string | null | undefined, maxChars?: number): string;
|
|
9
|
+
declare function generateAvatarUrl(name: string, size?: number, backgroundColor?: string, textColor?: string): string;
|
|
10
|
+
declare function isValidAvatarUrl(url: string): boolean;
|
|
11
|
+
declare function getAvatarColorFromName(name: string): string;
|
|
12
|
+
declare function generateDynamicAvatarUrl(name: string, size?: number): string;
|
|
9
13
|
declare function generateUniqueId(text: string, prefix?: string, suffix?: string): string;
|
|
10
14
|
declare function truncateText(text: string, maxLength: number, suffix?: string): string;
|
|
11
15
|
declare function capitalize(text: string, options?: {
|
|
@@ -105,4 +109,4 @@ declare namespace ptBr {
|
|
|
105
109
|
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
110
|
}
|
|
107
111
|
|
|
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 };
|
|
112
|
+
export { Locale, type ValidationResult, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatNumber$1 as formatNumber, formatPercentage, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, ptBr as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export { formatCurrency } from './number/index.js';
|
|
|
6
6
|
export { GenericStatus, getStatusColor, getStatusVariant, translateStatus } from './status/index.js';
|
|
7
7
|
|
|
8
8
|
declare function extractInitials(name: string | null | undefined, maxChars?: number): string;
|
|
9
|
+
declare function generateAvatarUrl(name: string, size?: number, backgroundColor?: string, textColor?: string): string;
|
|
10
|
+
declare function isValidAvatarUrl(url: string): boolean;
|
|
11
|
+
declare function getAvatarColorFromName(name: string): string;
|
|
12
|
+
declare function generateDynamicAvatarUrl(name: string, size?: number): string;
|
|
9
13
|
declare function generateUniqueId(text: string, prefix?: string, suffix?: string): string;
|
|
10
14
|
declare function truncateText(text: string, maxLength: number, suffix?: string): string;
|
|
11
15
|
declare function capitalize(text: string, options?: {
|
|
@@ -105,4 +109,4 @@ declare namespace ptBr {
|
|
|
105
109
|
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
110
|
}
|
|
107
111
|
|
|
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 };
|
|
112
|
+
export { Locale, type ValidationResult, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatNumber$1 as formatNumber, formatPercentage, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, ptBr as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,55 @@ function extractInitials(name, maxChars = 2) {
|
|
|
23
23
|
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
24
24
|
return initials;
|
|
25
25
|
}
|
|
26
|
+
function generateAvatarUrl(name, size = 200, backgroundColor = "0891b2", textColor = "fff") {
|
|
27
|
+
const encodedName = encodeURIComponent(name);
|
|
28
|
+
return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;
|
|
29
|
+
}
|
|
30
|
+
function isValidAvatarUrl(url) {
|
|
31
|
+
if (!url || typeof url !== "string") {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
new URL(url);
|
|
36
|
+
return true;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getAvatarColorFromName(name) {
|
|
42
|
+
if (!name || typeof name !== "string") {
|
|
43
|
+
return "#0891b2";
|
|
44
|
+
}
|
|
45
|
+
let hash = 0;
|
|
46
|
+
for (let i = 0; i < name.length; i++) {
|
|
47
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
48
|
+
}
|
|
49
|
+
const colors = [
|
|
50
|
+
"#0891b2",
|
|
51
|
+
// cyan-600
|
|
52
|
+
"#9333ea",
|
|
53
|
+
// purple-600
|
|
54
|
+
"#db2777",
|
|
55
|
+
// pink-600
|
|
56
|
+
"#059669",
|
|
57
|
+
// emerald-600
|
|
58
|
+
"#2563eb",
|
|
59
|
+
// blue-600
|
|
60
|
+
"#f97316",
|
|
61
|
+
// orange-500
|
|
62
|
+
"#dc2626",
|
|
63
|
+
// red-600
|
|
64
|
+
"#7c3aed"
|
|
65
|
+
// violet-600
|
|
66
|
+
];
|
|
67
|
+
const index = Math.abs(hash) % colors.length;
|
|
68
|
+
return colors[index];
|
|
69
|
+
}
|
|
70
|
+
function generateDynamicAvatarUrl(name, size = 200) {
|
|
71
|
+
const color = getAvatarColorFromName(name);
|
|
72
|
+
const colorHex = color.replace("#", "");
|
|
73
|
+
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
74
|
+
}
|
|
26
75
|
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
27
76
|
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
28
77
|
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
@@ -811,8 +860,11 @@ exports.formatDateTime = formatDateTime;
|
|
|
811
860
|
exports.formatNumber = formatNumber2;
|
|
812
861
|
exports.formatPercentage = formatPercentage;
|
|
813
862
|
exports.formatRelativeDate = formatRelativeDate;
|
|
863
|
+
exports.generateAvatarUrl = generateAvatarUrl;
|
|
864
|
+
exports.generateDynamicAvatarUrl = generateDynamicAvatarUrl;
|
|
814
865
|
exports.generateMockChartData = generateMockChartData;
|
|
815
866
|
exports.generateUniqueId = generateUniqueId;
|
|
867
|
+
exports.getAvatarColorFromName = getAvatarColorFromName;
|
|
816
868
|
exports.getElementPosition = getElementPosition;
|
|
817
869
|
exports.getStatusColor = getStatusColor;
|
|
818
870
|
exports.getStatusVariant = getStatusVariant;
|
|
@@ -821,6 +873,7 @@ exports.isDarkMode = isDarkMode;
|
|
|
821
873
|
exports.isElementVisible = isElementVisible;
|
|
822
874
|
exports.isEmpty = isEmpty;
|
|
823
875
|
exports.isMobile = isMobile;
|
|
876
|
+
exports.isValidAvatarUrl = isValidAvatarUrl;
|
|
824
877
|
exports.isValidDate = isValidDate;
|
|
825
878
|
exports.normalizeSpaces = normalizeSpaces;
|
|
826
879
|
exports.onDarkModeChange = onDarkModeChange;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/text/index.ts","../src/string/index.ts","../src/date/index.ts","../src/number/index.ts","../src/status/index.ts","../src/validation/index.ts","../src/dom/index.ts","../src/stats/index.ts","../src/pt-br.ts"],"names":["formatNumber","window","formatCompact","formatCurrency","formatDate","formatDateTime","formatRelativeDate","translateStatus"],"mappings":";;;;;;;;;AA0BO,IAAM,cAAA,GAAyB;AAK/B,IAAM,YAAA,GAAuC;AAAA,EAClD,OAAA,EAAS,KAAA;AAAA,EACT,OAAA,EAAS,KAAA;AAAA,EACT,OAAA,EAAS;AACX;;;ACVO,SAAS,eAAA,CAAgB,IAAA,EAAiC,QAAA,GAAW,CAAA,EAAW;AACrF,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,CAAK,MAAK,EAAG;AACzB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,EAAA,MAAM,WAAW,KAAA,CACd,KAAA,CAAM,CAAA,EAAG,QAAQ,EACjB,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,CACxC,KAAK,EAAE,CAAA;AAEV,EAAA,OAAO,QAAA;AACT;AAiBO,SAAS,gBAAA,CACd,IAAA,EACA,MAAA,GAAS,EAAA,EACT,SAAS,EAAA,EACD;AACR,EAAA,MAAM,IAAA,GAAO,IAAA,CACV,WAAA,EAAY,CACZ,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA,CAC9B,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA,CACvB,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CACnB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAClB,IAAA,EAAK,CACL,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA;AAElB,EAAA,MAAM,QAAQ,CAAC,MAAA,EAAQ,MAAM,MAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AACnD,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;AAiBO,SAAS,YAAA,CACd,IAAA,EACA,SAAA,EACA,MAAA,GAAS,KAAA,EACD;AACR,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,IAAU,SAAA,EAAW;AACrC,IAAA,OAAO,IAAA,IAAQ,EAAA;AAAA,EACjB;AAEA,EAAA,OAAO,KAAK,SAAA,CAAU,CAAA,EAAG,SAAA,GAAY,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA;AACxD;AAgBO,SAAS,UAAA,CACd,IAAA,EACA,OAAA,GAA4D,EAAC,EACrD;AACR,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAElB,EAAA,MAAM,EAAE,aAAA,GAAgB,KAAA,EAAO,SAAA,GAAY,OAAM,GAAI,OAAA;AAErD,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,aAAY,IAC1B,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAO,IAAA,CAAK,QAAQ,OAAA,EAAS,CAAA,IAAA,KAAQ,KAAK,WAAA,EAAa,EAAE,WAAA,EAAY;AAAA,EACvE;AAEA,EAAA,OAAO,KAAK,OAAA,CAAQ,OAAA,EAAS,CAAA,IAAA,KAAQ,IAAA,CAAK,aAAa,CAAA;AACzD;AAeO,SAAS,SAAA,CAAU,IAAA,EAAc,WAAA,GAAc,IAAA,EAAc;AAClE,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAElB,EAAA,MAAM,OAAA,GAAU,cAAc,UAAA,GAAa,QAAA;AAC3C,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA;AACjC;AAeO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,CAAK,MAAK,EAAG;AACzB,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA;AAClC;AAeO,SAAS,QAAQ,IAAA,EAA0C;AAChE,EAAA,OAAO,CAAC,IAAA,IAAQ,CAAC,IAAA,CAAK,IAAA,EAAK;AAC7B;AAeO,SAAS,eAAA,CACd,IAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAElB,EAAA,MAAM,EAAE,QAAA,GAAW,KAAA,EAAM,GAAI,OAAA;AAE7B,EAAA,IAAI,OAAA,GAAU,IAAA;AAEd,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA;AAAA,EACvC,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA;AAAA,EACvC;AAEA,EAAA,OAAO,QAAQ,IAAA,EAAK;AACtB;;;AC1MO,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;;;ACbA,IAAM,cAAA,GAAiB;AAAA,EACrB,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,OAAA;AAAA,IACL,MAAA,EAAQ,CAAC,CAAA,KAAc,CAAA,MAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAW,SAAS,CAAA,CAAA;AAAA,IAChE,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,MAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,MAAA,GAAS,OAAO,CAAA,CAAA;AAAA,IAC1D,GAAA,EAAK,CAAC,CAAA,KAAc,CAAA,MAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,KAAA,GAAQ,MAAM,CAAA,CAAA;AAAA,IACvD,KAAA,EAAO,CAAC,CAAA,KAAc,CAAA,MAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAQ,OAAO,CAAA,CAAA;AAAA,IAC1D,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,MAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,KAAA,GAAQ,MAAM,CAAA;AAAA,GAC1D;AAAA,EACA,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,KAAA;AAAA,IACL,MAAA,EAAQ,CAAC,CAAA,KAAc,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAW,SAAS,CAAA,IAAA,CAAA;AAAA,IAC7D,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,MAAA,GAAS,OAAO,CAAA,IAAA,CAAA;AAAA,IACvD,GAAA,EAAK,CAAC,CAAA,KAAc,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,KAAA,GAAQ,MAAM,CAAA,IAAA,CAAA;AAAA,IACpD,KAAA,EAAO,CAAC,CAAA,KAAc,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,OAAA,GAAU,QAAQ,CAAA,IAAA,CAAA;AAAA,IAC1D,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,MAAA,GAAS,OAAO,CAAA,IAAA;AAAA,GACzD;AAAA,EACA,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,OAAA;AAAA,IACL,MAAA,EAAQ,CAAC,CAAA,KAAc,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAW,SAAS,CAAA,CAAA;AAAA,IAClE,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,MAAA,GAAS,OAAO,CAAA,CAAA;AAAA,IAC5D,GAAA,EAAK,CAAC,CAAA,KAAc,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAQ,SAAM,CAAA,CAAA;AAAA,IACzD,KAAA,EAAO,CAAC,CAAA,KAAc,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,KAAA,GAAQ,OAAO,CAAA,CAAA;AAAA,IAC5D,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,CAAA,GAAI,QAAA,GAAQ,SAAM,CAAA;AAAA;AAE9D,CAAA;AAgBO,SAAS,UAAA,CACd,IAAA,EACA,MAAA,GAAoC,MAAA,EACpC,SAAiB,cAAA,EACT;AACR,EAAA,MAAM,IAAI,OAAO,IAAA,KAAS,WAAW,IAAI,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAGtD,EAAA,MAAM,OAAA,GAAsC;AAAA,IAC1C,GAAA,EAAK,SAAA;AAAA,IACL,KAAA,EAAO,MAAA,KAAW,OAAA,GAAU,SAAA,GAAY,MAAA;AAAA,IACxC,IAAA,EAAM,SAAA;AAAA,IACN,GAAI,MAAA,KAAW,MAAA,IAAU,EAAE,SAAS,MAAA;AAAO,GAC7C;AAEA,EAAA,IAAI,WAAW,OAAA,EAAS;AACtB,IAAA,OAAO,CAAA,CAAE,kBAAA,CAAmB,MAAA,EAAQ,EAAE,GAAA,EAAK,WAAW,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,SAAA,EAAW,CAAA;AAAA,EAC3F;AAEA,EAAA,OAAO,CAAA,CAAE,kBAAA,CAAmB,MAAA,EAAQ,OAAO,CAAA;AAC7C;AAaO,SAAS,cAAA,CAAe,IAAA,EAAqB,MAAA,GAAiB,cAAA,EAAwB;AAC3F,EAAA,MAAM,IAAI,OAAO,IAAA,KAAS,WAAW,IAAI,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAEtD,EAAA,OAAO,CAAA,CAAE,eAAe,MAAA,EAAQ;AAAA,IAC9B,GAAA,EAAK,SAAA;AAAA,IACL,KAAA,EAAO,MAAA;AAAA,IACP,IAAA,EAAM,SAAA;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ;AAAA,GACT,CAAA;AACH;AAcO,SAAS,kBAAA,CAAmB,IAAA,EAAqB,MAAA,GAAiB,cAAA,EAAwB;AAC/F,EAAA,MAAM,IAAI,OAAO,IAAA,KAAS,WAAW,IAAI,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAGtD,EAAA,IAAI,EAAE,aAAa,IAAA,CAAA,IAAS,MAAA,CAAO,MAAM,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG;AACrD,IAAA,OAAO,EAAA;AAAA,EACT;AACA,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,OAAA,EAAQ,GAAI,EAAE,OAAA,EAAQ;AACzC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,GAAI,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA;AACvC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,EAAE,CAAA;AAExC,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAG,CAAA;AAEzC,EAAA,MAAM,KAAA,GAAQ,eAAe,MAAM,CAAA;AAGnC,EAAA,IAAI,UAAU,EAAA,EAAI;AAChB,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,aAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,UAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,aAAA;AAAA,EACjC;AAEA,EAAA,IAAI,OAAA,GAAU,EAAA,EAAI,OAAO,KAAA,CAAM,GAAA;AAC/B,EAAA,IAAI,OAAA,GAAU,EAAA,EAAI,OAAO,KAAA,CAAM,OAAO,OAAO,CAAA;AAC7C,EAAA,IAAI,QAAA,GAAW,EAAA,EAAI,OAAO,KAAA,CAAM,KAAK,QAAQ,CAAA;AAG7C,EAAA,IAAI,YAAY,CAAA,EAAG;AACjB,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,OAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,WAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,MAAA;AAAA,EACjC;AAEA,EAAA,IAAI,YAAY,CAAA,EAAG;AACjB,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,WAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,0BAAA;AAC/B,IAAA,IAAI,MAAA,KAAW,SAAS,OAAO,UAAA;AAAA,EACjC;AAEA,EAAA,IAAI,OAAA,GAAU,EAAA,EAAI,OAAO,KAAA,CAAM,IAAI,OAAO,CAAA;AAC1C,EAAA,IAAI,SAAA,GAAY,EAAA,EAAI,OAAO,KAAA,CAAM,MAAM,SAAS,CAAA;AAChD,EAAA,OAAO,KAAA,CAAM,KAAK,QAAQ,CAAA;AAC5B;AAQO,SAAS,YAAY,IAAA,EAAoB;AAC9C,EAAA,OAAO,KAAK,WAAA,EAAY;AAC1B;AAQO,SAAS,YAAY,IAAA,EAA6B;AACvD,EAAA,OAAO,gBAAgB,IAAA,IAAQ,CAAC,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA;AACtD;;;AC1JO,SAAS,cAAA,CACd,KAAA,EACA,MAAA,GAAiB,cAAA,EACjB,OAAA,EACQ;AACR,EAAA,MAAM,QAAA,GAAW,aAAa,MAAM,CAAA;AACpC,EAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ;AAAA,IACnC,KAAA,EAAO,UAAA;AAAA,IACP,QAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACjB;AAuCO,SAAS,YAAA,CAAa,KAAA,EAAe,QAAA,GAAW,CAAA,EAAG,SAAiB,cAAA,EAAwB;AACjG,EAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ;AAAA,IACnC,qBAAA,EAAuB,QAAA;AAAA,IACvB,qBAAA,EAAuB;AAAA,GACxB,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACjB;AAcO,SAAS,aAAA,CAAc,KAAA,EAAe,QAAA,GAAW,CAAA,EAAG,SAAiB,cAAA,EAAwB;AAClG,EAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ;AAAA,IACnC,QAAA,EAAU,SAAA;AAAA,IACV,cAAA,EAAgB,OAAA;AAAA,IAChB,qBAAA,EAAuB,QAAA;AAAA,IACvB,qBAAA,EAAuB;AAAA,GACxB,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACjB;;;ACpEA,IAAM,mBAAA,GAA8D;AAAA,EAClE,OAAA,EAAS;AAAA;AAAA,IAET,KAAA,EAAO,UAAA;AAAA,IACP,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU,WAAA;AAAA,IACV,SAAA,EAAW,UAAA;AAAA,IACX,OAAA,EAAS,aAAA;AAAA;AAAA,IAGT,OAAA,EAAS,UAAA;AAAA,IACT,MAAA,EAAQ,OAAA;AAAA,IACR,QAAA,EAAU,SAAA;AAAA,IACV,SAAA,EAAW,cAAA;AAAA,IACX,SAAA,EAAW,WAAA;AAAA;AAAA,IAGX,QAAA,EAAU,UAAA;AAAA,IACV,QAAA,EAAU,WAAA;AAAA;AAAA,IAGV,UAAA,EAAY,aAAA;AAAA,IACZ,IAAA,EAAM,MAAA;AAAA,IACN,MAAA,EAAQ,aAAA;AAAA,IACR,QAAA,EAAU,aAAA;AAAA,IACV,MAAA,EAAQ,QAAA;AAAA;AAAA,IAGN,QAAA,EAAU,YAAA;AAAA,IACV,UAAA,EAAY,mBAAA;AAAA,IACZ,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AAAA,EACA,OAAA,EAAS;AAAA,IACP,KAAA,EAAO,OAAA;AAAA,IACP,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU,UAAA;AAAA,IACV,SAAA,EAAW,WAAA;AAAA,IACX,OAAA,EAAS,SAAA;AAAA,IACT,OAAA,EAAS,SAAA;AAAA,IACT,MAAA,EAAQ,QAAA;AAAA,IACR,QAAA,EAAU,UAAA;AAAA,IACV,SAAA,EAAW,WAAA;AAAA,IACX,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU,UAAA;AAAA,IACV,QAAA,EAAU,UAAA;AAAA,IACV,UAAA,EAAY,YAAA;AAAA,IACZ,IAAA,EAAM,MAAA;AAAA,IACN,MAAA,EAAQ,QAAA;AAAA,IACR,QAAA,EAAU,UAAA;AAAA,IACV,MAAA,EAAQ,QAAA;AAAA,IACR,QAAA,EAAU,UAAA;AAAA,IACV,UAAA,EAAY,YAAA;AAAA,IACZ,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AAAA,EACA,OAAA,EAAS;AAAA,IACP,KAAA,EAAO,UAAA;AAAA,IACP,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU,WAAA;AAAA,IACV,SAAA,EAAW,YAAA;AAAA,IACX,OAAA,EAAS,WAAA;AAAA,IACT,OAAA,EAAS,WAAA;AAAA,IACT,MAAA,EAAQ,QAAA;AAAA,IACR,QAAA,EAAU,UAAA;AAAA,IACV,SAAA,EAAW,YAAA;AAAA,IACX,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU,UAAA;AAAA,IACV,QAAA,EAAU,WAAA;AAAA,IACV,UAAA,EAAY,YAAA;AAAA,IACZ,IAAA,EAAM,QAAA;AAAA,IACN,MAAA,EAAQ,WAAA;AAAA,IACR,QAAA,EAAU,aAAA;AAAA,IACV,MAAA,EAAQ,SAAA;AAAA,IACR,QAAA,EAAU,YAAA;AAAA,IACV,UAAA,EAAY,eAAA;AAAA,IACZ,MAAA,EAAQ,WAAA;AAAA,IACR,SAAA,EAAW;AAAA;AAEf,CAAA;AAcO,SAAS,eAAA,CAAgB,MAAA,EAAgB,MAAA,GAAiB,cAAA,EAAwB;AACvF,EAAA,MAAM,UAAA,GAAa,OAAO,WAAA,EAAY;AACtC,EAAA,OAAO,mBAAA,CAAoB,MAAM,CAAA,CAAE,UAAU,CAAA,IAAK,MAAA;AACpD;AAYO,SAAS,eAAe,MAAA,EAAwB;AACrD,EAAA,MAAM,UAAA,GAAa,OAAO,WAAA,EAAY;AAEtC,EAAA,MAAM,QAAA,GAAmC;AAAA,IACvC,KAAA,EAAO,eAAA;AAAA,IACP,OAAA,EAAS,iBAAA;AAAA,IACT,SAAA,EAAW,gBAAA;AAAA,IACX,MAAA,EAAQ,gBAAA;AAAA,IACR,QAAA,EAAU,eAAA;AAAA,IACV,QAAA,EAAU,iBAAA;AAAA,IACV,OAAA,EAAS,cAAA;AAAA,IACT,SAAA,EAAW,eAAA;AAAA,IACX,SAAA,EAAW,gBAAA;AAAA,IACX,SAAA,EAAW,cAAA;AAAA,IACX,QAAA,EAAU,gBAAA;AAAA,IACV,QAAA,EAAU,cAAA;AAAA,IACV,MAAA,EAAQ,cAAA;AAAA,IACR,QAAA,EAAU,gBAAA;AAAA,IACV,MAAA,EAAQ;AAAA,GACV;AAEA,EAAA,OAAO,QAAA,CAAS,UAAU,CAAA,IAAK,eAAA;AACjC;AAYO,SAAS,iBAAiB,MAAA,EAAqE;AACpG,EAAA,MAAM,UAAA,GAAa,OAAO,WAAA,EAAY;AAEtC,EAAA,IAAI,CAAC,aAAa,QAAA,EAAU,WAAA,EAAa,YAAY,UAAU,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG;AACrF,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,WAAW,WAAA,EAAa,UAAA,EAAY,UAAU,QAAQ,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG;AACjF,IAAA,OAAO,aAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,OAAA,EAAS,UAAA,EAAY,UAAU,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG;AAC1D,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,OAAO,SAAA;AACT;;;AChKO,SAAS,aAAA,CAAc,KAAA,EAAe,MAAA,GAAiB,cAAA,EAAkC;AAC9F,EAAA,MAAM,UAAA,GAAa,4BAAA;AACnB,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA;AAErC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,OAAA,EAAS,CAAC,mBAAgB,CAAA;AAAA,MAC1B,OAAA,EAAS,CAAC,eAAe,CAAA;AAAA,MACzB,OAAA,EAAS,CAAC,mBAAgB;AAAA,KAC5B;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAA,IAAK,OAAO,OAAO;AAAA,KAC1C;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AACzB;AAcO,SAAS,iBACd,QAAA,EACA,OAAA,GAMI,EAAC,EACL,SAAiB,cAAA,EACC;AAClB,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,CAAA;AAAA,IACZ,gBAAA,GAAmB,IAAA;AAAA,IACnB,gBAAA,GAAmB,IAAA;AAAA,IACnB,cAAA,GAAiB,IAAA;AAAA,IACjB,mBAAA,GAAsB;AAAA,GACxB,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,6BAA6B,SAAS,CAAA,WAAA,CAAA;AAAA,MACjD,SAAA,EAAW,qDAAA;AAAA,MACX,SAAA,EAAW,qDAAA;AAAA,MACX,OAAA,EAAS,2CAAA;AAAA,MACT,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,6BAA6B,SAAS,CAAA,WAAA,CAAA;AAAA,MACjD,SAAA,EAAW,qDAAA;AAAA,MACX,SAAA,EAAW,qDAAA;AAAA,MACX,OAAA,EAAS,2CAAA;AAAA,MACT,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,wCAAqC,SAAS,CAAA,WAAA,CAAA;AAAA,MACzD,SAAA,EAAW,gEAAA;AAAA,MACX,SAAA,EAAW,gEAAA;AAAA,MACX,OAAA,EAAS,sDAAA;AAAA,MACT,YAAA,EAAc;AAAA;AAChB,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,MAAM,CAAA,IAAK,cAAc,OAAO,CAAA;AAE/D,EAAA,IAAI,QAAA,CAAS,SAAS,SAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,gBAAA,IAAoB,CAAC,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC/C,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,gBAAA,IAAoB,CAAC,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC/C,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,cAAA,IAAkB,CAAC,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC1C,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,mBAAA,IAAuB,CAAC,wBAAA,CAAyB,IAAA,CAAK,QAAQ,CAAA,EAAG;AACnE,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACnC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,MAAA,KAAW,CAAA;AAAA,IAC3B;AAAA,GACF;AACF;AAaO,SAAS,WAAA,CAAY,GAAA,EAAa,MAAA,GAAiB,cAAA,EAAkC;AAC1F,EAAA,IAAI;AACF,IAAA,IAAI,IAAI,GAAG,CAAA;AACX,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,OAAA,EAAS,CAAC,iBAAc,CAAA;AAAA,MACxB,OAAA,EAAS,CAAC,aAAa,CAAA;AAAA,MACvB,OAAA,EAAS,CAAC,iBAAc;AAAA,KAC1B;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAA,IAAK,OAAO,OAAO;AAAA,KAC1C;AAAA,EACF;AACF;AAaO,SAAS,aAAA,CAAc,KAAA,EAAe,MAAA,GAAiB,cAAA,EAAkC;AAE9F,EAAA,MAAM,UAAA,GAAa,qCAAA;AACnB,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA;AAErC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,OAAA,EAAS,CAAC,sBAAmB,CAAA;AAAA,MAC7B,OAAA,EAAS,CAAC,sBAAsB,CAAA;AAAA,MAChC,OAAA,EAAS,CAAC,yBAAmB;AAAA,KAC/B;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAA,IAAK,OAAO,OAAO;AAAA,KAC1C;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AACzB;AAcO,SAAS,iBACd,QAAA,EACA,OAAA,GAII,EAAC,EACL,SAAiB,cAAA,EACC;AAClB,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,CAAA;AAAA,IACZ,SAAA,GAAY,EAAA;AAAA,IACZ,iBAAA,GAAoB;AAAA,GACtB,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,mCAAgC,SAAS,CAAA,YAAA,CAAA;AAAA,MACpD,SAAA,EAAW,mCAAgC,SAAS,CAAA,YAAA,CAAA;AAAA,MACpD,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,+BAA+B,SAAS,CAAA,YAAA,CAAA;AAAA,MACnD,SAAA,EAAW,8BAA8B,SAAS,CAAA,YAAA,CAAA;AAAA,MAClD,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,iCAA8B,SAAS,CAAA,YAAA,CAAA;AAAA,MAClD,SAAA,EAAW,iCAA8B,SAAS,CAAA,YAAA,CAAA;AAAA,MAClD,YAAA,EAAc;AAAA;AAChB,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,MAAM,CAAA,IAAK,cAAc,OAAO,CAAA;AAE/D,EAAA,IAAI,QAAA,CAAS,SAAS,SAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,QAAA,CAAS,SAAS,SAAA,EAAW;AAC/B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,MAAM,aAAA,GAAgB,oBAClB,sBAAA,GACA,sBAAA;AAEJ,EAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,QAAQ,CAAA,EAAG;AACjC,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACnC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,MAAA,KAAW,CAAA;AAAA,IAC3B;AAAA,GACF;AACF;AAcO,SAAS,aACd,IAAA,EACA,OAAA,GAGI,EAAC,EACL,SAAiB,cAAA,EACC;AAClB,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,CAAA;AAAA,IACZ,SAAA,GAAY;AAAA,GACd,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,+BAA4B,SAAS,CAAA,YAAA,CAAA;AAAA,MAChD,SAAA,EAAW,+BAA4B,SAAS,CAAA,YAAA,CAAA;AAAA,MAChD,aAAA,EAAe;AAAA,KACjB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,2BAA2B,SAAS,CAAA,YAAA,CAAA;AAAA,MAC/C,SAAA,EAAW,0BAA0B,SAAS,CAAA,YAAA,CAAA;AAAA,MAC9C,aAAA,EAAe;AAAA,KACjB;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,6BAA0B,SAAS,CAAA,YAAA,CAAA;AAAA,MAC9C,SAAA,EAAW,6BAA0B,SAAS,CAAA,YAAA,CAAA;AAAA,MAC9C,aAAA,EAAe;AAAA;AACjB,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,MAAM,CAAA,IAAK,cAAc,OAAO,CAAA;AAE/D,EAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,MAAM,SAAA,GAAY,4BAAA;AAClB,EAAA,IAAI,CAAC,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,EAAG;AACzB,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,aAAa,CAAA;AAAA,EACpC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,MAAA,KAAW,CAAA;AAAA,IAC3B;AAAA,GACF;AACF;AAcO,SAAS,aACd,IAAA,EACA,OAAA,GAII,EAAC,EACL,SAAiB,cAAA,EACC;AAClB,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,CAAA;AAAA,IACZ,SAAA,GAAY,QAAA;AAAA,IACZ,SAAA,GAAY;AAAA,GACd,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,wBAAA,EAAwB,SAAS,CAAA,YAAA,CAAA;AAAA,MACxD,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,wBAAA,EAAwB,SAAS,CAAA,YAAA;AAAA,KAC1D;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,oBAAA,EAAuB,SAAS,CAAA,YAAA,CAAA;AAAA,MACvD,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,mBAAA,EAAsB,SAAS,CAAA,YAAA;AAAA,KACxD;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,sBAAA,EAAsB,SAAS,CAAA,YAAA,CAAA;AAAA,MACtD,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,sBAAA,EAAsB,SAAS,CAAA,YAAA;AAAA;AACxD,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,MAAM,CAAA,IAAK,cAAc,OAAO,CAAA;AAE/D,EAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EAChC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,MAAA,KAAW,CAAA;AAAA,IAC3B;AAAA,GACF;AACF;;;ACrXO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAE1C,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA,CAAE,OAAA;AAC/D;AAgBO,SAAS,sBACd,QAAA,EACY;AACZ,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA;AAEvE,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAA2B;AAC/C,IAAA,QAAA,CAAS,EAAE,OAAO,CAAA;AAAA,EACpB,CAAA;AAGA,EAAA,IAAI,WAAW,gBAAA,EAAkB;AAC/B,IAAA,UAAA,CAAW,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAAA,EACpD,CAAA,MAAO;AAEL,IAAC,UAAA,CAAmB,YAAY,YAAY,CAAA;AAAA,EAC9C;AAGA,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,WAAW,mBAAA,EAAqB;AAClC,MAAA,UAAA,CAAW,mBAAA,CAAoB,UAAU,YAAY,CAAA;AAAA,IACvD,CAAA,MAAO;AAEL,MAAC,UAAA,CAAmB,eAAe,YAAY,CAAA;AAAA,IACjD;AAAA,EACF,CAAA;AACF;AAaO,SAAS,iBACd,CAAA,GAAY,CAAA,EACZ,IAAY,CAAA,EACZ,OAAA,GAGI,EAAC,EACC;AACN,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAO,QAAA,EAAS,GAAI,OAAA;AAErC,EAAA,MAAA,CAAO,QAAA,CAAS;AAAA,IACd,IAAA,EAAM,CAAA;AAAA,IACN,GAAA,EAAK,CAAA;AAAA,IACL,QAAA,EAAU,QAAA,KAAa,MAAA,GAAS,QAAA,GAAW,MAAA;AAAA,GAC5C,CAAA;AACH;AAWO,SAAS,WAAA,CAAY,SAAkB,KAAA,EAAa;AACzD,EAAA,gBAAA,CAAiB,CAAA,EAAG,CAAA,EAAG,EAAE,MAAA,EAAQ,CAAA;AACnC;AAYO,SAAS,cAAA,CACd,CAAA,EACA,CAAA,EACA,QAAA,GAAmB,GAAA,EACb;AACN,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,MAAM,YAAY,CAAA,GAAI,MAAA;AACtB,EAAA,MAAM,YAAY,CAAA,GAAI,MAAA;AACtB,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAElC,EAAA,SAAS,QAAQ,WAAA,EAA2B;AAC1C,IAAA,MAAM,UAAU,WAAA,GAAc,SAAA;AAC9B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,OAAA,GAAU,UAAU,CAAC,CAAA;AAG/C,IAAA,MAAM,eAAe,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,UAAU,CAAC,CAAA;AAEjD,IAAA,MAAM,QAAA,GAAW,SAAU,SAAA,GAAY,YAAA;AACvC,IAAA,MAAM,QAAA,GAAW,SAAU,SAAA,GAAY,YAAA;AAEvC,IAAA,MAAA,CAAO,QAAA,CAAS,UAAU,QAAQ,CAAA;AAElC,IAAA,IAAI,WAAW,CAAA,EAAG;AAChB,MAAA,qBAAA,CAAsB,OAAO,CAAA;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,qBAAA,CAAsB,OAAO,CAAA;AAC/B;AAYO,SAAS,eAAA,CACd,OAAA,EACA,OAAA,GAII,EAAC,EACC;AACN,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAO,MAAA,GAAS,CAAA,EAAG,UAAS,GAAI,OAAA;AAEjD,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,aAAA,GAAgB,QAAA,CAAS,cAAc,OAAO,CAAA;AAAA,EAChD,CAAA,MAAO;AACL,IAAA,aAAA,GAAgB,OAAA;AAAA,EAClB;AAEA,EAAA,IAAI,CAAC,aAAA,EAAe;AAEpB,EAAA,MAAM,IAAA,GAAO,cAAc,qBAAA,EAAsB;AACjD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,GAAM,MAAA,CAAO,OAAA,GAAU,MAAA;AAE9C,EAAA,MAAA,CAAO,QAAA,CAAS;AAAA,IACd,IAAA,EAAM,CAAA;AAAA,IACN,GAAA,EAAK,SAAA;AAAA,IACL,QAAA,EAAU,QAAA,KAAa,MAAA,GAAS,QAAA,GAAW,MAAA;AAAA,GAC5C,CAAA;AACH;AAaO,SAAS,gBAAA,CACd,OAAA,EACA,SAAA,GAAoB,CAAA,EACX;AACT,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAE1C,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,aAAA,GAAgB,QAAA,CAAS,cAAc,OAAO,CAAA;AAAA,EAChD,CAAA,MAAO;AACL,IAAA,aAAA,GAAgB,OAAA;AAAA,EAClB;AAEA,EAAA,IAAI,CAAC,eAAe,OAAO,KAAA;AAE3B,EAAA,MAAM,IAAA,GAAO,cAAc,qBAAA,EAAsB;AACjD,EAAA,MAAM,eAAe,MAAA,CAAO,WAAA;AAC5B,EAAA,MAAM,cAAc,MAAA,CAAO,UAAA;AAE3B,EAAA,MAAM,oBAAoB,YAAA,GAAe,SAAA;AACzC,EAAA,MAAM,sBAAsB,WAAA,GAAc,SAAA;AAE1C,EAAA,MAAM,sBACJ,IAAA,CAAK,MAAA,IAAU,iBAAA,IACf,IAAA,CAAK,OAAO,YAAA,GAAe,iBAAA;AAE7B,EAAA,MAAM,wBACJ,IAAA,CAAK,KAAA,IAAS,mBAAA,IACd,IAAA,CAAK,QAAQ,WAAA,GAAc,mBAAA;AAE7B,EAAA,OAAO,mBAAA,IAAuB,qBAAA;AAChC;AAYO,SAAS,mBACd,OAAA,EACiC;AACjC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,IAAA;AAE1C,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,aAAA,GAAgB,QAAA,CAAS,cAAc,OAAO,CAAA;AAAA,EAChD,CAAA,MAAO;AACL,IAAA,aAAA,GAAgB,OAAA;AAAA,EAClB;AAEA,EAAA,IAAI,CAAC,eAAe,OAAO,IAAA;AAE3B,EAAA,MAAM,IAAA,GAAO,cAAc,qBAAA,EAAsB;AAEjD,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAA,CAAK,IAAA,GAAO,MAAA,CAAO,OAAA;AAAA,IACtB,CAAA,EAAG,IAAA,CAAK,GAAA,GAAM,MAAA,CAAO;AAAA,GACvB;AACF;AAYO,SAAS,QAAA,GAAoB;AAClC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAG1C,EAAA,MAAM,aAAa,gEAAA,CAAiE,IAAA;AAAA,IAClF,SAAA,CAAU;AAAA,GACZ;AAGA,EAAA,MAAM,cAAA,GAAiB,OAAO,UAAA,IAAc,GAAA;AAE5C,EAAA,OAAO,UAAA,IAAc,cAAA;AACvB;AAYO,SAAS,UAAA,GAAsB;AACpC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAE1C,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,8BAA8B,CAAA,CAAE,OAAA;AAC3D;AAaO,SAAS,iBACd,QAAA,EACY;AACZ,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,CAAW,8BAA8B,CAAA;AAEnE,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAA2B;AAC/C,IAAA,QAAA,CAAS,EAAE,OAAO,CAAA;AAAA,EACpB,CAAA;AAGA,EAAA,IAAI,WAAW,gBAAA,EAAkB;AAC/B,IAAA,UAAA,CAAW,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAAA,EACpD,CAAA,MAAO;AACL,IAAC,UAAA,CAAmB,YAAY,YAAY,CAAA;AAAA,EAC9C;AAGA,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,WAAW,mBAAA,EAAqB;AAClC,MAAA,UAAA,CAAW,mBAAA,CAAoB,UAAU,YAAY,CAAA;AAAA,IACvD,CAAA,MAAO;AACL,MAAC,UAAA,CAAmB,eAAe,YAAY,CAAA;AAAA,IACjD;AAAA,EACF,CAAA;AACF;AAeA,eAAsB,gBAAgB,IAAA,EAAgC;AACpE,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAE1C,EAAA,IAAI;AAEF,IAAA,IAAI,SAAA,CAAU,SAAA,IAAa,MAAA,CAAO,eAAA,EAAiB;AACjD,MAAA,MAAM,SAAA,CAAU,SAAA,CAAU,SAAA,CAAU,IAAI,CAAA;AACxC,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAClD,IAAA,QAAA,CAAS,KAAA,GAAQ,IAAA;AACjB,IAAA,QAAA,CAAS,MAAM,QAAA,GAAW,OAAA;AAC1B,IAAA,QAAA,CAAS,MAAM,IAAA,GAAO,WAAA;AACtB,IAAA,QAAA,CAAS,MAAM,GAAA,GAAM,WAAA;AACrB,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAClC,IAAA,QAAA,CAAS,KAAA,EAAM;AACf,IAAA,QAAA,CAAS,MAAA,EAAO;AAEhB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,WAAA,CAAY,MAAM,CAAA;AAC1C,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAElC,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAWO,SAAS,YAAA,CAAa,MAAY,QAAA,EAAwB;AAC/D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACvC,EAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,EAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAC9B,EAAA,IAAA,CAAK,KAAA,EAAM;AACX,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAC9B,EAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AACzB;;;AC9YO,SAASA,cAAa,GAAA,EAAqB;AAChD,EAAA,IAAI,OAAO,GAAA,EAAS;AAClB,IAAA,OAAA,CAAQ,GAAA,GAAM,GAAA,EAAS,OAAA,CAAQ,CAAC,CAAA,GAAI,GAAA;AAAA,EACtC;AACA,EAAA,IAAI,OAAO,GAAA,EAAM;AACf,IAAA,OAAA,CAAQ,GAAA,GAAM,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA,GAAI,GAAA;AAAA,EACnC;AACA,EAAA,OAAO,IAAI,QAAA,EAAS;AACtB;AAgBO,SAAS,eAAA,CAAgB,SAAiB,QAAA,EAA0B;AACzE,EAAA,IAAI,QAAA,KAAa,GAAG,OAAO,GAAA;AAC3B,EAAA,OAAO,IAAA,CAAK,KAAA,CAAA,CAAQ,OAAA,GAAU,QAAA,IAAY,WAAY,GAAG,CAAA;AAC3D;AAgBO,SAAS,gBAAA,CACd,KAAA,EACA,OAAA,GAAqD,EAAC,EAC9C;AACR,EAAA,MAAM,EAAE,QAAA,GAAW,IAAA,EAAM,QAAA,GAAW,GAAE,GAAI,OAAA;AAE1C,EAAA,MAAM,IAAA,GAAO,QAAA,IAAY,KAAA,GAAQ,CAAA,GAAI,GAAA,GAAM,EAAA;AAC3C,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA;AAE7C,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,EAAG,cAAc,CAAA,CAAA,CAAA;AACjC;AAkBO,SAAS,qBAAA,CACd,IAAA,EACA,MAAA,GAAiB,OAAA,EACW;AAC5B,EAAA,MAAM,OAAO,EAAC;AACd,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AAErB,EAAA,KAAA,IAAS,CAAA,GAAI,IAAA,GAAO,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAClC,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,GAAG,CAAA;AACzB,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAQ,GAAI,CAAC,CAAA;AAE/B,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,kBAAA,CAAmB,MAAA,EAAQ;AAAA,QACpC,GAAA,EAAK,SAAA;AAAA,QACL,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,MACD,OAAO,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,GAAI,CAAA,GAAI,GAAA;AAAA,MAC1C,aAAa,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,GAAG,CAAA,GAAI,GAAA;AAAA,MAC/C,OAAO,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,GAAG,CAAA,GAAI,EAAA;AAAA,MACzC,UAAU,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,EAAE,CAAA,GAAI,EAAA;AAAA,MAC3C,QAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,EAAE,CAAA,GAAI;AAAA,KAC1C,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,IAAA;AACT;AAeO,SAAS,kBACd,IAAA,EAGK;AAGL,EAAA,OAAO,IAAA;AACT;AAeO,SAAS,sBAAA,CAAuB,MAAgBC,OAAAA,EAA0B;AAC/E,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,KAAA,IAAS,IAAIA,OAAAA,GAAS,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AAC7C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,CAAA,GAAIA,UAAS,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AACvE,IAAA,MAAA,CAAO,IAAA,CAAK,MAAMA,OAAM,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,MAAA;AACT;AAcO,SAAS,UAAA,CACd,MACA,KAAA,EAC8B;AAC9B,EAAA,MAAM,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,IAAA,KAAQ,OAAO,IAAA,CAAK,KAAK,CAAC,CAAA,IAAK,CAAC,CAAA;AAExD,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AAAA,IACvB,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM;AAAA,GACzB;AACF;;;AC9LA,IAAA,aAAA,GAAA;AAAA,QAAA,CAAA,aAAA,EAAA;AAAA,EAAA,aAAA,EAAA,MAAAC,cAAAA;AAAA,EAAA,cAAA,EAAA,MAAAC,eAAAA;AAAA,EAAA,UAAA,EAAA,MAAAC,WAAAA;AAAA,EAAA,cAAA,EAAA,MAAAC,eAAAA;AAAA,EAAA,YAAA,EAAA,MAAAL,aAAAA;AAAA,EAAA,kBAAA,EAAA,MAAAM,mBAAAA;AAAA,EAAA,eAAA,EAAA,MAAAC;AAAA,CAAA,CAAA;AAiCO,SAASH,WAAAA,CACd,IAAA,EACA,MAAA,GAAoC,MAAA,EAC5B;AACR,EAAA,OAAO,UAAA,CAAe,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AAC7C;AAKO,SAASC,gBAAe,IAAA,EAA6B;AAC1D,EAAA,OAAO,cAAA,CAAmB,MAAM,OAAO,CAAA;AACzC;AAKO,SAASC,oBAAmB,IAAA,EAA6B;AAC9D,EAAA,OAAO,kBAAA,CAAuB,MAAM,OAAO,CAAA;AAC7C;AASO,SAASH,eAAAA,CACd,OACA,OAAA,EACQ;AACR,EAAA,OAAO,cAAA,CAAmB,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AACnD;AAKO,SAASH,aAAAA,CAAa,KAAA,EAAe,QAAA,GAAW,CAAA,EAAW;AAChE,EAAA,OAAO,YAAA,CAAiB,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AAClD;AAKO,SAASE,cAAAA,CAAc,KAAA,EAAe,QAAA,GAAW,CAAA,EAAW;AACjE,EAAA,OAAO,aAAA,CAAkB,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AACnD;AASO,SAASK,iBAAgB,MAAA,EAAwB;AACtD,EAAA,OAAO,eAAA,CAAoB,QAAQ,OAAO,CAAA;AAC5C","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 * Text Utilities\r\n *\r\n * Utilitários universais para manipulação de texto e strings.\r\n *\r\n * @module @rainersoft/utils/text\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxChars - Número máximo de caracteres (padrão: 2)\r\n * @returns Iniciais do nome em maiúsculas\r\n *\r\n * @example\r\n * ```ts\r\n * extractInitials('John Doe') // 'JD'\r\n * extractInitials('Maria Silva Santos') // 'MS'\r\n * extractInitials('Apple') // 'A'\r\n * extractInitials('', 3) // ''\r\n * ```\r\n */\r\nexport function extractInitials(name: string | null | undefined, maxChars = 2): string {\r\n if (!name || !name.trim()) {\r\n return '';\r\n }\r\n\r\n const words = name.trim().split(/\\s+/);\r\n const initials = words\r\n .slice(0, maxChars)\r\n .map(word => word.charAt(0).toUpperCase())\r\n .join('');\r\n\r\n return initials;\r\n}\r\n\r\n/**\r\n * Gera ID único baseado em texto\r\n *\r\n * @param text - Texto base para o ID\r\n * @param prefix - Prefixo opcional\r\n * @param suffix - Sufixo opcional\r\n * @returns ID único em formato slug\r\n *\r\n * @example\r\n * ```ts\r\n * generateUniqueId('Hello World') // 'hello-world'\r\n * generateUniqueId('Hello World', 'section') // 'section-hello-world'\r\n * generateUniqueId('Olá! Como vai?', '', '123') // 'ola-como-vai-123'\r\n * ```\r\n */\r\nexport function generateUniqueId(\r\n text: string,\r\n prefix = '',\r\n suffix = ''\r\n): string {\r\n const slug = text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '') // Remove acentos\r\n .replace(/[^\\w\\s-]/g, '') // Remove caracteres especiais\r\n .replace(/\\s+/g, '-') // Substitui espaços por hífens\r\n .replace(/-+/g, '-') // Remove hífens duplicados\r\n .trim()\r\n .substring(0, 50); // Limita tamanho\r\n\r\n const parts = [prefix, slug, suffix].filter(Boolean);\r\n return parts.join('-');\r\n}\r\n\r\n/**\r\n * Trunca texto com elipse\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo para adicionar (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * ```ts\r\n * truncateText('Hello World', 5) // 'Hello...'\r\n * truncateText('Hello World', 8, '...') // 'Hello...'\r\n * truncateText('Short', 10) // 'Short'\r\n * ```\r\n */\r\nexport function truncateText(\r\n text: string,\r\n maxLength: number,\r\n suffix = '...'\r\n): string {\r\n if (!text || text.length <= maxLength) {\r\n return text || '';\r\n }\r\n\r\n return text.substring(0, maxLength - suffix.length) + suffix;\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 * @param options - Opções de capitalização\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * ```ts\r\n * capitalize('hello world') // 'Hello World'\r\n * capitalize('hello world', { firstWordOnly: true }) // 'Hello world'\r\n * capitalize('HELLO WORLD', { lowerRest: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function capitalize(\r\n text: string,\r\n options: { firstWordOnly?: boolean; lowerRest?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { firstWordOnly = false, lowerRest = false } = options;\r\n\r\n if (firstWordOnly) {\r\n return text.charAt(0).toUpperCase() + \r\n (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));\r\n }\r\n\r\n if (lowerRest) {\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase()).toLowerCase();\r\n }\r\n\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Remove caracteres especiais mantendo apenas alfanuméricos e espaços\r\n *\r\n * @param text - Texto para limpar\r\n * @param allowSpaces - Se deve permitir espaços\r\n * @returns Texto limpo\r\n *\r\n * @example\r\n * ```ts\r\n * cleanText('Olá! Como vai?') // 'Ola Como vai'\r\n * cleanText('Olá! Como vai?', false) // 'OlaComoVai'\r\n * ```\r\n */\r\nexport function cleanText(text: string, allowSpaces = true): string {\r\n if (!text) return '';\r\n\r\n const pattern = allowSpaces ? /[^\\w\\s]/g : /[^\\w]/g;\r\n return text.replace(pattern, '');\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\n * @example\r\n * ```ts\r\n * countWords('Hello world') // 2\r\n * countWords(' Hello world ') // 2\r\n * countWords('') // 0\r\n * ```\r\n */\r\nexport function countWords(text: string): number {\r\n if (!text || !text.trim()) {\r\n return 0;\r\n }\r\n\r\n return text.trim().split(/\\s+/).length;\r\n}\r\n\r\n/**\r\n * Verifica se texto está vazio ou contém apenas espaços\r\n *\r\n * @param text - Texto para verificar\r\n * @returns True se estiver vazio\r\n *\r\n * @example\r\n * ```ts\r\n * isEmpty('') // true\r\n * isEmpty(' ') // true\r\n * isEmpty('Hello') // false\r\n * ```\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || !text.trim();\r\n}\r\n\r\n/**\r\n * Remove espaços em branco extras\r\n *\r\n * @param text - Texto para limpar\r\n * @param options - Opções de limpeza\r\n * @returns Texto sem espaços extras\r\n *\r\n * @example\r\n * ```ts\r\n * normalizeSpaces(' Hello World ') // 'Hello World'\r\n * normalizeSpaces('Hello\\nWorld', { newlines: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function normalizeSpaces(\r\n text: string,\r\n options: { newlines?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { newlines = false } = options;\r\n \r\n let cleaned = text;\r\n \r\n if (newlines) {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n } else {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n }\r\n \r\n return cleaned.trim();\r\n}\r\n","/**\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","/**\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","/**\r\n * Number Utilities\r\n *\r\n * Utilitários para formatação de números, moedas e percentuais.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/number\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport type { Locale } from '../types';\r\nimport { DEFAULT_LOCALE, CURRENCY_MAP } from '../types';\r\n\r\n/**\r\n * Formata número como moeda com suporte a idiomas\r\n *\r\n * @param value - Valor numérico\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @param options - Opções de formatação\r\n * @returns Valor formatado\r\n *\r\n * @example\r\n * formatCurrency(1234.56) // 'R$ 1.234,56' (pt-BR)\r\n * formatCurrency(1234.56, 'en-US') // '$1,234.56'\r\n * formatCurrency(1234.56, 'es-ES') // '1.234,56 €'\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n locale: Locale = DEFAULT_LOCALE,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n const currency = CURRENCY_MAP[locale];\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n ...options,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número como percentual\r\n *\r\n * @param value - Valor entre 0 e 1 (ou 0 e 100 se usePercentage=true)\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param usePercentage - Se true, espera valor 0-100 (padrão: false)\r\n * @returns Percentual formatado\r\n *\r\n * @example\r\n * formatPercent(0.1234) // '12%'\r\n * formatPercent(0.1234, 2) // '12,34%'\r\n * formatPercent(12.34, 2, true) // '12,34%'\r\n */\r\nexport function formatPercent(\r\n value: number,\r\n decimals = 0,\r\n usePercentage = false\r\n): string {\r\n return new Intl.NumberFormat('pt-BR', {\r\n style: 'percent',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(usePercentage ? value / 100 : value);\r\n}\r\n\r\n/**\r\n * Formata número com separadores de milhar\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número formatado\r\n *\r\n * @example\r\n * formatNumber(1234567) // '1.234.567' (pt-BR)\r\n * formatNumber(1234567, 0, 'en-US') // '1,234,567'\r\n */\r\nexport function formatNumber(value: number, decimals = 0, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número de forma compacta (1K, 1M, 1B)\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 1)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número compacto\r\n *\r\n * @example\r\n * formatCompact(1234) // '1,2 mil' (pt-BR)\r\n * formatCompact(1234567, 1, 'en-US') // '1.2M'\r\n */\r\nexport function formatCompact(value: number, decimals = 1, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n notation: 'compact',\r\n compactDisplay: 'short',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Converte string de moeda para número\r\n *\r\n * @param currency - String de moeda (ex: 'R$ 1.234,56')\r\n * @returns Valor numérico\r\n *\r\n * @example\r\n * parseCurrency('R$ 1.234,56') // 1234.56\r\n * parseCurrency('1.234,56') // 1234.56\r\n */\r\nexport function parseCurrency(currency: string): number {\r\n const cleaned = currency\r\n .replace(/[R$\\s]/g, '')\r\n .replace(/\\./g, '')\r\n .replace(',', '.');\r\n return parseFloat(cleaned);\r\n}\r\n\r\n/**\r\n * Arredonda número para casas decimais\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais\r\n * @returns Valor arredondado\r\n *\r\n * @example\r\n * round(1.2345, 2) // 1.23\r\n */\r\nexport function round(value: number, decimals = 2): number {\r\n const factor = Math.pow(10, decimals);\r\n return Math.round(value * factor) / factor;\r\n}\r\n\r\n/**\r\n * Clamp - limita número entre min e max\r\n *\r\n * @param value - Valor\r\n * @param min - Mínimo\r\n * @param max - Máximo\r\n * @returns Valor limitado\r\n *\r\n * @example\r\n * clamp(150, 0, 100) // 100\r\n * clamp(-10, 0, 100) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n return Math.min(Math.max(value, min), max);\r\n}\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","/**\r\n * Validation Utilities\r\n *\r\n * Utilitários para validação de dados com suporte a múltiplos idiomas.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/validation\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 * Interface para resultado de validação\r\n */\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors?: string[];\r\n}\r\n\r\n/**\r\n * Valida email usando regex RFC 5322\r\n *\r\n * @param email - Email para validar\r\n * @param locale - Idioma das mensagens de erro (padrão: 'pt-BR')\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateEmail('user@example.com') // { isValid: true }\r\n * validateEmail('invalid-email') // { isValid: false, errors: ['Email inválido'] }\r\n */\r\nexport function validateEmail(email: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n const isValid = emailRegex.test(email);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Email inválido'],\r\n 'en-US': ['Invalid email'],\r\n 'es-ES': ['Email inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida senha com critérios de segurança\r\n *\r\n * @param password - Senha para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePassword('MySecure123!') // { isValid: true }\r\n * validatePassword('123') // { isValid: false, errors: ['Senha deve ter pelo menos 8 caracteres'] }\r\n */\r\nexport function validatePassword(\r\n password: string, \r\n options: {\r\n minLength?: number;\r\n requireUppercase?: boolean;\r\n requireLowercase?: boolean;\r\n requireNumbers?: boolean;\r\n requireSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 8,\r\n requireUppercase = true,\r\n requireLowercase = true,\r\n requireNumbers = true,\r\n requireSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Senha deve ter pelo menos ${minLength} caracteres`,\r\n uppercase: 'Senha deve conter pelo menos uma letra maiúscula',\r\n lowercase: 'Senha deve conter pelo menos uma letra minúscula',\r\n numbers: 'Senha deve conter pelo menos um número',\r\n specialChars: 'Senha deve conter pelo menos um caractere especial'\r\n },\r\n 'en-US': {\r\n minLength: `Password must be at least ${minLength} characters`,\r\n uppercase: 'Password must contain at least one uppercase letter',\r\n lowercase: 'Password must contain at least one lowercase letter',\r\n numbers: 'Password must contain at least one number',\r\n specialChars: 'Password must contain at least one special character'\r\n },\r\n 'es-ES': {\r\n minLength: `La contraseña debe tener al menos ${minLength} caracteres`,\r\n uppercase: 'La contraseña debe contener al menos una letra mayúscula',\r\n lowercase: 'La contraseña debe contener al menos una letra minúscula',\r\n numbers: 'La contraseña debe contener al menos un número',\r\n specialChars: 'La contraseña debe contener al menos un carácter especial'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (password.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (requireUppercase && !/[A-Z]/.test(password)) {\r\n errors.push(messages.uppercase);\r\n }\r\n \r\n if (requireLowercase && !/[a-z]/.test(password)) {\r\n errors.push(messages.lowercase);\r\n }\r\n \r\n if (requireNumbers && !/\\d/.test(password)) {\r\n errors.push(messages.numbers);\r\n }\r\n \r\n if (requireSpecialChars && !/[!@#$%^&*(),.?\":{}|<>]/.test(password)) {\r\n errors.push(messages.specialChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida URL\r\n *\r\n * @param url - URL para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUrl('https://example.com') // { isValid: true }\r\n * validateUrl('not-a-url') // { isValid: false, errors: ['URL inválida'] }\r\n */\r\nexport function validateUrl(url: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n try {\r\n new URL(url);\r\n return { isValid: true };\r\n } catch {\r\n const errors = {\r\n 'pt-BR': ['URL inválida'],\r\n 'en-US': ['Invalid URL'],\r\n 'es-ES': ['URL inválida']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Valida telefone (formato brasileiro por padrão)\r\n *\r\n * @param phone - Telefone para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePhone('(11) 98765-4321') // { isValid: true }\r\n * validatePhone('123') // { isValid: false, errors: ['Telefone inválido'] }\r\n */\r\nexport function validatePhone(phone: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n // Regex para telefone brasileiro: (XX) XXXXX-XXXX ou (XX) XXXX-XXXX\r\n const phoneRegex = /^\\(?\\d{2}\\)?[\\s-]?\\d{4,5}[-]?\\d{4}$/;\r\n const isValid = phoneRegex.test(phone);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Telefone inválido'],\r\n 'en-US': ['Invalid phone number'],\r\n 'es-ES': ['Teléfono inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida username para registro\r\n *\r\n * @param username - Username para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUsername('user123') // { isValid: true }\r\n * validateUsername('us') // { isValid: false, errors: ['Username muito curto'] }\r\n */\r\nexport function validateUsername(\r\n username: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n allowSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 20,\r\n allowSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Username muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muito longo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contém caracteres inválidos'\r\n },\r\n 'en-US': {\r\n minLength: `Username too short (minimum ${minLength} characters)`,\r\n maxLength: `Username too long (maximum ${maxLength} characters)`,\r\n invalidChars: 'Username contains invalid characters'\r\n },\r\n 'es-ES': {\r\n minLength: `Username muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muy largo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contiene caracteres inválidos'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (username.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (username.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const usernameRegex = allowSpecialChars \r\n ? /^[a-zA-Z0-9_]{3,20}$/\r\n : /^[a-zA-Z0-9_]{3,20}$/;\r\n \r\n if (!usernameRegex.test(username)) {\r\n errors.push(messages.invalidChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida slug para URLs amigáveis\r\n *\r\n * @param slug - Slug para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateSlug('my-post-title') // { isValid: true }\r\n * validateSlug('My Post Title') // { isValid: false, errors: ['Slug inválido'] }\r\n */\r\nexport function validateSlug(\r\n slug: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 100\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Slug muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muito longo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use apenas letras minúsculas, números e hífens'\r\n },\r\n 'en-US': {\r\n minLength: `Slug too short (minimum ${minLength} characters)`,\r\n maxLength: `Slug too long (maximum ${maxLength} characters)`,\r\n invalidFormat: 'Invalid slug - use only lowercase letters, numbers and hyphens'\r\n },\r\n 'es-ES': {\r\n minLength: `Slug muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muy largo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use solo letras minúsculas, números y guiones'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (slug.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (slug.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n if (!slugRegex.test(slug)) {\r\n errors.push(messages.invalidFormat);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida texto com comprimento mínimo e máximo\r\n *\r\n * @param text - Texto para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateText('Hello', { minLength: 3 }) // { isValid: true }\r\n * validateText('Hi', { minLength: 3 }) // { isValid: false, errors: ['Texto muito curto'] }\r\n */\r\nexport function validateText(\r\n text: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n fieldName?: string;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 0,\r\n maxLength = Infinity,\r\n fieldName = 'Texto'\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `${fieldName} muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muito longo (máximo ${maxLength} caracteres)`\r\n },\r\n 'en-US': {\r\n minLength: `${fieldName} too short (minimum ${minLength} characters)`,\r\n maxLength: `${fieldName} too long (maximum ${maxLength} characters)`\r\n },\r\n 'es-ES': {\r\n minLength: `${fieldName} muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muy largo (máximo ${maxLength} caracteres)`\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (text.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (text.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n","/**\r\n * DOM Utilities\r\n *\r\n * Utilitários para manipulação do DOM e interações com o browser.\r\n * Funciona em qualquer ambiente browser moderno.\r\n *\r\n * @module @rainersoft/utils/dom\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Verifica se usuário prefere movimento reduzido (accessibility)\r\n *\r\n * @returns true se preferir movimento reduzido\r\n *\r\n * @example\r\n * if (prefersReducedMotion()) {\r\n * // Desabilitar animações\r\n * }\r\n */\r\nexport function prefersReducedMotion(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças na preferência de movimento\r\n *\r\n * @param callback - Função chamada quando a preferência muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onReducedMotionChange((prefersReduced) => {\r\n * console.log('Motion preference changed:', prefersReduced);\r\n * });\r\n * \r\n * // Remover listener quando necessário\r\n * unsubscribe();\r\n */\r\nexport function onReducedMotionChange(\r\n callback: (prefersReduced: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener (compatibilidade com browsers antigos)\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Rola a página para uma posição específica\r\n *\r\n * @param x - Posição horizontal (padrão: 0)\r\n * @param y - Posição vertical (padrão: 0)\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToPosition(0, 500); // Rola para o topo com 500px de margem\r\n * scrollToPosition(0, 0, { smooth: true }); // Scroll suave para o topo\r\n */\r\nexport function scrollToPosition(\r\n x: number = 0,\r\n y: number = 0,\r\n options: {\r\n smooth?: boolean;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, behavior } = options;\r\n \r\n window.scrollTo({\r\n left: x,\r\n top: y,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Rola a página para o topo\r\n *\r\n * @param smooth - Se deve usar scroll suave (padrão: false)\r\n *\r\n * @example\r\n * scrollToTop(); // Scroll instantâneo para o topo\r\n * scrollToTop(true); // Scroll suave para o topo\r\n */\r\nexport function scrollToTop(smooth: boolean = false): void {\r\n scrollToPosition(0, 0, { smooth });\r\n}\r\n\r\n/**\r\n * Rola suavemente para uma posição\r\n *\r\n * @param x - Posição horizontal\r\n * @param y - Posição vertical\r\n * @param duration - Duração da animação em ms (padrão: 300)\r\n *\r\n * @example\r\n * smoothScrollTo(0, 500, 500); // Animação de 500ms para rolar 500px\r\n */\r\nexport function smoothScrollTo(\r\n x: number,\r\n y: number,\r\n duration: number = 300\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const startX = window.scrollX;\r\n const startY = window.scrollY;\r\n const distanceX = x - startX;\r\n const distanceY = y - startY;\r\n const startTime = performance.now();\r\n \r\n function animate(currentTime: number): void {\r\n const elapsed = currentTime - startTime;\r\n const progress = Math.min(elapsed / duration, 1);\r\n \r\n // Easing function (ease-out)\r\n const easeProgress = 1 - Math.pow(1 - progress, 3);\r\n \r\n const currentX = startX + (distanceX * easeProgress);\r\n const currentY = startY + (distanceY * easeProgress);\r\n \r\n window.scrollTo(currentX, currentY);\r\n \r\n if (progress < 1) {\r\n requestAnimationFrame(animate);\r\n }\r\n }\r\n \r\n requestAnimationFrame(animate);\r\n}\r\n\r\n/**\r\n * Rola para um elemento específico\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToElement('#my-element'); // Scroll instantâneo\r\n * scrollToElement('.section', { smooth: true, offset: 100 }); // Scroll suave com offset\r\n */\r\nexport function scrollToElement(\r\n element: string | Element,\r\n options: {\r\n smooth?: boolean;\r\n offset?: number;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, offset = 0, behavior } = options;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const absoluteY = rect.top + window.scrollY - offset;\r\n \r\n window.scrollTo({\r\n left: 0,\r\n top: absoluteY,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Verifica se elemento está visível na viewport\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param threshold - Limiar de visibilidade (0 a 1, padrão: 0)\r\n * @returns true se elemento estiver visível\r\n *\r\n * @example\r\n * isElementVisible('#my-element'); // true se elemento estiver na viewport\r\n * isElementVisible('.section', 0.5); // true se 50% do elemento estiver visível\r\n */\r\nexport function isElementVisible(\r\n element: string | Element,\r\n threshold: number = 0\r\n): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return false;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const windowHeight = window.innerHeight;\r\n const windowWidth = window.innerWidth;\r\n \r\n const verticalThreshold = windowHeight * threshold;\r\n const horizontalThreshold = windowWidth * threshold;\r\n \r\n const isVisibleVertically = \r\n rect.bottom >= verticalThreshold && \r\n rect.top <= windowHeight - verticalThreshold;\r\n \r\n const isVisibleHorizontally = \r\n rect.right >= horizontalThreshold && \r\n rect.left <= windowWidth - horizontalThreshold;\r\n \r\n return isVisibleVertically && isVisibleHorizontally;\r\n}\r\n\r\n/**\r\n * Obtém a posição de um elemento em relação ao documento\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @returns Posição { x, y } ou null se elemento não for encontrado\r\n *\r\n * @example\r\n * const position = getElementPosition('#my-element');\r\n * console.log('X:', position.x, 'Y:', position.y);\r\n */\r\nexport function getElementPosition(\r\n element: string | Element\r\n): { x: number; y: number } | null {\r\n if (typeof window === 'undefined') return null;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return null;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n \r\n return {\r\n x: rect.left + window.scrollX,\r\n y: rect.top + window.scrollY\r\n };\r\n}\r\n\r\n/**\r\n * Verifica se está em dispositivo móvel\r\n *\r\n * @returns true se for dispositivo móvel\r\n *\r\n * @example\r\n * if (isMobile()) {\r\n * // Aplicar layout mobile\r\n * }\r\n */\r\nexport function isMobile(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n // Verificar User Agent\r\n const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\r\n navigator.userAgent\r\n );\r\n \r\n // Verificar tamanho de tela (fallback)\r\n const isMobileScreen = window.innerWidth <= 768;\r\n \r\n return isMobileUA || isMobileScreen;\r\n}\r\n\r\n/**\r\n * Verifica se está em modo escuro\r\n *\r\n * @returns true se o sistema preferir modo escuro\r\n *\r\n * @example\r\n * if (isDarkMode()) {\r\n * // Aplicar tema escuro\r\n * }\r\n */\r\nexport function isDarkMode(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças no tema do sistema\r\n *\r\n * @param callback - Função chamada quando o tema muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onDarkModeChange((isDark) => {\r\n * console.log('Theme changed:', isDark ? 'dark' : 'light');\r\n * });\r\n */\r\nexport function onDarkModeChange(\r\n callback: (isDark: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Copia texto para a área de transferência\r\n *\r\n * @param text - Texto para copiar\r\n * @returns Promise que resolve para true se sucesso\r\n *\r\n * @example\r\n * copyToClipboard('Hello World').then(success => {\r\n * if (success) {\r\n * console.log('Texto copiado!');\r\n * }\r\n * });\r\n */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof window === 'undefined') return false;\r\n \r\n try {\r\n // Tentar usar a API moderna\r\n if (navigator.clipboard && window.isSecureContext) {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n }\r\n \r\n // Fallback para browsers mais antigos\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-999999px';\r\n textArea.style.top = '-999999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n \r\n const result = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n \r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Baixa um arquivo como blob\r\n *\r\n * @param blob - Blob para baixar\r\n * @param filename - Nome do arquivo\r\n *\r\n * @example\r\n * downloadFile(new Blob(['Hello World'], { type: 'text/plain' }), 'hello.txt');\r\n */\r\nexport function downloadFile(blob: Blob, filename: string): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = filename;\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n","/**\r\n * Stats Formatting Utilities\r\n *\r\n * Utilitários universais para formatação de estatísticas e números.\r\n *\r\n * @module @rainersoft/utils/stats\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Formata número grande com abreviação (1.5k, 2.3M, etc)\r\n *\r\n * @param num - Número para formatar\r\n * @returns String formatada com abreviação\r\n *\r\n * @example\r\n * ```ts\r\n * formatNumber(1500) // '1.5k'\r\n * formatNumber(2500000) // '2.5M'\r\n * formatNumber(999) // '999'\r\n * ```\r\n */\r\nexport function formatNumber(num: number): string {\r\n if (num >= 1000000) {\r\n return (num / 1000000).toFixed(1) + 'M';\r\n }\r\n if (num >= 1000) {\r\n return (num / 1000).toFixed(1) + 'k';\r\n }\r\n return num.toString();\r\n}\r\n\r\n/**\r\n * Calcula percentual de mudança entre dois valores\r\n *\r\n * @param current - Valor atual\r\n * @param previous - Valor anterior\r\n * @returns Percentual de mudança (arredondado)\r\n *\r\n * @example\r\n * ```ts\r\n * calculateChange(150, 100) // 50\r\n * calculateChange(80, 100) // -20\r\n * calculateChange(100, 0) // 100\r\n * ```\r\n */\r\nexport function calculateChange(current: number, previous: number): number {\r\n if (previous === 0) return 100;\r\n return Math.round(((current - previous) / previous) * 100);\r\n}\r\n\r\n/**\r\n * Formata percentual com sinal\r\n *\r\n * @param value - Valor do percentual\r\n * @param options - Opções de formatação\r\n * @returns String formatada com sinal e símbolo\r\n *\r\n * @example\r\n * ```ts\r\n * formatPercentage(25) // '+25%'\r\n * formatPercentage(-10) // '-10%'\r\n * formatPercentage(0) // '0%'\r\n * ```\r\n */\r\nexport function formatPercentage(\r\n value: number,\r\n options: { showSign?: boolean; decimals?: number } = {}\r\n): string {\r\n const { showSign = true, decimals = 0 } = options;\r\n \r\n const sign = showSign && value > 0 ? '+' : '';\r\n const formattedValue = value.toFixed(decimals);\r\n \r\n return `${sign}${formattedValue}%`;\r\n}\r\n\r\n/**\r\n * Gera dados de exemplo para gráficos\r\n *\r\n * @param days - Número de dias para gerar dados\r\n * @param locale - Idioma para formatação de datas\r\n * @returns Array de dados mock\r\n *\r\n * @example\r\n * ```ts\r\n * const data = generateMockChartData(7);\r\n * // [\r\n * // { date: '01/12', views: 1234, uniqueViews: 890, likes: 67, comments: 23 },\r\n * // ...\r\n * // ]\r\n * ```\r\n */\r\nexport function generateMockChartData(\r\n days: number,\r\n locale: string = 'pt-BR'\r\n): Array<Record<string, any>> {\r\n const data = [];\r\n const now = new Date();\r\n\r\n for (let i = days - 1; i >= 0; i--) {\r\n const date = new Date(now);\r\n date.setDate(date.getDate() - i);\r\n\r\n data.push({\r\n date: date.toLocaleDateString(locale, {\r\n day: '2-digit',\r\n month: '2-digit',\r\n }),\r\n views: Math.floor(Math.random() * 1000) + 500,\r\n uniqueViews: Math.floor(Math.random() * 700) + 300,\r\n likes: Math.floor(Math.random() * 100) + 50,\r\n comments: Math.floor(Math.random() * 50) + 10,\r\n shares: Math.floor(Math.random() * 30) + 5,\r\n });\r\n }\r\n\r\n return data;\r\n}\r\n\r\n/**\r\n * Agrupa dados por período (dia, semana, mês)\r\n *\r\n * @param data - Array de dados para agrupar\r\n * @param period - Período de agrupamento\r\n * @param dateField - Campo de data nos objetos\r\n * @returns Array de dados agrupados\r\n *\r\n * @example\r\n * ```ts\r\n * const grouped = groupDataByPeriod(data, 'week', 'date');\r\n * ```\r\n */\r\nexport function groupDataByPeriod<T extends Record<string, any>>(\r\n data: T[],\r\n // period: 'day' | 'week' | 'month' = 'day', // Pode ser usado futuramente para agrupamento\r\n // dateField: keyof T = 'date' as keyof T\r\n): T[] {\r\n // Implementação simplificada - pode ser expandida\r\n // Por enquanto, retorna os dados originais\r\n return data;\r\n}\r\n\r\n/**\r\n * Calcula médias móveis para suavizar dados\r\n *\r\n * @param data - Array de valores numéricos\r\n * @param window - Tamanho da janela de média móvel\r\n * @returns Array com médias móveis\r\n *\r\n * @example\r\n * ```ts\r\n * const smoothed = calculateMovingAverage([1, 2, 3, 4, 5], 3);\r\n * // [2, 3, 4] (médias de [1,2,3], [2,3,4], [3,4,5])\r\n * ```\r\n */\r\nexport function calculateMovingAverage(data: number[], window: number): number[] {\r\n const result: number[] = [];\r\n \r\n for (let i = window - 1; i < data.length; i++) {\r\n const sum = data.slice(i - window + 1, i + 1).reduce((a, b) => a + b, 0);\r\n result.push(sum / window);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Encontra valor máximo e mínimo em array de objetos\r\n *\r\n * @param data - Array de objetos\r\n * @param field - Campo para analisar\r\n * @returns Objeto com min e max\r\n *\r\n * @example\r\n * ```ts\r\n * const { min, max } = findMinMax(data, 'views');\r\n * ```\r\n */\r\nexport function findMinMax<T extends Record<string, any>>(\r\n data: T[],\r\n field: keyof T\r\n): { min: number; max: number } {\r\n const values = data.map(item => Number(item[field]) || 0);\r\n \r\n return {\r\n min: Math.min(...values),\r\n max: Math.max(...values)\r\n };\r\n}\r\n","/**\r\n * Helpers pt-BR\r\n *\r\n * Funções pré-configuradas para português brasileiro.\r\n * Facilitam o uso sem precisar passar locale em cada chamada.\r\n *\r\n * @module @rainersoft/utils/pt-br\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport {\r\n formatDate as formatDateBase,\r\n formatDateTime as formatDateTimeBase,\r\n formatRelativeDate as formatRelativeDateBase,\r\n} from './date';\r\n\r\nimport {\r\n formatCurrency as formatCurrencyBase,\r\n formatNumber as formatNumberBase,\r\n formatCompact as formatCompactBase,\r\n} from './number';\r\n\r\nimport {\r\n translateStatus as translateStatusBase,\r\n} from './status';\r\n\r\n// ============================================================================\r\n// DATE - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata data em português (Brasil)\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long'\r\n): string {\r\n return formatDateBase(date, format, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data e hora em português (Brasil)\r\n */\r\nexport function formatDateTime(date: string | Date): string {\r\n return formatDateTimeBase(date, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data relativa em português (Brasil)\r\n */\r\nexport function formatRelativeDate(date: string | Date): string {\r\n return formatRelativeDateBase(date, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// NUMBER - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata moeda em Real (BRL)\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n return formatCurrencyBase(value, 'pt-BR', options);\r\n}\r\n\r\n/**\r\n * Formata número em português (Brasil)\r\n */\r\nexport function formatNumber(value: number, decimals = 0): string {\r\n return formatNumberBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata número compacto em português (Brasil)\r\n */\r\nexport function formatCompact(value: number, decimals = 1): string {\r\n return formatCompactBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// STATUS - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Traduz status para português (Brasil)\r\n */\r\nexport function translateStatus(status: string): string {\r\n return translateStatusBase(status, 'pt-BR');\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/text/index.ts","../src/string/index.ts","../src/date/index.ts","../src/number/index.ts","../src/status/index.ts","../src/validation/index.ts","../src/dom/index.ts","../src/stats/index.ts","../src/pt-br.ts"],"names":["formatNumber","window","formatCompact","formatCurrency","formatDate","formatDateTime","formatRelativeDate","translateStatus"],"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 * Text Utilities\r\n *\r\n * Utilitários universais para manipulação de texto e strings.\r\n *\r\n * @module @rainersoft/utils/text\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n// ============================================================================\r\n// AVATAR UTILITIES\r\n// ============================================================================\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxChars - Número máximo de caracteres (padrão: 2)\r\n * @returns Iniciais do nome em maiúsculas\r\n *\r\n * @example\r\n * ```ts\r\n * extractInitials('John Doe') // 'JD'\r\n * extractInitials('Maria Silva Santos') // 'MS'\r\n * extractInitials('Apple') // 'A'\r\n * extractInitials('', 3) // ''\r\n * ```\r\n */\r\nexport function extractInitials(name: string | null | undefined, maxChars = 2): string {\r\n if (!name || !name.trim()) {\r\n return '';\r\n }\r\n\r\n const words = name.trim().split(/\\s+/);\r\n const initials = words\r\n .slice(0, maxChars)\r\n .map(word => word.charAt(0).toUpperCase())\r\n .join('');\r\n\r\n return initials;\r\n}\r\n\r\n/**\r\n * Gera URL do avatar com base no nome\r\n *\r\n * @param name - Nome para gerar avatar\r\n * @param size - Tamanho do avatar (default: 200)\r\n * @param backgroundColor - Cor de fundo (default: cyan)\r\n * @param textColor - Cor do texto (default: white)\r\n * @returns URL do avatar\r\n *\r\n * @example\r\n * ```ts\r\n * generateAvatarUrl('John Doe') // URL do avatar\r\n * generateAvatarUrl('John Doe', 100, 'f97316', 'fff') // URL com cor laranja\r\n * ```\r\n */\r\nexport function generateAvatarUrl(\r\n name: string,\r\n size: number = 200,\r\n backgroundColor: string = '0891b2',\r\n textColor: string = 'fff'\r\n): string {\r\n const encodedName = encodeURIComponent(name);\r\n \r\n return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;\r\n}\r\n\r\n/**\r\n * Valida se uma URL de avatar é válida\r\n *\r\n * @param url - URL do avatar\r\n * @returns true se a URL for válida\r\n *\r\n * @example\r\n * ```ts\r\n * isValidAvatarUrl('https://example.com/avatar.jpg') // true\r\n * isValidAvatarUrl('invalid-url') // false\r\n * ```\r\n */\r\nexport function isValidAvatarUrl(url: string): boolean {\r\n if (!url || typeof url !== 'string') {\r\n return false;\r\n }\r\n\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Obtém a cor do avatar baseada no hash do nome\r\n *\r\n * @param name - Nome para gerar cor\r\n * @returns Cor em formato hexadecimal\r\n *\r\n * @example\r\n * ```ts\r\n * getAvatarColorFromName('John Doe') // '#0891b2' (ou outra cor)\r\n * getAvatarColorFromName('') // '#0891b2' (cor padrão)\r\n * ```\r\n */\r\nexport function getAvatarColorFromName(name: string): string {\r\n if (!name || typeof name !== 'string') {\r\n return '#0891b2'; // cyan-600 como padrão\r\n }\r\n\r\n // Gera hash simples do nome\r\n let hash = 0;\r\n for (let i = 0; i < name.length; i++) {\r\n hash = name.charCodeAt(i) + ((hash << 5) - hash);\r\n }\r\n\r\n // Cores baseadas em design tokens (compatível com @rainersoft/design-tokens)\r\n const colors = [\r\n '#0891b2', // cyan-600\r\n '#9333ea', // purple-600\r\n '#db2777', // pink-600\r\n '#059669', // emerald-600\r\n '#2563eb', // blue-600\r\n '#f97316', // orange-500\r\n '#dc2626', // red-600\r\n '#7c3aed', // violet-600\r\n ];\r\n\r\n const index = Math.abs(hash) % colors.length;\r\n return colors[index];\r\n}\r\n\r\n/**\r\n * Gera avatar com cor baseada no nome\r\n *\r\n * @param name - Nome para gerar avatar\r\n * @param size - Tamanho do avatar\r\n * @returns URL do avatar com cor automática\r\n *\r\n * @example\r\n * ```ts\r\n * generateDynamicAvatarUrl('John Doe') // URL com cor baseada no nome\r\n * generateDynamicAvatarUrl('Jane Smith', 150) // URL com tamanho 150\r\n * ```\r\n */\r\nexport function generateDynamicAvatarUrl(name: string, size: number = 200): string {\r\n const color = getAvatarColorFromName(name);\r\n const colorHex = color.replace('#', '');\r\n return generateAvatarUrl(name, size, colorHex, 'fff');\r\n}\r\n\r\n// ============================================================================\r\n// TEXT UTILITIES\r\n// ============================================================================\r\n\r\n/**\r\n * Gera ID único baseado em texto\r\n *\r\n * @param text - Texto base para o ID\r\n * @param prefix - Prefixo opcional\r\n * @param suffix - Sufixo opcional\r\n * @returns ID único em formato slug\r\n *\r\n * @example\r\n * ```ts\r\n * generateUniqueId('Hello World') // 'hello-world'\r\n * generateUniqueId('Hello World', 'section') // 'section-hello-world'\r\n * generateUniqueId('Olá! Como vai?', '', '123') // 'ola-como-vai-123'\r\n * ```\r\n */\r\nexport function generateUniqueId(\r\n text: string,\r\n prefix = '',\r\n suffix = ''\r\n): string {\r\n const slug = text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '') // Remove acentos\r\n .replace(/[^\\w\\s-]/g, '') // Remove caracteres especiais\r\n .replace(/\\s+/g, '-') // Substitui espaços por hífens\r\n .replace(/-+/g, '-') // Remove hífens duplicados\r\n .trim()\r\n .substring(0, 50); // Limita tamanho\r\n\r\n const parts = [prefix, slug, suffix].filter(Boolean);\r\n return parts.join('-');\r\n}\r\n\r\n/**\r\n * Trunca texto com elipse\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo para adicionar (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * ```ts\r\n * truncateText('Hello World', 5) // 'Hello...'\r\n * truncateText('Hello World', 8, '...') // 'Hello...'\r\n * truncateText('Short', 10) // 'Short'\r\n * ```\r\n */\r\nexport function truncateText(\r\n text: string,\r\n maxLength: number,\r\n suffix = '...'\r\n): string {\r\n if (!text || text.length <= maxLength) {\r\n return text || '';\r\n }\r\n\r\n return text.substring(0, maxLength - suffix.length) + suffix;\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 * @param options - Opções de capitalização\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * ```ts\r\n * capitalize('hello world') // 'Hello World'\r\n * capitalize('hello world', { firstWordOnly: true }) // 'Hello world'\r\n * capitalize('HELLO WORLD', { lowerRest: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function capitalize(\r\n text: string,\r\n options: { firstWordOnly?: boolean; lowerRest?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { firstWordOnly = false, lowerRest = false } = options;\r\n\r\n if (firstWordOnly) {\r\n return text.charAt(0).toUpperCase() + \r\n (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));\r\n }\r\n\r\n if (lowerRest) {\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase()).toLowerCase();\r\n }\r\n\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Remove caracteres especiais mantendo apenas alfanuméricos e espaços\r\n *\r\n * @param text - Texto para limpar\r\n * @param allowSpaces - Se deve permitir espaços\r\n * @returns Texto limpo\r\n *\r\n * @example\r\n * ```ts\r\n * cleanText('Olá! Como vai?') // 'Ola Como vai'\r\n * cleanText('Olá! Como vai?', false) // 'OlaComoVai'\r\n * ```\r\n */\r\nexport function cleanText(text: string, allowSpaces = true): string {\r\n if (!text) return '';\r\n\r\n const pattern = allowSpaces ? /[^\\w\\s]/g : /[^\\w]/g;\r\n return text.replace(pattern, '');\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\n * @example\r\n * ```ts\r\n * countWords('Hello world') // 2\r\n * countWords(' Hello world ') // 2\r\n * countWords('') // 0\r\n * ```\r\n */\r\nexport function countWords(text: string): number {\r\n if (!text || !text.trim()) {\r\n return 0;\r\n }\r\n\r\n return text.trim().split(/\\s+/).length;\r\n}\r\n\r\n/**\r\n * Verifica se texto está vazio ou contém apenas espaços\r\n *\r\n * @param text - Texto para verificar\r\n * @returns True se estiver vazio\r\n *\r\n * @example\r\n * ```ts\r\n * isEmpty('') // true\r\n * isEmpty(' ') // true\r\n * isEmpty('Hello') // false\r\n * ```\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || !text.trim();\r\n}\r\n\r\n/**\r\n * Remove espaços em branco extras\r\n *\r\n * @param text - Texto para limpar\r\n * @param options - Opções de limpeza\r\n * @returns Texto sem espaços extras\r\n *\r\n * @example\r\n * ```ts\r\n * normalizeSpaces(' Hello World ') // 'Hello World'\r\n * normalizeSpaces('Hello\\nWorld', { newlines: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function normalizeSpaces(\r\n text: string,\r\n options: { newlines?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { newlines = false } = options;\r\n \r\n let cleaned = text;\r\n \r\n if (newlines) {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n } else {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n }\r\n \r\n return cleaned.trim();\r\n}\r\n","/**\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","/**\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","/**\r\n * Number Utilities\r\n *\r\n * Utilitários para formatação de números, moedas e percentuais.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/number\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport type { Locale } from '../types';\r\nimport { DEFAULT_LOCALE, CURRENCY_MAP } from '../types';\r\n\r\n/**\r\n * Formata número como moeda com suporte a idiomas\r\n *\r\n * @param value - Valor numérico\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @param options - Opções de formatação\r\n * @returns Valor formatado\r\n *\r\n * @example\r\n * formatCurrency(1234.56) // 'R$ 1.234,56' (pt-BR)\r\n * formatCurrency(1234.56, 'en-US') // '$1,234.56'\r\n * formatCurrency(1234.56, 'es-ES') // '1.234,56 €'\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n locale: Locale = DEFAULT_LOCALE,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n const currency = CURRENCY_MAP[locale];\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n ...options,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número como percentual\r\n *\r\n * @param value - Valor entre 0 e 1 (ou 0 e 100 se usePercentage=true)\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param usePercentage - Se true, espera valor 0-100 (padrão: false)\r\n * @returns Percentual formatado\r\n *\r\n * @example\r\n * formatPercent(0.1234) // '12%'\r\n * formatPercent(0.1234, 2) // '12,34%'\r\n * formatPercent(12.34, 2, true) // '12,34%'\r\n */\r\nexport function formatPercent(\r\n value: number,\r\n decimals = 0,\r\n usePercentage = false\r\n): string {\r\n return new Intl.NumberFormat('pt-BR', {\r\n style: 'percent',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(usePercentage ? value / 100 : value);\r\n}\r\n\r\n/**\r\n * Formata número com separadores de milhar\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número formatado\r\n *\r\n * @example\r\n * formatNumber(1234567) // '1.234.567' (pt-BR)\r\n * formatNumber(1234567, 0, 'en-US') // '1,234,567'\r\n */\r\nexport function formatNumber(value: number, decimals = 0, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número de forma compacta (1K, 1M, 1B)\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 1)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número compacto\r\n *\r\n * @example\r\n * formatCompact(1234) // '1,2 mil' (pt-BR)\r\n * formatCompact(1234567, 1, 'en-US') // '1.2M'\r\n */\r\nexport function formatCompact(value: number, decimals = 1, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n notation: 'compact',\r\n compactDisplay: 'short',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Converte string de moeda para número\r\n *\r\n * @param currency - String de moeda (ex: 'R$ 1.234,56')\r\n * @returns Valor numérico\r\n *\r\n * @example\r\n * parseCurrency('R$ 1.234,56') // 1234.56\r\n * parseCurrency('1.234,56') // 1234.56\r\n */\r\nexport function parseCurrency(currency: string): number {\r\n const cleaned = currency\r\n .replace(/[R$\\s]/g, '')\r\n .replace(/\\./g, '')\r\n .replace(',', '.');\r\n return parseFloat(cleaned);\r\n}\r\n\r\n/**\r\n * Arredonda número para casas decimais\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais\r\n * @returns Valor arredondado\r\n *\r\n * @example\r\n * round(1.2345, 2) // 1.23\r\n */\r\nexport function round(value: number, decimals = 2): number {\r\n const factor = Math.pow(10, decimals);\r\n return Math.round(value * factor) / factor;\r\n}\r\n\r\n/**\r\n * Clamp - limita número entre min e max\r\n *\r\n * @param value - Valor\r\n * @param min - Mínimo\r\n * @param max - Máximo\r\n * @returns Valor limitado\r\n *\r\n * @example\r\n * clamp(150, 0, 100) // 100\r\n * clamp(-10, 0, 100) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n return Math.min(Math.max(value, min), max);\r\n}\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","/**\r\n * Validation Utilities\r\n *\r\n * Utilitários para validação de dados com suporte a múltiplos idiomas.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/validation\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 * Interface para resultado de validação\r\n */\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors?: string[];\r\n}\r\n\r\n/**\r\n * Valida email usando regex RFC 5322\r\n *\r\n * @param email - Email para validar\r\n * @param locale - Idioma das mensagens de erro (padrão: 'pt-BR')\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateEmail('user@example.com') // { isValid: true }\r\n * validateEmail('invalid-email') // { isValid: false, errors: ['Email inválido'] }\r\n */\r\nexport function validateEmail(email: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n const isValid = emailRegex.test(email);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Email inválido'],\r\n 'en-US': ['Invalid email'],\r\n 'es-ES': ['Email inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida senha com critérios de segurança\r\n *\r\n * @param password - Senha para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePassword('MySecure123!') // { isValid: true }\r\n * validatePassword('123') // { isValid: false, errors: ['Senha deve ter pelo menos 8 caracteres'] }\r\n */\r\nexport function validatePassword(\r\n password: string, \r\n options: {\r\n minLength?: number;\r\n requireUppercase?: boolean;\r\n requireLowercase?: boolean;\r\n requireNumbers?: boolean;\r\n requireSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 8,\r\n requireUppercase = true,\r\n requireLowercase = true,\r\n requireNumbers = true,\r\n requireSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Senha deve ter pelo menos ${minLength} caracteres`,\r\n uppercase: 'Senha deve conter pelo menos uma letra maiúscula',\r\n lowercase: 'Senha deve conter pelo menos uma letra minúscula',\r\n numbers: 'Senha deve conter pelo menos um número',\r\n specialChars: 'Senha deve conter pelo menos um caractere especial'\r\n },\r\n 'en-US': {\r\n minLength: `Password must be at least ${minLength} characters`,\r\n uppercase: 'Password must contain at least one uppercase letter',\r\n lowercase: 'Password must contain at least one lowercase letter',\r\n numbers: 'Password must contain at least one number',\r\n specialChars: 'Password must contain at least one special character'\r\n },\r\n 'es-ES': {\r\n minLength: `La contraseña debe tener al menos ${minLength} caracteres`,\r\n uppercase: 'La contraseña debe contener al menos una letra mayúscula',\r\n lowercase: 'La contraseña debe contener al menos una letra minúscula',\r\n numbers: 'La contraseña debe contener al menos un número',\r\n specialChars: 'La contraseña debe contener al menos un carácter especial'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (password.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (requireUppercase && !/[A-Z]/.test(password)) {\r\n errors.push(messages.uppercase);\r\n }\r\n \r\n if (requireLowercase && !/[a-z]/.test(password)) {\r\n errors.push(messages.lowercase);\r\n }\r\n \r\n if (requireNumbers && !/\\d/.test(password)) {\r\n errors.push(messages.numbers);\r\n }\r\n \r\n if (requireSpecialChars && !/[!@#$%^&*(),.?\":{}|<>]/.test(password)) {\r\n errors.push(messages.specialChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida URL\r\n *\r\n * @param url - URL para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUrl('https://example.com') // { isValid: true }\r\n * validateUrl('not-a-url') // { isValid: false, errors: ['URL inválida'] }\r\n */\r\nexport function validateUrl(url: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n try {\r\n new URL(url);\r\n return { isValid: true };\r\n } catch {\r\n const errors = {\r\n 'pt-BR': ['URL inválida'],\r\n 'en-US': ['Invalid URL'],\r\n 'es-ES': ['URL inválida']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Valida telefone (formato brasileiro por padrão)\r\n *\r\n * @param phone - Telefone para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePhone('(11) 98765-4321') // { isValid: true }\r\n * validatePhone('123') // { isValid: false, errors: ['Telefone inválido'] }\r\n */\r\nexport function validatePhone(phone: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n // Regex para telefone brasileiro: (XX) XXXXX-XXXX ou (XX) XXXX-XXXX\r\n const phoneRegex = /^\\(?\\d{2}\\)?[\\s-]?\\d{4,5}[-]?\\d{4}$/;\r\n const isValid = phoneRegex.test(phone);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Telefone inválido'],\r\n 'en-US': ['Invalid phone number'],\r\n 'es-ES': ['Teléfono inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida username para registro\r\n *\r\n * @param username - Username para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUsername('user123') // { isValid: true }\r\n * validateUsername('us') // { isValid: false, errors: ['Username muito curto'] }\r\n */\r\nexport function validateUsername(\r\n username: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n allowSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 20,\r\n allowSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Username muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muito longo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contém caracteres inválidos'\r\n },\r\n 'en-US': {\r\n minLength: `Username too short (minimum ${minLength} characters)`,\r\n maxLength: `Username too long (maximum ${maxLength} characters)`,\r\n invalidChars: 'Username contains invalid characters'\r\n },\r\n 'es-ES': {\r\n minLength: `Username muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muy largo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contiene caracteres inválidos'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (username.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (username.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const usernameRegex = allowSpecialChars \r\n ? /^[a-zA-Z0-9_]{3,20}$/\r\n : /^[a-zA-Z0-9_]{3,20}$/;\r\n \r\n if (!usernameRegex.test(username)) {\r\n errors.push(messages.invalidChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida slug para URLs amigáveis\r\n *\r\n * @param slug - Slug para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateSlug('my-post-title') // { isValid: true }\r\n * validateSlug('My Post Title') // { isValid: false, errors: ['Slug inválido'] }\r\n */\r\nexport function validateSlug(\r\n slug: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 100\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Slug muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muito longo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use apenas letras minúsculas, números e hífens'\r\n },\r\n 'en-US': {\r\n minLength: `Slug too short (minimum ${minLength} characters)`,\r\n maxLength: `Slug too long (maximum ${maxLength} characters)`,\r\n invalidFormat: 'Invalid slug - use only lowercase letters, numbers and hyphens'\r\n },\r\n 'es-ES': {\r\n minLength: `Slug muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muy largo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use solo letras minúsculas, números y guiones'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (slug.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (slug.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n if (!slugRegex.test(slug)) {\r\n errors.push(messages.invalidFormat);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida texto com comprimento mínimo e máximo\r\n *\r\n * @param text - Texto para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateText('Hello', { minLength: 3 }) // { isValid: true }\r\n * validateText('Hi', { minLength: 3 }) // { isValid: false, errors: ['Texto muito curto'] }\r\n */\r\nexport function validateText(\r\n text: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n fieldName?: string;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 0,\r\n maxLength = Infinity,\r\n fieldName = 'Texto'\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `${fieldName} muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muito longo (máximo ${maxLength} caracteres)`\r\n },\r\n 'en-US': {\r\n minLength: `${fieldName} too short (minimum ${minLength} characters)`,\r\n maxLength: `${fieldName} too long (maximum ${maxLength} characters)`\r\n },\r\n 'es-ES': {\r\n minLength: `${fieldName} muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muy largo (máximo ${maxLength} caracteres)`\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (text.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (text.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n","/**\r\n * DOM Utilities\r\n *\r\n * Utilitários para manipulação do DOM e interações com o browser.\r\n * Funciona em qualquer ambiente browser moderno.\r\n *\r\n * @module @rainersoft/utils/dom\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Verifica se usuário prefere movimento reduzido (accessibility)\r\n *\r\n * @returns true se preferir movimento reduzido\r\n *\r\n * @example\r\n * if (prefersReducedMotion()) {\r\n * // Desabilitar animações\r\n * }\r\n */\r\nexport function prefersReducedMotion(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças na preferência de movimento\r\n *\r\n * @param callback - Função chamada quando a preferência muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onReducedMotionChange((prefersReduced) => {\r\n * console.log('Motion preference changed:', prefersReduced);\r\n * });\r\n * \r\n * // Remover listener quando necessário\r\n * unsubscribe();\r\n */\r\nexport function onReducedMotionChange(\r\n callback: (prefersReduced: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener (compatibilidade com browsers antigos)\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Rola a página para uma posição específica\r\n *\r\n * @param x - Posição horizontal (padrão: 0)\r\n * @param y - Posição vertical (padrão: 0)\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToPosition(0, 500); // Rola para o topo com 500px de margem\r\n * scrollToPosition(0, 0, { smooth: true }); // Scroll suave para o topo\r\n */\r\nexport function scrollToPosition(\r\n x: number = 0,\r\n y: number = 0,\r\n options: {\r\n smooth?: boolean;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, behavior } = options;\r\n \r\n window.scrollTo({\r\n left: x,\r\n top: y,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Rola a página para o topo\r\n *\r\n * @param smooth - Se deve usar scroll suave (padrão: false)\r\n *\r\n * @example\r\n * scrollToTop(); // Scroll instantâneo para o topo\r\n * scrollToTop(true); // Scroll suave para o topo\r\n */\r\nexport function scrollToTop(smooth: boolean = false): void {\r\n scrollToPosition(0, 0, { smooth });\r\n}\r\n\r\n/**\r\n * Rola suavemente para uma posição\r\n *\r\n * @param x - Posição horizontal\r\n * @param y - Posição vertical\r\n * @param duration - Duração da animação em ms (padrão: 300)\r\n *\r\n * @example\r\n * smoothScrollTo(0, 500, 500); // Animação de 500ms para rolar 500px\r\n */\r\nexport function smoothScrollTo(\r\n x: number,\r\n y: number,\r\n duration: number = 300\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const startX = window.scrollX;\r\n const startY = window.scrollY;\r\n const distanceX = x - startX;\r\n const distanceY = y - startY;\r\n const startTime = performance.now();\r\n \r\n function animate(currentTime: number): void {\r\n const elapsed = currentTime - startTime;\r\n const progress = Math.min(elapsed / duration, 1);\r\n \r\n // Easing function (ease-out)\r\n const easeProgress = 1 - Math.pow(1 - progress, 3);\r\n \r\n const currentX = startX + (distanceX * easeProgress);\r\n const currentY = startY + (distanceY * easeProgress);\r\n \r\n window.scrollTo(currentX, currentY);\r\n \r\n if (progress < 1) {\r\n requestAnimationFrame(animate);\r\n }\r\n }\r\n \r\n requestAnimationFrame(animate);\r\n}\r\n\r\n/**\r\n * Rola para um elemento específico\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToElement('#my-element'); // Scroll instantâneo\r\n * scrollToElement('.section', { smooth: true, offset: 100 }); // Scroll suave com offset\r\n */\r\nexport function scrollToElement(\r\n element: string | Element,\r\n options: {\r\n smooth?: boolean;\r\n offset?: number;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, offset = 0, behavior } = options;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const absoluteY = rect.top + window.scrollY - offset;\r\n \r\n window.scrollTo({\r\n left: 0,\r\n top: absoluteY,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Verifica se elemento está visível na viewport\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param threshold - Limiar de visibilidade (0 a 1, padrão: 0)\r\n * @returns true se elemento estiver visível\r\n *\r\n * @example\r\n * isElementVisible('#my-element'); // true se elemento estiver na viewport\r\n * isElementVisible('.section', 0.5); // true se 50% do elemento estiver visível\r\n */\r\nexport function isElementVisible(\r\n element: string | Element,\r\n threshold: number = 0\r\n): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return false;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const windowHeight = window.innerHeight;\r\n const windowWidth = window.innerWidth;\r\n \r\n const verticalThreshold = windowHeight * threshold;\r\n const horizontalThreshold = windowWidth * threshold;\r\n \r\n const isVisibleVertically = \r\n rect.bottom >= verticalThreshold && \r\n rect.top <= windowHeight - verticalThreshold;\r\n \r\n const isVisibleHorizontally = \r\n rect.right >= horizontalThreshold && \r\n rect.left <= windowWidth - horizontalThreshold;\r\n \r\n return isVisibleVertically && isVisibleHorizontally;\r\n}\r\n\r\n/**\r\n * Obtém a posição de um elemento em relação ao documento\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @returns Posição { x, y } ou null se elemento não for encontrado\r\n *\r\n * @example\r\n * const position = getElementPosition('#my-element');\r\n * console.log('X:', position.x, 'Y:', position.y);\r\n */\r\nexport function getElementPosition(\r\n element: string | Element\r\n): { x: number; y: number } | null {\r\n if (typeof window === 'undefined') return null;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return null;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n \r\n return {\r\n x: rect.left + window.scrollX,\r\n y: rect.top + window.scrollY\r\n };\r\n}\r\n\r\n/**\r\n * Verifica se está em dispositivo móvel\r\n *\r\n * @returns true se for dispositivo móvel\r\n *\r\n * @example\r\n * if (isMobile()) {\r\n * // Aplicar layout mobile\r\n * }\r\n */\r\nexport function isMobile(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n // Verificar User Agent\r\n const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\r\n navigator.userAgent\r\n );\r\n \r\n // Verificar tamanho de tela (fallback)\r\n const isMobileScreen = window.innerWidth <= 768;\r\n \r\n return isMobileUA || isMobileScreen;\r\n}\r\n\r\n/**\r\n * Verifica se está em modo escuro\r\n *\r\n * @returns true se o sistema preferir modo escuro\r\n *\r\n * @example\r\n * if (isDarkMode()) {\r\n * // Aplicar tema escuro\r\n * }\r\n */\r\nexport function isDarkMode(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças no tema do sistema\r\n *\r\n * @param callback - Função chamada quando o tema muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onDarkModeChange((isDark) => {\r\n * console.log('Theme changed:', isDark ? 'dark' : 'light');\r\n * });\r\n */\r\nexport function onDarkModeChange(\r\n callback: (isDark: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Copia texto para a área de transferência\r\n *\r\n * @param text - Texto para copiar\r\n * @returns Promise que resolve para true se sucesso\r\n *\r\n * @example\r\n * copyToClipboard('Hello World').then(success => {\r\n * if (success) {\r\n * console.log('Texto copiado!');\r\n * }\r\n * });\r\n */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof window === 'undefined') return false;\r\n \r\n try {\r\n // Tentar usar a API moderna\r\n if (navigator.clipboard && window.isSecureContext) {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n }\r\n \r\n // Fallback para browsers mais antigos\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-999999px';\r\n textArea.style.top = '-999999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n \r\n const result = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n \r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Baixa um arquivo como blob\r\n *\r\n * @param blob - Blob para baixar\r\n * @param filename - Nome do arquivo\r\n *\r\n * @example\r\n * downloadFile(new Blob(['Hello World'], { type: 'text/plain' }), 'hello.txt');\r\n */\r\nexport function downloadFile(blob: Blob, filename: string): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = filename;\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n","/**\r\n * Stats Formatting Utilities\r\n *\r\n * Utilitários universais para formatação de estatísticas e números.\r\n *\r\n * @module @rainersoft/utils/stats\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Formata número grande com abreviação (1.5k, 2.3M, etc)\r\n *\r\n * @param num - Número para formatar\r\n * @returns String formatada com abreviação\r\n *\r\n * @example\r\n * ```ts\r\n * formatNumber(1500) // '1.5k'\r\n * formatNumber(2500000) // '2.5M'\r\n * formatNumber(999) // '999'\r\n * ```\r\n */\r\nexport function formatNumber(num: number): string {\r\n if (num >= 1000000) {\r\n return (num / 1000000).toFixed(1) + 'M';\r\n }\r\n if (num >= 1000) {\r\n return (num / 1000).toFixed(1) + 'k';\r\n }\r\n return num.toString();\r\n}\r\n\r\n/**\r\n * Calcula percentual de mudança entre dois valores\r\n *\r\n * @param current - Valor atual\r\n * @param previous - Valor anterior\r\n * @returns Percentual de mudança (arredondado)\r\n *\r\n * @example\r\n * ```ts\r\n * calculateChange(150, 100) // 50\r\n * calculateChange(80, 100) // -20\r\n * calculateChange(100, 0) // 100\r\n * ```\r\n */\r\nexport function calculateChange(current: number, previous: number): number {\r\n if (previous === 0) return 100;\r\n return Math.round(((current - previous) / previous) * 100);\r\n}\r\n\r\n/**\r\n * Formata percentual com sinal\r\n *\r\n * @param value - Valor do percentual\r\n * @param options - Opções de formatação\r\n * @returns String formatada com sinal e símbolo\r\n *\r\n * @example\r\n * ```ts\r\n * formatPercentage(25) // '+25%'\r\n * formatPercentage(-10) // '-10%'\r\n * formatPercentage(0) // '0%'\r\n * ```\r\n */\r\nexport function formatPercentage(\r\n value: number,\r\n options: { showSign?: boolean; decimals?: number } = {}\r\n): string {\r\n const { showSign = true, decimals = 0 } = options;\r\n \r\n const sign = showSign && value > 0 ? '+' : '';\r\n const formattedValue = value.toFixed(decimals);\r\n \r\n return `${sign}${formattedValue}%`;\r\n}\r\n\r\n/**\r\n * Gera dados de exemplo para gráficos\r\n *\r\n * @param days - Número de dias para gerar dados\r\n * @param locale - Idioma para formatação de datas\r\n * @returns Array de dados mock\r\n *\r\n * @example\r\n * ```ts\r\n * const data = generateMockChartData(7);\r\n * // [\r\n * // { date: '01/12', views: 1234, uniqueViews: 890, likes: 67, comments: 23 },\r\n * // ...\r\n * // ]\r\n * ```\r\n */\r\nexport function generateMockChartData(\r\n days: number,\r\n locale: string = 'pt-BR'\r\n): Array<Record<string, any>> {\r\n const data = [];\r\n const now = new Date();\r\n\r\n for (let i = days - 1; i >= 0; i--) {\r\n const date = new Date(now);\r\n date.setDate(date.getDate() - i);\r\n\r\n data.push({\r\n date: date.toLocaleDateString(locale, {\r\n day: '2-digit',\r\n month: '2-digit',\r\n }),\r\n views: Math.floor(Math.random() * 1000) + 500,\r\n uniqueViews: Math.floor(Math.random() * 700) + 300,\r\n likes: Math.floor(Math.random() * 100) + 50,\r\n comments: Math.floor(Math.random() * 50) + 10,\r\n shares: Math.floor(Math.random() * 30) + 5,\r\n });\r\n }\r\n\r\n return data;\r\n}\r\n\r\n/**\r\n * Agrupa dados por período (dia, semana, mês)\r\n *\r\n * @param data - Array de dados para agrupar\r\n * @param period - Período de agrupamento\r\n * @param dateField - Campo de data nos objetos\r\n * @returns Array de dados agrupados\r\n *\r\n * @example\r\n * ```ts\r\n * const grouped = groupDataByPeriod(data, 'week', 'date');\r\n * ```\r\n */\r\nexport function groupDataByPeriod<T extends Record<string, any>>(\r\n data: T[],\r\n // period: 'day' | 'week' | 'month' = 'day', // Pode ser usado futuramente para agrupamento\r\n // dateField: keyof T = 'date' as keyof T\r\n): T[] {\r\n // Implementação simplificada - pode ser expandida\r\n // Por enquanto, retorna os dados originais\r\n return data;\r\n}\r\n\r\n/**\r\n * Calcula médias móveis para suavizar dados\r\n *\r\n * @param data - Array de valores numéricos\r\n * @param window - Tamanho da janela de média móvel\r\n * @returns Array com médias móveis\r\n *\r\n * @example\r\n * ```ts\r\n * const smoothed = calculateMovingAverage([1, 2, 3, 4, 5], 3);\r\n * // [2, 3, 4] (médias de [1,2,3], [2,3,4], [3,4,5])\r\n * ```\r\n */\r\nexport function calculateMovingAverage(data: number[], window: number): number[] {\r\n const result: number[] = [];\r\n \r\n for (let i = window - 1; i < data.length; i++) {\r\n const sum = data.slice(i - window + 1, i + 1).reduce((a, b) => a + b, 0);\r\n result.push(sum / window);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Encontra valor máximo e mínimo em array de objetos\r\n *\r\n * @param data - Array de objetos\r\n * @param field - Campo para analisar\r\n * @returns Objeto com min e max\r\n *\r\n * @example\r\n * ```ts\r\n * const { min, max } = findMinMax(data, 'views');\r\n * ```\r\n */\r\nexport function findMinMax<T extends Record<string, any>>(\r\n data: T[],\r\n field: keyof T\r\n): { min: number; max: number } {\r\n const values = data.map(item => Number(item[field]) || 0);\r\n \r\n return {\r\n min: Math.min(...values),\r\n max: Math.max(...values)\r\n };\r\n}\r\n","/**\r\n * Helpers pt-BR\r\n *\r\n * Funções pré-configuradas para português brasileiro.\r\n * Facilitam o uso sem precisar passar locale em cada chamada.\r\n *\r\n * @module @rainersoft/utils/pt-br\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport {\r\n formatDate as formatDateBase,\r\n formatDateTime as formatDateTimeBase,\r\n formatRelativeDate as formatRelativeDateBase,\r\n} from './date';\r\n\r\nimport {\r\n formatCurrency as formatCurrencyBase,\r\n formatNumber as formatNumberBase,\r\n formatCompact as formatCompactBase,\r\n} from './number';\r\n\r\nimport {\r\n translateStatus as translateStatusBase,\r\n} from './status';\r\n\r\n// ============================================================================\r\n// DATE - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata data em português (Brasil)\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long'\r\n): string {\r\n return formatDateBase(date, format, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data e hora em português (Brasil)\r\n */\r\nexport function formatDateTime(date: string | Date): string {\r\n return formatDateTimeBase(date, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data relativa em português (Brasil)\r\n */\r\nexport function formatRelativeDate(date: string | Date): string {\r\n return formatRelativeDateBase(date, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// NUMBER - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata moeda em Real (BRL)\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n return formatCurrencyBase(value, 'pt-BR', options);\r\n}\r\n\r\n/**\r\n * Formata número em português (Brasil)\r\n */\r\nexport function formatNumber(value: number, decimals = 0): string {\r\n return formatNumberBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata número compacto em português (Brasil)\r\n */\r\nexport function formatCompact(value: number, decimals = 1): string {\r\n return formatCompactBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// STATUS - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Traduz status para português (Brasil)\r\n */\r\nexport function translateStatus(status: string): string {\r\n return translateStatusBase(status, 'pt-BR');\r\n}\r\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,55 @@ function extractInitials(name, maxChars = 2) {
|
|
|
21
21
|
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
22
22
|
return initials;
|
|
23
23
|
}
|
|
24
|
+
function generateAvatarUrl(name, size = 200, backgroundColor = "0891b2", textColor = "fff") {
|
|
25
|
+
const encodedName = encodeURIComponent(name);
|
|
26
|
+
return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;
|
|
27
|
+
}
|
|
28
|
+
function isValidAvatarUrl(url) {
|
|
29
|
+
if (!url || typeof url !== "string") {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
new URL(url);
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getAvatarColorFromName(name) {
|
|
40
|
+
if (!name || typeof name !== "string") {
|
|
41
|
+
return "#0891b2";
|
|
42
|
+
}
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (let i = 0; i < name.length; i++) {
|
|
45
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
46
|
+
}
|
|
47
|
+
const colors = [
|
|
48
|
+
"#0891b2",
|
|
49
|
+
// cyan-600
|
|
50
|
+
"#9333ea",
|
|
51
|
+
// purple-600
|
|
52
|
+
"#db2777",
|
|
53
|
+
// pink-600
|
|
54
|
+
"#059669",
|
|
55
|
+
// emerald-600
|
|
56
|
+
"#2563eb",
|
|
57
|
+
// blue-600
|
|
58
|
+
"#f97316",
|
|
59
|
+
// orange-500
|
|
60
|
+
"#dc2626",
|
|
61
|
+
// red-600
|
|
62
|
+
"#7c3aed"
|
|
63
|
+
// violet-600
|
|
64
|
+
];
|
|
65
|
+
const index = Math.abs(hash) % colors.length;
|
|
66
|
+
return colors[index];
|
|
67
|
+
}
|
|
68
|
+
function generateDynamicAvatarUrl(name, size = 200) {
|
|
69
|
+
const color = getAvatarColorFromName(name);
|
|
70
|
+
const colorHex = color.replace("#", "");
|
|
71
|
+
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
72
|
+
}
|
|
24
73
|
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
25
74
|
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
26
75
|
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
@@ -792,6 +841,6 @@ function translateStatus2(status) {
|
|
|
792
841
|
return translateStatus(status, "pt-BR");
|
|
793
842
|
}
|
|
794
843
|
|
|
795
|
-
export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime, formatNumber2 as formatNumber, formatPercentage, formatRelativeDate, generateMockChartData, generateUniqueId, getElementPosition, getStatusColor, getStatusVariant, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidDate, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, textToSlug, toISOString, translateStatus, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
|
|
844
|
+
export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime, formatNumber2 as formatNumber, formatPercentage, formatRelativeDate, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, getStatusColor, getStatusVariant, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, isValidDate, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, textToSlug, toISOString, translateStatus, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
|
|
796
845
|
//# sourceMappingURL=index.mjs.map
|
|
797
846
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/text/index.ts","../src/string/index.ts","../src/date/index.ts","../src/number/index.ts","../src/status/index.ts","../src/validation/index.ts","../src/dom/index.ts","../src/stats/index.ts","../src/pt-br.ts"],"names":["formatNumber","window","formatCompact","formatCurrency","formatDate","formatDateTime","formatRelativeDate","translateStatus"],"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 * Text Utilities\r\n *\r\n * Utilitários universais para manipulação de texto e strings.\r\n *\r\n * @module @rainersoft/utils/text\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxChars - Número máximo de caracteres (padrão: 2)\r\n * @returns Iniciais do nome em maiúsculas\r\n *\r\n * @example\r\n * ```ts\r\n * extractInitials('John Doe') // 'JD'\r\n * extractInitials('Maria Silva Santos') // 'MS'\r\n * extractInitials('Apple') // 'A'\r\n * extractInitials('', 3) // ''\r\n * ```\r\n */\r\nexport function extractInitials(name: string | null | undefined, maxChars = 2): string {\r\n if (!name || !name.trim()) {\r\n return '';\r\n }\r\n\r\n const words = name.trim().split(/\\s+/);\r\n const initials = words\r\n .slice(0, maxChars)\r\n .map(word => word.charAt(0).toUpperCase())\r\n .join('');\r\n\r\n return initials;\r\n}\r\n\r\n/**\r\n * Gera ID único baseado em texto\r\n *\r\n * @param text - Texto base para o ID\r\n * @param prefix - Prefixo opcional\r\n * @param suffix - Sufixo opcional\r\n * @returns ID único em formato slug\r\n *\r\n * @example\r\n * ```ts\r\n * generateUniqueId('Hello World') // 'hello-world'\r\n * generateUniqueId('Hello World', 'section') // 'section-hello-world'\r\n * generateUniqueId('Olá! Como vai?', '', '123') // 'ola-como-vai-123'\r\n * ```\r\n */\r\nexport function generateUniqueId(\r\n text: string,\r\n prefix = '',\r\n suffix = ''\r\n): string {\r\n const slug = text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '') // Remove acentos\r\n .replace(/[^\\w\\s-]/g, '') // Remove caracteres especiais\r\n .replace(/\\s+/g, '-') // Substitui espaços por hífens\r\n .replace(/-+/g, '-') // Remove hífens duplicados\r\n .trim()\r\n .substring(0, 50); // Limita tamanho\r\n\r\n const parts = [prefix, slug, suffix].filter(Boolean);\r\n return parts.join('-');\r\n}\r\n\r\n/**\r\n * Trunca texto com elipse\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo para adicionar (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * ```ts\r\n * truncateText('Hello World', 5) // 'Hello...'\r\n * truncateText('Hello World', 8, '...') // 'Hello...'\r\n * truncateText('Short', 10) // 'Short'\r\n * ```\r\n */\r\nexport function truncateText(\r\n text: string,\r\n maxLength: number,\r\n suffix = '...'\r\n): string {\r\n if (!text || text.length <= maxLength) {\r\n return text || '';\r\n }\r\n\r\n return text.substring(0, maxLength - suffix.length) + suffix;\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 * @param options - Opções de capitalização\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * ```ts\r\n * capitalize('hello world') // 'Hello World'\r\n * capitalize('hello world', { firstWordOnly: true }) // 'Hello world'\r\n * capitalize('HELLO WORLD', { lowerRest: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function capitalize(\r\n text: string,\r\n options: { firstWordOnly?: boolean; lowerRest?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { firstWordOnly = false, lowerRest = false } = options;\r\n\r\n if (firstWordOnly) {\r\n return text.charAt(0).toUpperCase() + \r\n (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));\r\n }\r\n\r\n if (lowerRest) {\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase()).toLowerCase();\r\n }\r\n\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Remove caracteres especiais mantendo apenas alfanuméricos e espaços\r\n *\r\n * @param text - Texto para limpar\r\n * @param allowSpaces - Se deve permitir espaços\r\n * @returns Texto limpo\r\n *\r\n * @example\r\n * ```ts\r\n * cleanText('Olá! Como vai?') // 'Ola Como vai'\r\n * cleanText('Olá! Como vai?', false) // 'OlaComoVai'\r\n * ```\r\n */\r\nexport function cleanText(text: string, allowSpaces = true): string {\r\n if (!text) return '';\r\n\r\n const pattern = allowSpaces ? /[^\\w\\s]/g : /[^\\w]/g;\r\n return text.replace(pattern, '');\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\n * @example\r\n * ```ts\r\n * countWords('Hello world') // 2\r\n * countWords(' Hello world ') // 2\r\n * countWords('') // 0\r\n * ```\r\n */\r\nexport function countWords(text: string): number {\r\n if (!text || !text.trim()) {\r\n return 0;\r\n }\r\n\r\n return text.trim().split(/\\s+/).length;\r\n}\r\n\r\n/**\r\n * Verifica se texto está vazio ou contém apenas espaços\r\n *\r\n * @param text - Texto para verificar\r\n * @returns True se estiver vazio\r\n *\r\n * @example\r\n * ```ts\r\n * isEmpty('') // true\r\n * isEmpty(' ') // true\r\n * isEmpty('Hello') // false\r\n * ```\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || !text.trim();\r\n}\r\n\r\n/**\r\n * Remove espaços em branco extras\r\n *\r\n * @param text - Texto para limpar\r\n * @param options - Opções de limpeza\r\n * @returns Texto sem espaços extras\r\n *\r\n * @example\r\n * ```ts\r\n * normalizeSpaces(' Hello World ') // 'Hello World'\r\n * normalizeSpaces('Hello\\nWorld', { newlines: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function normalizeSpaces(\r\n text: string,\r\n options: { newlines?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { newlines = false } = options;\r\n \r\n let cleaned = text;\r\n \r\n if (newlines) {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n } else {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n }\r\n \r\n return cleaned.trim();\r\n}\r\n","/**\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","/**\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","/**\r\n * Number Utilities\r\n *\r\n * Utilitários para formatação de números, moedas e percentuais.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/number\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport type { Locale } from '../types';\r\nimport { DEFAULT_LOCALE, CURRENCY_MAP } from '../types';\r\n\r\n/**\r\n * Formata número como moeda com suporte a idiomas\r\n *\r\n * @param value - Valor numérico\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @param options - Opções de formatação\r\n * @returns Valor formatado\r\n *\r\n * @example\r\n * formatCurrency(1234.56) // 'R$ 1.234,56' (pt-BR)\r\n * formatCurrency(1234.56, 'en-US') // '$1,234.56'\r\n * formatCurrency(1234.56, 'es-ES') // '1.234,56 €'\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n locale: Locale = DEFAULT_LOCALE,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n const currency = CURRENCY_MAP[locale];\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n ...options,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número como percentual\r\n *\r\n * @param value - Valor entre 0 e 1 (ou 0 e 100 se usePercentage=true)\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param usePercentage - Se true, espera valor 0-100 (padrão: false)\r\n * @returns Percentual formatado\r\n *\r\n * @example\r\n * formatPercent(0.1234) // '12%'\r\n * formatPercent(0.1234, 2) // '12,34%'\r\n * formatPercent(12.34, 2, true) // '12,34%'\r\n */\r\nexport function formatPercent(\r\n value: number,\r\n decimals = 0,\r\n usePercentage = false\r\n): string {\r\n return new Intl.NumberFormat('pt-BR', {\r\n style: 'percent',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(usePercentage ? value / 100 : value);\r\n}\r\n\r\n/**\r\n * Formata número com separadores de milhar\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número formatado\r\n *\r\n * @example\r\n * formatNumber(1234567) // '1.234.567' (pt-BR)\r\n * formatNumber(1234567, 0, 'en-US') // '1,234,567'\r\n */\r\nexport function formatNumber(value: number, decimals = 0, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número de forma compacta (1K, 1M, 1B)\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 1)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número compacto\r\n *\r\n * @example\r\n * formatCompact(1234) // '1,2 mil' (pt-BR)\r\n * formatCompact(1234567, 1, 'en-US') // '1.2M'\r\n */\r\nexport function formatCompact(value: number, decimals = 1, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n notation: 'compact',\r\n compactDisplay: 'short',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Converte string de moeda para número\r\n *\r\n * @param currency - String de moeda (ex: 'R$ 1.234,56')\r\n * @returns Valor numérico\r\n *\r\n * @example\r\n * parseCurrency('R$ 1.234,56') // 1234.56\r\n * parseCurrency('1.234,56') // 1234.56\r\n */\r\nexport function parseCurrency(currency: string): number {\r\n const cleaned = currency\r\n .replace(/[R$\\s]/g, '')\r\n .replace(/\\./g, '')\r\n .replace(',', '.');\r\n return parseFloat(cleaned);\r\n}\r\n\r\n/**\r\n * Arredonda número para casas decimais\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais\r\n * @returns Valor arredondado\r\n *\r\n * @example\r\n * round(1.2345, 2) // 1.23\r\n */\r\nexport function round(value: number, decimals = 2): number {\r\n const factor = Math.pow(10, decimals);\r\n return Math.round(value * factor) / factor;\r\n}\r\n\r\n/**\r\n * Clamp - limita número entre min e max\r\n *\r\n * @param value - Valor\r\n * @param min - Mínimo\r\n * @param max - Máximo\r\n * @returns Valor limitado\r\n *\r\n * @example\r\n * clamp(150, 0, 100) // 100\r\n * clamp(-10, 0, 100) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n return Math.min(Math.max(value, min), max);\r\n}\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","/**\r\n * Validation Utilities\r\n *\r\n * Utilitários para validação de dados com suporte a múltiplos idiomas.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/validation\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 * Interface para resultado de validação\r\n */\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors?: string[];\r\n}\r\n\r\n/**\r\n * Valida email usando regex RFC 5322\r\n *\r\n * @param email - Email para validar\r\n * @param locale - Idioma das mensagens de erro (padrão: 'pt-BR')\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateEmail('user@example.com') // { isValid: true }\r\n * validateEmail('invalid-email') // { isValid: false, errors: ['Email inválido'] }\r\n */\r\nexport function validateEmail(email: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n const isValid = emailRegex.test(email);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Email inválido'],\r\n 'en-US': ['Invalid email'],\r\n 'es-ES': ['Email inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida senha com critérios de segurança\r\n *\r\n * @param password - Senha para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePassword('MySecure123!') // { isValid: true }\r\n * validatePassword('123') // { isValid: false, errors: ['Senha deve ter pelo menos 8 caracteres'] }\r\n */\r\nexport function validatePassword(\r\n password: string, \r\n options: {\r\n minLength?: number;\r\n requireUppercase?: boolean;\r\n requireLowercase?: boolean;\r\n requireNumbers?: boolean;\r\n requireSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 8,\r\n requireUppercase = true,\r\n requireLowercase = true,\r\n requireNumbers = true,\r\n requireSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Senha deve ter pelo menos ${minLength} caracteres`,\r\n uppercase: 'Senha deve conter pelo menos uma letra maiúscula',\r\n lowercase: 'Senha deve conter pelo menos uma letra minúscula',\r\n numbers: 'Senha deve conter pelo menos um número',\r\n specialChars: 'Senha deve conter pelo menos um caractere especial'\r\n },\r\n 'en-US': {\r\n minLength: `Password must be at least ${minLength} characters`,\r\n uppercase: 'Password must contain at least one uppercase letter',\r\n lowercase: 'Password must contain at least one lowercase letter',\r\n numbers: 'Password must contain at least one number',\r\n specialChars: 'Password must contain at least one special character'\r\n },\r\n 'es-ES': {\r\n minLength: `La contraseña debe tener al menos ${minLength} caracteres`,\r\n uppercase: 'La contraseña debe contener al menos una letra mayúscula',\r\n lowercase: 'La contraseña debe contener al menos una letra minúscula',\r\n numbers: 'La contraseña debe contener al menos un número',\r\n specialChars: 'La contraseña debe contener al menos un carácter especial'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (password.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (requireUppercase && !/[A-Z]/.test(password)) {\r\n errors.push(messages.uppercase);\r\n }\r\n \r\n if (requireLowercase && !/[a-z]/.test(password)) {\r\n errors.push(messages.lowercase);\r\n }\r\n \r\n if (requireNumbers && !/\\d/.test(password)) {\r\n errors.push(messages.numbers);\r\n }\r\n \r\n if (requireSpecialChars && !/[!@#$%^&*(),.?\":{}|<>]/.test(password)) {\r\n errors.push(messages.specialChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida URL\r\n *\r\n * @param url - URL para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUrl('https://example.com') // { isValid: true }\r\n * validateUrl('not-a-url') // { isValid: false, errors: ['URL inválida'] }\r\n */\r\nexport function validateUrl(url: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n try {\r\n new URL(url);\r\n return { isValid: true };\r\n } catch {\r\n const errors = {\r\n 'pt-BR': ['URL inválida'],\r\n 'en-US': ['Invalid URL'],\r\n 'es-ES': ['URL inválida']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Valida telefone (formato brasileiro por padrão)\r\n *\r\n * @param phone - Telefone para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePhone('(11) 98765-4321') // { isValid: true }\r\n * validatePhone('123') // { isValid: false, errors: ['Telefone inválido'] }\r\n */\r\nexport function validatePhone(phone: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n // Regex para telefone brasileiro: (XX) XXXXX-XXXX ou (XX) XXXX-XXXX\r\n const phoneRegex = /^\\(?\\d{2}\\)?[\\s-]?\\d{4,5}[-]?\\d{4}$/;\r\n const isValid = phoneRegex.test(phone);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Telefone inválido'],\r\n 'en-US': ['Invalid phone number'],\r\n 'es-ES': ['Teléfono inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida username para registro\r\n *\r\n * @param username - Username para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUsername('user123') // { isValid: true }\r\n * validateUsername('us') // { isValid: false, errors: ['Username muito curto'] }\r\n */\r\nexport function validateUsername(\r\n username: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n allowSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 20,\r\n allowSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Username muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muito longo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contém caracteres inválidos'\r\n },\r\n 'en-US': {\r\n minLength: `Username too short (minimum ${minLength} characters)`,\r\n maxLength: `Username too long (maximum ${maxLength} characters)`,\r\n invalidChars: 'Username contains invalid characters'\r\n },\r\n 'es-ES': {\r\n minLength: `Username muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muy largo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contiene caracteres inválidos'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (username.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (username.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const usernameRegex = allowSpecialChars \r\n ? /^[a-zA-Z0-9_]{3,20}$/\r\n : /^[a-zA-Z0-9_]{3,20}$/;\r\n \r\n if (!usernameRegex.test(username)) {\r\n errors.push(messages.invalidChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida slug para URLs amigáveis\r\n *\r\n * @param slug - Slug para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateSlug('my-post-title') // { isValid: true }\r\n * validateSlug('My Post Title') // { isValid: false, errors: ['Slug inválido'] }\r\n */\r\nexport function validateSlug(\r\n slug: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 100\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Slug muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muito longo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use apenas letras minúsculas, números e hífens'\r\n },\r\n 'en-US': {\r\n minLength: `Slug too short (minimum ${minLength} characters)`,\r\n maxLength: `Slug too long (maximum ${maxLength} characters)`,\r\n invalidFormat: 'Invalid slug - use only lowercase letters, numbers and hyphens'\r\n },\r\n 'es-ES': {\r\n minLength: `Slug muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muy largo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use solo letras minúsculas, números y guiones'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (slug.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (slug.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n if (!slugRegex.test(slug)) {\r\n errors.push(messages.invalidFormat);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida texto com comprimento mínimo e máximo\r\n *\r\n * @param text - Texto para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateText('Hello', { minLength: 3 }) // { isValid: true }\r\n * validateText('Hi', { minLength: 3 }) // { isValid: false, errors: ['Texto muito curto'] }\r\n */\r\nexport function validateText(\r\n text: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n fieldName?: string;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 0,\r\n maxLength = Infinity,\r\n fieldName = 'Texto'\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `${fieldName} muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muito longo (máximo ${maxLength} caracteres)`\r\n },\r\n 'en-US': {\r\n minLength: `${fieldName} too short (minimum ${minLength} characters)`,\r\n maxLength: `${fieldName} too long (maximum ${maxLength} characters)`\r\n },\r\n 'es-ES': {\r\n minLength: `${fieldName} muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muy largo (máximo ${maxLength} caracteres)`\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (text.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (text.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n","/**\r\n * DOM Utilities\r\n *\r\n * Utilitários para manipulação do DOM e interações com o browser.\r\n * Funciona em qualquer ambiente browser moderno.\r\n *\r\n * @module @rainersoft/utils/dom\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Verifica se usuário prefere movimento reduzido (accessibility)\r\n *\r\n * @returns true se preferir movimento reduzido\r\n *\r\n * @example\r\n * if (prefersReducedMotion()) {\r\n * // Desabilitar animações\r\n * }\r\n */\r\nexport function prefersReducedMotion(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças na preferência de movimento\r\n *\r\n * @param callback - Função chamada quando a preferência muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onReducedMotionChange((prefersReduced) => {\r\n * console.log('Motion preference changed:', prefersReduced);\r\n * });\r\n * \r\n * // Remover listener quando necessário\r\n * unsubscribe();\r\n */\r\nexport function onReducedMotionChange(\r\n callback: (prefersReduced: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener (compatibilidade com browsers antigos)\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Rola a página para uma posição específica\r\n *\r\n * @param x - Posição horizontal (padrão: 0)\r\n * @param y - Posição vertical (padrão: 0)\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToPosition(0, 500); // Rola para o topo com 500px de margem\r\n * scrollToPosition(0, 0, { smooth: true }); // Scroll suave para o topo\r\n */\r\nexport function scrollToPosition(\r\n x: number = 0,\r\n y: number = 0,\r\n options: {\r\n smooth?: boolean;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, behavior } = options;\r\n \r\n window.scrollTo({\r\n left: x,\r\n top: y,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Rola a página para o topo\r\n *\r\n * @param smooth - Se deve usar scroll suave (padrão: false)\r\n *\r\n * @example\r\n * scrollToTop(); // Scroll instantâneo para o topo\r\n * scrollToTop(true); // Scroll suave para o topo\r\n */\r\nexport function scrollToTop(smooth: boolean = false): void {\r\n scrollToPosition(0, 0, { smooth });\r\n}\r\n\r\n/**\r\n * Rola suavemente para uma posição\r\n *\r\n * @param x - Posição horizontal\r\n * @param y - Posição vertical\r\n * @param duration - Duração da animação em ms (padrão: 300)\r\n *\r\n * @example\r\n * smoothScrollTo(0, 500, 500); // Animação de 500ms para rolar 500px\r\n */\r\nexport function smoothScrollTo(\r\n x: number,\r\n y: number,\r\n duration: number = 300\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const startX = window.scrollX;\r\n const startY = window.scrollY;\r\n const distanceX = x - startX;\r\n const distanceY = y - startY;\r\n const startTime = performance.now();\r\n \r\n function animate(currentTime: number): void {\r\n const elapsed = currentTime - startTime;\r\n const progress = Math.min(elapsed / duration, 1);\r\n \r\n // Easing function (ease-out)\r\n const easeProgress = 1 - Math.pow(1 - progress, 3);\r\n \r\n const currentX = startX + (distanceX * easeProgress);\r\n const currentY = startY + (distanceY * easeProgress);\r\n \r\n window.scrollTo(currentX, currentY);\r\n \r\n if (progress < 1) {\r\n requestAnimationFrame(animate);\r\n }\r\n }\r\n \r\n requestAnimationFrame(animate);\r\n}\r\n\r\n/**\r\n * Rola para um elemento específico\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToElement('#my-element'); // Scroll instantâneo\r\n * scrollToElement('.section', { smooth: true, offset: 100 }); // Scroll suave com offset\r\n */\r\nexport function scrollToElement(\r\n element: string | Element,\r\n options: {\r\n smooth?: boolean;\r\n offset?: number;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, offset = 0, behavior } = options;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const absoluteY = rect.top + window.scrollY - offset;\r\n \r\n window.scrollTo({\r\n left: 0,\r\n top: absoluteY,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Verifica se elemento está visível na viewport\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param threshold - Limiar de visibilidade (0 a 1, padrão: 0)\r\n * @returns true se elemento estiver visível\r\n *\r\n * @example\r\n * isElementVisible('#my-element'); // true se elemento estiver na viewport\r\n * isElementVisible('.section', 0.5); // true se 50% do elemento estiver visível\r\n */\r\nexport function isElementVisible(\r\n element: string | Element,\r\n threshold: number = 0\r\n): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return false;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const windowHeight = window.innerHeight;\r\n const windowWidth = window.innerWidth;\r\n \r\n const verticalThreshold = windowHeight * threshold;\r\n const horizontalThreshold = windowWidth * threshold;\r\n \r\n const isVisibleVertically = \r\n rect.bottom >= verticalThreshold && \r\n rect.top <= windowHeight - verticalThreshold;\r\n \r\n const isVisibleHorizontally = \r\n rect.right >= horizontalThreshold && \r\n rect.left <= windowWidth - horizontalThreshold;\r\n \r\n return isVisibleVertically && isVisibleHorizontally;\r\n}\r\n\r\n/**\r\n * Obtém a posição de um elemento em relação ao documento\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @returns Posição { x, y } ou null se elemento não for encontrado\r\n *\r\n * @example\r\n * const position = getElementPosition('#my-element');\r\n * console.log('X:', position.x, 'Y:', position.y);\r\n */\r\nexport function getElementPosition(\r\n element: string | Element\r\n): { x: number; y: number } | null {\r\n if (typeof window === 'undefined') return null;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return null;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n \r\n return {\r\n x: rect.left + window.scrollX,\r\n y: rect.top + window.scrollY\r\n };\r\n}\r\n\r\n/**\r\n * Verifica se está em dispositivo móvel\r\n *\r\n * @returns true se for dispositivo móvel\r\n *\r\n * @example\r\n * if (isMobile()) {\r\n * // Aplicar layout mobile\r\n * }\r\n */\r\nexport function isMobile(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n // Verificar User Agent\r\n const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\r\n navigator.userAgent\r\n );\r\n \r\n // Verificar tamanho de tela (fallback)\r\n const isMobileScreen = window.innerWidth <= 768;\r\n \r\n return isMobileUA || isMobileScreen;\r\n}\r\n\r\n/**\r\n * Verifica se está em modo escuro\r\n *\r\n * @returns true se o sistema preferir modo escuro\r\n *\r\n * @example\r\n * if (isDarkMode()) {\r\n * // Aplicar tema escuro\r\n * }\r\n */\r\nexport function isDarkMode(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças no tema do sistema\r\n *\r\n * @param callback - Função chamada quando o tema muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onDarkModeChange((isDark) => {\r\n * console.log('Theme changed:', isDark ? 'dark' : 'light');\r\n * });\r\n */\r\nexport function onDarkModeChange(\r\n callback: (isDark: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Copia texto para a área de transferência\r\n *\r\n * @param text - Texto para copiar\r\n * @returns Promise que resolve para true se sucesso\r\n *\r\n * @example\r\n * copyToClipboard('Hello World').then(success => {\r\n * if (success) {\r\n * console.log('Texto copiado!');\r\n * }\r\n * });\r\n */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof window === 'undefined') return false;\r\n \r\n try {\r\n // Tentar usar a API moderna\r\n if (navigator.clipboard && window.isSecureContext) {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n }\r\n \r\n // Fallback para browsers mais antigos\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-999999px';\r\n textArea.style.top = '-999999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n \r\n const result = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n \r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Baixa um arquivo como blob\r\n *\r\n * @param blob - Blob para baixar\r\n * @param filename - Nome do arquivo\r\n *\r\n * @example\r\n * downloadFile(new Blob(['Hello World'], { type: 'text/plain' }), 'hello.txt');\r\n */\r\nexport function downloadFile(blob: Blob, filename: string): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = filename;\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n","/**\r\n * Stats Formatting Utilities\r\n *\r\n * Utilitários universais para formatação de estatísticas e números.\r\n *\r\n * @module @rainersoft/utils/stats\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Formata número grande com abreviação (1.5k, 2.3M, etc)\r\n *\r\n * @param num - Número para formatar\r\n * @returns String formatada com abreviação\r\n *\r\n * @example\r\n * ```ts\r\n * formatNumber(1500) // '1.5k'\r\n * formatNumber(2500000) // '2.5M'\r\n * formatNumber(999) // '999'\r\n * ```\r\n */\r\nexport function formatNumber(num: number): string {\r\n if (num >= 1000000) {\r\n return (num / 1000000).toFixed(1) + 'M';\r\n }\r\n if (num >= 1000) {\r\n return (num / 1000).toFixed(1) + 'k';\r\n }\r\n return num.toString();\r\n}\r\n\r\n/**\r\n * Calcula percentual de mudança entre dois valores\r\n *\r\n * @param current - Valor atual\r\n * @param previous - Valor anterior\r\n * @returns Percentual de mudança (arredondado)\r\n *\r\n * @example\r\n * ```ts\r\n * calculateChange(150, 100) // 50\r\n * calculateChange(80, 100) // -20\r\n * calculateChange(100, 0) // 100\r\n * ```\r\n */\r\nexport function calculateChange(current: number, previous: number): number {\r\n if (previous === 0) return 100;\r\n return Math.round(((current - previous) / previous) * 100);\r\n}\r\n\r\n/**\r\n * Formata percentual com sinal\r\n *\r\n * @param value - Valor do percentual\r\n * @param options - Opções de formatação\r\n * @returns String formatada com sinal e símbolo\r\n *\r\n * @example\r\n * ```ts\r\n * formatPercentage(25) // '+25%'\r\n * formatPercentage(-10) // '-10%'\r\n * formatPercentage(0) // '0%'\r\n * ```\r\n */\r\nexport function formatPercentage(\r\n value: number,\r\n options: { showSign?: boolean; decimals?: number } = {}\r\n): string {\r\n const { showSign = true, decimals = 0 } = options;\r\n \r\n const sign = showSign && value > 0 ? '+' : '';\r\n const formattedValue = value.toFixed(decimals);\r\n \r\n return `${sign}${formattedValue}%`;\r\n}\r\n\r\n/**\r\n * Gera dados de exemplo para gráficos\r\n *\r\n * @param days - Número de dias para gerar dados\r\n * @param locale - Idioma para formatação de datas\r\n * @returns Array de dados mock\r\n *\r\n * @example\r\n * ```ts\r\n * const data = generateMockChartData(7);\r\n * // [\r\n * // { date: '01/12', views: 1234, uniqueViews: 890, likes: 67, comments: 23 },\r\n * // ...\r\n * // ]\r\n * ```\r\n */\r\nexport function generateMockChartData(\r\n days: number,\r\n locale: string = 'pt-BR'\r\n): Array<Record<string, any>> {\r\n const data = [];\r\n const now = new Date();\r\n\r\n for (let i = days - 1; i >= 0; i--) {\r\n const date = new Date(now);\r\n date.setDate(date.getDate() - i);\r\n\r\n data.push({\r\n date: date.toLocaleDateString(locale, {\r\n day: '2-digit',\r\n month: '2-digit',\r\n }),\r\n views: Math.floor(Math.random() * 1000) + 500,\r\n uniqueViews: Math.floor(Math.random() * 700) + 300,\r\n likes: Math.floor(Math.random() * 100) + 50,\r\n comments: Math.floor(Math.random() * 50) + 10,\r\n shares: Math.floor(Math.random() * 30) + 5,\r\n });\r\n }\r\n\r\n return data;\r\n}\r\n\r\n/**\r\n * Agrupa dados por período (dia, semana, mês)\r\n *\r\n * @param data - Array de dados para agrupar\r\n * @param period - Período de agrupamento\r\n * @param dateField - Campo de data nos objetos\r\n * @returns Array de dados agrupados\r\n *\r\n * @example\r\n * ```ts\r\n * const grouped = groupDataByPeriod(data, 'week', 'date');\r\n * ```\r\n */\r\nexport function groupDataByPeriod<T extends Record<string, any>>(\r\n data: T[],\r\n // period: 'day' | 'week' | 'month' = 'day', // Pode ser usado futuramente para agrupamento\r\n // dateField: keyof T = 'date' as keyof T\r\n): T[] {\r\n // Implementação simplificada - pode ser expandida\r\n // Por enquanto, retorna os dados originais\r\n return data;\r\n}\r\n\r\n/**\r\n * Calcula médias móveis para suavizar dados\r\n *\r\n * @param data - Array de valores numéricos\r\n * @param window - Tamanho da janela de média móvel\r\n * @returns Array com médias móveis\r\n *\r\n * @example\r\n * ```ts\r\n * const smoothed = calculateMovingAverage([1, 2, 3, 4, 5], 3);\r\n * // [2, 3, 4] (médias de [1,2,3], [2,3,4], [3,4,5])\r\n * ```\r\n */\r\nexport function calculateMovingAverage(data: number[], window: number): number[] {\r\n const result: number[] = [];\r\n \r\n for (let i = window - 1; i < data.length; i++) {\r\n const sum = data.slice(i - window + 1, i + 1).reduce((a, b) => a + b, 0);\r\n result.push(sum / window);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Encontra valor máximo e mínimo em array de objetos\r\n *\r\n * @param data - Array de objetos\r\n * @param field - Campo para analisar\r\n * @returns Objeto com min e max\r\n *\r\n * @example\r\n * ```ts\r\n * const { min, max } = findMinMax(data, 'views');\r\n * ```\r\n */\r\nexport function findMinMax<T extends Record<string, any>>(\r\n data: T[],\r\n field: keyof T\r\n): { min: number; max: number } {\r\n const values = data.map(item => Number(item[field]) || 0);\r\n \r\n return {\r\n min: Math.min(...values),\r\n max: Math.max(...values)\r\n };\r\n}\r\n","/**\r\n * Helpers pt-BR\r\n *\r\n * Funções pré-configuradas para português brasileiro.\r\n * Facilitam o uso sem precisar passar locale em cada chamada.\r\n *\r\n * @module @rainersoft/utils/pt-br\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport {\r\n formatDate as formatDateBase,\r\n formatDateTime as formatDateTimeBase,\r\n formatRelativeDate as formatRelativeDateBase,\r\n} from './date';\r\n\r\nimport {\r\n formatCurrency as formatCurrencyBase,\r\n formatNumber as formatNumberBase,\r\n formatCompact as formatCompactBase,\r\n} from './number';\r\n\r\nimport {\r\n translateStatus as translateStatusBase,\r\n} from './status';\r\n\r\n// ============================================================================\r\n// DATE - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata data em português (Brasil)\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long'\r\n): string {\r\n return formatDateBase(date, format, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data e hora em português (Brasil)\r\n */\r\nexport function formatDateTime(date: string | Date): string {\r\n return formatDateTimeBase(date, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data relativa em português (Brasil)\r\n */\r\nexport function formatRelativeDate(date: string | Date): string {\r\n return formatRelativeDateBase(date, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// NUMBER - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata moeda em Real (BRL)\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n return formatCurrencyBase(value, 'pt-BR', options);\r\n}\r\n\r\n/**\r\n * Formata número em português (Brasil)\r\n */\r\nexport function formatNumber(value: number, decimals = 0): string {\r\n return formatNumberBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata número compacto em português (Brasil)\r\n */\r\nexport function formatCompact(value: number, decimals = 1): string {\r\n return formatCompactBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// STATUS - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Traduz status para português (Brasil)\r\n */\r\nexport function translateStatus(status: string): string {\r\n return translateStatusBase(status, 'pt-BR');\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/text/index.ts","../src/string/index.ts","../src/date/index.ts","../src/number/index.ts","../src/status/index.ts","../src/validation/index.ts","../src/dom/index.ts","../src/stats/index.ts","../src/pt-br.ts"],"names":["formatNumber","window","formatCompact","formatCurrency","formatDate","formatDateTime","formatRelativeDate","translateStatus"],"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 * Text Utilities\r\n *\r\n * Utilitários universais para manipulação de texto e strings.\r\n *\r\n * @module @rainersoft/utils/text\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n// ============================================================================\r\n// AVATAR UTILITIES\r\n// ============================================================================\r\n\r\n/**\r\n * Extrai iniciais de um nome\r\n *\r\n * @param name - Nome completo\r\n * @param maxChars - Número máximo de caracteres (padrão: 2)\r\n * @returns Iniciais do nome em maiúsculas\r\n *\r\n * @example\r\n * ```ts\r\n * extractInitials('John Doe') // 'JD'\r\n * extractInitials('Maria Silva Santos') // 'MS'\r\n * extractInitials('Apple') // 'A'\r\n * extractInitials('', 3) // ''\r\n * ```\r\n */\r\nexport function extractInitials(name: string | null | undefined, maxChars = 2): string {\r\n if (!name || !name.trim()) {\r\n return '';\r\n }\r\n\r\n const words = name.trim().split(/\\s+/);\r\n const initials = words\r\n .slice(0, maxChars)\r\n .map(word => word.charAt(0).toUpperCase())\r\n .join('');\r\n\r\n return initials;\r\n}\r\n\r\n/**\r\n * Gera URL do avatar com base no nome\r\n *\r\n * @param name - Nome para gerar avatar\r\n * @param size - Tamanho do avatar (default: 200)\r\n * @param backgroundColor - Cor de fundo (default: cyan)\r\n * @param textColor - Cor do texto (default: white)\r\n * @returns URL do avatar\r\n *\r\n * @example\r\n * ```ts\r\n * generateAvatarUrl('John Doe') // URL do avatar\r\n * generateAvatarUrl('John Doe', 100, 'f97316', 'fff') // URL com cor laranja\r\n * ```\r\n */\r\nexport function generateAvatarUrl(\r\n name: string,\r\n size: number = 200,\r\n backgroundColor: string = '0891b2',\r\n textColor: string = 'fff'\r\n): string {\r\n const encodedName = encodeURIComponent(name);\r\n \r\n return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;\r\n}\r\n\r\n/**\r\n * Valida se uma URL de avatar é válida\r\n *\r\n * @param url - URL do avatar\r\n * @returns true se a URL for válida\r\n *\r\n * @example\r\n * ```ts\r\n * isValidAvatarUrl('https://example.com/avatar.jpg') // true\r\n * isValidAvatarUrl('invalid-url') // false\r\n * ```\r\n */\r\nexport function isValidAvatarUrl(url: string): boolean {\r\n if (!url || typeof url !== 'string') {\r\n return false;\r\n }\r\n\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Obtém a cor do avatar baseada no hash do nome\r\n *\r\n * @param name - Nome para gerar cor\r\n * @returns Cor em formato hexadecimal\r\n *\r\n * @example\r\n * ```ts\r\n * getAvatarColorFromName('John Doe') // '#0891b2' (ou outra cor)\r\n * getAvatarColorFromName('') // '#0891b2' (cor padrão)\r\n * ```\r\n */\r\nexport function getAvatarColorFromName(name: string): string {\r\n if (!name || typeof name !== 'string') {\r\n return '#0891b2'; // cyan-600 como padrão\r\n }\r\n\r\n // Gera hash simples do nome\r\n let hash = 0;\r\n for (let i = 0; i < name.length; i++) {\r\n hash = name.charCodeAt(i) + ((hash << 5) - hash);\r\n }\r\n\r\n // Cores baseadas em design tokens (compatível com @rainersoft/design-tokens)\r\n const colors = [\r\n '#0891b2', // cyan-600\r\n '#9333ea', // purple-600\r\n '#db2777', // pink-600\r\n '#059669', // emerald-600\r\n '#2563eb', // blue-600\r\n '#f97316', // orange-500\r\n '#dc2626', // red-600\r\n '#7c3aed', // violet-600\r\n ];\r\n\r\n const index = Math.abs(hash) % colors.length;\r\n return colors[index];\r\n}\r\n\r\n/**\r\n * Gera avatar com cor baseada no nome\r\n *\r\n * @param name - Nome para gerar avatar\r\n * @param size - Tamanho do avatar\r\n * @returns URL do avatar com cor automática\r\n *\r\n * @example\r\n * ```ts\r\n * generateDynamicAvatarUrl('John Doe') // URL com cor baseada no nome\r\n * generateDynamicAvatarUrl('Jane Smith', 150) // URL com tamanho 150\r\n * ```\r\n */\r\nexport function generateDynamicAvatarUrl(name: string, size: number = 200): string {\r\n const color = getAvatarColorFromName(name);\r\n const colorHex = color.replace('#', '');\r\n return generateAvatarUrl(name, size, colorHex, 'fff');\r\n}\r\n\r\n// ============================================================================\r\n// TEXT UTILITIES\r\n// ============================================================================\r\n\r\n/**\r\n * Gera ID único baseado em texto\r\n *\r\n * @param text - Texto base para o ID\r\n * @param prefix - Prefixo opcional\r\n * @param suffix - Sufixo opcional\r\n * @returns ID único em formato slug\r\n *\r\n * @example\r\n * ```ts\r\n * generateUniqueId('Hello World') // 'hello-world'\r\n * generateUniqueId('Hello World', 'section') // 'section-hello-world'\r\n * generateUniqueId('Olá! Como vai?', '', '123') // 'ola-como-vai-123'\r\n * ```\r\n */\r\nexport function generateUniqueId(\r\n text: string,\r\n prefix = '',\r\n suffix = ''\r\n): string {\r\n const slug = text\r\n .toLowerCase()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '') // Remove acentos\r\n .replace(/[^\\w\\s-]/g, '') // Remove caracteres especiais\r\n .replace(/\\s+/g, '-') // Substitui espaços por hífens\r\n .replace(/-+/g, '-') // Remove hífens duplicados\r\n .trim()\r\n .substring(0, 50); // Limita tamanho\r\n\r\n const parts = [prefix, slug, suffix].filter(Boolean);\r\n return parts.join('-');\r\n}\r\n\r\n/**\r\n * Trunca texto com elipse\r\n *\r\n * @param text - Texto para truncar\r\n * @param maxLength - Comprimento máximo\r\n * @param suffix - Sufixo para adicionar (padrão: '...')\r\n * @returns Texto truncado\r\n *\r\n * @example\r\n * ```ts\r\n * truncateText('Hello World', 5) // 'Hello...'\r\n * truncateText('Hello World', 8, '...') // 'Hello...'\r\n * truncateText('Short', 10) // 'Short'\r\n * ```\r\n */\r\nexport function truncateText(\r\n text: string,\r\n maxLength: number,\r\n suffix = '...'\r\n): string {\r\n if (!text || text.length <= maxLength) {\r\n return text || '';\r\n }\r\n\r\n return text.substring(0, maxLength - suffix.length) + suffix;\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 * @param options - Opções de capitalização\r\n * @returns Texto capitalizado\r\n *\r\n * @example\r\n * ```ts\r\n * capitalize('hello world') // 'Hello World'\r\n * capitalize('hello world', { firstWordOnly: true }) // 'Hello world'\r\n * capitalize('HELLO WORLD', { lowerRest: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function capitalize(\r\n text: string,\r\n options: { firstWordOnly?: boolean; lowerRest?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { firstWordOnly = false, lowerRest = false } = options;\r\n\r\n if (firstWordOnly) {\r\n return text.charAt(0).toUpperCase() + \r\n (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));\r\n }\r\n\r\n if (lowerRest) {\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase()).toLowerCase();\r\n }\r\n\r\n return text.replace(/\\b\\w/g, char => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Remove caracteres especiais mantendo apenas alfanuméricos e espaços\r\n *\r\n * @param text - Texto para limpar\r\n * @param allowSpaces - Se deve permitir espaços\r\n * @returns Texto limpo\r\n *\r\n * @example\r\n * ```ts\r\n * cleanText('Olá! Como vai?') // 'Ola Como vai'\r\n * cleanText('Olá! Como vai?', false) // 'OlaComoVai'\r\n * ```\r\n */\r\nexport function cleanText(text: string, allowSpaces = true): string {\r\n if (!text) return '';\r\n\r\n const pattern = allowSpaces ? /[^\\w\\s]/g : /[^\\w]/g;\r\n return text.replace(pattern, '');\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\n * @example\r\n * ```ts\r\n * countWords('Hello world') // 2\r\n * countWords(' Hello world ') // 2\r\n * countWords('') // 0\r\n * ```\r\n */\r\nexport function countWords(text: string): number {\r\n if (!text || !text.trim()) {\r\n return 0;\r\n }\r\n\r\n return text.trim().split(/\\s+/).length;\r\n}\r\n\r\n/**\r\n * Verifica se texto está vazio ou contém apenas espaços\r\n *\r\n * @param text - Texto para verificar\r\n * @returns True se estiver vazio\r\n *\r\n * @example\r\n * ```ts\r\n * isEmpty('') // true\r\n * isEmpty(' ') // true\r\n * isEmpty('Hello') // false\r\n * ```\r\n */\r\nexport function isEmpty(text: string | null | undefined): boolean {\r\n return !text || !text.trim();\r\n}\r\n\r\n/**\r\n * Remove espaços em branco extras\r\n *\r\n * @param text - Texto para limpar\r\n * @param options - Opções de limpeza\r\n * @returns Texto sem espaços extras\r\n *\r\n * @example\r\n * ```ts\r\n * normalizeSpaces(' Hello World ') // 'Hello World'\r\n * normalizeSpaces('Hello\\nWorld', { newlines: true }) // 'Hello World'\r\n * ```\r\n */\r\nexport function normalizeSpaces(\r\n text: string,\r\n options: { newlines?: boolean } = {}\r\n): string {\r\n if (!text) return '';\r\n\r\n const { newlines = false } = options;\r\n \r\n let cleaned = text;\r\n \r\n if (newlines) {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n } else {\r\n cleaned = cleaned.replace(/\\s+/g, ' ');\r\n }\r\n \r\n return cleaned.trim();\r\n}\r\n","/**\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","/**\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","/**\r\n * Number Utilities\r\n *\r\n * Utilitários para formatação de números, moedas e percentuais.\r\n * Suporte para múltiplos idiomas: pt-BR, en-US, es-ES.\r\n *\r\n * @module @rainersoft/utils/number\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport type { Locale } from '../types';\r\nimport { DEFAULT_LOCALE, CURRENCY_MAP } from '../types';\r\n\r\n/**\r\n * Formata número como moeda com suporte a idiomas\r\n *\r\n * @param value - Valor numérico\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @param options - Opções de formatação\r\n * @returns Valor formatado\r\n *\r\n * @example\r\n * formatCurrency(1234.56) // 'R$ 1.234,56' (pt-BR)\r\n * formatCurrency(1234.56, 'en-US') // '$1,234.56'\r\n * formatCurrency(1234.56, 'es-ES') // '1.234,56 €'\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n locale: Locale = DEFAULT_LOCALE,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n const currency = CURRENCY_MAP[locale];\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n ...options,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número como percentual\r\n *\r\n * @param value - Valor entre 0 e 1 (ou 0 e 100 se usePercentage=true)\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param usePercentage - Se true, espera valor 0-100 (padrão: false)\r\n * @returns Percentual formatado\r\n *\r\n * @example\r\n * formatPercent(0.1234) // '12%'\r\n * formatPercent(0.1234, 2) // '12,34%'\r\n * formatPercent(12.34, 2, true) // '12,34%'\r\n */\r\nexport function formatPercent(\r\n value: number,\r\n decimals = 0,\r\n usePercentage = false\r\n): string {\r\n return new Intl.NumberFormat('pt-BR', {\r\n style: 'percent',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(usePercentage ? value / 100 : value);\r\n}\r\n\r\n/**\r\n * Formata número com separadores de milhar\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 0)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número formatado\r\n *\r\n * @example\r\n * formatNumber(1234567) // '1.234.567' (pt-BR)\r\n * formatNumber(1234567, 0, 'en-US') // '1,234,567'\r\n */\r\nexport function formatNumber(value: number, decimals = 0, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Formata número de forma compacta (1K, 1M, 1B)\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais (padrão: 1)\r\n * @param locale - Idioma (padrão: 'pt-BR')\r\n * @returns Número compacto\r\n *\r\n * @example\r\n * formatCompact(1234) // '1,2 mil' (pt-BR)\r\n * formatCompact(1234567, 1, 'en-US') // '1.2M'\r\n */\r\nexport function formatCompact(value: number, decimals = 1, locale: Locale = DEFAULT_LOCALE): string {\r\n return new Intl.NumberFormat(locale, {\r\n notation: 'compact',\r\n compactDisplay: 'short',\r\n minimumFractionDigits: decimals,\r\n maximumFractionDigits: decimals,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Converte string de moeda para número\r\n *\r\n * @param currency - String de moeda (ex: 'R$ 1.234,56')\r\n * @returns Valor numérico\r\n *\r\n * @example\r\n * parseCurrency('R$ 1.234,56') // 1234.56\r\n * parseCurrency('1.234,56') // 1234.56\r\n */\r\nexport function parseCurrency(currency: string): number {\r\n const cleaned = currency\r\n .replace(/[R$\\s]/g, '')\r\n .replace(/\\./g, '')\r\n .replace(',', '.');\r\n return parseFloat(cleaned);\r\n}\r\n\r\n/**\r\n * Arredonda número para casas decimais\r\n *\r\n * @param value - Valor numérico\r\n * @param decimals - Casas decimais\r\n * @returns Valor arredondado\r\n *\r\n * @example\r\n * round(1.2345, 2) // 1.23\r\n */\r\nexport function round(value: number, decimals = 2): number {\r\n const factor = Math.pow(10, decimals);\r\n return Math.round(value * factor) / factor;\r\n}\r\n\r\n/**\r\n * Clamp - limita número entre min e max\r\n *\r\n * @param value - Valor\r\n * @param min - Mínimo\r\n * @param max - Máximo\r\n * @returns Valor limitado\r\n *\r\n * @example\r\n * clamp(150, 0, 100) // 100\r\n * clamp(-10, 0, 100) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n return Math.min(Math.max(value, min), max);\r\n}\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","/**\r\n * Validation Utilities\r\n *\r\n * Utilitários para validação de dados com suporte a múltiplos idiomas.\r\n * Funções puras, sem dependências externas, prontas para qualquer plataforma.\r\n *\r\n * @module @rainersoft/utils/validation\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 * Interface para resultado de validação\r\n */\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors?: string[];\r\n}\r\n\r\n/**\r\n * Valida email usando regex RFC 5322\r\n *\r\n * @param email - Email para validar\r\n * @param locale - Idioma das mensagens de erro (padrão: 'pt-BR')\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateEmail('user@example.com') // { isValid: true }\r\n * validateEmail('invalid-email') // { isValid: false, errors: ['Email inválido'] }\r\n */\r\nexport function validateEmail(email: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n const isValid = emailRegex.test(email);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Email inválido'],\r\n 'en-US': ['Invalid email'],\r\n 'es-ES': ['Email inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida senha com critérios de segurança\r\n *\r\n * @param password - Senha para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePassword('MySecure123!') // { isValid: true }\r\n * validatePassword('123') // { isValid: false, errors: ['Senha deve ter pelo menos 8 caracteres'] }\r\n */\r\nexport function validatePassword(\r\n password: string, \r\n options: {\r\n minLength?: number;\r\n requireUppercase?: boolean;\r\n requireLowercase?: boolean;\r\n requireNumbers?: boolean;\r\n requireSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 8,\r\n requireUppercase = true,\r\n requireLowercase = true,\r\n requireNumbers = true,\r\n requireSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Senha deve ter pelo menos ${minLength} caracteres`,\r\n uppercase: 'Senha deve conter pelo menos uma letra maiúscula',\r\n lowercase: 'Senha deve conter pelo menos uma letra minúscula',\r\n numbers: 'Senha deve conter pelo menos um número',\r\n specialChars: 'Senha deve conter pelo menos um caractere especial'\r\n },\r\n 'en-US': {\r\n minLength: `Password must be at least ${minLength} characters`,\r\n uppercase: 'Password must contain at least one uppercase letter',\r\n lowercase: 'Password must contain at least one lowercase letter',\r\n numbers: 'Password must contain at least one number',\r\n specialChars: 'Password must contain at least one special character'\r\n },\r\n 'es-ES': {\r\n minLength: `La contraseña debe tener al menos ${minLength} caracteres`,\r\n uppercase: 'La contraseña debe contener al menos una letra mayúscula',\r\n lowercase: 'La contraseña debe contener al menos una letra minúscula',\r\n numbers: 'La contraseña debe contener al menos un número',\r\n specialChars: 'La contraseña debe contener al menos un carácter especial'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (password.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (requireUppercase && !/[A-Z]/.test(password)) {\r\n errors.push(messages.uppercase);\r\n }\r\n \r\n if (requireLowercase && !/[a-z]/.test(password)) {\r\n errors.push(messages.lowercase);\r\n }\r\n \r\n if (requireNumbers && !/\\d/.test(password)) {\r\n errors.push(messages.numbers);\r\n }\r\n \r\n if (requireSpecialChars && !/[!@#$%^&*(),.?\":{}|<>]/.test(password)) {\r\n errors.push(messages.specialChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida URL\r\n *\r\n * @param url - URL para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUrl('https://example.com') // { isValid: true }\r\n * validateUrl('not-a-url') // { isValid: false, errors: ['URL inválida'] }\r\n */\r\nexport function validateUrl(url: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n try {\r\n new URL(url);\r\n return { isValid: true };\r\n } catch {\r\n const errors = {\r\n 'pt-BR': ['URL inválida'],\r\n 'en-US': ['Invalid URL'],\r\n 'es-ES': ['URL inválida']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Valida telefone (formato brasileiro por padrão)\r\n *\r\n * @param phone - Telefone para validar\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validatePhone('(11) 98765-4321') // { isValid: true }\r\n * validatePhone('123') // { isValid: false, errors: ['Telefone inválido'] }\r\n */\r\nexport function validatePhone(phone: string, locale: Locale = DEFAULT_LOCALE): ValidationResult {\r\n // Regex para telefone brasileiro: (XX) XXXXX-XXXX ou (XX) XXXX-XXXX\r\n const phoneRegex = /^\\(?\\d{2}\\)?[\\s-]?\\d{4,5}[-]?\\d{4}$/;\r\n const isValid = phoneRegex.test(phone);\r\n \r\n if (!isValid) {\r\n const errors = {\r\n 'pt-BR': ['Telefone inválido'],\r\n 'en-US': ['Invalid phone number'],\r\n 'es-ES': ['Teléfono inválido']\r\n };\r\n \r\n return {\r\n isValid: false,\r\n errors: errors[locale] || errors['pt-BR']\r\n };\r\n }\r\n \r\n return { isValid: true };\r\n}\r\n\r\n/**\r\n * Valida username para registro\r\n *\r\n * @param username - Username para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateUsername('user123') // { isValid: true }\r\n * validateUsername('us') // { isValid: false, errors: ['Username muito curto'] }\r\n */\r\nexport function validateUsername(\r\n username: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n allowSpecialChars?: boolean;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 20,\r\n allowSpecialChars = false\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Username muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muito longo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contém caracteres inválidos'\r\n },\r\n 'en-US': {\r\n minLength: `Username too short (minimum ${minLength} characters)`,\r\n maxLength: `Username too long (maximum ${maxLength} characters)`,\r\n invalidChars: 'Username contains invalid characters'\r\n },\r\n 'es-ES': {\r\n minLength: `Username muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Username muy largo (máximo ${maxLength} caracteres)`,\r\n invalidChars: 'Username contiene caracteres inválidos'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (username.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (username.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const usernameRegex = allowSpecialChars \r\n ? /^[a-zA-Z0-9_]{3,20}$/\r\n : /^[a-zA-Z0-9_]{3,20}$/;\r\n \r\n if (!usernameRegex.test(username)) {\r\n errors.push(messages.invalidChars);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida slug para URLs amigáveis\r\n *\r\n * @param slug - Slug para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateSlug('my-post-title') // { isValid: true }\r\n * validateSlug('My Post Title') // { isValid: false, errors: ['Slug inválido'] }\r\n */\r\nexport function validateSlug(\r\n slug: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 3,\r\n maxLength = 100\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `Slug muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muito longo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use apenas letras minúsculas, números e hífens'\r\n },\r\n 'en-US': {\r\n minLength: `Slug too short (minimum ${minLength} characters)`,\r\n maxLength: `Slug too long (maximum ${maxLength} characters)`,\r\n invalidFormat: 'Invalid slug - use only lowercase letters, numbers and hyphens'\r\n },\r\n 'es-ES': {\r\n minLength: `Slug muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `Slug muy largo (máximo ${maxLength} caracteres)`,\r\n invalidFormat: 'Slug inválido - use solo letras minúsculas, números y guiones'\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (slug.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (slug.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n if (!slugRegex.test(slug)) {\r\n errors.push(messages.invalidFormat);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n\r\n/**\r\n * Valida texto com comprimento mínimo e máximo\r\n *\r\n * @param text - Texto para validar\r\n * @param options - Opções de validação\r\n * @param locale - Idioma das mensagens de erro\r\n * @returns Resultado da validação\r\n *\r\n * @example\r\n * validateText('Hello', { minLength: 3 }) // { isValid: true }\r\n * validateText('Hi', { minLength: 3 }) // { isValid: false, errors: ['Texto muito curto'] }\r\n */\r\nexport function validateText(\r\n text: string,\r\n options: {\r\n minLength?: number;\r\n maxLength?: number;\r\n fieldName?: string;\r\n } = {},\r\n locale: Locale = DEFAULT_LOCALE\r\n): ValidationResult {\r\n const {\r\n minLength = 0,\r\n maxLength = Infinity,\r\n fieldName = 'Texto'\r\n } = options;\r\n \r\n const errors: string[] = [];\r\n \r\n const errorMessages = {\r\n 'pt-BR': {\r\n minLength: `${fieldName} muito curto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muito longo (máximo ${maxLength} caracteres)`\r\n },\r\n 'en-US': {\r\n minLength: `${fieldName} too short (minimum ${minLength} characters)`,\r\n maxLength: `${fieldName} too long (maximum ${maxLength} characters)`\r\n },\r\n 'es-ES': {\r\n minLength: `${fieldName} muy corto (mínimo ${minLength} caracteres)`,\r\n maxLength: `${fieldName} muy largo (máximo ${maxLength} caracteres)`\r\n }\r\n };\r\n \r\n const messages = errorMessages[locale] || errorMessages['pt-BR'];\r\n \r\n if (text.length < minLength) {\r\n errors.push(messages.minLength);\r\n }\r\n \r\n if (text.length > maxLength) {\r\n errors.push(messages.maxLength);\r\n }\r\n \r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n}\r\n","/**\r\n * DOM Utilities\r\n *\r\n * Utilitários para manipulação do DOM e interações com o browser.\r\n * Funciona em qualquer ambiente browser moderno.\r\n *\r\n * @module @rainersoft/utils/dom\r\n * @author Rainer Teixeira\r\n */\r\n\r\n/**\r\n * Verifica se usuário prefere movimento reduzido (accessibility)\r\n *\r\n * @returns true se preferir movimento reduzido\r\n *\r\n * @example\r\n * if (prefersReducedMotion()) {\r\n * // Desabilitar animações\r\n * }\r\n */\r\nexport function prefersReducedMotion(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças na preferência de movimento\r\n *\r\n * @param callback - Função chamada quando a preferência muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onReducedMotionChange((prefersReduced) => {\r\n * console.log('Motion preference changed:', prefersReduced);\r\n * });\r\n * \r\n * // Remover listener quando necessário\r\n * unsubscribe();\r\n */\r\nexport function onReducedMotionChange(\r\n callback: (prefersReduced: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener (compatibilidade com browsers antigos)\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n // Fallback para browsers mais antigos\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Rola a página para uma posição específica\r\n *\r\n * @param x - Posição horizontal (padrão: 0)\r\n * @param y - Posição vertical (padrão: 0)\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToPosition(0, 500); // Rola para o topo com 500px de margem\r\n * scrollToPosition(0, 0, { smooth: true }); // Scroll suave para o topo\r\n */\r\nexport function scrollToPosition(\r\n x: number = 0,\r\n y: number = 0,\r\n options: {\r\n smooth?: boolean;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, behavior } = options;\r\n \r\n window.scrollTo({\r\n left: x,\r\n top: y,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Rola a página para o topo\r\n *\r\n * @param smooth - Se deve usar scroll suave (padrão: false)\r\n *\r\n * @example\r\n * scrollToTop(); // Scroll instantâneo para o topo\r\n * scrollToTop(true); // Scroll suave para o topo\r\n */\r\nexport function scrollToTop(smooth: boolean = false): void {\r\n scrollToPosition(0, 0, { smooth });\r\n}\r\n\r\n/**\r\n * Rola suavemente para uma posição\r\n *\r\n * @param x - Posição horizontal\r\n * @param y - Posição vertical\r\n * @param duration - Duração da animação em ms (padrão: 300)\r\n *\r\n * @example\r\n * smoothScrollTo(0, 500, 500); // Animação de 500ms para rolar 500px\r\n */\r\nexport function smoothScrollTo(\r\n x: number,\r\n y: number,\r\n duration: number = 300\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const startX = window.scrollX;\r\n const startY = window.scrollY;\r\n const distanceX = x - startX;\r\n const distanceY = y - startY;\r\n const startTime = performance.now();\r\n \r\n function animate(currentTime: number): void {\r\n const elapsed = currentTime - startTime;\r\n const progress = Math.min(elapsed / duration, 1);\r\n \r\n // Easing function (ease-out)\r\n const easeProgress = 1 - Math.pow(1 - progress, 3);\r\n \r\n const currentX = startX + (distanceX * easeProgress);\r\n const currentY = startY + (distanceY * easeProgress);\r\n \r\n window.scrollTo(currentX, currentY);\r\n \r\n if (progress < 1) {\r\n requestAnimationFrame(animate);\r\n }\r\n }\r\n \r\n requestAnimationFrame(animate);\r\n}\r\n\r\n/**\r\n * Rola para um elemento específico\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param options - Opções de scroll\r\n *\r\n * @example\r\n * scrollToElement('#my-element'); // Scroll instantâneo\r\n * scrollToElement('.section', { smooth: true, offset: 100 }); // Scroll suave com offset\r\n */\r\nexport function scrollToElement(\r\n element: string | Element,\r\n options: {\r\n smooth?: boolean;\r\n offset?: number;\r\n behavior?: ScrollBehavior;\r\n } = {}\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const { smooth = false, offset = 0, behavior } = options;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const absoluteY = rect.top + window.scrollY - offset;\r\n \r\n window.scrollTo({\r\n left: 0,\r\n top: absoluteY,\r\n behavior: behavior || (smooth ? 'smooth' : 'auto')\r\n });\r\n}\r\n\r\n/**\r\n * Verifica se elemento está visível na viewport\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @param threshold - Limiar de visibilidade (0 a 1, padrão: 0)\r\n * @returns true se elemento estiver visível\r\n *\r\n * @example\r\n * isElementVisible('#my-element'); // true se elemento estiver na viewport\r\n * isElementVisible('.section', 0.5); // true se 50% do elemento estiver visível\r\n */\r\nexport function isElementVisible(\r\n element: string | Element,\r\n threshold: number = 0\r\n): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return false;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n const windowHeight = window.innerHeight;\r\n const windowWidth = window.innerWidth;\r\n \r\n const verticalThreshold = windowHeight * threshold;\r\n const horizontalThreshold = windowWidth * threshold;\r\n \r\n const isVisibleVertically = \r\n rect.bottom >= verticalThreshold && \r\n rect.top <= windowHeight - verticalThreshold;\r\n \r\n const isVisibleHorizontally = \r\n rect.right >= horizontalThreshold && \r\n rect.left <= windowWidth - horizontalThreshold;\r\n \r\n return isVisibleVertically && isVisibleHorizontally;\r\n}\r\n\r\n/**\r\n * Obtém a posição de um elemento em relação ao documento\r\n *\r\n * @param element - Elemento ou seletor CSS\r\n * @returns Posição { x, y } ou null se elemento não for encontrado\r\n *\r\n * @example\r\n * const position = getElementPosition('#my-element');\r\n * console.log('X:', position.x, 'Y:', position.y);\r\n */\r\nexport function getElementPosition(\r\n element: string | Element\r\n): { x: number; y: number } | null {\r\n if (typeof window === 'undefined') return null;\r\n \r\n let targetElement: Element | null;\r\n \r\n if (typeof element === 'string') {\r\n targetElement = document.querySelector(element);\r\n } else {\r\n targetElement = element;\r\n }\r\n \r\n if (!targetElement) return null;\r\n \r\n const rect = targetElement.getBoundingClientRect();\r\n \r\n return {\r\n x: rect.left + window.scrollX,\r\n y: rect.top + window.scrollY\r\n };\r\n}\r\n\r\n/**\r\n * Verifica se está em dispositivo móvel\r\n *\r\n * @returns true se for dispositivo móvel\r\n *\r\n * @example\r\n * if (isMobile()) {\r\n * // Aplicar layout mobile\r\n * }\r\n */\r\nexport function isMobile(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n // Verificar User Agent\r\n const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\r\n navigator.userAgent\r\n );\r\n \r\n // Verificar tamanho de tela (fallback)\r\n const isMobileScreen = window.innerWidth <= 768;\r\n \r\n return isMobileUA || isMobileScreen;\r\n}\r\n\r\n/**\r\n * Verifica se está em modo escuro\r\n *\r\n * @returns true se o sistema preferir modo escuro\r\n *\r\n * @example\r\n * if (isDarkMode()) {\r\n * // Aplicar tema escuro\r\n * }\r\n */\r\nexport function isDarkMode(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n \r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\n/**\r\n * Adiciona listener para mudanças no tema do sistema\r\n *\r\n * @param callback - Função chamada quando o tema muda\r\n * @returns Função para remover o listener\r\n *\r\n * @example\r\n * const unsubscribe = onDarkModeChange((isDark) => {\r\n * console.log('Theme changed:', isDark ? 'dark' : 'light');\r\n * });\r\n */\r\nexport function onDarkModeChange(\r\n callback: (isDark: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {};\r\n }\r\n \r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n \r\n const handleChange = (e: MediaQueryListEvent) => {\r\n callback(e.matches);\r\n };\r\n \r\n // Adicionar listener\r\n if (mediaQuery.addEventListener) {\r\n mediaQuery.addEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).addListener(handleChange);\r\n }\r\n \r\n // Retornar função de cleanup\r\n return () => {\r\n if (mediaQuery.removeEventListener) {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n } else {\r\n (mediaQuery as any).removeListener(handleChange);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Copia texto para a área de transferência\r\n *\r\n * @param text - Texto para copiar\r\n * @returns Promise que resolve para true se sucesso\r\n *\r\n * @example\r\n * copyToClipboard('Hello World').then(success => {\r\n * if (success) {\r\n * console.log('Texto copiado!');\r\n * }\r\n * });\r\n */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof window === 'undefined') return false;\r\n \r\n try {\r\n // Tentar usar a API moderna\r\n if (navigator.clipboard && window.isSecureContext) {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n }\r\n \r\n // Fallback para browsers mais antigos\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-999999px';\r\n textArea.style.top = '-999999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n \r\n const result = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n \r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Baixa um arquivo como blob\r\n *\r\n * @param blob - Blob para baixar\r\n * @param filename - Nome do arquivo\r\n *\r\n * @example\r\n * downloadFile(new Blob(['Hello World'], { type: 'text/plain' }), 'hello.txt');\r\n */\r\nexport function downloadFile(blob: Blob, filename: string): void {\r\n if (typeof window === 'undefined') return;\r\n \r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = filename;\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n","/**\r\n * Stats Formatting Utilities\r\n *\r\n * Utilitários universais para formatação de estatísticas e números.\r\n *\r\n * @module @rainersoft/utils/stats\r\n * @author Rainer Teixeira\r\n * @version 1.0.0\r\n */\r\n\r\n/**\r\n * Formata número grande com abreviação (1.5k, 2.3M, etc)\r\n *\r\n * @param num - Número para formatar\r\n * @returns String formatada com abreviação\r\n *\r\n * @example\r\n * ```ts\r\n * formatNumber(1500) // '1.5k'\r\n * formatNumber(2500000) // '2.5M'\r\n * formatNumber(999) // '999'\r\n * ```\r\n */\r\nexport function formatNumber(num: number): string {\r\n if (num >= 1000000) {\r\n return (num / 1000000).toFixed(1) + 'M';\r\n }\r\n if (num >= 1000) {\r\n return (num / 1000).toFixed(1) + 'k';\r\n }\r\n return num.toString();\r\n}\r\n\r\n/**\r\n * Calcula percentual de mudança entre dois valores\r\n *\r\n * @param current - Valor atual\r\n * @param previous - Valor anterior\r\n * @returns Percentual de mudança (arredondado)\r\n *\r\n * @example\r\n * ```ts\r\n * calculateChange(150, 100) // 50\r\n * calculateChange(80, 100) // -20\r\n * calculateChange(100, 0) // 100\r\n * ```\r\n */\r\nexport function calculateChange(current: number, previous: number): number {\r\n if (previous === 0) return 100;\r\n return Math.round(((current - previous) / previous) * 100);\r\n}\r\n\r\n/**\r\n * Formata percentual com sinal\r\n *\r\n * @param value - Valor do percentual\r\n * @param options - Opções de formatação\r\n * @returns String formatada com sinal e símbolo\r\n *\r\n * @example\r\n * ```ts\r\n * formatPercentage(25) // '+25%'\r\n * formatPercentage(-10) // '-10%'\r\n * formatPercentage(0) // '0%'\r\n * ```\r\n */\r\nexport function formatPercentage(\r\n value: number,\r\n options: { showSign?: boolean; decimals?: number } = {}\r\n): string {\r\n const { showSign = true, decimals = 0 } = options;\r\n \r\n const sign = showSign && value > 0 ? '+' : '';\r\n const formattedValue = value.toFixed(decimals);\r\n \r\n return `${sign}${formattedValue}%`;\r\n}\r\n\r\n/**\r\n * Gera dados de exemplo para gráficos\r\n *\r\n * @param days - Número de dias para gerar dados\r\n * @param locale - Idioma para formatação de datas\r\n * @returns Array de dados mock\r\n *\r\n * @example\r\n * ```ts\r\n * const data = generateMockChartData(7);\r\n * // [\r\n * // { date: '01/12', views: 1234, uniqueViews: 890, likes: 67, comments: 23 },\r\n * // ...\r\n * // ]\r\n * ```\r\n */\r\nexport function generateMockChartData(\r\n days: number,\r\n locale: string = 'pt-BR'\r\n): Array<Record<string, any>> {\r\n const data = [];\r\n const now = new Date();\r\n\r\n for (let i = days - 1; i >= 0; i--) {\r\n const date = new Date(now);\r\n date.setDate(date.getDate() - i);\r\n\r\n data.push({\r\n date: date.toLocaleDateString(locale, {\r\n day: '2-digit',\r\n month: '2-digit',\r\n }),\r\n views: Math.floor(Math.random() * 1000) + 500,\r\n uniqueViews: Math.floor(Math.random() * 700) + 300,\r\n likes: Math.floor(Math.random() * 100) + 50,\r\n comments: Math.floor(Math.random() * 50) + 10,\r\n shares: Math.floor(Math.random() * 30) + 5,\r\n });\r\n }\r\n\r\n return data;\r\n}\r\n\r\n/**\r\n * Agrupa dados por período (dia, semana, mês)\r\n *\r\n * @param data - Array de dados para agrupar\r\n * @param period - Período de agrupamento\r\n * @param dateField - Campo de data nos objetos\r\n * @returns Array de dados agrupados\r\n *\r\n * @example\r\n * ```ts\r\n * const grouped = groupDataByPeriod(data, 'week', 'date');\r\n * ```\r\n */\r\nexport function groupDataByPeriod<T extends Record<string, any>>(\r\n data: T[],\r\n // period: 'day' | 'week' | 'month' = 'day', // Pode ser usado futuramente para agrupamento\r\n // dateField: keyof T = 'date' as keyof T\r\n): T[] {\r\n // Implementação simplificada - pode ser expandida\r\n // Por enquanto, retorna os dados originais\r\n return data;\r\n}\r\n\r\n/**\r\n * Calcula médias móveis para suavizar dados\r\n *\r\n * @param data - Array de valores numéricos\r\n * @param window - Tamanho da janela de média móvel\r\n * @returns Array com médias móveis\r\n *\r\n * @example\r\n * ```ts\r\n * const smoothed = calculateMovingAverage([1, 2, 3, 4, 5], 3);\r\n * // [2, 3, 4] (médias de [1,2,3], [2,3,4], [3,4,5])\r\n * ```\r\n */\r\nexport function calculateMovingAverage(data: number[], window: number): number[] {\r\n const result: number[] = [];\r\n \r\n for (let i = window - 1; i < data.length; i++) {\r\n const sum = data.slice(i - window + 1, i + 1).reduce((a, b) => a + b, 0);\r\n result.push(sum / window);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Encontra valor máximo e mínimo em array de objetos\r\n *\r\n * @param data - Array de objetos\r\n * @param field - Campo para analisar\r\n * @returns Objeto com min e max\r\n *\r\n * @example\r\n * ```ts\r\n * const { min, max } = findMinMax(data, 'views');\r\n * ```\r\n */\r\nexport function findMinMax<T extends Record<string, any>>(\r\n data: T[],\r\n field: keyof T\r\n): { min: number; max: number } {\r\n const values = data.map(item => Number(item[field]) || 0);\r\n \r\n return {\r\n min: Math.min(...values),\r\n max: Math.max(...values)\r\n };\r\n}\r\n","/**\r\n * Helpers pt-BR\r\n *\r\n * Funções pré-configuradas para português brasileiro.\r\n * Facilitam o uso sem precisar passar locale em cada chamada.\r\n *\r\n * @module @rainersoft/utils/pt-br\r\n * @author Rainer Teixeira\r\n */\r\n\r\nimport {\r\n formatDate as formatDateBase,\r\n formatDateTime as formatDateTimeBase,\r\n formatRelativeDate as formatRelativeDateBase,\r\n} from './date';\r\n\r\nimport {\r\n formatCurrency as formatCurrencyBase,\r\n formatNumber as formatNumberBase,\r\n formatCompact as formatCompactBase,\r\n} from './number';\r\n\r\nimport {\r\n translateStatus as translateStatusBase,\r\n} from './status';\r\n\r\n// ============================================================================\r\n// DATE - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata data em português (Brasil)\r\n */\r\nexport function formatDate(\r\n date: string | Date,\r\n format: 'short' | 'long' | 'full' = 'long'\r\n): string {\r\n return formatDateBase(date, format, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data e hora em português (Brasil)\r\n */\r\nexport function formatDateTime(date: string | Date): string {\r\n return formatDateTimeBase(date, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata data relativa em português (Brasil)\r\n */\r\nexport function formatRelativeDate(date: string | Date): string {\r\n return formatRelativeDateBase(date, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// NUMBER - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Formata moeda em Real (BRL)\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n options?: Intl.NumberFormatOptions\r\n): string {\r\n return formatCurrencyBase(value, 'pt-BR', options);\r\n}\r\n\r\n/**\r\n * Formata número em português (Brasil)\r\n */\r\nexport function formatNumber(value: number, decimals = 0): string {\r\n return formatNumberBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n/**\r\n * Formata número compacto em português (Brasil)\r\n */\r\nexport function formatCompact(value: number, decimals = 1): string {\r\n return formatCompactBase(value, decimals, 'pt-BR');\r\n}\r\n\r\n// ============================================================================\r\n// STATUS - PT-BR\r\n// ============================================================================\r\n\r\n/**\r\n * Traduz status para português (Brasil)\r\n */\r\nexport function translateStatus(status: string): string {\r\n return translateStatusBase(status, 'pt-BR');\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rainersoft/utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
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
5
|
"author": {
|
|
7
6
|
"name": "Rainer Teixeira",
|
|
8
7
|
"email": "suporte@rainersoft.com.br"
|
|
@@ -56,16 +55,6 @@
|
|
|
56
55
|
"README.md",
|
|
57
56
|
"LICENSE"
|
|
58
57
|
],
|
|
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
58
|
"peerDependencies": {
|
|
70
59
|
"react": "^18.0.0 || ^19.0.0"
|
|
71
60
|
},
|
|
@@ -83,5 +72,15 @@
|
|
|
83
72
|
"ts-jest": "^29.1.2",
|
|
84
73
|
"tsup": "^8.5.1",
|
|
85
74
|
"typescript": "^5.9.3"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"dev": "tsup --watch",
|
|
78
|
+
"build": "tsup",
|
|
79
|
+
"test": "jest",
|
|
80
|
+
"test:watch": "jest --watch",
|
|
81
|
+
"test:coverage": "jest --coverage",
|
|
82
|
+
"lint": "eslint src --ext .ts",
|
|
83
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
84
|
+
"typecheck": "tsc --noEmit"
|
|
86
85
|
}
|
|
87
|
-
}
|
|
86
|
+
}
|