@zauru-sdk/components 6.19.1 → 6.20.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/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [6.20.0](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.19.2...@zauru-sdk/components@6.20.0) (2026-10-31)
7
+
8
+
9
+ ### Features
10
+
11
+ * **components:** permitir rechazar fechas no permitidas en FormDatePicker ([29715e8](https://github.com/intuitiva/zauru-typescript-sdk/commit/29715e89aabaf3099dbc1e396b06baca25db2438))
12
+
13
+
14
+
15
+
16
+
17
+ ## [6.19.2](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.19.1...@zauru-sdk/components@6.19.2) (2026-10-31)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **components:** mostrar tooltips de fecha y hora por encima de otros campos ([f8647e8](https://github.com/intuitiva/zauru-typescript-sdk/commit/f8647e8da1eb7d81c5be13ec639338559d37721d))
23
+
24
+
25
+
26
+
27
+
6
28
  ## [6.19.1](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.19.0...@zauru-sdk/components@6.19.1) (2026-10-31)
7
29
 
8
30
 
@@ -11,6 +11,8 @@ type Props = {
11
11
  disabled?: boolean;
12
12
  className?: string;
13
13
  required?: boolean;
14
+ isDateAllowed?: (value: string) => boolean;
15
+ onDateRejected?: (value: string) => void;
14
16
  };
15
17
  export declare const FormDatePicker: (props: Props) => import("react/jsx-runtime").JSX.Element;
16
18
  export {};
@@ -3,14 +3,16 @@ import { useEffect, useState } from "react";
3
3
  import { CalendarIconSVG, CloseSvgIcon, IdeaIconSVG } from "@zauru-sdk/icons";
4
4
  import { useFormContext } from "react-hook-form";
5
5
  export const FormDatePicker = (props) => {
6
- const { id, name, title, defaultValue = "", hint, helpText, onChange, tabIndex, disabled = false, className = "", isClearable = false, required = false, } = props;
6
+ const { id, name, title, defaultValue = "", hint, helpText, onChange, tabIndex, disabled = false, className = "", isClearable = false, required = false, isDateAllowed, onDateRejected, } = props;
7
+ const inputId = id ?? name;
7
8
  const [value, setValue] = useState(defaultValue);
9
+ const [rejectNonce, setRejectNonce] = useState(0);
8
10
  const [showTooltip, setShowTooltip] = useState(false);
9
- const { register: tempRegister, formState: { errors }, } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
11
+ const { register: tempRegister, formState: { errors }, } = useFormContext() || { formState: {} };
10
12
  const error = errors ? errors[props.name ?? "-1"] : undefined;
11
13
  const register = tempRegister
12
14
  ? tempRegister(props.name ?? "-1", { required })
13
- : undefined; // Solo usar register si está disponible
15
+ : undefined;
14
16
  const color = error ? "red" : "gray";
15
17
  const isReadOnly = disabled;
16
18
  const bgColor = isReadOnly ? "bg-gray-200" : `bg-${color}-50`;
@@ -19,15 +21,24 @@ export const FormDatePicker = (props) => {
19
21
  useEffect(() => {
20
22
  setValue(defaultValue);
21
23
  }, [defaultValue]);
24
+ const commitValue = (next, event) => {
25
+ setValue(next);
26
+ onChange && onChange(next);
27
+ if (event && register) {
28
+ register.onChange(event);
29
+ }
30
+ };
22
31
  const clearValue = () => {
23
- setValue("");
24
- onChange && onChange("");
32
+ commitValue("");
25
33
  };
26
- return (_jsxs("div", { children: [title && (_jsxs("label", { htmlFor: error ? `${name}-error` : `${name}-success`, className: `block text-sm font-medium ${textColor} ${className}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "flex relative items-center", children: [_jsx("div", { className: "absolute left-0 flex items-center pl-3 pointer-events-none", children: _jsx(CalendarIconSVG, {}) }), _jsx("input", { id: id, tabIndex: tabIndex, type: "date", value: value ?? "", pattern: "\\d{4}-\\d{2}-\\d{2}", className: `${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`, ...(register ?? {}), name: name, onChange: (e) => {
27
- setValue(e.target.value);
28
- onChange && onChange(e.target.value);
29
- if (register) {
30
- register.onChange(e);
34
+ return (_jsxs("div", { className: showTooltip ? "relative z-50" : "relative", children: [title && (_jsxs("label", { htmlFor: inputId, className: `block text-sm font-medium ${textColor} ${className}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "flex relative items-center", children: [_jsx("div", { className: "absolute left-0 flex items-center pl-3 pointer-events-none", children: _jsx(CalendarIconSVG, {}) }), _jsx("input", { id: inputId, tabIndex: tabIndex, type: "date", value: value ?? "", pattern: "\\d{4}-\\d{2}-\\d{2}", className: `${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`, ...(register ?? {}), name: name, onChange: (e) => {
35
+ const next = e.target.value;
36
+ if (next && isDateAllowed && !isDateAllowed(next)) {
37
+ onDateRejected?.(next);
38
+ e.target.value = value ?? "";
39
+ setRejectNonce((nonce) => nonce + 1);
40
+ return;
31
41
  }
32
- } }), value && isClearable && (_jsx("button", { type: "button", onClick: clearValue, className: "absolute right-0 mr-10", children: _jsx(CloseSvgIcon, {}) })), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black", children: helpText }))] }) }))] }), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error.message?.toString()] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
42
+ commitValue(next, e);
43
+ } }, rejectNonce), value && isClearable && (_jsx("button", { type: "button", onClick: clearValue, className: "absolute right-0 mr-10", children: _jsx(CloseSvgIcon, {}) })), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 z-50 mt-8 p-2 bg-white border rounded shadow text-black", children: helpText }))] }) }))] }), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error.message?.toString()] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
33
44
  };
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ClockIconSVG, CloseSvgIcon, IdeaIconSVG } from "@zauru-sdk/icons";
3
3
  import { useEffect, useState } from "react";
4
4
  import { useFormContext } from "react-hook-form";
@@ -30,5 +30,5 @@ export const FormTimePicker = (props) => {
30
30
  register.onChange(e);
31
31
  }
32
32
  };
33
- return (_jsxs(_Fragment, { children: [title && (_jsxs("label", { htmlFor: error ? `${name}-error` : `${name}-success`, className: `block text-sm font-medium ${textColor}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "flex relative items-center", children: [_jsx("div", { className: "absolute left-0 flex items-center pl-3 pointer-events-none", children: _jsx(ClockIconSVG, {}) }), _jsx("input", { id: id, tabIndex: tabIndex, type: "time", value: value, pattern: "\\d{2}:\\d{2}", className: `${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`, ...(register ?? {}), name: name, onChange: handleOnChange }), value && (_jsx("button", { type: "button", onClick: clearValue, className: "absolute right-0 mr-10", children: _jsx(CloseSvgIcon, {}) })), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black", children: helpText }))] }) }))] }), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error.message?.toString()] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
33
+ return (_jsxs("div", { className: showTooltip ? "relative z-50" : "relative", children: [title && (_jsxs("label", { htmlFor: error ? `${name}-error` : `${name}-success`, className: `block text-sm font-medium ${textColor}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "flex relative items-center", children: [_jsx("div", { className: "absolute left-0 flex items-center pl-3 pointer-events-none", children: _jsx(ClockIconSVG, {}) }), _jsx("input", { id: id, tabIndex: tabIndex, type: "time", value: value, pattern: "\\d{2}:\\d{2}", className: `${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`, ...(register ?? {}), name: name, onChange: handleOnChange }), value && (_jsx("button", { type: "button", onClick: clearValue, className: "absolute right-0 mr-10", children: _jsx(CloseSvgIcon, {}) })), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 z-50 mt-8 p-2 bg-white border rounded shadow text-black", children: helpText }))] }) }))] }), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error.message?.toString()] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
34
34
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "6.19.1",
3
+ "version": "6.20.0",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -62,5 +62,5 @@
62
62
  "styled-components": "^5.3.5",
63
63
  "zod": "^3.23.8"
64
64
  },
65
- "gitHead": "08f14cc3a87fabe1b2dfe678b9fdeb32ed4aaaef"
65
+ "gitHead": "9fbc98b91a8ee4adffcdc639608b009e0088cb14"
66
66
  }
@@ -15,6 +15,8 @@ type Props = {
15
15
  disabled?: boolean;
16
16
  className?: string;
17
17
  required?: boolean;
18
+ isDateAllowed?: (value: string) => boolean;
19
+ onDateRejected?: (value: string) => void;
18
20
  };
19
21
 
20
22
  export const FormDatePicker = (props: Props) => {
@@ -31,18 +33,22 @@ export const FormDatePicker = (props: Props) => {
31
33
  className = "",
32
34
  isClearable = false,
33
35
  required = false,
36
+ isDateAllowed,
37
+ onDateRejected,
34
38
  } = props;
35
39
 
40
+ const inputId = id ?? name;
36
41
  const [value, setValue] = useState<string | null>(defaultValue);
42
+ const [rejectNonce, setRejectNonce] = useState(0);
37
43
  const [showTooltip, setShowTooltip] = useState<boolean>(false);
38
44
  const {
39
45
  register: tempRegister,
40
46
  formState: { errors },
41
- } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
47
+ } = useFormContext() || { formState: {} };
42
48
  const error = errors ? errors[props.name ?? "-1"] : undefined;
43
49
  const register = tempRegister
44
50
  ? tempRegister(props.name ?? "-1", { required })
45
- : undefined; // Solo usar register si está disponible
51
+ : undefined;
46
52
 
47
53
  const color = error ? "red" : "gray";
48
54
 
@@ -55,16 +61,26 @@ export const FormDatePicker = (props: Props) => {
55
61
  setValue(defaultValue);
56
62
  }, [defaultValue]);
57
63
 
64
+ const commitValue = (
65
+ next: string,
66
+ event?: React.ChangeEvent<HTMLInputElement>,
67
+ ) => {
68
+ setValue(next);
69
+ onChange && onChange(next);
70
+ if (event && register) {
71
+ register.onChange(event);
72
+ }
73
+ };
74
+
58
75
  const clearValue = () => {
59
- setValue("");
60
- onChange && onChange("");
76
+ commitValue("");
61
77
  };
62
78
 
63
79
  return (
64
- <div>
80
+ <div className={showTooltip ? "relative z-50" : "relative"}>
65
81
  {title && (
66
82
  <label
67
- htmlFor={error ? `${name}-error` : `${name}-success`}
83
+ htmlFor={inputId}
68
84
  className={`block text-sm font-medium ${textColor} ${className}`}
69
85
  >
70
86
  {title}
@@ -76,7 +92,8 @@ export const FormDatePicker = (props: Props) => {
76
92
  <CalendarIconSVG />
77
93
  </div>
78
94
  <input
79
- id={id}
95
+ key={rejectNonce}
96
+ id={inputId}
80
97
  tabIndex={tabIndex}
81
98
  type="date"
82
99
  value={value ?? ""}
@@ -85,11 +102,14 @@ export const FormDatePicker = (props: Props) => {
85
102
  {...(register ?? {})}
86
103
  name={name}
87
104
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
88
- setValue(e.target.value);
89
- onChange && onChange(e.target.value);
90
- if (register) {
91
- register.onChange(e);
105
+ const next = e.target.value;
106
+ if (next && isDateAllowed && !isDateAllowed(next)) {
107
+ onDateRejected?.(next);
108
+ e.target.value = value ?? "";
109
+ setRejectNonce((nonce) => nonce + 1);
110
+ return;
92
111
  }
112
+ commitValue(next, e);
93
113
  }}
94
114
  ></input>
95
115
  {value && isClearable && (
@@ -110,7 +130,7 @@ export const FormDatePicker = (props: Props) => {
110
130
  >
111
131
  <IdeaIconSVG />
112
132
  {showTooltip && (
113
- <div className="absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black">
133
+ <div className="absolute -left-48 top-0 z-50 mt-8 p-2 bg-white border rounded shadow text-black">
114
134
  {helpText}
115
135
  </div>
116
136
  )}
@@ -65,7 +65,7 @@ export const FormTimePicker = (props: Props) => {
65
65
  };
66
66
 
67
67
  return (
68
- <>
68
+ <div className={showTooltip ? "relative z-50" : "relative"}>
69
69
  {title && (
70
70
  <label
71
71
  htmlFor={error ? `${name}-error` : `${name}-success`}
@@ -108,7 +108,7 @@ export const FormTimePicker = (props: Props) => {
108
108
  >
109
109
  <IdeaIconSVG />
110
110
  {showTooltip && (
111
- <div className="absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black">
111
+ <div className="absolute -left-48 top-0 z-50 mt-8 p-2 bg-white border rounded shadow text-black">
112
112
  {helpText}
113
113
  </div>
114
114
  )}
@@ -128,6 +128,6 @@ export const FormTimePicker = (props: Props) => {
128
128
  {hint}
129
129
  </p>
130
130
  )}
131
- </>
131
+ </div>
132
132
  );
133
133
  };