@rainersoft/utils 1.0.4 → 1.2.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/index.mjs CHANGED
@@ -119,6 +119,28 @@ function normalizeSpaces(text, options = {}) {
119
119
  }
120
120
  return cleaned.trim();
121
121
  }
122
+ function calculateReadingTime(content, wordsPerMinute = 200) {
123
+ let text = "";
124
+ if (typeof content === "object" && content !== null) {
125
+ const extractText = (node) => {
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
+ }
122
144
 
123
145
  // src/string/index.ts
124
146
  function textToSlug(text) {
@@ -357,6 +379,25 @@ function getStatusVariant(status) {
357
379
  }
358
380
  return "outline";
359
381
  }
382
+ function translatePostStatus(status, locale = DEFAULT_LOCALE) {
383
+ const postStatusMap = {
384
+ "draft": "DRAFT",
385
+ "published": "PUBLISHED",
386
+ "archived": "ARCHIVED",
387
+ "scheduled": "SCHEDULED",
388
+ "pending_review": "PENDING"
389
+ };
390
+ const normalized = postStatusMap[status.toLowerCase()] || status.toUpperCase();
391
+ if (status.toLowerCase() === "pending_review") {
392
+ const translations = {
393
+ "pt-BR": "Aguardando Revis\xE3o",
394
+ "en-US": "Pending Review",
395
+ "es-ES": "Pendiente de Revisi\xF3n"
396
+ };
397
+ return translations[locale] || translations["pt-BR"];
398
+ }
399
+ return translateStatus(normalized, locale);
400
+ }
360
401
 
361
402
  // src/validation/index.ts
362
403
  function validateEmail(email, locale = DEFAULT_LOCALE) {
@@ -572,6 +613,17 @@ function validateText(text, options = {}, locale = DEFAULT_LOCALE) {
572
613
  errors
573
614
  };
574
615
  }
616
+ function validateMessage(message, options = {}, locale = DEFAULT_LOCALE) {
617
+ const {
618
+ minLength = 10,
619
+ maxLength = 1e3
620
+ } = options;
621
+ return validateText(message, {
622
+ minLength,
623
+ maxLength,
624
+ fieldName: locale === "pt-BR" ? "Mensagem" : locale === "en-US" ? "Message" : "Mensaje"
625
+ }, locale);
626
+ }
575
627
 
576
628
  // src/dom/index.ts
577
629
  function prefersReducedMotion() {
@@ -809,6 +861,142 @@ function findMinMax(data, field) {
809
861
  max: Math.max(...values)
810
862
  };
811
863
  }
864
+
865
+ // src/auth/index.ts
866
+ var TOKEN_KEY = "auth_token";
867
+ var REFRESH_TOKEN_KEY = "refresh_token";
868
+ var getToken = () => {
869
+ if (typeof window === "undefined") {
870
+ return null;
871
+ }
872
+ return localStorage.getItem(TOKEN_KEY);
873
+ };
874
+ var setToken = (token) => {
875
+ if (typeof window === "undefined") {
876
+ return;
877
+ }
878
+ localStorage.setItem(TOKEN_KEY, token);
879
+ };
880
+ var getRefreshToken = () => {
881
+ if (typeof window === "undefined") {
882
+ return null;
883
+ }
884
+ return localStorage.getItem(REFRESH_TOKEN_KEY);
885
+ };
886
+ var setRefreshToken = (refreshToken) => {
887
+ if (typeof window === "undefined") {
888
+ return;
889
+ }
890
+ localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken);
891
+ };
892
+ var removeToken = () => {
893
+ if (typeof window === "undefined") {
894
+ return;
895
+ }
896
+ localStorage.removeItem(TOKEN_KEY);
897
+ localStorage.removeItem(REFRESH_TOKEN_KEY);
898
+ };
899
+ var hasToken = () => {
900
+ return !!getToken();
901
+ };
902
+ var getTokens = () => {
903
+ return {
904
+ accessToken: getToken(),
905
+ refreshToken: getRefreshToken()
906
+ };
907
+ };
908
+ var setTokens = ({
909
+ accessToken,
910
+ refreshToken
911
+ }) => {
912
+ setToken(accessToken);
913
+ setRefreshToken(refreshToken);
914
+ };
915
+
916
+ // src/search/index.ts
917
+ function searchContent(query, content, options = {}) {
918
+ if (!query.trim()) return content;
919
+ const {
920
+ fields = ["title", "description", "content", "tags"],
921
+ caseSensitive = false,
922
+ exactMatch = false
923
+ } = options;
924
+ const searchQuery = caseSensitive ? query : query.toLowerCase();
925
+ return content.filter((item) => {
926
+ return fields.some((field) => {
927
+ const value = item[field];
928
+ if (!value) return false;
929
+ if (Array.isArray(value)) {
930
+ return value.some((v) => {
931
+ const strValue2 = caseSensitive ? String(v) : String(v).toLowerCase();
932
+ return exactMatch ? strValue2 === searchQuery : strValue2.includes(searchQuery);
933
+ });
934
+ }
935
+ const strValue = caseSensitive ? String(value) : String(value).toLowerCase();
936
+ return exactMatch ? strValue === searchQuery : strValue.includes(searchQuery);
937
+ });
938
+ });
939
+ }
940
+ function searchWithScore(query, content, options = {}) {
941
+ if (!query.trim()) return content;
942
+ const {
943
+ fields = ["title", "description", "content", "tags"],
944
+ caseSensitive = false
945
+ } = options;
946
+ const searchQuery = caseSensitive ? query : query.toLowerCase();
947
+ const scored = content.map((item) => {
948
+ let score = 0;
949
+ fields.forEach((field, index) => {
950
+ const value = item[field];
951
+ if (!value) return;
952
+ const weight = fields.length - index;
953
+ if (Array.isArray(value)) {
954
+ const matches = value.filter((v) => {
955
+ const strValue = caseSensitive ? String(v) : String(v).toLowerCase();
956
+ return strValue.includes(searchQuery);
957
+ }).length;
958
+ score += matches * weight;
959
+ } else {
960
+ const strValue = caseSensitive ? String(value) : String(value).toLowerCase();
961
+ if (strValue.includes(searchQuery)) {
962
+ score += weight;
963
+ if (strValue === searchQuery) {
964
+ score += weight * 2;
965
+ }
966
+ }
967
+ }
968
+ });
969
+ return { item, score };
970
+ });
971
+ return scored.filter(({ score }) => score > 0).sort((a, b) => b.score - a.score).map(({ item }) => item);
972
+ }
973
+ function fuzzySearch(query, content, options = {}) {
974
+ if (!query.trim()) return content;
975
+ const {
976
+ fields = ["title", "description"],
977
+ caseSensitive = false,
978
+ threshold = 0.6
979
+ // Similaridade mínima (0-1)
980
+ } = options;
981
+ const searchQuery = caseSensitive ? query : query.toLowerCase();
982
+ return content.filter((item) => {
983
+ return fields.some((field) => {
984
+ const value = item[field];
985
+ if (!value) return false;
986
+ const strValue = caseSensitive ? String(value) : String(value).toLowerCase();
987
+ const similarity = calculateSimilarity(searchQuery, strValue);
988
+ return similarity >= threshold;
989
+ });
990
+ });
991
+ }
992
+ function calculateSimilarity(str1, str2) {
993
+ if (str1 === str2) return 1;
994
+ if (str1.length === 0 || str2.length === 0) return 0;
995
+ if (str2.includes(str1)) return 0.8;
996
+ const common = str1.split("").filter((char) => str2.includes(char)).length;
997
+ const similarity = common / Math.max(str1.length, str2.length);
998
+ return similarity;
999
+ }
812
1000
  function usePasswordStrength(password, options = {}) {
813
1001
  const {
814
1002
  minLength = 8,
@@ -1029,6 +1217,6 @@ function translateStatus2(status) {
1029
1217
  return translateStatus(status, "pt-BR");
1030
1218
  }
1031
1219
 
1032
- export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime, formatNumber2 as formatNumber, formatPercentage, formatRelativeDate, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, getStatusColor, getStatusVariant, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, isValidDate, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, textToSlug, toISOString, translateStatus, truncateText, usePasswordStrength, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
1220
+ export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, calculateReadingTime, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime, formatNumber2 as formatNumber, formatPercentage, formatRelativeDate, fuzzySearch, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, getRefreshToken, getStatusColor, getStatusVariant, getToken, getTokens, groupDataByPeriod, hasToken, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, isValidDate, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, removeToken, scrollToElement, scrollToPosition, scrollToTop, searchContent, searchWithScore, setRefreshToken, setToken, setTokens, smoothScrollTo, textToSlug, toISOString, translatePostStatus, translateStatus, truncateText, usePasswordStrength, validateEmail, validateMessage, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
1033
1221
  //# sourceMappingURL=index.mjs.map
1034
1222
  //# sourceMappingURL=index.mjs.map