@rjsf/daisyui 6.0.0-beta.9 → 6.0.1

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 (99) hide show
  1. package/README.md +9 -16
  2. package/dist/chakra-ui.esm.js +382 -472
  3. package/dist/chakra-ui.esm.js.map +4 -4
  4. package/dist/chakra-ui.umd.js +194 -287
  5. package/dist/{index.js → index.cjs} +404 -496
  6. package/dist/index.cjs.map +7 -0
  7. package/lib/templates/ArrayFieldItemButtonsTemplate/ArrayFieldItemButtonsTemplate.d.ts +2 -2
  8. package/lib/templates/ArrayFieldItemButtonsTemplate/ArrayFieldItemButtonsTemplate.js +2 -7
  9. package/lib/templates/ArrayFieldItemButtonsTemplate/ArrayFieldItemButtonsTemplate.js.map +1 -1
  10. package/lib/templates/ArrayFieldItemTemplate/ArrayFieldItemTemplate.d.ts +3 -3
  11. package/lib/templates/ArrayFieldItemTemplate/ArrayFieldItemTemplate.js +1 -1
  12. package/lib/templates/ArrayFieldItemTemplate/ArrayFieldItemTemplate.js.map +1 -1
  13. package/lib/templates/ArrayFieldTemplate/ArrayFieldTemplate.js +3 -4
  14. package/lib/templates/ArrayFieldTemplate/ArrayFieldTemplate.js.map +1 -1
  15. package/lib/templates/ArrayFieldTitleTemplate/ArrayFieldTitleTemplate.js +7 -3
  16. package/lib/templates/ArrayFieldTitleTemplate/ArrayFieldTitleTemplate.js.map +1 -1
  17. package/lib/templates/BaseInputTemplate/BaseInputTemplate.js +8 -2
  18. package/lib/templates/BaseInputTemplate/BaseInputTemplate.js.map +1 -1
  19. package/lib/templates/ButtonTemplates/AddButton.js +1 -1
  20. package/lib/templates/ButtonTemplates/AddButton.js.map +1 -1
  21. package/lib/templates/ButtonTemplates/IconButton.js +4 -4
  22. package/lib/templates/ButtonTemplates/IconButton.js.map +1 -1
  23. package/lib/templates/FieldTemplate/FieldTemplate.js +6 -3
  24. package/lib/templates/FieldTemplate/FieldTemplate.js.map +1 -1
  25. package/lib/templates/MultiSchemaFieldTemplate/MultiSchemaFieldTemplate.d.ts +2 -0
  26. package/lib/templates/MultiSchemaFieldTemplate/MultiSchemaFieldTemplate.js +6 -0
  27. package/lib/templates/MultiSchemaFieldTemplate/MultiSchemaFieldTemplate.js.map +1 -0
  28. package/lib/templates/MultiSchemaFieldTemplate/index.d.ts +2 -0
  29. package/lib/templates/MultiSchemaFieldTemplate/index.js +3 -0
  30. package/lib/templates/MultiSchemaFieldTemplate/index.js.map +1 -0
  31. package/lib/templates/ObjectFieldTemplate/ObjectFieldTemplate.js +4 -3
  32. package/lib/templates/ObjectFieldTemplate/ObjectFieldTemplate.js.map +1 -1
  33. package/lib/templates/OptionalDataControlsTemplate/OptionalDataControlsTemplate.d.ts +10 -0
  34. package/lib/templates/OptionalDataControlsTemplate/OptionalDataControlsTemplate.js +23 -0
  35. package/lib/templates/OptionalDataControlsTemplate/OptionalDataControlsTemplate.js.map +1 -0
  36. package/lib/templates/OptionalDataControlsTemplate/index.d.ts +2 -0
  37. package/lib/templates/OptionalDataControlsTemplate/index.js +3 -0
  38. package/lib/templates/OptionalDataControlsTemplate/index.js.map +1 -0
  39. package/lib/templates/Templates.js +4 -0
  40. package/lib/templates/Templates.js.map +1 -1
  41. package/lib/templates/TitleField/TitleField.js +6 -2
  42. package/lib/templates/TitleField/TitleField.js.map +1 -1
  43. package/lib/templates/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.js +11 -11
  44. package/lib/templates/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.js.map +1 -1
  45. package/lib/tsconfig.tsbuildinfo +1 -1
  46. package/lib/widgets/AltDateWidget/AltDateWidget.d.ts +1 -1
  47. package/lib/widgets/AltDateWidget/AltDateWidget.js +5 -121
  48. package/lib/widgets/AltDateWidget/AltDateWidget.js.map +1 -1
  49. package/lib/widgets/CheckboxWidget/CheckboxWidget.js +2 -2
  50. package/lib/widgets/CheckboxWidget/CheckboxWidget.js.map +1 -1
  51. package/lib/widgets/CheckboxesWidget/CheckboxesWidget.d.ts +1 -1
  52. package/lib/widgets/CheckboxesWidget/CheckboxesWidget.js +2 -2
  53. package/lib/widgets/CheckboxesWidget/CheckboxesWidget.js.map +1 -1
  54. package/lib/widgets/DateTimeWidget/DateTimeWidget.js +2 -2
  55. package/lib/widgets/DateTimeWidget/DateTimeWidget.js.map +1 -1
  56. package/lib/widgets/DateWidget/DateWidget.js +2 -2
  57. package/lib/widgets/DateWidget/DateWidget.js.map +1 -1
  58. package/lib/widgets/RadioWidget/RadioWidget.d.ts +1 -1
  59. package/lib/widgets/RadioWidget/RadioWidget.js +2 -2
  60. package/lib/widgets/RadioWidget/RadioWidget.js.map +1 -1
  61. package/lib/widgets/TextareaWidget/TextareaWidget.js +2 -2
  62. package/lib/widgets/TextareaWidget/TextareaWidget.js.map +1 -1
  63. package/lib/widgets/Widgets.d.ts +1 -2
  64. package/lib/widgets/Widgets.js +1 -3
  65. package/lib/widgets/Widgets.js.map +1 -1
  66. package/package.json +24 -22
  67. package/src/templates/ArrayFieldItemButtonsTemplate/ArrayFieldItemButtonsTemplate.tsx +15 -20
  68. package/src/templates/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx +3 -3
  69. package/src/templates/ArrayFieldTemplate/ArrayFieldTemplate.tsx +9 -13
  70. package/src/templates/ArrayFieldTitleTemplate/ArrayFieldTitleTemplate.tsx +12 -2
  71. package/src/templates/BaseInputTemplate/BaseInputTemplate.tsx +14 -6
  72. package/src/templates/ButtonTemplates/AddButton.tsx +1 -1
  73. package/src/templates/ButtonTemplates/IconButton.tsx +4 -4
  74. package/src/templates/FieldTemplate/FieldTemplate.tsx +48 -19
  75. package/src/templates/MultiSchemaFieldTemplate/MultiSchemaFieldTemplate.tsx +15 -0
  76. package/src/templates/MultiSchemaFieldTemplate/index.ts +2 -0
  77. package/src/templates/ObjectFieldTemplate/ObjectFieldTemplate.tsx +13 -9
  78. package/src/templates/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx +46 -0
  79. package/src/templates/OptionalDataControlsTemplate/index.ts +2 -0
  80. package/src/templates/Templates.tsx +4 -0
  81. package/src/templates/TitleField/TitleField.tsx +12 -3
  82. package/src/templates/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx +38 -34
  83. package/src/widgets/AltDateWidget/AltDateWidget.tsx +18 -253
  84. package/src/widgets/CheckboxWidget/CheckboxWidget.tsx +5 -3
  85. package/src/widgets/CheckboxesWidget/CheckboxesWidget.tsx +2 -1
  86. package/src/widgets/DateTimeWidget/DateTimeWidget.tsx +2 -2
  87. package/src/widgets/DateWidget/DateWidget.tsx +2 -2
  88. package/src/widgets/RadioWidget/RadioWidget.tsx +2 -1
  89. package/src/widgets/TextareaWidget/TextareaWidget.tsx +2 -1
  90. package/src/widgets/Widgets.tsx +0 -3
  91. package/dist/index.js.map +0 -7
  92. package/lib/widgets/FileWidget/FileWidget.d.ts +0 -12
  93. package/lib/widgets/FileWidget/FileWidget.js +0 -57
  94. package/lib/widgets/FileWidget/FileWidget.js.map +0 -1
  95. package/lib/widgets/FileWidget/index.d.ts +0 -2
  96. package/lib/widgets/FileWidget/index.js +0 -3
  97. package/lib/widgets/FileWidget/index.js.map +0 -1
  98. package/src/widgets/FileWidget/FileWidget.tsx +0 -86
  99. package/src/widgets/FileWidget/index.ts +0 -2
@@ -1,9 +1,8 @@
1
- import { useMemo } from 'react';
2
1
  import {
3
2
  FormContextType,
4
3
  RJSFSchema,
5
4
  StrictRJSFSchema,
6
- ArrayFieldItemButtonsTemplateType,
5
+ ArrayFieldItemButtonsTemplateProps,
7
6
  buttonId,
8
7
  } from '@rjsf/utils';
9
8
 
@@ -14,27 +13,23 @@ export default function ArrayFieldItemButtonsTemplate<
14
13
  T = any,
15
14
  S extends StrictRJSFSchema = RJSFSchema,
16
15
  F extends FormContextType = any,
17
- >(props: ArrayFieldItemButtonsTemplateType<T, S, F>) {
16
+ >(props: ArrayFieldItemButtonsTemplateProps<T, S, F>) {
18
17
  const {
19
18
  disabled,
20
19
  hasCopy,
21
20
  hasMoveDown,
22
21
  hasMoveUp,
23
22
  hasRemove,
24
- idSchema,
25
- index,
26
- onCopyIndexClick,
27
- onDropIndexClick,
28
- onReorderClick,
23
+ fieldPathId,
24
+ onCopyItem,
25
+ onRemoveItem,
26
+ onMoveDownItem,
27
+ onMoveUpItem,
29
28
  readonly,
30
29
  registry,
31
30
  uiSchema,
32
31
  } = props;
33
32
  const { CopyButton, MoveDownButton, MoveUpButton, RemoveButton } = registry.templates.ButtonTemplates;
34
- const onCopyClick = useMemo(() => onCopyIndexClick(index), [index, onCopyIndexClick]);
35
- const onRemoveClick = useMemo(() => onDropIndexClick(index), [index, onDropIndexClick]);
36
- const onArrowUpClick = useMemo(() => onReorderClick(index, index - 1), [index, onReorderClick]);
37
- const onArrowDownClick = useMemo(() => onReorderClick(index, index + 1), [index, onReorderClick]);
38
33
 
39
34
  const renderMany = [hasMoveUp || hasMoveDown, hasCopy, hasRemove].filter(Boolean).length > 1;
40
35
  const btnClass = renderMany ? 'join-item btn btn-sm px-2' : 'btn btn-sm px-2 rounded-sm';
@@ -45,18 +40,18 @@ export default function ArrayFieldItemButtonsTemplate<
45
40
  {(hasMoveUp || hasMoveDown) && (
46
41
  <>
47
42
  <MoveUpButton
48
- id={buttonId<T>(idSchema, 'moveUp')}
43
+ id={buttonId(fieldPathId, 'moveUp')}
49
44
  className={`rjsf-array-item-move-up ${btnClass}`}
50
45
  disabled={disabled || readonly || !hasMoveUp}
51
- onClick={onArrowUpClick}
46
+ onClick={onMoveUpItem}
52
47
  uiSchema={uiSchema}
53
48
  registry={registry}
54
49
  />
55
50
  <MoveDownButton
56
- id={buttonId<T>(idSchema, 'moveDown')}
51
+ id={buttonId(fieldPathId, 'moveDown')}
57
52
  className={`rjsf-array-item-move-down ${btnClass}`}
58
53
  disabled={disabled || readonly || !hasMoveDown}
59
- onClick={onArrowDownClick}
54
+ onClick={onMoveDownItem}
60
55
  uiSchema={uiSchema}
61
56
  registry={registry}
62
57
  />
@@ -64,20 +59,20 @@ export default function ArrayFieldItemButtonsTemplate<
64
59
  )}
65
60
  {hasCopy && (
66
61
  <CopyButton
67
- id={buttonId<T>(idSchema, 'copy')}
62
+ id={buttonId(fieldPathId, 'copy')}
68
63
  className={`rjsf-array-item-copy ${btnClass}`}
69
64
  disabled={disabled || readonly}
70
- onClick={onCopyClick}
65
+ onClick={onCopyItem}
71
66
  uiSchema={uiSchema}
72
67
  registry={registry}
73
68
  />
74
69
  )}
75
70
  {hasRemove && (
76
71
  <RemoveButton
77
- id={buttonId<T>(idSchema, 'remove')}
72
+ id={buttonId(fieldPathId, 'remove')}
78
73
  className={`rjsf-array-item-remove ${removeBtnClass}`}
79
74
  disabled={disabled || readonly}
80
- onClick={onRemoveClick}
75
+ onClick={onRemoveItem}
81
76
  uiSchema={uiSchema}
82
77
  registry={registry}
83
78
  />
@@ -1,5 +1,5 @@
1
1
  import {
2
- ArrayFieldItemTemplateType,
2
+ ArrayFieldItemTemplateProps,
3
3
  FormContextType,
4
4
  getTemplate,
5
5
  getUiOptions,
@@ -15,7 +15,7 @@ import {
15
15
  * - Positions items with z-index to create a stacked effect
16
16
  * - Places action buttons in an easily accessible location
17
17
  *
18
- * @param props - The `ArrayFieldItemTemplateType` props for the component with additional properties:
18
+ * @param props - The `ArrayFieldItemTemplateProps` props for the component with additional properties:
19
19
  * @param props.index - The position of this item in the array (optional)
20
20
  * @param props.totalItems - The total number of items in the array (optional)
21
21
  */
@@ -23,7 +23,7 @@ export default function ArrayFieldItemTemplate<
23
23
  T = any,
24
24
  S extends StrictRJSFSchema = RJSFSchema,
25
25
  F extends FormContextType = any,
26
- >(props: ArrayFieldItemTemplateType<T, S, F>) {
26
+ >(props: ArrayFieldItemTemplateProps<T, S, F>) {
27
27
  const { children, buttonsProps, hasToolbar, registry, uiSchema, index, totalItems } = props;
28
28
  const uiOptions = getUiOptions<T, S, F>(uiSchema);
29
29
  const ArrayFieldItemButtonsTemplate = getTemplate<'ArrayFieldItemButtonsTemplate', T, S, F>(
@@ -30,8 +30,9 @@ export default function ArrayFieldTemplate<T = any, S extends RJSFSchema = RJSFS
30
30
  canAdd,
31
31
  className,
32
32
  disabled,
33
- idSchema,
33
+ fieldPathId,
34
34
  items,
35
+ optionalDataControl,
35
36
  onAddClick,
36
37
  readonly,
37
38
  registry,
@@ -47,16 +48,12 @@ export default function ArrayFieldTemplate<T = any, S extends RJSFSchema = RJSFS
47
48
  registry as Registry<T, S, F>,
48
49
  uiOptions,
49
50
  );
50
- const ArrayFieldItemTemplate = getTemplate<'ArrayFieldItemTemplate', T, S, F>(
51
- 'ArrayFieldItemTemplate',
52
- registry as Registry<T, S, F>,
53
- uiOptions,
54
- );
55
51
  const ArrayFieldTitleTemplate = getTemplate<'ArrayFieldTitleTemplate', T, S, F>(
56
52
  'ArrayFieldTitleTemplate',
57
53
  registry as Registry<T, S, F>,
58
54
  uiOptions,
59
55
  );
56
+ const showOptionalDataControlInTitle = !readonly && !disabled;
60
57
  // Button templates are not overridden in the uiSchema
61
58
  const {
62
59
  ButtonTemplates: { AddButton },
@@ -78,26 +75,25 @@ export default function ArrayFieldTemplate<T = any, S extends RJSFSchema = RJSFS
78
75
  return (
79
76
  <div className={`array-field-template ${className}`}>
80
77
  <ArrayFieldTitleTemplate
81
- idSchema={idSchema}
78
+ fieldPathId={fieldPathId}
82
79
  title={uiOptions.title || title}
83
80
  schema={schema}
84
81
  uiSchema={uiSchema}
85
82
  required={required}
86
83
  registry={registry}
84
+ optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
87
85
  />
88
86
  <ArrayFieldDescriptionTemplate
89
- idSchema={idSchema}
87
+ fieldPathId={fieldPathId}
90
88
  description={uiOptions.description || schema.description}
91
89
  schema={schema}
92
90
  uiSchema={uiSchema}
93
91
  registry={registry}
94
92
  />
95
93
  <div className='flex flex-col gap-4'>
94
+ {!showOptionalDataControlInTitle ? optionalDataControl : undefined}
96
95
  <div className='rjsf-array-item-list'>
97
- {items &&
98
- items.map(({ key, ...itemProps }, index) => (
99
- <ArrayFieldItemTemplate key={key} {...itemProps} index={index} totalItems={items.length} />
100
- ))}
96
+ {items}
101
97
  {items && items.length === 0 && canAdd && (
102
98
  <div className='text-center italic text-base-content/70'>{TranslatableString.EmptyArray}</div>
103
99
  )}
@@ -105,7 +101,7 @@ export default function ArrayFieldTemplate<T = any, S extends RJSFSchema = RJSFS
105
101
  {canAdd && (
106
102
  <div className='flex justify-end'>
107
103
  <AddButton
108
- id={buttonId<T>(idSchema, 'add')}
104
+ id={buttonId(fieldPathId, 'add')}
109
105
  className='rjsf-array-item-add btn btn-primary btn-sm'
110
106
  onClick={handleAddClick}
111
107
  disabled={disabled || readonly}
@@ -10,6 +10,16 @@ export default function ArrayFieldTitleTemplate<
10
10
  S extends StrictRJSFSchema = RJSFSchema,
11
11
  F extends FormContextType = any,
12
12
  >(props: ArrayFieldTitleProps<T, S, F>) {
13
- const { title } = props;
14
- return <h3 className='text-2xl font-bold'>{title}</h3>;
13
+ const { title, optionalDataControl } = props;
14
+ let heading = <h3 className='text-2xl font-bold'>{title}</h3>;
15
+ if (optionalDataControl) {
16
+ heading = (
17
+ <>
18
+ <div className='flex flex-col'>{heading}</div>
19
+ <div className='flex justify-end'>{optionalDataControl}</div>
20
+ </>
21
+ );
22
+ }
23
+
24
+ return heading;
15
25
  }
@@ -30,6 +30,8 @@ export default function BaseInputTemplate<
30
30
  >(props: WidgetProps<T, S, F>) {
31
31
  const {
32
32
  id,
33
+ htmlName,
34
+ multiple,
33
35
  value,
34
36
  required,
35
37
  disabled,
@@ -47,10 +49,15 @@ export default function BaseInputTemplate<
47
49
  } = props;
48
50
 
49
51
  const inputProps = getInputProps<T, S, F>(schema, type, options);
50
-
52
+ let className = 'input input-bordered';
53
+ let isMulti = multiple;
54
+ if (type === 'file') {
55
+ isMulti = schema.type === 'array' || Boolean(options.multiple);
56
+ className = 'file-input w-full';
57
+ }
51
58
  // Extract step, min, max, accept from inputProps
52
59
  const { step, min, max, accept, ...rest } = inputProps;
53
- const htmlInputProps = { step, min, max, accept, ...(schema.examples ? { list: examplesId<T>(id) } : undefined) };
60
+ const htmlInputProps = { step, min, max, accept, ...(schema.examples ? { list: examplesId(id) } : undefined) };
54
61
 
55
62
  const _onChange = useCallback(
56
63
  ({ target: { value } }: ChangeEvent<HTMLInputElement>) => onChange(value === '' ? options.emptyValue : value),
@@ -75,23 +82,24 @@ export default function BaseInputTemplate<
75
82
  </label>
76
83
  <input
77
84
  id={id}
78
- name={id}
85
+ name={htmlName || id}
79
86
  value={value || value === 0 ? value : ''}
80
87
  placeholder={placeholder}
81
88
  required={required}
82
89
  disabled={disabled || readonly}
83
90
  autoFocus={autofocus}
84
- className='input input-bordered'
91
+ className={className}
92
+ multiple={isMulti}
85
93
  {...rest}
86
94
  {...htmlInputProps}
87
95
  onChange={onChangeOverride || _onChange}
88
96
  onBlur={_onBlur}
89
97
  onFocus={_onFocus}
90
- aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)}
98
+ aria-describedby={ariaDescribedByIds(id, !!schema.examples)}
91
99
  />
92
100
  </div>
93
101
  {Array.isArray(schema.examples) && (
94
- <datalist id={examplesId<T>(id)}>
102
+ <datalist id={examplesId(id)}>
95
103
  {(schema.examples as string[])
96
104
  .concat(schema.default && !schema.examples.includes(schema.default) ? ([schema.default] as string[]) : [])
97
105
  .map((example: any) => {
@@ -23,11 +23,11 @@ export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSche
23
23
  <div className='row'>
24
24
  <p className={`col-xs-3 col-xs-offset-9 text-right ${className}`}>
25
25
  <DaisyUIButton
26
+ title={translateString(TranslatableString.AddButton)}
26
27
  {...otherProps}
27
28
  iconType='info'
28
29
  icon={faPlus as IconDefinition}
29
30
  className='btn-add col-xs-12 btn-primary btn-primary-content'
30
- title={translateString(TranslatableString.AddButton)}
31
31
  onClick={onClick}
32
32
  disabled={disabled}
33
33
  registry={registry}
@@ -11,7 +11,7 @@ export function CopyButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
11
11
  registry: { translateString },
12
12
  } = props;
13
13
  return (
14
- <DaisyUIButton {...props} title={translateString(TranslatableString.CopyButton)} icon={faCopy as IconDefinition} />
14
+ <DaisyUIButton title={translateString(TranslatableString.CopyButton)} {...props} icon={faCopy as IconDefinition} />
15
15
  );
16
16
  }
17
17
 
@@ -23,8 +23,8 @@ export function MoveDownButton<T = any, S extends StrictRJSFSchema = RJSFSchema,
23
23
  } = props;
24
24
  return (
25
25
  <DaisyUIButton
26
- {...props}
27
26
  title={translateString(TranslatableString.MoveDownButton)}
27
+ {...props}
28
28
  icon={faArrowDown as IconDefinition}
29
29
  />
30
30
  );
@@ -38,8 +38,8 @@ export function MoveUpButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F
38
38
  } = props;
39
39
  return (
40
40
  <DaisyUIButton
41
- {...props}
42
41
  title={translateString(TranslatableString.MoveUpButton)}
42
+ {...props}
43
43
  icon={faArrowUp as IconDefinition}
44
44
  />
45
45
  );
@@ -53,8 +53,8 @@ export function RemoveButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F
53
53
  } = props;
54
54
  return (
55
55
  <DaisyUIButton
56
- {...props}
57
56
  title={translateString(TranslatableString.RemoveButton)}
57
+ {...props}
58
58
  iconType='danger'
59
59
  icon={faTrash as IconDefinition}
60
60
  />
@@ -1,4 +1,11 @@
1
- import { FieldTemplateProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';
1
+ import {
2
+ FieldTemplateProps,
3
+ StrictRJSFSchema,
4
+ RJSFSchema,
5
+ FormContextType,
6
+ getTemplate,
7
+ getUiOptions,
8
+ } from '@rjsf/utils';
2
9
 
3
10
  /** The `FieldTemplate` component provides the main layout for each form field
4
11
  * with DaisyUI styling. It handles:
@@ -23,44 +30,66 @@ export default function FieldTemplate<
23
30
  label,
24
31
  children,
25
32
  errors,
26
- formContext,
27
33
  formData,
28
34
  help,
29
35
  hideError,
30
36
  displayLabel,
37
+ onKeyRename,
38
+ onKeyRenameBlur,
39
+ onRemoveProperty,
31
40
  classNames,
32
- // Destructure props we don't want to pass to div
33
- onKeyChange,
34
- onDropPropertyClick,
35
41
  uiSchema,
36
42
  schema,
37
43
  readonly,
38
44
  required,
45
+ registry,
46
+ // Destructure props we don't want to pass to div
47
+ description,
39
48
  rawErrors,
40
49
  rawHelp,
41
50
  rawDescription,
42
51
  hidden,
43
52
  onChange,
44
- registry,
45
53
  ...divProps
46
54
  } = props;
47
55
 
48
56
  // Special handling for checkboxes - they should have the label after the input
49
57
  const isCheckbox = schema.type === 'boolean';
58
+ const uiOptions = getUiOptions<T, S, F>(uiSchema);
59
+ const WrapIfAdditionalTemplate = getTemplate<'WrapIfAdditionalTemplate', T, S, F>(
60
+ 'WrapIfAdditionalTemplate',
61
+ registry,
62
+ uiOptions,
63
+ );
50
64
 
51
65
  return (
52
- <div className={`field-template mb-3 ${classNames || ''}`} {...divProps}>
53
- {displayLabel && !isCheckbox && (
54
- <label htmlFor={id} className='label'>
55
- <span className='label-text font-medium'>
56
- {label}
57
- {required && <span className='text-error ml-1'>*</span>}
58
- </span>
59
- </label>
60
- )}
61
- {children}
62
- {errors}
63
- {help}
64
- </div>
66
+ <WrapIfAdditionalTemplate
67
+ classNames={classNames}
68
+ disabled={divProps.disabled}
69
+ id={id}
70
+ label={label}
71
+ onKeyRename={onKeyRename}
72
+ onKeyRenameBlur={onKeyRenameBlur}
73
+ onRemoveProperty={onRemoveProperty}
74
+ readonly={readonly}
75
+ required={required}
76
+ schema={schema}
77
+ uiSchema={uiSchema}
78
+ registry={registry}
79
+ >
80
+ <div className={`field-template mb-3 ${classNames || ''}`} {...divProps}>
81
+ {displayLabel && !isCheckbox && (
82
+ <label htmlFor={id} className='label'>
83
+ <span className='label-text font-medium'>
84
+ {label}
85
+ {required && <span className='text-error ml-1'>*</span>}
86
+ </span>
87
+ </label>
88
+ )}
89
+ {children}
90
+ {errors}
91
+ {help}
92
+ </div>
93
+ </WrapIfAdditionalTemplate>
65
94
  );
66
95
  }
@@ -0,0 +1,15 @@
1
+ import { FormContextType, MultiSchemaFieldTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+
3
+ export default function MultiSchemaFieldTemplate<
4
+ T = any,
5
+ S extends StrictRJSFSchema = RJSFSchema,
6
+ F extends FormContextType = any,
7
+ >(props: MultiSchemaFieldTemplateProps<T, S, F>) {
8
+ const { optionSchemaField, selector } = props;
9
+ return (
10
+ <div className='p-4 border rounded-sm shadow-sm'>
11
+ <div className='mb-4'>{selector}</div>
12
+ {optionSchemaField}
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './MultiSchemaFieldTemplate';
2
+ export * from './MultiSchemaFieldTemplate';
@@ -35,10 +35,11 @@ export default function ObjectFieldTemplate<
35
35
  disabled,
36
36
  readonly,
37
37
  uiSchema,
38
- idSchema,
38
+ fieldPathId,
39
39
  schema,
40
40
  formData,
41
- onAddClick,
41
+ optionalDataControl,
42
+ onAddProperty,
42
43
  registry,
43
44
  } = props;
44
45
  const uiOptions = getUiOptions<T, S, F>(uiSchema);
@@ -48,29 +49,31 @@ export default function ObjectFieldTemplate<
48
49
  registry,
49
50
  uiOptions,
50
51
  );
52
+ const showOptionalDataControlInTitle = !readonly && !disabled;
51
53
  // Button templates are not overridden in the uiSchema
52
54
  const {
53
55
  ButtonTemplates: { AddButton },
54
56
  } = registry.templates;
55
57
 
56
58
  // Check if this is the root object
57
- const isRoot = idSchema.$id === 'root';
59
+ const isRoot = fieldPathId.$id === 'root';
58
60
 
59
61
  return (
60
62
  <div className={`form-control ${isRoot ? 'bg-base-100 p-6 rounded-xl shadow-lg' : ''}`}>
61
63
  {title && (
62
64
  <TitleFieldTemplate
63
- id={titleId<T>(idSchema)}
65
+ id={titleId(fieldPathId)}
64
66
  title={title}
65
67
  required={required}
66
68
  schema={schema}
67
69
  uiSchema={uiSchema}
68
70
  registry={registry}
71
+ optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
69
72
  />
70
73
  )}
71
74
  {description && (
72
75
  <DescriptionFieldTemplate
73
- id={descriptionId<T>(idSchema)}
76
+ id={descriptionId(fieldPathId)}
74
77
  description={description}
75
78
  schema={schema}
76
79
  uiSchema={uiSchema}
@@ -78,13 +81,14 @@ export default function ObjectFieldTemplate<
78
81
  />
79
82
  )}
80
83
  <div className={`grid grid-cols-1 gap-${description ? 3 : 4} ${isRoot ? '' : 'mb-4'}`}>
84
+ {!showOptionalDataControlInTitle ? optionalDataControl : undefined}
81
85
  {properties.map((element, index) =>
82
86
  element.hidden ? (
83
87
  element.content
84
88
  ) : (
85
89
  <div
86
- key={`${idSchema.$id}-${element.name}-${index}`}
87
- className={idSchema.$id === 'root' && element.name === 'tasks' ? 'mt-2' : ''}
90
+ key={`${fieldPathId.$id}-${element.name}-${index}`}
91
+ className={fieldPathId.$id === 'root' && element.name === 'tasks' ? 'mt-2' : ''}
88
92
  >
89
93
  {element.content}
90
94
  </div>
@@ -93,9 +97,9 @@ export default function ObjectFieldTemplate<
93
97
  {canExpand<T, S, F>(schema, uiSchema, formData) && (
94
98
  <div className='flex justify-end'>
95
99
  <AddButton
96
- id={buttonId<T>(idSchema, 'add')}
100
+ id={buttonId(fieldPathId, 'add')}
97
101
  className='rjsf-object-property-expand btn btn-primary btn-sm'
98
- onClick={onAddClick(schema)}
102
+ onClick={onAddProperty}
99
103
  disabled={disabled || readonly}
100
104
  uiSchema={uiSchema}
101
105
  registry={registry}
@@ -0,0 +1,46 @@
1
+ import { faPlus } from '@fortawesome/free-solid-svg-icons';
2
+ import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
3
+ import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
4
+
5
+ import { RemoveButton } from '../ButtonTemplates';
6
+ import DaisyUIButton from '../ButtonTemplates/DaisyUIButton';
7
+
8
+ /** The OptionalDataControlsTemplate renders one of three different states. If
9
+ * there is an `onAddClick()` function, it renders the "Add" button. If there is
10
+ * an `onRemoveClick()` function, it renders the "Remove" button. Otherwise it
11
+ * renders the "No data found" section. All of them use the `label` as either
12
+ * the `title` of buttons or simply outputting it.
13
+ *
14
+ * @param props - The `OptionalDataControlsTemplateProps` for the template
15
+ */
16
+ export default function OptionalDataControlsTemplate<
17
+ T = any,
18
+ S extends StrictRJSFSchema = RJSFSchema,
19
+ F extends FormContextType = any,
20
+ >(props: OptionalDataControlsTemplateProps<T, S, F>) {
21
+ const { id, registry, label, onAddClick, onRemoveClick } = props;
22
+ if (onAddClick) {
23
+ return (
24
+ <DaisyUIButton
25
+ id={id}
26
+ registry={registry}
27
+ iconType='info'
28
+ icon={faPlus as IconDefinition}
29
+ className='rjsf-add-optional-data'
30
+ onClick={onAddClick}
31
+ title={label}
32
+ />
33
+ );
34
+ } else if (onRemoveClick) {
35
+ return (
36
+ <RemoveButton
37
+ id={id}
38
+ registry={registry}
39
+ className='rjsf-remove-optional-data'
40
+ onClick={onRemoveClick}
41
+ title={label}
42
+ />
43
+ );
44
+ }
45
+ return <em id={id}>{label}</em>;
46
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './OptionalDataControlsTemplate';
2
+ export * from './OptionalDataControlsTemplate';
@@ -11,7 +11,9 @@ import FieldErrorTemplate from './FieldErrorTemplate';
11
11
  import FieldHelpTemplate from './FieldHelpTemplate';
12
12
  import FieldTemplate from './FieldTemplate';
13
13
  import GridTemplate from './GridTemplate/GridTemplate';
14
+ import MultiSchemaFieldTemplate from './MultiSchemaFieldTemplate';
14
15
  import ObjectFieldTemplate from './ObjectFieldTemplate';
16
+ import OptionalDataControlsTemplate from './OptionalDataControlsTemplate';
15
17
  import TitleFieldTemplate from './TitleField/TitleField';
16
18
  import WrapIfAdditionalTemplate from './WrapIfAdditionalTemplate';
17
19
 
@@ -53,7 +55,9 @@ export function generateTemplates<
53
55
  FieldHelpTemplate,
54
56
  FieldTemplate,
55
57
  GridTemplate,
58
+ MultiSchemaFieldTemplate,
56
59
  ObjectFieldTemplate,
60
+ OptionalDataControlsTemplate,
57
61
  TitleFieldTemplate,
58
62
  WrapIfAdditionalTemplate,
59
63
  };
@@ -14,13 +14,22 @@ import { TitleFieldProps, StrictRJSFSchema, RJSFSchema, FormContextType, getUiOp
14
14
  export default function TitleField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
15
15
  props: TitleFieldProps<T, S, F>,
16
16
  ) {
17
- const { id, title, uiSchema } = props;
17
+ const { id, title, uiSchema, optionalDataControl } = props;
18
18
  const uiOptions = getUiOptions<T, S, F>(uiSchema);
19
19
 
20
+ let heading = <h2 className='text-3xl font-bold text-primary mb-2'>{uiOptions.title || title}</h2>;
21
+ if (optionalDataControl) {
22
+ heading = (
23
+ <div className='flex'>
24
+ <div className='flex flex-auto'>{heading}</div>
25
+ <div className='flex justify-end'>{optionalDataControl}</div>
26
+ </div>
27
+ );
28
+ }
20
29
  return (
21
30
  <div id={id} className='title-field mb-6'>
22
- <h2 className='text-3xl font-bold text-primary mb-2'>{uiOptions.title || title}</h2>
23
- <div className='divider divider-primary'></div>
31
+ {heading}
32
+ <div className='divider divider-primary my-0'></div>
24
33
  </div>
25
34
  );
26
35
  }