react-better-html 1.1.229 → 1.1.231

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,58 @@ 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 finalHour = minHours && readyHour < minHours ? minHours : maxHours && readyHour > maxHours ? maxHours : readyHour;
5038
+ const finalMinute = minHours !== void 0 && minMinutes !== void 0 && finalHour === minHours && readyMinute < minMinutes ? minMinutes : maxHours !== void 0 && maxMinutes !== void 0 && finalHour === maxHours && readyMinute > maxMinutes ? maxMinutes : readyMinute;
5039
+ const newValue = `${finalHour.toString().padStart(2, "0")}:${finalMinute.toString().padStart(2, "0")}`;
5040
+ inputFieldProps.onChangeValue?.(newValue);
5041
+ }
5042
+ inputFieldProps.onBlur?.(event);
5043
+ },
5044
+ [
5045
+ minHours,
5046
+ maxHours,
5047
+ minMinutes,
5048
+ maxMinutes,
5049
+ hoursToRender,
5050
+ minutesToRender,
5051
+ readyHours,
5052
+ readyMinutes,
5053
+ inputFieldProps.onChangeValue,
5054
+ inputFieldProps.onBlur
5055
+ ]
5056
+ );
4962
5057
  const onClickHour = (0, import_react21.useCallback)(
4963
5058
  (hour) => {
4964
5059
  const value = `${hour.toString().padStart(2, "0")}:${internalValue?.toString().split(":")[1] || "00"}`;
@@ -5011,8 +5106,9 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5011
5106
  height: "100%",
5012
5107
  overflowY: "auto",
5013
5108
  tabIndex: -1,
5014
- children: hours.map((hour) => {
5109
+ children: readyHours.map((hour) => {
5015
5110
  const isSelected = hour.toString() === valueHour;
5111
+ const isDisabled = minHours && hour < minHours || maxHours && hour > maxHours;
5016
5112
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5017
5113
  Div_default.row,
5018
5114
  {
@@ -5021,10 +5117,11 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5021
5117
  color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
5022
5118
  backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
5023
5119
  filterHover: "brightness(0.9)",
5024
- cursor: "pointer",
5120
+ cursor: isDisabled ? "not-allowed" : "pointer",
5025
5121
  padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
5122
+ opacity: isDisabled ? 0.6 : void 0,
5026
5123
  value: hour,
5027
- onClickWithValue: onClickHour,
5124
+ onClickWithValue: !isDisabled ? onClickHour : void 0,
5028
5125
  ref: isSelected ? selectedHourRef : void 0,
5029
5126
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: hour.toString().padStart(2, "0") })
5030
5127
  },
@@ -5041,8 +5138,10 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5041
5138
  height: "100%",
5042
5139
  overflowY: "auto",
5043
5140
  tabIndex: -1,
5044
- children: minutes.map((minute) => {
5141
+ children: readyMinutes.map((minute) => {
5045
5142
  const isSelected = minute.toString() === valueMinute;
5143
+ const currentHour = parseInt(valueHour);
5144
+ const isDisabled = minHours !== void 0 && minMinutes !== void 0 && currentHour === minHours && minute < minMinutes || maxHours !== void 0 && maxMinutes !== void 0 && currentHour === maxHours && minute > maxMinutes;
5046
5145
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5047
5146
  Div_default.row,
5048
5147
  {
@@ -5051,10 +5150,11 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5051
5150
  color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
5052
5151
  backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
5053
5152
  filterHover: "brightness(0.9)",
5054
- cursor: "pointer",
5153
+ cursor: isDisabled ? "not-allowed" : "pointer",
5055
5154
  padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
5155
+ opacity: isDisabled ? 0.6 : void 0,
5056
5156
  value: minute,
5057
- onClickWithValue: onClickMinute,
5157
+ onClickWithValue: !isDisabled ? onClickMinute : void 0,
5058
5158
  ref: isSelected ? selectedMinuteRef : void 0,
5059
5159
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: minute.toString().padStart(2, "0") })
5060
5160
  },
@@ -5070,7 +5170,8 @@ InputFieldComponent.time = (0, import_react21.forwardRef)(function Time({ ...pro
5070
5170
  ref,
5071
5171
  ...props,
5072
5172
  ...inputFieldProps,
5073
- minWidth: buttonWidth * 2 + 2
5173
+ minWidth: buttonWidth * 2 + 2,
5174
+ onBlur
5074
5175
  }
5075
5176
  );
5076
5177
  });