@react-fabric/form 1.0.0-beta.54 → 1.0.0-beta.56

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.
Files changed (50) hide show
  1. package/dist/cjs/builder/FileField.js +2 -2
  2. package/dist/cjs/input/AvatarInput.js +17 -13
  3. package/dist/cjs/input/ColorInput.js +5 -3
  4. package/dist/cjs/input/ColorPicker.js +52 -46
  5. package/dist/cjs/input/DateInput.js +6 -4
  6. package/dist/cjs/input/Input.js +6 -4
  7. package/dist/cjs/input/Number.js +6 -4
  8. package/dist/cjs/input/Password.js +6 -4
  9. package/dist/cjs/input/Search.js +6 -4
  10. package/dist/cjs/input/Switch.js +3 -3
  11. package/dist/cjs/input/Textarea.js +6 -4
  12. package/dist/cjs/select/AutoComplete.js +1 -2
  13. package/dist/esm/builder/FileField.js +3 -3
  14. package/dist/esm/input/AvatarInput.js +18 -14
  15. package/dist/esm/input/ColorInput.js +5 -3
  16. package/dist/esm/input/ColorPicker.js +52 -46
  17. package/dist/esm/input/DateInput.js +6 -4
  18. package/dist/esm/input/Input.js +6 -4
  19. package/dist/esm/input/Number.js +6 -4
  20. package/dist/esm/input/Password.js +6 -4
  21. package/dist/esm/input/Search.js +6 -4
  22. package/dist/esm/input/Switch.js +3 -3
  23. package/dist/esm/input/Textarea.js +6 -4
  24. package/dist/esm/select/AutoComplete.js +1 -2
  25. package/dist/types/input/AvatarInput.d.ts +5 -1
  26. package/dist/types/input/DateInput.d.ts +1 -1
  27. package/dist/types/input/Input.d.ts +1 -1
  28. package/dist/types/input/Number.d.ts +1 -1
  29. package/dist/types/input/Password.d.ts +1 -1
  30. package/dist/types/input/RangeSlider.d.ts +1 -1
  31. package/dist/types/input/Search.d.ts +1 -1
  32. package/dist/types/input/Slider.d.ts +1 -1
  33. package/dist/types/input/Textarea.d.ts +1 -1
  34. package/dist/types/types/index.d.ts +4 -0
  35. package/package.json +4 -4
  36. package/src/builder/FileField.tsx +9 -3
  37. package/src/input/AvatarInput.tsx +19 -10
  38. package/src/input/ColorInput.tsx +5 -3
  39. package/src/input/ColorPicker.tsx +48 -43
  40. package/src/input/DateInput.tsx +4 -3
  41. package/src/input/Input.tsx +4 -3
  42. package/src/input/Number.tsx +4 -3
  43. package/src/input/Password.tsx +4 -3
  44. package/src/input/RangeSlider.tsx +1 -1
  45. package/src/input/Search.tsx +4 -3
  46. package/src/input/Slider.tsx +4 -1
  47. package/src/input/Switch.tsx +3 -3
  48. package/src/input/Textarea.tsx +4 -3
  49. package/src/select/AutoComplete.tsx +1 -1
  50. package/src/types/index.ts +4 -0
@@ -21,7 +21,13 @@
21
21
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- import { Button, Icon, ProgressBar, Tooltip } from "@react-fabric/core";
24
+ import {
25
+ Button,
26
+ CoreIcons,
27
+ Icon,
28
+ ProgressBar,
29
+ Tooltip,
30
+ } from "@react-fabric/core";
25
31
  import { FileUtil, Format, isString } from "@react-fabric/utilities";
26
32
  import { Fragment } from "react";
27
33
  import { useTranslation } from "react-i18next";
@@ -118,7 +124,7 @@ export const FileField = ({
118
124
  </div>
119
125
  {file.progress && (
120
126
  <Icon
121
- icon="mdi mdi-stop-circle"
127
+ icon={CoreIcons.stop}
122
128
  bg="danger"
123
129
  color="white"
124
130
  size="sm"
@@ -129,7 +135,7 @@ export const FileField = ({
129
135
  )}
130
136
  {!file.progress && (
131
137
  <Icon
132
- icon="mdi mdi-trash-can"
138
+ icon={CoreIcons.trash}
133
139
  color="danger"
134
140
  size="sm"
135
141
  aria-label="remove"
@@ -21,7 +21,7 @@
21
21
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- import { Avatar, Icon, ProgressBar } from "@react-fabric/core";
24
+ import { Avatar, CoreIcons, Icon, ProgressBar } from "@react-fabric/core";
25
25
  import { type RefProp } from "@react-fabric/core/dist/types/types";
26
26
  import { useEffect, useState } from "react";
27
27
  import { useFileUploader, type UploadHandler } from "../hooks/useFileUploader";
@@ -36,6 +36,10 @@ export interface Props extends RefProp {
36
36
  * actual avatar storage path
37
37
  */
38
38
  value?: string;
39
+ /**
40
+ * default avatar image
41
+ */
42
+ defaultValue?: string;
39
43
  /**
40
44
  * avatar name
41
45
  */
@@ -71,6 +75,7 @@ export const AvatarInput = ({
71
75
  size = "6rem",
72
76
  avatarName,
73
77
  value,
78
+ defaultValue,
74
79
  fileUrl,
75
80
  uploadHandler,
76
81
  ...rest
@@ -99,16 +104,19 @@ export const AvatarInput = ({
99
104
  })
100
105
  );
101
106
  } else {
102
- setBase64("");
107
+ setBase64(fileUrl?.(defaultValue ?? "") ?? defaultValue ?? "");
103
108
  }
104
- }, [files, list]);
109
+ }, [files, list, defaultValue]);
105
110
 
106
111
  useEffect(() => {
112
+ !value &&
113
+ defaultValue &&
114
+ setBase64(fileUrl?.(defaultValue) ?? defaultValue);
107
115
  value && setBase64(fileUrl?.(value) ?? value);
108
- }, [value]);
116
+ }, [value, defaultValue]);
109
117
 
110
118
  return (
111
- <div className="flex flex-nowrap items-end">
119
+ <div className="flex flex-nowrap items-end overflow-hidden">
112
120
  <div className="inline-block leading-none rounded-full relative outline overflow-hidden">
113
121
  <Avatar name={avatarName ?? "temp"} size={size} avatar={base64} />
114
122
  <div className="absolute inset-x-0 bottom-0 cursor-pointer bg-black/20 hover:bg-black/50 text-white text-xs text-center py-1">
@@ -121,9 +129,9 @@ export const AvatarInput = ({
121
129
  />
122
130
  </div>
123
131
  </div>
124
- <HiddenInput hiddenValue={list?.[0]?.path} {...rest} />
132
+ <HiddenInput hiddenValue={list?.[0]?.path ?? defaultValue} {...rest} />
125
133
  {files.map((file, idx) => (
126
- <div key={idx} className="px-2 py-1 flex-1">
134
+ <div key={idx} className="px-2 py-1 flex-1 overflow-hidden">
127
135
  <div className="flex flex-nowrap gap-1 items-center">
128
136
  <div className="flex-initial truncate pe-2">{file.filename}</div>
129
137
  {file.error && (
@@ -133,20 +141,21 @@ export const AvatarInput = ({
133
141
  )}
134
142
  {file.progress && (
135
143
  <Icon
136
- icon="mdi mdi-stop-circle"
144
+ icon={CoreIcons.stop}
137
145
  bg="danger"
138
146
  color="white"
139
147
  size="sm"
140
- className="p-[2px]"
148
+ className="p-[2px] flex-content"
141
149
  aria-label="abort"
142
150
  onClick={() => file.abort?.()}
143
151
  />
144
152
  )}
145
153
  {!file.progress && (
146
154
  <Icon
147
- icon="mdi mdi-trash-can"
155
+ icon={CoreIcons.trash}
148
156
  color="danger"
149
157
  size="sm"
158
+ className="flex-content"
150
159
  aria-label="remove"
151
160
  onClick={() => remove(file.key)}
152
161
  />
@@ -96,10 +96,11 @@ export const ColorInput = ({
96
96
 
97
97
  const handleChange = useCallback(
98
98
  (e?: string) => {
99
- setActualValue(e ?? defaultColor);
100
- onChange != null && startTransition(() => onChange(e ?? null));
99
+ const value = e ?? defaultColor;
100
+ setActualValue(value);
101
+ onChange != null && startTransition(() => onChange(value ?? null));
101
102
  },
102
- [onChange],
103
+ [onChange, defaultColor],
103
104
  );
104
105
 
105
106
  const arrowRef = useRef(null);
@@ -200,6 +201,7 @@ export const ColorInput = ({
200
201
  )}
201
202
  {!disabled && showPicker && (
202
203
  <Icon
204
+ className="flex-content p-1"
203
205
  icon={CoreIcons.colorPicker}
204
206
  onClick={() =>
205
207
  (window as AnyObject).EyeDropper &&
@@ -137,50 +137,55 @@ export const ColorPicker: FC<ColorProps> = memo(
137
137
  );
138
138
 
139
139
  return (
140
- <SketchPicker
141
- width="16rem"
142
- className={"fabric-colorPicker"}
143
- styles={
144
- {
145
- default: {
146
- hue: {
147
- boxShadow: "0 0 1px 1px var(--color-shadow)",
140
+ <div
141
+ // prevent default on mouse down to avoid selection issues
142
+ onMouseDown={(e) => e.preventDefault()}
143
+ >
144
+ <SketchPicker
145
+ width="16rem"
146
+ className={"fabric-colorPicker"}
147
+ styles={
148
+ {
149
+ default: {
150
+ hue: {
151
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
152
+ },
153
+ alpha: {
154
+ backgroundColor: "var(--fabric-bg)",
155
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
156
+ },
157
+ color: {
158
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
159
+ },
160
+ saturation: {
161
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
162
+ },
163
+ activeColor: {
164
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
165
+ },
166
+ picker: {
167
+ backgroundColor: "var(--fabric-bg)",
168
+ boxShadow:
169
+ "0 0 0 1px var(--color-shadow), 0 0 8px var(--fabric-shadow)",
170
+ },
171
+ checkboard: {
172
+ white: "transparent",
173
+ black: "red",
174
+ },
148
175
  },
149
- alpha: {
150
- backgroundColor: "var(--fabric-bg)",
151
- boxShadow: "0 0 1px 1px var(--color-shadow)",
152
- },
153
- color: {
154
- boxShadow: "0 0 1px 1px var(--color-shadow)",
155
- },
156
- saturation: {
157
- boxShadow: "0 0 1px 1px var(--color-shadow)",
158
- },
159
- activeColor: {
160
- boxShadow: "0 0 1px 1px var(--color-shadow)",
161
- },
162
- picker: {
163
- backgroundColor: "var(--fabric-bg)",
164
- boxShadow:
165
- "0 0 0 1px var(--color-shadow), 0 0 8px var(--fabric-shadow)",
166
- },
167
- checkboard: {
168
- white: "transparent",
169
- black: "red",
170
- },
171
- },
172
- } as AnyObject
173
- }
174
- color={actualValue}
175
- presetColors={swatches}
176
- disableAlpha={hideAlpha}
177
- onChange={({ rgb: { a = 1, ...rgb } }) =>
178
- setActualValue(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
179
- }
180
- onChangeComplete={({ rgb: { a = 1, ...rgb } }) =>
181
- handleChange(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
182
- }
183
- />
176
+ } as AnyObject
177
+ }
178
+ color={actualValue}
179
+ presetColors={swatches}
180
+ disableAlpha={hideAlpha}
181
+ onChange={({ rgb: { a = 1, ...rgb } }) =>
182
+ setActualValue(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
183
+ }
184
+ onChangeComplete={({ rgb: { a = 1, ...rgb } }) =>
185
+ handleChange(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
186
+ }
187
+ />
188
+ </div>
184
189
  );
185
190
  },
186
191
  );
@@ -88,6 +88,7 @@ export const DateInput = ({
88
88
  disabled,
89
89
  required,
90
90
  placeholder,
91
+ defaultValue,
91
92
  autoFocus,
92
93
  error,
93
94
  type = "date",
@@ -102,7 +103,7 @@ export const DateInput = ({
102
103
  }: DateProps) => {
103
104
  const [actualValue, setActualValue] = useState("");
104
105
  const [inputValue, setInputValue] = useState("");
105
- const deferred = useDeferredValue(value);
106
+ const deferred = useDeferredValue(value ?? defaultValue);
106
107
 
107
108
  const inputFormat = useMemo(
108
109
  () => (type === "datetime" ? "yyyy-MM-dd HH:mm" : "yyyy-MM-dd"),
@@ -118,7 +119,7 @@ export const DateInput = ({
118
119
 
119
120
  const handleChange = useCallback(
120
121
  (e?: ChangeEvent<HTMLInputElement>) => {
121
- const value = e?.currentTarget.value;
122
+ const value = e?.currentTarget.value ?? defaultValue;
122
123
  if (value) {
123
124
  const parsed = DateUtil.parseDate(value);
124
125
  setActualValue(parsed?.toISOString?.());
@@ -131,7 +132,7 @@ export const DateInput = ({
131
132
  onChange != null && startTransition(() => onChange(null));
132
133
  }
133
134
  },
134
- [onChange, inputFormat],
135
+ [onChange, inputFormat, defaultValue],
135
136
  );
136
137
 
137
138
  const handleDateChange = useCallback(
@@ -58,6 +58,7 @@ export const Input = ({
58
58
  disabled,
59
59
  required,
60
60
  placeholder,
61
+ defaultValue,
61
62
  autoFocus,
62
63
  error,
63
64
  monospace,
@@ -69,7 +70,7 @@ export const Input = ({
69
70
  ...rest
70
71
  }: TextInputProps) => {
71
72
  const [actualValue, setActualValue] = useState("");
72
- const deferred = useDeferredValue(value);
73
+ const deferred = useDeferredValue(value ?? defaultValue);
73
74
 
74
75
  const handleEnterPressed = useHandleEnter(onEnterPressed);
75
76
 
@@ -79,11 +80,11 @@ export const Input = ({
79
80
 
80
81
  const handleChange = useCallback(
81
82
  (e?: ChangeEvent<HTMLInputElement>) => {
82
- const value = e?.target.value;
83
+ const value = e?.target.value ?? defaultValue;
83
84
  setActualValue(value ?? "");
84
85
  onChange?.(value ?? null);
85
86
  },
86
- [onchange],
87
+ [onChange, defaultValue],
87
88
  );
88
89
 
89
90
  return (
@@ -66,6 +66,7 @@ export const Number = ({
66
66
  disabled,
67
67
  required,
68
68
  placeholder,
69
+ defaultValue,
69
70
  autoFocus,
70
71
  name,
71
72
  min,
@@ -78,7 +79,7 @@ export const Number = ({
78
79
  ...rest
79
80
  }: NumberProps) => {
80
81
  const [actualValue, setActualValue] = useState<"" | number>("");
81
- const deferred = useDeferredValue(value);
82
+ const deferred = useDeferredValue(value ?? defaultValue);
82
83
 
83
84
  const handleEnterPressed = useHandleEnter(onEnterPressed);
84
85
 
@@ -88,11 +89,11 @@ export const Number = ({
88
89
 
89
90
  const handleChange = useCallback(
90
91
  (e?: ChangeEvent<HTMLInputElement>) => {
91
- const number = e?.target.valueAsNumber;
92
+ const number = e?.target.valueAsNumber ?? defaultValue;
92
93
  setActualValue(number ?? "");
93
94
  onChange?.(number ?? null);
94
95
  },
95
- [onChange],
96
+ [onChange, defaultValue],
96
97
  );
97
98
 
98
99
  return (
@@ -63,6 +63,7 @@ export const Password = ({
63
63
  disabled,
64
64
  required,
65
65
  placeholder,
66
+ defaultValue,
66
67
  autoFocus,
67
68
  showToggle,
68
69
  onBlur,
@@ -75,7 +76,7 @@ export const Password = ({
75
76
  const [show, setShow] = useState(false);
76
77
 
77
78
  const [actualValue, setActualValue] = useState("");
78
- const deferred = useDeferredValue(value);
79
+ const deferred = useDeferredValue(value ?? defaultValue);
79
80
 
80
81
  const handleEnterPressed = useHandleEnter(onEnterPressed);
81
82
 
@@ -85,11 +86,11 @@ export const Password = ({
85
86
 
86
87
  const handleChange = useCallback(
87
88
  (e?: ChangeEvent<HTMLInputElement>) => {
88
- const value = e?.target.value;
89
+ const value = e?.target.value ?? defaultValue;
89
90
  setActualValue(value ?? "");
90
91
  onChange?.(value ?? null);
91
92
  },
92
- [onChange],
93
+ [onChange, defaultValue],
93
94
  );
94
95
 
95
96
  return (
@@ -38,7 +38,7 @@ import { type InputProps } from "../types";
38
38
  export interface RangeProps
39
39
  extends Omit<
40
40
  InputProps<[number, number]>,
41
- "placeholder" | "allowClear" | "children"
41
+ "placeholder" | "allowClear" | "children" | "defaultValue"
42
42
  > {
43
43
  /**
44
44
  * min value
@@ -74,6 +74,7 @@ export const Search = ({
74
74
  required,
75
75
  searching,
76
76
  placeholder,
77
+ defaultValue,
77
78
  autoFocus,
78
79
  hideHandle,
79
80
  allowClear = true,
@@ -86,7 +87,7 @@ export const Search = ({
86
87
  ...rest
87
88
  }: SearchProps) => {
88
89
  const [actualValue, setActualValue] = useState("");
89
- const deferred = useDeferredValue(value);
90
+ const deferred = useDeferredValue(value ?? defaultValue);
90
91
 
91
92
  const refValue = useRef("");
92
93
  const handleSearch = useDebounce(
@@ -103,7 +104,7 @@ export const Search = ({
103
104
 
104
105
  const handleChange = useCallback(
105
106
  (e?: ChangeEvent<HTMLInputElement>) => {
106
- const value = e?.target.value;
107
+ const value = e?.target.value ?? defaultValue;
107
108
  refValue.current = value ?? "";
108
109
  setActualValue(value ?? "");
109
110
  onChange?.(value ?? null);
@@ -113,7 +114,7 @@ export const Search = ({
113
114
  handleSearch();
114
115
  }
115
116
  },
116
- [onChange, searchOnChange, handleSearch],
117
+ [onChange, searchOnChange, handleSearch, defaultValue],
117
118
  );
118
119
 
119
120
  return (
@@ -36,7 +36,10 @@ import { useRanger } from "../ranger";
36
36
  import { type InputProps } from "../types";
37
37
 
38
38
  export interface SliderProps
39
- extends Omit<InputProps<number>, "placeholder" | "allowClear" | "children"> {
39
+ extends Omit<
40
+ InputProps<number>,
41
+ "placeholder" | "allowClear" | "children" | "defaultValue"
42
+ > {
40
43
  /**
41
44
  * min value
42
45
  */
@@ -147,7 +147,7 @@ export const Switch = ({
147
147
  actualValue && getBgClass(color ? `${color}-500` : "primary-500"),
148
148
  !actualValue &&
149
149
  (defaultColor ? getBgClass(`${defaultColor}-500`) : "bg-tint-200"),
150
- "relative grid grid-cols-2 items-center h-6 min-w-10 cursor-pointer rounded-full p-1 transition-colors duration-200 ease-in-out",
150
+ "relative grid grid-cols-2 items-center h-[1.5em] min-w-[2.5em] cursor-pointer rounded-full p-[0.25em] transition-colors duration-200 ease-in-out",
151
151
  )}
152
152
  style={{
153
153
  backgroundColor: actualValue
@@ -177,10 +177,10 @@ export const Switch = ({
177
177
  className={classNames(
178
178
  !disabled && "shadow-sm",
179
179
  actualValue ? "translate-x-[100%]" : "translate-x-0",
180
- "pointer-events-none inline-block h-4 start-1 absolute rounded-full bg-white ring-0 transition duration-200 ease-in-out",
180
+ "pointer-events-none inline-block h-[1em] start-[0.25em] absolute rounded-full bg-white ring-0 transition duration-200 ease-in-out",
181
181
  )}
182
182
  style={{
183
- width: "calc(50% - 0.25rem)",
183
+ width: "calc(50% - 0.25em)",
184
184
  }}
185
185
  />
186
186
  {(!!onLabel || !!offLabel) && (
@@ -74,6 +74,7 @@ export const Textarea = ({
74
74
  disabled,
75
75
  required,
76
76
  placeholder,
77
+ defaultValue,
77
78
  autoFocus,
78
79
  rows = 5,
79
80
  maxRows = 12,
@@ -87,7 +88,7 @@ export const Textarea = ({
87
88
  }: TextareaProps) => {
88
89
  const [actualValue, setActualValue] = useState("");
89
90
  const [fixedRows, setFixedRows] = useState(rows);
90
- const deferred = useDeferredValue(value);
91
+ const deferred = useDeferredValue(value ?? defaultValue);
91
92
  const wrapperRef = useRef(null);
92
93
 
93
94
  useEffect(() => {
@@ -96,11 +97,11 @@ export const Textarea = ({
96
97
 
97
98
  const handleChange = useCallback(
98
99
  (e?: ChangeEvent<HTMLTextAreaElement>) => {
99
- const value = e?.target.value;
100
+ const value = e?.target.value ?? defaultValue;
100
101
  setActualValue(value ?? "");
101
102
  onChange?.(value ?? null);
102
103
  },
103
- [onChange],
104
+ [onChange, defaultValue],
104
105
  );
105
106
 
106
107
  useEffect(() => {
@@ -190,7 +190,7 @@ export const AutoComplete = ({
190
190
  return false;
191
191
  } else {
192
192
  onEnterPressed?.(evt);
193
- submitRef.current?.click();
193
+ setOpen(false);
194
194
  }
195
195
  } else if (evt.key === "Backspace") {
196
196
  !state.query && multiple && handleRemove();
@@ -32,6 +32,10 @@ export interface InputProps<V = string> extends TestProps {
32
32
  * value
33
33
  */
34
34
  value?: V | null;
35
+ /**
36
+ * default value
37
+ */
38
+ defaultValue?: V | null;
35
39
  /**
36
40
  * change handler
37
41
  */