@react-fabric/form 1.0.0-beta.45 → 1.0.0-beta.47

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 (56) hide show
  1. package/css/_field.css +38 -14
  2. package/dist/cjs/form/Form.js +1 -1
  3. package/dist/cjs/index.js +2 -0
  4. package/dist/cjs/input/ArrayInput.js +27 -10
  5. package/dist/cjs/input/ColorInput.js +23 -31
  6. package/dist/cjs/input/DateInput.js +1 -1
  7. package/dist/cjs/input/Field.js +1 -0
  8. package/dist/cjs/input/File.js +1 -1
  9. package/dist/cjs/input/Input.js +5 -3
  10. package/dist/cjs/input/Number.js +1 -1
  11. package/dist/cjs/input/Password.js +1 -1
  12. package/dist/cjs/input/RangeSlider.js +2 -2
  13. package/dist/cjs/input/Search.js +1 -1
  14. package/dist/cjs/input/Slider.js +2 -2
  15. package/dist/cjs/input/Textarea.js +1 -1
  16. package/dist/cjs/internal/InputWrapper.js +2 -2
  17. package/dist/cjs/select/useSelect.js +1 -1
  18. package/dist/esm/form/Form.js +1 -1
  19. package/dist/esm/index.js +1 -0
  20. package/dist/esm/input/ArrayInput.js +24 -7
  21. package/dist/esm/input/ColorInput.js +23 -31
  22. package/dist/esm/input/DateInput.js +1 -1
  23. package/dist/esm/input/Field.js +1 -0
  24. package/dist/esm/input/File.js +1 -1
  25. package/dist/esm/input/Input.js +5 -3
  26. package/dist/esm/input/Number.js +1 -1
  27. package/dist/esm/input/Password.js +1 -1
  28. package/dist/esm/input/RangeSlider.js +2 -2
  29. package/dist/esm/input/Search.js +1 -1
  30. package/dist/esm/input/Slider.js +2 -2
  31. package/dist/esm/input/Textarea.js +1 -1
  32. package/dist/esm/internal/InputWrapper.js +2 -2
  33. package/dist/esm/select/useSelect.js +1 -1
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/input/ArrayInput.d.ts +20 -4
  36. package/dist/types/input/ColorInput.d.ts +1 -1
  37. package/dist/types/input/Input.d.ts +1 -1
  38. package/dist/types/types/index.d.ts +1 -0
  39. package/package.json +5 -5
  40. package/src/form/Form.tsx +1 -1
  41. package/src/index.ts +1 -0
  42. package/src/input/ArrayInput.tsx +50 -12
  43. package/src/input/ColorInput.tsx +13 -42
  44. package/src/input/DateInput.tsx +1 -1
  45. package/src/input/Field.tsx +1 -0
  46. package/src/input/File.tsx +1 -1
  47. package/src/input/Input.tsx +7 -2
  48. package/src/input/Number.tsx +1 -1
  49. package/src/input/Password.tsx +1 -1
  50. package/src/input/RangeSlider.tsx +2 -2
  51. package/src/input/Search.tsx +1 -1
  52. package/src/input/Slider.tsx +2 -2
  53. package/src/input/Textarea.tsx +1 -1
  54. package/src/internal/InputWrapper.tsx +6 -3
  55. package/src/select/useSelect.tsx +1 -0
  56. package/src/types/index.ts +2 -0
@@ -5,33 +5,30 @@ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
5
5
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
6
6
  import { useFloating, autoUpdate, shift, flip, offset, arrow, useClick, useDismiss, useInteractions, FloatingArrow } from '@floating-ui/react';
7
7
  import { Icon, CoreIcons } from '@react-fabric/core';
8
- import { isString } from '@react-fabric/utilities';
9
- import classNames from 'classnames';
10
8
  import { useState, useDeferredValue, useEffect, useCallback, startTransition, useRef } from 'react';
9
+ import { InputWrapper } from '../internal/InputWrapper.js';
11
10
  import { ColorPicker } from './ColorPicker.js';
12
11
  import { jsxs, jsx } from 'react/jsx-runtime';
13
12
 
14
- var _excluded = ["ref", "required", "disabled", "allowClear", "invalid", "error", "value", "showPicker", "defaultColor", "decorateEnd", "decorateStart", "onBlur", "onFocus", "onChange", "noOutline"];
13
+ var _excluded = ["ref", "required", "disabled", "readOnly", "invalid", "error", "value", "showPicker", "defaultColor", "onBlur", "onFocus", "onChange", "noOutline"];
15
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
16
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
16
  var ColorInput = function ColorInput(_ref) {
18
17
  _ref.ref;
19
- _ref.required;
20
- var disabled = _ref.disabled,
21
- allowClear = _ref.allowClear;
22
- _ref.invalid;
23
- _ref.error;
24
- var value = _ref.value,
18
+ var required = _ref.required,
19
+ disabled = _ref.disabled,
20
+ readOnly = _ref.readOnly,
21
+ invalid = _ref.invalid,
22
+ error = _ref.error,
23
+ value = _ref.value,
25
24
  showPicker = _ref.showPicker,
26
25
  _ref$defaultColor = _ref.defaultColor,
27
26
  defaultColor = _ref$defaultColor === void 0 ? "" : _ref$defaultColor,
28
- decorateEnd = _ref.decorateEnd,
29
- decorateStart = _ref.decorateStart,
30
27
  onBlur = _ref.onBlur,
31
28
  onFocus = _ref.onFocus,
32
- onChange = _ref.onChange,
33
- noOutline = _ref.noOutline,
34
- rest = _objectWithoutProperties(_ref, _excluded);
29
+ onChange = _ref.onChange;
30
+ _ref.noOutline;
31
+ var rest = _objectWithoutProperties(_ref, _excluded);
35
32
  var _useState = useState(""),
36
33
  _useState2 = _slicedToArray(_useState, 2),
37
34
  actualValue = _useState2[0],
@@ -70,7 +67,7 @@ var ColorInput = function ColorInput(_ref) {
70
67
  floatingStyles = _useFloating.floatingStyles,
71
68
  context = _useFloating.context;
72
69
  var click = useClick(context, {
73
- enabled: !disabled
70
+ enabled: !disabled && !readOnly
74
71
  });
75
72
  var dismiss = useDismiss(context, {
76
73
  referencePress: true
@@ -78,12 +75,16 @@ var ColorInput = function ColorInput(_ref) {
78
75
  var _useInteractions = useInteractions([dismiss, click]),
79
76
  getReferenceProps = _useInteractions.getReferenceProps,
80
77
  getFloatingProps = _useInteractions.getFloatingProps;
81
- return /*#__PURE__*/jsxs("div", {
82
- className: classNames("flex-content min-h-[1.5em] min-w-[3.5em] self-stretch flex items-center outline-tint-200 rounded", !disabled && "bg-base", !noOutline && "bg-(--fabric-input) outline overflow-hidden"),
83
- children: [decorateStart && /*#__PURE__*/jsx("div", {
84
- className: classNames("text-muted leading-none flex-content", isString(decorateStart) && "px-2"),
85
- children: decorateStart
86
- }), /*#__PURE__*/jsx("button", _objectSpread(_objectSpread({
78
+ return /*#__PURE__*/jsxs(InputWrapper, _objectSpread(_objectSpread({
79
+ showClear: actualValue !== defaultColor && !disabled && !readOnly,
80
+ onClear: handleChange,
81
+ invalid: invalid,
82
+ readOnly: readOnly,
83
+ disabled: disabled,
84
+ required: required,
85
+ error: error
86
+ }, rest), {}, {
87
+ children: [/*#__PURE__*/jsx("button", _objectSpread(_objectSpread({
87
88
  "data-ref": "button",
88
89
  className: "flex-1 flex items-center",
89
90
  ref: refs.setReference
@@ -131,17 +132,8 @@ var ColorInput = function ColorInput(_ref) {
131
132
  return handleChange(resp.sRGBHex);
132
133
  });
133
134
  }
134
- }), decorateEnd && /*#__PURE__*/jsx("div", {
135
- className: classNames("text-muted leading-none flex-content", isString(decorateEnd) && "px-2"),
136
- children: decorateEnd
137
- }), !disabled && allowClear && actualValue !== defaultColor && /*#__PURE__*/jsx(Icon, {
138
- icon: CoreIcons.close,
139
- onClick: function onClick() {
140
- return handleChange();
141
- },
142
- className: classNames("text-tint-500 hover:text-tint-700 p-[0.25em] flex-content")
143
135
  })]
144
- });
136
+ }));
145
137
  };
146
138
 
147
139
  export { ColorInput };
@@ -130,7 +130,7 @@ var DateInput = function DateInput(_ref) {
130
130
  getReferenceProps = _useInteractions.getReferenceProps,
131
131
  getFloatingProps = _useInteractions.getFloatingProps;
132
132
  return /*#__PURE__*/jsxs(InputWrapper, _objectSpread(_objectSpread({
133
- showClear: !!actualValue,
133
+ showClear: !!actualValue && !disabled && !readOnly,
134
134
  onClear: handleChange,
135
135
  invalid: invalid,
136
136
  readOnly: readOnly,
@@ -20,6 +20,7 @@ var Field = function Field(_ref) {
20
20
  return /*#__PURE__*/jsx(FieldWrapper, _objectSpread(_objectSpread({}, rest), {}, {
21
21
  children: /*#__PURE__*/jsx("div", {
22
22
  className: classNames("fabric-fieldGroup", !plain && !noOutline && "outline", !plain && "bg-base", plain && "flex-wrap", "flex-1 rounded", !vertical && "flex"),
23
+ "data-vertical": !!vertical,
23
24
  children: cloneChildren(children, function (child) {
24
25
  return /*#__PURE__*/cloneElement(child, {
25
26
  "data-inner": true
@@ -99,7 +99,7 @@ var FileInput = function FileInput(_ref) {
99
99
  onChange === null || onChange === void 0 || onChange(listRef.current);
100
100
  }, [onChange]);
101
101
  return /*#__PURE__*/jsx(InputWrapper, _objectSpread(_objectSpread({
102
- showClear: !isEmpty(actualValue),
102
+ showClear: !isEmpty(actualValue) && !disabled && !readOnly,
103
103
  onClear: handleChange,
104
104
  invalid: invalid,
105
105
  readOnly: readOnly,
@@ -7,9 +7,10 @@ import { useState, useDeferredValue, useMemo, useEffect, useCallback } from 'rea
7
7
  import { InputWrapper } from '../internal/InputWrapper.js';
8
8
  import { handleEnter } from '../utils/eventHandlers.js';
9
9
  import '@react-fabric/utilities';
10
+ import classNames from 'classnames';
10
11
  import { jsx } from 'react/jsx-runtime';
11
12
 
12
- var _excluded = ["ref", "name", "value", "invalid", "readOnly", "disabled", "required", "placeholder", "autoFocus", "error", "type", "onBlur", "onFocus", "onChange", "onEnterPressed"];
13
+ var _excluded = ["ref", "name", "value", "invalid", "readOnly", "disabled", "required", "placeholder", "autoFocus", "error", "monospace", "type", "onBlur", "onFocus", "onChange", "onEnterPressed"];
13
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
16
  var Input = function Input(_ref) {
@@ -23,6 +24,7 @@ var Input = function Input(_ref) {
23
24
  placeholder = _ref.placeholder,
24
25
  autoFocus = _ref.autoFocus,
25
26
  error = _ref.error,
27
+ monospace = _ref.monospace,
26
28
  _ref$type = _ref.type,
27
29
  type = _ref$type === void 0 ? "text" : _ref$type,
28
30
  onBlur = _ref.onBlur,
@@ -47,7 +49,7 @@ var Input = function Input(_ref) {
47
49
  onChange === null || onChange === void 0 || onChange(value !== null && value !== void 0 ? value : null);
48
50
  }, [onchange]);
49
51
  return /*#__PURE__*/jsx(InputWrapper, _objectSpread(_objectSpread({
50
- showClear: !!actualValue,
52
+ showClear: !!actualValue && !disabled && !readOnly,
51
53
  onClear: handleChange,
52
54
  invalid: invalid,
53
55
  readOnly: readOnly,
@@ -56,7 +58,7 @@ var Input = function Input(_ref) {
56
58
  error: error
57
59
  }, rest), {}, {
58
60
  children: /*#__PURE__*/jsx("input", {
59
- className: "appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer",
61
+ className: classNames("appearance-none bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 peer", monospace && "font-mono text-sm"),
60
62
  "aria-invalid": invalid,
61
63
  "aria-disabled": disabled,
62
64
  "aria-readonly": readOnly,
@@ -47,7 +47,7 @@ var Number = function Number(_ref) {
47
47
  onChange === null || onChange === void 0 || onChange(number !== null && number !== void 0 ? number : null);
48
48
  }, [onChange]);
49
49
  return /*#__PURE__*/jsx(InputWrapper, _objectSpread(_objectSpread({
50
- showClear: !!actualValue,
50
+ showClear: !!actualValue && !disabled && !readOnly,
51
51
  onClear: handleChange,
52
52
  invalid: invalid,
53
53
  readOnly: readOnly,
@@ -55,7 +55,7 @@ var Password = function Password(_ref) {
55
55
  onChange === null || onChange === void 0 || onChange(value !== null && value !== void 0 ? value : null);
56
56
  }, [onChange]);
57
57
  return /*#__PURE__*/jsxs(InputWrapper, _objectSpread(_objectSpread({
58
- showClear: !!actualValue,
58
+ showClear: !!actualValue && !disabled && !readOnly,
59
59
  onClear: handleChange,
60
60
  invalid: invalid,
61
61
  readOnly: readOnly,
@@ -114,14 +114,14 @@ var RangeSlider = function RangeSlider(_ref) {
114
114
  isReadOnly: readOnly,
115
115
  canClear: !!actualValue,
116
116
  children: /*#__PURE__*/jsxs("div", {
117
- className: classNames("flex-auto order-3 flex items-center select-none z-0", vertical && "flex-col w-8", invalid ? "text-danger-500" : "text-primary-600"),
117
+ className: classNames("flex-1 order-3 flex items-center select-none z-0", vertical && "flex-col w-8", invalid ? "text-danger-500" : "text-primary-600"),
118
118
  "data-vertical": !!vertical,
119
119
  style: invalid ? undefined : {
120
120
  color: color
121
121
  },
122
122
  children: [showLabels && (vertical ? maxDisplay : minDisplay), /*#__PURE__*/jsxs("div", {
123
123
  ref: rangerInstance.trackElRef,
124
- className: classNames("flex-auto relative flex items-center", vertical ? "my-2 w-8" : "mx-2 h-8"),
124
+ className: classNames("flex-1 relative flex items-center", vertical ? "my-2 w-8" : "mx-2 h-8"),
125
125
  style: {
126
126
  height: vertical ? height : undefined
127
127
  },
@@ -62,7 +62,7 @@ var Search = function Search(_ref) {
62
62
  }
63
63
  }, [onChange, searchOnChange, handleSearch]);
64
64
  return /*#__PURE__*/jsx(InputWrapper, _objectSpread(_objectSpread({
65
- showClear: !!actualValue,
65
+ showClear: !!actualValue && !disabled && !readOnly,
66
66
  onClear: handleChange,
67
67
  allowClear: allowClear,
68
68
  invalid: invalid,
@@ -116,14 +116,14 @@ var Slider = function Slider(_ref) {
116
116
  isReadOnly: readOnly,
117
117
  canClear: !!actualValue,
118
118
  children: /*#__PURE__*/jsxs("div", {
119
- className: classNames("flex-auto order-3 flex items-center select-none relative z-0", vertical && "flex-col w-8", invalid ? "text-danger-500" : "text-primary-600"),
119
+ className: classNames("flex-1 order-3 flex items-center select-none relative z-0", vertical && "flex-col w-8", invalid ? "text-danger-500" : "text-primary-600"),
120
120
  "data-vertical": !!vertical,
121
121
  style: invalid ? undefined : {
122
122
  color: color
123
123
  },
124
124
  children: [showLabels && (vertical ? maxDisplay : minDisplay), /*#__PURE__*/jsxs("div", {
125
125
  ref: rangerInstance.trackElRef,
126
- className: classNames("flex-auto relative flex items-center", vertical ? "my-2 w-8" : "mx-2 h-8"),
126
+ className: classNames("flex-1 relative flex items-center", vertical ? "my-2 w-8" : "mx-2 h-8"),
127
127
  style: {
128
128
  height: vertical ? height : undefined
129
129
  },
@@ -61,7 +61,7 @@ var Textarea = function Textarea(_ref) {
61
61
  }
62
62
  }, [actualValue, variableRows, rows, maxRows]);
63
63
  return /*#__PURE__*/jsx(InputWrapper, _objectSpread(_objectSpread({
64
- showClear: !!actualValue,
64
+ showClear: !!actualValue && !disabled && !readOnly,
65
65
  onClear: handleChange,
66
66
  invalid: invalid,
67
67
  readOnly: readOnly,
@@ -69,7 +69,7 @@ var InputWrapper = function InputWrapper(_ref) {
69
69
  var el = /*#__PURE__*/jsxs("div", {
70
70
  role: "none",
71
71
  ref: wrapperRef,
72
- className: classNames("fabric-inputWrapper", invalid && "fabric-invalidWrapper", !noOutline && !noBorder && "bg-(--fabric-input) outline -outline-offset-1 overflow-hidden", "flex flex-nowrap items-center flex-1", textarea ? "rounded-capped group" : "rounded", isExpanded ? "fixed inset-4 z-[99]" : floatingExpand ? "absolute inset-x-0" : "relative", !noOutline && "after:absolute after:bottom-0 after:h-[2px] after:bg-primary-500 after:mx-auto"),
72
+ className: classNames("fabric-inputWrapper", invalid && "fabric-invalidWrapper", !noOutline && !noBorder && "bg-(--fabric-input) outline overflow-hidden", "flex flex-nowrap items-center flex-1", textarea ? "rounded-capped group" : "rounded", isExpanded ? "fixed inset-4 z-[99]" : floatingExpand ? "absolute inset-x-0" : "relative", !noOutline && "after:absolute after:bottom-0 after:h-px after:bg-primary-500 after:mx-auto"),
73
73
  onKeyDown: function onKeyDown(e) {
74
74
  return e.key === "Escape" && isExpanded && (setExpanded(false), e.stopPropagation());
75
75
  },
@@ -103,7 +103,7 @@ var InputWrapper = function InputWrapper(_ref) {
103
103
  return /*#__PURE__*/jsx(Wrapper, _objectSpread(_objectSpread({}, wrapperProps), {}, {
104
104
  children: /*#__PURE__*/jsx("div", {
105
105
  ref: elRef,
106
- className: "flex-1 relative min-h-8 flex flex-col flex-nowrap",
106
+ className: classNames("relative min-h-8 flex flex-col flex-nowrap", width ? "flex-auto" : "flex-1"),
107
107
  style: {
108
108
  width: width,
109
109
  flexBasis: width
@@ -249,7 +249,7 @@ var useSelect = function useSelect(_ref) {
249
249
  setActive: true
250
250
  });
251
251
  });
252
- }, [onQuery]);
252
+ }, [onQuery], 300);
253
253
 
254
254
  // handlers
255
255
  var handleQuery = useCallback(function (query) {
@@ -6,6 +6,7 @@ export { useFileUploader } from "./hooks/useFileUploader";
6
6
  export { useFormBuilder } from "./hooks/useFormBuilder";
7
7
  export { DATA_TYPES, SCHEMA_CUSTOM_LIST, type FormSchema, type SchemaDef, } from "./types/schema";
8
8
  export { ArrayInput } from "./input/ArrayInput";
9
+ export { AvatarInput } from "./input/AvatarInput";
9
10
  export { Checkbox } from "./input/Checkbox";
10
11
  export { ColorInput } from "./input/ColorInput";
11
12
  export { ColorPicker } from "./input/ColorPicker";
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode, type Ref } from "react";
2
- export interface ArrayInputProps {
2
+ export interface ArrayInputProps<T extends AnyObject = string> {
3
3
  /**
4
4
  * input label
5
5
  */
@@ -58,13 +58,29 @@ export interface ArrayInputProps {
58
58
  */
59
59
  fixedList?: boolean;
60
60
  arrayRef?: Ref<{
61
- addItem: (item: AnyObject) => void;
61
+ addItem: (item: T) => void;
62
62
  removeItem: (idx: number) => void;
63
63
  }>;
64
64
  /**
65
- * Add item
65
+ * add new item
66
66
  */
67
67
  onAdd?: () => AnyObject;
68
+ /**
69
+ * on item remove
70
+ */
71
+ onRemove?: (item: T, idx: number) => void;
72
+ /**
73
+ * before item remove
74
+ */
75
+ onBeforeRemove?: (item: T, idx: number) => Promise<boolean> | boolean;
76
+ /**
77
+ * can remove item
78
+ */
79
+ canRemove?: (props: {
80
+ item: T;
81
+ index: number;
82
+ lastItem: boolean;
83
+ }) => boolean;
68
84
  /**
69
85
  * field width
70
86
  */
@@ -78,4 +94,4 @@ export interface ArrayInputProps {
78
94
  */
79
95
  labelWidth?: string;
80
96
  }
81
- export declare const ArrayInput: ({ name, children, addLabel, fixedList, focusName, buttonPosition, onAdd, arrayRef, enableSorting, disabled, readOnly, minItems, maxItems, ...rest }: ArrayInputProps) => import("react/jsx-runtime").JSX.Element;
97
+ export declare const ArrayInput: <T extends unknown = string>({ name, children, addLabel, fixedList, focusName, buttonPosition, onAdd, onRemove, onBeforeRemove, canRemove, arrayRef, enableSorting, disabled, readOnly, minItems, maxItems, ...rest }: ArrayInputProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -7,4 +7,4 @@ export interface ColorInputProps extends InputProps, Omit<ColorProps, "onChange"
7
7
  */
8
8
  showPicker?: boolean;
9
9
  }
10
- export declare const ColorInput: ({ ref, required, disabled, allowClear, invalid, error, value, showPicker, defaultColor, decorateEnd, decorateStart, onBlur, onFocus, onChange, noOutline, ...rest }: ColorInputProps) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const ColorInput: ({ ref, required, disabled, readOnly, invalid, error, value, showPicker, defaultColor, onBlur, onFocus, onChange, noOutline, ...rest }: ColorInputProps) => import("react/jsx-runtime").JSX.Element;
@@ -6,4 +6,4 @@ export interface TextInputProps extends InputProps, RefProp<HTMLInputElement> {
6
6
  */
7
7
  type?: "email" | "file" | "search" | "tel" | "text" | "url";
8
8
  }
9
- export declare const Input: ({ ref, name, value, invalid, readOnly, disabled, required, placeholder, autoFocus, error, type, onBlur, onFocus, onChange, onEnterPressed, ...rest }: TextInputProps) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const Input: ({ ref, name, value, invalid, readOnly, disabled, required, placeholder, autoFocus, error, monospace, type, onBlur, onFocus, onChange, onEnterPressed, ...rest }: TextInputProps) => import("react/jsx-runtime").JSX.Element;
@@ -51,6 +51,7 @@ export interface InputProps<V = string> extends TestProps {
51
51
  * info label at bottom
52
52
  */
53
53
  info?: string;
54
+ monospace?: boolean;
54
55
  /**
55
56
  * required
56
57
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-fabric/form",
3
- "version": "1.0.0-beta.45",
3
+ "version": "1.0.0-beta.47",
4
4
  "description": "RUF: Form package",
5
5
  "author": "Adarsh Pastakia <adarshpastakia@outlook.com>",
6
6
  "license": "MIT",
@@ -41,9 +41,9 @@
41
41
  "@dnd-kit/utilities": "^3.2.2",
42
42
  "@floating-ui/react": "^0.26.24",
43
43
  "@hookform/resolvers": "^3.9.0",
44
- "@react-fabric/core": "^1.0.0-beta.45",
45
- "@react-fabric/date": "^1.0.0-beta.45",
46
- "@react-fabric/utilities": "^1.0.0-beta.45",
44
+ "@react-fabric/core": "^1.0.0-beta.47",
45
+ "@react-fabric/date": "^1.0.0-beta.47",
46
+ "@react-fabric/utilities": "^1.0.0-beta.47",
47
47
  "classnames": "^2.5.1",
48
48
  "color": "^4.2.3",
49
49
  "react-color": "^2.19.3",
@@ -63,5 +63,5 @@
63
63
  "node": ">=18.12.0",
64
64
  "npm": ">=8.19.0"
65
65
  },
66
- "gitHead": "37d7cbcd99da40553f4ac775c3332d5281565936"
66
+ "gitHead": "832a1bce055337127ba17c505731f419248cc15e"
67
67
  }
package/src/form/Form.tsx CHANGED
@@ -90,7 +90,7 @@ export const Form = <K extends KeyValue>({
90
90
  });
91
91
 
92
92
  const [, startTransition] = useTransition();
93
- const changeHandler = useDebounce(onChange, [onChange]);
93
+ const changeHandler = useDebounce(onChange, [onChange], 300);
94
94
  useEffect(() => {
95
95
  const subscription = form.watch((value) => {
96
96
  startTransition(() => changeHandler?.(value as K));
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export {
39
39
  } from "./types/schema";
40
40
 
41
41
  export { ArrayInput } from "./input/ArrayInput";
42
+ export { AvatarInput } from "./input/AvatarInput";
42
43
  export { Checkbox } from "./input/Checkbox";
43
44
  export { ColorInput } from "./input/ColorInput";
44
45
  export { ColorPicker } from "./input/ColorPicker";
@@ -30,7 +30,7 @@ import {
30
30
  Icon,
31
31
  Tooltip,
32
32
  } from "@react-fabric/core";
33
- import { isString } from "@react-fabric/utilities";
33
+ import { isFalse, isString } from "@react-fabric/utilities";
34
34
  import classNames from "classnames";
35
35
  import {
36
36
  cloneElement,
@@ -48,7 +48,7 @@ import { FieldWrapper } from "../internal/FieldWrapper";
48
48
  import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
49
49
  import { CSS } from "@dnd-kit/utilities";
50
50
 
51
- export interface ArrayInputProps {
51
+ export interface ArrayInputProps<T extends AnyObject = string> {
52
52
  /**
53
53
  * input label
54
54
  */
@@ -107,13 +107,25 @@ export interface ArrayInputProps {
107
107
  */
108
108
  fixedList?: boolean;
109
109
  arrayRef?: Ref<{
110
- addItem: (item: AnyObject) => void;
110
+ addItem: (item: T) => void;
111
111
  removeItem: (idx: number) => void;
112
112
  }>;
113
113
  /**
114
- * Add item
114
+ * add new item
115
115
  */
116
116
  onAdd?: () => AnyObject;
117
+ /**
118
+ * on item remove
119
+ */
120
+ onRemove?: (item: T, idx: number) => void;
121
+ /**
122
+ * before item remove
123
+ */
124
+ onBeforeRemove?: (item: T, idx: number) => Promise<boolean> | boolean;
125
+ /**
126
+ * can remove item
127
+ */
128
+ canRemove?: (props: { item: T; index: number; lastItem: boolean }) => boolean;
117
129
 
118
130
  /**
119
131
  * field width
@@ -129,7 +141,7 @@ export interface ArrayInputProps {
129
141
  labelWidth?: string;
130
142
  }
131
143
 
132
- export const ArrayInput = ({
144
+ export const ArrayInput = <T extends AnyObject = string>({
133
145
  name,
134
146
  children,
135
147
  addLabel,
@@ -137,6 +149,9 @@ export const ArrayInput = ({
137
149
  focusName = "",
138
150
  buttonPosition = "bottom",
139
151
  onAdd,
152
+ onRemove,
153
+ onBeforeRemove,
154
+ canRemove,
140
155
  arrayRef,
141
156
  enableSorting,
142
157
  disabled = false,
@@ -144,7 +159,7 @@ export const ArrayInput = ({
144
159
  minItems = 0,
145
160
  maxItems = Number.MAX_SAFE_INTEGER,
146
161
  ...rest
147
- }: ArrayInputProps) => {
162
+ }: ArrayInputProps<T>) => {
148
163
  const { t } = useTranslation("form");
149
164
  const form = useFormContext();
150
165
 
@@ -153,6 +168,7 @@ export const ArrayInput = ({
153
168
 
154
169
  const { fields, append, remove, move } = useFieldArray({
155
170
  name,
171
+ keyName: "__ID__",
156
172
  control: form.control,
157
173
  });
158
174
 
@@ -164,7 +180,7 @@ export const ArrayInput = ({
164
180
  );
165
181
 
166
182
  const handleAdd = useCallback(
167
- (item: AnyObject) => {
183
+ (item: T) => {
168
184
  append(item);
169
185
  setTimeout(() => {
170
186
  form.setFocus(
@@ -175,6 +191,19 @@ export const ArrayInput = ({
175
191
  [name, fields, focusName],
176
192
  );
177
193
 
194
+ const handleRemove = useCallback(
195
+ (item: T, index: number) => {
196
+ const ret = onBeforeRemove?.(item, index);
197
+ void Promise.resolve(ret).then((b) => {
198
+ if (!isFalse(b)) {
199
+ remove(index);
200
+ onRemove?.(item, index);
201
+ }
202
+ });
203
+ },
204
+ [remove, onRemove, onBeforeRemove],
205
+ );
206
+
178
207
  useImperativeHandle(arrayRef, () => ({
179
208
  addItem: handleAdd,
180
209
  removeItem: remove,
@@ -184,7 +213,7 @@ export const ArrayInput = ({
184
213
  ({ children }: PropsWithChildren) => {
185
214
  if (enableSorting) {
186
215
  // pass id list to dnd context
187
- const idMap = fields.map((item) => item.id);
216
+ const idMap = fields.map((item) => item.__ID__);
188
217
  const handleDragEnd = (e: DragEndEvent) => {
189
218
  if (e.over && e.active.id !== e.over.id) {
190
219
  // find index of item and drop over
@@ -304,8 +333,8 @@ export const ArrayInput = ({
304
333
  <Wrapper>
305
334
  {fields.map((item, index) => (
306
335
  <SortableItem
307
- key={item.id}
308
- id={item.id}
336
+ key={item.__ID__}
337
+ id={item.__ID__}
309
338
  className="flex items-center flex-nowrap gap-2 mb-1"
310
339
  >
311
340
  {typeof children === "function"
@@ -342,8 +371,17 @@ export const ArrayInput = ({
342
371
  color="danger"
343
372
  variant="link"
344
373
  className="self-end"
345
- disabled={disabled || readOnly || fields.length <= minItems}
346
- onClick={() => remove(index)}
374
+ disabled={
375
+ disabled ||
376
+ readOnly ||
377
+ fields.length <= minItems ||
378
+ canRemove?.({
379
+ item: item as T,
380
+ index,
381
+ lastItem: index + 1 === fields.length,
382
+ }) !== false
383
+ }
384
+ onClick={() => handleRemove(item as T, index)}
347
385
  />
348
386
  )}
349
387
  </SortableItem>
@@ -35,8 +35,6 @@ import {
35
35
  } from "@floating-ui/react";
36
36
  import { CoreIcons, Icon } from "@react-fabric/core";
37
37
  import { type RefProp } from "@react-fabric/core/dist/types/types";
38
- import { isString } from "@react-fabric/utilities";
39
- import classNames from "classnames";
40
38
  import {
41
39
  startTransition,
42
40
  useCallback,
@@ -45,6 +43,7 @@ import {
45
43
  useRef,
46
44
  useState,
47
45
  } from "react";
46
+ import { InputWrapper } from "../internal/InputWrapper";
48
47
  import { type InputProps } from "../types";
49
48
  import { ColorPicker, type ColorProps } from "./ColorPicker";
50
49
 
@@ -62,14 +61,12 @@ export const ColorInput = ({
62
61
  ref,
63
62
  required,
64
63
  disabled,
65
- allowClear,
64
+ readOnly,
66
65
  invalid,
67
66
  error,
68
67
  value,
69
68
  showPicker,
70
69
  defaultColor = "",
71
- decorateEnd,
72
- decorateStart,
73
70
  onBlur,
74
71
  onFocus,
75
72
  onChange,
@@ -113,7 +110,7 @@ export const ColorInput = ({
113
110
  ],
114
111
  });
115
112
  const click = useClick(context, {
116
- enabled: !disabled,
113
+ enabled: !disabled && !readOnly,
117
114
  });
118
115
  const dismiss = useDismiss(context, {
119
116
  referencePress: true,
@@ -125,23 +122,16 @@ export const ColorInput = ({
125
122
  ]);
126
123
 
127
124
  return (
128
- <div
129
- className={classNames(
130
- "flex-content min-h-[1.5em] min-w-[3.5em] self-stretch flex items-center outline-tint-200 rounded",
131
- !disabled && "bg-base",
132
- !noOutline && "bg-(--fabric-input) outline overflow-hidden",
133
- )}
125
+ <InputWrapper
126
+ showClear={actualValue !== defaultColor && !disabled && !readOnly}
127
+ onClear={handleChange}
128
+ invalid={invalid}
129
+ readOnly={readOnly}
130
+ disabled={disabled}
131
+ required={required}
132
+ error={error}
133
+ {...rest}
134
134
  >
135
- {decorateStart && (
136
- <div
137
- className={classNames(
138
- "text-muted leading-none flex-content",
139
- isString(decorateStart) && "px-2",
140
- )}
141
- >
142
- {decorateStart}
143
- </div>
144
- )}
145
135
  <button
146
136
  data-ref="button"
147
137
  className="flex-1 flex items-center"
@@ -206,25 +196,6 @@ export const ColorInput = ({
206
196
  }
207
197
  />
208
198
  )}
209
- {decorateEnd && (
210
- <div
211
- className={classNames(
212
- "text-muted leading-none flex-content",
213
- isString(decorateEnd) && "px-2",
214
- )}
215
- >
216
- {decorateEnd}
217
- </div>
218
- )}
219
- {!disabled && allowClear && actualValue !== defaultColor && (
220
- <Icon
221
- icon={CoreIcons.close}
222
- onClick={() => handleChange()}
223
- className={classNames(
224
- "text-tint-500 hover:text-tint-700 p-[0.25em] flex-content",
225
- )}
226
- />
227
- )}
228
- </div>
199
+ </InputWrapper>
229
200
  );
230
201
  };
@@ -186,7 +186,7 @@ export const DateInput = ({
186
186
 
187
187
  return (
188
188
  <InputWrapper
189
- showClear={!!actualValue}
189
+ showClear={!!actualValue && !disabled && !readOnly}
190
190
  onClear={handleChange}
191
191
  invalid={invalid}
192
192
  readOnly={readOnly}