@lodashventure/medusa-media-manager 0.2.10 → 0.2.12

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.
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useState, useMemo, useCallback, useRef, useEffect } from "react";
3
3
  import { defineRouteConfig } from "@medusajs/admin-sdk";
4
4
  import { SquaresPlus, ListBullet, ArrowPath, CloudArrowUp, Photo, ShieldCheck, DocumentText, PlaySolid, X, CircleArrowUp, ArrowDownTray, SquareTwoStack, Trash } from "@medusajs/icons";
5
- import { Input, Select, TooltipProvider, Tooltip, IconButton, clx, Button, Badge, Skeleton, Table, StatusBadge, toast, Drawer, FocusModal, Textarea, Container, Heading, Alert } from "@medusajs/ui";
5
+ import { Input, Select, TooltipProvider, Tooltip, IconButton, clx, Button, Badge, Skeleton, Table, StatusBadge, toast, Drawer, FocusModal, Textarea, Prompt, Container, Heading, Alert } from "@medusajs/ui";
6
6
  import "@medusajs/admin-shared";
7
7
  const ALL_OPTION_VALUE = "all";
8
8
  const normalizeSelectValue = (value) => {
@@ -703,11 +703,13 @@ const MediaAssetDialog = ({
703
703
  const [visibility, setVisibility] = useState("public");
704
704
  const [deletePromptOpen, setDeletePromptOpen] = useState(false);
705
705
  const [deleteAttempted, setDeleteAttempted] = useState(false);
706
+ const [isDeleting, setIsDeleting] = useState(false);
706
707
  useEffect(() => {
707
708
  if (!assetId) {
708
709
  setAsset(null);
709
710
  setPreviewUrl(null);
710
711
  setDeleteAttempted(false);
712
+ setDeletePromptOpen(false);
711
713
  return;
712
714
  }
713
715
  let isMounted = true;
@@ -801,6 +803,10 @@ const MediaAssetDialog = ({
801
803
  if (!assetId) {
802
804
  return;
803
805
  }
806
+ if (isDeleting) {
807
+ return;
808
+ }
809
+ setIsDeleting(true);
804
810
  try {
805
811
  await deleteMediaAsset(assetId, force);
806
812
  toast.success("Asset deleted");
@@ -813,6 +819,8 @@ const MediaAssetDialog = ({
813
819
  toast.error("Failed to delete", {
814
820
  description: (err == null ? void 0 : err.message) ?? "Unable to delete asset. If it's in use, try forcing deletion."
815
821
  });
822
+ } finally {
823
+ setIsDeleting(false);
816
824
  }
817
825
  };
818
826
  const handleVariantCopy = async (preset) => {
@@ -858,67 +866,239 @@ const MediaAssetDialog = ({
858
866
  }
859
867
  };
860
868
  const assetRelations = (asset == null ? void 0 : asset.relations) ?? [];
861
- return /* @__PURE__ */ jsx(FocusModal, { open: Boolean(assetId), onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(
862
- FocusModal.Content,
863
- {
864
- ref: modalContentRef,
865
- className: "flex h-full w-full max-w-3xl flex-col overflow-y-auto p-6",
866
- children: [
867
- /* @__PURE__ */ jsxs(FocusModal.Header, { children: [
868
- /* @__PURE__ */ jsx(FocusModal.Title, { className: "text-lg font-semibold", children: "Asset details" }),
869
- /* @__PURE__ */ jsx(FocusModal.Description, { children: "Review and update metadata, copy delivery URLs, or replace the original file." })
870
- ] }),
871
- isLoading ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: "Loading asset..." }) }) : asset ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-y-6", children: [
872
- /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-y-4", children: [
873
- /* @__PURE__ */ jsx("div", { className: "aspect-video w-full overflow-hidden rounded-lg border border-ui-border-base bg-ui-bg-subtle", children: previewUrl ? /* @__PURE__ */ jsx(
874
- "img",
875
- {
876
- src: previewUrl,
877
- alt: asset.original_filename,
878
- className: "h-full w-full object-contain"
879
- }
880
- ) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center text-ui-fg-muted", children: /* @__PURE__ */ jsx(Photo, { className: "size-8" }) }) }),
881
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-ui-fg-subtle", children: [
882
- /* @__PURE__ */ jsx("span", { children: asset.mime }),
883
- /* @__PURE__ */ jsx("span", { children: "·" }),
884
- /* @__PURE__ */ jsx("span", { children: formatFileSize(asset.size_bytes) }),
885
- /* @__PURE__ */ jsx("span", { children: "·" }),
886
- /* @__PURE__ */ jsxs("span", { children: [
887
- "Updated ",
888
- formatDateTime(asset.updated_at)
869
+ return /* @__PURE__ */ jsxs(FocusModal, { open: Boolean(assetId), onOpenChange: (open) => !open && onClose(), children: [
870
+ /* @__PURE__ */ jsxs(
871
+ FocusModal.Content,
872
+ {
873
+ ref: modalContentRef,
874
+ className: "flex h-full w-full max-w-3xl flex-col overflow-y-auto p-6",
875
+ children: [
876
+ /* @__PURE__ */ jsxs(FocusModal.Header, { children: [
877
+ /* @__PURE__ */ jsx(FocusModal.Title, { className: "text-lg font-semibold", children: "Asset details" }),
878
+ /* @__PURE__ */ jsx(FocusModal.Description, { children: "Review and update metadata, copy delivery URLs, or replace the original file." })
879
+ ] }),
880
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-sm text-ui-fg-subtle", children: "Loading asset..." }) }) : asset ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-y-6", children: [
881
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-y-4", children: [
882
+ /* @__PURE__ */ jsx("div", { className: "aspect-video w-full overflow-hidden rounded-lg border border-ui-border-base bg-ui-bg-subtle", children: previewUrl ? /* @__PURE__ */ jsx(
883
+ "img",
884
+ {
885
+ src: previewUrl,
886
+ alt: asset.original_filename,
887
+ className: "h-full w-full object-contain"
888
+ }
889
+ ) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center text-ui-fg-muted", children: /* @__PURE__ */ jsx(Photo, { className: "size-8" }) }) }),
890
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-ui-fg-subtle", children: [
891
+ /* @__PURE__ */ jsx("span", { children: asset.mime }),
892
+ /* @__PURE__ */ jsx("span", { children: "·" }),
893
+ /* @__PURE__ */ jsx("span", { children: formatFileSize(asset.size_bytes) }),
894
+ /* @__PURE__ */ jsx("span", { children: "·" }),
895
+ /* @__PURE__ */ jsxs("span", { children: [
896
+ "Updated ",
897
+ formatDateTime(asset.updated_at)
898
+ ] }),
899
+ /* @__PURE__ */ jsx(
900
+ StatusBadge,
901
+ {
902
+ size: "small",
903
+ color: STATUS_COLORS[asset.status] ?? "default",
904
+ children: asset.status
905
+ }
906
+ ),
907
+ /* @__PURE__ */ jsx(
908
+ Badge,
909
+ {
910
+ size: "small",
911
+ variant: asset.visibility === "public" ? "neutral" : "warning",
912
+ className: "capitalize",
913
+ children: asset.visibility
914
+ }
915
+ )
916
+ ] }),
917
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
918
+ /* @__PURE__ */ jsxs(
919
+ Button,
920
+ {
921
+ type: "button",
922
+ variant: "secondary",
923
+ onClick: () => {
924
+ var _a2;
925
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
926
+ },
927
+ isLoading: isReplacing,
928
+ children: [
929
+ /* @__PURE__ */ jsx(CircleArrowUp, { className: "mr-1 size-4" }),
930
+ "Replace file"
931
+ ]
932
+ }
933
+ ),
934
+ /* @__PURE__ */ jsxs(
935
+ Button,
936
+ {
937
+ type: "button",
938
+ variant: "secondary",
939
+ onClick: () => handleVariantCopy("medium"),
940
+ children: [
941
+ /* @__PURE__ */ jsx(ArrowDownTray, { className: "mr-1 size-4" }),
942
+ "Get URL"
943
+ ]
944
+ }
945
+ )
889
946
  ] }),
890
947
  /* @__PURE__ */ jsx(
891
- StatusBadge,
948
+ "input",
892
949
  {
893
- size: "small",
894
- color: STATUS_COLORS[asset.status] ?? "default",
895
- children: asset.status
950
+ type: "file",
951
+ ref: fileInputRef,
952
+ className: "hidden",
953
+ onChange: (event) => {
954
+ var _a2;
955
+ return handleReplace(((_a2 = event.target.files) == null ? void 0 : _a2[0]) ?? null);
956
+ }
957
+ }
958
+ )
959
+ ] }),
960
+ /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
961
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
962
+ /* @__PURE__ */ jsx(
963
+ Input,
964
+ {
965
+ label: "Title",
966
+ placeholder: "Hero banner",
967
+ value: title,
968
+ onChange: (event) => setTitle(event.target.value)
969
+ }
970
+ ),
971
+ /* @__PURE__ */ jsx(
972
+ Input,
973
+ {
974
+ label: "Alt text",
975
+ placeholder: "Describe the media for accessibility",
976
+ value: altText,
977
+ onChange: (event) => setAltText(event.target.value)
978
+ }
979
+ )
980
+ ] }),
981
+ /* @__PURE__ */ jsx(
982
+ Textarea,
983
+ {
984
+ label: "Caption",
985
+ placeholder: "Optional caption or notes",
986
+ value: caption,
987
+ onChange: (event) => setCaption(event.target.value)
896
988
  }
897
989
  ),
898
990
  /* @__PURE__ */ jsx(
899
- Badge,
991
+ Input,
900
992
  {
901
- size: "small",
902
- variant: asset.visibility === "public" ? "neutral" : "warning",
903
- className: "capitalize",
904
- children: asset.visibility
993
+ label: "Tags",
994
+ placeholder: "summer, lookbook, hero",
995
+ value: tagsInput,
996
+ onChange: (event) => setTagsInput(event.target.value),
997
+ helperText: "Separate tags with commas"
905
998
  }
906
- )
999
+ ),
1000
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1001
+ /* @__PURE__ */ jsxs(
1002
+ Select,
1003
+ {
1004
+ value: status,
1005
+ onValueChange: (value) => setStatus(value),
1006
+ children: [
1007
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Status" }) }),
1008
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
1009
+ /* @__PURE__ */ jsx(Select.Item, { value: "draft", children: "Draft" }),
1010
+ /* @__PURE__ */ jsx(Select.Item, { value: "published", children: "Published" }),
1011
+ /* @__PURE__ */ jsx(Select.Item, { value: "archived", children: "Archived" })
1012
+ ] })
1013
+ ]
1014
+ }
1015
+ ),
1016
+ /* @__PURE__ */ jsxs(
1017
+ Select,
1018
+ {
1019
+ value: visibility,
1020
+ onValueChange: (value) => setVisibility(value),
1021
+ children: [
1022
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Visibility" }) }),
1023
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
1024
+ /* @__PURE__ */ jsx(Select.Item, { value: "public", children: "Public" }),
1025
+ /* @__PURE__ */ jsx(Select.Item, { value: "private", children: "Private" })
1026
+ ] })
1027
+ ]
1028
+ }
1029
+ )
1030
+ ] })
907
1031
  ] }),
908
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
1032
+ ((_a = asset.variants) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1033
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Variants" }),
1034
+ /* @__PURE__ */ jsxs(Table, { children: [
1035
+ /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1036
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Name" }),
1037
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Format" }),
1038
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Dimensions" }),
1039
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Size" }),
1040
+ /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "Actions" })
1041
+ ] }) }),
1042
+ /* @__PURE__ */ jsx(Table.Body, { children: asset.variants.map((variant) => /* @__PURE__ */ jsxs(
1043
+ Table.Row,
1044
+ {
1045
+ children: [
1046
+ /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: variant.preset }),
1047
+ /* @__PURE__ */ jsx(Table.Cell, { children: variant.format }),
1048
+ /* @__PURE__ */ jsx(Table.Cell, { children: variant.width && variant.height ? `${variant.width}×${variant.height}` : "-" }),
1049
+ /* @__PURE__ */ jsx(Table.Cell, { children: formatFileSize(variant.size_bytes) }),
1050
+ /* @__PURE__ */ jsx(Table.Cell, { className: "flex justify-end gap-2", children: /* @__PURE__ */ jsxs(
1051
+ Button,
1052
+ {
1053
+ size: "small",
1054
+ variant: "secondary",
1055
+ onClick: () => handleVariantCopy(variant.preset),
1056
+ children: [
1057
+ /* @__PURE__ */ jsx(SquareTwoStack, { className: "mr-1 size-4" }),
1058
+ " Copy URL"
1059
+ ]
1060
+ }
1061
+ ) })
1062
+ ]
1063
+ },
1064
+ variant.id ?? `${variant.preset}-${variant.format}`
1065
+ )) })
1066
+ ] })
1067
+ ] }) : null,
1068
+ /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1069
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Usage" }),
1070
+ assetRelations.length ? /* @__PURE__ */ jsxs(Table, { children: [
1071
+ /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1072
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Entity" }),
1073
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Reference" }),
1074
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Role" })
1075
+ ] }) }),
1076
+ /* @__PURE__ */ jsx(Table.Body, { children: assetRelations.map((relation) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1077
+ /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: relation.entity_type }),
1078
+ /* @__PURE__ */ jsx(Table.Cell, { className: "font-mono text-xs", children: relation.entity_id }),
1079
+ /* @__PURE__ */ jsx(Table.Cell, { children: relation.relation_role })
1080
+ ] }, relation.id)) })
1081
+ ] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-ui-fg-subtle", children: "This asset is not linked to any entities." })
1082
+ ] })
1083
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-sm text-ui-fg-subtle", children: "Select an asset to view details." }),
1084
+ /* @__PURE__ */ jsxs(FocusModal.Footer, { className: "mt-6 flex flex-wrap items-center justify-between gap-3", children: [
1085
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
909
1086
  /* @__PURE__ */ jsxs(
910
1087
  Button,
911
1088
  {
912
1089
  type: "button",
913
- variant: "secondary",
1090
+ variant: "danger",
914
1091
  onClick: () => {
915
- var _a2;
916
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
1092
+ if (!asset) {
1093
+ return;
1094
+ }
1095
+ setDeletePromptOpen(true);
917
1096
  },
918
- isLoading: isReplacing,
1097
+ disabled: !asset || isDeleting,
1098
+ isLoading: isDeleting,
919
1099
  children: [
920
- /* @__PURE__ */ jsx(CircleArrowUp, { className: "mr-1 size-4" }),
921
- "Replace file"
1100
+ /* @__PURE__ */ jsx(Trash, { className: "mr-1 size-4" }),
1101
+ " Delete"
922
1102
  ]
923
1103
  }
924
1104
  ),
@@ -927,227 +1107,82 @@ const MediaAssetDialog = ({
927
1107
  {
928
1108
  type: "button",
929
1109
  variant: "secondary",
930
- onClick: () => handleVariantCopy("medium"),
1110
+ onClick: () => asset && handleVariantCopy("medium"),
1111
+ disabled: !asset,
931
1112
  children: [
932
- /* @__PURE__ */ jsx(ArrowDownTray, { className: "mr-1 size-4" }),
933
- "Get URL"
1113
+ /* @__PURE__ */ jsx(ArrowPath, { className: "mr-1 size-4" }),
1114
+ " Copy URL"
934
1115
  ]
935
1116
  }
936
1117
  )
937
1118
  ] }),
938
- /* @__PURE__ */ jsx(
939
- "input",
940
- {
941
- type: "file",
942
- ref: fileInputRef,
943
- className: "hidden",
944
- onChange: (event) => {
945
- var _a2;
946
- return handleReplace(((_a2 = event.target.files) == null ? void 0 : _a2[0]) ?? null);
947
- }
948
- }
949
- )
950
- ] }),
951
- /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
952
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
953
- /* @__PURE__ */ jsx(
954
- Input,
955
- {
956
- label: "Title",
957
- placeholder: "Hero banner",
958
- value: title,
959
- onChange: (event) => setTitle(event.target.value)
960
- }
961
- ),
1119
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1120
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
962
1121
  /* @__PURE__ */ jsx(
963
- Input,
964
- {
965
- label: "Alt text",
966
- placeholder: "Describe the media for accessibility",
967
- value: altText,
968
- onChange: (event) => setAltText(event.target.value)
969
- }
970
- )
971
- ] }),
972
- /* @__PURE__ */ jsx(
973
- Textarea,
974
- {
975
- label: "Caption",
976
- placeholder: "Optional caption or notes",
977
- value: caption,
978
- onChange: (event) => setCaption(event.target.value)
979
- }
980
- ),
981
- /* @__PURE__ */ jsx(
982
- Input,
983
- {
984
- label: "Tags",
985
- placeholder: "summer, lookbook, hero",
986
- value: tagsInput,
987
- onChange: (event) => setTagsInput(event.target.value),
988
- helperText: "Separate tags with commas"
989
- }
990
- ),
991
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
992
- /* @__PURE__ */ jsxs(
993
- Select,
1122
+ Button,
994
1123
  {
995
- value: status,
996
- onValueChange: (value) => setStatus(value),
997
- children: [
998
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Status" }) }),
999
- /* @__PURE__ */ jsxs(Select.Content, { children: [
1000
- /* @__PURE__ */ jsx(Select.Item, { value: "draft", children: "Draft" }),
1001
- /* @__PURE__ */ jsx(Select.Item, { value: "published", children: "Published" }),
1002
- /* @__PURE__ */ jsx(Select.Item, { value: "archived", children: "Archived" })
1003
- ] })
1004
- ]
1005
- }
1006
- ),
1007
- /* @__PURE__ */ jsxs(
1008
- Select,
1009
- {
1010
- value: visibility,
1011
- onValueChange: (value) => setVisibility(value),
1012
- children: [
1013
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Visibility" }) }),
1014
- /* @__PURE__ */ jsxs(Select.Content, { children: [
1015
- /* @__PURE__ */ jsx(Select.Item, { value: "public", children: "Public" }),
1016
- /* @__PURE__ */ jsx(Select.Item, { value: "private", children: "Private" })
1017
- ] })
1018
- ]
1124
+ onClick: handleSave,
1125
+ disabled: !asset || isSaving,
1126
+ isLoading: isSaving,
1127
+ children: "Save changes"
1019
1128
  }
1020
1129
  )
1021
1130
  ] })
1022
1131
  ] }),
1023
- ((_a = asset.variants) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1024
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Variants" }),
1025
- /* @__PURE__ */ jsxs(Table, { children: [
1026
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1027
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Name" }),
1028
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Format" }),
1029
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Dimensions" }),
1030
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Size" }),
1031
- /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "Actions" })
1032
- ] }) }),
1033
- /* @__PURE__ */ jsx(Table.Body, { children: asset.variants.map((variant) => /* @__PURE__ */ jsxs(
1034
- Table.Row,
1035
- {
1036
- children: [
1037
- /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: variant.preset }),
1038
- /* @__PURE__ */ jsx(Table.Cell, { children: variant.format }),
1039
- /* @__PURE__ */ jsx(Table.Cell, { children: variant.width && variant.height ? `${variant.width}×${variant.height}` : "-" }),
1040
- /* @__PURE__ */ jsx(Table.Cell, { children: formatFileSize(variant.size_bytes) }),
1041
- /* @__PURE__ */ jsx(Table.Cell, { className: "flex justify-end gap-2", children: /* @__PURE__ */ jsxs(
1042
- Button,
1043
- {
1044
- size: "small",
1045
- variant: "secondary",
1046
- onClick: () => handleVariantCopy(variant.preset),
1047
- children: [
1048
- /* @__PURE__ */ jsx(SquareTwoStack, { className: "mr-1 size-4" }),
1049
- " Copy URL"
1050
- ]
1051
- }
1052
- ) })
1053
- ]
1054
- },
1055
- variant.id ?? `${variant.preset}-${variant.format}`
1056
- )) })
1057
- ] })
1058
- ] }) : null,
1059
- /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1060
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Usage" }),
1061
- assetRelations.length ? /* @__PURE__ */ jsxs(Table, { children: [
1062
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1063
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Entity" }),
1064
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Reference" }),
1065
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Role" })
1066
- ] }) }),
1067
- /* @__PURE__ */ jsx(Table.Body, { children: assetRelations.map((relation) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1068
- /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: relation.entity_type }),
1069
- /* @__PURE__ */ jsx(Table.Cell, { className: "font-mono text-xs", children: relation.entity_id }),
1070
- /* @__PURE__ */ jsx(Table.Cell, { children: relation.relation_role })
1071
- ] }, relation.id)) })
1072
- ] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-ui-fg-subtle", children: "This asset is not linked to any entities." })
1073
- ] })
1074
- ] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-sm text-ui-fg-subtle", children: "Select an asset to view details." }),
1075
- /* @__PURE__ */ jsxs(FocusModal.Footer, { className: "mt-6 flex flex-wrap items-center justify-between gap-3", children: [
1076
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1077
- /* @__PURE__ */ jsxs(
1132
+ deleteAttempted && asset && /* @__PURE__ */ jsxs("div", { className: "mt-4 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4 text-sm text-ui-fg-subtle", children: [
1133
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-ui-fg-base", children: "Having trouble deleting?" }),
1134
+ /* @__PURE__ */ jsx("p", { className: "mt-1", children: "If the asset is still referenced, remove those relations first or attempt a force delete." }),
1135
+ /* @__PURE__ */ jsx(
1078
1136
  Button,
1079
1137
  {
1080
- type: "button",
1138
+ className: "mt-3",
1081
1139
  variant: "danger",
1140
+ size: "small",
1141
+ disabled: isDeleting,
1142
+ isLoading: isDeleting,
1082
1143
  onClick: () => {
1083
- if (!asset) {
1084
- return;
1085
- }
1086
- const confirmDelete = window.confirm(
1087
- "Delete this asset and all generated variants?"
1144
+ const confirmForce = window.confirm(
1145
+ "Force delete will remove the asset even if it is still referenced. Continue?"
1088
1146
  );
1089
- if (confirmDelete) {
1090
- handleDelete(false);
1147
+ if (confirmForce) {
1148
+ handleDelete(true);
1091
1149
  }
1092
1150
  },
1093
- disabled: !asset,
1094
- children: [
1095
- /* @__PURE__ */ jsx(Trash, { className: "mr-1 size-4" }),
1096
- " Delete"
1097
- ]
1098
- }
1099
- ),
1100
- /* @__PURE__ */ jsxs(
1101
- Button,
1102
- {
1103
- type: "button",
1104
- variant: "secondary",
1105
- onClick: () => asset && handleVariantCopy("medium"),
1106
- disabled: !asset,
1107
- children: [
1108
- /* @__PURE__ */ jsx(ArrowPath, { className: "mr-1 size-4" }),
1109
- " Copy URL"
1110
- ]
1151
+ children: "Force delete"
1111
1152
  }
1112
1153
  )
1154
+ ] })
1155
+ ]
1156
+ }
1157
+ ),
1158
+ /* @__PURE__ */ jsx(
1159
+ Prompt,
1160
+ {
1161
+ variant: "confirmation",
1162
+ open: Boolean(asset) && deletePromptOpen,
1163
+ onOpenChange: (open) => setDeletePromptOpen(open),
1164
+ children: /* @__PURE__ */ jsxs(Prompt.Content, { children: [
1165
+ /* @__PURE__ */ jsxs(Prompt.Header, { children: [
1166
+ /* @__PURE__ */ jsx(Prompt.Title, { children: "Delete asset" }),
1167
+ /* @__PURE__ */ jsx(Prompt.Description, { children: asset ? `Delete "${asset.original_filename}" and all generated variants? This cannot be undone.` : "Delete this asset and all generated variants? This cannot be undone." })
1113
1168
  ] }),
1114
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1115
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
1116
- /* @__PURE__ */ jsx(
1169
+ /* @__PURE__ */ jsxs(Prompt.Footer, { children: [
1170
+ /* @__PURE__ */ jsx(Prompt.Cancel, { children: "Cancel" }),
1171
+ /* @__PURE__ */ jsx(Prompt.Action, { asChild: true, children: /* @__PURE__ */ jsx(
1117
1172
  Button,
1118
1173
  {
1119
- onClick: handleSave,
1120
- disabled: !asset || isSaving,
1121
- isLoading: isSaving,
1122
- children: "Save changes"
1174
+ variant: "danger",
1175
+ onClick: () => handleDelete(false),
1176
+ disabled: isDeleting,
1177
+ isLoading: isDeleting,
1178
+ children: "Delete"
1123
1179
  }
1124
- )
1180
+ ) })
1125
1181
  ] })
1126
- ] }),
1127
- deleteAttempted && asset && /* @__PURE__ */ jsxs("div", { className: "mt-4 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4 text-sm text-ui-fg-subtle", children: [
1128
- /* @__PURE__ */ jsx("p", { className: "font-medium text-ui-fg-base", children: "Having trouble deleting?" }),
1129
- /* @__PURE__ */ jsx("p", { className: "mt-1", children: "If the asset is still referenced, remove those relations first or attempt a force delete." }),
1130
- /* @__PURE__ */ jsx(
1131
- Button,
1132
- {
1133
- className: "mt-3",
1134
- variant: "danger",
1135
- size: "small",
1136
- onClick: () => {
1137
- const confirmForce = window.confirm(
1138
- "Force delete will remove the asset even if it is still referenced. Continue?"
1139
- );
1140
- if (confirmForce) {
1141
- handleDelete(true);
1142
- }
1143
- },
1144
- children: "Force delete"
1145
- }
1146
- )
1147
1182
  ] })
1148
- ]
1149
- }
1150
- ) });
1183
+ }
1184
+ )
1185
+ ] });
1151
1186
  };
1152
1187
  const MediaAssetDrawer = MediaAssetDialog;
1153
1188
  const PAGE_SIZE = 24;