@rainersoft/utils 1.0.1 → 1.0.3

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
@@ -1,3 +1,5 @@
1
+ import React from 'react';
2
+
1
3
  var __defProp = Object.defineProperty;
2
4
  var __export = (target, all) => {
3
5
  for (var name in all)
@@ -807,6 +809,192 @@ function findMinMax(data, field) {
807
809
  max: Math.max(...values)
808
810
  };
809
811
  }
812
+ function usePasswordStrength(password, options = {}) {
813
+ const {
814
+ minLength = 8,
815
+ requireUppercase = true,
816
+ requireLowercase = true,
817
+ requireNumbers = true,
818
+ requireSpecialChars = true,
819
+ customPatterns = [],
820
+ labels = {}
821
+ } = options;
822
+ const defaultLabels = {
823
+ veryWeak: "Very Weak",
824
+ weak: "Weak",
825
+ fair: "Fair",
826
+ good: "Good",
827
+ strong: "Strong",
828
+ enterPassword: "Enter a password",
829
+ useMinLength: `Use at least ${minLength} characters`,
830
+ addUppercase: "Add uppercase letters",
831
+ addLowercase: "Add lowercase letters",
832
+ addNumbers: "Add numbers",
833
+ addSpecialChars: "Add special characters (!@#$%)",
834
+ avoidRepeating: "Avoid repeating characters",
835
+ avoidCommon: "Avoid common passwords or obvious patterns"
836
+ };
837
+ const finalLabels = { ...defaultLabels, ...labels };
838
+ const strength = React.useMemo(() => {
839
+ if (!password) return 0;
840
+ let score = 0;
841
+ const length = password.length;
842
+ if (length >= minLength) score += 25;
843
+ if (length >= 12) score += 15;
844
+ if (length >= 16) score += 10;
845
+ if (/[a-z]/.test(password) && requireLowercase) score += 15;
846
+ if (/[A-Z]/.test(password) && requireUppercase) score += 15;
847
+ if (/[0-9]/.test(password) && requireNumbers) score += 15;
848
+ if (/[^a-zA-Z0-9]/.test(password) && requireSpecialChars) score += 20;
849
+ customPatterns.forEach((pattern) => {
850
+ if (new RegExp(pattern).test(password)) {
851
+ score += 5;
852
+ }
853
+ });
854
+ if (/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9])/.test(password)) {
855
+ score += 10;
856
+ }
857
+ const commonPatterns = [
858
+ /^123456/,
859
+ /password/i,
860
+ /qwerty/i,
861
+ /admin/i,
862
+ /abc123/i,
863
+ /^(.)\1+$/,
864
+ // Caracteres repetidos
865
+ /^(?:[a-z]+|[A-Z]+|[0-9]+)$/
866
+ // Apenas um tipo de caractere
867
+ ];
868
+ commonPatterns.forEach((pattern) => {
869
+ if (pattern.test(password)) {
870
+ score = Math.max(0, score - 20);
871
+ }
872
+ });
873
+ return Math.min(100, Math.max(0, score));
874
+ }, [password, minLength, requireUppercase, requireLowercase, requireNumbers, requireSpecialChars, customPatterns]);
875
+ const level = React.useMemo(() => {
876
+ if (strength < 20) return "very-weak";
877
+ if (strength < 40) return "weak";
878
+ if (strength < 60) return "fair";
879
+ if (strength < 80) return "good";
880
+ return "strong";
881
+ }, [strength]);
882
+ const color = React.useMemo(() => {
883
+ switch (level) {
884
+ case "very-weak":
885
+ return "#ef4444";
886
+ // red-500
887
+ case "weak":
888
+ return "#f97316";
889
+ // orange-500
890
+ case "fair":
891
+ return "#eab308";
892
+ // yellow-500
893
+ case "good":
894
+ return "#22c55e";
895
+ // green-500
896
+ case "strong":
897
+ return "#059669";
898
+ // emerald-600
899
+ default:
900
+ return "#6b7280";
901
+ }
902
+ }, [level]);
903
+ const label = React.useMemo(() => {
904
+ switch (level) {
905
+ case "very-weak":
906
+ return finalLabels.veryWeak;
907
+ case "weak":
908
+ return finalLabels.weak;
909
+ case "fair":
910
+ return finalLabels.fair;
911
+ case "good":
912
+ return finalLabels.good;
913
+ case "strong":
914
+ return finalLabels.strong;
915
+ default:
916
+ return finalLabels.enterPassword;
917
+ }
918
+ }, [level, finalLabels]);
919
+ const validations = React.useMemo(() => {
920
+ return {
921
+ hasMinLength: password.length >= minLength,
922
+ hasUppercase: !requireUppercase || /[A-Z]/.test(password),
923
+ hasLowercase: !requireLowercase || /[a-z]/.test(password),
924
+ hasNumbers: !requireNumbers || /[0-9]/.test(password),
925
+ hasSpecialChars: !requireSpecialChars || /[^a-zA-Z0-9]/.test(password),
926
+ noRepeatingChars: !/^(.)\1+$/.test(password),
927
+ noCommonPatterns: !/123456|password|qwerty|admin|abc123/i.test(password)
928
+ };
929
+ }, [password, minLength, requireUppercase, requireLowercase, requireNumbers, requireSpecialChars]);
930
+ const isValid = React.useMemo(() => {
931
+ return Object.values(validations).every(Boolean);
932
+ }, [validations]);
933
+ const suggestions = React.useMemo(() => {
934
+ const suggestions2 = [];
935
+ if (!validations.hasMinLength) {
936
+ suggestions2.push(finalLabels.useMinLength);
937
+ }
938
+ if (!validations.hasUppercase && requireUppercase) {
939
+ suggestions2.push(finalLabels.addUppercase);
940
+ }
941
+ if (!validations.hasLowercase && requireLowercase) {
942
+ suggestions2.push(finalLabels.addLowercase);
943
+ }
944
+ if (!validations.hasNumbers && requireNumbers) {
945
+ suggestions2.push(finalLabels.addNumbers);
946
+ }
947
+ if (!validations.hasSpecialChars && requireSpecialChars) {
948
+ suggestions2.push(finalLabels.addSpecialChars);
949
+ }
950
+ if (!validations.noRepeatingChars) {
951
+ suggestions2.push(finalLabels.avoidRepeating);
952
+ }
953
+ if (!validations.noCommonPatterns) {
954
+ suggestions2.push(finalLabels.avoidCommon);
955
+ }
956
+ return suggestions2;
957
+ }, [validations, finalLabels, minLength, requireUppercase, requireLowercase, requireNumbers, requireSpecialChars]);
958
+ const generateStrongPassword = React.useCallback((length = 16) => {
959
+ const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
960
+ const lowercase = "abcdefghijklmnopqrstuvwxyz";
961
+ const numbers = "0123456789";
962
+ const special = "!@#$%^&*()_+-=[]{}|;:,.<>?";
963
+ let chars = lowercase;
964
+ if (requireUppercase) chars += uppercase;
965
+ if (requireNumbers) chars += numbers;
966
+ if (requireSpecialChars) chars += special;
967
+ let password2 = "";
968
+ if (requireLowercase) password2 += lowercase[Math.floor(Math.random() * lowercase.length)];
969
+ if (requireUppercase) password2 += uppercase[Math.floor(Math.random() * uppercase.length)];
970
+ if (requireNumbers) password2 += numbers[Math.floor(Math.random() * numbers.length)];
971
+ if (requireSpecialChars) password2 += special[Math.floor(Math.random() * special.length)];
972
+ for (let i = password2.length; i < length; i++) {
973
+ password2 += chars[Math.floor(Math.random() * chars.length)];
974
+ }
975
+ return password2.split("").sort(() => Math.random() - 0.5).join("");
976
+ }, [requireUppercase, requireLowercase, requireNumbers, requireSpecialChars]);
977
+ return {
978
+ // Métricas principais
979
+ strength,
980
+ level,
981
+ color,
982
+ label,
983
+ isValid,
984
+ // Validações detalhadas
985
+ validations,
986
+ // Feedback ao usuário
987
+ suggestions,
988
+ // Utilitários
989
+ generateStrongPassword,
990
+ // Estados convenientes
991
+ isVeryWeak: level === "very-weak",
992
+ isWeak: level === "weak",
993
+ isFair: level === "fair",
994
+ isGood: level === "good",
995
+ isStrong: level === "strong"
996
+ };
997
+ }
810
998
 
811
999
  // src/pt-br.ts
812
1000
  var pt_br_exports = {};
@@ -841,6 +1029,6 @@ function translateStatus2(status) {
841
1029
  return translateStatus(status, "pt-BR");
842
1030
  }
843
1031
 
844
- export { CURRENCY_MAP, DEFAULT_LOCALE, calculateChange, calculateMovingAverage, capitalize, cleanText, copyToClipboard, countWords, downloadFile, extractInitials, findMinMax, formatCurrency, formatDate, formatDateTime, formatNumber2 as formatNumber, formatPercentage, formatRelativeDate, generateAvatarUrl, generateDynamicAvatarUrl, generateMockChartData, generateUniqueId, getAvatarColorFromName, getElementPosition, getStatusColor, getStatusVariant, groupDataByPeriod, isDarkMode, isElementVisible, isEmpty, isMobile, isValidAvatarUrl, isValidDate, normalizeSpaces, onDarkModeChange, onReducedMotionChange, prefersReducedMotion, pt_br_exports as ptBR, scrollToElement, scrollToPosition, scrollToTop, smoothScrollTo, textToSlug, toISOString, translateStatus, truncateText, validateEmail, validatePassword, validatePhone, validateSlug, validateText, validateUrl, validateUsername };
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 };
845
1033
  //# sourceMappingURL=index.mjs.map
846
1034
  //# sourceMappingURL=index.mjs.map