@rainersoft/utils 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/index.d.mts +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.js +63 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +54 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/date/index.d.mts +2 -9
- package/dist/date/index.d.ts +2 -9
- package/dist/index-BA11MtKk.d.ts +18 -0
- package/dist/index-BPYjFrM1.d.mts +18 -0
- package/dist/index-BfZE8XjJ.d.ts +18 -0
- package/dist/index-BuqX8-qm.d.mts +18 -0
- package/dist/index-DeZ9ZulO.d.mts +28 -0
- package/dist/index-DeZ9ZulO.d.ts +28 -0
- package/dist/index.d.mts +181 -49
- package/dist/index.d.ts +181 -49
- package/dist/index.js +897 -155
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +858 -154
- package/dist/index.mjs.map +1 -1
- package/dist/search/index.d.mts +12 -0
- package/dist/search/index.d.ts +12 -0
- package/dist/search/index.js +92 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/index.mjs +88 -0
- package/dist/search/index.mjs.map +1 -0
- package/dist/status/index.d.mts +2 -9
- package/dist/status/index.d.ts +2 -9
- package/dist/string/index.d.mts +6 -1
- package/dist/string/index.d.ts +6 -1
- package/dist/string/index.js +73 -1
- package/dist/string/index.js.map +1 -1
- package/dist/string/index.mjs +69 -2
- package/dist/string/index.mjs.map +1 -1
- package/package.json +102 -87
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useRef, useState, useCallback, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
5
|
var __export = (target, all) => {
|
|
5
6
|
for (var name in all)
|
|
6
7
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
8
|
};
|
|
9
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
8
10
|
|
|
9
11
|
// src/types.ts
|
|
10
12
|
var DEFAULT_LOCALE = "pt-BR";
|
|
@@ -14,140 +16,88 @@ var CURRENCY_MAP = {
|
|
|
14
16
|
"es-ES": "EUR"
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
// src/
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const words = name.trim().split(/\s+/);
|
|
23
|
-
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
24
|
-
return initials;
|
|
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;
|
|
19
|
+
// src/accessibility/index.ts
|
|
20
|
+
function hexToRgb(hex) {
|
|
21
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
22
|
+
if (!result) {
|
|
23
|
+
throw new Error(`Invalid hex color: ${hex}`);
|
|
39
24
|
}
|
|
25
|
+
return {
|
|
26
|
+
r: parseInt(result[1], 16),
|
|
27
|
+
g: parseInt(result[2], 16),
|
|
28
|
+
b: parseInt(result[3], 16)
|
|
29
|
+
};
|
|
40
30
|
}
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const colorHex = color.replace("#", "");
|
|
73
|
-
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
74
|
-
}
|
|
75
|
-
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
76
|
-
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
77
|
-
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
78
|
-
return parts.join("-");
|
|
79
|
-
}
|
|
80
|
-
function truncateText(text, maxLength, suffix = "...") {
|
|
81
|
-
if (!text || text.length <= maxLength) {
|
|
82
|
-
return text || "";
|
|
83
|
-
}
|
|
84
|
-
return text.substring(0, maxLength - suffix.length) + suffix;
|
|
85
|
-
}
|
|
86
|
-
function capitalize(text, options = {}) {
|
|
87
|
-
if (!text) return "";
|
|
88
|
-
const { firstWordOnly = false, lowerRest = false } = options;
|
|
89
|
-
if (firstWordOnly) {
|
|
90
|
-
return text.charAt(0).toUpperCase() + (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));
|
|
91
|
-
}
|
|
92
|
-
if (lowerRest) {
|
|
93
|
-
return text.replace(/\b\w/g, (char) => char.toUpperCase()).toLowerCase();
|
|
94
|
-
}
|
|
95
|
-
return text.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
96
|
-
}
|
|
97
|
-
function cleanText(text, allowSpaces = true) {
|
|
98
|
-
if (!text) return "";
|
|
99
|
-
const pattern = allowSpaces ? /[^\w\s]/g : /[^\w]/g;
|
|
100
|
-
return text.replace(pattern, "");
|
|
101
|
-
}
|
|
102
|
-
function countWords(text) {
|
|
103
|
-
if (!text || !text.trim()) {
|
|
104
|
-
return 0;
|
|
31
|
+
function getLuminance(r, g, b) {
|
|
32
|
+
const [rs, gs, bs] = [r, g, b].map((val) => {
|
|
33
|
+
const v = val / 255;
|
|
34
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
35
|
+
});
|
|
36
|
+
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
37
|
+
}
|
|
38
|
+
function getContrast(color1, color2) {
|
|
39
|
+
const rgb1 = hexToRgb(color1);
|
|
40
|
+
const rgb2 = hexToRgb(color2);
|
|
41
|
+
const lum1 = getLuminance(rgb1.r, rgb1.g, rgb1.b);
|
|
42
|
+
const lum2 = getLuminance(rgb2.r, rgb2.g, rgb2.b);
|
|
43
|
+
const lighter = Math.max(lum1, lum2);
|
|
44
|
+
const darker = Math.min(lum1, lum2);
|
|
45
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
46
|
+
}
|
|
47
|
+
function getContrastInfo(foreground, background) {
|
|
48
|
+
const contrast = getContrast(foreground, background);
|
|
49
|
+
const meetsAA = contrast >= 4.5;
|
|
50
|
+
const meetsAALarge = contrast >= 3;
|
|
51
|
+
const meetsAAA = contrast >= 7;
|
|
52
|
+
const meetsAAALarge = contrast >= 4.5;
|
|
53
|
+
let level = "Fail";
|
|
54
|
+
if (meetsAAA) {
|
|
55
|
+
level = "AAA";
|
|
56
|
+
} else if (meetsAAALarge) {
|
|
57
|
+
level = "AAA Large";
|
|
58
|
+
} else if (meetsAA) {
|
|
59
|
+
level = "AA";
|
|
60
|
+
} else if (meetsAALarge) {
|
|
61
|
+
level = "AA Large";
|
|
105
62
|
}
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
63
|
+
return {
|
|
64
|
+
contrast,
|
|
65
|
+
meetsAA,
|
|
66
|
+
meetsAALarge,
|
|
67
|
+
meetsAAA,
|
|
68
|
+
meetsAAALarge,
|
|
69
|
+
level
|
|
70
|
+
};
|
|
110
71
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
let
|
|
115
|
-
|
|
116
|
-
|
|
72
|
+
function validateContrast(foreground, background, options = {}) {
|
|
73
|
+
const { requireAAA = false, largeText = false } = options;
|
|
74
|
+
const info = getContrastInfo(foreground, background);
|
|
75
|
+
let valid = false;
|
|
76
|
+
let message = "";
|
|
77
|
+
if (requireAAA) {
|
|
78
|
+
valid = largeText ? info.meetsAAALarge : info.meetsAAA;
|
|
79
|
+
message = valid ? `Contraste v\xE1lido (WCAG AAA${largeText ? " - Texto Grande" : ""})` : `Contraste insuficiente para WCAG AAA${largeText ? " - Texto Grande" : ""}. Requerido: ${largeText ? "4.5:1" : "7:1"}, atual: ${info.contrast.toFixed(2)}:1`;
|
|
117
80
|
} else {
|
|
118
|
-
|
|
81
|
+
valid = largeText ? info.meetsAALarge : info.meetsAA;
|
|
82
|
+
message = valid ? `Contraste v\xE1lido (WCAG AA${largeText ? " - Texto Grande" : ""})` : `Contraste insuficiente para WCAG AA${largeText ? " - Texto Grande" : ""}. Requerido: ${largeText ? "3:1" : "4.5:1"}, atual: ${info.contrast.toFixed(2)}:1`;
|
|
119
83
|
}
|
|
120
|
-
return
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (!node) return "";
|
|
127
|
-
let result = "";
|
|
128
|
-
if (node.text) {
|
|
129
|
-
result += node.text + " ";
|
|
130
|
-
}
|
|
131
|
-
if (Array.isArray(node.content)) {
|
|
132
|
-
result += node.content.map(extractText).join(" ");
|
|
133
|
-
}
|
|
134
|
-
return result;
|
|
135
|
-
};
|
|
136
|
-
text = extractText(content);
|
|
137
|
-
} else if (typeof content === "string") {
|
|
138
|
-
text = content.replace(/<[^>]*>/g, "");
|
|
139
|
-
}
|
|
140
|
-
const words = text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
141
|
-
const time = Math.ceil(words / wordsPerMinute);
|
|
142
|
-
return time > 0 ? time : 1;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// src/string/index.ts
|
|
146
|
-
function textToSlug(text) {
|
|
147
|
-
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
84
|
+
return {
|
|
85
|
+
valid,
|
|
86
|
+
level: info.level,
|
|
87
|
+
contrast: info.contrast,
|
|
88
|
+
message
|
|
89
|
+
};
|
|
148
90
|
}
|
|
149
91
|
|
|
150
92
|
// src/date/index.ts
|
|
93
|
+
var date_exports = {};
|
|
94
|
+
__export(date_exports, {
|
|
95
|
+
formatDate: () => formatDate,
|
|
96
|
+
formatDateTime: () => formatDateTime,
|
|
97
|
+
formatRelativeDate: () => formatRelativeDate,
|
|
98
|
+
isValidDate: () => isValidDate,
|
|
99
|
+
toISOString: () => toISOString
|
|
100
|
+
});
|
|
151
101
|
var RELATIVE_TEXTS = {
|
|
152
102
|
"pt-BR": {
|
|
153
103
|
now: "agora",
|
|
@@ -240,31 +190,14 @@ function isValidDate(date) {
|
|
|
240
190
|
return date instanceof Date && !isNaN(date.getTime());
|
|
241
191
|
}
|
|
242
192
|
|
|
243
|
-
// src/number/index.ts
|
|
244
|
-
function formatCurrency(value, locale = DEFAULT_LOCALE, options) {
|
|
245
|
-
const currency = CURRENCY_MAP[locale];
|
|
246
|
-
return new Intl.NumberFormat(locale, {
|
|
247
|
-
style: "currency",
|
|
248
|
-
currency,
|
|
249
|
-
...options
|
|
250
|
-
}).format(value);
|
|
251
|
-
}
|
|
252
|
-
function formatNumber(value, decimals = 0, locale = DEFAULT_LOCALE) {
|
|
253
|
-
return new Intl.NumberFormat(locale, {
|
|
254
|
-
minimumFractionDigits: decimals,
|
|
255
|
-
maximumFractionDigits: decimals
|
|
256
|
-
}).format(value);
|
|
257
|
-
}
|
|
258
|
-
function formatCompact(value, decimals = 1, locale = DEFAULT_LOCALE) {
|
|
259
|
-
return new Intl.NumberFormat(locale, {
|
|
260
|
-
notation: "compact",
|
|
261
|
-
compactDisplay: "short",
|
|
262
|
-
minimumFractionDigits: decimals,
|
|
263
|
-
maximumFractionDigits: decimals
|
|
264
|
-
}).format(value);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
193
|
// src/status/index.ts
|
|
194
|
+
var status_exports = {};
|
|
195
|
+
__export(status_exports, {
|
|
196
|
+
getStatusColor: () => getStatusColor,
|
|
197
|
+
getStatusVariant: () => getStatusVariant,
|
|
198
|
+
translatePostStatus: () => translatePostStatus,
|
|
199
|
+
translateStatus: () => translateStatus
|
|
200
|
+
});
|
|
268
201
|
var STATUS_TRANSLATIONS = {
|
|
269
202
|
"pt-BR": {
|
|
270
203
|
// Estados de conteúdo
|
|
@@ -625,6 +558,198 @@ function validateMessage(message, options = {}, locale = DEFAULT_LOCALE) {
|
|
|
625
558
|
}, locale);
|
|
626
559
|
}
|
|
627
560
|
|
|
561
|
+
// src/content/tiptap-utils.ts
|
|
562
|
+
function extractTextFromTiptap(content) {
|
|
563
|
+
function extractFromNode(node) {
|
|
564
|
+
if ("text" in node && typeof node.text === "string") {
|
|
565
|
+
return node.text;
|
|
566
|
+
}
|
|
567
|
+
if ("content" in node && Array.isArray(node.content)) {
|
|
568
|
+
return node.content.map((child) => extractFromNode(child)).join(" ");
|
|
569
|
+
}
|
|
570
|
+
return "";
|
|
571
|
+
}
|
|
572
|
+
return extractFromNode(content).trim();
|
|
573
|
+
}
|
|
574
|
+
function generateExcerpt(content, maxLength = 160) {
|
|
575
|
+
const text = extractTextFromTiptap(content);
|
|
576
|
+
if (text.length <= maxLength) {
|
|
577
|
+
return text;
|
|
578
|
+
}
|
|
579
|
+
return text.substring(0, maxLength).trim() + "...";
|
|
580
|
+
}
|
|
581
|
+
function createEmptyTiptapContent() {
|
|
582
|
+
return {
|
|
583
|
+
type: "doc",
|
|
584
|
+
content: []
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function isContentEmpty(content) {
|
|
588
|
+
if (!content || !content.content || content.content.length === 0) {
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
const text = extractTextFromTiptap(content);
|
|
592
|
+
return text.trim().length === 0;
|
|
593
|
+
}
|
|
594
|
+
function countWords(content) {
|
|
595
|
+
const text = extractTextFromTiptap(content);
|
|
596
|
+
return text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
597
|
+
}
|
|
598
|
+
function countCharacters(content) {
|
|
599
|
+
return extractTextFromTiptap(content).length;
|
|
600
|
+
}
|
|
601
|
+
function getReadingTime(content, wordsPerMinute = 200) {
|
|
602
|
+
const wordCount = countWords(content);
|
|
603
|
+
return Math.ceil(wordCount / wordsPerMinute);
|
|
604
|
+
}
|
|
605
|
+
function getContentStats(content) {
|
|
606
|
+
const wordCount = countWords(content);
|
|
607
|
+
const characterCount = extractTextFromTiptap(content).length;
|
|
608
|
+
const readingTime = getReadingTime(content);
|
|
609
|
+
return {
|
|
610
|
+
wordCount,
|
|
611
|
+
characterCount,
|
|
612
|
+
readingTime
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
function containsText(content, searchText) {
|
|
616
|
+
const text = extractTextFromTiptap(content).toLowerCase();
|
|
617
|
+
return text.includes(searchText.toLowerCase());
|
|
618
|
+
}
|
|
619
|
+
function replaceText(content, searchText, replaceText2) {
|
|
620
|
+
function processNode(node) {
|
|
621
|
+
const newNode = { ...node };
|
|
622
|
+
if ("text" in node && typeof node.text === "string") {
|
|
623
|
+
newNode.text = node.text.replace(
|
|
624
|
+
new RegExp(searchText, "gi"),
|
|
625
|
+
replaceText2
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
if ("content" in node && Array.isArray(node.content)) {
|
|
629
|
+
newNode.content = node.content.map((child) => processNode(child));
|
|
630
|
+
}
|
|
631
|
+
return newNode;
|
|
632
|
+
}
|
|
633
|
+
const newContent = {
|
|
634
|
+
...content,
|
|
635
|
+
content: content.content.map((node) => processNode(node))
|
|
636
|
+
};
|
|
637
|
+
return newContent;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/color/index.ts
|
|
641
|
+
function hexToRgb2(hex) {
|
|
642
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
643
|
+
if (!result) {
|
|
644
|
+
throw new Error(`Invalid hex color: ${hex}`);
|
|
645
|
+
}
|
|
646
|
+
return {
|
|
647
|
+
r: parseInt(result[1], 16),
|
|
648
|
+
g: parseInt(result[2], 16),
|
|
649
|
+
b: parseInt(result[3], 16)
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function rgbToHex(r, g, b) {
|
|
653
|
+
const toHex = (n) => {
|
|
654
|
+
const hex = Math.round(Math.max(0, Math.min(255, n))).toString(16);
|
|
655
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
656
|
+
};
|
|
657
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
658
|
+
}
|
|
659
|
+
function hexToHsl(hex) {
|
|
660
|
+
const rgb = hexToRgb2(hex);
|
|
661
|
+
const r = rgb.r / 255;
|
|
662
|
+
const g = rgb.g / 255;
|
|
663
|
+
const b = rgb.b / 255;
|
|
664
|
+
const max = Math.max(r, g, b);
|
|
665
|
+
const min = Math.min(r, g, b);
|
|
666
|
+
let h = 0;
|
|
667
|
+
let s = 0;
|
|
668
|
+
const l = (max + min) / 2;
|
|
669
|
+
if (max !== min) {
|
|
670
|
+
const d = max - min;
|
|
671
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
672
|
+
switch (max) {
|
|
673
|
+
case r:
|
|
674
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
675
|
+
break;
|
|
676
|
+
case g:
|
|
677
|
+
h = ((b - r) / d + 2) / 6;
|
|
678
|
+
break;
|
|
679
|
+
case b:
|
|
680
|
+
h = ((r - g) / d + 4) / 6;
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return {
|
|
685
|
+
h: Math.round(h * 360),
|
|
686
|
+
s: Math.round(s * 100),
|
|
687
|
+
l: Math.round(l * 100)
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
function hslToHex(h, s, l) {
|
|
691
|
+
h = h / 360;
|
|
692
|
+
s = s / 100;
|
|
693
|
+
l = l / 100;
|
|
694
|
+
let r, g, b;
|
|
695
|
+
if (s === 0) {
|
|
696
|
+
r = g = b = l;
|
|
697
|
+
} else {
|
|
698
|
+
const hue2rgb = (p2, q2, t) => {
|
|
699
|
+
if (t < 0) t += 1;
|
|
700
|
+
if (t > 1) t -= 1;
|
|
701
|
+
if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
|
|
702
|
+
if (t < 1 / 2) return q2;
|
|
703
|
+
if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
|
|
704
|
+
return p2;
|
|
705
|
+
};
|
|
706
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
707
|
+
const p = 2 * l - q;
|
|
708
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
709
|
+
g = hue2rgb(p, q, h);
|
|
710
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
711
|
+
}
|
|
712
|
+
return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
|
|
713
|
+
}
|
|
714
|
+
function adjustBrightness(hex, amount) {
|
|
715
|
+
const hsl = hexToHsl(hex);
|
|
716
|
+
const newL = Math.max(0, Math.min(100, hsl.l + amount));
|
|
717
|
+
return hslToHex(hsl.h, hsl.s, newL);
|
|
718
|
+
}
|
|
719
|
+
function adjustSaturation(hex, amount) {
|
|
720
|
+
const hsl = hexToHsl(hex);
|
|
721
|
+
const newS = Math.max(0, Math.min(100, hsl.s + amount));
|
|
722
|
+
return hslToHex(hsl.h, newS, hsl.l);
|
|
723
|
+
}
|
|
724
|
+
function adjustHue(hex, degrees) {
|
|
725
|
+
const hsl = hexToHsl(hex);
|
|
726
|
+
const newH = (hsl.h + degrees) % 360;
|
|
727
|
+
return hslToHex(newH < 0 ? newH + 360 : newH, hsl.s, hsl.l);
|
|
728
|
+
}
|
|
729
|
+
function lighten(hex, amount) {
|
|
730
|
+
return adjustBrightness(hex, amount);
|
|
731
|
+
}
|
|
732
|
+
function darken(hex, amount) {
|
|
733
|
+
return adjustBrightness(hex, -amount);
|
|
734
|
+
}
|
|
735
|
+
function hexToRgba(hex, alpha) {
|
|
736
|
+
const rgb = hexToRgb2(hex);
|
|
737
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
|
738
|
+
}
|
|
739
|
+
function getComplementary(hex) {
|
|
740
|
+
return adjustHue(hex, 180);
|
|
741
|
+
}
|
|
742
|
+
function getAnalogousPalette(hex, count = 5) {
|
|
743
|
+
const hsl = hexToHsl(hex);
|
|
744
|
+
const step = 30;
|
|
745
|
+
const palette = [];
|
|
746
|
+
for (let i = 0; i < count; i++) {
|
|
747
|
+
const hue = (hsl.h + (i - Math.floor(count / 2)) * step) % 360;
|
|
748
|
+
palette.push(hslToHex(hue < 0 ? hue + 360 : hue, hsl.s, hsl.l));
|
|
749
|
+
}
|
|
750
|
+
return palette;
|
|
751
|
+
}
|
|
752
|
+
|
|
628
753
|
// src/dom/index.ts
|
|
629
754
|
function prefersReducedMotion() {
|
|
630
755
|
if (typeof window === "undefined") return false;
|
|
@@ -802,9 +927,314 @@ function downloadFile(blob, filename) {
|
|
|
802
927
|
document.body.removeChild(link);
|
|
803
928
|
URL.revokeObjectURL(url);
|
|
804
929
|
}
|
|
930
|
+
var DEFAULT_CONFIG = {
|
|
931
|
+
autoRefresh: true,
|
|
932
|
+
refreshInterval: 15 * 60 * 1e3,
|
|
933
|
+
// 15 minutes
|
|
934
|
+
tokenStorageKey: "auth_token",
|
|
935
|
+
userStorageKey: "auth_user",
|
|
936
|
+
apiEndpoint: "/api/auth",
|
|
937
|
+
onAuthChange: () => {
|
|
938
|
+
},
|
|
939
|
+
onError: () => {
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
var AuthStorage = class {
|
|
943
|
+
static setItem(key, value) {
|
|
944
|
+
if (!this.isClient) return;
|
|
945
|
+
try {
|
|
946
|
+
localStorage.setItem(key, value);
|
|
947
|
+
} catch (error) {
|
|
948
|
+
console.warn("Failed to save to localStorage:", error);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
static getItem(key) {
|
|
952
|
+
if (!this.isClient) return null;
|
|
953
|
+
try {
|
|
954
|
+
return localStorage.getItem(key);
|
|
955
|
+
} catch (error) {
|
|
956
|
+
console.warn("Failed to read from localStorage:", error);
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
static removeItem(key) {
|
|
961
|
+
if (!this.isClient) return;
|
|
962
|
+
try {
|
|
963
|
+
localStorage.removeItem(key);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
console.warn("Failed to remove from localStorage:", error);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
static setUser(user, key) {
|
|
969
|
+
this.setItem(key, JSON.stringify(user));
|
|
970
|
+
}
|
|
971
|
+
static getUser(key) {
|
|
972
|
+
const data = this.getItem(key);
|
|
973
|
+
if (!data) return null;
|
|
974
|
+
try {
|
|
975
|
+
return JSON.parse(data);
|
|
976
|
+
} catch {
|
|
977
|
+
this.removeItem(key);
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
static removeUser(key) {
|
|
982
|
+
this.removeItem(key);
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
__publicField(AuthStorage, "isClient", typeof window !== "undefined");
|
|
986
|
+
var TokenManager = class {
|
|
987
|
+
static decodeToken(token) {
|
|
988
|
+
try {
|
|
989
|
+
const payload = token.split(".")[1];
|
|
990
|
+
const decoded = atob(payload);
|
|
991
|
+
return JSON.parse(decoded);
|
|
992
|
+
} catch {
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
static isTokenExpired(token) {
|
|
997
|
+
const decoded = this.decodeToken(token);
|
|
998
|
+
if (!decoded) return true;
|
|
999
|
+
const now = Date.now() / 1e3;
|
|
1000
|
+
return decoded.exp < now;
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
function useAuth(config = {}) {
|
|
1004
|
+
const configRef = useRef({ ...DEFAULT_CONFIG, ...config });
|
|
1005
|
+
const cfg = configRef.current;
|
|
1006
|
+
const [user, setUser] = useState(null);
|
|
1007
|
+
const [loading, setLoading] = useState(false);
|
|
1008
|
+
const [error, setError] = useState(null);
|
|
1009
|
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
1010
|
+
const refreshTimerRef = useRef(null);
|
|
1011
|
+
const storeToken = useCallback((token, refreshToken2) => {
|
|
1012
|
+
AuthStorage.setItem(cfg.tokenStorageKey, token);
|
|
1013
|
+
if (refreshToken2) {
|
|
1014
|
+
AuthStorage.setItem(`${cfg.tokenStorageKey}_refresh`, refreshToken2);
|
|
1015
|
+
}
|
|
1016
|
+
}, [cfg.tokenStorageKey]);
|
|
1017
|
+
const getStoredToken = useCallback(() => {
|
|
1018
|
+
return AuthStorage.getItem(cfg.tokenStorageKey);
|
|
1019
|
+
}, [cfg.tokenStorageKey]);
|
|
1020
|
+
const clearTokens = useCallback(() => {
|
|
1021
|
+
AuthStorage.removeItem(cfg.tokenStorageKey);
|
|
1022
|
+
AuthStorage.removeItem(`${cfg.tokenStorageKey}_refresh`);
|
|
1023
|
+
}, [cfg.tokenStorageKey]);
|
|
1024
|
+
const apiCall = useCallback(async (endpoint, options = {}) => {
|
|
1025
|
+
const token = getStoredToken();
|
|
1026
|
+
const url = `${cfg.apiEndpoint}${endpoint}`;
|
|
1027
|
+
const response = await fetch(url, {
|
|
1028
|
+
...options,
|
|
1029
|
+
headers: {
|
|
1030
|
+
"Content-Type": "application/json",
|
|
1031
|
+
...token && { Authorization: `Bearer ${token}` },
|
|
1032
|
+
...options.headers
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
if (!response.ok) {
|
|
1036
|
+
const error2 = await response.text();
|
|
1037
|
+
throw new Error(error2 || `HTTP ${response.status}`);
|
|
1038
|
+
}
|
|
1039
|
+
return response.json();
|
|
1040
|
+
}, [cfg.apiEndpoint, getStoredToken]);
|
|
1041
|
+
const login = useCallback(async (credentials) => {
|
|
1042
|
+
setLoading(true);
|
|
1043
|
+
setError(null);
|
|
1044
|
+
try {
|
|
1045
|
+
const response = await apiCall("/login", {
|
|
1046
|
+
method: "POST",
|
|
1047
|
+
body: JSON.stringify(credentials)
|
|
1048
|
+
});
|
|
1049
|
+
if (response.success && response.user && response.token) {
|
|
1050
|
+
setUser(response.user);
|
|
1051
|
+
setIsAuthenticated(true);
|
|
1052
|
+
storeToken(response.token, response.refreshToken);
|
|
1053
|
+
if (cfg.onAuthChange) {
|
|
1054
|
+
cfg.onAuthChange(response.user);
|
|
1055
|
+
}
|
|
1056
|
+
return { success: true, user: response.user, token: response.token };
|
|
1057
|
+
} else {
|
|
1058
|
+
const errorMsg = response.error || "Login failed";
|
|
1059
|
+
setError(errorMsg);
|
|
1060
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1061
|
+
return { success: false, error: errorMsg };
|
|
1062
|
+
}
|
|
1063
|
+
} catch (error2) {
|
|
1064
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Login failed";
|
|
1065
|
+
setError(errorMsg);
|
|
1066
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1067
|
+
return { success: false, error: errorMsg };
|
|
1068
|
+
} finally {
|
|
1069
|
+
setLoading(false);
|
|
1070
|
+
}
|
|
1071
|
+
}, [apiCall, setUser, storeToken, cfg]);
|
|
1072
|
+
const logout = useCallback(async (options = {}) => {
|
|
1073
|
+
try {
|
|
1074
|
+
if (options.invalidateAllSessions) {
|
|
1075
|
+
await apiCall("/logout", { method: "POST" });
|
|
1076
|
+
}
|
|
1077
|
+
} catch (error2) {
|
|
1078
|
+
console.warn("Logout API call failed:", error2);
|
|
1079
|
+
} finally {
|
|
1080
|
+
setUser(null);
|
|
1081
|
+
setIsAuthenticated(false);
|
|
1082
|
+
clearTokens();
|
|
1083
|
+
if (refreshTimerRef.current) {
|
|
1084
|
+
clearInterval(refreshTimerRef.current);
|
|
1085
|
+
refreshTimerRef.current = null;
|
|
1086
|
+
}
|
|
1087
|
+
if (cfg.onAuthChange) {
|
|
1088
|
+
cfg.onAuthChange(null);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}, [apiCall, clearTokens, cfg]);
|
|
1092
|
+
const register = useCallback(async (userData) => {
|
|
1093
|
+
setLoading(true);
|
|
1094
|
+
setError(null);
|
|
1095
|
+
try {
|
|
1096
|
+
const response = await apiCall("/register", {
|
|
1097
|
+
method: "POST",
|
|
1098
|
+
body: JSON.stringify(userData)
|
|
1099
|
+
});
|
|
1100
|
+
if (response.success && response.user && response.token) {
|
|
1101
|
+
setUser(response.user);
|
|
1102
|
+
setIsAuthenticated(true);
|
|
1103
|
+
storeToken(response.token, response.refreshToken);
|
|
1104
|
+
if (cfg.onAuthChange) {
|
|
1105
|
+
cfg.onAuthChange(response.user);
|
|
1106
|
+
}
|
|
1107
|
+
return { success: true, user: response.user, token: response.token };
|
|
1108
|
+
} else {
|
|
1109
|
+
const errorMsg = response.error || "Registration failed";
|
|
1110
|
+
setError(errorMsg);
|
|
1111
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1112
|
+
return { success: false, error: errorMsg };
|
|
1113
|
+
}
|
|
1114
|
+
} catch (error2) {
|
|
1115
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Registration failed";
|
|
1116
|
+
setError(errorMsg);
|
|
1117
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1118
|
+
return { success: false, error: errorMsg };
|
|
1119
|
+
} finally {
|
|
1120
|
+
setLoading(false);
|
|
1121
|
+
}
|
|
1122
|
+
}, [apiCall, setUser, storeToken, cfg]);
|
|
1123
|
+
const updateProfile = useCallback(async (data) => {
|
|
1124
|
+
if (!user) {
|
|
1125
|
+
const error2 = "No user logged in";
|
|
1126
|
+
setError(error2);
|
|
1127
|
+
if (cfg.onError) cfg.onError(error2);
|
|
1128
|
+
return { success: false, error: error2 };
|
|
1129
|
+
}
|
|
1130
|
+
setLoading(true);
|
|
1131
|
+
setError(null);
|
|
1132
|
+
try {
|
|
1133
|
+
const response = await apiCall("/profile", {
|
|
1134
|
+
method: "PUT",
|
|
1135
|
+
body: JSON.stringify(data)
|
|
1136
|
+
});
|
|
1137
|
+
if (response.success && response.user) {
|
|
1138
|
+
setUser(response.user);
|
|
1139
|
+
if (cfg.onAuthChange) {
|
|
1140
|
+
cfg.onAuthChange(response.user);
|
|
1141
|
+
}
|
|
1142
|
+
return { success: true, user: response.user };
|
|
1143
|
+
} else {
|
|
1144
|
+
const errorMsg = response.error || "Profile update failed";
|
|
1145
|
+
setError(errorMsg);
|
|
1146
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1147
|
+
return { success: false, error: errorMsg };
|
|
1148
|
+
}
|
|
1149
|
+
} catch (error2) {
|
|
1150
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Profile update failed";
|
|
1151
|
+
setError(errorMsg);
|
|
1152
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1153
|
+
return { success: false, error: errorMsg };
|
|
1154
|
+
} finally {
|
|
1155
|
+
setLoading(false);
|
|
1156
|
+
}
|
|
1157
|
+
}, [apiCall, user, setUser, cfg]);
|
|
1158
|
+
const refreshToken = useCallback(async () => {
|
|
1159
|
+
const refreshToken2 = AuthStorage.getItem(`${cfg.tokenStorageKey}_refresh`);
|
|
1160
|
+
if (!refreshToken2) {
|
|
1161
|
+
return { success: false, error: "No refresh token available" };
|
|
1162
|
+
}
|
|
1163
|
+
try {
|
|
1164
|
+
const response = await apiCall("/refresh", {
|
|
1165
|
+
method: "POST",
|
|
1166
|
+
body: JSON.stringify({ refreshToken: refreshToken2 })
|
|
1167
|
+
});
|
|
1168
|
+
if (response.success && response.token && response.user) {
|
|
1169
|
+
setUser(response.user);
|
|
1170
|
+
storeToken(response.token, response.refreshToken);
|
|
1171
|
+
if (cfg.onAuthChange) {
|
|
1172
|
+
cfg.onAuthChange(response.user);
|
|
1173
|
+
}
|
|
1174
|
+
return { success: true, user: response.user, token: response.token };
|
|
1175
|
+
} else {
|
|
1176
|
+
await logout();
|
|
1177
|
+
return { success: false, error: "Session expired" };
|
|
1178
|
+
}
|
|
1179
|
+
} catch (error2) {
|
|
1180
|
+
await logout();
|
|
1181
|
+
return { success: false, error: "Session expired" };
|
|
1182
|
+
}
|
|
1183
|
+
}, [apiCall, setUser, storeToken, logout, cfg]);
|
|
1184
|
+
const resetError = useCallback(() => {
|
|
1185
|
+
setError(null);
|
|
1186
|
+
}, []);
|
|
1187
|
+
useEffect(() => {
|
|
1188
|
+
const token = getStoredToken();
|
|
1189
|
+
const storedUser = AuthStorage.getUser(cfg.userStorageKey);
|
|
1190
|
+
if (token && storedUser && !TokenManager.isTokenExpired(token)) {
|
|
1191
|
+
setUser(storedUser);
|
|
1192
|
+
setIsAuthenticated(true);
|
|
1193
|
+
if (cfg.onAuthChange) {
|
|
1194
|
+
cfg.onAuthChange(storedUser);
|
|
1195
|
+
}
|
|
1196
|
+
} else if (token && TokenManager.isTokenExpired(token)) {
|
|
1197
|
+
refreshToken();
|
|
1198
|
+
} else {
|
|
1199
|
+
setLoading(false);
|
|
1200
|
+
}
|
|
1201
|
+
return () => {
|
|
1202
|
+
if (refreshTimerRef.current) {
|
|
1203
|
+
clearInterval(refreshTimerRef.current);
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
}, []);
|
|
1207
|
+
return {
|
|
1208
|
+
user,
|
|
1209
|
+
loading,
|
|
1210
|
+
error,
|
|
1211
|
+
isAuthenticated,
|
|
1212
|
+
login,
|
|
1213
|
+
logout,
|
|
1214
|
+
register,
|
|
1215
|
+
updateProfile,
|
|
1216
|
+
refreshToken,
|
|
1217
|
+
resetError
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function useIsAuthenticated() {
|
|
1221
|
+
const { isAuthenticated } = useAuth();
|
|
1222
|
+
return isAuthenticated;
|
|
1223
|
+
}
|
|
1224
|
+
function useCurrentUser() {
|
|
1225
|
+
const { user } = useAuth();
|
|
1226
|
+
return user;
|
|
1227
|
+
}
|
|
1228
|
+
function useHasRole(role) {
|
|
1229
|
+
const { user } = useAuth();
|
|
1230
|
+
return user?.role === role;
|
|
1231
|
+
}
|
|
1232
|
+
function useIsAdmin() {
|
|
1233
|
+
return useHasRole("admin" /* ADMIN */);
|
|
1234
|
+
}
|
|
805
1235
|
|
|
806
1236
|
// src/stats/index.ts
|
|
807
|
-
function
|
|
1237
|
+
function formatNumber(num) {
|
|
808
1238
|
if (num >= 1e6) {
|
|
809
1239
|
return (num / 1e6).toFixed(1) + "M";
|
|
810
1240
|
}
|
|
@@ -862,7 +1292,18 @@ function findMinMax(data, field) {
|
|
|
862
1292
|
};
|
|
863
1293
|
}
|
|
864
1294
|
|
|
865
|
-
// src/
|
|
1295
|
+
// src/authentication/index.ts
|
|
1296
|
+
var authentication_exports = {};
|
|
1297
|
+
__export(authentication_exports, {
|
|
1298
|
+
getRefreshToken: () => getRefreshToken,
|
|
1299
|
+
getToken: () => getToken,
|
|
1300
|
+
getTokens: () => getTokens,
|
|
1301
|
+
hasToken: () => hasToken,
|
|
1302
|
+
removeToken: () => removeToken,
|
|
1303
|
+
setRefreshToken: () => setRefreshToken,
|
|
1304
|
+
setToken: () => setToken,
|
|
1305
|
+
setTokens: () => setTokens
|
|
1306
|
+
});
|
|
866
1307
|
var TOKEN_KEY = "auth_token";
|
|
867
1308
|
var REFRESH_TOKEN_KEY = "refresh_token";
|
|
868
1309
|
var getToken = () => {
|
|
@@ -997,6 +1438,109 @@ function calculateSimilarity(str1, str2) {
|
|
|
997
1438
|
const similarity = common / Math.max(str1.length, str2.length);
|
|
998
1439
|
return similarity;
|
|
999
1440
|
}
|
|
1441
|
+
|
|
1442
|
+
// src/string/index.ts
|
|
1443
|
+
function textToSlug(text) {
|
|
1444
|
+
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/^-+|-+$/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
1445
|
+
}
|
|
1446
|
+
function truncate(text, maxLength, suffix = "...") {
|
|
1447
|
+
if (text.length <= maxLength) return text;
|
|
1448
|
+
return text.slice(0, maxLength - suffix.length) + suffix;
|
|
1449
|
+
}
|
|
1450
|
+
function getInitials(name, maxInitials = 2) {
|
|
1451
|
+
return name.split(" ").filter((word) => word.length > 0).map((word) => word[0]).join("").toUpperCase().slice(0, maxInitials);
|
|
1452
|
+
}
|
|
1453
|
+
function formatPhone(phone) {
|
|
1454
|
+
const digits = phone.replace(/\D/g, "");
|
|
1455
|
+
if (digits.length === 11) {
|
|
1456
|
+
return digits.replace(/(\d{2})(\d{5})(\d{4})/, "($1) $2-$3");
|
|
1457
|
+
}
|
|
1458
|
+
return digits.replace(/(\d{2})(\d{4})(\d{4})/, "($1) $2-$3");
|
|
1459
|
+
}
|
|
1460
|
+
function formatCPF(cpf) {
|
|
1461
|
+
const digits = cpf.replace(/\D/g, "");
|
|
1462
|
+
return digits.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
|
|
1463
|
+
}
|
|
1464
|
+
function formatCNPJ(cnpj) {
|
|
1465
|
+
const digits = cnpj.replace(/\D/g, "");
|
|
1466
|
+
return digits.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
|
|
1467
|
+
}
|
|
1468
|
+
function isCPF(cpf) {
|
|
1469
|
+
const digits = cpf.replace(/\D/g, "");
|
|
1470
|
+
if (digits.length !== 11 || /^(\d)\1{10}$/.test(digits)) {
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
let sum = 0;
|
|
1474
|
+
for (let i = 0; i < 9; i++) {
|
|
1475
|
+
sum += parseInt(digits.charAt(i)) * (10 - i);
|
|
1476
|
+
}
|
|
1477
|
+
let remainder = sum * 10 % 11;
|
|
1478
|
+
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
1479
|
+
if (remainder !== parseInt(digits.charAt(9))) {
|
|
1480
|
+
return false;
|
|
1481
|
+
}
|
|
1482
|
+
sum = 0;
|
|
1483
|
+
for (let i = 0; i < 10; i++) {
|
|
1484
|
+
sum += parseInt(digits.charAt(i)) * (11 - i);
|
|
1485
|
+
}
|
|
1486
|
+
remainder = sum * 10 % 11;
|
|
1487
|
+
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
1488
|
+
if (remainder !== parseInt(digits.charAt(10))) {
|
|
1489
|
+
return false;
|
|
1490
|
+
}
|
|
1491
|
+
return true;
|
|
1492
|
+
}
|
|
1493
|
+
function isCNPJ(cnpj) {
|
|
1494
|
+
const digits = cnpj.replace(/\D/g, "");
|
|
1495
|
+
if (digits.length !== 14 || /^(\d)\1{13}$/.test(digits)) {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
1499
|
+
let sum = 0;
|
|
1500
|
+
for (let i = 0; i < 12; i++) {
|
|
1501
|
+
sum += parseInt(digits.charAt(i)) * weights1[i];
|
|
1502
|
+
}
|
|
1503
|
+
let remainder = sum % 11;
|
|
1504
|
+
const digit1 = remainder < 2 ? 0 : 11 - remainder;
|
|
1505
|
+
if (digit1 !== parseInt(digits.charAt(12))) {
|
|
1506
|
+
return false;
|
|
1507
|
+
}
|
|
1508
|
+
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
1509
|
+
sum = 0;
|
|
1510
|
+
for (let i = 0; i < 13; i++) {
|
|
1511
|
+
sum += parseInt(digits.charAt(i)) * weights2[i];
|
|
1512
|
+
}
|
|
1513
|
+
remainder = sum % 11;
|
|
1514
|
+
const digit2 = remainder < 2 ? 0 : 11 - remainder;
|
|
1515
|
+
if (digit2 !== parseInt(digits.charAt(13))) {
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
return true;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
// src/number/index.ts
|
|
1522
|
+
function formatCurrency(value, locale = DEFAULT_LOCALE, options) {
|
|
1523
|
+
const currency = CURRENCY_MAP[locale];
|
|
1524
|
+
return new Intl.NumberFormat(locale, {
|
|
1525
|
+
style: "currency",
|
|
1526
|
+
currency,
|
|
1527
|
+
...options
|
|
1528
|
+
}).format(value);
|
|
1529
|
+
}
|
|
1530
|
+
function formatNumber2(value, decimals = 0, locale = DEFAULT_LOCALE) {
|
|
1531
|
+
return new Intl.NumberFormat(locale, {
|
|
1532
|
+
minimumFractionDigits: decimals,
|
|
1533
|
+
maximumFractionDigits: decimals
|
|
1534
|
+
}).format(value);
|
|
1535
|
+
}
|
|
1536
|
+
function formatCompact(value, decimals = 1, locale = DEFAULT_LOCALE) {
|
|
1537
|
+
return new Intl.NumberFormat(locale, {
|
|
1538
|
+
notation: "compact",
|
|
1539
|
+
compactDisplay: "short",
|
|
1540
|
+
minimumFractionDigits: decimals,
|
|
1541
|
+
maximumFractionDigits: decimals
|
|
1542
|
+
}).format(value);
|
|
1543
|
+
}
|
|
1000
1544
|
function usePasswordStrength(password, options = {}) {
|
|
1001
1545
|
const {
|
|
1002
1546
|
minLength = 8,
|
|
@@ -1187,6 +1731,7 @@ function usePasswordStrength(password, options = {}) {
|
|
|
1187
1731
|
// src/pt-br.ts
|
|
1188
1732
|
var pt_br_exports = {};
|
|
1189
1733
|
__export(pt_br_exports, {
|
|
1734
|
+
default: () => pt_br_default,
|
|
1190
1735
|
formatCompact: () => formatCompact2,
|
|
1191
1736
|
formatCurrency: () => formatCurrency2,
|
|
1192
1737
|
formatDate: () => formatDate2,
|
|
@@ -1208,7 +1753,7 @@ function formatCurrency2(value, options) {
|
|
|
1208
1753
|
return formatCurrency(value, "pt-BR", options);
|
|
1209
1754
|
}
|
|
1210
1755
|
function formatNumber3(value, decimals = 0) {
|
|
1211
|
-
return
|
|
1756
|
+
return formatNumber2(value, decimals, "pt-BR");
|
|
1212
1757
|
}
|
|
1213
1758
|
function formatCompact2(value, decimals = 1) {
|
|
1214
1759
|
return formatCompact(value, decimals, "pt-BR");
|
|
@@ -1216,7 +1761,166 @@ function formatCompact2(value, decimals = 1) {
|
|
|
1216
1761
|
function translateStatus2(status) {
|
|
1217
1762
|
return translateStatus(status, "pt-BR");
|
|
1218
1763
|
}
|
|
1764
|
+
var pt_br_default = {
|
|
1765
|
+
formatDate: formatDate2,
|
|
1766
|
+
formatDateTime: formatDateTime2,
|
|
1767
|
+
formatRelativeDate: formatRelativeDate2,
|
|
1768
|
+
formatCurrency: formatCurrency2,
|
|
1769
|
+
formatNumber: formatNumber3,
|
|
1770
|
+
formatCompact: formatCompact2,
|
|
1771
|
+
translateStatus: translateStatus2
|
|
1772
|
+
};
|
|
1773
|
+
|
|
1774
|
+
// src/text/index.ts
|
|
1775
|
+
var text_exports = {};
|
|
1776
|
+
__export(text_exports, {
|
|
1777
|
+
calculateReadingTime: () => calculateReadingTime,
|
|
1778
|
+
capitalize: () => capitalize,
|
|
1779
|
+
cleanText: () => cleanText2,
|
|
1780
|
+
countWords: () => countWords2,
|
|
1781
|
+
extractInitials: () => extractInitials,
|
|
1782
|
+
generateAvatarUrl: () => generateAvatarUrl,
|
|
1783
|
+
generateDynamicAvatarUrl: () => generateDynamicAvatarUrl,
|
|
1784
|
+
generateUniqueId: () => generateUniqueId,
|
|
1785
|
+
getAvatarColorFromName: () => getAvatarColorFromName,
|
|
1786
|
+
isEmpty: () => isEmpty,
|
|
1787
|
+
isValidAvatarUrl: () => isValidAvatarUrl,
|
|
1788
|
+
normalizeSpaces: () => normalizeSpaces,
|
|
1789
|
+
truncateText: () => truncateText
|
|
1790
|
+
});
|
|
1791
|
+
function extractInitials(name, maxChars = 2) {
|
|
1792
|
+
if (!name || !name.trim()) {
|
|
1793
|
+
return "";
|
|
1794
|
+
}
|
|
1795
|
+
const words = name.trim().split(/\s+/);
|
|
1796
|
+
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
1797
|
+
return initials;
|
|
1798
|
+
}
|
|
1799
|
+
function generateAvatarUrl(name, size = 200, backgroundColor = "0891b2", textColor = "fff") {
|
|
1800
|
+
const encodedName = encodeURIComponent(name);
|
|
1801
|
+
return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;
|
|
1802
|
+
}
|
|
1803
|
+
function isValidAvatarUrl(url) {
|
|
1804
|
+
if (!url || typeof url !== "string") {
|
|
1805
|
+
return false;
|
|
1806
|
+
}
|
|
1807
|
+
try {
|
|
1808
|
+
new URL(url);
|
|
1809
|
+
return true;
|
|
1810
|
+
} catch {
|
|
1811
|
+
return false;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
function getAvatarColorFromName(name) {
|
|
1815
|
+
if (!name || typeof name !== "string") {
|
|
1816
|
+
return "#0891b2";
|
|
1817
|
+
}
|
|
1818
|
+
let hash = 0;
|
|
1819
|
+
for (let i = 0; i < name.length; i++) {
|
|
1820
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
1821
|
+
}
|
|
1822
|
+
const colors = [
|
|
1823
|
+
"#0891b2",
|
|
1824
|
+
// cyan-600
|
|
1825
|
+
"#9333ea",
|
|
1826
|
+
// purple-600
|
|
1827
|
+
"#db2777",
|
|
1828
|
+
// pink-600
|
|
1829
|
+
"#059669",
|
|
1830
|
+
// emerald-600
|
|
1831
|
+
"#2563eb",
|
|
1832
|
+
// blue-600
|
|
1833
|
+
"#f97316",
|
|
1834
|
+
// orange-500
|
|
1835
|
+
"#dc2626",
|
|
1836
|
+
// red-600
|
|
1837
|
+
"#7c3aed"
|
|
1838
|
+
// violet-600
|
|
1839
|
+
];
|
|
1840
|
+
const index = Math.abs(hash) % colors.length;
|
|
1841
|
+
return colors[index];
|
|
1842
|
+
}
|
|
1843
|
+
function generateDynamicAvatarUrl(name, size = 200) {
|
|
1844
|
+
const color = getAvatarColorFromName(name);
|
|
1845
|
+
const colorHex = color.replace("#", "");
|
|
1846
|
+
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
1847
|
+
}
|
|
1848
|
+
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
1849
|
+
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
1850
|
+
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
1851
|
+
return parts.join("-");
|
|
1852
|
+
}
|
|
1853
|
+
function truncateText(text, maxLength, suffix = "...") {
|
|
1854
|
+
if (!text || text.length <= maxLength) {
|
|
1855
|
+
return text || "";
|
|
1856
|
+
}
|
|
1857
|
+
return text.substring(0, maxLength - suffix.length) + suffix;
|
|
1858
|
+
}
|
|
1859
|
+
function capitalize(text, options = {}) {
|
|
1860
|
+
if (!text) return "";
|
|
1861
|
+
const { firstWordOnly = false, lowerRest = false } = options;
|
|
1862
|
+
if (firstWordOnly) {
|
|
1863
|
+
return text.charAt(0).toUpperCase() + (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));
|
|
1864
|
+
}
|
|
1865
|
+
if (lowerRest) {
|
|
1866
|
+
return text.replace(/\b\w/g, (char) => char.toUpperCase()).toLowerCase();
|
|
1867
|
+
}
|
|
1868
|
+
return text.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
1869
|
+
}
|
|
1870
|
+
function cleanText2(text, allowSpaces = true) {
|
|
1871
|
+
if (!text) return "";
|
|
1872
|
+
const pattern = allowSpaces ? /[^\w\s]/g : /[^\w]/g;
|
|
1873
|
+
return text.replace(pattern, "");
|
|
1874
|
+
}
|
|
1875
|
+
function countWords2(text) {
|
|
1876
|
+
if (!text || !text.trim()) {
|
|
1877
|
+
return 0;
|
|
1878
|
+
}
|
|
1879
|
+
return text.trim().split(/\s+/).length;
|
|
1880
|
+
}
|
|
1881
|
+
function isEmpty(text) {
|
|
1882
|
+
return !text || !text.trim();
|
|
1883
|
+
}
|
|
1884
|
+
function normalizeSpaces(text, options = {}) {
|
|
1885
|
+
if (!text) return "";
|
|
1886
|
+
const { newlines = false } = options;
|
|
1887
|
+
let cleaned = text;
|
|
1888
|
+
if (newlines) {
|
|
1889
|
+
cleaned = cleaned.replace(/\s+/g, " ");
|
|
1890
|
+
} else {
|
|
1891
|
+
cleaned = cleaned.replace(/\s+/g, " ");
|
|
1892
|
+
}
|
|
1893
|
+
return cleaned.trim();
|
|
1894
|
+
}
|
|
1895
|
+
function calculateReadingTime(content, wordsPerMinute = 200) {
|
|
1896
|
+
let text = "";
|
|
1897
|
+
if (typeof content === "object" && content !== null) {
|
|
1898
|
+
const extractText = (node) => {
|
|
1899
|
+
if (!node) return "";
|
|
1900
|
+
let result = "";
|
|
1901
|
+
if (node.text) {
|
|
1902
|
+
result += node.text + " ";
|
|
1903
|
+
}
|
|
1904
|
+
if (Array.isArray(node.content)) {
|
|
1905
|
+
result += node.content.map(extractText).join(" ");
|
|
1906
|
+
}
|
|
1907
|
+
return result;
|
|
1908
|
+
};
|
|
1909
|
+
text = extractText(content);
|
|
1910
|
+
} else if (typeof content === "string") {
|
|
1911
|
+
text = content.replace(/<[^>]*>/g, "");
|
|
1912
|
+
}
|
|
1913
|
+
const words = text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
1914
|
+
const time = Math.ceil(words / wordsPerMinute);
|
|
1915
|
+
return time > 0 ? time : 1;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
// src/index.ts
|
|
1919
|
+
var textProcessing = text_exports;
|
|
1920
|
+
var datetime = date_exports;
|
|
1921
|
+
var authentication = authentication_exports;
|
|
1922
|
+
var stateManagement = status_exports;
|
|
1219
1923
|
|
|
1220
|
-
export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, calculateReadingTime, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime,
|
|
1924
|
+
export { CURRENCY_MAP, DEFAULT_LOCALE, adjustBrightness, adjustHue, adjustSaturation, authentication, calculateChange, calculateMovingAverage, calculateReadingTime, capitalize, cleanText2 as cleanText, containsText, copyToClipboard, countCharacters, countWords2 as countWords, createEmptyTiptapContent, darken, datetime, downloadFile, extractInitials, extractTextFromTiptap, findMinMax, formatCNPJ, formatCPF, formatCurrency, formatDate, formatDateTime, formatNumber, formatPercentage, formatPhone, formatRelativeDate, fuzzySearch, generateAvatarUrl, generateDynamicAvatarUrl, generateExcerpt, generateMockChartData, generateUniqueId, getAnalogousPalette, getAvatarColorFromName, getComplementary, getContentStats, getElementPosition, getInitials, getReadingTime, getRefreshToken, getStatusColor, getStatusVariant, getToken, getTokens, groupDataByPeriod, hasToken, hexToHsl, hexToRgb, hexToRgba, hslToHex, isCNPJ, isCPF, isContentEmpty, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, isValidDate, lighten, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, removeToken, replaceText, rgbToHex, scrollToElement, scrollToPosition, scrollToTop, searchContent, searchWithScore, setRefreshToken, setToken, setTokens, smoothScrollTo, stateManagement, textProcessing, textToSlug, toISOString, translatePostStatus, translateStatus, truncate, truncateText, useAuth, useCurrentUser, useHasRole, useIsAdmin, useIsAuthenticated, usePasswordStrength, validateContrast, validateEmail, validateMessage, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
|
|
1221
1925
|
//# sourceMappingURL=index.mjs.map
|
|
1222
1926
|
//# sourceMappingURL=index.mjs.map
|