@opengovsg/oui 0.0.21 → 0.0.22

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 (43) hide show
  1. package/dist/cjs/calendar/calendar-month-day-selector.cjs +2 -1
  2. package/dist/cjs/date-picker/date-picker.cjs +34 -9
  3. package/dist/cjs/field/field.cjs +1 -1
  4. package/dist/cjs/file-dropzone/contexts.cjs +18 -0
  5. package/dist/cjs/file-dropzone/file-dropzone.cjs +311 -0
  6. package/dist/cjs/file-dropzone/file-info.cjs +146 -0
  7. package/dist/cjs/file-dropzone/index.cjs +13 -0
  8. package/dist/cjs/file-dropzone/types.cjs +3 -0
  9. package/dist/cjs/file-dropzone/utils.cjs +31 -0
  10. package/dist/cjs/index.cjs +9 -2
  11. package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/trash-2.cjs +25 -0
  12. package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/upload.cjs +23 -0
  13. package/dist/esm/calendar/calendar-month-day-selector.js +2 -1
  14. package/dist/esm/date-picker/date-picker.js +34 -9
  15. package/dist/esm/field/field.js +1 -1
  16. package/dist/esm/file-dropzone/contexts.js +13 -0
  17. package/dist/esm/file-dropzone/file-dropzone.js +309 -0
  18. package/dist/esm/file-dropzone/file-info.js +144 -0
  19. package/dist/esm/file-dropzone/index.js +4 -0
  20. package/dist/esm/file-dropzone/types.js +1 -0
  21. package/dist/esm/file-dropzone/utils.js +28 -0
  22. package/dist/esm/index.js +4 -1
  23. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/trash-2.js +20 -0
  24. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/upload.js +18 -0
  25. package/dist/types/calendar/calendar-month-day-selector.d.ts.map +1 -1
  26. package/dist/types/date-picker/date-picker.d.ts +5 -2
  27. package/dist/types/date-picker/date-picker.d.ts.map +1 -1
  28. package/dist/types/file-dropzone/contexts.d.ts +4 -0
  29. package/dist/types/file-dropzone/contexts.d.ts.map +1 -0
  30. package/dist/types/file-dropzone/file-dropzone.d.ts +82 -0
  31. package/dist/types/file-dropzone/file-dropzone.d.ts.map +1 -0
  32. package/dist/types/file-dropzone/file-info.d.ts +9 -0
  33. package/dist/types/file-dropzone/file-info.d.ts.map +1 -0
  34. package/dist/types/file-dropzone/index.d.ts +7 -0
  35. package/dist/types/file-dropzone/index.d.ts.map +1 -0
  36. package/dist/types/file-dropzone/types.d.ts +24 -0
  37. package/dist/types/file-dropzone/types.d.ts.map +1 -0
  38. package/dist/types/file-dropzone/utils.d.ts +8 -0
  39. package/dist/types/file-dropzone/utils.d.ts.map +1 -0
  40. package/dist/types/index.d.mts +1 -0
  41. package/dist/types/index.d.ts +1 -0
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/package.json +4 -3
@@ -63,7 +63,8 @@ const CalendarMonthDaySelector = () => {
63
63
  list: slots.yearList({ className: classNames?.yearList }),
64
64
  selectedText: slots.selectorText({
65
65
  className: classNames?.selectorText
66
- })
66
+ }),
67
+ popover: "min-w-[8ch]"
67
68
  },
68
69
  selectedKey: state.visibleRange.start.year,
69
70
  "aria-label": formatMessage("selectYear"),
@@ -25,6 +25,7 @@ function DatePicker(originalProps) {
25
25
  calendarProps,
26
26
  popoverProps,
27
27
  calendarButtonProps,
28
+ selectorIcon,
28
29
  ...props
29
30
  },
30
31
  variantProps
@@ -63,20 +64,44 @@ function DatePicker(originalProps) {
63
64
  className: classNames?.calendarButton
64
65
  }),
65
66
  ...calendarButtonProps,
66
- children: /* @__PURE__ */ jsxRuntime.jsx(calendar.default, { "aria-hidden": true })
67
+ children: selectorIcon ?? /* @__PURE__ */ jsxRuntime.jsx(
68
+ calendar.default,
69
+ {
70
+ className: styles.selectorIcon({
71
+ className: classNames?.selectorIcon
72
+ }),
73
+ "aria-hidden": true
74
+ }
75
+ )
67
76
  }
68
77
  )
69
78
  ] }),
70
- /* @__PURE__ */ jsxRuntime.jsx(popover.Popover, { placement: "bottom end", ...popoverProps, children: /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Dialog, { className: styles.dialog({ className: classNames?.dialog }), children: /* @__PURE__ */ jsxRuntime.jsx(
71
- calendar$1.Calendar,
79
+ /* @__PURE__ */ jsxRuntime.jsx(
80
+ popover.Popover,
72
81
  {
73
- size: variantProps.size === "xs" ? "sm" : variantProps.size,
74
- classNames: classNames?.calendar,
75
- ...calendarProps
82
+ placement: "bottom end",
83
+ classNames: classNames?.popover,
84
+ ...popoverProps,
85
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Dialog, { className: styles.dialog({ className: classNames?.dialog }), children: /* @__PURE__ */ jsxRuntime.jsx(
86
+ calendar$1.Calendar,
87
+ {
88
+ size: variantProps.size === "xs" ? "sm" : variantProps.size,
89
+ classNames: classNames?.calendar,
90
+ pageBehavior: props.pageBehavior,
91
+ ...calendarProps
92
+ }
93
+ ) })
76
94
  }
77
- ) }) }),
78
- description && /* @__PURE__ */ jsxRuntime.jsx(field.Description, { size: variantProps.size, children: description }),
79
- /* @__PURE__ */ jsxRuntime.jsx(field.FieldError, { size: variantProps.size, children: errorMessage })
95
+ ),
96
+ description && /* @__PURE__ */ jsxRuntime.jsx(
97
+ field.Description,
98
+ {
99
+ className: classNames?.description,
100
+ size: variantProps.size,
101
+ children: description
102
+ }
103
+ ),
104
+ /* @__PURE__ */ jsxRuntime.jsx(field.FieldError, { classNames: classNames?.error, size: variantProps.size, children: errorMessage })
80
105
  ]
81
106
  }
82
107
  );
@@ -15,8 +15,8 @@ function Description({ size, className, ...props }) {
15
15
  return /* @__PURE__ */ jsxRuntime.jsx(
16
16
  reactAriaComponents.Text,
17
17
  {
18
- ...props,
19
18
  slot: "description",
19
+ ...props,
20
20
  className: ouiTheme.descriptionStyles({ className, size })
21
21
  }
22
22
  );
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var context = require('../system/react-utils/context.cjs');
5
+
6
+ const [FileDropzoneStateContext, useFileDropzoneStateContext] = context.createContext({
7
+ strict: true,
8
+ name: "FileDropzoneStateContext"
9
+ });
10
+ const [FileDropzoneStyleContext, useFileDropzoneStyleContext] = context.createContext({
11
+ strict: true,
12
+ name: "FileDropzoneStyleContext"
13
+ });
14
+
15
+ exports.FileDropzoneStateContext = FileDropzoneStateContext;
16
+ exports.FileDropzoneStyleContext = FileDropzoneStyleContext;
17
+ exports.useFileDropzoneStateContext = useFileDropzoneStateContext;
18
+ exports.useFileDropzoneStyleContext = useFileDropzoneStyleContext;
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var $670gB$react = require('react');
7
+ var form = require('@react-stately/form');
8
+ var reactAria = require('react-aria');
9
+ var reactAriaComponents = require('react-aria-components');
10
+ var reactDropzone = require('react-dropzone');
11
+ var ouiTheme = require('@opengovsg/oui-theme');
12
+ var utils = require('../system/utils.cjs');
13
+ var contexts = require('./contexts.cjs');
14
+ var fileInfo = require('./file-info.cjs');
15
+ var utils$1 = require('./utils.cjs');
16
+ var useControllableState = require('../hooks/use-controllable-state.cjs');
17
+ var upload = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/upload.cjs');
18
+ var field = require('../field/field.cjs');
19
+
20
+ const FileDropzone = (originalProps) => {
21
+ const [props, variantProps] = utils.mapPropsVariants(
22
+ originalProps,
23
+ ouiTheme.fileDropzoneStyles.variantKeys
24
+ );
25
+ const {
26
+ name,
27
+ allowedMimeTypes = [],
28
+ maxFileSize = Number.POSITIVE_INFINITY,
29
+ minFileSize = 0,
30
+ showFileSizeText = true,
31
+ maxFiles = 1,
32
+ isDisabled,
33
+ isReadOnly,
34
+ classNames,
35
+ itemClassNames,
36
+ validator,
37
+ showRejectedFiles,
38
+ onError,
39
+ errorMessage,
40
+ label,
41
+ description,
42
+ children,
43
+ hideDropzoneOnValue = maxFiles === 1,
44
+ imagePreview = "small"
45
+ } = props;
46
+ const [value, setValue] = useControllableState.useControllableState({
47
+ value: props.value,
48
+ defaultValue: props.defaultValue || [],
49
+ onChange: props.onChange
50
+ });
51
+ const [rejections, setRejections] = useControllableState.useControllableState({
52
+ value: props.rejections,
53
+ defaultValue: [],
54
+ onChange: props.onRejection
55
+ });
56
+ const validationState = form.useFormValidationState({
57
+ ...props,
58
+ value
59
+ });
60
+ const { isInvalid, validationErrors, validationDetails } = validationState.displayValidation;
61
+ const { labelProps, fieldProps, descriptionProps, errorMessageProps } = reactAria.useField({
62
+ ...props,
63
+ isInvalid,
64
+ errorMessage: props.errorMessage || validationErrors
65
+ });
66
+ const slots = ouiTheme.fileDropzoneStyles(variantProps);
67
+ const fileSizeTextId = reactAria.useId();
68
+ const formatError = $670gB$react.useCallback(
69
+ (error) => utils$1.formatErrorMessage(error, {
70
+ maxFileSize,
71
+ minFileSize,
72
+ maxFiles
73
+ }),
74
+ [maxFileSize, maxFiles, minFileSize]
75
+ );
76
+ const onDrop = $670gB$react.useCallback(
77
+ (acceptedFiles, fileRejections) => {
78
+ const files = acceptedFiles;
79
+ if (showRejectedFiles) {
80
+ const invalidFiles = fileRejections.map(({ file, errors }) => {
81
+ file.errors = errors;
82
+ return file;
83
+ });
84
+ setRejections(invalidFiles);
85
+ }
86
+ setValue(files);
87
+ if (onError && fileRejections.length > 0) {
88
+ const firstError = fileRejections[0].errors[0];
89
+ onError(formatError(firstError));
90
+ }
91
+ },
92
+ [formatError, onError, setRejections, setValue, showRejectedFiles]
93
+ );
94
+ const handleRemoveFile = $670gB$react.useCallback(
95
+ (fileName) => {
96
+ setValue((files) => files.filter((file) => file.name !== fileName));
97
+ },
98
+ [setValue]
99
+ );
100
+ const handleRemoveRejection = $670gB$react.useCallback(
101
+ (fileName) => {
102
+ setRejections(
103
+ (rejections2) => rejections2.filter((file) => file.name !== fileName)
104
+ );
105
+ },
106
+ [setRejections]
107
+ );
108
+ const { getInputProps, ...dropzoneState } = reactDropzone.useDropzone({
109
+ validator,
110
+ accept: allowedMimeTypes.reduce(
111
+ (acc, type) => ({ ...acc, [type]: [] }),
112
+ {}
113
+ ),
114
+ onError: (e) => onError?.(e.message),
115
+ onDrop,
116
+ disabled: isDisabled,
117
+ noDrag: isReadOnly,
118
+ // Prevent ref hijack when there is a label
119
+ noClick: true,
120
+ noKeyboard: true,
121
+ maxSize: maxFileSize,
122
+ minSize: minFileSize,
123
+ maxFiles,
124
+ multiple: maxFiles !== 1
125
+ });
126
+ const fileSizeText = $670gB$react.useMemo(() => {
127
+ const notDefaultMaxFileSize = maxFileSize !== Number.POSITIVE_INFINITY;
128
+ const notDefaultMinFileSize = minFileSize !== 0;
129
+ const shouldShow = showFileSizeText && (notDefaultMaxFileSize || notDefaultMinFileSize);
130
+ if (!shouldShow) return null;
131
+ if (notDefaultMaxFileSize && notDefaultMinFileSize) {
132
+ return `File size must be between ${utils$1.formatBytes(minFileSize, 2)} and ${utils$1.formatBytes(
133
+ maxFileSize,
134
+ 2
135
+ )}`;
136
+ }
137
+ if (notDefaultMaxFileSize) {
138
+ return `Maximum file size: ${utils$1.formatBytes(maxFileSize, 2)}`;
139
+ }
140
+ if (notDefaultMinFileSize) {
141
+ return `Minimum file size: ${utils$1.formatBytes(minFileSize, 2)}`;
142
+ }
143
+ return null;
144
+ }, [maxFileSize, minFileSize, showFileSizeText]);
145
+ const triggerFileSelector = $670gB$react.useCallback(() => {
146
+ if (isDisabled || isReadOnly) return;
147
+ dropzoneState.inputRef.current?.click();
148
+ }, [dropzoneState, isDisabled, isReadOnly]);
149
+ $670gB$react.useEffect(() => {
150
+ if (value.length <= maxFiles) {
151
+ let changed = false;
152
+ const newFiles = value.map((file) => {
153
+ if (file.errors?.some((e) => e.code === "too-many-files")) {
154
+ file.errors = file.errors.filter((e) => e.code !== "too-many-files");
155
+ changed = true;
156
+ }
157
+ return file;
158
+ });
159
+ if (changed) {
160
+ setValue(newFiles);
161
+ }
162
+ }
163
+ }, [maxFiles, setValue, value]);
164
+ const inputProps = $670gB$react.useMemo(() => {
165
+ const inputProps2 = { ...fieldProps, name };
166
+ if (fileSizeText) {
167
+ inputProps2["aria-describedby"] = inputProps2["aria-describedby"] ? `${inputProps2["aria-describedby"]} ${fileSizeTextId}` : fileSizeTextId;
168
+ }
169
+ return getInputProps(inputProps2);
170
+ }, [fieldProps, getInputProps, fileSizeTextId, name, fileSizeText]);
171
+ const showDropzone = $670gB$react.useMemo(() => {
172
+ if (hideDropzoneOnValue) {
173
+ return value.length < maxFiles;
174
+ }
175
+ return true;
176
+ }, [hideDropzoneOnValue, maxFiles, value.length]);
177
+ return /* @__PURE__ */ jsxRuntime.jsx(
178
+ reactAriaComponents.Provider,
179
+ {
180
+ values: [
181
+ [
182
+ contexts.FileDropzoneStyleContext,
183
+ { slots, classNames, itemClassNames, ...variantProps }
184
+ ],
185
+ [
186
+ contexts.FileDropzoneStateContext,
187
+ {
188
+ isDisabled,
189
+ isReadOnly,
190
+ maxFiles,
191
+ maxFileSize,
192
+ showDropzone,
193
+ files: value,
194
+ handleRemoveFile,
195
+ handleRemoveRejection,
196
+ formatError,
197
+ inputProps,
198
+ triggerFileSelector,
199
+ ...dropzoneState
200
+ }
201
+ ],
202
+ [reactAriaComponents.LabelContext, labelProps],
203
+ [
204
+ reactAriaComponents.GroupContext,
205
+ {
206
+ role: "presentation",
207
+ isInvalid,
208
+ isDisabled: props.isDisabled || false
209
+ }
210
+ ],
211
+ [
212
+ reactAriaComponents.TextContext,
213
+ {
214
+ slots: {
215
+ fileSize: {},
216
+ description: descriptionProps,
217
+ errorMessage: errorMessageProps
218
+ }
219
+ }
220
+ ],
221
+ [reactAriaComponents.FieldErrorContext, { isInvalid, validationErrors, validationDetails }]
222
+ ],
223
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactAriaComponents.Group, { className: slots.base({ className: classNames?.base }), children: [
224
+ label && /* @__PURE__ */ jsxRuntime.jsx(field.Label, { size: variantProps.size, children: label }),
225
+ showDropzone && /* @__PURE__ */ jsxRuntime.jsx(FileDropzoneDropzone, {}),
226
+ value.map((file) => {
227
+ if (typeof children === "function") {
228
+ return children({
229
+ file,
230
+ removeFile: () => handleRemoveFile(file.name)
231
+ });
232
+ }
233
+ return /* @__PURE__ */ jsxRuntime.jsx(fileInfo.FileInfo, { imagePreview, file }, file.name);
234
+ }),
235
+ rejections.length >= 1 && rejections.map((rj) => /* @__PURE__ */ jsxRuntime.jsx(fileInfo.FileInfo, { imagePreview, file: rj }, rj.name)),
236
+ fileSizeText && /* @__PURE__ */ jsxRuntime.jsx(
237
+ field.Description,
238
+ {
239
+ size: variantProps.size,
240
+ id: fileSizeTextId,
241
+ slot: "fileSize",
242
+ children: fileSizeText
243
+ }
244
+ ),
245
+ description && /* @__PURE__ */ jsxRuntime.jsx(field.Description, { size: variantProps.size, children: description }),
246
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx(field.FieldError, { size: variantProps.size, children: errorMessage })
247
+ ] })
248
+ }
249
+ );
250
+ };
251
+ const FileDropzoneDropzone = () => {
252
+ const {
253
+ maxFiles,
254
+ getRootProps,
255
+ inputProps,
256
+ triggerFileSelector,
257
+ isDisabled,
258
+ isDragActive
259
+ } = contexts.useFileDropzoneStateContext();
260
+ const { slots, classNames } = contexts.useFileDropzoneStyleContext();
261
+ return /* @__PURE__ */ jsxRuntime.jsxs(
262
+ "div",
263
+ {
264
+ ...getRootProps({
265
+ "aria-disabled": isDisabled,
266
+ className: slots.group({
267
+ className: classNames?.group
268
+ })
269
+ }),
270
+ tabIndex: isDisabled ? void 0 : 0,
271
+ onClick: triggerFileSelector,
272
+ onKeyDown: (e) => {
273
+ if (e.key === "Enter" || e.key === " ") {
274
+ e.preventDefault();
275
+ triggerFileSelector();
276
+ }
277
+ },
278
+ children: [
279
+ /* @__PURE__ */ jsxRuntime.jsx("input", { ...inputProps }),
280
+ /* @__PURE__ */ jsxRuntime.jsxs(
281
+ "div",
282
+ {
283
+ "data-dragging": ouiTheme.dataAttr(isDragActive),
284
+ className: slots.dropzone({ className: classNames?.dropzone }),
285
+ children: [
286
+ /* @__PURE__ */ jsxRuntime.jsx(upload.default, { className: slots.icon({ className: classNames?.icon }) }),
287
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: slots.text({ className: classNames?.text }), children: [
288
+ /* @__PURE__ */ jsxRuntime.jsxs(
289
+ "span",
290
+ {
291
+ className: slots.dropzoneHighlight({
292
+ className: classNames?.dropzoneHighlight
293
+ }),
294
+ children: [
295
+ "Choose ",
296
+ maxFiles === 1 ? `file` : `files`
297
+ ]
298
+ }
299
+ ),
300
+ " ",
301
+ "or drag and drop here"
302
+ ] })
303
+ ]
304
+ }
305
+ )
306
+ ]
307
+ }
308
+ );
309
+ };
310
+
311
+ exports.FileDropzone = FileDropzone;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var $670gB$react = require('react');
7
+ var ouiTheme = require('@opengovsg/oui-theme');
8
+ var contexts = require('./contexts.cjs');
9
+ var utils = require('./utils.cjs');
10
+ var trash2 = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/trash-2.cjs');
11
+ var button = require('../button/button.cjs');
12
+
13
+ const FileInfo = ({ file, imagePreview, classNames }) => {
14
+ const {
15
+ handleRemoveFile,
16
+ handleRemoveRejection,
17
+ formatError,
18
+ isDisabled,
19
+ isReadOnly
20
+ } = contexts.useFileDropzoneStateContext();
21
+ const { size, variant, itemClassNames } = contexts.useFileDropzoneStyleContext();
22
+ const readableFileSize = utils.formatBytes(file.size, 2);
23
+ const styles = ouiTheme.fileInfoDropzoneStyles({
24
+ size,
25
+ variant,
26
+ imagePreview: imagePreview ?? void 0
27
+ });
28
+ const [previewSrc, setPreviewSrc] = $670gB$react.useState("");
29
+ $670gB$react.useEffect(() => {
30
+ let objectUrl = "";
31
+ if (file.type.startsWith("image/")) {
32
+ objectUrl = URL.createObjectURL(file);
33
+ setPreviewSrc(objectUrl);
34
+ }
35
+ return () => URL.revokeObjectURL(objectUrl);
36
+ }, [file]);
37
+ return /* @__PURE__ */ jsxRuntime.jsxs(
38
+ "div",
39
+ {
40
+ className: styles.base({
41
+ className: ouiTheme.cn(itemClassNames?.base, classNames?.base)
42
+ }),
43
+ children: [
44
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sr-only", children: [
45
+ "File attached: ",
46
+ file.name,
47
+ " with file size of ",
48
+ readableFileSize
49
+ ] }),
50
+ imagePreview && previewSrc && /* @__PURE__ */ jsxRuntime.jsx(
51
+ "div",
52
+ {
53
+ className: styles.imageContainer({
54
+ className: ouiTheme.cn(
55
+ itemClassNames?.imageContainer,
56
+ classNames?.imageContainer
57
+ )
58
+ }),
59
+ children: /* @__PURE__ */ jsxRuntime.jsx(
60
+ "img",
61
+ {
62
+ src: previewSrc,
63
+ alt: `Image preview of uploaded file: ${file.name}`,
64
+ className: styles.image({
65
+ className: ouiTheme.cn(itemClassNames?.image, classNames?.image)
66
+ })
67
+ }
68
+ )
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsxRuntime.jsxs(
72
+ "div",
73
+ {
74
+ className: styles.container({
75
+ className: ouiTheme.cn(itemClassNames?.container, classNames?.container)
76
+ }),
77
+ children: [
78
+ /* @__PURE__ */ jsxRuntime.jsxs(
79
+ "div",
80
+ {
81
+ className: styles.textContainer({
82
+ className: ouiTheme.cn(
83
+ itemClassNames?.textContainer,
84
+ classNames?.textContainer
85
+ )
86
+ }),
87
+ children: [
88
+ /* @__PURE__ */ jsxRuntime.jsx(
89
+ "p",
90
+ {
91
+ title: file.name,
92
+ className: styles.name({
93
+ className: ouiTheme.cn(itemClassNames?.name, classNames?.name)
94
+ }),
95
+ children: file.name
96
+ }
97
+ ),
98
+ /* @__PURE__ */ jsxRuntime.jsx(
99
+ "p",
100
+ {
101
+ className: styles.size({
102
+ className: ouiTheme.cn(itemClassNames?.size, classNames?.size)
103
+ }),
104
+ children: readableFileSize
105
+ }
106
+ ),
107
+ file.errors?.length && /* @__PURE__ */ jsxRuntime.jsx(
108
+ "p",
109
+ {
110
+ className: styles.error({
111
+ className: ouiTheme.cn(itemClassNames?.error, classNames?.error)
112
+ }),
113
+ children: file.errors.map(formatError).join(", ")
114
+ }
115
+ )
116
+ ]
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsxRuntime.jsx(
120
+ button.Button,
121
+ {
122
+ isDisabled: isDisabled || isReadOnly,
123
+ isIconOnly: !file.errors?.length,
124
+ size: size === "md" ? "md" : "xs",
125
+ variant: "clear",
126
+ color: file.errors?.length ? "main" : "critical",
127
+ "aria-label": "Remove file",
128
+ className: styles.actionButton({
129
+ className: ouiTheme.cn(
130
+ itemClassNames?.actionButton,
131
+ classNames?.actionButton
132
+ )
133
+ }),
134
+ onPress: () => file.errors?.length ? handleRemoveRejection(file.name) : handleRemoveFile(file.name),
135
+ children: file.errors?.length ? "Dismiss" : /* @__PURE__ */ jsxRuntime.jsx(trash2.default, {})
136
+ }
137
+ )
138
+ ]
139
+ }
140
+ )
141
+ ]
142
+ }
143
+ );
144
+ };
145
+
146
+ exports.FileInfo = FileInfo;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var fileDropzone = require('./file-dropzone.cjs');
5
+ var fileInfo = require('./file-info.cjs');
6
+ var utils = require('./utils.cjs');
7
+
8
+
9
+
10
+ exports.FileDropzone = fileDropzone.FileDropzone;
11
+ exports.FileInfo = fileInfo.FileInfo;
12
+ exports.formatBytes = utils.formatBytes;
13
+ exports.formatErrorMessage = utils.formatErrorMessage;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ 'use strict';
3
+
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var reactDropzone = require('react-dropzone');
5
+
6
+ const formatBytes = (bytes, decimals = 2, size) => {
7
+ const k = 1e3;
8
+ const dm = decimals < 0 ? 0 : decimals;
9
+ const sizes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
10
+ if (bytes === 0 || bytes === void 0)
11
+ return size !== void 0 ? `0 ${size}` : "0 bytes";
12
+ const i = size !== void 0 ? sizes.indexOf(size) : Math.floor(Math.log(bytes) / Math.log(k));
13
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
14
+ };
15
+ const formatErrorMessage = (error, config) => {
16
+ const { maxFileSize, minFileSize, maxFiles } = config;
17
+ switch (error.code) {
18
+ case reactDropzone.ErrorCode.FileTooLarge:
19
+ return `You have exceeded the size limit, please upload a file below ${formatBytes(maxFileSize, 2)}`;
20
+ case reactDropzone.ErrorCode.FileTooSmall:
21
+ return `Please upload a file above ${formatBytes(minFileSize, 2)}`;
22
+ case reactDropzone.ErrorCode.TooManyFiles:
23
+ return `Maximum number of files allowed is ${maxFiles}.`;
24
+ default: {
25
+ return error.message;
26
+ }
27
+ }
28
+ };
29
+
30
+ exports.formatBytes = formatBytes;
31
+ exports.formatErrorMessage = formatErrorMessage;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  'use strict';
3
3
 
4
- var toggle = require('./toggle/toggle.cjs');
5
4
  var useControllableState = require('./hooks/use-controllable-state.cjs');
6
5
  var button = require('./button/button.cjs');
7
6
  var govtBanner = require('./govt-banner/govt-banner.cjs');
@@ -9,6 +8,7 @@ var ripple = require('./ripple/ripple.cjs');
9
8
  var useRipple = require('./ripple/use-ripple.cjs');
10
9
  var spinner = require('./spinner/spinner.cjs');
11
10
  var useSpinner = require('./spinner/use-spinner.cjs');
11
+ var toggle = require('./toggle/toggle.cjs');
12
12
  var skipNavLink = require('./skip-nav-link/skip-nav-link.cjs');
13
13
  var input = require('./input/input.cjs');
14
14
  var textField = require('./text-field/text-field.cjs');
@@ -44,10 +44,12 @@ var pagination = require('./pagination/pagination.cjs');
44
44
  var paginationCursor = require('./pagination/pagination-cursor.cjs');
45
45
  var paginationItem = require('./pagination/pagination-item.cjs');
46
46
  var usePagination$1 = require('./pagination/use-pagination.cjs');
47
+ var fileDropzone = require('./file-dropzone/file-dropzone.cjs');
48
+ var fileInfo = require('./file-dropzone/file-info.cjs');
49
+ var utils$1 = require('./file-dropzone/utils.cjs');
47
50
 
48
51
 
49
52
 
50
- exports.Toggle = toggle.Toggle;
51
53
  exports.useControllableState = useControllableState.useControllableState;
52
54
  exports.Button = button.Button;
53
55
  exports.GovtBanner = govtBanner.GovtBanner;
@@ -55,6 +57,7 @@ exports.Ripple = ripple.Ripple;
55
57
  exports.useRipple = useRipple.useRipple;
56
58
  exports.Spinner = spinner.Spinner;
57
59
  exports.useSpinner = useSpinner.useSpinner;
60
+ exports.Toggle = toggle.Toggle;
58
61
  exports.SkipNavLink = skipNavLink.SkipNavLink;
59
62
  exports.Input = input.Input;
60
63
  exports.TextField = textField.TextField;
@@ -123,3 +126,7 @@ exports.PaginationCursor = paginationCursor.PaginationCursor;
123
126
  exports.PaginationItem = paginationItem.PaginationItem;
124
127
  exports.CURSOR_TRANSITION_TIMEOUT = usePagination$1.CURSOR_TRANSITION_TIMEOUT;
125
128
  exports.usePagination = usePagination$1.usePagination;
129
+ exports.FileDropzone = fileDropzone.FileDropzone;
130
+ exports.FileInfo = fileInfo.FileInfo;
131
+ exports.formatBytes = utils$1.formatBytes;
132
+ exports.formatErrorMessage = utils$1.formatErrorMessage;
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var createLucideIcon = require('../createLucideIcon.cjs');
6
+
7
+ /**
8
+ * @license lucide-react v0.475.0 - ISC
9
+ *
10
+ * This source code is licensed under the ISC license.
11
+ * See the LICENSE file in the root directory of this source tree.
12
+ */
13
+
14
+
15
+ const __iconNode = [
16
+ ["path", { d: "M3 6h18", key: "d0wm0j" }],
17
+ ["path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6", key: "4alrt4" }],
18
+ ["path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2", key: "v07s0e" }],
19
+ ["line", { x1: "10", x2: "10", y1: "11", y2: "17", key: "1uufr5" }],
20
+ ["line", { x1: "14", x2: "14", y1: "11", y2: "17", key: "xtxkd" }]
21
+ ];
22
+ const Trash2 = createLucideIcon.default("Trash2", __iconNode);
23
+
24
+ exports.__iconNode = __iconNode;
25
+ exports.default = Trash2;