@react-fabric/form 1.0.0-beta.5 → 1.0.0-beta.51
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/{src/input/ArrayInput.module.css → css/_arrayInput.css} +8 -8
- package/css/_colorPicker.css +65 -0
- package/{src/internal/Field.module.css → css/_field.css} +64 -29
- package/{src/input/File.module.css → css/_file.css} +21 -6
- package/css/styles.css +27 -0
- package/dist/cjs/builder/FileField.js +37 -25
- package/dist/cjs/builder/FormField.js +50 -34
- package/dist/cjs/builder/SchemaEditor.js +72 -0
- package/dist/cjs/builder/components/AddSchemaFields.js +62 -0
- package/dist/cjs/builder/components/SchemaArrayForm.js +143 -0
- package/dist/cjs/builder/components/SchemaField.js +414 -0
- package/dist/cjs/form/Controller.js +1 -1
- package/dist/cjs/form/Form.js +11 -6
- package/dist/cjs/hooks/useFormBuilder.js +27 -15
- package/dist/cjs/index.js +11 -2
- package/dist/cjs/input/ArrayInput.js +61 -33
- package/dist/cjs/input/AvatarInput.js +9 -8
- package/dist/cjs/input/Checkbox.js +6 -5
- package/dist/cjs/input/ColorInput.js +95 -56
- package/dist/cjs/input/ColorPicker.js +1 -35
- package/dist/cjs/input/DateInput.js +186 -0
- package/dist/cjs/input/Field.js +5 -4
- package/dist/cjs/input/File.js +4 -7
- package/dist/cjs/input/Hidden.js +3 -1
- package/dist/cjs/input/Input.js +11 -7
- package/dist/cjs/input/Number.js +9 -7
- package/dist/cjs/input/Password.js +10 -8
- package/dist/cjs/input/Radio.js +2 -2
- package/dist/cjs/input/RadioGroup.js +6 -3
- package/dist/cjs/input/{Range.js → RangeSlider.js} +5 -5
- package/dist/cjs/input/Search.js +16 -16
- package/dist/cjs/input/Slider.js +3 -3
- package/dist/cjs/input/Switch.js +30 -7
- package/dist/cjs/input/Textarea.js +13 -4
- package/dist/cjs/internal/ErrorIcon.js +1 -1
- package/dist/cjs/internal/FieldWrapper.js +11 -4
- package/dist/cjs/internal/InputWrapper.js +19 -16
- package/dist/cjs/select/AutoComplete.js +12 -8
- package/dist/cjs/select/DualList.js +4 -1
- package/dist/cjs/select/List.js +45 -20
- package/dist/cjs/select/Options.js +2 -2
- package/dist/cjs/select/Select.js +14 -4
- package/dist/cjs/select/useSelect.js +10 -6
- package/dist/cjs/types/schema.js +43 -0
- package/dist/cjs/utils/eventHandlers.js +11 -5
- package/dist/cjs/utils/getColor.js +6 -0
- package/dist/esm/builder/FileField.js +39 -27
- package/dist/esm/builder/FormField.js +50 -34
- package/dist/esm/builder/SchemaEditor.js +72 -0
- package/dist/esm/builder/components/AddSchemaFields.js +62 -0
- package/dist/esm/builder/components/SchemaArrayForm.js +143 -0
- package/dist/esm/builder/components/SchemaField.js +414 -0
- package/dist/esm/form/Controller.js +1 -1
- package/dist/esm/form/Form.js +11 -6
- package/dist/esm/hooks/useFormBuilder.js +25 -13
- package/dist/esm/index.js +5 -1
- package/dist/esm/input/ArrayInput.js +61 -33
- package/dist/esm/input/AvatarInput.js +9 -8
- package/dist/esm/input/Checkbox.js +6 -5
- package/dist/esm/input/ColorInput.js +97 -58
- package/dist/esm/input/ColorPicker.js +1 -35
- package/dist/esm/input/DateInput.js +186 -0
- package/dist/esm/input/Field.js +6 -5
- package/dist/esm/input/File.js +6 -9
- package/dist/esm/input/Hidden.js +3 -1
- package/dist/esm/input/Input.js +13 -9
- package/dist/esm/input/Number.js +11 -9
- package/dist/esm/input/Password.js +12 -10
- package/dist/esm/input/Radio.js +2 -2
- package/dist/esm/input/RadioGroup.js +7 -4
- package/dist/esm/input/{Range.js → RangeSlider.js} +5 -5
- package/dist/esm/input/Search.js +18 -18
- package/dist/esm/input/Slider.js +3 -3
- package/dist/esm/input/Switch.js +32 -9
- package/dist/esm/input/Textarea.js +14 -5
- package/dist/esm/internal/ErrorIcon.js +1 -1
- package/dist/esm/internal/FieldWrapper.js +11 -4
- package/dist/esm/internal/InputWrapper.js +19 -16
- package/dist/esm/select/AutoComplete.js +12 -8
- package/dist/esm/select/DualList.js +4 -1
- package/dist/esm/select/List.js +46 -21
- package/dist/esm/select/Options.js +2 -2
- package/dist/esm/select/Select.js +14 -4
- package/dist/esm/select/useSelect.js +11 -7
- package/{src/input/ColorPicker.module.css → dist/esm/types/schema.js} +18 -27
- package/dist/esm/utils/eventHandlers.js +11 -5
- package/dist/esm/utils/getColor.js +6 -1
- package/dist/types/builder/FileField.d.ts +4 -2
- package/dist/types/builder/FormField.d.ts +3 -1
- package/dist/types/builder/SchemaEditor.d.ts +2 -0
- package/dist/types/builder/components/AddSchemaFields.d.ts +2 -0
- package/dist/types/builder/components/SchemaArrayForm.d.ts +2 -0
- package/dist/types/builder/components/SchemaField.d.ts +10 -0
- package/dist/types/form/Controller.d.ts +2 -2
- package/dist/types/form/Form.d.ts +5 -1
- package/dist/types/hooks/useFormBuilder.d.ts +3 -1
- package/dist/types/index.d.ts +5 -2
- package/dist/types/input/ArrayInput.d.ts +39 -6
- package/dist/types/input/AvatarInput.d.ts +6 -3
- package/dist/types/input/Checkbox.d.ts +4 -4
- package/dist/types/input/ColorInput.d.ts +2 -2
- package/dist/types/input/ColorPicker.d.ts +1 -1
- package/dist/types/input/DateInput.d.ts +19 -0
- package/dist/types/input/Field.d.ts +0 -1
- package/dist/types/input/Input.d.ts +1 -1
- package/dist/types/input/Number.d.ts +1 -1
- package/dist/types/input/Password.d.ts +1 -1
- package/dist/types/input/Radio.d.ts +0 -1
- package/dist/types/input/RadioGroup.d.ts +18 -3
- package/dist/types/input/{Range.d.ts → RangeSlider.d.ts} +1 -1
- package/dist/types/input/Search.d.ts +5 -1
- package/dist/types/input/Switch.d.ts +7 -4
- package/dist/types/input/Textarea.d.ts +5 -1
- package/dist/types/internal/FieldWrapper.d.ts +1 -1
- package/dist/types/internal/InputWrapper.d.ts +1 -1
- package/dist/types/ranger/index.d.ts +2 -2
- package/dist/types/select/AutoComplete.d.ts +1 -1
- package/dist/types/select/DualList.d.ts +6 -2
- package/dist/types/select/List.d.ts +1 -1
- package/dist/types/select/Select.d.ts +1 -1
- package/dist/types/select/useSelect.d.ts +7 -15
- package/dist/types/types/index.d.ts +28 -7
- package/dist/types/types/schema.d.ts +78 -33
- package/dist/types/utils/eventHandlers.d.ts +1 -1
- package/package.json +15 -12
- package/src/builder/FileField.tsx +53 -27
- package/src/builder/FormField.tsx +52 -32
- package/src/builder/SchemaEditor.tsx +72 -0
- package/src/builder/components/AddSchemaFields.tsx +74 -0
- package/src/builder/components/SchemaArrayForm.tsx +158 -0
- package/src/builder/components/SchemaField.tsx +436 -0
- package/src/form/Controller.tsx +3 -3
- package/src/form/Form.tsx +14 -5
- package/src/hooks/useFormBuilder.tsx +29 -15
- package/src/index.ts +11 -2
- package/src/input/ArrayInput.tsx +130 -54
- package/src/input/AvatarInput.tsx +12 -8
- package/src/input/Checkbox.tsx +6 -5
- package/src/input/ColorInput.tsx +113 -69
- package/src/input/ColorPicker.tsx +2 -36
- package/src/input/DateInput.tsx +250 -0
- package/src/input/Field.tsx +10 -11
- package/src/input/File.tsx +7 -14
- package/src/input/Hidden.tsx +4 -1
- package/src/input/Input.tsx +15 -10
- package/src/input/Number.tsx +10 -10
- package/src/input/Password.tsx +13 -12
- package/src/input/Radio.tsx +2 -2
- package/src/input/RadioGroup.tsx +27 -4
- package/src/input/{Range.tsx → RangeSlider.tsx} +4 -4
- package/src/input/Search.tsx +20 -19
- package/src/input/Slider.tsx +3 -3
- package/src/input/Switch.tsx +43 -7
- package/src/input/Textarea.tsx +19 -5
- package/src/internal/ErrorIcon.tsx +1 -1
- package/src/internal/FieldWrapper.tsx +8 -4
- package/src/internal/InputWrapper.tsx +36 -20
- package/src/select/AutoComplete.tsx +5 -1
- package/src/select/DualList.tsx +8 -0
- package/src/select/List.tsx +41 -8
- package/src/select/Options.tsx +1 -1
- package/src/select/Select.tsx +13 -3
- package/src/select/useSelect.tsx +13 -5
- package/src/types/index.ts +34 -8
- package/src/types/schema.ts +96 -41
- package/src/utils/eventHandlers.ts +9 -3
- package/dist/cjs/input/ArrayInput.module.css +0 -1
- package/dist/cjs/input/ColorPicker.module.css +0 -1
- package/dist/cjs/input/File.module.css +0 -1
- package/dist/cjs/internal/Field.module.css +0 -1
- package/dist/esm/input/ArrayInput.module.css +0 -1
- package/dist/esm/input/ColorPicker.module.css +0 -1
- package/dist/esm/input/File.module.css +0 -1
- package/dist/esm/internal/Field.module.css +0 -1
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
type FC,
|
|
33
33
|
} from "react";
|
|
34
34
|
import { SketchPicker } from "react-color";
|
|
35
|
-
import classes from "./ColorPicker.module.css";
|
|
36
35
|
|
|
37
36
|
export interface ColorProps {
|
|
38
37
|
/**
|
|
@@ -50,7 +49,7 @@ export interface ColorProps {
|
|
|
50
49
|
/**
|
|
51
50
|
* color value
|
|
52
51
|
*/
|
|
53
|
-
value?: string;
|
|
52
|
+
value?: string | null;
|
|
54
53
|
/**
|
|
55
54
|
* change handler
|
|
56
55
|
*/
|
|
@@ -130,17 +129,14 @@ export const ColorPicker: FC<ColorProps> = memo(
|
|
|
130
129
|
return (
|
|
131
130
|
<SketchPicker
|
|
132
131
|
width="16rem"
|
|
133
|
-
className={
|
|
132
|
+
className={"fabric-colorPicker"}
|
|
134
133
|
styles={
|
|
135
134
|
{
|
|
136
135
|
default: {
|
|
137
136
|
hue: {
|
|
138
|
-
borderRadius: "99px",
|
|
139
137
|
boxShadow: "0 0 1px 1px var(--color-shadow)",
|
|
140
138
|
},
|
|
141
139
|
alpha: {
|
|
142
|
-
height: "1rem",
|
|
143
|
-
borderRadius: "99px",
|
|
144
140
|
backgroundColor: "var(--fabric-bg)",
|
|
145
141
|
boxShadow: "0 0 1px 1px var(--color-shadow)",
|
|
146
142
|
},
|
|
@@ -158,36 +154,6 @@ export const ColorPicker: FC<ColorProps> = memo(
|
|
|
158
154
|
boxShadow:
|
|
159
155
|
"0 0 0 1px var(--color-shadow), 0 0 8px var(--fabric-shadow)",
|
|
160
156
|
},
|
|
161
|
-
Alpha: {
|
|
162
|
-
alpha: {
|
|
163
|
-
paddingRight: "calc(1rem - 2px)",
|
|
164
|
-
},
|
|
165
|
-
slider: {
|
|
166
|
-
width: "calc(1rem - 2px)",
|
|
167
|
-
borderRadius: "99px",
|
|
168
|
-
height: "calc(1rem - 2px)",
|
|
169
|
-
transform: "none",
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
Hue: {
|
|
173
|
-
hue: {
|
|
174
|
-
paddingRight: "calc(1rem - 2px)",
|
|
175
|
-
},
|
|
176
|
-
slider: {
|
|
177
|
-
width: "calc(1rem - 2px)",
|
|
178
|
-
borderRadius: "99px",
|
|
179
|
-
height: "calc(1rem - 2px)",
|
|
180
|
-
transform: "none",
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
Saturation: {
|
|
184
|
-
circle: {
|
|
185
|
-
width: "0.5rem",
|
|
186
|
-
borderRadius: "99px",
|
|
187
|
-
height: "0.5rem",
|
|
188
|
-
transform: "translate(-0.25rem, -0.25rem)",
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
157
|
checkboard: {
|
|
192
158
|
white: "transparent",
|
|
193
159
|
black: "red",
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* React Fabric
|
|
3
|
+
* @version: 1.0.0
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* The MIT License (MIT)
|
|
7
|
+
* Copyright (c) 2025 Adarsh Pastakia
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
10
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
11
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
13
|
+
* subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
16
|
+
* portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
19
|
+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
20
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
arrow,
|
|
26
|
+
autoUpdate,
|
|
27
|
+
flip,
|
|
28
|
+
FloatingArrow,
|
|
29
|
+
offset,
|
|
30
|
+
shift,
|
|
31
|
+
useClick,
|
|
32
|
+
useDismiss,
|
|
33
|
+
useFloating,
|
|
34
|
+
useFocus,
|
|
35
|
+
useInteractions,
|
|
36
|
+
} from "@floating-ui/react";
|
|
37
|
+
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
38
|
+
import { type DateLike, DatePanel, DateUtil } from "@react-fabric/date";
|
|
39
|
+
import { mergeRefs } from "@react-fabric/utilities";
|
|
40
|
+
import classNames from "classnames";
|
|
41
|
+
import {
|
|
42
|
+
type ChangeEvent,
|
|
43
|
+
startTransition,
|
|
44
|
+
useCallback,
|
|
45
|
+
useDeferredValue,
|
|
46
|
+
useEffect,
|
|
47
|
+
useMemo,
|
|
48
|
+
useRef,
|
|
49
|
+
useState,
|
|
50
|
+
} from "react";
|
|
51
|
+
import { InputWrapper } from "../internal/InputWrapper";
|
|
52
|
+
import { type InputProps } from "../types";
|
|
53
|
+
import { useHandleEnter } from "../utils";
|
|
54
|
+
|
|
55
|
+
export interface DateProps
|
|
56
|
+
extends InputProps<string>,
|
|
57
|
+
RefProp<HTMLInputElement> {
|
|
58
|
+
type?: "date" | "datetime";
|
|
59
|
+
/**
|
|
60
|
+
* date format
|
|
61
|
+
*/
|
|
62
|
+
format?: string;
|
|
63
|
+
/**
|
|
64
|
+
* minimum value
|
|
65
|
+
*/
|
|
66
|
+
min?: DateLike;
|
|
67
|
+
/**
|
|
68
|
+
* maximum value
|
|
69
|
+
*/
|
|
70
|
+
max?: DateLike;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const DateInput = ({
|
|
74
|
+
ref,
|
|
75
|
+
name,
|
|
76
|
+
value,
|
|
77
|
+
invalid,
|
|
78
|
+
readOnly,
|
|
79
|
+
disabled,
|
|
80
|
+
required,
|
|
81
|
+
placeholder,
|
|
82
|
+
autoFocus,
|
|
83
|
+
error,
|
|
84
|
+
type = "date",
|
|
85
|
+
onBlur,
|
|
86
|
+
onFocus,
|
|
87
|
+
onChange,
|
|
88
|
+
onEnterPressed,
|
|
89
|
+
format = "dd/MM/yyyy",
|
|
90
|
+
min,
|
|
91
|
+
max,
|
|
92
|
+
...rest
|
|
93
|
+
}: DateProps) => {
|
|
94
|
+
const [actualValue, setActualValue] = useState("");
|
|
95
|
+
const [inputValue, setInputValue] = useState("");
|
|
96
|
+
const deferred = useDeferredValue(value);
|
|
97
|
+
|
|
98
|
+
const inputFormat = useMemo(
|
|
99
|
+
() => (type === "datetime" ? "yyyy-MM-dd HH:mm" : "yyyy-MM-dd"),
|
|
100
|
+
[type],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
setActualValue(deferred ?? "");
|
|
105
|
+
setInputValue(deferred ? DateUtil.format(deferred, inputFormat) : "");
|
|
106
|
+
}, [deferred, inputFormat]);
|
|
107
|
+
|
|
108
|
+
const handleEnterPressed = useHandleEnter(onEnterPressed);
|
|
109
|
+
|
|
110
|
+
const handleChange = useCallback(
|
|
111
|
+
(e?: ChangeEvent<HTMLInputElement>) => {
|
|
112
|
+
const value = e?.currentTarget.value;
|
|
113
|
+
if (value) {
|
|
114
|
+
const parsed = DateUtil.parseDate(value);
|
|
115
|
+
setActualValue(parsed?.toISOString?.());
|
|
116
|
+
setInputValue(DateUtil.format(parsed, inputFormat));
|
|
117
|
+
onChange != null &&
|
|
118
|
+
startTransition(() => onChange(parsed?.toISOString?.()));
|
|
119
|
+
} else {
|
|
120
|
+
setActualValue("");
|
|
121
|
+
setInputValue("");
|
|
122
|
+
onChange != null && startTransition(() => onChange(null));
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[onChange, inputFormat],
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const handleDateChange = useCallback(
|
|
129
|
+
(value?: string) => {
|
|
130
|
+
if (value) {
|
|
131
|
+
const parsed = DateUtil.parseDate(value);
|
|
132
|
+
setActualValue(parsed?.toISOString?.());
|
|
133
|
+
setInputValue(DateUtil.format(parsed, inputFormat));
|
|
134
|
+
onChange != null &&
|
|
135
|
+
startTransition(() => onChange(parsed?.toISOString?.()));
|
|
136
|
+
} else {
|
|
137
|
+
setActualValue("");
|
|
138
|
+
setInputValue("");
|
|
139
|
+
onChange != null && startTransition(() => onChange(null));
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
[onChange, inputFormat],
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const arrowRef = useRef(null);
|
|
146
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
147
|
+
const { refs, floatingStyles, context } = useFloating({
|
|
148
|
+
open: isOpen,
|
|
149
|
+
onOpenChange: (open, _, reason) => {
|
|
150
|
+
console.log(reason);
|
|
151
|
+
if (reason === "reference-press") return;
|
|
152
|
+
setIsOpen(open);
|
|
153
|
+
},
|
|
154
|
+
strategy: "fixed",
|
|
155
|
+
placement: "bottom-start",
|
|
156
|
+
whileElementsMounted: autoUpdate,
|
|
157
|
+
middleware: [
|
|
158
|
+
shift({ padding: 8 }),
|
|
159
|
+
flip(),
|
|
160
|
+
offset(9),
|
|
161
|
+
arrow({
|
|
162
|
+
element: arrowRef,
|
|
163
|
+
}),
|
|
164
|
+
],
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const focus = useFocus(context, {
|
|
168
|
+
enabled: !disabled,
|
|
169
|
+
});
|
|
170
|
+
const click = useClick(context, {
|
|
171
|
+
enabled: !disabled,
|
|
172
|
+
toggle: false,
|
|
173
|
+
});
|
|
174
|
+
const dismiss = useDismiss(context, {
|
|
175
|
+
referencePress: true,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
179
|
+
dismiss,
|
|
180
|
+
click,
|
|
181
|
+
focus,
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<InputWrapper
|
|
186
|
+
showClear={!!actualValue && !disabled && !readOnly}
|
|
187
|
+
onClear={handleChange}
|
|
188
|
+
invalid={invalid}
|
|
189
|
+
readOnly={readOnly}
|
|
190
|
+
disabled={disabled}
|
|
191
|
+
required={required}
|
|
192
|
+
error={error}
|
|
193
|
+
{...rest}
|
|
194
|
+
>
|
|
195
|
+
<input
|
|
196
|
+
className={classNames(
|
|
197
|
+
"appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer",
|
|
198
|
+
!value && "empty",
|
|
199
|
+
)}
|
|
200
|
+
aria-invalid={invalid}
|
|
201
|
+
aria-disabled={disabled}
|
|
202
|
+
aria-readonly={readOnly}
|
|
203
|
+
aria-errormessage={error}
|
|
204
|
+
placeholder={placeholder}
|
|
205
|
+
disabled={disabled}
|
|
206
|
+
readOnly={readOnly}
|
|
207
|
+
data-testid={name}
|
|
208
|
+
name={name}
|
|
209
|
+
size={1}
|
|
210
|
+
type={type === "datetime" ? "datetime-local" : "date"}
|
|
211
|
+
autoComplete="off"
|
|
212
|
+
autoFocus={autoFocus}
|
|
213
|
+
value={inputValue}
|
|
214
|
+
ref={mergeRefs(ref, refs.setReference)}
|
|
215
|
+
{...getReferenceProps({
|
|
216
|
+
onBlur,
|
|
217
|
+
onFocus,
|
|
218
|
+
})}
|
|
219
|
+
onChange={handleChange}
|
|
220
|
+
onKeyDown={handleEnterPressed}
|
|
221
|
+
/>
|
|
222
|
+
{isOpen && (
|
|
223
|
+
<div
|
|
224
|
+
ref={refs.setFloating}
|
|
225
|
+
style={{
|
|
226
|
+
zIndex: "var(--z-popover)",
|
|
227
|
+
...floatingStyles,
|
|
228
|
+
}}
|
|
229
|
+
className="shadow-lg bg-base ring-1 ring-tint-100"
|
|
230
|
+
data-ref="dropdownBody"
|
|
231
|
+
{...getFloatingProps()}
|
|
232
|
+
>
|
|
233
|
+
<DatePanel
|
|
234
|
+
withTime={type === "datetime"}
|
|
235
|
+
value={actualValue}
|
|
236
|
+
max={max}
|
|
237
|
+
min={min}
|
|
238
|
+
onChange={handleDateChange}
|
|
239
|
+
/>
|
|
240
|
+
<FloatingArrow
|
|
241
|
+
ref={arrowRef}
|
|
242
|
+
context={context}
|
|
243
|
+
strokeWidth={0.5}
|
|
244
|
+
className="fill-base stroke-muted"
|
|
245
|
+
/>
|
|
246
|
+
</div>
|
|
247
|
+
)}
|
|
248
|
+
</InputWrapper>
|
|
249
|
+
);
|
|
250
|
+
};
|
package/src/input/Field.tsx
CHANGED
|
@@ -21,13 +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 { cloneChildren } from "@react-fabric/core";
|
|
24
25
|
import {
|
|
25
26
|
type ChildrenProp,
|
|
26
27
|
type CssProp,
|
|
27
28
|
} from "@react-fabric/core/dist/types/types";
|
|
28
29
|
import classNames from "classnames";
|
|
29
|
-
import {
|
|
30
|
-
import classes from "../internal/Field.module.css";
|
|
30
|
+
import { cloneElement } from "react";
|
|
31
31
|
import { FieldWrapper } from "../internal/FieldWrapper";
|
|
32
32
|
|
|
33
33
|
export interface FieldProps extends ChildrenProp, CssProp {
|
|
@@ -83,20 +83,19 @@ export const Field = ({
|
|
|
83
83
|
<FieldWrapper {...rest}>
|
|
84
84
|
<div
|
|
85
85
|
className={classNames(
|
|
86
|
-
|
|
86
|
+
"fabric-fieldGroup",
|
|
87
87
|
!plain && !noOutline && "outline",
|
|
88
88
|
!plain && "bg-base",
|
|
89
|
+
plain && "flex-wrap",
|
|
89
90
|
"flex-1 rounded",
|
|
90
|
-
!vertical && "flex
|
|
91
|
+
!vertical && "flex",
|
|
91
92
|
)}
|
|
93
|
+
data-vertical={!!vertical}
|
|
92
94
|
>
|
|
93
|
-
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
cloneElement(child as AnyObject, {
|
|
98
|
-
"data-inner": true,
|
|
99
|
-
}),
|
|
95
|
+
{cloneChildren(children, (child: AnyObject) =>
|
|
96
|
+
cloneElement(child, {
|
|
97
|
+
"data-inner": true,
|
|
98
|
+
}),
|
|
100
99
|
)}
|
|
101
100
|
</div>
|
|
102
101
|
</FieldWrapper>
|
package/src/input/File.tsx
CHANGED
|
@@ -36,15 +36,13 @@ import {
|
|
|
36
36
|
useCallback,
|
|
37
37
|
useDeferredValue,
|
|
38
38
|
useEffect,
|
|
39
|
-
useMemo,
|
|
40
39
|
useRef,
|
|
41
40
|
useState,
|
|
42
41
|
type ChangeEvent,
|
|
43
42
|
} from "react";
|
|
44
43
|
import { InputWrapper } from "../internal/InputWrapper";
|
|
45
44
|
import { type InputProps } from "../types";
|
|
46
|
-
import {
|
|
47
|
-
import classes from "./File.module.css";
|
|
45
|
+
import { useHandleEnter } from "../utils";
|
|
48
46
|
|
|
49
47
|
export interface FileInputProps
|
|
50
48
|
extends InputProps<AnyObject>,
|
|
@@ -101,10 +99,7 @@ export const FileInput = ({
|
|
|
101
99
|
const [actualValue, setActualValue] = useState<File | File[] | null>();
|
|
102
100
|
const deferred = useDeferredValue(value);
|
|
103
101
|
|
|
104
|
-
const handleEnterPressed =
|
|
105
|
-
() => handleEnter(onEnterPressed),
|
|
106
|
-
[onEnterPressed],
|
|
107
|
-
);
|
|
102
|
+
const handleEnterPressed = useHandleEnter(onEnterPressed);
|
|
108
103
|
|
|
109
104
|
useEffect(() => {
|
|
110
105
|
setActualValue(deferred);
|
|
@@ -134,7 +129,7 @@ export const FileInput = ({
|
|
|
134
129
|
}
|
|
135
130
|
} else {
|
|
136
131
|
setActualValue(e?.target.files?.item(0));
|
|
137
|
-
onChange?.(e?.target.files?.item(0) ??
|
|
132
|
+
onChange?.(e?.target.files?.item(0) ?? null);
|
|
138
133
|
if (!e && inputRef.current) inputRef.current.value = "";
|
|
139
134
|
}
|
|
140
135
|
},
|
|
@@ -152,7 +147,7 @@ export const FileInput = ({
|
|
|
152
147
|
|
|
153
148
|
return (
|
|
154
149
|
<InputWrapper
|
|
155
|
-
showClear={!isEmpty(actualValue)}
|
|
150
|
+
showClear={!isEmpty(actualValue) && !disabled && !readOnly}
|
|
156
151
|
onClear={handleChange}
|
|
157
152
|
invalid={invalid}
|
|
158
153
|
readOnly={readOnly}
|
|
@@ -194,11 +189,9 @@ export const FileInput = ({
|
|
|
194
189
|
>
|
|
195
190
|
<input
|
|
196
191
|
className={classNames(
|
|
197
|
-
"appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0",
|
|
198
|
-
|
|
199
|
-
isArray(actualValue) &&
|
|
200
|
-
actualValue?.length &&
|
|
201
|
-
"text-[var(--fabric-bg)]",
|
|
192
|
+
"appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer",
|
|
193
|
+
"fabric-fileInput",
|
|
194
|
+
isArray(actualValue) && actualValue?.length && "text-(--fabric-bg)",
|
|
202
195
|
)}
|
|
203
196
|
aria-invalid={invalid}
|
|
204
197
|
aria-disabled={disabled}
|
package/src/input/Hidden.tsx
CHANGED
package/src/input/Input.tsx
CHANGED
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
25
|
+
import classNames from "classnames";
|
|
25
26
|
import {
|
|
26
27
|
useCallback,
|
|
27
28
|
useDeferredValue,
|
|
28
29
|
useEffect,
|
|
29
|
-
useMemo,
|
|
30
30
|
useState,
|
|
31
31
|
type ChangeEvent,
|
|
32
32
|
} from "react";
|
|
33
33
|
import { InputWrapper } from "../internal/InputWrapper";
|
|
34
34
|
import { type InputProps } from "../types";
|
|
35
|
-
import {
|
|
35
|
+
import { useHandleEnter } from "../utils";
|
|
36
36
|
|
|
37
37
|
export interface TextInputProps extends InputProps, RefProp<HTMLInputElement> {
|
|
38
38
|
/**
|
|
@@ -52,7 +52,10 @@ export const Input = ({
|
|
|
52
52
|
placeholder,
|
|
53
53
|
autoFocus,
|
|
54
54
|
error,
|
|
55
|
+
monospace,
|
|
55
56
|
type = "text",
|
|
57
|
+
onBlur,
|
|
58
|
+
onFocus,
|
|
56
59
|
onChange,
|
|
57
60
|
onEnterPressed,
|
|
58
61
|
...rest
|
|
@@ -60,10 +63,7 @@ export const Input = ({
|
|
|
60
63
|
const [actualValue, setActualValue] = useState("");
|
|
61
64
|
const deferred = useDeferredValue(value);
|
|
62
65
|
|
|
63
|
-
const handleEnterPressed =
|
|
64
|
-
() => handleEnter(onEnterPressed),
|
|
65
|
-
[onEnterPressed],
|
|
66
|
-
);
|
|
66
|
+
const handleEnterPressed = useHandleEnter(onEnterPressed);
|
|
67
67
|
|
|
68
68
|
useEffect(() => {
|
|
69
69
|
setActualValue(deferred ?? "");
|
|
@@ -73,14 +73,14 @@ export const Input = ({
|
|
|
73
73
|
(e?: ChangeEvent<HTMLInputElement>) => {
|
|
74
74
|
const value = e?.target.value;
|
|
75
75
|
setActualValue(value ?? "");
|
|
76
|
-
onChange?.(value ??
|
|
76
|
+
onChange?.(value ?? null);
|
|
77
77
|
},
|
|
78
78
|
[onchange],
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
return (
|
|
82
82
|
<InputWrapper
|
|
83
|
-
showClear={!!actualValue}
|
|
83
|
+
showClear={!!actualValue && !disabled && !readOnly}
|
|
84
84
|
onClear={handleChange}
|
|
85
85
|
invalid={invalid}
|
|
86
86
|
readOnly={readOnly}
|
|
@@ -90,7 +90,10 @@ export const Input = ({
|
|
|
90
90
|
{...rest}
|
|
91
91
|
>
|
|
92
92
|
<input
|
|
93
|
-
className=
|
|
93
|
+
className={classNames(
|
|
94
|
+
"appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer",
|
|
95
|
+
monospace && "font-mono text-sm",
|
|
96
|
+
)}
|
|
94
97
|
aria-invalid={invalid}
|
|
95
98
|
aria-disabled={disabled}
|
|
96
99
|
aria-readonly={readOnly}
|
|
@@ -104,8 +107,10 @@ export const Input = ({
|
|
|
104
107
|
type={type}
|
|
105
108
|
ref={ref}
|
|
106
109
|
autoComplete="off"
|
|
107
|
-
{
|
|
110
|
+
autoFocus={autoFocus}
|
|
108
111
|
value={actualValue}
|
|
112
|
+
onBlur={onBlur}
|
|
113
|
+
onFocus={onFocus}
|
|
109
114
|
onChange={handleChange}
|
|
110
115
|
onKeyDown={handleEnterPressed}
|
|
111
116
|
/>
|
package/src/input/Number.tsx
CHANGED
|
@@ -26,13 +26,12 @@ import {
|
|
|
26
26
|
useCallback,
|
|
27
27
|
useDeferredValue,
|
|
28
28
|
useEffect,
|
|
29
|
-
useMemo,
|
|
30
29
|
useState,
|
|
31
30
|
type ChangeEvent,
|
|
32
31
|
} from "react";
|
|
33
32
|
import { InputWrapper } from "../internal/InputWrapper";
|
|
34
33
|
import { type InputProps } from "../types";
|
|
35
|
-
import {
|
|
34
|
+
import { useHandleEnter } from "../utils";
|
|
36
35
|
|
|
37
36
|
export interface NumberProps
|
|
38
37
|
extends InputProps<number>,
|
|
@@ -64,6 +63,8 @@ export const Number = ({
|
|
|
64
63
|
min,
|
|
65
64
|
max,
|
|
66
65
|
step,
|
|
66
|
+
onBlur,
|
|
67
|
+
onFocus,
|
|
67
68
|
onChange,
|
|
68
69
|
onEnterPressed,
|
|
69
70
|
...rest
|
|
@@ -71,10 +72,7 @@ export const Number = ({
|
|
|
71
72
|
const [actualValue, setActualValue] = useState<"" | number>("");
|
|
72
73
|
const deferred = useDeferredValue(value);
|
|
73
74
|
|
|
74
|
-
const handleEnterPressed =
|
|
75
|
-
() => handleEnter(onEnterPressed),
|
|
76
|
-
[onEnterPressed],
|
|
77
|
-
);
|
|
75
|
+
const handleEnterPressed = useHandleEnter(onEnterPressed);
|
|
78
76
|
|
|
79
77
|
useEffect(() => {
|
|
80
78
|
setActualValue(deferred ?? "");
|
|
@@ -84,14 +82,14 @@ export const Number = ({
|
|
|
84
82
|
(e?: ChangeEvent<HTMLInputElement>) => {
|
|
85
83
|
const number = e?.target.valueAsNumber;
|
|
86
84
|
setActualValue(number ?? "");
|
|
87
|
-
onChange?.(number ??
|
|
85
|
+
onChange?.(number ?? null);
|
|
88
86
|
},
|
|
89
87
|
[onChange],
|
|
90
88
|
);
|
|
91
89
|
|
|
92
90
|
return (
|
|
93
91
|
<InputWrapper
|
|
94
|
-
showClear={!!actualValue}
|
|
92
|
+
showClear={!!actualValue && !disabled && !readOnly}
|
|
95
93
|
onClear={handleChange}
|
|
96
94
|
invalid={invalid}
|
|
97
95
|
readOnly={readOnly}
|
|
@@ -100,7 +98,7 @@ export const Number = ({
|
|
|
100
98
|
{...rest}
|
|
101
99
|
>
|
|
102
100
|
<input
|
|
103
|
-
className="appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0"
|
|
101
|
+
className="appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer"
|
|
104
102
|
aria-invalid={invalid}
|
|
105
103
|
aria-disabled={disabled}
|
|
106
104
|
aria-readonly={readOnly}
|
|
@@ -116,8 +114,10 @@ export const Number = ({
|
|
|
116
114
|
step={step}
|
|
117
115
|
ref={ref}
|
|
118
116
|
autoComplete="off"
|
|
119
|
-
{
|
|
117
|
+
autoFocus={autoFocus}
|
|
120
118
|
value={actualValue}
|
|
119
|
+
onBlur={onBlur}
|
|
120
|
+
onFocus={onFocus}
|
|
121
121
|
onChange={handleChange}
|
|
122
122
|
onKeyDown={handleEnterPressed}
|
|
123
123
|
/>
|
package/src/input/Password.tsx
CHANGED
|
@@ -28,14 +28,13 @@ import {
|
|
|
28
28
|
useCallback,
|
|
29
29
|
useDeferredValue,
|
|
30
30
|
useEffect,
|
|
31
|
-
useMemo,
|
|
32
31
|
useState,
|
|
33
32
|
type ChangeEvent,
|
|
34
33
|
} from "react";
|
|
35
34
|
import { useTranslation } from "react-i18next";
|
|
36
35
|
import { InputWrapper } from "../internal/InputWrapper";
|
|
37
36
|
import { type InputProps } from "../types";
|
|
38
|
-
import {
|
|
37
|
+
import { useHandleEnter } from "../utils";
|
|
39
38
|
|
|
40
39
|
export interface PasswordProps extends InputProps, RefProp<HTMLInputElement> {
|
|
41
40
|
/**
|
|
@@ -60,6 +59,8 @@ export const Password = ({
|
|
|
60
59
|
placeholder,
|
|
61
60
|
autoFocus,
|
|
62
61
|
showToggle,
|
|
62
|
+
onBlur,
|
|
63
|
+
onFocus,
|
|
63
64
|
onChange,
|
|
64
65
|
onEnterPressed,
|
|
65
66
|
...rest
|
|
@@ -70,10 +71,7 @@ export const Password = ({
|
|
|
70
71
|
const [actualValue, setActualValue] = useState("");
|
|
71
72
|
const deferred = useDeferredValue(value);
|
|
72
73
|
|
|
73
|
-
const handleEnterPressed =
|
|
74
|
-
() => handleEnter(onEnterPressed),
|
|
75
|
-
[onEnterPressed],
|
|
76
|
-
);
|
|
74
|
+
const handleEnterPressed = useHandleEnter(onEnterPressed);
|
|
77
75
|
|
|
78
76
|
useEffect(() => {
|
|
79
77
|
setActualValue(deferred ?? "");
|
|
@@ -83,22 +81,23 @@ export const Password = ({
|
|
|
83
81
|
(e?: ChangeEvent<HTMLInputElement>) => {
|
|
84
82
|
const value = e?.target.value;
|
|
85
83
|
setActualValue(value ?? "");
|
|
86
|
-
onChange?.(value ??
|
|
84
|
+
onChange?.(value ?? null);
|
|
87
85
|
},
|
|
88
86
|
[onChange],
|
|
89
87
|
);
|
|
90
88
|
|
|
91
89
|
return (
|
|
92
90
|
<InputWrapper
|
|
93
|
-
showClear={!!actualValue}
|
|
91
|
+
showClear={!!actualValue && !disabled && !readOnly}
|
|
94
92
|
onClear={handleChange}
|
|
95
93
|
invalid={invalid}
|
|
96
94
|
readOnly={readOnly}
|
|
97
95
|
disabled={disabled}
|
|
98
96
|
required={required}
|
|
99
97
|
{...rest}
|
|
100
|
-
|
|
101
|
-
showToggle &&
|
|
98
|
+
actionButton={
|
|
99
|
+
showToggle &&
|
|
100
|
+
actualValue && (
|
|
102
101
|
<Tooltip
|
|
103
102
|
color="warning"
|
|
104
103
|
content={t(show ? "password.hide" : "password.show")}
|
|
@@ -116,7 +115,7 @@ export const Password = ({
|
|
|
116
115
|
}
|
|
117
116
|
>
|
|
118
117
|
<input
|
|
119
|
-
className="appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0"
|
|
118
|
+
className="appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer"
|
|
120
119
|
aria-invalid={invalid}
|
|
121
120
|
aria-disabled={disabled}
|
|
122
121
|
aria-readonly={readOnly}
|
|
@@ -129,8 +128,10 @@ export const Password = ({
|
|
|
129
128
|
type={show ? "text" : "password"}
|
|
130
129
|
ref={ref}
|
|
131
130
|
autoComplete="off"
|
|
132
|
-
{
|
|
131
|
+
autoFocus={autoFocus}
|
|
133
132
|
value={actualValue}
|
|
133
|
+
onBlur={onBlur}
|
|
134
|
+
onFocus={onFocus}
|
|
134
135
|
onChange={handleChange}
|
|
135
136
|
onKeyDown={handleEnterPressed}
|
|
136
137
|
/>
|
package/src/input/Radio.tsx
CHANGED
|
@@ -126,7 +126,7 @@ export const Radio = ({
|
|
|
126
126
|
<Icon
|
|
127
127
|
className={classNames(
|
|
128
128
|
"p-0.5 hidden peer-checked:inline-block",
|
|
129
|
-
icon && !iconChecked && "bg-primary-500 text-white",
|
|
129
|
+
icon && !iconChecked && "bg-primary-500 text-white!",
|
|
130
130
|
)}
|
|
131
131
|
color={invalid ? "danger" : "primary"}
|
|
132
132
|
size="1.25em"
|
|
@@ -139,7 +139,7 @@ export const Radio = ({
|
|
|
139
139
|
icon={iconOff}
|
|
140
140
|
/>
|
|
141
141
|
{label && (
|
|
142
|
-
<span className="flex-initial leading-
|
|
142
|
+
<span className="flex-initial leading-tight truncate">{label}</span>
|
|
143
143
|
)}
|
|
144
144
|
</label>
|
|
145
145
|
);
|