@react-fabric/form 1.0.0-beta.46 → 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.
@@ -5,17 +5,17 @@ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProp
5
5
  var core = require('@dnd-kit/core');
6
6
  var sortable = require('@dnd-kit/sortable');
7
7
  var core$1 = require('@react-fabric/core');
8
- var utilities$1 = require('@react-fabric/utilities');
8
+ var utilities = require('@react-fabric/utilities');
9
9
  var classNames = require('classnames');
10
10
  var react = require('react');
11
11
  var reactHookForm = require('react-hook-form');
12
12
  var reactI18next = require('react-i18next');
13
13
  var FieldWrapper = require('../internal/FieldWrapper.js');
14
14
  var modifiers = require('@dnd-kit/modifiers');
15
- var utilities = require('@dnd-kit/utilities');
15
+ var utilities$1 = require('@dnd-kit/utilities');
16
16
  var jsxRuntime = require('react/jsx-runtime');
17
17
 
18
- var _excluded = ["name", "children", "addLabel", "fixedList", "focusName", "buttonPosition", "onAdd", "arrayRef", "enableSorting", "disabled", "readOnly", "minItems", "maxItems"];
18
+ var _excluded = ["name", "children", "addLabel", "fixedList", "focusName", "buttonPosition", "onAdd", "onRemove", "onBeforeRemove", "canRemove", "arrayRef", "enableSorting", "disabled", "readOnly", "minItems", "maxItems"];
19
19
  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; }
20
20
  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; }
21
21
  var ArrayInput = function ArrayInput(_ref) {
@@ -28,6 +28,9 @@ var ArrayInput = function ArrayInput(_ref) {
28
28
  _ref$buttonPosition = _ref.buttonPosition,
29
29
  buttonPosition = _ref$buttonPosition === void 0 ? "bottom" : _ref$buttonPosition,
30
30
  onAdd = _ref.onAdd,
31
+ onRemove = _ref.onRemove,
32
+ onBeforeRemove = _ref.onBeforeRemove,
33
+ canRemove = _ref.canRemove,
31
34
  arrayRef = _ref.arrayRef,
32
35
  enableSorting = _ref.enableSorting,
33
36
  _ref$disabled = _ref.disabled,
@@ -45,6 +48,7 @@ var ArrayInput = function ArrayInput(_ref) {
45
48
  if (!(form !== null && form !== void 0 && form.control)) throw new Error("ArrayInput must be contained within a Form element");
46
49
  var _useFieldArray = reactHookForm.useFieldArray({
47
50
  name: name,
51
+ keyName: "__ID__",
48
52
  control: form.control
49
53
  }),
50
54
  fields = _useFieldArray.fields,
@@ -61,6 +65,15 @@ var ArrayInput = function ArrayInput(_ref) {
61
65
  form.setFocus("".concat(name, ".").concat(fields.length).concat(focusName ? "." + focusName : ""));
62
66
  }, 100);
63
67
  }, [name, fields, focusName]);
68
+ var handleRemove = react.useCallback(function (item, index) {
69
+ var ret = onBeforeRemove === null || onBeforeRemove === void 0 ? void 0 : onBeforeRemove(item, index);
70
+ void Promise.resolve(ret).then(function (b) {
71
+ if (!utilities.isFalse(b)) {
72
+ remove(index);
73
+ onRemove === null || onRemove === void 0 || onRemove(item, index);
74
+ }
75
+ });
76
+ }, [remove, onRemove, onBeforeRemove]);
64
77
  react.useImperativeHandle(arrayRef, function () {
65
78
  return {
66
79
  addItem: handleAdd,
@@ -72,7 +85,7 @@ var ArrayInput = function ArrayInput(_ref) {
72
85
  if (enableSorting) {
73
86
  // pass id list to dnd context
74
87
  var idMap = fields.map(function (item) {
75
- return item.id;
88
+ return item.__ID__;
76
89
  });
77
90
  var handleDragEnd = function handleDragEnd(e) {
78
91
  if (e.over && e.active.id !== e.over.id) {
@@ -113,7 +126,7 @@ var ArrayInput = function ArrayInput(_ref) {
113
126
  className: className,
114
127
  ref: setNodeRef,
115
128
  style: {
116
- transform: utilities.CSS.Transform.toString(transform),
129
+ transform: utilities$1.CSS.Transform.toString(transform),
117
130
  transition: transition
118
131
  },
119
132
  children: [/*#__PURE__*/jsxRuntime.jsx(core$1.Icon, _objectSpread(_objectSpread({
@@ -135,7 +148,7 @@ var ArrayInput = function ArrayInput(_ref) {
135
148
  className: "flex justify-end",
136
149
  children: /*#__PURE__*/jsxRuntime.jsx(core$1.Tooltip, {
137
150
  color: "danger-200",
138
- content: utilities$1.isString(error) ? "".concat(error) : t(error === null || error === void 0 ? void 0 : error.key, error !== null && error !== void 0 && error.values ? _objectSpread(_objectSpread({}, error === null || error === void 0 ? void 0 : error.values), {}, {
151
+ content: utilities.isString(error) ? "".concat(error) : t(error === null || error === void 0 ? void 0 : error.key, error !== null && error !== void 0 && error.values ? _objectSpread(_objectSpread({}, error === null || error === void 0 ? void 0 : error.values), {}, {
139
152
  label: t((_error$values$label = (_error$values = error.values) === null || _error$values === void 0 ? void 0 : _error$values.label) !== null && _error$values$label !== void 0 ? _error$values$label : "form:badkey", (_error$values2 = error.values) === null || _error$values2 === void 0 ? void 0 : _error$values2.path)
140
153
  }) : {}),
141
154
  children: /*#__PURE__*/jsxRuntime.jsx(core$1.Button, {
@@ -163,7 +176,7 @@ var ArrayInput = function ArrayInput(_ref) {
163
176
  children: /*#__PURE__*/jsxRuntime.jsx(Wrapper, {
164
177
  children: fields.map(function (item, index) {
165
178
  return /*#__PURE__*/jsxRuntime.jsxs(SortableItem, {
166
- id: item.id,
179
+ id: item.__ID__,
167
180
  className: "flex items-center flex-nowrap gap-2 mb-1",
168
181
  children: [typeof children === "function" ? children({
169
182
  index: index,
@@ -185,12 +198,16 @@ var ArrayInput = function ArrayInput(_ref) {
185
198
  color: "danger",
186
199
  variant: "link",
187
200
  className: "self-end",
188
- disabled: disabled || readOnly || fields.length <= minItems,
201
+ disabled: disabled || readOnly || fields.length <= minItems || (canRemove === null || canRemove === void 0 ? void 0 : canRemove({
202
+ item: item,
203
+ index: index,
204
+ lastItem: index + 1 === fields.length
205
+ })) !== false,
189
206
  onClick: function onClick() {
190
- return remove(index);
207
+ return handleRemove(item, index);
191
208
  }
192
209
  })]
193
- }, item.id);
210
+ }, item.__ID__);
194
211
  })
195
212
  })
196
213
  })), !fixedList && onAdd && buttonPosition !== "top" && addButton]
@@ -5,7 +5,7 @@ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProper
5
5
  import { DndContext } from '@dnd-kit/core';
6
6
  import { SortableContext, useSortable } from '@dnd-kit/sortable';
7
7
  import { Icon, CoreIcons, Tooltip, Button, cloneChildren } from '@react-fabric/core';
8
- import { isString } from '@react-fabric/utilities';
8
+ import { isFalse, isString } from '@react-fabric/utilities';
9
9
  import classNames from 'classnames';
10
10
  import { useMemo, useCallback, useImperativeHandle, cloneElement } from 'react';
11
11
  import { useFormContext, useFieldArray } from 'react-hook-form';
@@ -15,7 +15,7 @@ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
15
15
  import { CSS } from '@dnd-kit/utilities';
16
16
  import { jsx, jsxs } from 'react/jsx-runtime';
17
17
 
18
- var _excluded = ["name", "children", "addLabel", "fixedList", "focusName", "buttonPosition", "onAdd", "arrayRef", "enableSorting", "disabled", "readOnly", "minItems", "maxItems"];
18
+ var _excluded = ["name", "children", "addLabel", "fixedList", "focusName", "buttonPosition", "onAdd", "onRemove", "onBeforeRemove", "canRemove", "arrayRef", "enableSorting", "disabled", "readOnly", "minItems", "maxItems"];
19
19
  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; }
20
20
  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; }
21
21
  var ArrayInput = function ArrayInput(_ref) {
@@ -28,6 +28,9 @@ var ArrayInput = function ArrayInput(_ref) {
28
28
  _ref$buttonPosition = _ref.buttonPosition,
29
29
  buttonPosition = _ref$buttonPosition === void 0 ? "bottom" : _ref$buttonPosition,
30
30
  onAdd = _ref.onAdd,
31
+ onRemove = _ref.onRemove,
32
+ onBeforeRemove = _ref.onBeforeRemove,
33
+ canRemove = _ref.canRemove,
31
34
  arrayRef = _ref.arrayRef,
32
35
  enableSorting = _ref.enableSorting,
33
36
  _ref$disabled = _ref.disabled,
@@ -45,6 +48,7 @@ var ArrayInput = function ArrayInput(_ref) {
45
48
  if (!(form !== null && form !== void 0 && form.control)) throw new Error("ArrayInput must be contained within a Form element");
46
49
  var _useFieldArray = useFieldArray({
47
50
  name: name,
51
+ keyName: "__ID__",
48
52
  control: form.control
49
53
  }),
50
54
  fields = _useFieldArray.fields,
@@ -61,6 +65,15 @@ var ArrayInput = function ArrayInput(_ref) {
61
65
  form.setFocus("".concat(name, ".").concat(fields.length).concat(focusName ? "." + focusName : ""));
62
66
  }, 100);
63
67
  }, [name, fields, focusName]);
68
+ var handleRemove = useCallback(function (item, index) {
69
+ var ret = onBeforeRemove === null || onBeforeRemove === void 0 ? void 0 : onBeforeRemove(item, index);
70
+ void Promise.resolve(ret).then(function (b) {
71
+ if (!isFalse(b)) {
72
+ remove(index);
73
+ onRemove === null || onRemove === void 0 || onRemove(item, index);
74
+ }
75
+ });
76
+ }, [remove, onRemove, onBeforeRemove]);
64
77
  useImperativeHandle(arrayRef, function () {
65
78
  return {
66
79
  addItem: handleAdd,
@@ -72,7 +85,7 @@ var ArrayInput = function ArrayInput(_ref) {
72
85
  if (enableSorting) {
73
86
  // pass id list to dnd context
74
87
  var idMap = fields.map(function (item) {
75
- return item.id;
88
+ return item.__ID__;
76
89
  });
77
90
  var handleDragEnd = function handleDragEnd(e) {
78
91
  if (e.over && e.active.id !== e.over.id) {
@@ -163,7 +176,7 @@ var ArrayInput = function ArrayInput(_ref) {
163
176
  children: /*#__PURE__*/jsx(Wrapper, {
164
177
  children: fields.map(function (item, index) {
165
178
  return /*#__PURE__*/jsxs(SortableItem, {
166
- id: item.id,
179
+ id: item.__ID__,
167
180
  className: "flex items-center flex-nowrap gap-2 mb-1",
168
181
  children: [typeof children === "function" ? children({
169
182
  index: index,
@@ -185,12 +198,16 @@ var ArrayInput = function ArrayInput(_ref) {
185
198
  color: "danger",
186
199
  variant: "link",
187
200
  className: "self-end",
188
- disabled: disabled || readOnly || fields.length <= minItems,
201
+ disabled: disabled || readOnly || fields.length <= minItems || (canRemove === null || canRemove === void 0 ? void 0 : canRemove({
202
+ item: item,
203
+ index: index,
204
+ lastItem: index + 1 === fields.length
205
+ })) !== false,
189
206
  onClick: function onClick() {
190
- return remove(index);
207
+ return handleRemove(item, index);
191
208
  }
192
209
  })]
193
- }, item.id);
210
+ }, item.__ID__);
194
211
  })
195
212
  })
196
213
  })), !fixedList && onAdd && buttonPosition !== "top" && addButton]
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-fabric/form",
3
- "version": "1.0.0-beta.46",
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.46",
45
- "@react-fabric/date": "^1.0.0-beta.46",
46
- "@react-fabric/utilities": "^1.0.0-beta.46",
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": "0dfc20b9c84712bb1cb5205c22464e8a1eb2341c"
66
+ "gitHead": "832a1bce055337127ba17c505731f419248cc15e"
67
67
  }
@@ -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>