@rainersoft/utils 1.3.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/index-DeZ9ZulO.d.mts +28 -0
- package/dist/index-DeZ9ZulO.d.ts +28 -0
- package/dist/index.d.mts +173 -77
- package/dist/index.d.ts +173 -77
- package/dist/index.js +864 -174
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +829 -173
- 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/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.js
CHANGED
|
@@ -7,10 +7,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
7
7
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
8
8
|
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
11
|
var __export = (target, all) => {
|
|
11
12
|
for (var name in all)
|
|
12
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
14
|
};
|
|
15
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
14
16
|
|
|
15
17
|
// src/types.ts
|
|
16
18
|
var DEFAULT_LOCALE = "pt-BR";
|
|
@@ -20,153 +22,77 @@ var CURRENCY_MAP = {
|
|
|
20
22
|
"es-ES": "EUR"
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
// src/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
cleanText: () => cleanText,
|
|
29
|
-
countWords: () => countWords,
|
|
30
|
-
extractInitials: () => extractInitials,
|
|
31
|
-
generateAvatarUrl: () => generateAvatarUrl,
|
|
32
|
-
generateDynamicAvatarUrl: () => generateDynamicAvatarUrl,
|
|
33
|
-
generateUniqueId: () => generateUniqueId,
|
|
34
|
-
getAvatarColorFromName: () => getAvatarColorFromName,
|
|
35
|
-
isEmpty: () => isEmpty,
|
|
36
|
-
isValidAvatarUrl: () => isValidAvatarUrl,
|
|
37
|
-
normalizeSpaces: () => normalizeSpaces,
|
|
38
|
-
truncateText: () => truncateText
|
|
39
|
-
});
|
|
40
|
-
function extractInitials(name, maxChars = 2) {
|
|
41
|
-
if (!name || !name.trim()) {
|
|
42
|
-
return "";
|
|
43
|
-
}
|
|
44
|
-
const words = name.trim().split(/\s+/);
|
|
45
|
-
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
46
|
-
return initials;
|
|
47
|
-
}
|
|
48
|
-
function generateAvatarUrl(name, size = 200, backgroundColor = "0891b2", textColor = "fff") {
|
|
49
|
-
const encodedName = encodeURIComponent(name);
|
|
50
|
-
return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;
|
|
51
|
-
}
|
|
52
|
-
function isValidAvatarUrl(url) {
|
|
53
|
-
if (!url || typeof url !== "string") {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
new URL(url);
|
|
58
|
-
return true;
|
|
59
|
-
} catch {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function getAvatarColorFromName(name) {
|
|
64
|
-
if (!name || typeof name !== "string") {
|
|
65
|
-
return "#0891b2";
|
|
66
|
-
}
|
|
67
|
-
let hash = 0;
|
|
68
|
-
for (let i = 0; i < name.length; i++) {
|
|
69
|
-
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
70
|
-
}
|
|
71
|
-
const colors = [
|
|
72
|
-
"#0891b2",
|
|
73
|
-
// cyan-600
|
|
74
|
-
"#9333ea",
|
|
75
|
-
// purple-600
|
|
76
|
-
"#db2777",
|
|
77
|
-
// pink-600
|
|
78
|
-
"#059669",
|
|
79
|
-
// emerald-600
|
|
80
|
-
"#2563eb",
|
|
81
|
-
// blue-600
|
|
82
|
-
"#f97316",
|
|
83
|
-
// orange-500
|
|
84
|
-
"#dc2626",
|
|
85
|
-
// red-600
|
|
86
|
-
"#7c3aed"
|
|
87
|
-
// violet-600
|
|
88
|
-
];
|
|
89
|
-
const index = Math.abs(hash) % colors.length;
|
|
90
|
-
return colors[index];
|
|
91
|
-
}
|
|
92
|
-
function generateDynamicAvatarUrl(name, size = 200) {
|
|
93
|
-
const color = getAvatarColorFromName(name);
|
|
94
|
-
const colorHex = color.replace("#", "");
|
|
95
|
-
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
96
|
-
}
|
|
97
|
-
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
98
|
-
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
99
|
-
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
100
|
-
return parts.join("-");
|
|
101
|
-
}
|
|
102
|
-
function truncateText(text, maxLength, suffix = "...") {
|
|
103
|
-
if (!text || text.length <= maxLength) {
|
|
104
|
-
return text || "";
|
|
25
|
+
// src/accessibility/index.ts
|
|
26
|
+
function hexToRgb(hex) {
|
|
27
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
28
|
+
if (!result) {
|
|
29
|
+
throw new Error(`Invalid hex color: ${hex}`);
|
|
105
30
|
}
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (firstWordOnly) {
|
|
112
|
-
return text.charAt(0).toUpperCase() + (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));
|
|
113
|
-
}
|
|
114
|
-
if (lowerRest) {
|
|
115
|
-
return text.replace(/\b\w/g, (char) => char.toUpperCase()).toLowerCase();
|
|
116
|
-
}
|
|
117
|
-
return text.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
118
|
-
}
|
|
119
|
-
function cleanText(text, allowSpaces = true) {
|
|
120
|
-
if (!text) return "";
|
|
121
|
-
const pattern = allowSpaces ? /[^\w\s]/g : /[^\w]/g;
|
|
122
|
-
return text.replace(pattern, "");
|
|
31
|
+
return {
|
|
32
|
+
r: parseInt(result[1], 16),
|
|
33
|
+
g: parseInt(result[2], 16),
|
|
34
|
+
b: parseInt(result[3], 16)
|
|
35
|
+
};
|
|
123
36
|
}
|
|
124
|
-
function
|
|
125
|
-
|
|
126
|
-
|
|
37
|
+
function getLuminance(r, g, b) {
|
|
38
|
+
const [rs, gs, bs] = [r, g, b].map((val) => {
|
|
39
|
+
const v = val / 255;
|
|
40
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
41
|
+
});
|
|
42
|
+
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
43
|
+
}
|
|
44
|
+
function getContrast(color1, color2) {
|
|
45
|
+
const rgb1 = hexToRgb(color1);
|
|
46
|
+
const rgb2 = hexToRgb(color2);
|
|
47
|
+
const lum1 = getLuminance(rgb1.r, rgb1.g, rgb1.b);
|
|
48
|
+
const lum2 = getLuminance(rgb2.r, rgb2.g, rgb2.b);
|
|
49
|
+
const lighter = Math.max(lum1, lum2);
|
|
50
|
+
const darker = Math.min(lum1, lum2);
|
|
51
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
52
|
+
}
|
|
53
|
+
function getContrastInfo(foreground, background) {
|
|
54
|
+
const contrast = getContrast(foreground, background);
|
|
55
|
+
const meetsAA = contrast >= 4.5;
|
|
56
|
+
const meetsAALarge = contrast >= 3;
|
|
57
|
+
const meetsAAA = contrast >= 7;
|
|
58
|
+
const meetsAAALarge = contrast >= 4.5;
|
|
59
|
+
let level = "Fail";
|
|
60
|
+
if (meetsAAA) {
|
|
61
|
+
level = "AAA";
|
|
62
|
+
} else if (meetsAAALarge) {
|
|
63
|
+
level = "AAA Large";
|
|
64
|
+
} else if (meetsAA) {
|
|
65
|
+
level = "AA";
|
|
66
|
+
} else if (meetsAALarge) {
|
|
67
|
+
level = "AA Large";
|
|
127
68
|
}
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
69
|
+
return {
|
|
70
|
+
contrast,
|
|
71
|
+
meetsAA,
|
|
72
|
+
meetsAALarge,
|
|
73
|
+
meetsAAA,
|
|
74
|
+
meetsAAALarge,
|
|
75
|
+
level
|
|
76
|
+
};
|
|
132
77
|
}
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
let
|
|
137
|
-
|
|
138
|
-
|
|
78
|
+
function validateContrast(foreground, background, options = {}) {
|
|
79
|
+
const { requireAAA = false, largeText = false } = options;
|
|
80
|
+
const info = getContrastInfo(foreground, background);
|
|
81
|
+
let valid = false;
|
|
82
|
+
let message = "";
|
|
83
|
+
if (requireAAA) {
|
|
84
|
+
valid = largeText ? info.meetsAAALarge : info.meetsAAA;
|
|
85
|
+
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`;
|
|
139
86
|
} else {
|
|
140
|
-
|
|
87
|
+
valid = largeText ? info.meetsAALarge : info.meetsAA;
|
|
88
|
+
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`;
|
|
141
89
|
}
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (!node) return "";
|
|
149
|
-
let result = "";
|
|
150
|
-
if (node.text) {
|
|
151
|
-
result += node.text + " ";
|
|
152
|
-
}
|
|
153
|
-
if (Array.isArray(node.content)) {
|
|
154
|
-
result += node.content.map(extractText).join(" ");
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
157
|
-
};
|
|
158
|
-
text = extractText(content);
|
|
159
|
-
} else if (typeof content === "string") {
|
|
160
|
-
text = content.replace(/<[^>]*>/g, "");
|
|
161
|
-
}
|
|
162
|
-
const words = text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
163
|
-
const time = Math.ceil(words / wordsPerMinute);
|
|
164
|
-
return time > 0 ? time : 1;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// src/string/index.ts
|
|
168
|
-
function textToSlug(text) {
|
|
169
|
-
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
90
|
+
return {
|
|
91
|
+
valid,
|
|
92
|
+
level: info.level,
|
|
93
|
+
contrast: info.contrast,
|
|
94
|
+
message
|
|
95
|
+
};
|
|
170
96
|
}
|
|
171
97
|
|
|
172
98
|
// src/date/index.ts
|
|
@@ -270,30 +196,6 @@ function isValidDate(date) {
|
|
|
270
196
|
return date instanceof Date && !isNaN(date.getTime());
|
|
271
197
|
}
|
|
272
198
|
|
|
273
|
-
// src/number/index.ts
|
|
274
|
-
function formatCurrency(value, locale = DEFAULT_LOCALE, options) {
|
|
275
|
-
const currency = CURRENCY_MAP[locale];
|
|
276
|
-
return new Intl.NumberFormat(locale, {
|
|
277
|
-
style: "currency",
|
|
278
|
-
currency,
|
|
279
|
-
...options
|
|
280
|
-
}).format(value);
|
|
281
|
-
}
|
|
282
|
-
function formatNumber(value, decimals = 0, locale = DEFAULT_LOCALE) {
|
|
283
|
-
return new Intl.NumberFormat(locale, {
|
|
284
|
-
minimumFractionDigits: decimals,
|
|
285
|
-
maximumFractionDigits: decimals
|
|
286
|
-
}).format(value);
|
|
287
|
-
}
|
|
288
|
-
function formatCompact(value, decimals = 1, locale = DEFAULT_LOCALE) {
|
|
289
|
-
return new Intl.NumberFormat(locale, {
|
|
290
|
-
notation: "compact",
|
|
291
|
-
compactDisplay: "short",
|
|
292
|
-
minimumFractionDigits: decimals,
|
|
293
|
-
maximumFractionDigits: decimals
|
|
294
|
-
}).format(value);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
199
|
// src/status/index.ts
|
|
298
200
|
var status_exports = {};
|
|
299
201
|
__export(status_exports, {
|
|
@@ -662,6 +564,198 @@ function validateMessage(message, options = {}, locale = DEFAULT_LOCALE) {
|
|
|
662
564
|
}, locale);
|
|
663
565
|
}
|
|
664
566
|
|
|
567
|
+
// src/content/tiptap-utils.ts
|
|
568
|
+
function extractTextFromTiptap(content) {
|
|
569
|
+
function extractFromNode(node) {
|
|
570
|
+
if ("text" in node && typeof node.text === "string") {
|
|
571
|
+
return node.text;
|
|
572
|
+
}
|
|
573
|
+
if ("content" in node && Array.isArray(node.content)) {
|
|
574
|
+
return node.content.map((child) => extractFromNode(child)).join(" ");
|
|
575
|
+
}
|
|
576
|
+
return "";
|
|
577
|
+
}
|
|
578
|
+
return extractFromNode(content).trim();
|
|
579
|
+
}
|
|
580
|
+
function generateExcerpt(content, maxLength = 160) {
|
|
581
|
+
const text = extractTextFromTiptap(content);
|
|
582
|
+
if (text.length <= maxLength) {
|
|
583
|
+
return text;
|
|
584
|
+
}
|
|
585
|
+
return text.substring(0, maxLength).trim() + "...";
|
|
586
|
+
}
|
|
587
|
+
function createEmptyTiptapContent() {
|
|
588
|
+
return {
|
|
589
|
+
type: "doc",
|
|
590
|
+
content: []
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function isContentEmpty(content) {
|
|
594
|
+
if (!content || !content.content || content.content.length === 0) {
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
const text = extractTextFromTiptap(content);
|
|
598
|
+
return text.trim().length === 0;
|
|
599
|
+
}
|
|
600
|
+
function countWords(content) {
|
|
601
|
+
const text = extractTextFromTiptap(content);
|
|
602
|
+
return text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
603
|
+
}
|
|
604
|
+
function countCharacters(content) {
|
|
605
|
+
return extractTextFromTiptap(content).length;
|
|
606
|
+
}
|
|
607
|
+
function getReadingTime(content, wordsPerMinute = 200) {
|
|
608
|
+
const wordCount = countWords(content);
|
|
609
|
+
return Math.ceil(wordCount / wordsPerMinute);
|
|
610
|
+
}
|
|
611
|
+
function getContentStats(content) {
|
|
612
|
+
const wordCount = countWords(content);
|
|
613
|
+
const characterCount = extractTextFromTiptap(content).length;
|
|
614
|
+
const readingTime = getReadingTime(content);
|
|
615
|
+
return {
|
|
616
|
+
wordCount,
|
|
617
|
+
characterCount,
|
|
618
|
+
readingTime
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
function containsText(content, searchText) {
|
|
622
|
+
const text = extractTextFromTiptap(content).toLowerCase();
|
|
623
|
+
return text.includes(searchText.toLowerCase());
|
|
624
|
+
}
|
|
625
|
+
function replaceText(content, searchText, replaceText2) {
|
|
626
|
+
function processNode(node) {
|
|
627
|
+
const newNode = { ...node };
|
|
628
|
+
if ("text" in node && typeof node.text === "string") {
|
|
629
|
+
newNode.text = node.text.replace(
|
|
630
|
+
new RegExp(searchText, "gi"),
|
|
631
|
+
replaceText2
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
if ("content" in node && Array.isArray(node.content)) {
|
|
635
|
+
newNode.content = node.content.map((child) => processNode(child));
|
|
636
|
+
}
|
|
637
|
+
return newNode;
|
|
638
|
+
}
|
|
639
|
+
const newContent = {
|
|
640
|
+
...content,
|
|
641
|
+
content: content.content.map((node) => processNode(node))
|
|
642
|
+
};
|
|
643
|
+
return newContent;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/color/index.ts
|
|
647
|
+
function hexToRgb2(hex) {
|
|
648
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
649
|
+
if (!result) {
|
|
650
|
+
throw new Error(`Invalid hex color: ${hex}`);
|
|
651
|
+
}
|
|
652
|
+
return {
|
|
653
|
+
r: parseInt(result[1], 16),
|
|
654
|
+
g: parseInt(result[2], 16),
|
|
655
|
+
b: parseInt(result[3], 16)
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function rgbToHex(r, g, b) {
|
|
659
|
+
const toHex = (n) => {
|
|
660
|
+
const hex = Math.round(Math.max(0, Math.min(255, n))).toString(16);
|
|
661
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
662
|
+
};
|
|
663
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
664
|
+
}
|
|
665
|
+
function hexToHsl(hex) {
|
|
666
|
+
const rgb = hexToRgb2(hex);
|
|
667
|
+
const r = rgb.r / 255;
|
|
668
|
+
const g = rgb.g / 255;
|
|
669
|
+
const b = rgb.b / 255;
|
|
670
|
+
const max = Math.max(r, g, b);
|
|
671
|
+
const min = Math.min(r, g, b);
|
|
672
|
+
let h = 0;
|
|
673
|
+
let s = 0;
|
|
674
|
+
const l = (max + min) / 2;
|
|
675
|
+
if (max !== min) {
|
|
676
|
+
const d = max - min;
|
|
677
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
678
|
+
switch (max) {
|
|
679
|
+
case r:
|
|
680
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
681
|
+
break;
|
|
682
|
+
case g:
|
|
683
|
+
h = ((b - r) / d + 2) / 6;
|
|
684
|
+
break;
|
|
685
|
+
case b:
|
|
686
|
+
h = ((r - g) / d + 4) / 6;
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
h: Math.round(h * 360),
|
|
692
|
+
s: Math.round(s * 100),
|
|
693
|
+
l: Math.round(l * 100)
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function hslToHex(h, s, l) {
|
|
697
|
+
h = h / 360;
|
|
698
|
+
s = s / 100;
|
|
699
|
+
l = l / 100;
|
|
700
|
+
let r, g, b;
|
|
701
|
+
if (s === 0) {
|
|
702
|
+
r = g = b = l;
|
|
703
|
+
} else {
|
|
704
|
+
const hue2rgb = (p2, q2, t) => {
|
|
705
|
+
if (t < 0) t += 1;
|
|
706
|
+
if (t > 1) t -= 1;
|
|
707
|
+
if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
|
|
708
|
+
if (t < 1 / 2) return q2;
|
|
709
|
+
if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
|
|
710
|
+
return p2;
|
|
711
|
+
};
|
|
712
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
713
|
+
const p = 2 * l - q;
|
|
714
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
715
|
+
g = hue2rgb(p, q, h);
|
|
716
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
717
|
+
}
|
|
718
|
+
return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
|
|
719
|
+
}
|
|
720
|
+
function adjustBrightness(hex, amount) {
|
|
721
|
+
const hsl = hexToHsl(hex);
|
|
722
|
+
const newL = Math.max(0, Math.min(100, hsl.l + amount));
|
|
723
|
+
return hslToHex(hsl.h, hsl.s, newL);
|
|
724
|
+
}
|
|
725
|
+
function adjustSaturation(hex, amount) {
|
|
726
|
+
const hsl = hexToHsl(hex);
|
|
727
|
+
const newS = Math.max(0, Math.min(100, hsl.s + amount));
|
|
728
|
+
return hslToHex(hsl.h, newS, hsl.l);
|
|
729
|
+
}
|
|
730
|
+
function adjustHue(hex, degrees) {
|
|
731
|
+
const hsl = hexToHsl(hex);
|
|
732
|
+
const newH = (hsl.h + degrees) % 360;
|
|
733
|
+
return hslToHex(newH < 0 ? newH + 360 : newH, hsl.s, hsl.l);
|
|
734
|
+
}
|
|
735
|
+
function lighten(hex, amount) {
|
|
736
|
+
return adjustBrightness(hex, amount);
|
|
737
|
+
}
|
|
738
|
+
function darken(hex, amount) {
|
|
739
|
+
return adjustBrightness(hex, -amount);
|
|
740
|
+
}
|
|
741
|
+
function hexToRgba(hex, alpha) {
|
|
742
|
+
const rgb = hexToRgb2(hex);
|
|
743
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
|
744
|
+
}
|
|
745
|
+
function getComplementary(hex) {
|
|
746
|
+
return adjustHue(hex, 180);
|
|
747
|
+
}
|
|
748
|
+
function getAnalogousPalette(hex, count = 5) {
|
|
749
|
+
const hsl = hexToHsl(hex);
|
|
750
|
+
const step = 30;
|
|
751
|
+
const palette = [];
|
|
752
|
+
for (let i = 0; i < count; i++) {
|
|
753
|
+
const hue = (hsl.h + (i - Math.floor(count / 2)) * step) % 360;
|
|
754
|
+
palette.push(hslToHex(hue < 0 ? hue + 360 : hue, hsl.s, hsl.l));
|
|
755
|
+
}
|
|
756
|
+
return palette;
|
|
757
|
+
}
|
|
758
|
+
|
|
665
759
|
// src/dom/index.ts
|
|
666
760
|
function prefersReducedMotion() {
|
|
667
761
|
if (typeof window === "undefined") return false;
|
|
@@ -839,9 +933,314 @@ function downloadFile(blob, filename) {
|
|
|
839
933
|
document.body.removeChild(link);
|
|
840
934
|
URL.revokeObjectURL(url);
|
|
841
935
|
}
|
|
936
|
+
var DEFAULT_CONFIG = {
|
|
937
|
+
autoRefresh: true,
|
|
938
|
+
refreshInterval: 15 * 60 * 1e3,
|
|
939
|
+
// 15 minutes
|
|
940
|
+
tokenStorageKey: "auth_token",
|
|
941
|
+
userStorageKey: "auth_user",
|
|
942
|
+
apiEndpoint: "/api/auth",
|
|
943
|
+
onAuthChange: () => {
|
|
944
|
+
},
|
|
945
|
+
onError: () => {
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
var AuthStorage = class {
|
|
949
|
+
static setItem(key, value) {
|
|
950
|
+
if (!this.isClient) return;
|
|
951
|
+
try {
|
|
952
|
+
localStorage.setItem(key, value);
|
|
953
|
+
} catch (error) {
|
|
954
|
+
console.warn("Failed to save to localStorage:", error);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
static getItem(key) {
|
|
958
|
+
if (!this.isClient) return null;
|
|
959
|
+
try {
|
|
960
|
+
return localStorage.getItem(key);
|
|
961
|
+
} catch (error) {
|
|
962
|
+
console.warn("Failed to read from localStorage:", error);
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
static removeItem(key) {
|
|
967
|
+
if (!this.isClient) return;
|
|
968
|
+
try {
|
|
969
|
+
localStorage.removeItem(key);
|
|
970
|
+
} catch (error) {
|
|
971
|
+
console.warn("Failed to remove from localStorage:", error);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
static setUser(user, key) {
|
|
975
|
+
this.setItem(key, JSON.stringify(user));
|
|
976
|
+
}
|
|
977
|
+
static getUser(key) {
|
|
978
|
+
const data = this.getItem(key);
|
|
979
|
+
if (!data) return null;
|
|
980
|
+
try {
|
|
981
|
+
return JSON.parse(data);
|
|
982
|
+
} catch {
|
|
983
|
+
this.removeItem(key);
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
static removeUser(key) {
|
|
988
|
+
this.removeItem(key);
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
__publicField(AuthStorage, "isClient", typeof window !== "undefined");
|
|
992
|
+
var TokenManager = class {
|
|
993
|
+
static decodeToken(token) {
|
|
994
|
+
try {
|
|
995
|
+
const payload = token.split(".")[1];
|
|
996
|
+
const decoded = atob(payload);
|
|
997
|
+
return JSON.parse(decoded);
|
|
998
|
+
} catch {
|
|
999
|
+
return null;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
static isTokenExpired(token) {
|
|
1003
|
+
const decoded = this.decodeToken(token);
|
|
1004
|
+
if (!decoded) return true;
|
|
1005
|
+
const now = Date.now() / 1e3;
|
|
1006
|
+
return decoded.exp < now;
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
function useAuth(config = {}) {
|
|
1010
|
+
const configRef = React.useRef({ ...DEFAULT_CONFIG, ...config });
|
|
1011
|
+
const cfg = configRef.current;
|
|
1012
|
+
const [user, setUser] = React.useState(null);
|
|
1013
|
+
const [loading, setLoading] = React.useState(false);
|
|
1014
|
+
const [error, setError] = React.useState(null);
|
|
1015
|
+
const [isAuthenticated, setIsAuthenticated] = React.useState(false);
|
|
1016
|
+
const refreshTimerRef = React.useRef(null);
|
|
1017
|
+
const storeToken = React.useCallback((token, refreshToken2) => {
|
|
1018
|
+
AuthStorage.setItem(cfg.tokenStorageKey, token);
|
|
1019
|
+
if (refreshToken2) {
|
|
1020
|
+
AuthStorage.setItem(`${cfg.tokenStorageKey}_refresh`, refreshToken2);
|
|
1021
|
+
}
|
|
1022
|
+
}, [cfg.tokenStorageKey]);
|
|
1023
|
+
const getStoredToken = React.useCallback(() => {
|
|
1024
|
+
return AuthStorage.getItem(cfg.tokenStorageKey);
|
|
1025
|
+
}, [cfg.tokenStorageKey]);
|
|
1026
|
+
const clearTokens = React.useCallback(() => {
|
|
1027
|
+
AuthStorage.removeItem(cfg.tokenStorageKey);
|
|
1028
|
+
AuthStorage.removeItem(`${cfg.tokenStorageKey}_refresh`);
|
|
1029
|
+
}, [cfg.tokenStorageKey]);
|
|
1030
|
+
const apiCall = React.useCallback(async (endpoint, options = {}) => {
|
|
1031
|
+
const token = getStoredToken();
|
|
1032
|
+
const url = `${cfg.apiEndpoint}${endpoint}`;
|
|
1033
|
+
const response = await fetch(url, {
|
|
1034
|
+
...options,
|
|
1035
|
+
headers: {
|
|
1036
|
+
"Content-Type": "application/json",
|
|
1037
|
+
...token && { Authorization: `Bearer ${token}` },
|
|
1038
|
+
...options.headers
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
if (!response.ok) {
|
|
1042
|
+
const error2 = await response.text();
|
|
1043
|
+
throw new Error(error2 || `HTTP ${response.status}`);
|
|
1044
|
+
}
|
|
1045
|
+
return response.json();
|
|
1046
|
+
}, [cfg.apiEndpoint, getStoredToken]);
|
|
1047
|
+
const login = React.useCallback(async (credentials) => {
|
|
1048
|
+
setLoading(true);
|
|
1049
|
+
setError(null);
|
|
1050
|
+
try {
|
|
1051
|
+
const response = await apiCall("/login", {
|
|
1052
|
+
method: "POST",
|
|
1053
|
+
body: JSON.stringify(credentials)
|
|
1054
|
+
});
|
|
1055
|
+
if (response.success && response.user && response.token) {
|
|
1056
|
+
setUser(response.user);
|
|
1057
|
+
setIsAuthenticated(true);
|
|
1058
|
+
storeToken(response.token, response.refreshToken);
|
|
1059
|
+
if (cfg.onAuthChange) {
|
|
1060
|
+
cfg.onAuthChange(response.user);
|
|
1061
|
+
}
|
|
1062
|
+
return { success: true, user: response.user, token: response.token };
|
|
1063
|
+
} else {
|
|
1064
|
+
const errorMsg = response.error || "Login failed";
|
|
1065
|
+
setError(errorMsg);
|
|
1066
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1067
|
+
return { success: false, error: errorMsg };
|
|
1068
|
+
}
|
|
1069
|
+
} catch (error2) {
|
|
1070
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Login failed";
|
|
1071
|
+
setError(errorMsg);
|
|
1072
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1073
|
+
return { success: false, error: errorMsg };
|
|
1074
|
+
} finally {
|
|
1075
|
+
setLoading(false);
|
|
1076
|
+
}
|
|
1077
|
+
}, [apiCall, setUser, storeToken, cfg]);
|
|
1078
|
+
const logout = React.useCallback(async (options = {}) => {
|
|
1079
|
+
try {
|
|
1080
|
+
if (options.invalidateAllSessions) {
|
|
1081
|
+
await apiCall("/logout", { method: "POST" });
|
|
1082
|
+
}
|
|
1083
|
+
} catch (error2) {
|
|
1084
|
+
console.warn("Logout API call failed:", error2);
|
|
1085
|
+
} finally {
|
|
1086
|
+
setUser(null);
|
|
1087
|
+
setIsAuthenticated(false);
|
|
1088
|
+
clearTokens();
|
|
1089
|
+
if (refreshTimerRef.current) {
|
|
1090
|
+
clearInterval(refreshTimerRef.current);
|
|
1091
|
+
refreshTimerRef.current = null;
|
|
1092
|
+
}
|
|
1093
|
+
if (cfg.onAuthChange) {
|
|
1094
|
+
cfg.onAuthChange(null);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}, [apiCall, clearTokens, cfg]);
|
|
1098
|
+
const register = React.useCallback(async (userData) => {
|
|
1099
|
+
setLoading(true);
|
|
1100
|
+
setError(null);
|
|
1101
|
+
try {
|
|
1102
|
+
const response = await apiCall("/register", {
|
|
1103
|
+
method: "POST",
|
|
1104
|
+
body: JSON.stringify(userData)
|
|
1105
|
+
});
|
|
1106
|
+
if (response.success && response.user && response.token) {
|
|
1107
|
+
setUser(response.user);
|
|
1108
|
+
setIsAuthenticated(true);
|
|
1109
|
+
storeToken(response.token, response.refreshToken);
|
|
1110
|
+
if (cfg.onAuthChange) {
|
|
1111
|
+
cfg.onAuthChange(response.user);
|
|
1112
|
+
}
|
|
1113
|
+
return { success: true, user: response.user, token: response.token };
|
|
1114
|
+
} else {
|
|
1115
|
+
const errorMsg = response.error || "Registration failed";
|
|
1116
|
+
setError(errorMsg);
|
|
1117
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1118
|
+
return { success: false, error: errorMsg };
|
|
1119
|
+
}
|
|
1120
|
+
} catch (error2) {
|
|
1121
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Registration failed";
|
|
1122
|
+
setError(errorMsg);
|
|
1123
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1124
|
+
return { success: false, error: errorMsg };
|
|
1125
|
+
} finally {
|
|
1126
|
+
setLoading(false);
|
|
1127
|
+
}
|
|
1128
|
+
}, [apiCall, setUser, storeToken, cfg]);
|
|
1129
|
+
const updateProfile = React.useCallback(async (data) => {
|
|
1130
|
+
if (!user) {
|
|
1131
|
+
const error2 = "No user logged in";
|
|
1132
|
+
setError(error2);
|
|
1133
|
+
if (cfg.onError) cfg.onError(error2);
|
|
1134
|
+
return { success: false, error: error2 };
|
|
1135
|
+
}
|
|
1136
|
+
setLoading(true);
|
|
1137
|
+
setError(null);
|
|
1138
|
+
try {
|
|
1139
|
+
const response = await apiCall("/profile", {
|
|
1140
|
+
method: "PUT",
|
|
1141
|
+
body: JSON.stringify(data)
|
|
1142
|
+
});
|
|
1143
|
+
if (response.success && response.user) {
|
|
1144
|
+
setUser(response.user);
|
|
1145
|
+
if (cfg.onAuthChange) {
|
|
1146
|
+
cfg.onAuthChange(response.user);
|
|
1147
|
+
}
|
|
1148
|
+
return { success: true, user: response.user };
|
|
1149
|
+
} else {
|
|
1150
|
+
const errorMsg = response.error || "Profile update failed";
|
|
1151
|
+
setError(errorMsg);
|
|
1152
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1153
|
+
return { success: false, error: errorMsg };
|
|
1154
|
+
}
|
|
1155
|
+
} catch (error2) {
|
|
1156
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Profile update failed";
|
|
1157
|
+
setError(errorMsg);
|
|
1158
|
+
if (cfg.onError) cfg.onError(errorMsg);
|
|
1159
|
+
return { success: false, error: errorMsg };
|
|
1160
|
+
} finally {
|
|
1161
|
+
setLoading(false);
|
|
1162
|
+
}
|
|
1163
|
+
}, [apiCall, user, setUser, cfg]);
|
|
1164
|
+
const refreshToken = React.useCallback(async () => {
|
|
1165
|
+
const refreshToken2 = AuthStorage.getItem(`${cfg.tokenStorageKey}_refresh`);
|
|
1166
|
+
if (!refreshToken2) {
|
|
1167
|
+
return { success: false, error: "No refresh token available" };
|
|
1168
|
+
}
|
|
1169
|
+
try {
|
|
1170
|
+
const response = await apiCall("/refresh", {
|
|
1171
|
+
method: "POST",
|
|
1172
|
+
body: JSON.stringify({ refreshToken: refreshToken2 })
|
|
1173
|
+
});
|
|
1174
|
+
if (response.success && response.token && response.user) {
|
|
1175
|
+
setUser(response.user);
|
|
1176
|
+
storeToken(response.token, response.refreshToken);
|
|
1177
|
+
if (cfg.onAuthChange) {
|
|
1178
|
+
cfg.onAuthChange(response.user);
|
|
1179
|
+
}
|
|
1180
|
+
return { success: true, user: response.user, token: response.token };
|
|
1181
|
+
} else {
|
|
1182
|
+
await logout();
|
|
1183
|
+
return { success: false, error: "Session expired" };
|
|
1184
|
+
}
|
|
1185
|
+
} catch (error2) {
|
|
1186
|
+
await logout();
|
|
1187
|
+
return { success: false, error: "Session expired" };
|
|
1188
|
+
}
|
|
1189
|
+
}, [apiCall, setUser, storeToken, logout, cfg]);
|
|
1190
|
+
const resetError = React.useCallback(() => {
|
|
1191
|
+
setError(null);
|
|
1192
|
+
}, []);
|
|
1193
|
+
React.useEffect(() => {
|
|
1194
|
+
const token = getStoredToken();
|
|
1195
|
+
const storedUser = AuthStorage.getUser(cfg.userStorageKey);
|
|
1196
|
+
if (token && storedUser && !TokenManager.isTokenExpired(token)) {
|
|
1197
|
+
setUser(storedUser);
|
|
1198
|
+
setIsAuthenticated(true);
|
|
1199
|
+
if (cfg.onAuthChange) {
|
|
1200
|
+
cfg.onAuthChange(storedUser);
|
|
1201
|
+
}
|
|
1202
|
+
} else if (token && TokenManager.isTokenExpired(token)) {
|
|
1203
|
+
refreshToken();
|
|
1204
|
+
} else {
|
|
1205
|
+
setLoading(false);
|
|
1206
|
+
}
|
|
1207
|
+
return () => {
|
|
1208
|
+
if (refreshTimerRef.current) {
|
|
1209
|
+
clearInterval(refreshTimerRef.current);
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
}, []);
|
|
1213
|
+
return {
|
|
1214
|
+
user,
|
|
1215
|
+
loading,
|
|
1216
|
+
error,
|
|
1217
|
+
isAuthenticated,
|
|
1218
|
+
login,
|
|
1219
|
+
logout,
|
|
1220
|
+
register,
|
|
1221
|
+
updateProfile,
|
|
1222
|
+
refreshToken,
|
|
1223
|
+
resetError
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
function useIsAuthenticated() {
|
|
1227
|
+
const { isAuthenticated } = useAuth();
|
|
1228
|
+
return isAuthenticated;
|
|
1229
|
+
}
|
|
1230
|
+
function useCurrentUser() {
|
|
1231
|
+
const { user } = useAuth();
|
|
1232
|
+
return user;
|
|
1233
|
+
}
|
|
1234
|
+
function useHasRole(role) {
|
|
1235
|
+
const { user } = useAuth();
|
|
1236
|
+
return user?.role === role;
|
|
1237
|
+
}
|
|
1238
|
+
function useIsAdmin() {
|
|
1239
|
+
return useHasRole("admin" /* ADMIN */);
|
|
1240
|
+
}
|
|
842
1241
|
|
|
843
1242
|
// src/stats/index.ts
|
|
844
|
-
function
|
|
1243
|
+
function formatNumber(num) {
|
|
845
1244
|
if (num >= 1e6) {
|
|
846
1245
|
return (num / 1e6).toFixed(1) + "M";
|
|
847
1246
|
}
|
|
@@ -899,9 +1298,9 @@ function findMinMax(data, field) {
|
|
|
899
1298
|
};
|
|
900
1299
|
}
|
|
901
1300
|
|
|
902
|
-
// src/
|
|
903
|
-
var
|
|
904
|
-
__export(
|
|
1301
|
+
// src/authentication/index.ts
|
|
1302
|
+
var authentication_exports = {};
|
|
1303
|
+
__export(authentication_exports, {
|
|
905
1304
|
getRefreshToken: () => getRefreshToken,
|
|
906
1305
|
getToken: () => getToken,
|
|
907
1306
|
getTokens: () => getTokens,
|
|
@@ -1045,6 +1444,109 @@ function calculateSimilarity(str1, str2) {
|
|
|
1045
1444
|
const similarity = common / Math.max(str1.length, str2.length);
|
|
1046
1445
|
return similarity;
|
|
1047
1446
|
}
|
|
1447
|
+
|
|
1448
|
+
// src/string/index.ts
|
|
1449
|
+
function textToSlug(text) {
|
|
1450
|
+
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/^-+|-+$/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
1451
|
+
}
|
|
1452
|
+
function truncate(text, maxLength, suffix = "...") {
|
|
1453
|
+
if (text.length <= maxLength) return text;
|
|
1454
|
+
return text.slice(0, maxLength - suffix.length) + suffix;
|
|
1455
|
+
}
|
|
1456
|
+
function getInitials(name, maxInitials = 2) {
|
|
1457
|
+
return name.split(" ").filter((word) => word.length > 0).map((word) => word[0]).join("").toUpperCase().slice(0, maxInitials);
|
|
1458
|
+
}
|
|
1459
|
+
function formatPhone(phone) {
|
|
1460
|
+
const digits = phone.replace(/\D/g, "");
|
|
1461
|
+
if (digits.length === 11) {
|
|
1462
|
+
return digits.replace(/(\d{2})(\d{5})(\d{4})/, "($1) $2-$3");
|
|
1463
|
+
}
|
|
1464
|
+
return digits.replace(/(\d{2})(\d{4})(\d{4})/, "($1) $2-$3");
|
|
1465
|
+
}
|
|
1466
|
+
function formatCPF(cpf) {
|
|
1467
|
+
const digits = cpf.replace(/\D/g, "");
|
|
1468
|
+
return digits.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
|
|
1469
|
+
}
|
|
1470
|
+
function formatCNPJ(cnpj) {
|
|
1471
|
+
const digits = cnpj.replace(/\D/g, "");
|
|
1472
|
+
return digits.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
|
|
1473
|
+
}
|
|
1474
|
+
function isCPF(cpf) {
|
|
1475
|
+
const digits = cpf.replace(/\D/g, "");
|
|
1476
|
+
if (digits.length !== 11 || /^(\d)\1{10}$/.test(digits)) {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
let sum = 0;
|
|
1480
|
+
for (let i = 0; i < 9; i++) {
|
|
1481
|
+
sum += parseInt(digits.charAt(i)) * (10 - i);
|
|
1482
|
+
}
|
|
1483
|
+
let remainder = sum * 10 % 11;
|
|
1484
|
+
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
1485
|
+
if (remainder !== parseInt(digits.charAt(9))) {
|
|
1486
|
+
return false;
|
|
1487
|
+
}
|
|
1488
|
+
sum = 0;
|
|
1489
|
+
for (let i = 0; i < 10; i++) {
|
|
1490
|
+
sum += parseInt(digits.charAt(i)) * (11 - i);
|
|
1491
|
+
}
|
|
1492
|
+
remainder = sum * 10 % 11;
|
|
1493
|
+
if (remainder === 10 || remainder === 11) remainder = 0;
|
|
1494
|
+
if (remainder !== parseInt(digits.charAt(10))) {
|
|
1495
|
+
return false;
|
|
1496
|
+
}
|
|
1497
|
+
return true;
|
|
1498
|
+
}
|
|
1499
|
+
function isCNPJ(cnpj) {
|
|
1500
|
+
const digits = cnpj.replace(/\D/g, "");
|
|
1501
|
+
if (digits.length !== 14 || /^(\d)\1{13}$/.test(digits)) {
|
|
1502
|
+
return false;
|
|
1503
|
+
}
|
|
1504
|
+
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
1505
|
+
let sum = 0;
|
|
1506
|
+
for (let i = 0; i < 12; i++) {
|
|
1507
|
+
sum += parseInt(digits.charAt(i)) * weights1[i];
|
|
1508
|
+
}
|
|
1509
|
+
let remainder = sum % 11;
|
|
1510
|
+
const digit1 = remainder < 2 ? 0 : 11 - remainder;
|
|
1511
|
+
if (digit1 !== parseInt(digits.charAt(12))) {
|
|
1512
|
+
return false;
|
|
1513
|
+
}
|
|
1514
|
+
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
1515
|
+
sum = 0;
|
|
1516
|
+
for (let i = 0; i < 13; i++) {
|
|
1517
|
+
sum += parseInt(digits.charAt(i)) * weights2[i];
|
|
1518
|
+
}
|
|
1519
|
+
remainder = sum % 11;
|
|
1520
|
+
const digit2 = remainder < 2 ? 0 : 11 - remainder;
|
|
1521
|
+
if (digit2 !== parseInt(digits.charAt(13))) {
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
return true;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
// src/number/index.ts
|
|
1528
|
+
function formatCurrency(value, locale = DEFAULT_LOCALE, options) {
|
|
1529
|
+
const currency = CURRENCY_MAP[locale];
|
|
1530
|
+
return new Intl.NumberFormat(locale, {
|
|
1531
|
+
style: "currency",
|
|
1532
|
+
currency,
|
|
1533
|
+
...options
|
|
1534
|
+
}).format(value);
|
|
1535
|
+
}
|
|
1536
|
+
function formatNumber2(value, decimals = 0, locale = DEFAULT_LOCALE) {
|
|
1537
|
+
return new Intl.NumberFormat(locale, {
|
|
1538
|
+
minimumFractionDigits: decimals,
|
|
1539
|
+
maximumFractionDigits: decimals
|
|
1540
|
+
}).format(value);
|
|
1541
|
+
}
|
|
1542
|
+
function formatCompact(value, decimals = 1, locale = DEFAULT_LOCALE) {
|
|
1543
|
+
return new Intl.NumberFormat(locale, {
|
|
1544
|
+
notation: "compact",
|
|
1545
|
+
compactDisplay: "short",
|
|
1546
|
+
minimumFractionDigits: decimals,
|
|
1547
|
+
maximumFractionDigits: decimals
|
|
1548
|
+
}).format(value);
|
|
1549
|
+
}
|
|
1048
1550
|
function usePasswordStrength(password, options = {}) {
|
|
1049
1551
|
const {
|
|
1050
1552
|
minLength = 8,
|
|
@@ -1235,6 +1737,7 @@ function usePasswordStrength(password, options = {}) {
|
|
|
1235
1737
|
// src/pt-br.ts
|
|
1236
1738
|
var pt_br_exports = {};
|
|
1237
1739
|
__export(pt_br_exports, {
|
|
1740
|
+
default: () => pt_br_default,
|
|
1238
1741
|
formatCompact: () => formatCompact2,
|
|
1239
1742
|
formatCurrency: () => formatCurrency2,
|
|
1240
1743
|
formatDate: () => formatDate2,
|
|
@@ -1256,7 +1759,7 @@ function formatCurrency2(value, options) {
|
|
|
1256
1759
|
return formatCurrency(value, "pt-BR", options);
|
|
1257
1760
|
}
|
|
1258
1761
|
function formatNumber3(value, decimals = 0) {
|
|
1259
|
-
return
|
|
1762
|
+
return formatNumber2(value, decimals, "pt-BR");
|
|
1260
1763
|
}
|
|
1261
1764
|
function formatCompact2(value, decimals = 1) {
|
|
1262
1765
|
return formatCompact(value, decimals, "pt-BR");
|
|
@@ -1264,40 +1767,210 @@ function formatCompact2(value, decimals = 1) {
|
|
|
1264
1767
|
function translateStatus2(status) {
|
|
1265
1768
|
return translateStatus(status, "pt-BR");
|
|
1266
1769
|
}
|
|
1770
|
+
var pt_br_default = {
|
|
1771
|
+
formatDate: formatDate2,
|
|
1772
|
+
formatDateTime: formatDateTime2,
|
|
1773
|
+
formatRelativeDate: formatRelativeDate2,
|
|
1774
|
+
formatCurrency: formatCurrency2,
|
|
1775
|
+
formatNumber: formatNumber3,
|
|
1776
|
+
formatCompact: formatCompact2,
|
|
1777
|
+
translateStatus: translateStatus2
|
|
1778
|
+
};
|
|
1779
|
+
|
|
1780
|
+
// src/text/index.ts
|
|
1781
|
+
var text_exports = {};
|
|
1782
|
+
__export(text_exports, {
|
|
1783
|
+
calculateReadingTime: () => calculateReadingTime,
|
|
1784
|
+
capitalize: () => capitalize,
|
|
1785
|
+
cleanText: () => cleanText2,
|
|
1786
|
+
countWords: () => countWords2,
|
|
1787
|
+
extractInitials: () => extractInitials,
|
|
1788
|
+
generateAvatarUrl: () => generateAvatarUrl,
|
|
1789
|
+
generateDynamicAvatarUrl: () => generateDynamicAvatarUrl,
|
|
1790
|
+
generateUniqueId: () => generateUniqueId,
|
|
1791
|
+
getAvatarColorFromName: () => getAvatarColorFromName,
|
|
1792
|
+
isEmpty: () => isEmpty,
|
|
1793
|
+
isValidAvatarUrl: () => isValidAvatarUrl,
|
|
1794
|
+
normalizeSpaces: () => normalizeSpaces,
|
|
1795
|
+
truncateText: () => truncateText
|
|
1796
|
+
});
|
|
1797
|
+
function extractInitials(name, maxChars = 2) {
|
|
1798
|
+
if (!name || !name.trim()) {
|
|
1799
|
+
return "";
|
|
1800
|
+
}
|
|
1801
|
+
const words = name.trim().split(/\s+/);
|
|
1802
|
+
const initials = words.slice(0, maxChars).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
1803
|
+
return initials;
|
|
1804
|
+
}
|
|
1805
|
+
function generateAvatarUrl(name, size = 200, backgroundColor = "0891b2", textColor = "fff") {
|
|
1806
|
+
const encodedName = encodeURIComponent(name);
|
|
1807
|
+
return `https://ui-avatars.com/api/?name=${encodedName}&size=${size}&background=${backgroundColor}&color=${textColor}&font-size=0.5`;
|
|
1808
|
+
}
|
|
1809
|
+
function isValidAvatarUrl(url) {
|
|
1810
|
+
if (!url || typeof url !== "string") {
|
|
1811
|
+
return false;
|
|
1812
|
+
}
|
|
1813
|
+
try {
|
|
1814
|
+
new URL(url);
|
|
1815
|
+
return true;
|
|
1816
|
+
} catch {
|
|
1817
|
+
return false;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
function getAvatarColorFromName(name) {
|
|
1821
|
+
if (!name || typeof name !== "string") {
|
|
1822
|
+
return "#0891b2";
|
|
1823
|
+
}
|
|
1824
|
+
let hash = 0;
|
|
1825
|
+
for (let i = 0; i < name.length; i++) {
|
|
1826
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
1827
|
+
}
|
|
1828
|
+
const colors = [
|
|
1829
|
+
"#0891b2",
|
|
1830
|
+
// cyan-600
|
|
1831
|
+
"#9333ea",
|
|
1832
|
+
// purple-600
|
|
1833
|
+
"#db2777",
|
|
1834
|
+
// pink-600
|
|
1835
|
+
"#059669",
|
|
1836
|
+
// emerald-600
|
|
1837
|
+
"#2563eb",
|
|
1838
|
+
// blue-600
|
|
1839
|
+
"#f97316",
|
|
1840
|
+
// orange-500
|
|
1841
|
+
"#dc2626",
|
|
1842
|
+
// red-600
|
|
1843
|
+
"#7c3aed"
|
|
1844
|
+
// violet-600
|
|
1845
|
+
];
|
|
1846
|
+
const index = Math.abs(hash) % colors.length;
|
|
1847
|
+
return colors[index];
|
|
1848
|
+
}
|
|
1849
|
+
function generateDynamicAvatarUrl(name, size = 200) {
|
|
1850
|
+
const color = getAvatarColorFromName(name);
|
|
1851
|
+
const colorHex = color.replace("#", "");
|
|
1852
|
+
return generateAvatarUrl(name, size, colorHex, "fff");
|
|
1853
|
+
}
|
|
1854
|
+
function generateUniqueId(text, prefix = "", suffix = "") {
|
|
1855
|
+
const slug = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim().substring(0, 50);
|
|
1856
|
+
const parts = [prefix, slug, suffix].filter(Boolean);
|
|
1857
|
+
return parts.join("-");
|
|
1858
|
+
}
|
|
1859
|
+
function truncateText(text, maxLength, suffix = "...") {
|
|
1860
|
+
if (!text || text.length <= maxLength) {
|
|
1861
|
+
return text || "";
|
|
1862
|
+
}
|
|
1863
|
+
return text.substring(0, maxLength - suffix.length) + suffix;
|
|
1864
|
+
}
|
|
1865
|
+
function capitalize(text, options = {}) {
|
|
1866
|
+
if (!text) return "";
|
|
1867
|
+
const { firstWordOnly = false, lowerRest = false } = options;
|
|
1868
|
+
if (firstWordOnly) {
|
|
1869
|
+
return text.charAt(0).toUpperCase() + (lowerRest ? text.slice(1).toLowerCase() : text.slice(1));
|
|
1870
|
+
}
|
|
1871
|
+
if (lowerRest) {
|
|
1872
|
+
return text.replace(/\b\w/g, (char) => char.toUpperCase()).toLowerCase();
|
|
1873
|
+
}
|
|
1874
|
+
return text.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
1875
|
+
}
|
|
1876
|
+
function cleanText2(text, allowSpaces = true) {
|
|
1877
|
+
if (!text) return "";
|
|
1878
|
+
const pattern = allowSpaces ? /[^\w\s]/g : /[^\w]/g;
|
|
1879
|
+
return text.replace(pattern, "");
|
|
1880
|
+
}
|
|
1881
|
+
function countWords2(text) {
|
|
1882
|
+
if (!text || !text.trim()) {
|
|
1883
|
+
return 0;
|
|
1884
|
+
}
|
|
1885
|
+
return text.trim().split(/\s+/).length;
|
|
1886
|
+
}
|
|
1887
|
+
function isEmpty(text) {
|
|
1888
|
+
return !text || !text.trim();
|
|
1889
|
+
}
|
|
1890
|
+
function normalizeSpaces(text, options = {}) {
|
|
1891
|
+
if (!text) return "";
|
|
1892
|
+
const { newlines = false } = options;
|
|
1893
|
+
let cleaned = text;
|
|
1894
|
+
if (newlines) {
|
|
1895
|
+
cleaned = cleaned.replace(/\s+/g, " ");
|
|
1896
|
+
} else {
|
|
1897
|
+
cleaned = cleaned.replace(/\s+/g, " ");
|
|
1898
|
+
}
|
|
1899
|
+
return cleaned.trim();
|
|
1900
|
+
}
|
|
1901
|
+
function calculateReadingTime(content, wordsPerMinute = 200) {
|
|
1902
|
+
let text = "";
|
|
1903
|
+
if (typeof content === "object" && content !== null) {
|
|
1904
|
+
const extractText = (node) => {
|
|
1905
|
+
if (!node) return "";
|
|
1906
|
+
let result = "";
|
|
1907
|
+
if (node.text) {
|
|
1908
|
+
result += node.text + " ";
|
|
1909
|
+
}
|
|
1910
|
+
if (Array.isArray(node.content)) {
|
|
1911
|
+
result += node.content.map(extractText).join(" ");
|
|
1912
|
+
}
|
|
1913
|
+
return result;
|
|
1914
|
+
};
|
|
1915
|
+
text = extractText(content);
|
|
1916
|
+
} else if (typeof content === "string") {
|
|
1917
|
+
text = content.replace(/<[^>]*>/g, "");
|
|
1918
|
+
}
|
|
1919
|
+
const words = text.trim().split(/\s+/).filter((word) => word.length > 0).length;
|
|
1920
|
+
const time = Math.ceil(words / wordsPerMinute);
|
|
1921
|
+
return time > 0 ? time : 1;
|
|
1922
|
+
}
|
|
1267
1923
|
|
|
1268
1924
|
// src/index.ts
|
|
1269
1925
|
var textProcessing = text_exports;
|
|
1270
1926
|
var datetime = date_exports;
|
|
1271
|
-
var authentication =
|
|
1927
|
+
var authentication = authentication_exports;
|
|
1272
1928
|
var stateManagement = status_exports;
|
|
1273
1929
|
|
|
1274
1930
|
exports.CURRENCY_MAP = CURRENCY_MAP;
|
|
1275
1931
|
exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
|
|
1932
|
+
exports.adjustBrightness = adjustBrightness;
|
|
1933
|
+
exports.adjustHue = adjustHue;
|
|
1934
|
+
exports.adjustSaturation = adjustSaturation;
|
|
1276
1935
|
exports.authentication = authentication;
|
|
1277
1936
|
exports.calculateChange = calculateChange;
|
|
1278
1937
|
exports.calculateMovingAverage = calculateMovingAverage;
|
|
1279
1938
|
exports.calculateReadingTime = calculateReadingTime;
|
|
1280
1939
|
exports.capitalize = capitalize;
|
|
1281
|
-
exports.cleanText =
|
|
1940
|
+
exports.cleanText = cleanText2;
|
|
1941
|
+
exports.containsText = containsText;
|
|
1282
1942
|
exports.copyToClipboard = copyToClipboard;
|
|
1283
|
-
exports.
|
|
1943
|
+
exports.countCharacters = countCharacters;
|
|
1944
|
+
exports.countWords = countWords2;
|
|
1945
|
+
exports.createEmptyTiptapContent = createEmptyTiptapContent;
|
|
1946
|
+
exports.darken = darken;
|
|
1284
1947
|
exports.datetime = datetime;
|
|
1285
1948
|
exports.downloadFile = downloadFile;
|
|
1286
1949
|
exports.extractInitials = extractInitials;
|
|
1950
|
+
exports.extractTextFromTiptap = extractTextFromTiptap;
|
|
1287
1951
|
exports.findMinMax = findMinMax;
|
|
1952
|
+
exports.formatCNPJ = formatCNPJ;
|
|
1953
|
+
exports.formatCPF = formatCPF;
|
|
1288
1954
|
exports.formatCurrency = formatCurrency;
|
|
1289
1955
|
exports.formatDate = formatDate;
|
|
1290
1956
|
exports.formatDateTime = formatDateTime;
|
|
1291
|
-
exports.formatNumber =
|
|
1957
|
+
exports.formatNumber = formatNumber;
|
|
1292
1958
|
exports.formatPercentage = formatPercentage;
|
|
1959
|
+
exports.formatPhone = formatPhone;
|
|
1293
1960
|
exports.formatRelativeDate = formatRelativeDate;
|
|
1294
1961
|
exports.fuzzySearch = fuzzySearch;
|
|
1295
1962
|
exports.generateAvatarUrl = generateAvatarUrl;
|
|
1296
1963
|
exports.generateDynamicAvatarUrl = generateDynamicAvatarUrl;
|
|
1964
|
+
exports.generateExcerpt = generateExcerpt;
|
|
1297
1965
|
exports.generateMockChartData = generateMockChartData;
|
|
1298
1966
|
exports.generateUniqueId = generateUniqueId;
|
|
1967
|
+
exports.getAnalogousPalette = getAnalogousPalette;
|
|
1299
1968
|
exports.getAvatarColorFromName = getAvatarColorFromName;
|
|
1969
|
+
exports.getComplementary = getComplementary;
|
|
1970
|
+
exports.getContentStats = getContentStats;
|
|
1300
1971
|
exports.getElementPosition = getElementPosition;
|
|
1972
|
+
exports.getInitials = getInitials;
|
|
1973
|
+
exports.getReadingTime = getReadingTime;
|
|
1301
1974
|
exports.getRefreshToken = getRefreshToken;
|
|
1302
1975
|
exports.getStatusColor = getStatusColor;
|
|
1303
1976
|
exports.getStatusVariant = getStatusVariant;
|
|
@@ -1305,18 +1978,28 @@ exports.getToken = getToken;
|
|
|
1305
1978
|
exports.getTokens = getTokens;
|
|
1306
1979
|
exports.groupDataByPeriod = groupDataByPeriod;
|
|
1307
1980
|
exports.hasToken = hasToken;
|
|
1981
|
+
exports.hexToHsl = hexToHsl;
|
|
1982
|
+
exports.hexToRgb = hexToRgb;
|
|
1983
|
+
exports.hexToRgba = hexToRgba;
|
|
1984
|
+
exports.hslToHex = hslToHex;
|
|
1985
|
+
exports.isCNPJ = isCNPJ;
|
|
1986
|
+
exports.isCPF = isCPF;
|
|
1987
|
+
exports.isContentEmpty = isContentEmpty;
|
|
1308
1988
|
exports.isDarkMode = isDarkMode;
|
|
1309
1989
|
exports.isElementVisible = isElementVisible;
|
|
1310
1990
|
exports.isEmpty = isEmpty;
|
|
1311
1991
|
exports.isMobile = isMobile;
|
|
1312
1992
|
exports.isValidAvatarUrl = isValidAvatarUrl;
|
|
1313
1993
|
exports.isValidDate = isValidDate;
|
|
1994
|
+
exports.lighten = lighten;
|
|
1314
1995
|
exports.normalizeSpaces = normalizeSpaces;
|
|
1315
1996
|
exports.onDarkModeChange = onDarkModeChange;
|
|
1316
1997
|
exports.onReducedMotionChange = onReducedMotionChange;
|
|
1317
1998
|
exports.prefersReducedMotion = prefersReducedMotion;
|
|
1318
1999
|
exports.ptBR = pt_br_exports;
|
|
1319
2000
|
exports.removeToken = removeToken;
|
|
2001
|
+
exports.replaceText = replaceText;
|
|
2002
|
+
exports.rgbToHex = rgbToHex;
|
|
1320
2003
|
exports.scrollToElement = scrollToElement;
|
|
1321
2004
|
exports.scrollToPosition = scrollToPosition;
|
|
1322
2005
|
exports.scrollToTop = scrollToTop;
|
|
@@ -1332,8 +2015,15 @@ exports.textToSlug = textToSlug;
|
|
|
1332
2015
|
exports.toISOString = toISOString;
|
|
1333
2016
|
exports.translatePostStatus = translatePostStatus;
|
|
1334
2017
|
exports.translateStatus = translateStatus;
|
|
2018
|
+
exports.truncate = truncate;
|
|
1335
2019
|
exports.truncateText = truncateText;
|
|
2020
|
+
exports.useAuth = useAuth;
|
|
2021
|
+
exports.useCurrentUser = useCurrentUser;
|
|
2022
|
+
exports.useHasRole = useHasRole;
|
|
2023
|
+
exports.useIsAdmin = useIsAdmin;
|
|
2024
|
+
exports.useIsAuthenticated = useIsAuthenticated;
|
|
1336
2025
|
exports.usePasswordStrength = usePasswordStrength;
|
|
2026
|
+
exports.validateContrast = validateContrast;
|
|
1337
2027
|
exports.validateEmail = validateEmail;
|
|
1338
2028
|
exports.validateMessage = validateMessage;
|
|
1339
2029
|
exports.validatePassword = validatePassword;
|