@spark-ui/components 11.4.2 → 11.5.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.
@@ -25,6 +25,7 @@ __export(file_upload_exports, {
25
25
  module.exports = __toCommonJS(file_upload_exports);
26
26
 
27
27
  // src/file-upload/FileUpload.tsx
28
+ var import_form_field = require("@spark-ui/components/form-field");
28
29
  var import_use_combined_state = require("@spark-ui/hooks/use-combined-state");
29
30
  var import_react2 = require("react");
30
31
 
@@ -130,33 +131,45 @@ function getFileIcon(file) {
130
131
  // src/file-upload/FileUpload.tsx
131
132
  var import_jsx_runtime = require("react/jsx-runtime");
132
133
  var FileUploadContext = (0, import_react2.createContext)(null);
134
+ var ID_PREFIX = ":file-upload";
133
135
  var FileUpload = ({
134
136
  asChild: _asChild = false,
135
137
  children,
136
138
  defaultValue = [],
137
139
  value: controlledValue,
138
- onFilesChange,
140
+ onFileAccept,
141
+ onFileReject,
142
+ onFileChange,
139
143
  multiple = true,
140
144
  accept,
141
145
  maxFiles,
142
- onMaxFilesReached,
143
146
  maxFileSize,
144
147
  minFileSize,
145
- onFileSizeError,
146
- disabled = false,
147
- readOnly = false,
148
+ disabled: disabledProp = false,
149
+ readOnly: readOnlyProp = false,
148
150
  locale
149
151
  }) => {
152
+ const field = (0, import_form_field.useFormFieldControl)();
153
+ const {
154
+ id: fieldId,
155
+ name: fieldName,
156
+ isInvalid,
157
+ isRequired,
158
+ description,
159
+ disabled: fieldDisabled,
160
+ readOnly: fieldReadOnly
161
+ } = field;
150
162
  const defaultLocale = locale || (typeof navigator !== "undefined" && navigator.language ? navigator.language : "en");
163
+ const internalId = (0, import_react2.useId)();
164
+ const inputId = fieldId || `${ID_PREFIX}-${internalId}`;
165
+ const inputName = fieldName;
151
166
  const inputRef = (0, import_react2.useRef)(null);
152
167
  const triggerRef = (0, import_react2.useRef)(null);
153
168
  const dropzoneRef = (0, import_react2.useRef)(null);
154
169
  const deleteButtonRefs = (0, import_react2.useRef)([]);
155
- const [filesState, setFilesState, ,] = (0, import_use_combined_state.useCombinedState)(
156
- controlledValue,
157
- defaultValue,
158
- onFilesChange
159
- );
170
+ const disabled = fieldDisabled ?? disabledProp;
171
+ const readOnly = fieldReadOnly ?? readOnlyProp;
172
+ const [filesState, setFilesState, ,] = (0, import_use_combined_state.useCombinedState)(controlledValue, defaultValue);
160
173
  const files = filesState ?? [];
161
174
  const setFiles = setFilesState;
162
175
  const [rejectedFiles, setRejectedFiles] = (0, import_react2.useState)([]);
@@ -185,9 +198,6 @@ var FileUpload = ({
185
198
  errors: [error]
186
199
  });
187
200
  }
188
- if (onFileSizeError) {
189
- onFileSizeError(file, error);
190
- }
191
201
  };
192
202
  setFiles((prev) => {
193
203
  const currentFiles = prev ?? [];
@@ -251,19 +261,29 @@ var FileUpload = ({
251
261
  filesToAdd.forEach((file) => {
252
262
  addRejectedFile(file, "TOO_MANY_FILES");
253
263
  });
254
- onMaxFilesReached?.(maxFiles, filesToAdd.length);
255
264
  filesToAdd = [];
256
265
  } else if (filesToAdd.length > remainingSlots) {
257
266
  filesToAdd.forEach((file) => {
258
267
  addRejectedFile(file, "TOO_MANY_FILES");
259
268
  });
260
- onMaxFilesReached?.(maxFiles, filesToAdd.length);
261
269
  filesToAdd = [];
262
270
  }
263
271
  }
264
272
  const updated = multiple ? [...currentFiles, ...filesToAdd] : filesToAdd;
265
273
  const rejectedFilesToAdd = [...newRejectedFiles];
266
274
  setRejectedFiles(rejectedFilesToAdd);
275
+ if (filesToAdd.length > 0 && onFileAccept) {
276
+ onFileAccept({ files: filesToAdd });
277
+ }
278
+ if (rejectedFilesToAdd.length > 0 && onFileReject) {
279
+ onFileReject({ files: rejectedFilesToAdd });
280
+ }
281
+ if (onFileChange) {
282
+ onFileChange({
283
+ acceptedFiles: updated,
284
+ rejectedFiles: rejectedFilesToAdd
285
+ });
286
+ }
267
287
  return updated;
268
288
  });
269
289
  };
@@ -274,10 +294,18 @@ var FileUpload = ({
274
294
  setFiles((prev) => {
275
295
  const currentFiles = prev ?? [];
276
296
  const updated = currentFiles.filter((_, i) => i !== index);
297
+ let updatedRejectedFiles = rejectedFiles;
277
298
  if (maxFiles !== void 0 && updated.length < maxFiles) {
278
- setRejectedFiles(
279
- (prevRejected) => prevRejected.filter((rejected) => !rejected.errors.includes("TOO_MANY_FILES"))
299
+ updatedRejectedFiles = rejectedFiles.filter(
300
+ (rejected) => !rejected.errors.includes("TOO_MANY_FILES")
280
301
  );
302
+ setRejectedFiles(updatedRejectedFiles);
303
+ }
304
+ if (onFileChange) {
305
+ onFileChange({
306
+ acceptedFiles: updated,
307
+ rejectedFiles: updatedRejectedFiles
308
+ });
281
309
  }
282
310
  return updated;
283
311
  });
@@ -289,6 +317,12 @@ var FileUpload = ({
289
317
  setFiles([]);
290
318
  setRejectedFiles([]);
291
319
  deleteButtonRefs.current = [];
320
+ if (onFileChange) {
321
+ onFileChange({
322
+ acceptedFiles: [],
323
+ rejectedFiles: []
324
+ });
325
+ }
292
326
  };
293
327
  const removeRejectedFile = (index) => {
294
328
  if (disabled || readOnly) {
@@ -320,7 +354,10 @@ var FileUpload = ({
320
354
  maxFilesReached,
321
355
  disabled,
322
356
  readOnly,
323
- locale: defaultLocale
357
+ locale: defaultLocale,
358
+ description,
359
+ isInvalid,
360
+ isRequired
324
361
  },
325
362
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
326
363
  children,
@@ -330,12 +367,15 @@ var FileUpload = ({
330
367
  ref: inputRef,
331
368
  type: "file",
332
369
  tabIndex: -1,
333
- id: "image_uploads",
370
+ id: inputId,
334
371
  multiple,
335
- name: "image_uploads",
372
+ name: inputName,
336
373
  accept,
337
374
  disabled,
338
375
  readOnly: readOnly && !disabled,
376
+ required: isRequired,
377
+ "aria-invalid": isInvalid,
378
+ "aria-describedby": description,
339
379
  className: "sr-only",
340
380
  onChange: (e) => {
341
381
  if (e.target.files && !disabled && !readOnly) {
@@ -361,6 +401,9 @@ var useFileUploadContext = () => {
361
401
  return context;
362
402
  };
363
403
 
404
+ // src/file-upload/FileUploadAcceptedFile.tsx
405
+ var import_class_variance_authority10 = require("class-variance-authority");
406
+
364
407
  // src/icon/Icon.tsx
365
408
  var import_react4 = require("react");
366
409
 
@@ -488,7 +531,7 @@ var progressBarStyles = (0, import_class_variance_authority2.cva)(
488
531
  // src/progress/ProgressContext.tsx
489
532
  var import_react5 = require("react");
490
533
  var ProgressContext = (0, import_react5.createContext)(null);
491
- var ID_PREFIX = ":progress";
534
+ var ID_PREFIX2 = ":progress";
492
535
  var useProgress = () => {
493
536
  const context = (0, import_react5.useContext)(ProgressContext);
494
537
  if (!context) {
@@ -624,7 +667,7 @@ var ProgressLabel = ({
624
667
  ref: forwardedRef,
625
668
  ...others
626
669
  }) => {
627
- const internalID = `${ID_PREFIX}-label-${(0, import_react7.useId)()}`;
670
+ const internalID = `${ID_PREFIX2}-label-${(0, import_react7.useId)()}`;
628
671
  const id = idProp || internalID;
629
672
  const { onLabelId } = useProgress();
630
673
  const rootRef = (0, import_react7.useCallback)(
@@ -659,50 +702,24 @@ ProgressBar.displayName = "Progress.Bar";
659
702
  ProgressIndicator.displayName = "Progress.Indicator";
660
703
  ProgressLabel.displayName = "Progress.Label";
661
704
 
662
- // src/file-upload/FileUploadItem.tsx
663
- var import_class_variance_authority5 = require("class-variance-authority");
664
- var import_jsx_runtime9 = require("react/jsx-runtime");
665
- var Item = ({
666
- asChild: _asChild = false,
667
- className,
668
- children,
669
- ...props
670
- }) => {
671
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
672
- "li",
673
- {
674
- "data-spark-component": "file-upload-item",
675
- className: (0, import_class_variance_authority5.cx)(
676
- "relative",
677
- "default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md",
678
- "gap-md flex items-center justify-between default:w-full",
679
- className
680
- ),
681
- ...props,
682
- children
683
- }
684
- );
685
- };
686
- Item.displayName = "FileUpload.Item";
687
-
688
705
  // src/file-upload/FileUploadItemDeleteTrigger.tsx
689
706
  var import_Close = require("@spark-ui/icons/Close");
690
- var import_class_variance_authority10 = require("class-variance-authority");
707
+ var import_class_variance_authority9 = require("class-variance-authority");
691
708
  var import_react9 = require("react");
692
709
 
693
710
  // src/button/Button.tsx
694
- var import_class_variance_authority8 = require("class-variance-authority");
711
+ var import_class_variance_authority7 = require("class-variance-authority");
695
712
  var import_react8 = require("react");
696
713
 
697
714
  // src/spinner/Spinner.styles.tsx
698
715
  var import_internal_utils2 = require("@spark-ui/internal-utils");
699
- var import_class_variance_authority6 = require("class-variance-authority");
716
+ var import_class_variance_authority5 = require("class-variance-authority");
700
717
  var defaultVariants = {
701
718
  intent: "current",
702
719
  size: "current",
703
720
  isBackgroundVisible: false
704
721
  };
705
- var spinnerStyles = (0, import_class_variance_authority6.cva)(
722
+ var spinnerStyles = (0, import_class_variance_authority5.cva)(
706
723
  ["inline-block", "border-solid", "rounded-full", "border-md", "animate-spin"],
707
724
  {
708
725
  variants: {
@@ -743,7 +760,7 @@ var spinnerStyles = (0, import_class_variance_authority6.cva)(
743
760
  );
744
761
 
745
762
  // src/spinner/Spinner.tsx
746
- var import_jsx_runtime10 = require("react/jsx-runtime");
763
+ var import_jsx_runtime9 = require("react/jsx-runtime");
747
764
  var Spinner = ({
748
765
  className,
749
766
  size = "current",
@@ -753,7 +770,7 @@ var Spinner = ({
753
770
  ref,
754
771
  ...others
755
772
  }) => {
756
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
773
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
757
774
  "span",
758
775
  {
759
776
  role: "status",
@@ -761,14 +778,14 @@ var Spinner = ({
761
778
  ref,
762
779
  className: spinnerStyles({ className, size, intent, isBackgroundVisible }),
763
780
  ...others,
764
- children: label && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(VisuallyHidden, { children: label })
781
+ children: label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(VisuallyHidden, { children: label })
765
782
  }
766
783
  );
767
784
  };
768
785
 
769
786
  // src/button/Button.styles.tsx
770
787
  var import_internal_utils8 = require("@spark-ui/internal-utils");
771
- var import_class_variance_authority7 = require("class-variance-authority");
788
+ var import_class_variance_authority6 = require("class-variance-authority");
772
789
 
773
790
  // src/button/variants/filled.ts
774
791
  var import_internal_utils3 = require("@spark-ui/internal-utils");
@@ -1374,7 +1391,7 @@ var contrastVariants = [
1374
1391
  ];
1375
1392
 
1376
1393
  // src/button/Button.styles.tsx
1377
- var buttonStyles = (0, import_class_variance_authority7.cva)(
1394
+ var buttonStyles = (0, import_class_variance_authority6.cva)(
1378
1395
  [
1379
1396
  "u-shadow-border-transition",
1380
1397
  "box-border inline-flex items-center justify-center gap-md whitespace-nowrap",
@@ -1465,7 +1482,7 @@ var buttonStyles = (0, import_class_variance_authority7.cva)(
1465
1482
  );
1466
1483
 
1467
1484
  // src/button/Button.tsx
1468
- var import_jsx_runtime11 = require("react/jsx-runtime");
1485
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1469
1486
  var blockedEventHandlers = [
1470
1487
  "onClick",
1471
1488
  "onMouseDown",
@@ -1509,7 +1526,7 @@ var Button = ({
1509
1526
  className: loadingText ? "inline-block" : "absolute",
1510
1527
  ...loadingLabel && { "aria-label": loadingLabel }
1511
1528
  };
1512
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1529
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1513
1530
  Component,
1514
1531
  {
1515
1532
  "data-spark-component": "button",
@@ -1532,14 +1549,14 @@ var Button = ({
1532
1549
  children: wrapPolymorphicSlot(
1533
1550
  asChild,
1534
1551
  children,
1535
- (slotted) => isLoading ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Spinner, { ...spinnerProps }),
1552
+ (slotted) => isLoading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Spinner, { ...spinnerProps }),
1537
1554
  loadingText && loadingText,
1538
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1555
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1539
1556
  "div",
1540
1557
  {
1541
1558
  "aria-hidden": true,
1542
- className: (0, import_class_variance_authority8.cx)("gap-md", loadingText ? "hidden" : "inline-flex opacity-0"),
1559
+ className: (0, import_class_variance_authority7.cx)("gap-md", loadingText ? "hidden" : "inline-flex opacity-0"),
1543
1560
  children: slotted
1544
1561
  }
1545
1562
  )
@@ -1552,8 +1569,8 @@ Button.displayName = "Button";
1552
1569
 
1553
1570
  // src/icon-button/IconButton.styles.tsx
1554
1571
  var import_internal_utils9 = require("@spark-ui/internal-utils");
1555
- var import_class_variance_authority9 = require("class-variance-authority");
1556
- var iconButtonStyles = (0, import_class_variance_authority9.cva)(["pl-0 pr-0"], {
1572
+ var import_class_variance_authority8 = require("class-variance-authority");
1573
+ var iconButtonStyles = (0, import_class_variance_authority8.cva)(["pl-0 pr-0"], {
1557
1574
  variants: {
1558
1575
  /**
1559
1576
  * Sets the size of the icon.
@@ -1567,7 +1584,7 @@ var iconButtonStyles = (0, import_class_variance_authority9.cva)(["pl-0 pr-0"],
1567
1584
  });
1568
1585
 
1569
1586
  // src/icon-button/IconButton.tsx
1570
- var import_jsx_runtime12 = require("react/jsx-runtime");
1587
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1571
1588
  var IconButton = ({
1572
1589
  design = "filled",
1573
1590
  disabled = false,
@@ -1578,7 +1595,7 @@ var IconButton = ({
1578
1595
  ref,
1579
1596
  ...others
1580
1597
  }) => {
1581
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1598
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1582
1599
  Button,
1583
1600
  {
1584
1601
  "data-spark-component": "icon-button",
@@ -1596,15 +1613,16 @@ var IconButton = ({
1596
1613
  IconButton.displayName = "IconButton";
1597
1614
 
1598
1615
  // src/file-upload/FileUploadItemDeleteTrigger.tsx
1599
- var import_jsx_runtime13 = require("react/jsx-runtime");
1616
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1600
1617
  var ItemDeleteTrigger = ({
1601
1618
  className,
1602
- fileIndex,
1619
+ file,
1603
1620
  onClick,
1604
1621
  ...props
1605
1622
  }) => {
1606
- const { removeFile, triggerRef, dropzoneRef, deleteButtonRefs, disabled, readOnly } = useFileUploadContext();
1623
+ const { removeFile, triggerRef, dropzoneRef, deleteButtonRefs, disabled, readOnly, files } = useFileUploadContext();
1607
1624
  const buttonRef = (0, import_react9.useRef)(null);
1625
+ const fileIndex = files.findIndex((f) => f.name === file.name && f.size === file.size);
1608
1626
  const handleClick = (e) => {
1609
1627
  if (disabled || readOnly) {
1610
1628
  return;
@@ -1640,98 +1658,68 @@ var ItemDeleteTrigger = ({
1640
1658
  }
1641
1659
  }
1642
1660
  };
1643
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1661
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1644
1662
  IconButton,
1645
1663
  {
1646
1664
  ref: setRef,
1647
1665
  "data-spark-component": "file-upload-item-delete-trigger",
1648
- className: (0, import_class_variance_authority10.cx)(className),
1666
+ className: (0, import_class_variance_authority9.cx)(className),
1649
1667
  onClick: handleClick,
1650
1668
  disabled: disabled || readOnly,
1651
1669
  size: "sm",
1652
1670
  design: "contrast",
1653
1671
  intent: "surface",
1654
1672
  ...props,
1655
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_Close.Close, {}) })
1673
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_Close.Close, {}) })
1656
1674
  }
1657
1675
  );
1658
1676
  };
1659
1677
  ItemDeleteTrigger.displayName = "FileUpload.ItemDeleteTrigger";
1660
1678
 
1661
- // src/file-upload/FileUploadItemFileName.tsx
1662
- var import_class_variance_authority11 = require("class-variance-authority");
1663
- var import_jsx_runtime14 = require("react/jsx-runtime");
1664
- var ItemFileName = ({
1665
- asChild: _asChild = false,
1666
- className,
1667
- children,
1668
- ...props
1669
- }) => {
1670
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1671
- "p",
1672
- {
1673
- "data-spark-component": "file-upload-item-file-name",
1674
- className: (0, import_class_variance_authority11.cx)("text-body-2 truncate font-medium", className),
1675
- ...props,
1676
- children
1677
- }
1678
- );
1679
- };
1680
- ItemFileName.displayName = "FileUpload.ItemFileName";
1681
-
1682
- // src/file-upload/FileUploadItemSizeText.tsx
1683
- var import_class_variance_authority12 = require("class-variance-authority");
1684
- var import_jsx_runtime15 = require("react/jsx-runtime");
1685
- var ItemSizeText = ({
1686
- asChild: _asChild = false,
1687
- className,
1688
- children,
1689
- ...props
1690
- }) => {
1691
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1692
- "p",
1693
- {
1694
- "data-spark-component": "file-upload-item-size-text",
1695
- className: (0, import_class_variance_authority12.cx)("text-caption", className),
1696
- ...props,
1697
- children
1698
- }
1699
- );
1700
- };
1701
- ItemSizeText.displayName = "FileUpload.ItemSizeText";
1702
-
1703
1679
  // src/file-upload/FileUploadAcceptedFile.tsx
1704
- var import_jsx_runtime16 = require("react/jsx-runtime");
1680
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1705
1681
  var AcceptedFile = ({
1706
1682
  asChild: _asChild = false,
1707
1683
  className,
1708
1684
  file,
1709
- fileIndex,
1710
1685
  uploadProgress,
1711
1686
  deleteButtonAriaLabel,
1712
1687
  progressAriaLabel,
1713
1688
  ...props
1714
1689
  }) => {
1715
1690
  const { locale } = useFileUploadContext();
1716
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Item, { className, ...props, children: [
1717
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "size-sz-40 bg-support-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { size: "md", children: getFileIcon(file) }) }),
1718
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "min-w-0 flex-1", children: [
1719
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "gap-md flex flex-row items-center justify-between", children: [
1720
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ItemFileName, { children: file.name }),
1721
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ItemSizeText, { className: "opacity-dim-1", children: formatFileSize(file.size, locale) })
1722
- ] }),
1723
- uploadProgress !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "mt-md", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Progress2, { value: uploadProgress, max: 100, "aria-label": progressAriaLabel }) })
1724
- ] }),
1725
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ItemDeleteTrigger, { "aria-label": deleteButtonAriaLabel, fileIndex })
1726
- ] });
1691
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1692
+ "li",
1693
+ {
1694
+ "data-spark-component": "file-upload-accepted-file",
1695
+ className: (0, import_class_variance_authority10.cx)(
1696
+ "relative",
1697
+ "default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md",
1698
+ "gap-md flex items-center justify-between default:w-full",
1699
+ className
1700
+ ),
1701
+ ...props,
1702
+ children: [
1703
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "size-sz-40 bg-support-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: "md", children: getFileIcon(file) }) }),
1704
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "min-w-0 flex-1", children: [
1705
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gap-md flex flex-row items-center justify-between", children: [
1706
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-body-2 truncate font-medium", children: file.name }),
1707
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-caption opacity-dim-1", children: formatFileSize(file.size, locale) })
1708
+ ] }),
1709
+ uploadProgress !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-md", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Progress2, { value: uploadProgress, max: 100, "aria-label": progressAriaLabel }) })
1710
+ ] }),
1711
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ItemDeleteTrigger, { "aria-label": deleteButtonAriaLabel, file })
1712
+ ]
1713
+ }
1714
+ );
1727
1715
  };
1728
1716
  AcceptedFile.displayName = "FileUpload.AcceptedFile";
1729
1717
 
1730
1718
  // src/file-upload/FileUploadContext.tsx
1731
- var import_jsx_runtime17 = require("react/jsx-runtime");
1719
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1732
1720
  var Context = ({ children }) => {
1733
1721
  const { files = [], rejectedFiles = [], locale } = useFileUploadContext();
1734
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: children({
1722
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: children({
1735
1723
  acceptedFiles: files,
1736
1724
  rejectedFiles,
1737
1725
  formatFileSize,
@@ -1741,12 +1729,11 @@ var Context = ({ children }) => {
1741
1729
  Context.displayName = "FileUpload.Context";
1742
1730
 
1743
1731
  // src/file-upload/FileUploadDropzone.tsx
1744
- var import_class_variance_authority13 = require("class-variance-authority");
1732
+ var import_class_variance_authority11 = require("class-variance-authority");
1745
1733
  var import_react10 = require("react");
1746
- var import_jsx_runtime18 = require("react/jsx-runtime");
1734
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1747
1735
  function Dropzone({
1748
1736
  children,
1749
- onFiles,
1750
1737
  className,
1751
1738
  unstyled = false
1752
1739
  }) {
@@ -1761,7 +1748,6 @@ function Dropzone({
1761
1748
  return;
1762
1749
  }
1763
1750
  const files = e.dataTransfer.files;
1764
- onFiles?.(files);
1765
1751
  let filesArray = [];
1766
1752
  if (files) {
1767
1753
  filesArray = Array.isArray(files) ? [...files] : Array.from(files);
@@ -1784,7 +1770,7 @@ function Dropzone({
1784
1770
  }
1785
1771
  };
1786
1772
  const isDisabled = ctx.disabled || ctx.readOnly;
1787
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1773
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1788
1774
  "div",
1789
1775
  {
1790
1776
  ref: (node) => {
@@ -1796,18 +1782,21 @@ function Dropzone({
1796
1782
  role: "button",
1797
1783
  tabIndex: isDisabled ? -1 : 0,
1798
1784
  "aria-disabled": ctx.disabled ? true : void 0,
1785
+ "aria-describedby": ctx.description,
1786
+ "aria-invalid": ctx.isInvalid,
1787
+ "aria-required": ctx.isRequired,
1799
1788
  onClick: handleClick,
1800
1789
  onKeyDown: handleKeyDown,
1801
1790
  onDrop: handleDrop,
1802
1791
  onDragOver: (e) => {
1803
1792
  e.preventDefault();
1804
1793
  },
1805
- className: unstyled ? className : (0, import_class_variance_authority13.cx)(
1806
- "default:bg-surface default:border-sm default:border-outline default:rounded-lg default:border-dashed",
1794
+ className: unstyled ? className : (0, import_class_variance_authority11.cx)(
1795
+ "default:bg-surface default:border-sm default:border-outline default:relative default:rounded-lg default:border-dashed",
1807
1796
  "gap-lg flex flex-col items-center justify-center text-center",
1808
1797
  "default:p-xl",
1809
1798
  "transition-colors duration-200",
1810
- !isDisabled && "hover:bg-surface-hovered",
1799
+ !isDisabled && "default:hover:bg-surface-hovered",
1811
1800
  "data-[drag-over=true]:border-outline-high data-[drag-over=true]:bg-surface-hovered data-[drag-over=true]:border-solid",
1812
1801
  // Disabled: more visually disabled (opacity + cursor)
1813
1802
  ctx.disabled && "cursor-not-allowed opacity-50",
@@ -1830,9 +1819,9 @@ function Dropzone({
1830
1819
  Dropzone.displayName = "FileUploadDropzone";
1831
1820
 
1832
1821
  // src/file-upload/FileUploadPreviewImage.tsx
1833
- var import_class_variance_authority14 = require("class-variance-authority");
1822
+ var import_class_variance_authority12 = require("class-variance-authority");
1834
1823
  var import_react11 = require("react");
1835
- var import_jsx_runtime19 = require("react/jsx-runtime");
1824
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1836
1825
  var PreviewImage = ({
1837
1826
  asChild: _asChild = false,
1838
1827
  className,
@@ -1852,11 +1841,11 @@ var PreviewImage = ({
1852
1841
  };
1853
1842
  }, [imageUrl]);
1854
1843
  if (!isImage || imageError) {
1855
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1844
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1856
1845
  "div",
1857
1846
  {
1858
1847
  "data-spark-component": "file-upload-preview-image",
1859
- className: (0, import_class_variance_authority14.cx)(
1848
+ className: (0, import_class_variance_authority12.cx)(
1860
1849
  "bg-neutral-container flex items-center justify-center rounded-md",
1861
1850
  className
1862
1851
  ),
@@ -1865,24 +1854,24 @@ var PreviewImage = ({
1865
1854
  }
1866
1855
  );
1867
1856
  }
1868
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1857
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1869
1858
  "div",
1870
1859
  {
1871
1860
  "data-spark-component": "file-upload-preview-image",
1872
- className: (0, import_class_variance_authority14.cx)("bg-neutral-container overflow-hidden", className),
1861
+ className: (0, import_class_variance_authority12.cx)("bg-neutral-container overflow-hidden", className),
1873
1862
  ...props,
1874
1863
  children: [
1875
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1864
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1876
1865
  "img",
1877
1866
  {
1878
1867
  src: imageUrl,
1879
1868
  alt: file.name,
1880
- className: (0, import_class_variance_authority14.cx)("size-full object-cover", !imageLoaded && "opacity-0"),
1869
+ className: (0, import_class_variance_authority12.cx)("size-full object-cover", !imageLoaded && "opacity-0"),
1881
1870
  onLoad: () => setImageLoaded(true),
1882
1871
  onError: () => setImageError(true)
1883
1872
  }
1884
1873
  ),
1885
- !imageLoaded && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "absolute inset-0 flex items-center justify-center", children: fallback })
1874
+ !imageLoaded && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "absolute inset-0 flex items-center justify-center", children: fallback })
1886
1875
  ]
1887
1876
  }
1888
1877
  );
@@ -1891,21 +1880,24 @@ PreviewImage.displayName = "FileUpload.PreviewImage";
1891
1880
 
1892
1881
  // src/file-upload/FileUploadRejectedFile.tsx
1893
1882
  var import_WarningOutline = require("@spark-ui/icons/WarningOutline");
1894
- var import_class_variance_authority16 = require("class-variance-authority");
1883
+ var import_class_variance_authority14 = require("class-variance-authority");
1895
1884
 
1896
1885
  // src/file-upload/FileUploadRejectedFileDeleteTrigger.tsx
1897
1886
  var import_Close2 = require("@spark-ui/icons/Close");
1898
- var import_class_variance_authority15 = require("class-variance-authority");
1887
+ var import_class_variance_authority13 = require("class-variance-authority");
1899
1888
  var import_react12 = require("react");
1900
- var import_jsx_runtime20 = require("react/jsx-runtime");
1889
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1901
1890
  var RejectedFileDeleteTrigger = ({
1902
1891
  className,
1903
- rejectedFileIndex,
1892
+ rejectedFile,
1904
1893
  onClick,
1905
1894
  ...props
1906
1895
  }) => {
1907
- const { removeRejectedFile, triggerRef, dropzoneRef, disabled, readOnly } = useFileUploadContext();
1896
+ const { removeRejectedFile, triggerRef, dropzoneRef, disabled, readOnly, rejectedFiles } = useFileUploadContext();
1908
1897
  const buttonRef = (0, import_react12.useRef)(null);
1898
+ const rejectedFileIndex = rejectedFiles.findIndex(
1899
+ (rf) => rf.file.name === rejectedFile.file.name && rf.file.size === rejectedFile.file.size
1900
+ );
1909
1901
  const handleClick = (e) => {
1910
1902
  if (disabled || readOnly) {
1911
1903
  return;
@@ -1919,59 +1911,66 @@ var RejectedFileDeleteTrigger = ({
1919
1911
  }, 0);
1920
1912
  onClick?.(e);
1921
1913
  };
1922
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1914
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1923
1915
  IconButton,
1924
1916
  {
1925
1917
  ref: buttonRef,
1926
1918
  "data-spark-component": "file-upload-rejected-file-delete-trigger",
1927
- className: (0, import_class_variance_authority15.cx)(className),
1919
+ className: (0, import_class_variance_authority13.cx)(className),
1928
1920
  onClick: handleClick,
1929
1921
  disabled: disabled || readOnly,
1930
1922
  size: "sm",
1931
1923
  design: "contrast",
1932
1924
  intent: "surface",
1933
1925
  ...props,
1934
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_Close2.Close, {}) })
1926
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Icon, { size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_Close2.Close, {}) })
1935
1927
  }
1936
1928
  );
1937
1929
  };
1938
1930
  RejectedFileDeleteTrigger.displayName = "FileUpload.RejectedFileDeleteTrigger";
1939
1931
 
1940
1932
  // src/file-upload/FileUploadRejectedFile.tsx
1941
- var import_jsx_runtime21 = require("react/jsx-runtime");
1933
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1942
1934
  var RejectedFile = ({
1943
1935
  asChild: _asChild = false,
1944
1936
  className,
1945
1937
  rejectedFile,
1946
- rejectedFileIndex,
1947
1938
  renderError,
1948
1939
  deleteButtonAriaLabel,
1949
1940
  ...props
1950
1941
  }) => {
1951
1942
  const { locale } = useFileUploadContext();
1952
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Item, { className: (0, import_class_variance_authority16.cx)("border-error border-md", className), ...props, children: [
1953
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "size-sz-40 bg-error-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { size: "md", className: "text-error", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_WarningOutline.WarningOutline, {}) }) }),
1954
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "gap-md flex flex-col", children: [
1955
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "gap-md flex flex-row items-center justify-between", children: [
1956
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemFileName, { children: rejectedFile.file.name }),
1957
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemSizeText, { className: "opacity-dim-1", children: formatFileSize(rejectedFile.file.size, locale) })
1958
- ] }),
1959
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gap-xs flex flex-col", children: rejectedFile.errors.map((error, errorIndex) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-caption text-error", "data-error-code": error, children: renderError(error) }, errorIndex)) })
1960
- ] }) }),
1961
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1962
- RejectedFileDeleteTrigger,
1963
- {
1964
- "aria-label": deleteButtonAriaLabel,
1965
- rejectedFileIndex
1966
- }
1967
- )
1968
- ] });
1943
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1944
+ "li",
1945
+ {
1946
+ "data-spark-component": "file-upload-rejected-file",
1947
+ className: (0, import_class_variance_authority14.cx)(
1948
+ "relative",
1949
+ "default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md",
1950
+ "gap-md flex items-center justify-between default:w-full",
1951
+ "border-error border-md",
1952
+ className
1953
+ ),
1954
+ ...props,
1955
+ children: [
1956
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "size-sz-40 bg-error-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Icon, { size: "md", className: "text-error", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_WarningOutline.WarningOutline, {}) }) }),
1957
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "gap-md flex flex-col", children: [
1958
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "gap-md flex flex-row items-center justify-between", children: [
1959
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-body-2 truncate font-medium", children: rejectedFile.file.name }),
1960
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-caption opacity-dim-1", children: formatFileSize(rejectedFile.file.size, locale) })
1961
+ ] }),
1962
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "gap-xs flex flex-col", children: rejectedFile.errors.map((error, errorIndex) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-caption text-error", "data-error-code": error, children: renderError(error) }, errorIndex)) })
1963
+ ] }) }),
1964
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(RejectedFileDeleteTrigger, { "aria-label": deleteButtonAriaLabel, rejectedFile })
1965
+ ]
1966
+ }
1967
+ );
1969
1968
  };
1970
1969
  RejectedFile.displayName = "FileUpload.RejectedFile";
1971
1970
 
1972
1971
  // src/file-upload/FileUploadTrigger.tsx
1973
- var import_class_variance_authority17 = require("class-variance-authority");
1974
- var import_jsx_runtime22 = require("react/jsx-runtime");
1972
+ var import_class_variance_authority15 = require("class-variance-authority");
1973
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1975
1974
  var Trigger = ({
1976
1975
  className,
1977
1976
  children,
@@ -1982,7 +1981,7 @@ var Trigger = ({
1982
1981
  ref,
1983
1982
  ...props
1984
1983
  }) => {
1985
- const { inputRef, triggerRef, disabled, readOnly } = useFileUploadContext();
1984
+ const { inputRef, triggerRef, disabled, readOnly, description, isInvalid, isRequired } = useFileUploadContext();
1986
1985
  const handleClick = (e) => {
1987
1986
  e.stopPropagation();
1988
1987
  e.preventDefault();
@@ -1992,7 +1991,7 @@ var Trigger = ({
1992
1991
  };
1993
1992
  const buttonComponent = unstyled ? "button" : Button;
1994
1993
  const Comp = asChild ? Slot : buttonComponent;
1995
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1994
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1996
1995
  Comp,
1997
1996
  {
1998
1997
  type: "button",
@@ -2011,9 +2010,12 @@ var Trigger = ({
2011
2010
  design,
2012
2011
  intent,
2013
2012
  "data-spark-component": "file-upload-trigger",
2014
- className: (0, import_class_variance_authority17.cx)(className),
2013
+ className: (0, import_class_variance_authority15.cx)(className),
2015
2014
  disabled: disabled || readOnly,
2016
2015
  onClick: handleClick,
2016
+ "aria-describedby": description,
2017
+ "aria-invalid": isInvalid,
2018
+ "aria-required": isRequired,
2017
2019
  ...props,
2018
2020
  children
2019
2021
  }
@@ -2023,25 +2025,22 @@ Trigger.displayName = "FileUpload.Trigger";
2023
2025
 
2024
2026
  // src/file-upload/index.ts
2025
2027
  var FileUpload2 = Object.assign(FileUpload, {
2028
+ // Main input components
2026
2029
  Trigger,
2027
2030
  Dropzone,
2031
+ // Context components
2028
2032
  Context,
2029
- Item,
2030
- ItemFileName,
2031
- ItemSizeText,
2032
- ItemDeleteTrigger,
2033
- PreviewImage,
2034
2033
  AcceptedFile,
2035
2034
  RejectedFile,
2035
+ // Helpers for custom renders
2036
+ PreviewImage,
2037
+ ItemDeleteTrigger,
2036
2038
  RejectedFileDeleteTrigger
2037
2039
  });
2038
2040
  FileUpload2.displayName = "FileUpload";
2039
2041
  Trigger.displayName = "FileUpload.Trigger";
2040
2042
  Dropzone.displayName = "FileUpload.Dropzone";
2041
2043
  Context.displayName = "FileUpload.Context";
2042
- Item.displayName = "FileUpload.Item";
2043
- ItemFileName.displayName = "FileUpload.ItemFileName";
2044
- ItemSizeText.displayName = "FileUpload.ItemSizeText";
2045
2044
  ItemDeleteTrigger.displayName = "FileUpload.ItemDeleteTrigger";
2046
2045
  PreviewImage.displayName = "FileUpload.PreviewImage";
2047
2046
  AcceptedFile.displayName = "FileUpload.AcceptedFile";