react-better-html 1.1.42 → 1.1.44

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.
@@ -8,7 +8,7 @@ type InternalToggleInputProps<Value> = {
8
8
  infoText?: string;
9
9
  value?: Value;
10
10
  onChange?: (checked: boolean, value?: Value) => void;
11
- } & OmitProps<React.ComponentProps<"input">, "style" | "value" | "ref" | "onChange" | "name"> & ComponentStyle & ComponentHoverStyle;
11
+ } & OmitProps<React.ComponentProps<"input">, "style" | "value" | "ref" | "onChange"> & ComponentStyle & ComponentHoverStyle;
12
12
  export type ToggleInputProps<Value> = ComponentPropWithRef<ToggleInputRef, OmitProps<InternalToggleInputProps<Value>, "type">>;
13
13
  type ToggleInputComponentType = <Value>(props: ToggleInputProps<Value>) => React.ReactElement;
14
14
  declare const _default: {
@@ -11,13 +11,17 @@ const Text_1 = __importDefault(require("./Text"));
11
11
  const Div_1 = __importDefault(require("./Div"));
12
12
  const Icon_1 = __importDefault(require("./Icon"));
13
13
  const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
14
+ const Label_1 = __importDefault(require("./Label"));
15
+ const componentSize = 26;
16
+ const switchComponentBallGap = 3;
17
+ const switchComponentMouseDownDifference = 4;
14
18
  const InputElement = styled_components_1.default.input.withConfig({
15
19
  shouldForwardProp: (prop) => !["theme", "normalStyle", "hoverStyle"].includes(prop),
16
20
  }) `
17
21
  position: relative;
18
22
  appearance: none;
19
- width: 26px;
20
- height: 26px;
23
+ width: ${componentSize}px;
24
+ height: ${componentSize}px;
21
25
  background-color: ${(props) => props.theme.colors.backgroundContent};
22
26
  border: 1px solid ${(props) => props.theme.colors.border};
23
27
  border-radius: ${(props) => props.theme.styles.borderRadius / 2}px;
@@ -46,13 +50,15 @@ const InputElement = styled_components_1.default.input.withConfig({
46
50
  }
47
51
  `;
48
52
  const SwitchElement = styled_components_1.default.div.withConfig({
49
- shouldForwardProp: (prop) => !["theme", "checked", "disabled", "normalStyle", "hoverStyle"].includes(prop),
53
+ shouldForwardProp: (prop) => !["theme", "checked", "disabled", "isMouseDown", "normalStyle", "hoverStyle"].includes(prop),
50
54
  }) `
55
+ --width: ${(props) => componentSize * 2 - props.theme.styles.gap / 2}px;
56
+
51
57
  position: relative;
52
- width: 36px;
53
- height: 20px;
58
+ width: var(--width);
59
+ height: ${componentSize}px;
54
60
  background-color: ${(props) => (props.checked ? props.theme.colors.primary : props.theme.colors.border)};
55
- border-radius: 10px;
61
+ border-radius: 999px;
56
62
  cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
57
63
  opacity: ${(props) => (props.disabled ? 0.5 : 1)};
58
64
  transition: ${(props) => props.theme.styles.transition};
@@ -60,14 +66,18 @@ const SwitchElement = styled_components_1.default.div.withConfig({
60
66
  &::before {
61
67
  content: "";
62
68
  position: absolute;
63
- width: 16px;
64
- height: 16px;
65
- background-color: white;
66
- border-radius: 50%;
67
- top: 2px;
68
- left: 2px;
69
+ width: ${(props) => componentSize - switchComponentBallGap * 2 + (props.isMouseDown ? switchComponentMouseDownDifference : 0)}px;
70
+ height: ${componentSize - switchComponentBallGap * 2}px;
71
+ background-color: ${(props) => props.theme.colors.base};
72
+ border-radius: 999px;
73
+ top: ${switchComponentBallGap}px;
74
+ left: ${switchComponentBallGap}px;
75
+ transform: translateX(
76
+ ${(props) => props.checked
77
+ ? `calc(var(--width) - ${componentSize + (props.isMouseDown ? switchComponentMouseDownDifference : 0)}px)`
78
+ : "0px"}
79
+ );
69
80
  transition: ${(props) => props.theme.styles.transition};
70
- transform: translateX(${(props) => (props.checked ? "16px" : "0")});
71
81
  }
72
82
 
73
83
  ${(props) => props.normalStyle}
@@ -85,19 +95,19 @@ const ToggleInputComponent = (0, react_1.forwardRef)(function ToggleInput({ labe
85
95
  const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
86
96
  const [internalChecked, setInternalChecked] = (0, react_1.useState)(false);
87
97
  const onChangeElement = (0, react_1.useCallback)((event) => {
88
- const newValue = event.target.checked;
98
+ const newIsChecked = event.target.checked;
89
99
  if (controlledChecked === undefined)
90
- setInternalChecked(newValue);
91
- onChange?.(newValue, value);
100
+ setInternalChecked(newIsChecked);
101
+ onChange?.(newIsChecked, value);
92
102
  }, [onChange, controlledChecked, value]);
93
103
  const checked = controlledChecked ?? internalChecked;
94
104
  const onClickText = (0, react_1.useCallback)(() => {
95
- const newValue = !checked;
105
+ const newIsChecked = !checked;
96
106
  if (controlledChecked === undefined)
97
- setInternalChecked(newValue);
98
- onChange?.(newValue, value);
107
+ setInternalChecked(newIsChecked);
108
+ onChange?.(newIsChecked, value);
99
109
  }, [checked, controlledChecked, onChange, value]);
100
- return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "relative", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(InputElement, { theme: theme, type: props.type ?? "checkbox", checked: checked, onChange: onChangeElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }), props.type === "checkbox" ? ((0, jsx_runtime_1.jsx)(Icon_1.default, { name: "check", position: "absolute", top: "50%", left: "50%", color: theme.colors.base, size: 14, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none", transition: theme.styles.transition })) : props.type === "radio" ? ((0, jsx_runtime_1.jsx)(Div_1.default, { position: "absolute", width: 10, height: 10, top: "50%", left: "50%", backgroundColor: theme.colors.base, borderRadius: 999, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none" })) : undefined] }), text && ((0, jsx_runtime_1.jsx)(Text_1.default, { userSelect: "none", cursor: "pointer", onClick: onClickText, children: text }))] }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: errorText || infoText }))] }));
110
+ return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && (0, jsx_runtime_1.jsx)(Label_1.default, { text: label, required: required, isError: !!errorText }), (0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { position: "relative", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(InputElement, { theme: theme, type: props.type ?? "checkbox", checked: checked, onChange: onChangeElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }), props.type === "checkbox" ? ((0, jsx_runtime_1.jsx)(Icon_1.default, { name: "check", position: "absolute", top: "50%", left: "50%", color: theme.colors.base, size: 14, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none", transition: theme.styles.transition })) : props.type === "radio" ? ((0, jsx_runtime_1.jsx)(Div_1.default, { position: "absolute", width: 10, height: 10, top: "50%", left: "50%", backgroundColor: theme.colors.base, borderRadius: 999, transform: `translate(-50%, -50%)${checked ? "" : " scale(0.4)"}`, opacity: checked ? 1 : 0, pointerEvents: "none" })) : undefined] }), text && ((0, jsx_runtime_1.jsx)(Text_1.default, { userSelect: "none", cursor: "pointer", onClick: onClickText, children: text }))] }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: errorText || infoText }))] }));
101
111
  });
102
112
  exports.default = {
103
113
  checkbox: (0, react_1.forwardRef)(function Checkbox(props, ref) {
@@ -106,7 +116,7 @@ exports.default = {
106
116
  radiobutton: (0, react_1.forwardRef)(function RadioButton(props, ref) {
107
117
  return (0, jsx_runtime_1.jsx)(ToggleInputComponent, { type: "radio", ref: ref, ...props });
108
118
  }),
109
- switch: (0, react_1.forwardRef)(function Switch({ label, errorText, infoText, disabled, onChange, checked: controlledChecked, required, ...props }, ref) {
119
+ switch: (0, react_1.forwardRef)(function Switch({ label, errorText, infoText, disabled, value, onChange, checked: controlledChecked, required, ...props }, ref) {
110
120
  const theme = (0, BetterHtmlProvider_1.useTheme)();
111
121
  const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme, true);
112
122
  const styledComponentStylesWithExcluded = (0, hooks_1.useComponentPropsWithExcludedStyle)(props);
@@ -114,15 +124,16 @@ exports.default = {
114
124
  const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
115
125
  const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
116
126
  const [internalChecked, setInternalChecked] = (0, hooks_1.useBooleanState)();
127
+ const [isMouseDown, setIsMouseDown] = (0, hooks_1.useBooleanState)();
117
128
  const checked = controlledChecked ?? internalChecked;
118
129
  const onClickElement = (0, react_1.useCallback)(() => {
119
130
  if (disabled)
120
131
  return;
121
- const newValue = !checked;
132
+ const newIsChecked = !checked;
122
133
  if (controlledChecked === undefined)
123
- setInternalChecked.setState(newValue);
124
- onChange?.(newValue);
125
- }, [disabled, checked, onChange, controlledChecked]);
126
- return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "label", height: 16, fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: [label, required && ((0, jsx_runtime_1.jsxs)(Text_1.default, { as: "span", fontSize: 16, color: theme.colors.error, children: [" ", "*"] }))] })), (0, jsx_runtime_1.jsx)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, children: (0, jsx_runtime_1.jsx)(SwitchElement, { theme: theme, checked: checked, disabled: disabled ?? false, onClick: onClickElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }) }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: errorText || infoText }))] }));
134
+ setInternalChecked.setState(newIsChecked);
135
+ onChange?.(newIsChecked, value);
136
+ }, [disabled, checked, onChange, controlledChecked, value]);
137
+ return ((0, jsx_runtime_1.jsxs)(Div_1.default.column, { width: "100%", gap: theme.styles.gap / 2, ...styledComponentStylesWithExcluded, children: [label && (0, jsx_runtime_1.jsx)(Label_1.default, { text: label, required: required, isError: !!errorText }), (0, jsx_runtime_1.jsx)(Div_1.default.row, { alignItems: "center", gap: theme.styles.gap, onMouseDown: setIsMouseDown.setTrue, onMouseUp: setIsMouseDown.setFalse, onMouseOut: setIsMouseDown.setFalse, onTouchStart: setIsMouseDown.setTrue, onTouchEnd: setIsMouseDown.setFalse, onTouchCancel: setIsMouseDown.setFalse, children: (0, jsx_runtime_1.jsx)(SwitchElement, { theme: theme, checked: checked, disabled: disabled ?? false, isMouseDown: isMouseDown, onClick: onClickElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps }) }), (errorText || infoText) && ((0, jsx_runtime_1.jsx)(Text_1.default, { as: "span", display: "block", fontSize: 14, color: errorText ? theme.colors.error : theme.colors.textSecondary, children: errorText || infoText }))] }));
127
138
  }),
128
139
  };
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ import Form from "./components/Form";
16
16
  import Label from "./components/Label";
17
17
  import FormRow from "./components/FormRow";
18
18
  import BetterHtmlProvider, { useBetterHtmlContext, useTheme, useLoader, useLoaderControls } from "./components/BetterHtmlProvider";
19
- import { usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery } from "./utils/hooks";
19
+ import { usePageResize, usePageScroll, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery } from "./utils/hooks";
20
20
  import { generateRandomString, getBrowser, formatPhoneNumber } from "./utils/functions";
21
21
  import { type OmitProps, type ExcludeOptions, type PickValue, type PartialRecord, type DeepPartialRecord, type PickAllRequired } from "./types/app";
22
22
  import { type AppConfig, type BetterHtmlConfig } from "./types/config";
@@ -27,4 +27,4 @@ import { type PluginName, type BetterHtmlPlugin } from "./types/plugin";
27
27
  import { type Color, type ColorName, type ColorTheme, type Colors, type Styles, type Theme, type ThemeConfig } from "./types/theme";
28
28
  import { isMobileDevice } from "./constants";
29
29
  export * from "./plugins";
30
- export { BetterHtmlProvider, Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, PageHeader, Chip, InputField, Dropdown, DropdownOption, ToggleInput, Form, Label, FormRow, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery, generateRandomString, getBrowser, formatPhoneNumber, OmitProps, ExcludeOptions, PickValue, PartialRecord, DeepPartialRecord, PickAllRequired, AppConfig, BetterHtmlConfig, AssetName, AssetsConfig, IconName, IconsConfig, LoaderName, PluginName, BetterHtmlPlugin, LoaderConfig, Color, ColorName, ColorTheme, Colors, Styles, Theme, ThemeConfig, isMobileDevice, };
30
+ export { BetterHtmlProvider, Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, PageHeader, Chip, InputField, Dropdown, DropdownOption, ToggleInput, Form, Label, FormRow, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, usePageScroll, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery, generateRandomString, getBrowser, formatPhoneNumber, OmitProps, ExcludeOptions, PickValue, PartialRecord, DeepPartialRecord, PickAllRequired, AppConfig, BetterHtmlConfig, AssetName, AssetsConfig, IconName, IconsConfig, LoaderName, PluginName, BetterHtmlPlugin, LoaderConfig, Color, ColorName, ColorTheme, Colors, Styles, Theme, ThemeConfig, isMobileDevice, };
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
39
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
40
40
  };
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.isMobileDevice = exports.formatPhoneNumber = exports.getBrowser = exports.generateRandomString = exports.useUrlQuery = exports.useForm = exports.useDebounceState = exports.useBooleanState = exports.useMediaQuery = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.FormRow = exports.Label = exports.Form = exports.ToggleInput = exports.Dropdown = exports.InputField = exports.Chip = exports.PageHeader = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = exports.BetterHtmlProvider = void 0;
42
+ exports.isMobileDevice = exports.formatPhoneNumber = exports.getBrowser = exports.generateRandomString = exports.useUrlQuery = exports.useForm = exports.useDebounceState = exports.useBooleanState = exports.useMediaQuery = exports.usePageScroll = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.FormRow = exports.Label = exports.Form = exports.ToggleInput = exports.Dropdown = exports.InputField = exports.Chip = exports.PageHeader = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = exports.BetterHtmlProvider = void 0;
43
43
  const Div_1 = __importDefault(require("./components/Div"));
44
44
  exports.Div = Div_1.default;
45
45
  const Text_1 = __importDefault(require("./components/Text"));
@@ -82,6 +82,7 @@ Object.defineProperty(exports, "useLoader", { enumerable: true, get: function ()
82
82
  Object.defineProperty(exports, "useLoaderControls", { enumerable: true, get: function () { return BetterHtmlProvider_1.useLoaderControls; } });
83
83
  const hooks_1 = require("./utils/hooks");
84
84
  Object.defineProperty(exports, "usePageResize", { enumerable: true, get: function () { return hooks_1.usePageResize; } });
85
+ Object.defineProperty(exports, "usePageScroll", { enumerable: true, get: function () { return hooks_1.usePageScroll; } });
85
86
  Object.defineProperty(exports, "useMediaQuery", { enumerable: true, get: function () { return hooks_1.useMediaQuery; } });
86
87
  Object.defineProperty(exports, "useBooleanState", { enumerable: true, get: function () { return hooks_1.useBooleanState; } });
87
88
  Object.defineProperty(exports, "useDebounceState", { enumerable: true, get: function () { return hooks_1.useDebounceState; } });
@@ -62,6 +62,8 @@ export declare function useForm<FormFields extends Record<string, string | numbe
62
62
  getTextAreaProps: <FieldName extends keyof FormFields>(field: FieldName) => ComponentPropWithRef<HTMLTextAreaElement, TextareaFieldProps>;
63
63
  getDropdownFieldProps: <FieldName extends keyof FormFields>(field: FieldName) => OmitProps<ComponentPropWithRef<HTMLDivElement, DropdownProps<FormFields[FieldName], unknown>>, "options">;
64
64
  getCheckboxProps: <FieldName extends keyof FormFields>(field: FieldName) => ComponentPropWithRef<ToggleInputRef, ToggleInputProps<FormFields[FieldName]>>;
65
+ getRadioButtonProps: <FieldName extends keyof FormFields>(field: FieldName, value: FormFields[FieldName]) => ComponentPropWithRef<ToggleInputRef, ToggleInputProps<FormFields[FieldName]>>;
66
+ getSwitchProps: <FieldName extends keyof FormFields>(field: FieldName) => ComponentPropWithRef<ToggleInputRef, ToggleInputProps<FormFields[FieldName]>>;
65
67
  focusField: (field: keyof FormFields) => void;
66
68
  onSubmit: (event: React.FormEvent<HTMLFormElement>) => Promise<void>;
67
69
  reset: () => void;
@@ -255,6 +255,28 @@ function useForm({ defaultValues, requiredFields, onSubmit, validate, }) {
255
255
  errorText: errors[field],
256
256
  };
257
257
  }, [values, errors, setFieldValue]);
258
+ const getRadioButtonProps = (0, react_1.useCallback)((field, value) => {
259
+ return {
260
+ required: requiredFields?.includes(field),
261
+ checked: values[field] === value,
262
+ name: field.toString(),
263
+ value,
264
+ onChange: (checked, newValue) => {
265
+ setFieldValue(field, checked ? newValue : undefined);
266
+ },
267
+ errorText: errors[field],
268
+ };
269
+ }, [values, errors, setFieldValue]);
270
+ const getSwitchProps = (0, react_1.useCallback)((field) => {
271
+ return {
272
+ required: requiredFields?.includes(field),
273
+ checked: values[field],
274
+ onChange: (checked) => {
275
+ setFieldValue(field, checked);
276
+ },
277
+ errorText: errors[field],
278
+ };
279
+ }, [values, errors, setFieldValue]);
258
280
  const focusField = (0, react_1.useCallback)((field) => {
259
281
  inputFieldRefs.current[field]?.focus();
260
282
  }, []);
@@ -290,6 +312,8 @@ function useForm({ defaultValues, requiredFields, onSubmit, validate, }) {
290
312
  getTextAreaProps,
291
313
  getDropdownFieldProps,
292
314
  getCheckboxProps,
315
+ getRadioButtonProps,
316
+ getSwitchProps,
293
317
  focusField,
294
318
  onSubmit: onSubmitFunction,
295
319
  reset,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-better-html",
3
- "version": "1.1.42",
3
+ "version": "1.1.44",
4
4
  "description": "A component library for react that is as close to plane html as possible",
5
5
  "main": "dist/index.js",
6
6
  "files": [