@rjsf/mantine 6.0.0-beta.14

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 (173) hide show
  1. package/README.md +153 -0
  2. package/dist/index.js +1918 -0
  3. package/dist/index.js.map +7 -0
  4. package/dist/mantine.esm.js +1967 -0
  5. package/dist/mantine.esm.js.map +7 -0
  6. package/dist/mantine.umd.js +1714 -0
  7. package/lib/Form/index.d.ts +6 -0
  8. package/lib/Form/index.js +7 -0
  9. package/lib/Form/index.js.map +1 -0
  10. package/lib/Theme/index.d.ts +5 -0
  11. package/lib/Theme/index.js +10 -0
  12. package/lib/Theme/index.js.map +1 -0
  13. package/lib/index.d.ts +6 -0
  14. package/lib/index.js +7 -0
  15. package/lib/index.js.map +1 -0
  16. package/lib/templates/ArrayFieldItemTemplate.d.ts +6 -0
  17. package/lib/templates/ArrayFieldItemTemplate.js +14 -0
  18. package/lib/templates/ArrayFieldItemTemplate.js.map +1 -0
  19. package/lib/templates/ArrayFieldTemplate.d.ts +6 -0
  20. package/lib/templates/ArrayFieldTemplate.js +20 -0
  21. package/lib/templates/ArrayFieldTemplate.js.map +1 -0
  22. package/lib/templates/ArrayFieldTitleTemplate.d.ts +7 -0
  23. package/lib/templates/ArrayFieldTitleTemplate.js +18 -0
  24. package/lib/templates/ArrayFieldTitleTemplate.js.map +1 -0
  25. package/lib/templates/BaseInputTemplate.d.ts +8 -0
  26. package/lib/templates/BaseInputTemplate.js +36 -0
  27. package/lib/templates/BaseInputTemplate.js.map +1 -0
  28. package/lib/templates/ButtonTemplates/AddButton.d.ts +4 -0
  29. package/lib/templates/ButtonTemplates/AddButton.js +11 -0
  30. package/lib/templates/ButtonTemplates/AddButton.js.map +1 -0
  31. package/lib/templates/ButtonTemplates/IconButton.d.ts +8 -0
  32. package/lib/templates/ButtonTemplates/IconButton.js +25 -0
  33. package/lib/templates/ButtonTemplates/IconButton.js.map +1 -0
  34. package/lib/templates/ButtonTemplates/SubmitButton.d.ts +4 -0
  35. package/lib/templates/ButtonTemplates/SubmitButton.js +13 -0
  36. package/lib/templates/ButtonTemplates/SubmitButton.js.map +1 -0
  37. package/lib/templates/ButtonTemplates/index.d.ts +3 -0
  38. package/lib/templates/ButtonTemplates/index.js +15 -0
  39. package/lib/templates/ButtonTemplates/index.js.map +1 -0
  40. package/lib/templates/DescriptionField.d.ts +6 -0
  41. package/lib/templates/DescriptionField.js +15 -0
  42. package/lib/templates/DescriptionField.js.map +1 -0
  43. package/lib/templates/ErrorList.d.ts +6 -0
  44. package/lib/templates/ErrorList.js +13 -0
  45. package/lib/templates/ErrorList.js.map +1 -0
  46. package/lib/templates/FieldErrorTemplate.d.ts +6 -0
  47. package/lib/templates/FieldErrorTemplate.js +16 -0
  48. package/lib/templates/FieldErrorTemplate.js.map +1 -0
  49. package/lib/templates/FieldHelpTemplate.d.ts +6 -0
  50. package/lib/templates/FieldHelpTemplate.js +13 -0
  51. package/lib/templates/FieldHelpTemplate.js.map +1 -0
  52. package/lib/templates/FieldTemplate.d.ts +7 -0
  53. package/lib/templates/FieldTemplate.js +18 -0
  54. package/lib/templates/FieldTemplate.js.map +1 -0
  55. package/lib/templates/GridTemplate.d.ts +7 -0
  56. package/lib/templates/GridTemplate.js +20 -0
  57. package/lib/templates/GridTemplate.js.map +1 -0
  58. package/lib/templates/MultiSchemaFieldTemplate.d.ts +2 -0
  59. package/lib/templates/MultiSchemaFieldTemplate.js +6 -0
  60. package/lib/templates/MultiSchemaFieldTemplate.js.map +1 -0
  61. package/lib/templates/ObjectFieldTemplate.d.ts +8 -0
  62. package/lib/templates/ObjectFieldTemplate.js +24 -0
  63. package/lib/templates/ObjectFieldTemplate.js.map +1 -0
  64. package/lib/templates/TitleField.d.ts +6 -0
  65. package/lib/templates/TitleField.js +11 -0
  66. package/lib/templates/TitleField.js.map +1 -0
  67. package/lib/templates/WrapIfAdditionalTemplate.d.ts +7 -0
  68. package/lib/templates/WrapIfAdditionalTemplate.js +29 -0
  69. package/lib/templates/WrapIfAdditionalTemplate.js.map +1 -0
  70. package/lib/templates/icons.d.ts +11 -0
  71. package/lib/templates/icons.js +20 -0
  72. package/lib/templates/icons.js.map +1 -0
  73. package/lib/templates/index.d.ts +4 -0
  74. package/lib/templates/index.js +36 -0
  75. package/lib/templates/index.js.map +1 -0
  76. package/lib/tsconfig.tsbuildinfo +1 -0
  77. package/lib/utils.d.ts +2 -0
  78. package/lib/utils.js +35 -0
  79. package/lib/utils.js.map +1 -0
  80. package/lib/widgets/CheckboxWidget.d.ts +8 -0
  81. package/lib/widgets/CheckboxWidget.js +33 -0
  82. package/lib/widgets/CheckboxWidget.js.map +1 -0
  83. package/lib/widgets/CheckboxesWidget.d.ts +7 -0
  84. package/lib/widgets/CheckboxesWidget.js +33 -0
  85. package/lib/widgets/CheckboxesWidget.js.map +1 -0
  86. package/lib/widgets/ColorWidget.d.ts +6 -0
  87. package/lib/widgets/ColorWidget.js +28 -0
  88. package/lib/widgets/ColorWidget.js.map +1 -0
  89. package/lib/widgets/DateTime/AltDateTimeWidget.d.ts +13 -0
  90. package/lib/widgets/DateTime/AltDateTimeWidget.js +16 -0
  91. package/lib/widgets/DateTime/AltDateTimeWidget.js.map +1 -0
  92. package/lib/widgets/DateTime/AltDateWidget.d.ts +11 -0
  93. package/lib/widgets/DateTime/AltDateWidget.js +51 -0
  94. package/lib/widgets/DateTime/AltDateWidget.js.map +1 -0
  95. package/lib/widgets/DateTime/DateTimeInput.d.ts +5 -0
  96. package/lib/widgets/DateTime/DateTimeInput.js +39 -0
  97. package/lib/widgets/DateTime/DateTimeInput.js.map +1 -0
  98. package/lib/widgets/DateTime/DateTimeWidget.d.ts +6 -0
  99. package/lib/widgets/DateTime/DateTimeWidget.js +11 -0
  100. package/lib/widgets/DateTime/DateTimeWidget.js.map +1 -0
  101. package/lib/widgets/DateTime/DateWidget.d.ts +6 -0
  102. package/lib/widgets/DateTime/DateWidget.js +11 -0
  103. package/lib/widgets/DateTime/DateWidget.js.map +1 -0
  104. package/lib/widgets/DateTime/TimeWidget.d.ts +6 -0
  105. package/lib/widgets/DateTime/TimeWidget.js +27 -0
  106. package/lib/widgets/DateTime/TimeWidget.js.map +1 -0
  107. package/lib/widgets/DateTime/index.d.ts +5 -0
  108. package/lib/widgets/DateTime/index.js +6 -0
  109. package/lib/widgets/DateTime/index.js.map +1 -0
  110. package/lib/widgets/FileWidget.d.ts +7 -0
  111. package/lib/widgets/FileWidget.js +106 -0
  112. package/lib/widgets/FileWidget.js.map +1 -0
  113. package/lib/widgets/PasswordWidget.d.ts +7 -0
  114. package/lib/widgets/PasswordWidget.js +30 -0
  115. package/lib/widgets/PasswordWidget.js.map +1 -0
  116. package/lib/widgets/RadioWidget.d.ts +7 -0
  117. package/lib/widgets/RadioWidget.js +33 -0
  118. package/lib/widgets/RadioWidget.js.map +1 -0
  119. package/lib/widgets/RangeWidget.d.ts +7 -0
  120. package/lib/widgets/RangeWidget.js +34 -0
  121. package/lib/widgets/RangeWidget.js.map +1 -0
  122. package/lib/widgets/SelectWidget.d.ts +7 -0
  123. package/lib/widgets/SelectWidget.js +45 -0
  124. package/lib/widgets/SelectWidget.js.map +1 -0
  125. package/lib/widgets/TextareaWidget.d.ts +7 -0
  126. package/lib/widgets/TextareaWidget.js +30 -0
  127. package/lib/widgets/TextareaWidget.js.map +1 -0
  128. package/lib/widgets/index.d.ts +4 -0
  129. package/lib/widgets/index.js +34 -0
  130. package/lib/widgets/index.js.map +1 -0
  131. package/package.json +110 -0
  132. package/src/Form/index.ts +15 -0
  133. package/src/Theme/index.ts +18 -0
  134. package/src/index.ts +8 -0
  135. package/src/templates/ArrayFieldItemTemplate.tsx +40 -0
  136. package/src/templates/ArrayFieldTemplate.tsx +103 -0
  137. package/src/templates/ArrayFieldTitleTemplate.tsx +33 -0
  138. package/src/templates/BaseInputTemplate.tsx +134 -0
  139. package/src/templates/ButtonTemplates/AddButton.tsx +17 -0
  140. package/src/templates/ButtonTemplates/IconButton.tsx +87 -0
  141. package/src/templates/ButtonTemplates/SubmitButton.tsx +20 -0
  142. package/src/templates/ButtonTemplates/index.ts +21 -0
  143. package/src/templates/DescriptionField.tsx +24 -0
  144. package/src/templates/ErrorList.tsx +36 -0
  145. package/src/templates/FieldErrorTemplate.tsx +27 -0
  146. package/src/templates/FieldHelpTemplate.tsx +22 -0
  147. package/src/templates/FieldTemplate.tsx +66 -0
  148. package/src/templates/GridTemplate.tsx +30 -0
  149. package/src/templates/MultiSchemaFieldTemplate.tsx +15 -0
  150. package/src/templates/ObjectFieldTemplate.tsx +104 -0
  151. package/src/templates/TitleField.tsx +17 -0
  152. package/src/templates/WrapIfAdditionalTemplate.tsx +99 -0
  153. package/src/templates/icons.tsx +141 -0
  154. package/src/templates/index.ts +43 -0
  155. package/src/tsconfig.json +23 -0
  156. package/src/utils.ts +37 -0
  157. package/src/widgets/CheckboxWidget.tsx +110 -0
  158. package/src/widgets/CheckboxesWidget.tsx +112 -0
  159. package/src/widgets/ColorWidget.tsx +85 -0
  160. package/src/widgets/DateTime/AltDateTimeWidget.tsx +22 -0
  161. package/src/widgets/DateTime/AltDateWidget.tsx +139 -0
  162. package/src/widgets/DateTime/DateTimeInput.tsx +97 -0
  163. package/src/widgets/DateTime/DateTimeWidget.tsx +24 -0
  164. package/src/widgets/DateTime/DateWidget.tsx +22 -0
  165. package/src/widgets/DateTime/TimeWidget.tsx +83 -0
  166. package/src/widgets/DateTime/index.ts +5 -0
  167. package/src/widgets/FileWidget.tsx +176 -0
  168. package/src/widgets/PasswordWidget.tsx +88 -0
  169. package/src/widgets/RadioWidget.tsx +103 -0
  170. package/src/widgets/RangeWidget.tsx +95 -0
  171. package/src/widgets/SelectWidget.tsx +109 -0
  172. package/src/widgets/TextareaWidget.tsx +87 -0
  173. package/src/widgets/index.ts +42 -0
@@ -0,0 +1,139 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import {
3
+ ariaDescribedByIds,
4
+ dateRangeOptions,
5
+ parseDateString,
6
+ toDateString,
7
+ getDateElementProps,
8
+ titleId,
9
+ DateObject,
10
+ type DateElementFormat,
11
+ FormContextType,
12
+ RJSFSchema,
13
+ StrictRJSFSchema,
14
+ TranslatableString,
15
+ WidgetProps,
16
+ } from '@rjsf/utils';
17
+ import { Flex, Box, Group, Button, Select, Input } from '@mantine/core';
18
+
19
+ function readyForChange(state: DateObject) {
20
+ return Object.values(state).every((value) => value !== -1);
21
+ }
22
+
23
+ /** The `AltDateWidget` is an alternative widget for rendering date properties.
24
+ * @param props - The `WidgetProps` for this component
25
+ */
26
+ export default function AltDateWidget<
27
+ T = any,
28
+ S extends StrictRJSFSchema = RJSFSchema,
29
+ F extends FormContextType = any,
30
+ >(props: WidgetProps<T, S, F>) {
31
+ const {
32
+ id,
33
+ value,
34
+ required,
35
+ disabled,
36
+ readonly,
37
+ label,
38
+ hideLabel,
39
+ rawErrors,
40
+ options,
41
+ onChange,
42
+ showTime = false,
43
+ registry,
44
+ } = props;
45
+
46
+ const { translateString } = registry;
47
+ const [state, setState] = useState(parseDateString(value, showTime));
48
+
49
+ useEffect(() => {
50
+ setState(parseDateString(value, showTime));
51
+ }, [showTime, value]);
52
+
53
+ const handleChange = useCallback(
54
+ (property: keyof DateObject, nextValue: any) => {
55
+ const nextState = {
56
+ ...state,
57
+ [property]: typeof nextValue === 'undefined' ? -1 : nextValue,
58
+ };
59
+
60
+ if (readyForChange(nextState)) {
61
+ onChange(toDateString(nextState, showTime));
62
+ } else {
63
+ setState(nextState);
64
+ }
65
+ },
66
+ [state, onChange, showTime],
67
+ );
68
+
69
+ const handleSetNow = useCallback(() => {
70
+ if (!disabled && !readonly) {
71
+ const nextState = parseDateString(new Date().toJSON(), showTime);
72
+ onChange(toDateString(nextState, showTime));
73
+ }
74
+ }, [disabled, readonly, showTime, onChange]);
75
+
76
+ const handleClear = useCallback(() => {
77
+ if (!disabled && !readonly) {
78
+ onChange('');
79
+ }
80
+ }, [disabled, readonly, onChange]);
81
+
82
+ return (
83
+ <>
84
+ {!hideLabel && !!label && (
85
+ <Input.Label id={titleId<T>(id)} required={required}>
86
+ {label}
87
+ </Input.Label>
88
+ )}
89
+ <Flex gap='xs' align='center' wrap='nowrap'>
90
+ {getDateElementProps(
91
+ state,
92
+ showTime,
93
+ options.yearsRange as [number, number] | undefined,
94
+ options.format as DateElementFormat | undefined,
95
+ ).map((elemProps, i) => {
96
+ const elemId = id + '_' + elemProps.type;
97
+ return (
98
+ <Box key={i}>
99
+ <Select
100
+ id={elemId}
101
+ name={elemId}
102
+ placeholder={elemProps.type}
103
+ disabled={disabled || readonly}
104
+ data={dateRangeOptions<S>(elemProps.range[0], elemProps.range[1]).map((item) => item.value.toString())}
105
+ value={!elemProps.value || elemProps.value < 0 ? null : elemProps.value.toString()}
106
+ onChange={(v) => handleChange(elemProps.type as keyof DateObject, v)}
107
+ searchable={false}
108
+ allowDeselect={false}
109
+ comboboxProps={{ withinPortal: false }}
110
+ aria-describedby={ariaDescribedByIds<T>(elemId)}
111
+ />
112
+ </Box>
113
+ );
114
+ })}
115
+ <Group wrap='nowrap' gap={3}>
116
+ {(options.hideNowButton !== 'undefined' ? !options.hideNowButton : true) && (
117
+ <Button variant='subtle' size='xs' onClick={handleSetNow}>
118
+ {translateString(TranslatableString.NowLabel)}
119
+ </Button>
120
+ )}
121
+ {(options.hideClearButton !== 'undefined' ? !options.hideClearButton : true) && (
122
+ <Button variant='subtle' size='xs' onClick={handleClear}>
123
+ {translateString(TranslatableString.ClearLabel)}
124
+ </Button>
125
+ )}
126
+ </Group>
127
+ </Flex>
128
+ {rawErrors &&
129
+ rawErrors?.length > 0 &&
130
+ rawErrors.map((error: string, index: number) => (
131
+ <Input.Error key={`alt-date-widget-input-errors-${index}`}>{error}</Input.Error>
132
+ ))}
133
+ </>
134
+ );
135
+ }
136
+
137
+ AltDateWidget.defaultProps = {
138
+ showTime: false,
139
+ };
@@ -0,0 +1,97 @@
1
+ import { useCallback } from 'react';
2
+ import {
3
+ ariaDescribedByIds,
4
+ FormContextType,
5
+ labelValue,
6
+ RJSFSchema,
7
+ StrictRJSFSchema,
8
+ WidgetProps,
9
+ } from '@rjsf/utils';
10
+ import dayjs from 'dayjs';
11
+ import { DateInput } from '@mantine/dates';
12
+
13
+ const dateParser = (input: string, format: string) => {
14
+ if (!input) {
15
+ return null;
16
+ }
17
+ const d = dayjs(input, format);
18
+ return d.isValid() ? d.toDate() : null;
19
+ };
20
+
21
+ const dateFormat = (date?: Date, format?: string) => {
22
+ if (!date) {
23
+ return '';
24
+ }
25
+ return dayjs(date).format(format || 'YYYY-MM-DD');
26
+ };
27
+
28
+ /** The `DateTimeInput` is a base component that used by other Date-Time widget components.
29
+ * @param props - The `WidgetProps` for this component
30
+ */
31
+ export default function DateTimeInput<
32
+ T = any,
33
+ S extends StrictRJSFSchema = RJSFSchema,
34
+ F extends FormContextType = any,
35
+ >(props: WidgetProps<T, S, F>) {
36
+ const {
37
+ id,
38
+ name,
39
+ value,
40
+ placeholder,
41
+ required,
42
+ disabled,
43
+ readonly,
44
+ autofocus,
45
+ label,
46
+ hideLabel,
47
+ rawErrors,
48
+ options,
49
+ onChange,
50
+ onBlur,
51
+ onFocus,
52
+ valueFormat,
53
+ displayFormat,
54
+ } = props;
55
+
56
+ const handleChange = useCallback(
57
+ (nextValue: any) => {
58
+ onChange(dateFormat(nextValue, valueFormat as string));
59
+ },
60
+ [onChange, valueFormat],
61
+ );
62
+
63
+ const handleBlur = useCallback(() => {
64
+ if (onBlur) {
65
+ onBlur(id, value);
66
+ }
67
+ }, [onBlur, id, value]);
68
+
69
+ const handleFocus = useCallback(() => {
70
+ if (onFocus) {
71
+ onFocus(id, value);
72
+ }
73
+ }, [onFocus, id, value]);
74
+
75
+ return (
76
+ <DateInput
77
+ id={id}
78
+ name={name}
79
+ value={dateParser(value, valueFormat as string)}
80
+ dateParser={(v) => dateParser(v, displayFormat as string)}
81
+ placeholder={placeholder || undefined}
82
+ required={required}
83
+ disabled={disabled || readonly}
84
+ autoFocus={autofocus}
85
+ label={labelValue(label || undefined, hideLabel, false)}
86
+ onChange={handleChange}
87
+ onBlur={handleBlur}
88
+ onFocus={handleFocus}
89
+ error={rawErrors && rawErrors.length > 0 ? rawErrors.join('\n') : undefined}
90
+ {...options}
91
+ aria-describedby={ariaDescribedByIds<T>(id)}
92
+ popoverProps={{ withinPortal: false }}
93
+ classNames={typeof options?.classNames === 'object' ? options.classNames : undefined}
94
+ valueFormat={displayFormat}
95
+ />
96
+ );
97
+ }
@@ -0,0 +1,24 @@
1
+ import { FormContextType, RJSFSchema, StrictRJSFSchema, WidgetProps } from '@rjsf/utils';
2
+
3
+ import DateTimeInput from './DateTimeInput';
4
+
5
+ /** The `DateWidget` component uses the `DateTimeInput` changing the valueFormat to show `datetime`
6
+ *
7
+ * @param props - The `WidgetProps` for this component
8
+ */
9
+ export default function DateTimeWidget<
10
+ T = any,
11
+ S extends StrictRJSFSchema = RJSFSchema,
12
+ F extends FormContextType = any,
13
+ >(props: WidgetProps<T, S, F>) {
14
+ const { valueFormat = 'YYYY-MM-DD HH:mm:ss', displayFormat, ...otherOptions } = props.options;
15
+
16
+ return (
17
+ <DateTimeInput
18
+ {...props}
19
+ options={otherOptions}
20
+ valueFormat={valueFormat}
21
+ displayFormat={displayFormat || valueFormat}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,22 @@
1
+ import { FormContextType, RJSFSchema, StrictRJSFSchema, WidgetProps } from '@rjsf/utils';
2
+
3
+ import DateTimeInput from './DateTimeInput';
4
+
5
+ /** The `DateWidget` component uses the `DateTimeInput` changing the valueFormat to show `date`
6
+ *
7
+ * @param props - The `WidgetProps` for this component
8
+ */
9
+ export default function DateWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
10
+ props: WidgetProps<T, S, F>,
11
+ ) {
12
+ const { valueFormat = 'YYYY-MM-DD', displayFormat, ...otherOptions } = props.options;
13
+
14
+ return (
15
+ <DateTimeInput
16
+ {...props}
17
+ options={otherOptions}
18
+ valueFormat={valueFormat}
19
+ displayFormat={displayFormat || valueFormat}
20
+ />
21
+ );
22
+ }
@@ -0,0 +1,83 @@
1
+ import { ChangeEvent, FocusEvent, useCallback } from 'react';
2
+ import {
3
+ FormContextType,
4
+ RJSFSchema,
5
+ StrictRJSFSchema,
6
+ WidgetProps,
7
+ labelValue,
8
+ ariaDescribedByIds,
9
+ } from '@rjsf/utils';
10
+ import { TimeInput } from '@mantine/dates';
11
+
12
+ /** The `TimeWidget` component uses the `TimeInput` component from `@mantine/dates` for rendering.
13
+ *
14
+ * @param props - The `WidgetProps` for this component
15
+ */
16
+ export default function TimeWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
17
+ props: WidgetProps<T, S, F>,
18
+ ) {
19
+ const {
20
+ id,
21
+ name,
22
+ value,
23
+ placeholder,
24
+ required,
25
+ disabled,
26
+ readonly,
27
+ autofocus,
28
+ label,
29
+ hideLabel,
30
+ rawErrors,
31
+ options,
32
+ onChange,
33
+ onBlur,
34
+ onFocus,
35
+ } = props;
36
+
37
+ const emptyValue = options.emptyValue || '';
38
+
39
+ const handleChange = useCallback(
40
+ (e: ChangeEvent<HTMLInputElement>) => {
41
+ onChange(e.target.value === '' ? emptyValue : e.target.value);
42
+ },
43
+ [onChange, emptyValue],
44
+ );
45
+
46
+ const handleBlur = useCallback(
47
+ ({ target }: FocusEvent<HTMLInputElement>) => {
48
+ if (onBlur) {
49
+ onBlur(id, target && target.value);
50
+ }
51
+ },
52
+ [onBlur, id],
53
+ );
54
+
55
+ const handleFocus = useCallback(
56
+ ({ target }: FocusEvent<HTMLInputElement>) => {
57
+ if (onFocus) {
58
+ onFocus(id, target && target.value);
59
+ }
60
+ },
61
+ [onFocus, id],
62
+ );
63
+
64
+ return (
65
+ <TimeInput
66
+ id={id}
67
+ name={name}
68
+ value={value || ''}
69
+ placeholder={placeholder || undefined}
70
+ required={required}
71
+ disabled={disabled || readonly}
72
+ autoFocus={autofocus}
73
+ label={labelValue(label || undefined, hideLabel, false)}
74
+ onChange={handleChange}
75
+ onBlur={handleBlur}
76
+ onFocus={handleFocus}
77
+ error={rawErrors && rawErrors.length > 0 ? rawErrors.join('\n') : undefined}
78
+ {...options}
79
+ aria-describedby={ariaDescribedByIds<T>(id)}
80
+ classNames={typeof options?.classNames === 'object' ? options.classNames : undefined}
81
+ />
82
+ );
83
+ }
@@ -0,0 +1,5 @@
1
+ export { default as AltDateTimeWidget } from './AltDateTimeWidget';
2
+ export { default as AltDateWidget } from './AltDateWidget';
3
+ export { default as DateWidget } from './DateWidget';
4
+ export { default as DateTimeWidget } from './DateTimeWidget';
5
+ export { default as TimeWidget } from './TimeWidget';
@@ -0,0 +1,176 @@
1
+ import { useCallback } from 'react';
2
+ import {
3
+ dataURItoBlob,
4
+ ariaDescribedByIds,
5
+ FormContextType,
6
+ labelValue,
7
+ RJSFSchema,
8
+ StrictRJSFSchema,
9
+ WidgetProps,
10
+ } from '@rjsf/utils';
11
+ import { FileInput, Pill } from '@mantine/core';
12
+
13
+ import { cleanupOptions } from '../utils';
14
+
15
+ function addNameToDataURL(dataURL: string, name: string) {
16
+ if (dataURL === null) {
17
+ return null;
18
+ }
19
+ return dataURL.replace(';base64', `;name=${encodeURIComponent(name)};base64`);
20
+ }
21
+
22
+ type FileInfoType = {
23
+ dataURL?: string | null;
24
+ name: string;
25
+ size: number;
26
+ type: string;
27
+ };
28
+
29
+ function processFile(file: File): Promise<FileInfoType> {
30
+ const { name, size, type } = file;
31
+ return new Promise((resolve, reject) => {
32
+ const reader = new window.FileReader();
33
+ reader.onerror = reject;
34
+ reader.onload = (event) => {
35
+ if (typeof event.target?.result === 'string') {
36
+ resolve({
37
+ dataURL: addNameToDataURL(event.target.result, name),
38
+ name,
39
+ size,
40
+ type,
41
+ });
42
+ } else {
43
+ resolve({
44
+ dataURL: null,
45
+ name,
46
+ size,
47
+ type,
48
+ });
49
+ }
50
+ };
51
+ reader.readAsDataURL(file);
52
+ });
53
+ }
54
+
55
+ function processFiles(files: FileList) {
56
+ return Promise.all(Array.from(files).map(processFile));
57
+ }
58
+
59
+ function extractFileInfo(dataURLs: string[]): FileInfoType[] {
60
+ return dataURLs.reduce((acc, dataURL) => {
61
+ if (!dataURL) {
62
+ return acc;
63
+ }
64
+ try {
65
+ const { blob, name } = dataURItoBlob(dataURL);
66
+ return [
67
+ ...acc,
68
+ {
69
+ dataURL,
70
+ name: name,
71
+ size: blob.size,
72
+ type: blob.type,
73
+ },
74
+ ];
75
+ } catch (e) {
76
+ console.log(e);
77
+ // Invalid dataURI, so just ignore it.
78
+ return acc;
79
+ }
80
+ }, [] as FileInfoType[]);
81
+ }
82
+
83
+ /**
84
+ * The `FileWidget` is a widget for rendering file upload fields.
85
+ *
86
+ * @param props - The `WidgetProps` for this component
87
+ */
88
+ export default function FileWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
89
+ props: WidgetProps<T, S, F>,
90
+ ) {
91
+ const {
92
+ id,
93
+ name,
94
+ value,
95
+ placeholder,
96
+ required,
97
+ disabled,
98
+ readonly,
99
+ autofocus,
100
+ label,
101
+ hideLabel,
102
+ rawErrors,
103
+ options,
104
+ multiple,
105
+ onChange,
106
+ } = props;
107
+
108
+ const themeProps = cleanupOptions(options);
109
+
110
+ const handleChange = useCallback(
111
+ (files: any) => {
112
+ if (typeof files === 'object') {
113
+ processFiles(multiple ? files : [files]).then((filesInfoEvent) => {
114
+ const newValue = filesInfoEvent.map((fileInfo) => fileInfo.dataURL);
115
+ if (multiple) {
116
+ onChange(value.concat(newValue));
117
+ } else {
118
+ onChange(newValue[0]);
119
+ }
120
+ });
121
+ }
122
+ return;
123
+ },
124
+ [multiple, value, onChange],
125
+ );
126
+
127
+ const handleRemoveFile = useCallback(
128
+ (index: number) => {
129
+ if (multiple) {
130
+ const newValue = value.filter((_: any, i: number) => i !== index);
131
+ onChange(newValue);
132
+ } else {
133
+ onChange(undefined);
134
+ }
135
+ },
136
+ [multiple, value, onChange],
137
+ );
138
+
139
+ const ValueComponent = useCallback(
140
+ (props: any) => {
141
+ const filesInfo = props.value ? extractFileInfo(Array.isArray(props.value) ? props.value : [props.value]) : null;
142
+ if (Array.isArray(filesInfo) && filesInfo.length > 0) {
143
+ return (
144
+ <Pill.Group>
145
+ {filesInfo.map((file, index) => (
146
+ <Pill key={index} withRemoveButton onRemove={() => handleRemoveFile(index)}>
147
+ {file.name}
148
+ </Pill>
149
+ ))}
150
+ </Pill.Group>
151
+ );
152
+ }
153
+ return null;
154
+ },
155
+ [handleRemoveFile],
156
+ );
157
+
158
+ return (
159
+ <FileInput
160
+ id={id}
161
+ name={name}
162
+ value={value || ''}
163
+ placeholder={placeholder || undefined}
164
+ required={required}
165
+ disabled={disabled || readonly}
166
+ autoFocus={autofocus}
167
+ label={labelValue(label || undefined, hideLabel, false)}
168
+ multiple={!!multiple}
169
+ valueComponent={ValueComponent}
170
+ onChange={handleChange}
171
+ error={rawErrors && rawErrors.length > 0 ? rawErrors.join('\n') : undefined}
172
+ {...themeProps}
173
+ aria-describedby={ariaDescribedByIds<T>(id)}
174
+ />
175
+ );
176
+ }
@@ -0,0 +1,88 @@
1
+ import { ChangeEvent, FocusEvent, useCallback } from 'react';
2
+ import {
3
+ ariaDescribedByIds,
4
+ FormContextType,
5
+ labelValue,
6
+ RJSFSchema,
7
+ StrictRJSFSchema,
8
+ WidgetProps,
9
+ } from '@rjsf/utils';
10
+ import { PasswordInput } from '@mantine/core';
11
+
12
+ import { cleanupOptions } from '../utils';
13
+
14
+ /**
15
+ * The `PasswordWidget` component renders a password input element.
16
+ *
17
+ * @param props - The `WidgetProps` for this component
18
+ */
19
+ export default function PasswordWidget<
20
+ T = any,
21
+ S extends StrictRJSFSchema = RJSFSchema,
22
+ F extends FormContextType = any,
23
+ >(props: WidgetProps<T, S, F>) {
24
+ const {
25
+ id,
26
+ name,
27
+ value,
28
+ placeholder,
29
+ required,
30
+ disabled,
31
+ readonly,
32
+ autofocus,
33
+ label,
34
+ hideLabel,
35
+ rawErrors,
36
+ options,
37
+ onChange,
38
+ onBlur,
39
+ onFocus,
40
+ } = props;
41
+
42
+ const emptyValue = options.emptyValue || '';
43
+ const themeProps = cleanupOptions(options);
44
+
45
+ const handleChange = useCallback(
46
+ (e: ChangeEvent<HTMLInputElement>) => {
47
+ onChange(e.target.value === '' ? emptyValue : e.target.value);
48
+ },
49
+ [onChange, emptyValue],
50
+ );
51
+
52
+ const handleBlur = useCallback(
53
+ ({ target }: FocusEvent<HTMLInputElement>) => {
54
+ if (onBlur) {
55
+ onBlur(id, target && target.value);
56
+ }
57
+ },
58
+ [onBlur, id],
59
+ );
60
+
61
+ const handleFocus = useCallback(
62
+ ({ target }: FocusEvent<HTMLInputElement>) => {
63
+ if (onFocus) {
64
+ onFocus(id, target && target.value);
65
+ }
66
+ },
67
+ [onFocus, id],
68
+ );
69
+
70
+ return (
71
+ <PasswordInput
72
+ id={id}
73
+ name={name}
74
+ value={value || ''}
75
+ placeholder={placeholder || undefined}
76
+ required={required}
77
+ disabled={disabled || readonly}
78
+ autoFocus={autofocus}
79
+ label={labelValue(label || undefined, hideLabel, false)}
80
+ onChange={handleChange}
81
+ onBlur={handleBlur}
82
+ onFocus={handleFocus}
83
+ error={rawErrors && rawErrors.length > 0 ? rawErrors.join('\n') : undefined}
84
+ {...themeProps}
85
+ aria-describedby={ariaDescribedByIds<T>(id)}
86
+ />
87
+ );
88
+ }