react-better-html 1.1.229 → 1.1.230

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.d.mts CHANGED
@@ -139,6 +139,7 @@ type InputFieldProps = {
139
139
  holderRef?: React.ForwardedRef<HTMLDivElement>;
140
140
  } & OmitProps<React.ComponentProps<"input">, "style" | "ref" | "prefix"> & ComponentStyle & ComponentHoverStyle;
141
141
  type TextareaFieldProps = OmitProps<InputFieldProps, "type"> & OmitProps<React.ComponentProps<"textarea">, "style" | "ref">;
142
+ type InputFieldDateTimeExcludeProps = Pick<InputFieldProps, "min" | "max" | "minLength" | "maxLength">;
142
143
  type InputFieldComponentType = {
143
144
  (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>): React.ReactElement;
144
145
  multiline: (props: ComponentPropWithRef<HTMLTextAreaElement, TextareaFieldProps>) => React.ReactElement;
@@ -153,7 +154,9 @@ type InputFieldComponentType = {
153
154
  minDate?: Date;
154
155
  maxDate?: Date;
155
156
  }>) => React.ReactElement;
156
- dateTime: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps & {
157
+ dateTime: (props: ComponentPropWithRef<HTMLInputElement, OmitProps<InputFieldProps, keyof InputFieldDateTimeExcludeProps> & {
158
+ hoursToRender?: number[];
159
+ minutesToRender?: number[];
157
160
  minDate?: Date;
158
161
  maxDate?: Date;
159
162
  /** @default today */
@@ -161,7 +164,14 @@ type InputFieldComponentType = {
161
164
  /** @default "00:00" */
162
165
  defaultTimeAfterDatePick?: `${number}:${number}`;
163
166
  }>) => React.ReactElement;
164
- time: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
167
+ time: (props: ComponentPropWithRef<HTMLInputElement, OmitProps<InputFieldProps, keyof InputFieldDateTimeExcludeProps>> & {
168
+ hoursToRender?: number[];
169
+ minutesToRender?: number[];
170
+ /** @default 00:00 */
171
+ minTime?: string;
172
+ /** @default 23:59 */
173
+ maxTime?: string;
174
+ }) => React.ReactElement;
165
175
  color: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
166
176
  };
167
177
  declare const InputFieldComponent: InputFieldComponentType;
package/dist/index.d.ts CHANGED
@@ -139,6 +139,7 @@ type InputFieldProps = {
139
139
  holderRef?: React.ForwardedRef<HTMLDivElement>;
140
140
  } & OmitProps<React.ComponentProps<"input">, "style" | "ref" | "prefix"> & ComponentStyle & ComponentHoverStyle;
141
141
  type TextareaFieldProps = OmitProps<InputFieldProps, "type"> & OmitProps<React.ComponentProps<"textarea">, "style" | "ref">;
142
+ type InputFieldDateTimeExcludeProps = Pick<InputFieldProps, "min" | "max" | "minLength" | "maxLength">;
142
143
  type InputFieldComponentType = {
143
144
  (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>): React.ReactElement;
144
145
  multiline: (props: ComponentPropWithRef<HTMLTextAreaElement, TextareaFieldProps>) => React.ReactElement;
@@ -153,7 +154,9 @@ type InputFieldComponentType = {
153
154
  minDate?: Date;
154
155
  maxDate?: Date;
155
156
  }>) => React.ReactElement;
156
- dateTime: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps & {
157
+ dateTime: (props: ComponentPropWithRef<HTMLInputElement, OmitProps<InputFieldProps, keyof InputFieldDateTimeExcludeProps> & {
158
+ hoursToRender?: number[];
159
+ minutesToRender?: number[];
157
160
  minDate?: Date;
158
161
  maxDate?: Date;
159
162
  /** @default today */
@@ -161,7 +164,14 @@ type InputFieldComponentType = {
161
164
  /** @default "00:00" */
162
165
  defaultTimeAfterDatePick?: `${number}:${number}`;
163
166
  }>) => React.ReactElement;
164
- time: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
167
+ time: (props: ComponentPropWithRef<HTMLInputElement, OmitProps<InputFieldProps, keyof InputFieldDateTimeExcludeProps>> & {
168
+ hoursToRender?: number[];
169
+ minutesToRender?: number[];
170
+ /** @default 00:00 */
171
+ minTime?: string;
172
+ /** @default 23:59 */
173
+ maxTime?: string;
174
+ }) => React.ReactElement;
165
175
  color: (props: ComponentPropWithRef<HTMLInputElement, InputFieldProps>) => React.ReactElement;
166
176
  };
167
177
  declare const InputFieldComponent: InputFieldComponentType;
package/dist/index.js CHANGED
@@ -3251,6 +3251,18 @@ var decryptString = (text) => {
3251
3251
  });
3252
3252
  return decrypted.toString(import_crypto_js.default.enc.Utf8);
3253
3253
  };
3254
+ function findClosestNumber(numbers, target) {
3255
+ let closest = numbers[0];
3256
+ let minDistance = Math.abs(target - numbers[0]);
3257
+ for (let index = 1; index < numbers.length; index++) {
3258
+ const distance = Math.abs(target - numbers[index]);
3259
+ if (distance < minDistance || distance === minDistance && numbers[index] < closest) {
3260
+ closest = numbers[index];
3261
+ minDistance = distance;
3262
+ }
3263
+ }
3264
+ return closest;
3265
+ }
3254
3266
 
3255
3267
  // src/utils/localStorage.ts
3256
3268
  function generateLocalStorage() {
@@ -4798,13 +4810,29 @@ InputFieldComponent.date = (0, import_react21.forwardRef)(function Date2({ minDa
4798
4810
  }
4799
4811
  );
4800
4812
  });
4801
- InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime({ minDate, maxDate, defaultDateAfterTimePick, defaultTimeAfterDatePick = "00:00", ...props }, ref) {
4813
+ InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime({
4814
+ hoursToRender,
4815
+ minutesToRender,
4816
+ minDate,
4817
+ maxDate,
4818
+ defaultDateAfterTimePick,
4819
+ defaultTimeAfterDatePick = "00:00",
4820
+ ...props
4821
+ }, ref) {
4802
4822
  const theme2 = (0, import_react_better_core19.useTheme)();
4803
4823
  const holderRef = (0, import_react21.useRef)(null);
4804
4824
  const selectedHourRef = (0, import_react21.useRef)(null);
4805
4825
  const selectedMinuteRef = (0, import_react21.useRef)(null);
4806
4826
  const isMobileIOS = isMobileDevice && getBrowser() === "safari";
4807
4827
  const { internalValue, setInternalValue, inputFieldProps, insideInputFieldComponentProps, isOpen } = useComponentInputFieldDateProps(props, holderRef, isMobileIOS);
4828
+ const readyHours = (0, import_react21.useMemo)(
4829
+ () => hoursToRender?.filter((hour) => hour >= 0 && hour <= 23) ?? hours,
4830
+ [hoursToRender]
4831
+ );
4832
+ const readyMinutes = (0, import_react21.useMemo)(
4833
+ () => minutesToRender?.filter((hour) => hour >= 0 && hour <= 59) ?? minutes,
4834
+ [minutesToRender]
4835
+ );
4808
4836
  const onChange = (0, import_react21.useCallback)(
4809
4837
  (date) => {
4810
4838
  const newValue = date ? `${date}T${internalValue?.toString().split("T")[1] ?? defaultTimeAfterDatePick}` : "";
@@ -4813,6 +4841,32 @@ InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime(
4813
4841
  },
4814
4842
  [internalValue, defaultTimeAfterDatePick, inputFieldProps.onChangeValue]
4815
4843
  );
4844
+ const onBlur = (0, import_react21.useCallback)(
4845
+ (event) => {
4846
+ if (hoursToRender || minutesToRender) {
4847
+ const value = event.target.value;
4848
+ const hours2 = parseInt(value.split(":")[0] || "0");
4849
+ const minutes2 = parseInt(value.split(":")[1] || "0");
4850
+ const readyHour = readyHours.includes(hours2) ? hours2 : findClosestNumber(readyHours, hours2);
4851
+ const readyMinute = readyMinutes.includes(minutes2) ? minutes2 : findClosestNumber(readyMinutes, minutes2);
4852
+ const newTime = `${readyHour.toString().padStart(2, "0")}:${readyMinute.toString().padStart(2, "0")}`;
4853
+ const today = defaultDateAfterTimePick ?? `${(/* @__PURE__ */ new Date()).getFullYear()}-${((/* @__PURE__ */ new Date()).getMonth() + 1).toString().padStart(2, "0")}-${(/* @__PURE__ */ new Date()).getDate().toString().padStart(2, "0")}`;
4854
+ const newValue = `${(internalValue.trim() || today)?.toString().split("T")[0]}T${newTime}`;
4855
+ inputFieldProps.onChangeValue?.(newValue);
4856
+ }
4857
+ inputFieldProps.onBlur?.(event);
4858
+ },
4859
+ [
4860
+ defaultDateAfterTimePick,
4861
+ internalValue,
4862
+ hoursToRender,
4863
+ minutesToRender,
4864
+ readyHours,
4865
+ readyMinutes,
4866
+ inputFieldProps.onChangeValue,
4867
+ inputFieldProps.onBlur
4868
+ ]
4869
+ );
4816
4870
  const onClickHour = (0, import_react21.useCallback)(
4817
4871
  (hour) => {
4818
4872
  const newTime = `${hour.toString().padStart(2, "0")}:${internalValue?.toString().split(":")[1] || "00"}`;
@@ -4881,7 +4935,7 @@ InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime(
4881
4935
  height: `calc(100% - ${16 + theme2.styles.gap / 2}px)`,
4882
4936
  overflowY: "auto",
4883
4937
  tabIndex: -1,
4884
- children: hours.map((hour) => {
4938
+ children: readyHours.map((hour) => {
4885
4939
  const isSelected = hour.toString() === valueHour;
4886
4940
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4887
4941
  Div_default.row,
@@ -4915,7 +4969,7 @@ InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime(
4915
4969
  height: `calc(100% - ${16 + theme2.styles.gap / 2}px)`,
4916
4970
  overflowY: "auto",
4917
4971
  tabIndex: -1,
4918
- children: minutes.map((minute) => {
4972
+ children: readyMinutes.map((minute) => {
4919
4973
  const isSelected = minute.toString() === valueMinute;
4920
4974
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4921
4975
  Div_default.row,
@@ -4948,17 +5002,56 @@ InputFieldComponent.dateTime = (0, import_react21.forwardRef)(function DateTime(
4948
5002
  holderRef,
4949
5003
  ref,
4950
5004
  ...props,
4951
- ...inputFieldProps
5005
+ ...inputFieldProps,
5006
+ onBlur
4952
5007
  }
4953
5008
  );
4954
5009
  });
4955
- InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...props }, ref) {
5010
+ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ hoursToRender, minutesToRender, minTime, maxTime, ...props }, ref) {
4956
5011
  const theme2 = (0, import_react_better_core19.useTheme)();
4957
5012
  const holderRef = (0, import_react21.useRef)(null);
4958
5013
  const selectedHourRef = (0, import_react21.useRef)(null);
4959
5014
  const selectedMinuteRef = (0, import_react21.useRef)(null);
4960
5015
  const isMobileIOS = isMobileDevice && getBrowser() === "safari";
5016
+ const minHours = minTime ? parseInt(minTime.split(":")[0]) : void 0;
5017
+ const minMinutes = minTime ? parseInt(minTime.split(":")[1]) : void 0;
5018
+ const maxHours = maxTime ? parseInt(maxTime.split(":")[0]) : void 0;
5019
+ const maxMinutes = maxTime ? parseInt(maxTime.split(":")[1]) : void 0;
4961
5020
  const { internalValue, setInternalValue, inputFieldProps, insideInputFieldComponentProps, isOpen } = useComponentInputFieldDateProps(props, holderRef, isMobileIOS);
5021
+ const readyHours = (0, import_react21.useMemo)(
5022
+ () => hoursToRender?.filter((hour) => hour >= 0 && hour <= 23) ?? hours,
5023
+ [hoursToRender]
5024
+ );
5025
+ const readyMinutes = (0, import_react21.useMemo)(
5026
+ () => minutesToRender?.filter((hour) => hour >= 0 && hour <= 59) ?? minutes,
5027
+ [minutesToRender]
5028
+ );
5029
+ const onBlur = (0, import_react21.useCallback)(
5030
+ (event) => {
5031
+ if (!!minHours || !!maxHours || !!minMinutes || !!maxMinutes || hoursToRender || minutesToRender) {
5032
+ const value = event.target.value;
5033
+ const hours2 = parseInt(value.split(":")[0] || "0");
5034
+ const minutes2 = parseInt(value.split(":")[1] || "0");
5035
+ const readyHour = readyHours.includes(hours2) ? hours2 : findClosestNumber(readyHours, hours2);
5036
+ const readyMinute = readyMinutes.includes(minutes2) ? minutes2 : findClosestNumber(readyMinutes, minutes2);
5037
+ const newValue = `${(minHours && readyHour < minHours ? minHours : maxHours && readyHour > maxHours ? maxHours : readyHour).toString().padStart(2, "0")}:${(minMinutes && readyMinute < minMinutes ? minMinutes : maxHours && readyMinute > maxHours ? maxHours : readyMinute).toString().padStart(2, "0")}`;
5038
+ inputFieldProps.onChangeValue?.(newValue);
5039
+ }
5040
+ inputFieldProps.onBlur?.(event);
5041
+ },
5042
+ [
5043
+ minHours,
5044
+ maxHours,
5045
+ minMinutes,
5046
+ maxMinutes,
5047
+ hoursToRender,
5048
+ minutesToRender,
5049
+ readyHours,
5050
+ readyMinutes,
5051
+ inputFieldProps.onChangeValue,
5052
+ inputFieldProps.onBlur
5053
+ ]
5054
+ );
4962
5055
  const onClickHour = (0, import_react21.useCallback)(
4963
5056
  (hour) => {
4964
5057
  const value = `${hour.toString().padStart(2, "0")}:${internalValue?.toString().split(":")[1] || "00"}`;
@@ -5011,8 +5104,9 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5011
5104
  height: "100%",
5012
5105
  overflowY: "auto",
5013
5106
  tabIndex: -1,
5014
- children: hours.map((hour) => {
5107
+ children: readyHours.map((hour) => {
5015
5108
  const isSelected = hour.toString() === valueHour;
5109
+ const isDisabled = minHours && hour < minHours || maxHours && hour > maxHours;
5016
5110
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5017
5111
  Div_default.row,
5018
5112
  {
@@ -5021,10 +5115,11 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5021
5115
  color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
5022
5116
  backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
5023
5117
  filterHover: "brightness(0.9)",
5024
- cursor: "pointer",
5118
+ cursor: isDisabled ? "not-allowed" : "pointer",
5025
5119
  padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
5120
+ opacity: isDisabled ? 0.6 : void 0,
5026
5121
  value: hour,
5027
- onClickWithValue: onClickHour,
5122
+ onClickWithValue: !isDisabled ? onClickHour : void 0,
5028
5123
  ref: isSelected ? selectedHourRef : void 0,
5029
5124
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: hour.toString().padStart(2, "0") })
5030
5125
  },
@@ -5041,8 +5136,9 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5041
5136
  height: "100%",
5042
5137
  overflowY: "auto",
5043
5138
  tabIndex: -1,
5044
- children: minutes.map((minute) => {
5139
+ children: readyMinutes.map((minute) => {
5045
5140
  const isSelected = minute.toString() === valueMinute;
5141
+ const isDisabled = minMinutes && minute < minMinutes || maxMinutes && minute > maxMinutes;
5046
5142
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5047
5143
  Div_default.row,
5048
5144
  {
@@ -5051,10 +5147,11 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5051
5147
  color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
5052
5148
  backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
5053
5149
  filterHover: "brightness(0.9)",
5054
- cursor: "pointer",
5150
+ cursor: isDisabled ? "not-allowed" : "pointer",
5055
5151
  padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
5152
+ opacity: isDisabled ? 0.6 : void 0,
5056
5153
  value: minute,
5057
- onClickWithValue: onClickMinute,
5154
+ onClickWithValue: !isDisabled ? onClickMinute : void 0,
5058
5155
  ref: isSelected ? selectedMinuteRef : void 0,
5059
5156
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: minute.toString().padStart(2, "0") })
5060
5157
  },
@@ -5070,7 +5167,8 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5070
5167
  ref,
5071
5168
  ...props,
5072
5169
  ...inputFieldProps,
5073
- minWidth: buttonWidth * 2 + 2
5170
+ minWidth: buttonWidth * 2 + 2,
5171
+ onBlur
5074
5172
  }
5075
5173
  );
5076
5174
  });