@lodashventure/medusa-media-manager 0.2.5 → 0.2.8

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, Textarea, Container, Heading, Alert } from "@medusajs/ui";
5
+ import { Input, Select, TooltipProvider, Tooltip, IconButton, clx, Button, Badge, Skeleton, Table, StatusBadge, toast, Drawer, FocusModal, Textarea, Container, Heading, Alert } from "@medusajs/ui";
6
6
  import "@medusajs/admin-shared";
7
7
  const ALL_OPTION_VALUE = "all";
8
8
  const normalizeSelectValue = (value) => {
@@ -680,7 +680,7 @@ const STATUS_COLORS = {
680
680
  archived: "warning"
681
681
  };
682
682
  const DEFAULT_LOCALE = "default";
683
- const MediaAssetDrawer = ({
683
+ const MediaAssetDialog = ({
684
684
  assetId,
685
685
  onClose,
686
686
  onUpdated,
@@ -688,6 +688,7 @@ const MediaAssetDrawer = ({
688
688
  }) => {
689
689
  var _a;
690
690
  const fileInputRef = useRef(null);
691
+ const modalContentRef = useRef(null);
691
692
  const [asset, setAsset] = useState(null);
692
693
  const [isLoading, setIsLoading] = useState(false);
693
694
  const [isSaving, setIsSaving] = useState(false);
@@ -764,6 +765,11 @@ const MediaAssetDrawer = ({
764
765
  isMounted = false;
765
766
  };
766
767
  }, [assetId]);
768
+ useEffect(() => {
769
+ if (modalContentRef.current) {
770
+ modalContentRef.current.scrollTop = 0;
771
+ }
772
+ }, [assetId]);
767
773
  const tags = useMemo(() => parseTags(tagsInput), [tagsInput]);
768
774
  const handleSave = async () => {
769
775
  if (!asset || !assetId) {
@@ -852,290 +858,298 @@ const MediaAssetDrawer = ({
852
858
  }
853
859
  };
854
860
  const assetRelations = (asset == null ? void 0 : asset.relations) ?? [];
855
- return /* @__PURE__ */ jsx(Drawer, { open: Boolean(assetId), onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(Drawer.Content, { className: "flex h-full w-full max-w-3xl flex-col overflow-y-auto p-6", children: [
856
- /* @__PURE__ */ jsxs(Drawer.Header, { children: [
857
- /* @__PURE__ */ jsx(Drawer.Title, { className: "text-lg font-semibold", children: "Asset details" }),
858
- /* @__PURE__ */ jsx(Drawer.Description, { children: "Review and update metadata, copy delivery URLs, or replace the original file." })
859
- ] }),
860
- 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: [
861
- /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-y-4", children: [
862
- /* @__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(
863
- "img",
864
- {
865
- src: previewUrl,
866
- alt: asset.original_filename,
867
- className: "h-full w-full object-contain"
868
- }
869
- ) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center text-ui-fg-muted", children: /* @__PURE__ */ jsx(Photo, { className: "size-8" }) }) }),
870
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-ui-fg-subtle", children: [
871
- /* @__PURE__ */ jsx("span", { children: asset.mime }),
872
- /* @__PURE__ */ jsx("span", { children: "·" }),
873
- /* @__PURE__ */ jsx("span", { children: formatFileSize(asset.size_bytes) }),
874
- /* @__PURE__ */ jsx("span", { children: "·" }),
875
- /* @__PURE__ */ jsxs("span", { children: [
876
- "Updated ",
877
- formatDateTime(asset.updated_at)
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)
889
+ ] }),
890
+ /* @__PURE__ */ jsx(
891
+ StatusBadge,
892
+ {
893
+ size: "small",
894
+ color: STATUS_COLORS[asset.status] ?? "default",
895
+ children: asset.status
896
+ }
897
+ ),
898
+ /* @__PURE__ */ jsx(
899
+ Badge,
900
+ {
901
+ size: "small",
902
+ variant: asset.visibility === "public" ? "neutral" : "warning",
903
+ className: "capitalize",
904
+ children: asset.visibility
905
+ }
906
+ )
907
+ ] }),
908
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
909
+ /* @__PURE__ */ jsxs(
910
+ Button,
911
+ {
912
+ type: "button",
913
+ variant: "secondary",
914
+ onClick: () => {
915
+ var _a2;
916
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
917
+ },
918
+ isLoading: isReplacing,
919
+ children: [
920
+ /* @__PURE__ */ jsx(CircleArrowUp, { className: "mr-1 size-4" }),
921
+ "Replace file"
922
+ ]
923
+ }
924
+ ),
925
+ /* @__PURE__ */ jsxs(
926
+ Button,
927
+ {
928
+ type: "button",
929
+ variant: "secondary",
930
+ onClick: () => handleVariantCopy("medium"),
931
+ children: [
932
+ /* @__PURE__ */ jsx(ArrowDownTray, { className: "mr-1 size-4" }),
933
+ "Get URL"
934
+ ]
935
+ }
936
+ )
937
+ ] }),
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
+ )
878
950
  ] }),
879
- /* @__PURE__ */ jsx(
880
- StatusBadge,
881
- {
882
- size: "small",
883
- color: STATUS_COLORS[asset.status] ?? "default",
884
- children: asset.status
885
- }
886
- ),
887
- /* @__PURE__ */ jsx(
888
- Badge,
889
- {
890
- size: "small",
891
- variant: asset.visibility === "public" ? "neutral" : "warning",
892
- className: "capitalize",
893
- children: asset.visibility
894
- }
895
- )
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
+ ),
962
+ /* @__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,
994
+ {
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
+ ]
1019
+ }
1020
+ )
1021
+ ] })
1022
+ ] }),
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(
1078
+ Button,
1079
+ {
1080
+ type: "button",
1081
+ variant: "danger",
1082
+ onClick: () => {
1083
+ if (!asset) {
1084
+ return;
1085
+ }
1086
+ const confirmDelete = window.confirm(
1087
+ "Delete this asset and all generated variants?"
1088
+ );
1089
+ if (confirmDelete) {
1090
+ handleDelete(false);
1091
+ }
1092
+ },
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
+ ]
1111
+ }
1112
+ )
1113
+ ] }),
1114
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1115
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
1116
+ /* @__PURE__ */ jsx(
1117
+ Button,
1118
+ {
1119
+ onClick: handleSave,
1120
+ disabled: !asset || isSaving,
1121
+ isLoading: isSaving,
1122
+ children: "Save changes"
1123
+ }
1124
+ )
1125
+ ] })
896
1126
  ] }),
897
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
898
- /* @__PURE__ */ jsxs(
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(
899
1131
  Button,
900
1132
  {
901
- type: "button",
902
- variant: "secondary",
1133
+ className: "mt-3",
1134
+ variant: "danger",
1135
+ size: "small",
903
1136
  onClick: () => {
904
- var _a2;
905
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
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
+ }
906
1143
  },
907
- isLoading: isReplacing,
908
- children: [
909
- /* @__PURE__ */ jsx(CircleArrowUp, { className: "mr-1 size-4" }),
910
- "Replace file"
911
- ]
912
- }
913
- ),
914
- /* @__PURE__ */ jsxs(
915
- Button,
916
- {
917
- type: "button",
918
- variant: "secondary",
919
- onClick: () => handleVariantCopy("medium"),
920
- children: [
921
- /* @__PURE__ */ jsx(ArrowDownTray, { className: "mr-1 size-4" }),
922
- "Get URL"
923
- ]
924
- }
925
- )
926
- ] }),
927
- /* @__PURE__ */ jsx(
928
- "input",
929
- {
930
- type: "file",
931
- ref: fileInputRef,
932
- className: "hidden",
933
- onChange: (event) => {
934
- var _a2;
935
- return handleReplace(((_a2 = event.target.files) == null ? void 0 : _a2[0]) ?? null);
936
- }
937
- }
938
- )
939
- ] }),
940
- /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
941
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
942
- /* @__PURE__ */ jsx(
943
- Input,
944
- {
945
- label: "Title",
946
- placeholder: "Hero banner",
947
- value: title,
948
- onChange: (event) => setTitle(event.target.value)
949
- }
950
- ),
951
- /* @__PURE__ */ jsx(
952
- Input,
953
- {
954
- label: "Alt text",
955
- placeholder: "Describe the media for accessibility",
956
- value: altText,
957
- onChange: (event) => setAltText(event.target.value)
958
- }
959
- )
960
- ] }),
961
- /* @__PURE__ */ jsx(
962
- Textarea,
963
- {
964
- label: "Caption",
965
- placeholder: "Optional caption or notes",
966
- value: caption,
967
- onChange: (event) => setCaption(event.target.value)
968
- }
969
- ),
970
- /* @__PURE__ */ jsx(
971
- Input,
972
- {
973
- label: "Tags",
974
- placeholder: "summer, lookbook, hero",
975
- value: tagsInput,
976
- onChange: (event) => setTagsInput(event.target.value),
977
- helperText: "Separate tags with commas"
978
- }
979
- ),
980
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
981
- /* @__PURE__ */ jsxs(
982
- Select,
983
- {
984
- value: status,
985
- onValueChange: (value) => setStatus(value),
986
- children: [
987
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Status" }) }),
988
- /* @__PURE__ */ jsxs(Select.Content, { children: [
989
- /* @__PURE__ */ jsx(Select.Item, { value: "draft", children: "Draft" }),
990
- /* @__PURE__ */ jsx(Select.Item, { value: "published", children: "Published" }),
991
- /* @__PURE__ */ jsx(Select.Item, { value: "archived", children: "Archived" })
992
- ] })
993
- ]
994
- }
995
- ),
996
- /* @__PURE__ */ jsxs(
997
- Select,
998
- {
999
- value: visibility,
1000
- onValueChange: (value) => setVisibility(value),
1001
- children: [
1002
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Visibility" }) }),
1003
- /* @__PURE__ */ jsxs(Select.Content, { children: [
1004
- /* @__PURE__ */ jsx(Select.Item, { value: "public", children: "Public" }),
1005
- /* @__PURE__ */ jsx(Select.Item, { value: "private", children: "Private" })
1006
- ] })
1007
- ]
1144
+ children: "Force delete"
1008
1145
  }
1009
1146
  )
1010
1147
  ] })
1011
- ] }),
1012
- ((_a = asset.variants) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1013
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Variants" }),
1014
- /* @__PURE__ */ jsxs(Table, { children: [
1015
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1016
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Name" }),
1017
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Format" }),
1018
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Dimensions" }),
1019
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Size" }),
1020
- /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "Actions" })
1021
- ] }) }),
1022
- /* @__PURE__ */ jsx(Table.Body, { children: asset.variants.map((variant) => /* @__PURE__ */ jsxs(
1023
- Table.Row,
1024
- {
1025
- children: [
1026
- /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: variant.preset }),
1027
- /* @__PURE__ */ jsx(Table.Cell, { children: variant.format }),
1028
- /* @__PURE__ */ jsx(Table.Cell, { children: variant.width && variant.height ? `${variant.width}×${variant.height}` : "-" }),
1029
- /* @__PURE__ */ jsx(Table.Cell, { children: formatFileSize(variant.size_bytes) }),
1030
- /* @__PURE__ */ jsx(Table.Cell, { className: "flex justify-end gap-2", children: /* @__PURE__ */ jsxs(
1031
- Button,
1032
- {
1033
- size: "small",
1034
- variant: "secondary",
1035
- onClick: () => handleVariantCopy(variant.preset),
1036
- children: [
1037
- /* @__PURE__ */ jsx(SquareTwoStack, { className: "mr-1 size-4" }),
1038
- " Copy URL"
1039
- ]
1040
- }
1041
- ) })
1042
- ]
1043
- },
1044
- variant.id ?? `${variant.preset}-${variant.format}`
1045
- )) })
1046
- ] })
1047
- ] }) : null,
1048
- /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
1049
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Usage" }),
1050
- assetRelations.length ? /* @__PURE__ */ jsxs(Table, { children: [
1051
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1052
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Entity" }),
1053
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Reference" }),
1054
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Role" })
1055
- ] }) }),
1056
- /* @__PURE__ */ jsx(Table.Body, { children: assetRelations.map((relation) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1057
- /* @__PURE__ */ jsx(Table.Cell, { className: "capitalize", children: relation.entity_type }),
1058
- /* @__PURE__ */ jsx(Table.Cell, { className: "font-mono text-xs", children: relation.entity_id }),
1059
- /* @__PURE__ */ jsx(Table.Cell, { children: relation.relation_role })
1060
- ] }, relation.id)) })
1061
- ] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-ui-fg-subtle", children: "This asset is not linked to any entities." })
1062
- ] })
1063
- ] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-sm text-ui-fg-subtle", children: "Select an asset to view details." }),
1064
- /* @__PURE__ */ jsxs(Drawer.Footer, { className: "mt-6 flex flex-wrap items-center justify-between gap-3", children: [
1065
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1066
- /* @__PURE__ */ jsxs(
1067
- Button,
1068
- {
1069
- type: "button",
1070
- variant: "danger",
1071
- onClick: () => {
1072
- if (!asset) {
1073
- return;
1074
- }
1075
- const confirmDelete = window.confirm(
1076
- "Delete this asset and all generated variants?"
1077
- );
1078
- if (confirmDelete) {
1079
- handleDelete(false);
1080
- }
1081
- },
1082
- disabled: !asset,
1083
- children: [
1084
- /* @__PURE__ */ jsx(Trash, { className: "mr-1 size-4" }),
1085
- " Delete"
1086
- ]
1087
- }
1088
- ),
1089
- /* @__PURE__ */ jsxs(
1090
- Button,
1091
- {
1092
- type: "button",
1093
- variant: "secondary",
1094
- onClick: () => asset && handleVariantCopy("medium"),
1095
- disabled: !asset,
1096
- children: [
1097
- /* @__PURE__ */ jsx(ArrowPath, { className: "mr-1 size-4" }),
1098
- " Copy URL"
1099
- ]
1100
- }
1101
- )
1102
- ] }),
1103
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1104
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
1105
- /* @__PURE__ */ jsx(
1106
- Button,
1107
- {
1108
- onClick: handleSave,
1109
- disabled: !asset || isSaving,
1110
- isLoading: isSaving,
1111
- children: "Save changes"
1112
- }
1113
- )
1114
- ] })
1115
- ] }),
1116
- 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: [
1117
- /* @__PURE__ */ jsx("p", { className: "font-medium text-ui-fg-base", children: "Having trouble deleting?" }),
1118
- /* @__PURE__ */ jsx("p", { className: "mt-1", children: "If the asset is still referenced, remove those relations first or attempt a force delete." }),
1119
- /* @__PURE__ */ jsx(
1120
- Button,
1121
- {
1122
- className: "mt-3",
1123
- variant: "danger",
1124
- size: "small",
1125
- onClick: () => {
1126
- const confirmForce = window.confirm(
1127
- "Force delete will remove the asset even if it is still referenced. Continue?"
1128
- );
1129
- if (confirmForce) {
1130
- handleDelete(true);
1131
- }
1132
- },
1133
- children: "Force delete"
1134
- }
1135
- )
1136
- ] })
1137
- ] }) });
1148
+ ]
1149
+ }
1150
+ ) });
1138
1151
  };
1152
+ const MediaAssetDrawer = MediaAssetDialog;
1139
1153
  const PAGE_SIZE = 24;
1140
1154
  const MediaLibraryPage = () => {
1141
1155
  const [search, setSearch] = useState("");