@seedgrid/fe-components 0.2.4
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/blocked-email-domains.json +41 -0
- package/dist/buttons/SgButton.d.ts +43 -0
- package/dist/buttons/SgButton.d.ts.map +1 -0
- package/dist/buttons/SgButton.js +123 -0
- package/dist/buttons/SgFloatActionButton.d.ts +60 -0
- package/dist/buttons/SgFloatActionButton.d.ts.map +1 -0
- package/dist/buttons/SgFloatActionButton.js +532 -0
- package/dist/buttons/SgSpeedDial.d.ts +40 -0
- package/dist/buttons/SgSpeedDial.d.ts.map +1 -0
- package/dist/buttons/SgSpeedDial.js +149 -0
- package/dist/buttons/SgSplitButton.d.ts +32 -0
- package/dist/buttons/SgSplitButton.d.ts.map +1 -0
- package/dist/buttons/SgSplitButton.js +81 -0
- package/dist/clock/SgClock.d.ts +28 -0
- package/dist/clock/SgClock.d.ts.map +1 -0
- package/dist/clock/SgClock.js +280 -0
- package/dist/clock/SgTimeProvider.d.ts +13 -0
- package/dist/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/clock/SgTimeProvider.js +44 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/clock/themes/builtins.d.ts +3 -0
- package/dist/clock/themes/builtins.d.ts.map +1 -0
- package/dist/clock/themes/builtins.js +241 -0
- package/dist/clock/themes/index.d.ts +9 -0
- package/dist/clock/themes/index.d.ts.map +1 -0
- package/dist/clock/themes/index.js +7 -0
- package/dist/clock/themes/provider.d.ts +19 -0
- package/dist/clock/themes/provider.d.ts.map +1 -0
- package/dist/clock/themes/provider.js +54 -0
- package/dist/clock/themes/registry.d.ts +9 -0
- package/dist/clock/themes/registry.d.ts.map +1 -0
- package/dist/clock/themes/registry.js +25 -0
- package/dist/clock/themes/renderTheme.d.ts +7 -0
- package/dist/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/clock/themes/renderTheme.js +41 -0
- package/dist/clock/themes/types.d.ts +21 -0
- package/dist/clock/themes/types.d.ts.map +1 -0
- package/dist/clock/themes/types.js +1 -0
- package/dist/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/clock/themes/urlThemeCache.js +11 -0
- package/dist/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/clock/themes/useDarkFlag.js +14 -0
- package/dist/commons/SgBadge.d.ts +51 -0
- package/dist/commons/SgBadge.d.ts.map +1 -0
- package/dist/commons/SgBadge.js +141 -0
- package/dist/commons/SgBadgeOverlay.d.ts +13 -0
- package/dist/commons/SgBadgeOverlay.d.ts.map +1 -0
- package/dist/commons/SgBadgeOverlay.js +20 -0
- package/dist/commons/SgButton.d.ts +39 -0
- package/dist/commons/SgButton.d.ts.map +1 -0
- package/dist/commons/SgButton.js +116 -0
- package/dist/commons/SgPopup.d.ts +42 -0
- package/dist/commons/SgPopup.d.ts.map +1 -0
- package/dist/commons/SgPopup.js +218 -0
- package/dist/commons/SgToast.d.ts +44 -0
- package/dist/commons/SgToast.d.ts.map +1 -0
- package/dist/commons/SgToast.js +97 -0
- package/dist/commons/SgToaster.d.ts +11 -0
- package/dist/commons/SgToaster.d.ts.map +1 -0
- package/dist/commons/SgToaster.js +85 -0
- package/dist/commons/common-passwords.d.ts +2 -0
- package/dist/commons/common-passwords.d.ts.map +1 -0
- package/dist/commons/common-passwords.js +167 -0
- package/dist/environment/SgEnvironmentProvider.d.ts +31 -0
- package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -0
- package/dist/environment/SgEnvironmentProvider.js +120 -0
- package/dist/environment/persistence.d.ts +44 -0
- package/dist/environment/persistence.d.ts.map +1 -0
- package/dist/environment/persistence.js +149 -0
- package/dist/gadgets/clock/SgClock.d.ts +18 -0
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -0
- package/dist/gadgets/clock/SgClock.js +407 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts +13 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/gadgets/clock/SgTimeProvider.js +44 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/gadgets/clock/themes/builtins.d.ts +3 -0
- package/dist/gadgets/clock/themes/builtins.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/builtins.js +241 -0
- package/dist/gadgets/clock/themes/index.d.ts +9 -0
- package/dist/gadgets/clock/themes/index.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/index.js +7 -0
- package/dist/gadgets/clock/themes/provider.d.ts +19 -0
- package/dist/gadgets/clock/themes/provider.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/provider.js +54 -0
- package/dist/gadgets/clock/themes/registry.d.ts +9 -0
- package/dist/gadgets/clock/themes/registry.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/registry.js +25 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts +7 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/renderTheme.js +41 -0
- package/dist/gadgets/clock/themes/types.d.ts +21 -0
- package/dist/gadgets/clock/themes/types.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/types.js +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.js +11 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/useDarkFlag.js +14 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +23 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.js +118 -0
- package/dist/gadgets/flip-digit/index.d.ts +3 -0
- package/dist/gadgets/flip-digit/index.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/index.js +1 -0
- package/dist/i18n/en-US.json +76 -0
- package/dist/i18n/es.json +76 -0
- package/dist/i18n/index.d.ts +328 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +87 -0
- package/dist/i18n/pt-BR.json +76 -0
- package/dist/i18n/pt-PT.json +76 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/inputs/FloatingInput.d.ts +13 -0
- package/dist/inputs/FloatingInput.d.ts.map +1 -0
- package/dist/inputs/FloatingInput.js +53 -0
- package/dist/inputs/FloatingSelect.d.ts +15 -0
- package/dist/inputs/FloatingSelect.d.ts.map +1 -0
- package/dist/inputs/FloatingSelect.js +52 -0
- package/dist/inputs/FloatingTextArea.d.ts +11 -0
- package/dist/inputs/FloatingTextArea.d.ts.map +1 -0
- package/dist/inputs/FloatingTextArea.js +34 -0
- package/dist/inputs/InputBirthDate.d.ts +13 -0
- package/dist/inputs/InputBirthDate.d.ts.map +1 -0
- package/dist/inputs/InputBirthDate.js +46 -0
- package/dist/inputs/InputDate.d.ts +8 -0
- package/dist/inputs/InputDate.d.ts.map +1 -0
- package/dist/inputs/InputDate.js +23 -0
- package/dist/inputs/InputEmail.d.ts +14 -0
- package/dist/inputs/InputEmail.d.ts.map +1 -0
- package/dist/inputs/InputEmail.js +43 -0
- package/dist/inputs/InputPassword.d.ts +12 -0
- package/dist/inputs/InputPassword.d.ts.map +1 -0
- package/dist/inputs/InputPassword.js +42 -0
- package/dist/inputs/MaskedInputs.d.ts +27 -0
- package/dist/inputs/MaskedInputs.d.ts.map +1 -0
- package/dist/inputs/MaskedInputs.js +161 -0
- package/dist/inputs/SgAutocomplete.d.ts +42 -0
- package/dist/inputs/SgAutocomplete.d.ts.map +1 -0
- package/dist/inputs/SgAutocomplete.js +241 -0
- package/dist/inputs/SgCurrencyEdit.d.ts +56 -0
- package/dist/inputs/SgCurrencyEdit.d.ts.map +1 -0
- package/dist/inputs/SgCurrencyEdit.js +496 -0
- package/dist/inputs/SgInputBirthDate.d.ts +13 -0
- package/dist/inputs/SgInputBirthDate.d.ts.map +1 -0
- package/dist/inputs/SgInputBirthDate.js +48 -0
- package/dist/inputs/SgInputCEP.d.ts +33 -0
- package/dist/inputs/SgInputCEP.d.ts.map +1 -0
- package/dist/inputs/SgInputCEP.js +117 -0
- package/dist/inputs/SgInputCNPJ.d.ts +20 -0
- package/dist/inputs/SgInputCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCNPJ.js +133 -0
- package/dist/inputs/SgInputCPF.d.ts +15 -0
- package/dist/inputs/SgInputCPF.d.ts.map +1 -0
- package/dist/inputs/SgInputCPF.js +70 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts +15 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCPFCNPJ.js +92 -0
- package/dist/inputs/SgInputDate.d.ts +8 -0
- package/dist/inputs/SgInputDate.d.ts.map +1 -0
- package/dist/inputs/SgInputDate.js +120 -0
- package/dist/inputs/SgInputEmail.d.ts +16 -0
- package/dist/inputs/SgInputEmail.d.ts.map +1 -0
- package/dist/inputs/SgInputEmail.js +74 -0
- package/dist/inputs/SgInputFone.d.ts +15 -0
- package/dist/inputs/SgInputFone.d.ts.map +1 -0
- package/dist/inputs/SgInputFone.js +60 -0
- package/dist/inputs/SgInputMasked.d.ts +27 -0
- package/dist/inputs/SgInputMasked.d.ts.map +1 -0
- package/dist/inputs/SgInputMasked.js +161 -0
- package/dist/inputs/SgInputNumber.d.ts +49 -0
- package/dist/inputs/SgInputNumber.d.ts.map +1 -0
- package/dist/inputs/SgInputNumber.js +438 -0
- package/dist/inputs/SgInputPassword.d.ts +26 -0
- package/dist/inputs/SgInputPassword.d.ts.map +1 -0
- package/dist/inputs/SgInputPassword.js +278 -0
- package/dist/inputs/SgInputPhone.d.ts +15 -0
- package/dist/inputs/SgInputPhone.d.ts.map +1 -0
- package/dist/inputs/SgInputPhone.js +66 -0
- package/dist/inputs/SgInputPostalCode.d.ts +37 -0
- package/dist/inputs/SgInputPostalCode.d.ts.map +1 -0
- package/dist/inputs/SgInputPostalCode.js +193 -0
- package/dist/inputs/SgInputSelect.d.ts +16 -0
- package/dist/inputs/SgInputSelect.d.ts.map +1 -0
- package/dist/inputs/SgInputSelect.js +104 -0
- package/dist/inputs/SgInputText.d.ts +49 -0
- package/dist/inputs/SgInputText.d.ts.map +1 -0
- package/dist/inputs/SgInputText.js +336 -0
- package/dist/inputs/SgInputTextArea.d.ts +41 -0
- package/dist/inputs/SgInputTextArea.d.ts.map +1 -0
- package/dist/inputs/SgInputTextArea.js +216 -0
- package/dist/inputs/SgTextEditor.d.ts +27 -0
- package/dist/inputs/SgTextEditor.d.ts.map +1 -0
- package/dist/inputs/SgTextEditor.js +201 -0
- package/dist/integration/module.d.ts +39 -0
- package/dist/integration/module.d.ts.map +1 -0
- package/dist/integration/module.js +1 -0
- package/dist/layout/GroupBox.d.ts +10 -0
- package/dist/layout/GroupBox.d.ts.map +1 -0
- package/dist/layout/GroupBox.js +14 -0
- package/dist/layout/SgCard.d.ts +35 -0
- package/dist/layout/SgCard.d.ts.map +1 -0
- package/dist/layout/SgCard.js +106 -0
- package/dist/layout/SgDockLayout.d.ts +37 -0
- package/dist/layout/SgDockLayout.d.ts.map +1 -0
- package/dist/layout/SgDockLayout.js +101 -0
- package/dist/layout/SgDockZone.d.ts +12 -0
- package/dist/layout/SgDockZone.d.ts.map +1 -0
- package/dist/layout/SgDockZone.js +20 -0
- package/dist/layout/SgGrid.d.ts +18 -0
- package/dist/layout/SgGrid.d.ts.map +1 -0
- package/dist/layout/SgGrid.js +101 -0
- package/dist/layout/SgGroupBox.d.ts +10 -0
- package/dist/layout/SgGroupBox.d.ts.map +1 -0
- package/dist/layout/SgGroupBox.js +14 -0
- package/dist/layout/SgMainPanel.d.ts +11 -0
- package/dist/layout/SgMainPanel.d.ts.map +1 -0
- package/dist/layout/SgMainPanel.js +70 -0
- package/dist/layout/SgPanel.d.ts +22 -0
- package/dist/layout/SgPanel.d.ts.map +1 -0
- package/dist/layout/SgPanel.js +33 -0
- package/dist/layout/SgScreen.d.ts +11 -0
- package/dist/layout/SgScreen.d.ts.map +1 -0
- package/dist/layout/SgScreen.js +18 -0
- package/dist/layout/SgStack.d.ts +15 -0
- package/dist/layout/SgStack.d.ts.map +1 -0
- package/dist/layout/SgStack.js +32 -0
- package/dist/layout/SgToolBar.d.ts +46 -0
- package/dist/layout/SgToolBar.d.ts.map +1 -0
- package/dist/layout/SgToolBar.js +199 -0
- package/dist/layout/SgTreeView.d.ts +80 -0
- package/dist/layout/SgTreeView.d.ts.map +1 -0
- package/dist/layout/SgTreeView.js +338 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +19 -0
- package/dist/masks.d.ts +14 -0
- package/dist/masks.d.ts.map +1 -0
- package/dist/masks.js +91 -0
- package/dist/overlay/SgDialog.d.ts +39 -0
- package/dist/overlay/SgDialog.d.ts.map +1 -0
- package/dist/overlay/SgDialog.js +177 -0
- package/dist/overlay/SgPopup.d.ts +42 -0
- package/dist/overlay/SgPopup.d.ts.map +1 -0
- package/dist/overlay/SgPopup.js +218 -0
- package/dist/rhf.d.ts +6 -0
- package/dist/rhf.d.ts.map +1 -0
- package/dist/rhf.js +1 -0
- package/dist/validators.d.ts +27 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +218 -0
- package/dist/wizard/SGWizard.d.ts +28 -0
- package/dist/wizard/SGWizard.d.ts.map +1 -0
- package/dist/wizard/SGWizard.js +124 -0
- package/package.json +53 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SgInputText } from "./SgInputText";
|
|
5
|
+
import { maskCep } from "../masks";
|
|
6
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
7
|
+
function onlyDigits(value) {
|
|
8
|
+
return value.replace(/\D/g, "");
|
|
9
|
+
}
|
|
10
|
+
const defaultViaCepFetch = async (cep) => {
|
|
11
|
+
const response = await fetch(`https://viacep.com.br/ws/${cep}/json/`);
|
|
12
|
+
return (await response.json());
|
|
13
|
+
};
|
|
14
|
+
export function SgInputCEP(props) {
|
|
15
|
+
const i18n = useComponentsI18n();
|
|
16
|
+
const { required, requiredMessage, lengthMessage, invalidMessage, validateOnBlur, error, validation, onClear, inputProps, validateWithViaCep, viaCepErrorMessage, viaCepFetch, onViaCepResult, onViaCepError, ...rest } = props;
|
|
17
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
18
|
+
const [hasInteracted, setHasInteracted] = React.useState(false);
|
|
19
|
+
const lastValidatedCepRef = React.useRef(null);
|
|
20
|
+
const lastViaCepErroRef = React.useRef(null);
|
|
21
|
+
const runValidation = React.useCallback(async (value) => {
|
|
22
|
+
const digits = onlyDigits(value);
|
|
23
|
+
if (!digits && !required) {
|
|
24
|
+
setInternalError(null);
|
|
25
|
+
props.onValidation?.(null);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!digits && required) {
|
|
29
|
+
const message = requiredMessage ?? t(i18n, "components.inputs.required");
|
|
30
|
+
setInternalError(message);
|
|
31
|
+
props.onValidation?.(message);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (validation) {
|
|
35
|
+
const message = validation(value);
|
|
36
|
+
if (message) {
|
|
37
|
+
setInternalError(message);
|
|
38
|
+
props.onValidation?.(message);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (digits.length !== 8) {
|
|
43
|
+
const message = lengthMessage ?? t(i18n, "components.inputs.cep.length");
|
|
44
|
+
setInternalError(message);
|
|
45
|
+
props.onValidation?.(message);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (validateWithViaCep) {
|
|
49
|
+
if (lastValidatedCepRef.current === digits) {
|
|
50
|
+
const message = viaCepErrorMessage ?? invalidMessage ?? t(i18n, "components.inputs.cep.invalid");
|
|
51
|
+
if (lastViaCepErroRef.current) {
|
|
52
|
+
setInternalError(message);
|
|
53
|
+
props.onValidation?.(message);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
setInternalError(null);
|
|
57
|
+
props.onValidation?.(null);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const checker = viaCepFetch ?? defaultViaCepFetch;
|
|
63
|
+
const data = await checker(digits);
|
|
64
|
+
lastValidatedCepRef.current = digits;
|
|
65
|
+
lastViaCepErroRef.current = Boolean(data?.erro);
|
|
66
|
+
onViaCepResult?.(data);
|
|
67
|
+
if (data?.erro) {
|
|
68
|
+
const message = viaCepErrorMessage ?? invalidMessage ?? t(i18n, "components.inputs.cep.invalid");
|
|
69
|
+
setInternalError(message);
|
|
70
|
+
props.onValidation?.(message);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
onViaCepError?.(err);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
setInternalError(null);
|
|
79
|
+
props.onValidation?.(null);
|
|
80
|
+
}, [
|
|
81
|
+
i18n,
|
|
82
|
+
invalidMessage,
|
|
83
|
+
lengthMessage,
|
|
84
|
+
onViaCepError,
|
|
85
|
+
onViaCepResult,
|
|
86
|
+
props,
|
|
87
|
+
required,
|
|
88
|
+
requiredMessage,
|
|
89
|
+
validateWithViaCep,
|
|
90
|
+
validation,
|
|
91
|
+
viaCepErrorMessage,
|
|
92
|
+
viaCepFetch
|
|
93
|
+
]);
|
|
94
|
+
const mergedInputProps = {
|
|
95
|
+
...inputProps,
|
|
96
|
+
inputMode: inputProps?.inputMode ?? "numeric",
|
|
97
|
+
onChange: (event) => {
|
|
98
|
+
setHasInteracted(true);
|
|
99
|
+
event.target.value = maskCep(event.target.value);
|
|
100
|
+
runValidation(event.currentTarget.value);
|
|
101
|
+
inputProps?.onChange?.(event);
|
|
102
|
+
},
|
|
103
|
+
onBlur: (event) => {
|
|
104
|
+
if ((validateOnBlur ?? true) || hasInteracted) {
|
|
105
|
+
runValidation(event.currentTarget.value);
|
|
106
|
+
}
|
|
107
|
+
inputProps?.onBlur?.(event);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
return (_jsx(SgInputText, { ...rest, maxLength: rest.maxLength ?? 10, error: error ?? internalError ?? undefined, textInputType: props.textInputType ?? "numeric", onClear: () => {
|
|
111
|
+
setInternalError(null);
|
|
112
|
+
props.onValidation?.(null);
|
|
113
|
+
onClear?.();
|
|
114
|
+
lastValidatedCepRef.current = null;
|
|
115
|
+
lastViaCepErroRef.current = null;
|
|
116
|
+
}, inputProps: mergedInputProps }));
|
|
117
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type SgInputTextProps } from "./SgInputText";
|
|
3
|
+
export type SgInputCNPJProps = Omit<SgInputTextProps, "inputProps" | "error"> & {
|
|
4
|
+
inputProps: React.InputHTMLAttributes<HTMLInputElement>;
|
|
5
|
+
error?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
requiredMessage?: string;
|
|
8
|
+
lengthMessage?: string;
|
|
9
|
+
invalidMessage?: string;
|
|
10
|
+
validation?: (value: string) => string | null;
|
|
11
|
+
onValidation?: (message: string | null) => void;
|
|
12
|
+
validateOnBlur?: boolean;
|
|
13
|
+
validateWithPublicaCnpj?: boolean;
|
|
14
|
+
publicaCnpjErrorMessage?: string;
|
|
15
|
+
publicaCnpjFetch?: (cnpj: string) => Promise<unknown | null>;
|
|
16
|
+
onPublicaCnpjResult?: (data: unknown | null) => void;
|
|
17
|
+
onPublicaCnpjError?: (error: unknown) => void;
|
|
18
|
+
};
|
|
19
|
+
export declare function SgInputCNPJ(props: SgInputCNPJProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=SgInputCNPJ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgInputCNPJ.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputCNPJ.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKnE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,OAAO,CAAC,GAAG;IAC9E,UAAU,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC7D,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C,CAAC;AAgBF,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CA2IlD"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SgInputText } from "./SgInputText";
|
|
5
|
+
import { maskCnpj } from "../masks";
|
|
6
|
+
import { isValidCnpj } from "../validators";
|
|
7
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
8
|
+
function onlyAlnumUpper(value) {
|
|
9
|
+
return value.replace(/[^0-9A-Za-z]/g, "").toUpperCase();
|
|
10
|
+
}
|
|
11
|
+
function onlyDigits(value) {
|
|
12
|
+
return value.replace(/\D/g, "");
|
|
13
|
+
}
|
|
14
|
+
const defaultPublicaCnpjFetch = async (cnpj) => {
|
|
15
|
+
const response = await fetch(`https://publica.cnpj.ws/cnpj/${cnpj}`);
|
|
16
|
+
if (!response.ok)
|
|
17
|
+
return null;
|
|
18
|
+
return response.json();
|
|
19
|
+
};
|
|
20
|
+
export function SgInputCNPJ(props) {
|
|
21
|
+
const i18n = useComponentsI18n();
|
|
22
|
+
const { required, requiredMessage, lengthMessage, invalidMessage, validateOnBlur, error, validation, validateWithPublicaCnpj, publicaCnpjErrorMessage, publicaCnpjFetch, onPublicaCnpjResult, onPublicaCnpjError, ...rest } = props;
|
|
23
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
24
|
+
const lastValidatedCnpjRef = React.useRef(null);
|
|
25
|
+
const lastPublicaFoundRef = React.useRef(null);
|
|
26
|
+
const runValidation = React.useCallback(async (value) => {
|
|
27
|
+
const raw = onlyAlnumUpper(value);
|
|
28
|
+
if (!raw && !required) {
|
|
29
|
+
setInternalError(null);
|
|
30
|
+
props.onValidation?.(null);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!raw && required) {
|
|
34
|
+
const message = requiredMessage ?? t(i18n, "components.inputs.required");
|
|
35
|
+
setInternalError(message);
|
|
36
|
+
props.onValidation?.(message);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (validation) {
|
|
40
|
+
const message = validation(value);
|
|
41
|
+
if (message) {
|
|
42
|
+
setInternalError(message);
|
|
43
|
+
props.onValidation?.(message);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (raw.length !== 14) {
|
|
48
|
+
const message = lengthMessage ?? t(i18n, "components.inputs.cnpj.length");
|
|
49
|
+
setInternalError(message);
|
|
50
|
+
props.onValidation?.(message);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!isValidCnpj(value)) {
|
|
54
|
+
const message = invalidMessage ?? t(i18n, "components.inputs.cnpj.invalid");
|
|
55
|
+
setInternalError(message);
|
|
56
|
+
props.onValidation?.(message);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (validateWithPublicaCnpj && !/[A-Z]/.test(raw)) {
|
|
60
|
+
const digits = onlyDigits(raw);
|
|
61
|
+
if (digits.length === 14) {
|
|
62
|
+
if (lastValidatedCnpjRef.current === digits) {
|
|
63
|
+
const message = publicaCnpjErrorMessage ?? invalidMessage ?? t(i18n, "components.inputs.cnpj.invalid");
|
|
64
|
+
if (lastPublicaFoundRef.current === false) {
|
|
65
|
+
setInternalError(message);
|
|
66
|
+
props.onValidation?.(message);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
setInternalError(null);
|
|
70
|
+
props.onValidation?.(null);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const checker = publicaCnpjFetch ?? defaultPublicaCnpjFetch;
|
|
76
|
+
const data = await checker(digits);
|
|
77
|
+
lastValidatedCnpjRef.current = digits;
|
|
78
|
+
lastPublicaFoundRef.current = Boolean(data);
|
|
79
|
+
onPublicaCnpjResult?.(data);
|
|
80
|
+
if (!data) {
|
|
81
|
+
const message = publicaCnpjErrorMessage ?? invalidMessage ?? t(i18n, "components.inputs.cnpj.invalid");
|
|
82
|
+
setInternalError(message);
|
|
83
|
+
props.onValidation?.(message);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
onPublicaCnpjError?.(err);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
setInternalError(null);
|
|
93
|
+
props.onValidation?.(null);
|
|
94
|
+
}, [
|
|
95
|
+
i18n,
|
|
96
|
+
required,
|
|
97
|
+
requiredMessage,
|
|
98
|
+
lengthMessage,
|
|
99
|
+
invalidMessage,
|
|
100
|
+
validation,
|
|
101
|
+
props,
|
|
102
|
+
validateWithPublicaCnpj,
|
|
103
|
+
publicaCnpjErrorMessage,
|
|
104
|
+
publicaCnpjFetch,
|
|
105
|
+
onPublicaCnpjResult,
|
|
106
|
+
onPublicaCnpjError
|
|
107
|
+
]);
|
|
108
|
+
const inputProps = {
|
|
109
|
+
...rest.inputProps,
|
|
110
|
+
inputMode: rest.inputProps.inputMode ?? "text",
|
|
111
|
+
onChange: (event) => {
|
|
112
|
+
event.target.value = maskCnpj(event.target.value);
|
|
113
|
+
runValidation(event.currentTarget.value);
|
|
114
|
+
rest.inputProps.onChange?.(event);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const onBlur = inputProps.onBlur;
|
|
118
|
+
const shouldValidateOnBlur = validateOnBlur ?? true;
|
|
119
|
+
return (_jsx(SgInputText, { ...rest, maxLength: rest.maxLength ?? 18, error: error ?? internalError ?? undefined, onClear: () => {
|
|
120
|
+
setInternalError(null);
|
|
121
|
+
props.onValidation?.(null);
|
|
122
|
+
lastValidatedCnpjRef.current = null;
|
|
123
|
+
lastPublicaFoundRef.current = null;
|
|
124
|
+
rest.onClear?.();
|
|
125
|
+
}, inputProps: {
|
|
126
|
+
...inputProps,
|
|
127
|
+
onBlur: (event) => {
|
|
128
|
+
if (shouldValidateOnBlur)
|
|
129
|
+
runValidation(event.currentTarget.value);
|
|
130
|
+
onBlur?.(event);
|
|
131
|
+
}
|
|
132
|
+
} }));
|
|
133
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type SgInputTextProps } from "./SgInputText";
|
|
3
|
+
export type SgInputCPFProps = Omit<SgInputTextProps, "inputProps" | "error"> & {
|
|
4
|
+
inputProps: React.InputHTMLAttributes<HTMLInputElement>;
|
|
5
|
+
error?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
requiredMessage?: string;
|
|
8
|
+
lengthMessage?: string;
|
|
9
|
+
invalidMessage?: string;
|
|
10
|
+
validation?: (value: string) => string | null;
|
|
11
|
+
onValidation?: (message: string | null) => void;
|
|
12
|
+
validateOnBlur?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function SgInputCPF(props: SgInputCPFProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=SgInputCPF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgInputCPF.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputCPF.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKnE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,OAAO,CAAC,GAAG;IAC7E,UAAU,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAMF,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAwEhD"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SgInputText } from "./SgInputText";
|
|
5
|
+
import { maskCpf } from "../masks";
|
|
6
|
+
import { isValidCpf } from "../validators";
|
|
7
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
8
|
+
function onlyDigits(value) {
|
|
9
|
+
return value.replace(/\D/g, "");
|
|
10
|
+
}
|
|
11
|
+
export function SgInputCPF(props) {
|
|
12
|
+
const i18n = useComponentsI18n();
|
|
13
|
+
const { required, requiredMessage, lengthMessage, invalidMessage, validateOnBlur, error, validation, ...rest } = props;
|
|
14
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
15
|
+
const runValidation = React.useCallback((value) => {
|
|
16
|
+
const digits = onlyDigits(value);
|
|
17
|
+
if (!digits && !required) {
|
|
18
|
+
setInternalError(null);
|
|
19
|
+
props.onValidation?.(null);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!digits && required) {
|
|
23
|
+
const message = requiredMessage ?? t(i18n, "components.inputs.required");
|
|
24
|
+
setInternalError(message);
|
|
25
|
+
props.onValidation?.(message);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (validation) {
|
|
29
|
+
const message = validation(value);
|
|
30
|
+
if (message) {
|
|
31
|
+
setInternalError(message);
|
|
32
|
+
props.onValidation?.(message);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (digits.length !== 11) {
|
|
37
|
+
const message = lengthMessage ?? t(i18n, "components.inputs.cpf.length");
|
|
38
|
+
setInternalError(message);
|
|
39
|
+
props.onValidation?.(message);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!isValidCpf(value)) {
|
|
43
|
+
const message = invalidMessage ?? t(i18n, "components.inputs.cpf.invalid");
|
|
44
|
+
setInternalError(message);
|
|
45
|
+
props.onValidation?.(message);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
setInternalError(null);
|
|
49
|
+
props.onValidation?.(null);
|
|
50
|
+
}, [i18n, required, requiredMessage, lengthMessage, invalidMessage, validation, props]);
|
|
51
|
+
const inputProps = {
|
|
52
|
+
...rest.inputProps,
|
|
53
|
+
inputMode: rest.inputProps.inputMode ?? "numeric",
|
|
54
|
+
onChange: (event) => {
|
|
55
|
+
event.target.value = maskCpf(event.target.value);
|
|
56
|
+
runValidation(event.currentTarget.value);
|
|
57
|
+
rest.inputProps.onChange?.(event);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const onBlur = inputProps.onBlur;
|
|
61
|
+
const shouldValidateOnBlur = validateOnBlur ?? true;
|
|
62
|
+
return (_jsx(SgInputText, { ...rest, maxLength: rest.maxLength ?? 18, error: error ?? internalError ?? undefined, inputProps: {
|
|
63
|
+
...inputProps,
|
|
64
|
+
onBlur: (event) => {
|
|
65
|
+
if (shouldValidateOnBlur)
|
|
66
|
+
runValidation(event.currentTarget.value);
|
|
67
|
+
onBlur?.(event);
|
|
68
|
+
}
|
|
69
|
+
} }));
|
|
70
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type SgInputTextProps } from "./SgInputText";
|
|
3
|
+
export type SgInputCPFCNPJProps = Omit<SgInputTextProps, "inputProps" | "error"> & {
|
|
4
|
+
inputProps: React.InputHTMLAttributes<HTMLInputElement>;
|
|
5
|
+
error?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
requiredMessage?: string;
|
|
8
|
+
lengthMessage?: string;
|
|
9
|
+
invalidMessage?: string;
|
|
10
|
+
validation?: (value: string) => string | null;
|
|
11
|
+
onValidation?: (message: string | null) => void;
|
|
12
|
+
validateOnBlur?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function SgInputCPFCNPJ(props: SgInputCPFCNPJProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=SgInputCPFCNPJ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgInputCPFCNPJ.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputCPFCNPJ.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKnE,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,OAAO,CAAC,GAAG;IACjF,UAAU,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAUF,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CA2FxD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SgInputText } from "./SgInputText";
|
|
5
|
+
import { maskCpfCnpj } from "../masks";
|
|
6
|
+
import { isValidCnpj, isValidCpf } from "../validators";
|
|
7
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
8
|
+
function onlyDigits(value) {
|
|
9
|
+
return value.replace(/\D/g, "");
|
|
10
|
+
}
|
|
11
|
+
function onlyAlnumUpper(value) {
|
|
12
|
+
return value.replace(/[^0-9A-Za-z]/g, "").toUpperCase();
|
|
13
|
+
}
|
|
14
|
+
export function SgInputCPFCNPJ(props) {
|
|
15
|
+
const i18n = useComponentsI18n();
|
|
16
|
+
const { required, requiredMessage, lengthMessage, invalidMessage, validateOnBlur, error, validation, ...rest } = props;
|
|
17
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
18
|
+
const runValidation = React.useCallback((value) => {
|
|
19
|
+
const raw = onlyAlnumUpper(value);
|
|
20
|
+
if (!raw && !required) {
|
|
21
|
+
setInternalError(null);
|
|
22
|
+
props.onValidation?.(null);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!raw && required) {
|
|
26
|
+
const message = requiredMessage ?? t(i18n, "components.inputs.required");
|
|
27
|
+
setInternalError(message);
|
|
28
|
+
props.onValidation?.(message);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (validation) {
|
|
32
|
+
const message = validation(value);
|
|
33
|
+
if (message) {
|
|
34
|
+
setInternalError(message);
|
|
35
|
+
props.onValidation?.(message);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const isCnpj = /[A-Z]/.test(raw) || raw.length > 11;
|
|
40
|
+
if (!isCnpj) {
|
|
41
|
+
const digits = onlyDigits(value);
|
|
42
|
+
if (digits.length !== 11) {
|
|
43
|
+
const message = lengthMessage ?? t(i18n, "components.inputs.cpf.length");
|
|
44
|
+
setInternalError(message);
|
|
45
|
+
props.onValidation?.(message);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!isValidCpf(value)) {
|
|
49
|
+
const message = invalidMessage ?? t(i18n, "components.inputs.cpf.invalid");
|
|
50
|
+
setInternalError(message);
|
|
51
|
+
props.onValidation?.(message);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
setInternalError(null);
|
|
55
|
+
props.onValidation?.(null);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (raw.length !== 14) {
|
|
59
|
+
const message = lengthMessage ?? t(i18n, "components.inputs.cnpj.length");
|
|
60
|
+
setInternalError(message);
|
|
61
|
+
props.onValidation?.(message);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!isValidCnpj(value)) {
|
|
65
|
+
const message = invalidMessage ?? t(i18n, "components.inputs.cnpj.invalid");
|
|
66
|
+
setInternalError(message);
|
|
67
|
+
props.onValidation?.(message);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
setInternalError(null);
|
|
71
|
+
props.onValidation?.(null);
|
|
72
|
+
}, [i18n, required, requiredMessage, lengthMessage, invalidMessage, validation, props]);
|
|
73
|
+
const inputProps = {
|
|
74
|
+
...rest.inputProps,
|
|
75
|
+
inputMode: rest.inputProps.inputMode ?? "text",
|
|
76
|
+
onChange: (event) => {
|
|
77
|
+
event.target.value = maskCpfCnpj(event.target.value);
|
|
78
|
+
runValidation(event.currentTarget.value);
|
|
79
|
+
rest.inputProps.onChange?.(event);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const onBlur = inputProps.onBlur;
|
|
83
|
+
const shouldValidateOnBlur = validateOnBlur ?? true;
|
|
84
|
+
return (_jsx(SgInputText, { ...rest, maxLength: rest.maxLength ?? 18, error: error ?? internalError ?? undefined, inputProps: {
|
|
85
|
+
...inputProps,
|
|
86
|
+
onBlur: (event) => {
|
|
87
|
+
if (shouldValidateOnBlur)
|
|
88
|
+
runValidation(event.currentTarget.value);
|
|
89
|
+
onBlur?.(event);
|
|
90
|
+
}
|
|
91
|
+
} }));
|
|
92
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SgInputTextProps } from "./SgInputText";
|
|
2
|
+
export type SgInputDateProps = Omit<SgInputTextProps, "type"> & {
|
|
3
|
+
minDate?: string | Date;
|
|
4
|
+
maxDate?: string | Date;
|
|
5
|
+
alwaysFloat?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function SgInputDate(props: SgInputDateProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=SgInputDate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgInputDate.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputDate.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGnE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG;IAC9D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAuBF,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CAkIlD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SgInputText } from "./SgInputText";
|
|
5
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
6
|
+
function toDateValue(value) {
|
|
7
|
+
if (!value)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (typeof value === "string")
|
|
10
|
+
return value;
|
|
11
|
+
return value.toISOString().slice(0, 10);
|
|
12
|
+
}
|
|
13
|
+
function formatDateDisplay(value, locale) {
|
|
14
|
+
const iso = toDateValue(value);
|
|
15
|
+
if (!iso)
|
|
16
|
+
return "";
|
|
17
|
+
if (locale === "en-US")
|
|
18
|
+
return iso;
|
|
19
|
+
const [year, month, day] = iso.split("-");
|
|
20
|
+
if (!year || !month || !day)
|
|
21
|
+
return iso;
|
|
22
|
+
return `${day}/${month}/${year}`;
|
|
23
|
+
}
|
|
24
|
+
function parseDateValue(value) {
|
|
25
|
+
const date = new Date(value);
|
|
26
|
+
if (Number.isNaN(date.getTime()))
|
|
27
|
+
return null;
|
|
28
|
+
return date;
|
|
29
|
+
}
|
|
30
|
+
export function SgInputDate(props) {
|
|
31
|
+
const i18n = useComponentsI18n();
|
|
32
|
+
const { minDate, maxDate, inputProps, alwaysFloat, required, requiredMessage, validateOnBlur, validation, onValidation, error, ...rest } = props;
|
|
33
|
+
const showStaticLabel = true;
|
|
34
|
+
const labelText = rest.labelText ?? rest.label ?? "";
|
|
35
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
36
|
+
const hasError = Boolean(error ?? internalError);
|
|
37
|
+
const [hasInteracted, setHasInteracted] = React.useState(false);
|
|
38
|
+
const minDateValue = toDateValue(minDate);
|
|
39
|
+
const maxDateValue = toDateValue(maxDate);
|
|
40
|
+
const runValidation = React.useCallback((value) => {
|
|
41
|
+
if (!value && !required) {
|
|
42
|
+
setInternalError(null);
|
|
43
|
+
onValidation?.(null);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!value && required) {
|
|
47
|
+
const message = requiredMessage ?? t(i18n, "components.inputs.required");
|
|
48
|
+
setInternalError(message);
|
|
49
|
+
onValidation?.(message);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const customMessage = validation?.(value) ?? null;
|
|
53
|
+
if (customMessage) {
|
|
54
|
+
setInternalError(customMessage);
|
|
55
|
+
onValidation?.(customMessage);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const parsed = parseDateValue(value);
|
|
59
|
+
if (!parsed) {
|
|
60
|
+
const message = t(i18n, "components.inputs.date.invalid");
|
|
61
|
+
setInternalError(message);
|
|
62
|
+
onValidation?.(message);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const min = minDateValue ? parseDateValue(minDateValue) : null;
|
|
66
|
+
const max = maxDateValue ? parseDateValue(maxDateValue) : null;
|
|
67
|
+
if (min && parsed < min || max && parsed > max) {
|
|
68
|
+
const minLabel = formatDateDisplay(minDateValue, i18n.locale);
|
|
69
|
+
const maxLabel = formatDateDisplay(maxDateValue, i18n.locale);
|
|
70
|
+
const message = minLabel && maxLabel
|
|
71
|
+
? t(i18n, "components.inputs.date.range", { min: minLabel, max: maxLabel })
|
|
72
|
+
: minLabel
|
|
73
|
+
? t(i18n, "components.inputs.date.min", { min: minLabel })
|
|
74
|
+
: t(i18n, "components.inputs.date.max", { max: maxLabel });
|
|
75
|
+
setInternalError(message);
|
|
76
|
+
onValidation?.(message);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
setInternalError(null);
|
|
80
|
+
onValidation?.(null);
|
|
81
|
+
}, [i18n, maxDateValue, minDateValue, onValidation, required, requiredMessage, validation]);
|
|
82
|
+
const mergedInputProps = {
|
|
83
|
+
...inputProps,
|
|
84
|
+
placeholder: showStaticLabel ? " " : (inputProps?.placeholder ?? rest.hintText ?? labelText),
|
|
85
|
+
min: minDateValue,
|
|
86
|
+
max: maxDateValue,
|
|
87
|
+
readOnly: inputProps?.readOnly,
|
|
88
|
+
onChange: (event) => {
|
|
89
|
+
setHasInteracted(true);
|
|
90
|
+
if (validateOnBlur === false || internalError) {
|
|
91
|
+
runValidation(event.currentTarget.value);
|
|
92
|
+
}
|
|
93
|
+
inputProps?.onChange?.(event);
|
|
94
|
+
},
|
|
95
|
+
onBlur: (event) => {
|
|
96
|
+
if ((validateOnBlur ?? true) || hasInteracted) {
|
|
97
|
+
runValidation(event.currentTarget.value);
|
|
98
|
+
}
|
|
99
|
+
inputProps?.onBlur?.(event);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const inputClassName = (() => {
|
|
103
|
+
if (mergedInputProps.className)
|
|
104
|
+
return mergedInputProps.className;
|
|
105
|
+
const hasError = Boolean(error ?? internalError);
|
|
106
|
+
const baseClass = "peer h-11 w-full rounded-md bg-white pl-3 pr-7 py-2.5 text-sm shadow-sm placeholder-transparent focus:outline-none";
|
|
107
|
+
const borderClass = hasError
|
|
108
|
+
? "border border-[hsl(var(--destructive))] focus:border-[hsl(var(--destructive))] focus:ring-2 focus:ring-[hsl(var(--destructive)/0.25)]"
|
|
109
|
+
: "border border-border focus:border-[hsl(var(--primary))] focus:ring-2 focus:ring-[hsl(var(--primary)/0.25)]";
|
|
110
|
+
return [baseClass, borderClass].join(" ");
|
|
111
|
+
})();
|
|
112
|
+
return (_jsxs("div", { className: showStaticLabel ? "relative" : undefined, children: [_jsx("style", { children: `
|
|
113
|
+
input[type="date"]::-webkit-calendar-picker-indicator {
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
}
|
|
116
|
+
` }), showStaticLabel && labelText ? (_jsx("label", { htmlFor: rest.id, className: [
|
|
117
|
+
"pointer-events-none absolute left-3 top-0 z-10 -translate-y-1/2 bg-white px-1 text-[11px] font-medium leading-none",
|
|
118
|
+
hasError ? "text-[hsl(var(--destructive))]" : "text-foreground/70"
|
|
119
|
+
].join(" "), children: labelText })) : null, _jsx(SgInputText, { ...rest, type: "date", error: error ?? internalError ?? undefined, inputProps: mergedInputProps, className: inputClassName, labelClassName: showStaticLabel ? "sr-only" : undefined })] }));
|
|
120
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type SgInputTextProps } from "./SgInputText";
|
|
3
|
+
export type SgInputEmailProps = Omit<SgInputTextProps, "type" | "error"> & {
|
|
4
|
+
error?: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
requiredMessage?: string;
|
|
7
|
+
invalidMessage?: string;
|
|
8
|
+
blockFakeMail?: boolean;
|
|
9
|
+
blockedEmailDomains?: string[];
|
|
10
|
+
validation?: (value: string) => string | null;
|
|
11
|
+
validateOnBlur?: boolean;
|
|
12
|
+
onValidation?: (message: string | null) => void;
|
|
13
|
+
iconButtons?: React.ReactNode[];
|
|
14
|
+
};
|
|
15
|
+
export declare function SgInputEmail(props: Readonly<SgInputEmailProps>): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=SgInputEmail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgInputEmail.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputEmail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAInE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;CACjC,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,2CAiG9D"}
|