@byline/ui 2.2.9 → 2.3.0

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 (41) hide show
  1. package/dist/fields/field-renderer.js +2 -1
  2. package/dist/fields/file/file-field.d.ts +4 -2
  3. package/dist/fields/file/file-field.js +182 -81
  4. package/dist/fields/file/file-field.module.js +10 -5
  5. package/dist/fields/file/file-field_module.css +99 -32
  6. package/dist/fields/file/file-upload-field.d.ts +21 -0
  7. package/dist/fields/file/file-upload-field.js +128 -0
  8. package/dist/fields/file/file-upload-field.module.js +15 -0
  9. package/dist/fields/file/file-upload-field_module.css +74 -0
  10. package/dist/fields/image/image-field.js +33 -17
  11. package/dist/fields/image/image-field.module.js +1 -0
  12. package/dist/fields/image/image-field_module.css +23 -10
  13. package/dist/fields/relation/relation-field.js +37 -24
  14. package/dist/fields/relation/relation-field.module.js +1 -1
  15. package/dist/fields/relation/relation-field_module.css +16 -16
  16. package/dist/forms/form-context.d.ts +11 -0
  17. package/dist/forms/form-context.js +47 -3
  18. package/dist/forms/form-renderer.js +5 -3
  19. package/dist/forms/form-renderer_module.css +1 -2
  20. package/dist/icons/index.d.ts +1 -0
  21. package/dist/icons/index.js +1 -0
  22. package/dist/icons/video-icon.d.ts +6 -0
  23. package/dist/icons/video-icon.js +36 -0
  24. package/dist/react.d.ts +1 -0
  25. package/dist/react.js +1 -0
  26. package/package.json +5 -4
  27. package/src/fields/field-renderer.tsx +1 -0
  28. package/src/fields/file/file-field.module.css +114 -49
  29. package/src/fields/file/file-field.tsx +220 -56
  30. package/src/fields/file/file-upload-field.module.css +101 -0
  31. package/src/fields/file/file-upload-field.tsx +183 -0
  32. package/src/fields/image/image-field.module.css +27 -13
  33. package/src/fields/image/image-field.tsx +35 -12
  34. package/src/fields/relation/relation-field.module.css +21 -21
  35. package/src/fields/relation/relation-field.tsx +24 -20
  36. package/src/forms/form-context.tsx +73 -0
  37. package/src/forms/form-renderer.module.css +1 -2
  38. package/src/forms/form-renderer.tsx +9 -2
  39. package/src/icons/index.ts +1 -0
  40. package/src/icons/video-icon.tsx +32 -0
  41. package/src/react.ts +1 -0
@@ -137,7 +137,8 @@ const FieldRenderer = ({ field, defaultValue, basePath, disableSorting, hideLabe
137
137
  } : field,
138
138
  defaultValue: defaultValue,
139
139
  onChange: handleChange,
140
- path: path
140
+ path: path,
141
+ collectionPath: collectionPath
141
142
  });
142
143
  case 'image':
143
144
  return /*#__PURE__*/ jsx(ImageField, {
@@ -5,13 +5,15 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- import type { FileField as FieldType, StoredFileValue } from '@byline/core';
8
+ import { type FileField as FieldType, type StoredFileValue } from '@byline/core';
9
9
  interface FileFieldProps {
10
10
  field: FieldType;
11
+ /** Collection path required to call the /upload endpoint. */
12
+ collectionPath?: string;
11
13
  value?: StoredFileValue | null;
12
14
  defaultValue?: StoredFileValue | null;
13
15
  onChange?: (value: StoredFileValue | null) => void;
14
16
  path?: string;
15
17
  }
16
- export declare const FileField: ({ field, value, defaultValue, onChange: _onChange, path, }: FileFieldProps) => import("react").JSX.Element;
18
+ export declare const FileField: ({ field, collectionPath, value, defaultValue, onChange: _onChange, path, }: FileFieldProps) => import("react").JSX.Element;
17
19
  export {};
@@ -1,120 +1,221 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { isPendingStoredFileValue } from "@byline/core";
2
3
  import classnames from "classnames";
3
- import { useFieldError, useFieldValue, useIsDirty } from "../../forms/form-context.js";
4
- import { ErrorText } from "../../uikit.js";
4
+ import { IconButton } from "../../components/button/icon-button.js";
5
+ import { useFieldError, useFieldValue, useFormContext, useIsDirty, useIsFieldUploading } from "../../forms/form-context.js";
6
+ import { CloseIcon } from "../../icons/close-icon.js";
7
+ import { DocumentIcon } from "../../icons/document-icon.js";
8
+ import { DownloadIcon } from "../../icons/download-icon.js";
9
+ import { VideoIcon } from "../../icons/video-icon.js";
10
+ import { ErrorText, HelpText, Label, LoaderRing } from "../../uikit.js";
11
+ import { useFieldChangeHandler } from "../use-field-change-handler.js";
5
12
  import file_field_module from "./file-field.module.js";
6
- const FileField = ({ field, value, defaultValue, onChange: _onChange, path })=>{
13
+ import { FileUploadField } from "./file-upload-field.js";
14
+ function triggerDownload(url, filename) {
15
+ if ("u" < typeof document) return;
16
+ const a = document.createElement('a');
17
+ a.href = url;
18
+ if (filename) a.download = filename;
19
+ a.target = '_blank';
20
+ a.rel = 'noreferrer';
21
+ document.body.appendChild(a);
22
+ a.click();
23
+ document.body.removeChild(a);
24
+ }
25
+ const FileField = ({ field, collectionPath, value, defaultValue, onChange: _onChange, path })=>{
7
26
  const fieldPath = path ?? field.name;
8
27
  const fieldError = useFieldError(fieldPath);
9
28
  const isDirty = useIsDirty(fieldPath);
10
29
  const fieldValue = useFieldValue(fieldPath);
11
- const incomingValue = value ?? fieldValue ?? defaultValue ?? null;
12
- const isPlaceholderStoredFileValue = (v)=>{
30
+ const isUploading = useIsFieldUploading(fieldPath);
31
+ const { removePendingUpload } = useFormContext();
32
+ const handleChange = useFieldChangeHandler(field, fieldPath);
33
+ const incomingValue = isDirty ? fieldValue ?? null : value ?? fieldValue ?? defaultValue ?? null;
34
+ const isPending = isPendingStoredFileValue(incomingValue);
35
+ const isOldPlaceholder = (v)=>{
13
36
  if (!v || 'object' != typeof v) return false;
14
37
  const maybe = v;
15
38
  return 'placeholder' === maybe.storageProvider && 'pending' === maybe.storagePath;
16
39
  };
17
- const effectiveValue = isPlaceholderStoredFileValue(incomingValue) ? null : incomingValue;
40
+ const showUploadWidget = null == incomingValue || isOldPlaceholder(incomingValue);
41
+ const handleRemove = ()=>{
42
+ if (isPending) removePendingUpload(fieldPath);
43
+ handleChange(null);
44
+ };
45
+ const isVideo = incomingValue?.mimeType?.startsWith('video/') === true;
46
+ const FileGlyph = isVideo ? VideoIcon : DocumentIcon;
47
+ const htmlId = fieldPath;
18
48
  return /*#__PURE__*/ jsxs("div", {
19
- className: classnames('byline-field-file', field.name, isDirty && [
20
- 'byline-field-file-dirty',
21
- file_field_module.dirty
22
- ]),
49
+ className: `byline-field-file ${field.name}`,
23
50
  children: [
24
- /*#__PURE__*/ jsxs("div", {
51
+ /*#__PURE__*/ jsx("div", {
25
52
  className: classnames('byline-field-file-header', file_field_module.header),
26
- children: [
27
- /*#__PURE__*/ jsxs("div", {
28
- children: [
29
- /*#__PURE__*/ jsxs("div", {
30
- className: classnames('byline-field-file-label', file_field_module.label),
31
- children: [
32
- field.label ?? field.name,
33
- field.optional ? '' : ' *'
34
- ]
35
- }),
36
- field.helpText && /*#__PURE__*/ jsx("div", {
37
- className: classnames('byline-field-file-help', file_field_module.help),
38
- children: field.helpText
39
- })
40
- ]
41
- }),
42
- /*#__PURE__*/ jsx("button", {
43
- type: "button",
44
- className: classnames('byline-field-file-action', file_field_module.action),
45
- disabled: true,
46
- children: "Upload (coming soon)"
47
- })
48
- ]
53
+ children: /*#__PURE__*/ jsx(Label, {
54
+ id: htmlId,
55
+ htmlFor: htmlId,
56
+ label: field.label ?? field.name,
57
+ required: !field.optional
58
+ })
49
59
  }),
50
- null == effectiveValue ? /*#__PURE__*/ jsx("div", {
60
+ showUploadWidget ? collectionPath ? /*#__PURE__*/ jsx(FileUploadField, {
61
+ field: field,
62
+ collectionPath: collectionPath,
63
+ fieldPath: fieldPath,
64
+ onUploaded: (uploaded)=>{
65
+ handleChange(uploaded);
66
+ }
67
+ }) : /*#__PURE__*/ jsx("div", {
51
68
  className: classnames('byline-field-file-empty', file_field_module.empty),
52
69
  children: "No file selected"
53
70
  }) : /*#__PURE__*/ jsxs("div", {
54
- className: classnames('byline-field-file-meta', file_field_module.meta),
71
+ className: classnames('byline-field-file-tile', file_field_module.tile),
55
72
  children: [
56
- /*#__PURE__*/ jsxs("div", {
57
- children: [
58
- /*#__PURE__*/ jsx("span", {
59
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
60
- children: "Filename:"
61
- }),
62
- ' ',
63
- effectiveValue.filename
64
- ]
73
+ isUploading && /*#__PURE__*/ jsx("div", {
74
+ className: classnames('byline-field-file-uploading', file_field_module.uploading),
75
+ "aria-live": "polite",
76
+ "aria-busy": "true",
77
+ children: /*#__PURE__*/ jsx(LoaderRing, {})
65
78
  }),
66
- /*#__PURE__*/ jsxs("div", {
79
+ collectionPath && /*#__PURE__*/ jsxs("div", {
80
+ className: classnames('byline-field-file-actions', file_field_module.actions),
67
81
  children: [
68
- /*#__PURE__*/ jsx("span", {
69
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
70
- children: "Original:"
82
+ !isPending && incomingValue?.storageUrl && /*#__PURE__*/ jsx(IconButton, {
83
+ type: "button",
84
+ intent: "noeffect",
85
+ onClick: ()=>triggerDownload(incomingValue.storageUrl, incomingValue.originalFilename ?? incomingValue.filename),
86
+ size: "xs",
87
+ disabled: isUploading,
88
+ "aria-label": "Download file",
89
+ children: /*#__PURE__*/ jsx(DownloadIcon, {
90
+ width: "15px",
91
+ height: "15px"
92
+ })
71
93
  }),
72
- ' ',
73
- effectiveValue.originalFilename
94
+ /*#__PURE__*/ jsx(IconButton, {
95
+ type: "button",
96
+ intent: "noeffect",
97
+ onClick: handleRemove,
98
+ size: "xs",
99
+ disabled: isUploading,
100
+ "aria-label": "Remove file",
101
+ children: /*#__PURE__*/ jsx(CloseIcon, {
102
+ width: "15px",
103
+ height: "15px"
104
+ })
105
+ })
74
106
  ]
75
107
  }),
76
- /*#__PURE__*/ jsxs("div", {
108
+ !isPending && incomingValue?.storageUrl ? /*#__PURE__*/ jsx("a", {
109
+ href: incomingValue.storageUrl,
110
+ target: "_blank",
111
+ rel: "noreferrer",
112
+ "aria-label": `Open ${incomingValue.originalFilename ?? incomingValue.filename} in a new tab`,
113
+ className: classnames('byline-field-file-icon-wrap', file_field_module["icon-wrap"]),
114
+ children: /*#__PURE__*/ jsx(FileGlyph, {
115
+ width: "48px",
116
+ height: "48px",
117
+ className: classnames('byline-field-file-icon', file_field_module.icon)
118
+ })
119
+ }) : /*#__PURE__*/ jsxs("div", {
120
+ className: classnames('byline-field-file-icon-wrap', file_field_module["icon-wrap"]),
77
121
  children: [
78
- /*#__PURE__*/ jsx("span", {
79
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
80
- children: "Type:"
122
+ /*#__PURE__*/ jsx(FileGlyph, {
123
+ width: "48px",
124
+ height: "48px",
125
+ className: classnames('byline-field-file-icon', file_field_module.icon)
81
126
  }),
82
- ' ',
83
- effectiveValue.mimeType
127
+ isPending && /*#__PURE__*/ jsx("div", {
128
+ className: classnames('byline-field-file-pending', file_field_module.pending),
129
+ children: "Pending upload"
130
+ })
84
131
  ]
85
132
  }),
86
133
  /*#__PURE__*/ jsxs("div", {
134
+ className: classnames('byline-field-file-meta', file_field_module.meta),
87
135
  children: [
88
- /*#__PURE__*/ jsx("span", {
89
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
90
- children: "Size:"
136
+ /*#__PURE__*/ jsxs("div", {
137
+ children: [
138
+ /*#__PURE__*/ jsx("span", {
139
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
140
+ children: "Filename:"
141
+ }),
142
+ ' ',
143
+ incomingValue?.filename
144
+ ]
91
145
  }),
92
- ' ',
93
- effectiveValue.fileSize
94
- ]
95
- }),
96
- /*#__PURE__*/ jsxs("div", {
97
- children: [
98
- /*#__PURE__*/ jsx("span", {
99
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
100
- children: "Storage:"
146
+ /*#__PURE__*/ jsxs("div", {
147
+ children: [
148
+ /*#__PURE__*/ jsx("span", {
149
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
150
+ children: "Original:"
151
+ }),
152
+ ' ',
153
+ incomingValue?.originalFilename
154
+ ]
101
155
  }),
102
- ' ',
103
- effectiveValue.storageProvider
104
- ]
105
- }),
106
- /*#__PURE__*/ jsxs("div", {
107
- children: [
108
- /*#__PURE__*/ jsx("span", {
109
- className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
110
- children: "Path:"
156
+ /*#__PURE__*/ jsxs("div", {
157
+ children: [
158
+ /*#__PURE__*/ jsx("span", {
159
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
160
+ children: "Type:"
161
+ }),
162
+ ' ',
163
+ incomingValue?.mimeType
164
+ ]
165
+ }),
166
+ /*#__PURE__*/ jsxs("div", {
167
+ children: [
168
+ /*#__PURE__*/ jsx("span", {
169
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
170
+ children: "Size:"
171
+ }),
172
+ ' ',
173
+ incomingValue?.fileSize
174
+ ]
111
175
  }),
112
- ' ',
113
- effectiveValue.storagePath
176
+ isPending ? /*#__PURE__*/ jsxs("div", {
177
+ children: [
178
+ /*#__PURE__*/ jsx("span", {
179
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
180
+ children: "Status:"
181
+ }),
182
+ ' ',
183
+ /*#__PURE__*/ jsx("span", {
184
+ className: classnames('byline-field-file-meta-pending', file_field_module["meta-pending"]),
185
+ children: "Will upload on save"
186
+ })
187
+ ]
188
+ }) : /*#__PURE__*/ jsxs(Fragment, {
189
+ children: [
190
+ /*#__PURE__*/ jsxs("div", {
191
+ children: [
192
+ /*#__PURE__*/ jsx("span", {
193
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
194
+ children: "Storage:"
195
+ }),
196
+ ' ',
197
+ incomingValue?.storageProvider
198
+ ]
199
+ }),
200
+ /*#__PURE__*/ jsxs("div", {
201
+ children: [
202
+ /*#__PURE__*/ jsx("span", {
203
+ className: classnames('byline-field-file-meta-key', file_field_module["meta-key"]),
204
+ children: "Path:"
205
+ }),
206
+ ' ',
207
+ incomingValue?.storagePath
208
+ ]
209
+ })
210
+ ]
211
+ })
114
212
  ]
115
213
  })
116
214
  ]
117
215
  }),
216
+ field.helpText && /*#__PURE__*/ jsx(HelpText, {
217
+ text: field.helpText
218
+ }),
118
219
  fieldError && /*#__PURE__*/ jsx(ErrorText, {
119
220
  id: `${field.name}-error`,
120
221
  text: fieldError
@@ -1,13 +1,18 @@
1
1
  import "./file-field_module.css";
2
2
  const file_field_module = {
3
- dirty: "dirty-k9iSNW",
4
3
  header: "header-4BiMwv",
5
- label: "label-UvOUA0",
6
- help: "help-LIWT7a",
7
- action: "action-O9bmDz",
4
+ actions: "actions-Yd3WIq",
8
5
  empty: "empty-Afgknj",
6
+ tile: "tile-K1K1D_",
7
+ uploading: "uploading-KCIPa6",
8
+ "icon-wrap": "icon-wrap-TckWPs",
9
+ iconWrap: "icon-wrap-TckWPs",
10
+ icon: "icon-HnknJj",
11
+ pending: "pending-mh5ZKa",
9
12
  meta: "meta-mm1UmQ",
10
13
  "meta-key": "meta-key-q6cipk",
11
- metaKey: "meta-key-q6cipk"
14
+ metaKey: "meta-key-q6cipk",
15
+ "meta-pending": "meta-pending-Q0ICzl",
16
+ metaPending: "meta-pending-Q0ICzl"
12
17
  };
13
18
  export default file_field_module;
@@ -1,60 +1,123 @@
1
- :is(.dirty-k9iSNW, .byline-field-file-dirty) {
2
- padding: var(--spacing-12);
3
- border: var(--border-width-thin) var(--border-style-solid) var(--blue-300);
4
- border-radius: var(--border-radius-md);
5
- }
6
-
7
1
  :is(.header-4BiMwv, .byline-field-file-header) {
8
- justify-content: space-between;
9
2
  align-items: baseline;
3
+ gap: var(--spacing-8);
10
4
  margin-bottom: .25rem;
11
5
  display: flex;
12
6
  }
13
7
 
14
- :is(.label-UvOUA0, .byline-field-file-label) {
15
- color: var(--gray-100);
16
- font-size: var(--font-size-sm);
17
- font-weight: var(--font-weight-medium);
8
+ :is(.actions-Yd3WIq, .byline-field-file-actions) {
9
+ top: var(--spacing-6);
10
+ right: var(--spacing-6);
11
+ z-index: 1;
12
+ align-items: center;
13
+ gap: var(--spacing-4);
14
+ display: flex;
15
+ position: absolute;
18
16
  }
19
17
 
20
- :is(.help-LIWT7a, .byline-field-file-help) {
21
- color: var(--gray-400);
22
- font-size: var(--font-size-xs);
23
- margin-top: .125rem;
18
+ .byline-field-file-actions .byline-button {
19
+ color: var(--gray-900);
24
20
  }
25
21
 
26
- :is(.action-O9bmDz, .byline-field-file-action) {
27
- color: var(--blue-300);
22
+ :is(.dark .byline-field-file-actions .byline-button, [data-theme="dark"] .byline-field-file-actions .byline-button) {
23
+ color: var(--gray-200);
24
+ }
25
+
26
+ :is(.empty-Afgknj, .byline-field-file-empty) {
27
+ color: var(--gray-500);
28
28
  font-size: var(--font-size-xs);
29
+ font-style: italic;
30
+ }
31
+
32
+ :is(.tile-K1K1D_, .byline-field-file-tile) {
33
+ gap: var(--spacing-16);
34
+ padding: var(--spacing-8);
35
+ border: var(--border-width-thin) var(--border-style-solid) var(--primary-500);
36
+ border-radius: var(--border-radius-md);
37
+ margin-top: .25rem;
38
+ display: flex;
39
+ position: relative;
40
+ }
41
+
42
+ :is(.uploading-KCIPa6, .byline-field-file-uploading) {
43
+ z-index: 2;
44
+ background-color: oklch(from var(--gray-950) l c h / .5);
45
+ border-radius: var(--border-radius-md);
46
+ justify-content: center;
47
+ align-items: center;
48
+ display: flex;
49
+ position: absolute;
50
+ inset: 0;
51
+ }
52
+
53
+ :is(.icon-wrap-TckWPs, .byline-field-file-icon-wrap) {
54
+ border: var(--border-width-thin) var(--border-style-solid) var(--gray-600);
55
+ border-radius: var(--border-radius-sm);
56
+ width: 4rem;
57
+ height: 4rem;
58
+ color: var(--gray-300);
59
+ flex-shrink: 0;
60
+ justify-content: center;
61
+ align-self: flex-start;
62
+ align-items: center;
63
+ display: flex;
64
+ position: relative;
65
+ }
66
+
67
+ a.icon-wrap-TckWPs {
29
68
  cursor: pointer;
30
- background: none;
31
- border: none;
32
- padding: 0;
69
+ text-decoration: none;
70
+ transition: border-color .12s, color .12s;
33
71
  }
34
72
 
35
- :is(.action-O9bmDz:hover, .byline-field-file-action:hover) {
36
- color: var(--blue-200);
37
- text-underline-offset: 2px;
38
- text-decoration: underline;
73
+ a.byline-field-file-icon-wrap {
74
+ cursor: pointer;
75
+ text-decoration: none;
76
+ transition: border-color .12s, color .12s;
39
77
  }
40
78
 
41
- :is(.action-O9bmDz:disabled, .byline-field-file-action:disabled) {
42
- cursor: not-allowed;
43
- opacity: .6;
79
+ a.icon-wrap-TckWPs:hover {
80
+ border-color: var(--primary-500);
81
+ color: var(--primary-400);
44
82
  }
45
83
 
46
- :is(.empty-Afgknj, .byline-field-file-empty) {
47
- color: var(--gray-500);
48
- font-size: var(--font-size-xs);
49
- font-style: italic;
84
+ a.byline-field-file-icon-wrap:hover {
85
+ border-color: var(--primary-500);
86
+ color: var(--primary-400);
87
+ }
88
+
89
+ a.icon-wrap-TckWPs:focus-visible {
90
+ outline: 2px solid var(--primary-500);
91
+ outline-offset: 2px;
92
+ }
93
+
94
+ a.byline-field-file-icon-wrap:focus-visible {
95
+ outline: 2px solid var(--primary-500);
96
+ outline-offset: 2px;
97
+ }
98
+
99
+ :is(.icon-HnknJj, .byline-field-file-icon) {
100
+ opacity: .85;
101
+ }
102
+
103
+ :is(.pending-mh5ZKa, .byline-field-file-pending) {
104
+ background-color: oklch(from var(--yellow-600) l c h / .9);
105
+ color: var(--yellow-100);
106
+ font-size: .6rem;
107
+ font-weight: var(--font-weight-medium);
108
+ border-radius: var(--border-radius-sm);
109
+ padding: .125rem .375rem;
110
+ position: absolute;
111
+ top: .25rem;
112
+ left: .25rem;
50
113
  }
51
114
 
52
115
  :is(.meta-mm1UmQ, .byline-field-file-meta) {
116
+ padding-right: var(--spacing-32);
53
117
  color: var(--gray-200);
54
118
  font-size: var(--font-size-xs);
55
119
  flex-direction: column;
56
120
  gap: .125rem;
57
- margin-top: .25rem;
58
121
  display: flex;
59
122
  }
60
123
 
@@ -62,3 +125,7 @@
62
125
  font-weight: var(--font-weight-semibold);
63
126
  }
64
127
 
128
+ :is(.meta-pending-Q0ICzl, .byline-field-file-meta-pending) {
129
+ color: var(--yellow-400);
130
+ }
131
+
@@ -0,0 +1,21 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ import { type FileField as FieldType, type PendingStoredFileValue, type StoredFileValue } from '@byline/core';
9
+ interface FileUploadFieldProps {
10
+ field: FieldType;
11
+ /** Collection path used to build the upload URL (e.g. `'media'`). */
12
+ collectionPath: string;
13
+ /** Field path in the form (e.g. `'attachment'` or `'content.0.attachment'`). */
14
+ fieldPath: string;
15
+ /** Called with the PendingStoredFileValue for immediate UI update. */
16
+ onUploaded: (value: StoredFileValue | PendingStoredFileValue) => void;
17
+ /** Optional `accept` MIME-type / extension string for the native file input. */
18
+ accept?: string;
19
+ }
20
+ export declare const FileUploadField: ({ field: _field, collectionPath, fieldPath, onUploaded, accept, }: FileUploadFieldProps) => import("react").JSX.Element;
21
+ export {};