@timeax/form-palette 0.0.18 → 0.0.20

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.
package/dist/index.js CHANGED
@@ -36668,11 +36668,9 @@ var checkboxModule = {
36668
36668
  tags: ["checkbox", "group", "boolean", "tri-state"]
36669
36669
  }
36670
36670
  };
36671
- function capitalizeFirst3(label) {
36672
- if (!label) return label;
36673
- return label.charAt(0).toUpperCase() + label.slice(1);
36674
- }
36675
- function normalizeOptions(opts, config3) {
36671
+
36672
+ // src/lib/normalise-selects.ts
36673
+ function globalNormalizeOptions(opts, config3) {
36676
36674
  if (!opts || !opts.length) return [];
36677
36675
  return opts.map((raw, index2) => {
36678
36676
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
@@ -36699,6 +36697,13 @@ function normalizeOptions(opts, config3) {
36699
36697
  };
36700
36698
  });
36701
36699
  }
36700
+ function capitalizeFirst3(label) {
36701
+ if (!label) return label;
36702
+ return label.charAt(0).toUpperCase() + label.slice(1);
36703
+ }
36704
+ function normalizeOptions(opts, config3) {
36705
+ return globalNormalizeOptions(opts, config3);
36706
+ }
36702
36707
  function triggerHeight(size4) {
36703
36708
  switch (size4) {
36704
36709
  case "sm":
@@ -37320,36 +37325,8 @@ function removeSelectValue(current, valueToRemove) {
37320
37325
  const target = String(valueToRemove);
37321
37326
  return current.filter((v) => String(v) !== target);
37322
37327
  }
37323
- function capitalizeFirst4(label) {
37324
- if (!label) return label;
37325
- return label.charAt(0).toUpperCase() + label.slice(1);
37326
- }
37327
37328
  function normalizeOptions2(opts, config3) {
37328
- if (!opts || !opts.length) return [];
37329
- return opts.map((raw, index2) => {
37330
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
37331
- const asObj = typeof raw === "string" || typeof raw === "number" ? { label: String(raw), value: raw } : raw;
37332
- const value = typeof config3.optionValue === "function" ? config3.optionValue(raw) : typeof config3.optionValue === "string" ? asObj[config3.optionValue] : (_c = (_b = (_a = asObj.value) != null ? _a : asObj.id) != null ? _b : asObj.key) != null ? _c : String(index2);
37333
- let labelNode = typeof config3.optionLabel === "function" ? config3.optionLabel(raw) : typeof config3.optionLabel === "string" ? (_e = (_d = asObj[config3.optionLabel]) != null ? _d : asObj.label) != null ? _e : String(value) : (_f = asObj.label) != null ? _f : String(value);
37334
- if (config3.autoCap && typeof labelNode === "string") {
37335
- labelNode = capitalizeFirst4(labelNode);
37336
- }
37337
- const labelText = typeof labelNode === "string" ? labelNode : typeof labelNode === "number" ? String(labelNode) : (_g = asObj.labelText) != null ? _g : String(value);
37338
- const description = typeof config3.optionDescription === "function" ? config3.optionDescription(raw) : typeof config3.optionDescription === "string" ? asObj[config3.optionDescription] : asObj.description;
37339
- const disabled = typeof config3.optionDisabled === "function" ? config3.optionDisabled(raw) : typeof config3.optionDisabled === "string" ? !!asObj[config3.optionDisabled] : !!asObj.disabled;
37340
- const icon = typeof config3.optionIcon === "function" ? config3.optionIcon(raw) : typeof config3.optionIcon === "string" ? asObj[config3.optionIcon] : asObj.icon;
37341
- const key = typeof config3.optionKey === "function" ? config3.optionKey(raw, index2) : typeof config3.optionKey === "string" ? (_i = (_h = asObj[config3.optionKey]) != null ? _h : value) != null ? _i : index2 : (_k = (_j = asObj.key) != null ? _j : value) != null ? _k : index2;
37342
- return {
37343
- key: String(key),
37344
- value,
37345
- labelNode,
37346
- labelText,
37347
- description,
37348
- disabled,
37349
- icon,
37350
- raw
37351
- };
37352
- });
37329
+ return globalNormalizeOptions(opts, config3);
37353
37330
  }
37354
37331
  function triggerHeight2(size4) {
37355
37332
  switch (size4) {
@@ -37453,9 +37430,7 @@ var ShadcnMultiSelectVariant = React54__namespace.forwardRef(function ShadcnMult
37453
37430
  const filteredItems = React54__namespace.useMemo(() => {
37454
37431
  if (!query) return items;
37455
37432
  const q = query.toLowerCase();
37456
- return items.filter(
37457
- (it) => it.labelText.toLowerCase().includes(q)
37458
- );
37433
+ return items.filter((it) => it.labelText.toLowerCase().includes(q));
37459
37434
  }, [items, query]);
37460
37435
  const selectableItems = React54__namespace.useMemo(
37461
37436
  () => items.filter((it) => !it.disabled),
@@ -37608,7 +37583,7 @@ var ShadcnMultiSelectVariant = React54__namespace.forwardRef(function ShadcnMult
37608
37583
  type: "button",
37609
37584
  disabled: disabledTrigger,
37610
37585
  className: cn(
37611
- "flex w-full items-center justify-between rounded-md border border-input bg-background px-3 text-left shadow-xs",
37586
+ "flex w-full items-center justify-between rounded-md border border-input bg-surfaces-input px-3 text-left shadow-xs",
37612
37587
  "focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring",
37613
37588
  "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
37614
37589
  heightCls,
@@ -37733,9 +37708,7 @@ var ShadcnMultiSelectVariant = React54__namespace.forwardRef(function ShadcnMult
37733
37708
  }
37734
37709
  ),
37735
37710
  filteredItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: emptySearchText != null ? emptySearchText : "No results found" }) : filteredItems.map((item, index2) => {
37736
- const selected = selectedValues.has(
37737
- item.value
37738
- );
37711
+ const selected = selectedValues.has(item.value);
37739
37712
  const row = /* @__PURE__ */ jsxRuntime.jsxs(
37740
37713
  "button",
37741
37714
  {
@@ -37866,9 +37839,7 @@ var ShadcnMultiSelectVariant = React54__namespace.forwardRef(function ShadcnMult
37866
37839
  /* @__PURE__ */ jsxRuntime.jsx(
37867
37840
  "div",
37868
37841
  {
37869
- className: cn(
37870
- "flex-1 min-w-0 flex items-stretch"
37871
- ),
37842
+ className: cn("flex-1 min-w-0 flex items-stretch"),
37872
37843
  "data-slot": "select-region",
37873
37844
  children: MultiSelectCore
37874
37845
  }
@@ -39587,12 +39558,11 @@ function clampVisible(total, minVisible, maxVisible) {
39587
39558
  function sizeClasses(size4) {
39588
39559
  switch (size4) {
39589
39560
  case "sm":
39590
- return "text-xs min-h-[2rem]";
39561
+ return "h-8 text-xs";
39591
39562
  case "lg":
39592
- return "text-sm min-h-[2.75rem]";
39593
- case "md":
39563
+ return "h-11 text-base";
39594
39564
  default:
39595
- return "text-sm min-h-[2.5rem]";
39565
+ return "h-9 text-sm";
39596
39566
  }
39597
39567
  }
39598
39568
  function densityPadding(density) {
@@ -39603,7 +39573,7 @@ function densityPadding(density) {
39603
39573
  return "py-3 px-3 gap-3";
39604
39574
  case "comfortable":
39605
39575
  default:
39606
- return "py-2 px-3 gap-2";
39576
+ return "py-1 px-3 gap-2";
39607
39577
  }
39608
39578
  }
39609
39579
  function defaultMoreLabel(count3) {
@@ -40097,7 +40067,7 @@ function Badge({
40097
40067
  }
40098
40068
  );
40099
40069
  }
40100
- function capitalizeFirst5(label) {
40070
+ function capitalizeFirst4(label) {
40101
40071
  if (!label) return label;
40102
40072
  return label.charAt(0).toUpperCase() + label.slice(1);
40103
40073
  }
@@ -40109,7 +40079,7 @@ function normalizeTree(opts, config3, level = 0, parentValue, path = []) {
40109
40079
  const value = typeof config3.optionValue === "function" ? config3.optionValue(raw) : typeof config3.optionValue === "string" ? asObj[config3.optionValue] : (_c = (_b = (_a = asObj.value) != null ? _a : asObj.id) != null ? _b : asObj.key) != null ? _c : String(index2);
40110
40080
  let labelNode = typeof config3.optionLabel === "function" ? config3.optionLabel(raw) : typeof config3.optionLabel === "string" ? (_e = (_d = asObj[config3.optionLabel]) != null ? _d : asObj.label) != null ? _e : String(value) : (_f = asObj.label) != null ? _f : String(value);
40111
40081
  if (config3.autoCap && typeof labelNode === "string") {
40112
- labelNode = capitalizeFirst5(labelNode);
40082
+ labelNode = capitalizeFirst4(labelNode);
40113
40083
  }
40114
40084
  const labelText = typeof labelNode === "string" ? labelNode : typeof labelNode === "number" ? String(labelNode) : (_g = asObj.labelText) != null ? _g : String(value);
40115
40085
  const description = typeof config3.optionDescription === "function" ? config3.optionDescription(raw) : typeof config3.optionDescription === "string" ? asObj[config3.optionDescription] : asObj.description;
@@ -41438,15 +41408,34 @@ function formatSizeDefault(size4) {
41438
41408
  const mb = kb / 1024;
41439
41409
  return `${mb.toFixed(1)} MB`;
41440
41410
  }
41441
- function sliderHeight2(size4) {
41411
+ function triggerHeight4(size4) {
41442
41412
  switch (size4) {
41443
41413
  case "sm":
41444
- return "min-h-8 text-xs";
41414
+ return "h-8 text-xs";
41445
41415
  case "lg":
41446
- return "min-h-12 text-base";
41447
- case "md":
41416
+ return "h-11 text-base";
41417
+ default:
41418
+ return "h-9 text-sm";
41419
+ }
41420
+ }
41421
+ function chipHeight(size4) {
41422
+ switch (size4) {
41423
+ case "sm":
41424
+ return "h-5";
41425
+ case "lg":
41426
+ return "h-7";
41427
+ default:
41428
+ return "h-6";
41429
+ }
41430
+ }
41431
+ function pickerBtnSize(size4) {
41432
+ switch (size4) {
41433
+ case "sm":
41434
+ return "h-6 w-6";
41435
+ case "lg":
41436
+ return "h-8 w-8";
41448
41437
  default:
41449
- return "min-h-10 text-sm";
41438
+ return "h-7 w-7";
41450
41439
  }
41451
41440
  }
41452
41441
  function toArray(v) {
@@ -41523,481 +41512,657 @@ var FileThumbnail = ({ item }) => {
41523
41512
  setPreview(item.url || item.path || null);
41524
41513
  }
41525
41514
  }, [item]);
41526
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-sm border bg-muted/50", children: preview ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: preview, alt: "", className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-4 w-4 text-muted-foreground/50" }) });
41515
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-sm border bg-muted/50", children: preview ? /* @__PURE__ */ jsxRuntime.jsx(
41516
+ "img",
41517
+ {
41518
+ src: preview,
41519
+ alt: "",
41520
+ className: "h-full w-full object-cover"
41521
+ }
41522
+ ) : /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-4 w-4 text-muted-foreground/50" }) });
41527
41523
  };
41528
- var ShadcnFileVariant = React54__namespace.forwardRef(
41529
- function ShadcnFileVariant2(props, ref) {
41530
- const {
41531
- value,
41532
- onValue,
41533
- disabled,
41534
- readOnly,
41535
- error,
41536
- size: size4 = "md",
41537
- density = "comfortable",
41538
- multiple = false,
41539
- accept,
41540
- maxFiles,
41541
- maxTotalSize,
41542
- showDropArea = false,
41543
- dropIcon,
41544
- dropTitle,
41545
- dropDescription,
41546
- renderDropArea,
41547
- renderFileItem,
41548
- showCheckboxes,
41549
- onFilesAdded,
41550
- customLoader,
41551
- mergeMode = "append",
41552
- formatFileName,
41553
- formatFileSize = formatSizeDefault,
41554
- placeholder = "Select file...",
41555
- className,
41556
- dropAreaClassName,
41557
- listClassName,
41558
- leadingIcons,
41559
- trailingIcons,
41560
- icon,
41561
- leadingControl,
41562
- trailingControl,
41563
- leadingControlClassName,
41564
- trailingControlClassName,
41565
- joinControls = true,
41566
- extendBoxToControls = true
41567
- } = props;
41568
- const items = value != null ? value : [];
41569
- const isDisabled = !!disabled || !!readOnly;
41570
- const [dragOver, setDragOver] = React54__namespace.useState(false);
41571
- const [selectedIds, setSelectedIds] = React54__namespace.useState(() => /* @__PURE__ */ new Set());
41572
- const [popoverOpen, setPopoverOpen] = React54__namespace.useState(false);
41573
- const fileInputRef = React54__namespace.useRef(null);
41574
- const heightCls = sliderHeight2(size4);
41575
- const resolvedLeadingIcons = leadingIcons || (icon ? [icon] : []);
41576
- const resolvedTrailingIcons = trailingIcons || [];
41577
- const hasExternalControls = !!leadingControl || !!trailingControl;
41578
- const COLLAPSE_LIMIT = 2;
41579
- const emitChange = React54__namespace.useCallback(
41580
- (next, meta) => {
41581
- onValue == null ? void 0 : onValue(next, { source: "variant", raw: next, nativeEvent: void 0, meta });
41582
- },
41583
- [onValue]
41584
- );
41585
- const handleAddItems = (incoming, from) => {
41586
- if (isDisabled) return;
41587
- let next = multiple ? [...items] : [];
41588
- const added = [];
41589
- for (const item of incoming) {
41590
- if (multiple && maxFiles && next.length >= maxFiles) break;
41591
- const currentTotalSize = next.reduce((acc, i) => acc + (i.size || 0), 0);
41592
- if (maxTotalSize && currentTotalSize + (item.size || 0) > maxTotalSize) break;
41593
- next.push(item);
41594
- added.push(item);
41595
- }
41596
- if (added.length > 0) {
41597
- onFilesAdded == null ? void 0 : onFilesAdded(added, { source: "variant", raw: added, nativeEvent: void 0, meta: { from } });
41598
- emitChange(next, { action: "add", from, added });
41599
- }
41600
- };
41601
- const handleRemove = (id) => {
41602
- const next = items.filter((i) => i.id !== id);
41603
- emitChange(next, { action: "remove", id });
41604
- if (selectedIds.has(id)) {
41605
- const nextSel = new Set(selectedIds);
41606
- nextSel.delete(id);
41607
- setSelectedIds(nextSel);
41524
+ var ShadcnFileVariant = React54__namespace.forwardRef(function ShadcnFileVariant2(props, ref) {
41525
+ const {
41526
+ value,
41527
+ onValue,
41528
+ disabled,
41529
+ readOnly,
41530
+ error,
41531
+ size: size4 = "md",
41532
+ density = "comfortable",
41533
+ multiple = false,
41534
+ accept,
41535
+ maxFiles,
41536
+ maxTotalSize,
41537
+ showDropArea = false,
41538
+ dropIcon,
41539
+ dropTitle,
41540
+ dropDescription,
41541
+ renderDropArea,
41542
+ renderFileItem,
41543
+ showCheckboxes,
41544
+ onFilesAdded,
41545
+ customLoader,
41546
+ mergeMode = "append",
41547
+ formatFileName,
41548
+ formatFileSize = formatSizeDefault,
41549
+ placeholder = "Select file...",
41550
+ className,
41551
+ dropAreaClassName,
41552
+ listClassName,
41553
+ leadingIcons,
41554
+ trailingIcons,
41555
+ icon,
41556
+ leadingControl,
41557
+ trailingControl,
41558
+ leadingControlClassName,
41559
+ trailingControlClassName,
41560
+ joinControls = true,
41561
+ extendBoxToControls = true
41562
+ } = props;
41563
+ const items = value != null ? value : [];
41564
+ const isDisabled = Boolean(disabled || readOnly);
41565
+ const [dragOver, setDragOver] = React54__namespace.useState(false);
41566
+ const [selectedIds, setSelectedIds] = React54__namespace.useState(
41567
+ () => /* @__PURE__ */ new Set()
41568
+ );
41569
+ const [popoverOpen, setPopoverOpen] = React54__namespace.useState(false);
41570
+ const fileInputRef = React54__namespace.useRef(null);
41571
+ const heightCls = triggerHeight4(size4);
41572
+ const chipHeightCls = chipHeight(size4);
41573
+ const pickerBtnCls = pickerBtnSize(size4);
41574
+ const resolvedLeadingIcons = leadingIcons || (icon ? [icon] : []);
41575
+ const resolvedTrailingIcons = trailingIcons || [];
41576
+ const hasExternalControls = !!leadingControl || !!trailingControl;
41577
+ const COLLAPSE_LIMIT = 2;
41578
+ const emitChange = React54__namespace.useCallback(
41579
+ (next, meta) => {
41580
+ onValue == null ? void 0 : onValue(next, {
41581
+ source: "variant",
41582
+ raw: next,
41583
+ nativeEvent: void 0,
41584
+ meta
41585
+ });
41586
+ },
41587
+ [onValue]
41588
+ );
41589
+ const handleAddItems = (incoming, from) => {
41590
+ if (isDisabled) return;
41591
+ let next = multiple ? [...items] : [];
41592
+ const added = [];
41593
+ for (const item of incoming) {
41594
+ if (multiple && maxFiles && next.length >= maxFiles) break;
41595
+ const currentTotalSize = next.reduce(
41596
+ (acc, i) => acc + (i.size || 0),
41597
+ 0
41598
+ );
41599
+ if (maxTotalSize && currentTotalSize + (item.size || 0) > maxTotalSize)
41600
+ break;
41601
+ next.push(item);
41602
+ added.push(item);
41603
+ }
41604
+ if (added.length > 0) {
41605
+ onFilesAdded == null ? void 0 : onFilesAdded(added, {
41606
+ source: "variant",
41607
+ raw: added,
41608
+ nativeEvent: void 0,
41609
+ meta: { from }
41610
+ });
41611
+ emitChange(next, { action: "add", from, added });
41612
+ }
41613
+ };
41614
+ const handleRemove = (id) => {
41615
+ const next = items.filter((i) => i.id !== id);
41616
+ emitChange(next, { action: "remove", id });
41617
+ if (selectedIds.has(id)) {
41618
+ const nextSel = new Set(selectedIds);
41619
+ nextSel.delete(id);
41620
+ setSelectedIds(nextSel);
41621
+ }
41622
+ };
41623
+ const handleBulkRemove = () => {
41624
+ const next = items.filter((i) => !selectedIds.has(i.id));
41625
+ emitChange(next, {
41626
+ action: "bulk-remove",
41627
+ ids: Array.from(selectedIds)
41628
+ });
41629
+ setSelectedIds(/* @__PURE__ */ new Set());
41630
+ };
41631
+ const openPicker = async () => {
41632
+ var _a;
41633
+ if (isDisabled) return;
41634
+ if (customLoader) {
41635
+ try {
41636
+ const result = await customLoader({ multiple, current: items });
41637
+ if (!result) return;
41638
+ const normalized = toArray(result).map(normaliseFileLike);
41639
+ if (mergeMode === "replace" || !multiple) {
41640
+ emitChange(normalized, {
41641
+ action: "set",
41642
+ from: "custom-loader"
41643
+ });
41644
+ } else {
41645
+ handleAddItems(normalized, "custom-loader");
41646
+ }
41647
+ } catch (err) {
41648
+ console.error("Custom loader failed", err);
41608
41649
  }
41609
- };
41610
- const handleBulkRemove = () => {
41611
- const next = items.filter((i) => !selectedIds.has(i.id));
41612
- emitChange(next, { action: "bulk-remove", ids: Array.from(selectedIds) });
41613
- setSelectedIds(/* @__PURE__ */ new Set());
41614
- };
41615
- const openPicker = async () => {
41650
+ return;
41651
+ }
41652
+ (_a = fileInputRef.current) == null ? void 0 : _a.click();
41653
+ };
41654
+ const onDragOver = (e) => {
41655
+ e.preventDefault();
41656
+ if (!isDisabled) setDragOver(true);
41657
+ };
41658
+ const onDrop = (e) => {
41659
+ var _a;
41660
+ e.preventDefault();
41661
+ setDragOver(false);
41662
+ if (isDisabled || !((_a = e.dataTransfer.files) == null ? void 0 : _a.length)) return;
41663
+ const files = normaliseFromFiles(e.dataTransfer.files);
41664
+ handleAddItems(files, "drop");
41665
+ };
41666
+ const onNativeChange = (e) => {
41667
+ var _a;
41668
+ if ((_a = e.target.files) == null ? void 0 : _a.length) {
41669
+ handleAddItems(normaliseFromFiles(e.target.files), "input");
41670
+ }
41671
+ e.target.value = "";
41672
+ };
41673
+ const FileChip = ({
41674
+ item,
41675
+ condensed = false
41676
+ }) => {
41677
+ const name = formatFileName ? formatFileName(item) : item.name;
41678
+ const [preview, setPreview] = React54__namespace.useState(null);
41679
+ const [isOpen, setIsOpen] = React54__namespace.useState(false);
41680
+ React54__namespace.useEffect(() => {
41616
41681
  var _a;
41617
- if (isDisabled) return;
41618
- if (customLoader) {
41619
- try {
41620
- const result = await customLoader({ multiple, current: items });
41621
- if (!result) return;
41622
- const normalized = toArray(result).map(normaliseFileLike);
41623
- if (mergeMode === "replace" || !multiple) {
41624
- emitChange(normalized, { action: "set", from: "custom-loader" });
41625
- } else {
41626
- handleAddItems(normalized, "custom-loader");
41627
- }
41628
- } catch (err) {
41629
- console.error("Custom loader failed", err);
41630
- }
41682
+ const isImage2 = ((_a = item.type) == null ? void 0 : _a.startsWith("image/")) || item.name.match(/\.(jpg|jpeg|png|gif|webp)$/i);
41683
+ if (!isImage2) {
41684
+ setPreview(null);
41631
41685
  return;
41632
41686
  }
41633
- (_a = fileInputRef.current) == null ? void 0 : _a.click();
41634
- };
41635
- const onDragOver = (e) => {
41636
- e.preventDefault();
41637
- if (!isDisabled) setDragOver(true);
41638
- };
41639
- const onDrop = (e) => {
41640
- var _a;
41641
- e.preventDefault();
41642
- setDragOver(false);
41643
- if (isDisabled || !((_a = e.dataTransfer.files) == null ? void 0 : _a.length)) return;
41644
- const files = normaliseFromFiles(e.dataTransfer.files);
41645
- handleAddItems(files, "drop");
41646
- };
41647
- const onNativeChange = (e) => {
41648
- var _a;
41649
- if ((_a = e.target.files) == null ? void 0 : _a.length) {
41650
- handleAddItems(normaliseFromFiles(e.target.files), "input");
41687
+ if (item.file) {
41688
+ const url = URL.createObjectURL(item.file);
41689
+ setPreview(url);
41690
+ return () => URL.revokeObjectURL(url);
41651
41691
  }
41652
- e.target.value = "";
41653
- };
41654
- const FileChip = ({ item, condensed = false }) => {
41655
- const name = formatFileName ? formatFileName(item) : item.name;
41656
- const [preview, setPreview] = React54__namespace.useState(null);
41657
- const [isOpen, setIsOpen] = React54__namespace.useState(false);
41658
- React54__namespace.useEffect(() => {
41659
- var _a;
41660
- const isImage2 = ((_a = item.type) == null ? void 0 : _a.startsWith("image/")) || item.name.match(/\.(jpg|jpeg|png|gif|webp)$/i);
41661
- if (!isImage2) {
41662
- setPreview(null);
41663
- return;
41692
+ if (item.url || item.path) {
41693
+ setPreview(item.url || item.path || null);
41694
+ }
41695
+ }, [item]);
41696
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open: isOpen, onOpenChange: setIsOpen, children: [
41697
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
41698
+ "div",
41699
+ {
41700
+ role: "button",
41701
+ tabIndex: 0,
41702
+ className: cn(
41703
+ "flex items-center gap-1.5 overflow-hidden rounded-sm border bg-muted/60 px-1.5 text-xs transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none cursor-pointer",
41704
+ chipHeightCls,
41705
+ condensed ? "max-w-[120px]" : "max-w-[200px]"
41706
+ ),
41707
+ onPointerDown: (e) => e.stopPropagation(),
41708
+ onClick: (e) => {
41709
+ e.stopPropagation();
41710
+ setIsOpen(true);
41711
+ },
41712
+ onKeyDown: (e) => {
41713
+ if (e.key === "Enter" || e.key === " ") {
41714
+ e.stopPropagation();
41715
+ setIsOpen(true);
41716
+ }
41717
+ },
41718
+ children: [
41719
+ /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-3 w-3 text-muted-foreground shrink-0" }),
41720
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: name }),
41721
+ /* @__PURE__ */ jsxRuntime.jsx(
41722
+ "button",
41723
+ {
41724
+ type: "button",
41725
+ onPointerDown: (e) => e.stopPropagation(),
41726
+ onClick: (e) => {
41727
+ e.stopPropagation();
41728
+ handleRemove(item.id);
41729
+ },
41730
+ className: "ml-auto flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-muted-foreground/70 hover:bg-destructive/20 hover:text-destructive focus:outline-none",
41731
+ "aria-label": "Remove file",
41732
+ children: /* @__PURE__ */ jsxRuntime.jsx(X, { className: "h-3 w-3" })
41733
+ }
41734
+ )
41735
+ ]
41664
41736
  }
41665
- if (item.file) {
41666
- const url = URL.createObjectURL(item.file);
41667
- setPreview(url);
41668
- return () => URL.revokeObjectURL(url);
41737
+ ) }),
41738
+ /* @__PURE__ */ jsxRuntime.jsxs(
41739
+ PopoverContent2,
41740
+ {
41741
+ className: "w-64 p-0",
41742
+ align: "start",
41743
+ side: "bottom",
41744
+ children: [
41745
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative aspect-video w-full flex items-center justify-center bg-muted/30 border-b", children: preview ? /* @__PURE__ */ jsxRuntime.jsx(
41746
+ "img",
41747
+ {
41748
+ src: preview,
41749
+ alt: item.name,
41750
+ className: "h-full w-full object-contain"
41751
+ }
41752
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 text-muted-foreground/50", children: [
41753
+ /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-10 w-10" }),
41754
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase", children: "No Preview" })
41755
+ ] }) }),
41756
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3", children: [
41757
+ /* @__PURE__ */ jsxRuntime.jsx(
41758
+ "div",
41759
+ {
41760
+ className: "font-medium text-sm truncate",
41761
+ title: item.name,
41762
+ children: name
41763
+ }
41764
+ ),
41765
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center justify-between text-xs text-muted-foreground", children: [
41766
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(item.size) }),
41767
+ item.type && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uppercase opacity-70", children: item.type.split("/").pop() })
41768
+ ] })
41769
+ ] })
41770
+ ]
41669
41771
  }
41670
- if (item.url || item.path) {
41671
- setPreview(item.url || item.path || null);
41772
+ )
41773
+ ] });
41774
+ };
41775
+ const TriggerRegion = React54__namespace.useMemo(() => {
41776
+ if (showDropArea) {
41777
+ if (renderDropArea)
41778
+ return renderDropArea({ openPicker, isDragging: dragOver });
41779
+ return /* @__PURE__ */ jsxRuntime.jsxs(
41780
+ "div",
41781
+ {
41782
+ onClick: openPicker,
41783
+ onDragOver,
41784
+ onDragLeave: () => setDragOver(false),
41785
+ onDrop,
41786
+ className: cn(
41787
+ "group relative flex cursor-pointer flex-col items-center justify-center gap-3 rounded-lg border-2 border-dashed px-6 py-8 text-center transition-all duration-200",
41788
+ dragOver ? "border-primary bg-primary/5 ring-4 ring-primary/10" : "border-muted-foreground/25 hover:bg-muted/30 hover:border-muted-foreground/50",
41789
+ isDisabled && "cursor-not-allowed opacity-50",
41790
+ error && "border-destructive/50 bg-destructive/5",
41791
+ dropAreaClassName
41792
+ ),
41793
+ children: [
41794
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-full bg-surfaces-input p-3 shadow-sm", children: dropIcon != null ? dropIcon : /* @__PURE__ */ jsxRuntime.jsx(CloudUpload, { className: "h-5 w-5 text-muted-foreground" }) }),
41795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
41796
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: dropTitle != null ? dropTitle : "Click or drag to select" }),
41797
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: dropDescription != null ? dropDescription : multiple ? "Select files" : "Select a file" })
41798
+ ] })
41799
+ ]
41672
41800
  }
41673
- }, [item]);
41674
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open: isOpen, onOpenChange: setIsOpen, children: [
41675
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
41676
- "div",
41677
- {
41678
- role: "button",
41679
- tabIndex: 0,
41680
- className: cn(
41681
- "flex items-center gap-1.5 overflow-hidden rounded-sm border bg-muted/60 px-1.5 py-0.5 text-xs transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none cursor-pointer",
41682
- condensed ? "max-w-[120px]" : "max-w-[200px]"
41801
+ );
41802
+ }
41803
+ const hasItems = items.length > 0;
41804
+ const visibleItems = items.slice(0, COLLAPSE_LIMIT);
41805
+ const hiddenCount = items.length - COLLAPSE_LIMIT;
41806
+ const isOverflowing = hiddenCount > 0;
41807
+ const anySelected = selectedIds.size > 0 && showCheckboxes && multiple;
41808
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open: popoverOpen, onOpenChange: setPopoverOpen, children: [
41809
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
41810
+ "div",
41811
+ {
41812
+ className: cn(
41813
+ "relative flex w-full cursor-pointer items-center gap-2 px-3 py-0 transition-all",
41814
+ heightCls,
41815
+ (!joinControls || !hasExternalControls) && "rounded-md border border-input bg-surfaces-input ring-offset-background hover:bg-accent/5 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
41816
+ dragOver && (!joinControls || !hasExternalControls) && "border-primary ring-2 ring-primary/20",
41817
+ isDisabled && "cursor-not-allowed opacity-50",
41818
+ error && (!joinControls || !hasExternalControls) && "border-destructive text-destructive",
41819
+ className
41820
+ ),
41821
+ onDragOver,
41822
+ onDragLeave: () => setDragOver(false),
41823
+ onDrop,
41824
+ children: [
41825
+ resolvedLeadingIcons.map((ico, i) => /* @__PURE__ */ jsxRuntime.jsx(
41826
+ "span",
41827
+ {
41828
+ className: "flex shrink-0 items-center justify-center text-muted-foreground",
41829
+ children: ico
41830
+ },
41831
+ i
41832
+ )),
41833
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center gap-2 overflow-hidden", children: hasItems ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
41834
+ visibleItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
41835
+ FileChip,
41836
+ {
41837
+ item,
41838
+ condensed: multiple
41839
+ },
41840
+ item.id
41841
+ )),
41842
+ isOverflowing && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex h-5 items-center justify-center rounded-sm bg-muted px-1.5 text-xs font-medium text-muted-foreground", children: [
41843
+ "+",
41844
+ hiddenCount
41845
+ ] })
41846
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-muted-foreground", children: placeholder }) }),
41847
+ resolvedTrailingIcons.map((ico, i) => /* @__PURE__ */ jsxRuntime.jsx(
41848
+ "span",
41849
+ {
41850
+ className: "flex shrink-0 items-center justify-center text-muted-foreground",
41851
+ children: ico
41852
+ },
41853
+ i
41854
+ )),
41855
+ /* @__PURE__ */ jsxRuntime.jsx(
41856
+ Button2,
41857
+ {
41858
+ type: "button",
41859
+ variant: "ghost",
41860
+ size: "icon",
41861
+ className: cn(
41862
+ "shrink-0 text-muted-foreground hover:text-foreground",
41863
+ pickerBtnCls
41864
+ ),
41865
+ onPointerDown: (e) => e.stopPropagation(),
41866
+ onClick: (e) => {
41867
+ e.stopPropagation();
41868
+ openPicker();
41869
+ },
41870
+ children: /* @__PURE__ */ jsxRuntime.jsx(FolderUp, { className: "h-4 w-4" })
41871
+ }
41683
41872
  ),
41684
- onClick: (e) => {
41685
- e.stopPropagation();
41686
- setIsOpen(true);
41687
- },
41688
- onKeyDown: (e) => {
41689
- if (e.key === "Enter" || e.key === " ") {
41690
- e.stopPropagation();
41691
- setIsOpen(true);
41873
+ /* @__PURE__ */ jsxRuntime.jsx(
41874
+ ChevronDown,
41875
+ {
41876
+ className: cn(
41877
+ "h-4 w-4 shrink-0 text-muted-foreground opacity-50 transition-transform duration-200",
41878
+ popoverOpen && "rotate-180"
41879
+ )
41692
41880
  }
41693
- },
41694
- children: [
41695
- /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-3 w-3 text-muted-foreground shrink-0" }),
41696
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: name }),
41697
- /* @__PURE__ */ jsxRuntime.jsx(
41881
+ )
41882
+ ]
41883
+ }
41884
+ ) }),
41885
+ /* @__PURE__ */ jsxRuntime.jsx(
41886
+ PopoverContent2,
41887
+ {
41888
+ className: "w-(--radix-popover-trigger-width) p-0",
41889
+ align: "start",
41890
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
41891
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b px-3 py-2 text-xs font-medium text-muted-foreground", children: [
41892
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: anySelected ? `${selectedIds.size} selected` : `${items.length} files total` }),
41893
+ anySelected ? /* @__PURE__ */ jsxRuntime.jsx(
41698
41894
  "button",
41699
41895
  {
41700
41896
  type: "button",
41701
- onClick: (e) => {
41702
- e.stopPropagation();
41703
- handleRemove(item.id);
41704
- },
41705
- className: "ml-auto flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-muted-foreground/70 hover:bg-destructive/20 hover:text-destructive focus:outline-none",
41706
- "aria-label": "Remove file",
41707
- children: /* @__PURE__ */ jsxRuntime.jsx(X, { className: "h-3 w-3" })
41897
+ className: "text-destructive hover:underline",
41898
+ onClick: handleBulkRemove,
41899
+ children: "Remove selected"
41708
41900
  }
41709
- )
41710
- ]
41711
- }
41712
- ) }),
41713
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent2, { className: "w-64 p-0", align: "start", side: "bottom", children: [
41714
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative aspect-video w-full flex items-center justify-center bg-muted/30 border-b", children: preview ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: preview, alt: item.name, className: "h-full w-full object-contain" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 text-muted-foreground/50", children: [
41715
- /* @__PURE__ */ jsxRuntime.jsx(File2, { className: "h-10 w-10" }),
41716
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase", children: "No Preview" })
41717
- ] }) }),
41718
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3", children: [
41719
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-sm truncate", title: item.name, children: name }),
41720
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center justify-between text-xs text-muted-foreground", children: [
41721
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(item.size) }),
41722
- item.type && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uppercase opacity-70", children: item.type.split("/").pop() })
41723
- ] })
41901
+ ) : items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
41902
+ "button",
41903
+ {
41904
+ type: "button",
41905
+ className: "text-muted-foreground hover:text-foreground",
41906
+ onClick: () => emitChange([], { action: "clear" }),
41907
+ children: "Clear all"
41908
+ }
41909
+ ) : null
41910
+ ] }),
41911
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea2, { className: "h-auto max-h-[300px] w-full p-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
41912
+ items.map((item) => {
41913
+ var _a;
41914
+ const selected = selectedIds.has(item.id);
41915
+ const toggle = () => {
41916
+ const next = new Set(selectedIds);
41917
+ if (next.has(item.id))
41918
+ next.delete(item.id);
41919
+ else next.add(item.id);
41920
+ setSelectedIds(next);
41921
+ };
41922
+ return /* @__PURE__ */ jsxRuntime.jsxs(
41923
+ "div",
41924
+ {
41925
+ className: "group flex items-center gap-3 rounded-md px-2 py-2 text-sm transition-colors hover:bg-muted/50",
41926
+ children: [
41927
+ showCheckboxes && multiple && /* @__PURE__ */ jsxRuntime.jsx(
41928
+ Checkbox2,
41929
+ {
41930
+ checked: selected,
41931
+ onCheckedChange: toggle,
41932
+ className: "h-4 w-4 shrink-0"
41933
+ }
41934
+ ),
41935
+ /* @__PURE__ */ jsxRuntime.jsx(FileThumbnail, { item }),
41936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
41937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: (_a = formatFileName == null ? void 0 : formatFileName(item)) != null ? _a : item.name }),
41938
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
41939
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(
41940
+ item.size
41941
+ ) }),
41942
+ item.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive", children: "Failed" })
41943
+ ] })
41944
+ ] }),
41945
+ /* @__PURE__ */ jsxRuntime.jsx(
41946
+ Button2,
41947
+ {
41948
+ variant: "ghost",
41949
+ size: "icon",
41950
+ className: "h-7 w-7 opacity-0 group-hover:opacity-100",
41951
+ onClick: (e) => {
41952
+ e.stopPropagation();
41953
+ handleRemove(item.id);
41954
+ },
41955
+ children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "h-3.5 w-3.5 text-muted-foreground" })
41956
+ }
41957
+ )
41958
+ ]
41959
+ },
41960
+ item.id
41961
+ );
41962
+ }),
41963
+ items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-4 text-center text-xs text-muted-foreground", children: "No files selected" })
41964
+ ] }) }),
41965
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t p-1", children: /* @__PURE__ */ jsxRuntime.jsxs(
41966
+ Button2,
41967
+ {
41968
+ variant: "secondary",
41969
+ size: "sm",
41970
+ className: "w-full justify-start text-xs",
41971
+ onClick: () => {
41972
+ setPopoverOpen(false);
41973
+ openPicker();
41974
+ },
41975
+ children: [
41976
+ /* @__PURE__ */ jsxRuntime.jsx(Plus, { className: "mr-2 h-3 w-3" }),
41977
+ multiple ? "Add files..." : items.length ? "Replace file" : "Add file"
41978
+ ]
41979
+ }
41980
+ ) })
41724
41981
  ] })
41725
- ] })
41726
- ] });
41727
- };
41728
- const TriggerRegion = React54__namespace.useMemo(() => {
41729
- if (showDropArea) {
41730
- if (renderDropArea) return renderDropArea({ openPicker, isDragging: dragOver });
41731
- return /* @__PURE__ */ jsxRuntime.jsxs(
41732
- "div",
41982
+ }
41983
+ )
41984
+ ] });
41985
+ }, [
41986
+ showDropArea,
41987
+ items,
41988
+ multiple,
41989
+ dragOver,
41990
+ isDisabled,
41991
+ placeholder,
41992
+ joinControls,
41993
+ hasExternalControls,
41994
+ resolvedLeadingIcons,
41995
+ resolvedTrailingIcons,
41996
+ popoverOpen,
41997
+ COLLAPSE_LIMIT,
41998
+ heightCls,
41999
+ chipHeightCls,
42000
+ pickerBtnCls,
42001
+ openPicker,
42002
+ onDragOver,
42003
+ onDrop,
42004
+ renderDropArea,
42005
+ className,
42006
+ error,
42007
+ dropAreaClassName,
42008
+ dropIcon,
42009
+ dropTitle,
42010
+ dropDescription,
42011
+ selectedIds,
42012
+ showCheckboxes,
42013
+ handleBulkRemove,
42014
+ emitChange,
42015
+ formatFileName,
42016
+ formatFileSize,
42017
+ handleRemove
42018
+ ]);
42019
+ const showExternalList = multiple && showDropArea && items.length > 0;
42020
+ const anySelectedExternal = selectedIds.size > 0 && showCheckboxes && multiple;
42021
+ const ExternalFileList = showExternalList ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
42022
+ (anySelectedExternal || items.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between px-1 text-xs text-muted-foreground", children: [
42023
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
42024
+ items.length,
42025
+ " files"
42026
+ ] }),
42027
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
42028
+ anySelectedExternal && /* @__PURE__ */ jsxRuntime.jsx(
42029
+ "button",
41733
42030
  {
41734
- onClick: openPicker,
41735
- onDragOver,
41736
- onDragLeave: () => setDragOver(false),
41737
- onDrop,
41738
- className: cn(
41739
- "group relative flex cursor-pointer flex-col items-center justify-center gap-3 rounded-lg border-2 border-dashed px-6 py-8 text-center transition-all duration-200",
41740
- dragOver ? "border-primary bg-primary/5 ring-4 ring-primary/10" : "border-muted-foreground/25 hover:bg-muted/30 hover:border-muted-foreground/50",
41741
- isDisabled && "cursor-not-allowed opacity-50",
41742
- error && "border-destructive/50 bg-destructive/5",
41743
- dropAreaClassName
41744
- ),
41745
- children: [
41746
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-full bg-surfaces-input p-3 shadow-sm", children: dropIcon != null ? dropIcon : /* @__PURE__ */ jsxRuntime.jsx(CloudUpload, { className: "h-5 w-5 text-muted-foreground" }) }),
41747
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
41748
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: dropTitle != null ? dropTitle : "Click or drag to select" }),
41749
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: dropDescription != null ? dropDescription : multiple ? "Select files" : "Select a file" })
41750
- ] })
41751
- ]
42031
+ type: "button",
42032
+ onClick: handleBulkRemove,
42033
+ className: "text-destructive hover:underline",
42034
+ children: "Remove selected"
41752
42035
  }
41753
- );
42036
+ ),
42037
+ /* @__PURE__ */ jsxRuntime.jsx(
42038
+ "button",
42039
+ {
42040
+ type: "button",
42041
+ onClick: () => emitChange([], { action: "clear" }),
42042
+ className: "hover:text-foreground",
42043
+ children: "Clear all"
42044
+ }
42045
+ )
42046
+ ] })
42047
+ ] }),
42048
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea2, { className: cn("mt-1 w-full", listClassName), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: items.map((item, index2) => {
42049
+ var _a;
42050
+ const selected = selectedIds.has(item.id);
42051
+ const toggle = () => {
42052
+ const next = new Set(selectedIds);
42053
+ if (next.has(item.id)) next.delete(item.id);
42054
+ else next.add(item.id);
42055
+ setSelectedIds(next);
42056
+ };
42057
+ if (renderFileItem) {
42058
+ return renderFileItem({
42059
+ item,
42060
+ index: index2,
42061
+ selected,
42062
+ toggleSelected: toggle,
42063
+ remove: () => handleRemove(item.id)
42064
+ });
41754
42065
  }
41755
- const hasItems = items.length > 0;
41756
- const visibleItems = items.slice(0, COLLAPSE_LIMIT);
41757
- const hiddenCount = items.length - COLLAPSE_LIMIT;
41758
- const isOverflowing = hiddenCount > 0;
41759
- const anySelected = selectedIds.size > 0 && showCheckboxes && multiple;
41760
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open: popoverOpen, onOpenChange: setPopoverOpen, children: [
41761
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
42066
+ return /* @__PURE__ */ jsxRuntime.jsxs(
42067
+ "div",
42068
+ {
42069
+ className: "group relative flex items-center gap-3 rounded-lg border bg-card p-2 pr-3 transition-all hover:bg-muted/30",
42070
+ children: [
42071
+ showCheckboxes && /* @__PURE__ */ jsxRuntime.jsx(
42072
+ Checkbox2,
42073
+ {
42074
+ checked: selected,
42075
+ onCheckedChange: toggle,
42076
+ className: "ml-1"
42077
+ }
42078
+ ),
42079
+ /* @__PURE__ */ jsxRuntime.jsx(FileThumbnail, { item }),
42080
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
42081
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-foreground", children: (_a = formatFileName == null ? void 0 : formatFileName(item)) != null ? _a : item.name }) }),
42082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
42083
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(item.size) }),
42084
+ item.status === "loading" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-1 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }) }),
42085
+ item.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-1 text-destructive", children: /* @__PURE__ */ jsxRuntime.jsx(CircleAlert, { className: "h-3 w-3" }) }),
42086
+ item.status === "done" && /* @__PURE__ */ jsxRuntime.jsx(CircleCheck, { className: "h-3 w-3 text-emerald-500" })
42087
+ ] })
42088
+ ] }),
42089
+ /* @__PURE__ */ jsxRuntime.jsx(
42090
+ "button",
42091
+ {
42092
+ type: "button",
42093
+ onClick: () => handleRemove(item.id),
42094
+ className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground/70 opacity-0 transition-all hover:bg-destructive/10 hover:text-destructive group-hover:opacity-100",
42095
+ children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "h-4 w-4" })
42096
+ }
42097
+ )
42098
+ ]
42099
+ },
42100
+ item.id
42101
+ );
42102
+ }) }) })
42103
+ ] }) : null;
42104
+ const joinedBox = joinControls && extendBoxToControls && !showDropArea;
42105
+ return /* @__PURE__ */ jsxRuntime.jsxs(
42106
+ "div",
42107
+ {
42108
+ ref,
42109
+ className: cn("w-full", className),
42110
+ "aria-disabled": isDisabled,
42111
+ "aria-invalid": !!error,
42112
+ children: [
42113
+ /* @__PURE__ */ jsxRuntime.jsxs(
41762
42114
  "div",
41763
42115
  {
41764
42116
  className: cn(
41765
- "relative flex w-full cursor-pointer items-center gap-2 px-3 transition-all",
41766
- heightCls,
41767
- (!joinControls || !hasExternalControls) && "rounded-md border border-input bg-surfaces-input ring-offset-background hover:bg-accent/5 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
41768
- dragOver && "border-primary ring-2 ring-primary/20",
41769
- isDisabled && "cursor-not-allowed opacity-50",
41770
- error && "border-destructive text-destructive",
41771
- className
42117
+ "flex w-full",
42118
+ joinedBox ? "items-stretch rounded-md border border-input bg-surfaces-input shadow-xs ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2" : "items-start gap-2",
42119
+ // if the wrapper owns the border, apply border-state feedback here too
42120
+ joinedBox && dragOver && "border-primary ring-2 ring-primary/20",
42121
+ joinedBox && error && "border-destructive"
41772
42122
  ),
41773
- onDragOver,
41774
- onDragLeave: () => setDragOver(false),
41775
- onDrop,
41776
42123
  children: [
41777
- resolvedLeadingIcons.map((ico, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center justify-center text-muted-foreground", children: ico }, i)),
41778
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center gap-2 overflow-hidden", children: hasItems ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
41779
- visibleItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(FileChip, { item, condensed: multiple }, item.id)),
41780
- isOverflowing && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex h-5 items-center justify-center rounded-sm bg-muted px-1.5 text-xs font-medium text-muted-foreground", children: [
41781
- "+",
41782
- hiddenCount
41783
- ] })
41784
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-muted-foreground", children: placeholder }) }),
41785
- resolvedTrailingIcons.map((ico, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center justify-center text-muted-foreground", children: ico }, i)),
41786
- /* @__PURE__ */ jsxRuntime.jsx(
41787
- Button2,
42124
+ leadingControl && /* @__PURE__ */ jsxRuntime.jsx(
42125
+ "div",
41788
42126
  {
41789
- type: "button",
41790
- variant: "ghost",
41791
- size: "icon",
41792
- className: "h-6 w-6 shrink-0 text-muted-foreground hover:text-foreground",
41793
- onClick: (e) => {
41794
- e.stopPropagation();
41795
- openPicker();
41796
- },
41797
- children: /* @__PURE__ */ jsxRuntime.jsx(FolderUp, { className: "h-4 w-4" })
42127
+ className: cn(
42128
+ "flex items-center",
42129
+ joinControls && !showDropArea && "border-r bg-muted/50 px-3",
42130
+ leadingControlClassName
42131
+ ),
42132
+ children: leadingControl
41798
42133
  }
41799
42134
  ),
41800
- /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, { className: cn("h-4 w-4 shrink-0 text-muted-foreground opacity-50 transition-transform duration-200", popoverOpen && "rotate-180") })
42135
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: TriggerRegion }),
42136
+ trailingControl && /* @__PURE__ */ jsxRuntime.jsx(
42137
+ "div",
42138
+ {
42139
+ className: cn(
42140
+ "flex items-center",
42141
+ joinControls && !showDropArea && "border-l bg-muted/50 px-3",
42142
+ trailingControlClassName
42143
+ ),
42144
+ children: trailingControl
42145
+ }
42146
+ )
41801
42147
  ]
41802
42148
  }
41803
- ) }),
42149
+ ),
42150
+ ExternalFileList,
41804
42151
  /* @__PURE__ */ jsxRuntime.jsx(
41805
- PopoverContent2,
42152
+ "input",
41806
42153
  {
41807
- className: "w-(--radix-popover-trigger-width) p-0",
41808
- align: "start",
41809
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
41810
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b px-3 py-2 text-xs font-medium text-muted-foreground", children: [
41811
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: anySelected ? `${selectedIds.size} selected` : `${items.length} files total` }),
41812
- anySelected ? /* @__PURE__ */ jsxRuntime.jsx(
41813
- "button",
41814
- {
41815
- type: "button",
41816
- className: "text-destructive hover:underline",
41817
- onClick: handleBulkRemove,
41818
- children: "Remove selected"
41819
- }
41820
- ) : items.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
41821
- "button",
41822
- {
41823
- type: "button",
41824
- className: "text-muted-foreground hover:text-foreground",
41825
- onClick: () => emitChange([], { action: "clear" }),
41826
- children: "Clear all"
41827
- }
41828
- )
41829
- ] }),
41830
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea2, { className: "h-auto max-h-[300px] w-full p-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
41831
- items.map((item) => {
41832
- var _a;
41833
- const selected = selectedIds.has(item.id);
41834
- const toggle = () => {
41835
- const next = new Set(selectedIds);
41836
- if (next.has(item.id)) next.delete(item.id);
41837
- else next.add(item.id);
41838
- setSelectedIds(next);
41839
- };
41840
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group flex items-center gap-3 rounded-md px-2 py-2 text-sm transition-colors hover:bg-muted/50", children: [
41841
- showCheckboxes && multiple && /* @__PURE__ */ jsxRuntime.jsx(Checkbox2, { checked: selected, onCheckedChange: toggle, className: "h-4 w-4 shrink-0" }),
41842
- /* @__PURE__ */ jsxRuntime.jsx(FileThumbnail, { item }),
41843
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
41844
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: (_a = formatFileName == null ? void 0 : formatFileName(item)) != null ? _a : item.name }),
41845
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
41846
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(item.size) }),
41847
- item.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive", children: "Failed" })
41848
- ] })
41849
- ] }),
41850
- /* @__PURE__ */ jsxRuntime.jsx(
41851
- Button2,
41852
- {
41853
- variant: "ghost",
41854
- size: "icon",
41855
- className: "h-7 w-7 opacity-0 group-hover:opacity-100",
41856
- onClick: (e) => {
41857
- e.stopPropagation();
41858
- handleRemove(item.id);
41859
- },
41860
- children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "h-3.5 w-3.5 text-muted-foreground" })
41861
- }
41862
- )
41863
- ] }, item.id);
41864
- }),
41865
- items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-4 text-center text-xs text-muted-foreground", children: "No files selected" })
41866
- ] }) }),
41867
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t p-1", children: /* @__PURE__ */ jsxRuntime.jsxs(
41868
- Button2,
41869
- {
41870
- variant: "secondary",
41871
- size: "sm",
41872
- className: "w-full justify-start text-xs",
41873
- onClick: () => {
41874
- setPopoverOpen(false);
41875
- openPicker();
41876
- },
41877
- children: [
41878
- /* @__PURE__ */ jsxRuntime.jsx(Plus, { className: "mr-2 h-3 w-3" }),
41879
- multiple ? "Add files..." : items.length ? "Replace file" : "Add file"
41880
- ]
41881
- }
41882
- ) })
41883
- ] })
42154
+ ref: fileInputRef,
42155
+ type: "file",
42156
+ className: "hidden",
42157
+ multiple,
42158
+ accept: Array.isArray(accept) ? accept.join(",") : accept,
42159
+ onChange: onNativeChange
41884
42160
  }
41885
42161
  )
41886
- ] });
41887
- }, [
41888
- showDropArea,
41889
- items,
41890
- multiple,
41891
- dragOver,
41892
- isDisabled,
41893
- placeholder,
41894
- joinControls,
41895
- hasExternalControls,
41896
- resolvedLeadingIcons,
41897
- resolvedTrailingIcons,
41898
- popoverOpen,
41899
- COLLAPSE_LIMIT,
41900
- heightCls,
41901
- openPicker,
41902
- onDragOver,
41903
- onDrop,
41904
- renderDropArea,
41905
- className,
41906
- error,
41907
- dropAreaClassName,
41908
- dropIcon,
41909
- dropTitle,
41910
- dropDescription,
41911
- selectedIds,
41912
- showCheckboxes,
41913
- handleBulkRemove,
41914
- emitChange,
41915
- formatFileName,
41916
- formatFileSize,
41917
- handleRemove
41918
- ]);
41919
- const showExternalList = multiple && showDropArea && items.length > 0;
41920
- const anySelectedExternal = selectedIds.size > 0 && showCheckboxes && multiple;
41921
- const ExternalFileList = showExternalList ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
41922
- (anySelectedExternal || items.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between px-1 text-xs text-muted-foreground", children: [
41923
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
41924
- items.length,
41925
- " files"
41926
- ] }),
41927
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
41928
- anySelectedExternal && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: handleBulkRemove, className: "text-destructive hover:underline", children: "Remove selected" }),
41929
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => emitChange([], { action: "clear" }), className: "hover:text-foreground", children: "Clear all" })
41930
- ] })
41931
- ] }),
41932
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea2, { className: cn("mt-1 w-full", listClassName), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: items.map((item, index2) => {
41933
- var _a;
41934
- const selected = selectedIds.has(item.id);
41935
- const toggle = () => {
41936
- const next = new Set(selectedIds);
41937
- if (next.has(item.id)) next.delete(item.id);
41938
- else next.add(item.id);
41939
- setSelectedIds(next);
41940
- };
41941
- if (renderFileItem) {
41942
- return renderFileItem({ item, index: index2, selected, toggleSelected: toggle, remove: () => handleRemove(item.id) });
41943
- }
41944
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative flex items-center gap-3 rounded-lg border bg-card p-2 pr-3 transition-all hover:bg-muted/30", children: [
41945
- showCheckboxes && /* @__PURE__ */ jsxRuntime.jsx(Checkbox2, { checked: selected, onCheckedChange: toggle, className: "ml-1" }),
41946
- /* @__PURE__ */ jsxRuntime.jsx(FileThumbnail, { item }),
41947
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
41948
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-foreground", children: (_a = formatFileName == null ? void 0 : formatFileName(item)) != null ? _a : item.name }) }),
41949
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
41950
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFileSize(item.size) }),
41951
- item.status === "loading" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-1 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }) }),
41952
- item.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-1 text-destructive", children: /* @__PURE__ */ jsxRuntime.jsx(CircleAlert, { className: "h-3 w-3" }) }),
41953
- item.status === "done" && /* @__PURE__ */ jsxRuntime.jsx(CircleCheck, { className: "h-3 w-3 text-emerald-500" })
41954
- ] })
41955
- ] }),
41956
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => handleRemove(item.id), className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground/70 opacity-0 transition-all hover:bg-destructive/10 hover:text-destructive group-hover:opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) })
41957
- ] }, item.id);
41958
- }) }) })
41959
- ] }) : null;
41960
- return /* @__PURE__ */ jsxRuntime.jsxs(
41961
- "div",
41962
- {
41963
- ref,
41964
- className: cn("w-full", className),
41965
- "aria-disabled": isDisabled,
41966
- "aria-invalid": !!error,
41967
- children: [
41968
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
41969
- "flex w-full",
41970
- joinControls && extendBoxToControls && !showDropArea ? "items-stretch rounded-md border border-input bg-surfaces-input shadow-xs ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2" : "items-start gap-2"
41971
- ), children: [
41972
- leadingControl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
41973
- "flex items-center",
41974
- joinControls && !showDropArea && "border-r bg-muted/50 px-3",
41975
- leadingControlClassName
41976
- ), children: leadingControl }),
41977
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: TriggerRegion }),
41978
- trailingControl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
41979
- "flex items-center",
41980
- joinControls && !showDropArea && "border-l bg-muted/50 px-3",
41981
- trailingControlClassName
41982
- ), children: trailingControl })
41983
- ] }),
41984
- ExternalFileList,
41985
- /* @__PURE__ */ jsxRuntime.jsx(
41986
- "input",
41987
- {
41988
- ref: fileInputRef,
41989
- type: "file",
41990
- className: "hidden",
41991
- multiple,
41992
- accept: Array.isArray(accept) ? accept.join(",") : accept,
41993
- onChange: onNativeChange
41994
- }
41995
- )
41996
- ]
41997
- }
41998
- );
41999
- }
42000
- );
42162
+ ]
42163
+ }
42164
+ );
42165
+ });
42001
42166
  ShadcnFileVariant.displayName = "ShadcnFileVariant";
42002
42167
  var file_default = ShadcnFileVariant;
42003
42168
 
@@ -43163,7 +43328,7 @@ function normalizeValue(val, multiple) {
43163
43328
  if (Array.isArray(val)) return val[0] || "";
43164
43329
  return val || "";
43165
43330
  }
43166
- function capitalizeFirst6(label) {
43331
+ function capitalizeFirst5(label) {
43167
43332
  if (!label) return label;
43168
43333
  return label.charAt(0).toUpperCase() + label.slice(1);
43169
43334
  }
@@ -43189,7 +43354,7 @@ function normalizeOption(input, {
43189
43354
  label2 = String(rawValue != null ? rawValue : value2);
43190
43355
  }
43191
43356
  if (autoCap && typeof label2 === "string") {
43192
- label2 = capitalizeFirst6(label2);
43357
+ label2 = capitalizeFirst5(label2);
43193
43358
  }
43194
43359
  const icon = optionIcon != null ? anyInput[optionIcon] : (_b = anyInput.icon) != null ? _b : void 0;
43195
43360
  const disabled = optionDisabled != null ? !!anyInput[optionDisabled] : !!anyInput.disabled;
@@ -43211,7 +43376,7 @@ function normalizeOption(input, {
43211
43376
  const value2 = String(input);
43212
43377
  let label2 = value2;
43213
43378
  if (autoCap && typeof label2 === "string") {
43214
- label2 = capitalizeFirst6(label2);
43379
+ label2 = capitalizeFirst5(label2);
43215
43380
  }
43216
43381
  return {
43217
43382
  ui: {
@@ -43225,7 +43390,7 @@ function normalizeOption(input, {
43225
43390
  const value = String(baseValue);
43226
43391
  let label = anyInput.label != null ? anyInput.label : String(value);
43227
43392
  if (autoCap && typeof label === "string") {
43228
- label = capitalizeFirst6(label);
43393
+ label = capitalizeFirst5(label);
43229
43394
  }
43230
43395
  return {
43231
43396
  ui: {