@anvilkit/plugin-asset-manager 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +27 -19
  2. package/dist/adapters/data-url.cjs +9 -5
  3. package/dist/adapters/extract-image-dimensions.cjs +12 -8
  4. package/dist/adapters/in-memory.cjs +9 -5
  5. package/dist/adapters/s3-presigned.cjs +9 -5
  6. package/dist/index.cjs +16 -5
  7. package/dist/index.d.cts +11 -3
  8. package/dist/index.d.cts.map +1 -1
  9. package/dist/index.d.ts +11 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -1
  12. package/dist/plugin.cjs +76 -9
  13. package/dist/plugin.d.cts +3 -2
  14. package/dist/plugin.d.cts.map +1 -1
  15. package/dist/plugin.d.ts +3 -2
  16. package/dist/plugin.d.ts.map +1 -1
  17. package/dist/plugin.js +67 -4
  18. package/dist/sources/composite-source.cjs +137 -0
  19. package/dist/sources/composite-source.d.cts +39 -0
  20. package/dist/sources/composite-source.d.cts.map +1 -0
  21. package/dist/sources/composite-source.d.ts +39 -0
  22. package/dist/sources/composite-source.d.ts.map +1 -0
  23. package/dist/sources/composite-source.js +99 -0
  24. package/dist/sources/federated-search.cjs +163 -0
  25. package/dist/sources/federated-search.d.cts +33 -0
  26. package/dist/sources/federated-search.d.cts.map +1 -0
  27. package/dist/sources/federated-search.d.ts +33 -0
  28. package/dist/sources/federated-search.d.ts.map +1 -0
  29. package/dist/sources/federated-search.js +113 -0
  30. package/dist/sources/provider.cjs +18 -0
  31. package/dist/sources/provider.d.cts +51 -0
  32. package/dist/sources/provider.d.cts.map +1 -0
  33. package/dist/sources/provider.d.ts +51 -0
  34. package/dist/sources/provider.d.ts.map +1 -0
  35. package/dist/sources/provider.js +1 -0
  36. package/dist/sources/unsplash/client.cjs +189 -0
  37. package/dist/sources/unsplash/client.d.cts +87 -0
  38. package/dist/sources/unsplash/client.d.cts.map +1 -0
  39. package/dist/sources/unsplash/client.d.ts +87 -0
  40. package/dist/sources/unsplash/client.d.ts.map +1 -0
  41. package/dist/sources/unsplash/client.js +151 -0
  42. package/dist/sources/unsplash/index.cjs +192 -0
  43. package/dist/sources/unsplash/index.d.cts +16 -0
  44. package/dist/sources/unsplash/index.d.cts.map +1 -0
  45. package/dist/sources/unsplash/index.d.ts +16 -0
  46. package/dist/sources/unsplash/index.d.ts.map +1 -0
  47. package/dist/sources/unsplash/index.js +148 -0
  48. package/dist/sources/unsplash/themes.cjs +141 -0
  49. package/dist/sources/unsplash/themes.d.cts +18 -0
  50. package/dist/sources/unsplash/themes.d.cts.map +1 -0
  51. package/dist/sources/unsplash/themes.d.ts +18 -0
  52. package/dist/sources/unsplash/themes.d.ts.map +1 -0
  53. package/dist/sources/unsplash/themes.js +93 -0
  54. package/dist/sources/unsplash/throttle-cache.cjs +86 -0
  55. package/dist/sources/unsplash/throttle-cache.d.cts +25 -0
  56. package/dist/sources/unsplash/throttle-cache.d.cts.map +1 -0
  57. package/dist/sources/unsplash/throttle-cache.d.ts +25 -0
  58. package/dist/sources/unsplash/throttle-cache.d.ts.map +1 -0
  59. package/dist/sources/unsplash/throttle-cache.js +45 -0
  60. package/dist/testing/index.cjs +9 -5
  61. package/dist/types/categories.cjs +18 -0
  62. package/dist/types/categories.d.cts +48 -0
  63. package/dist/types/categories.d.cts.map +1 -0
  64. package/dist/types/categories.d.ts +48 -0
  65. package/dist/types/categories.d.ts.map +1 -0
  66. package/dist/types/categories.js +1 -0
  67. package/dist/types/data-source.cjs +18 -0
  68. package/dist/types/data-source.d.cts +59 -0
  69. package/dist/types/data-source.d.cts.map +1 -0
  70. package/dist/types/data-source.d.ts +59 -0
  71. package/dist/types/data-source.d.ts.map +1 -0
  72. package/dist/types/data-source.js +1 -0
  73. package/dist/types/filter.cjs +18 -0
  74. package/dist/types/filter.d.cts +55 -0
  75. package/dist/types/filter.d.cts.map +1 -0
  76. package/dist/types/filter.d.ts +55 -0
  77. package/dist/types/filter.d.ts.map +1 -0
  78. package/dist/types/filter.js +1 -0
  79. package/dist/types/folders.cjs +42 -0
  80. package/dist/types/folders.d.cts +46 -0
  81. package/dist/types/folders.d.cts.map +1 -0
  82. package/dist/types/folders.d.ts +46 -0
  83. package/dist/types/folders.d.ts.map +1 -0
  84. package/dist/types/folders.js +4 -0
  85. package/dist/types/options.cjs +18 -0
  86. package/dist/types/options.d.cts +68 -0
  87. package/dist/types/options.d.cts.map +1 -0
  88. package/dist/types/options.d.ts +68 -0
  89. package/dist/types/options.d.ts.map +1 -0
  90. package/dist/types/options.js +1 -0
  91. package/dist/types/types.d.cts +15 -27
  92. package/dist/types/types.d.cts.map +1 -1
  93. package/dist/types/types.d.ts +15 -27
  94. package/dist/types/types.d.ts.map +1 -1
  95. package/dist/types/unsplash.cjs +18 -0
  96. package/dist/types/unsplash.d.cts +60 -0
  97. package/dist/types/unsplash.d.cts.map +1 -0
  98. package/dist/types/unsplash.d.ts +60 -0
  99. package/dist/types/unsplash.d.ts.map +1 -0
  100. package/dist/types/unsplash.js +1 -0
  101. package/dist/ui/AssetBrowser.cjs +69 -104
  102. package/dist/ui/AssetBrowser.d.cts +17 -7
  103. package/dist/ui/AssetBrowser.d.cts.map +1 -1
  104. package/dist/ui/AssetBrowser.d.ts +17 -7
  105. package/dist/ui/AssetBrowser.d.ts.map +1 -1
  106. package/dist/ui/AssetBrowser.js +60 -99
  107. package/dist/ui/AssetCommandPalette.cjs +9 -5
  108. package/dist/ui/AssetManagerUI.cjs +17 -7
  109. package/dist/ui/AssetManagerUI.d.cts +19 -3
  110. package/dist/ui/AssetManagerUI.d.cts.map +1 -1
  111. package/dist/ui/AssetManagerUI.d.ts +19 -3
  112. package/dist/ui/AssetManagerUI.d.ts.map +1 -1
  113. package/dist/ui/AssetManagerUI.js +8 -2
  114. package/dist/ui/DeleteAssetDialog.cjs +9 -5
  115. package/dist/ui/DeleteFolderDialog.cjs +78 -0
  116. package/dist/ui/DeleteFolderDialog.d.cts +11 -0
  117. package/dist/ui/DeleteFolderDialog.d.cts.map +1 -0
  118. package/dist/ui/DeleteFolderDialog.d.ts +11 -0
  119. package/dist/ui/DeleteFolderDialog.d.ts.map +1 -0
  120. package/dist/ui/DeleteFolderDialog.js +40 -0
  121. package/dist/ui/EmptyFolderState.cjs +53 -0
  122. package/dist/ui/EmptyFolderState.d.cts +6 -0
  123. package/dist/ui/EmptyFolderState.d.cts.map +1 -0
  124. package/dist/ui/EmptyFolderState.d.ts +6 -0
  125. package/dist/ui/EmptyFolderState.d.ts.map +1 -0
  126. package/dist/ui/EmptyFolderState.js +15 -0
  127. package/dist/ui/FolderBreadcrumb.cjs +73 -0
  128. package/dist/ui/FolderBreadcrumb.d.cts +9 -0
  129. package/dist/ui/FolderBreadcrumb.d.cts.map +1 -0
  130. package/dist/ui/FolderBreadcrumb.d.ts +9 -0
  131. package/dist/ui/FolderBreadcrumb.d.ts.map +1 -0
  132. package/dist/ui/FolderBreadcrumb.js +35 -0
  133. package/dist/ui/FolderNameDialog.cjs +98 -0
  134. package/dist/ui/FolderNameDialog.d.cts +14 -0
  135. package/dist/ui/FolderNameDialog.d.cts.map +1 -0
  136. package/dist/ui/FolderNameDialog.d.ts +14 -0
  137. package/dist/ui/FolderNameDialog.d.ts.map +1 -0
  138. package/dist/ui/FolderNameDialog.js +60 -0
  139. package/dist/ui/FolderTree.cjs +83 -0
  140. package/dist/ui/FolderTree.d.cts +13 -0
  141. package/dist/ui/FolderTree.d.cts.map +1 -0
  142. package/dist/ui/FolderTree.d.ts +13 -0
  143. package/dist/ui/FolderTree.d.ts.map +1 -0
  144. package/dist/ui/FolderTree.js +42 -0
  145. package/dist/ui/MetadataPanel.cjs +16 -9
  146. package/dist/ui/MetadataPanel.d.cts.map +1 -1
  147. package/dist/ui/MetadataPanel.d.ts.map +1 -1
  148. package/dist/ui/MetadataPanel.js +7 -4
  149. package/dist/ui/MoveTargetPicker.cjs +84 -0
  150. package/dist/ui/MoveTargetPicker.d.cts +16 -0
  151. package/dist/ui/MoveTargetPicker.d.cts.map +1 -0
  152. package/dist/ui/MoveTargetPicker.d.ts +16 -0
  153. package/dist/ui/MoveTargetPicker.d.ts.map +1 -0
  154. package/dist/ui/MoveTargetPicker.js +46 -0
  155. package/dist/ui/ReplaceAssetDialog.cjs +9 -5
  156. package/dist/ui/ReplaceAssetDialog.d.cts +2 -1
  157. package/dist/ui/ReplaceAssetDialog.d.cts.map +1 -1
  158. package/dist/ui/ReplaceAssetDialog.d.ts +2 -1
  159. package/dist/ui/ReplaceAssetDialog.d.ts.map +1 -1
  160. package/dist/ui/UnsplashPanel.cjs +134 -0
  161. package/dist/ui/UnsplashPanel.d.cts +28 -0
  162. package/dist/ui/UnsplashPanel.d.cts.map +1 -0
  163. package/dist/ui/UnsplashPanel.d.ts +28 -0
  164. package/dist/ui/UnsplashPanel.d.ts.map +1 -0
  165. package/dist/ui/UnsplashPanel.js +96 -0
  166. package/dist/ui/UploadButton.cjs +10 -10
  167. package/dist/ui/UploadButton.d.cts +9 -2
  168. package/dist/ui/UploadButton.d.cts.map +1 -1
  169. package/dist/ui/UploadButton.d.ts +9 -2
  170. package/dist/ui/UploadButton.d.ts.map +1 -1
  171. package/dist/ui/UploadButton.js +1 -5
  172. package/dist/ui/index.cjs +46 -5
  173. package/dist/ui/index.d.cts +14 -0
  174. package/dist/ui/index.d.cts.map +1 -1
  175. package/dist/ui/index.d.ts +14 -0
  176. package/dist/ui/index.d.ts.map +1 -1
  177. package/dist/ui/index.js +7 -0
  178. package/dist/utils/asset-reference.cjs +12 -8
  179. package/dist/utils/csp.cjs +12 -8
  180. package/dist/utils/data-source.cjs +177 -0
  181. package/dist/utils/data-source.d.cts +63 -0
  182. package/dist/utils/data-source.d.cts.map +1 -0
  183. package/dist/utils/data-source.d.ts +63 -0
  184. package/dist/utils/data-source.d.ts.map +1 -0
  185. package/dist/utils/data-source.js +136 -0
  186. package/dist/utils/errors.cjs +31 -9
  187. package/dist/utils/errors.d.cts +27 -0
  188. package/dist/utils/errors.d.cts.map +1 -1
  189. package/dist/utils/errors.d.ts +27 -0
  190. package/dist/utils/errors.d.ts.map +1 -1
  191. package/dist/utils/errors.js +16 -1
  192. package/dist/utils/folders.cjs +261 -0
  193. package/dist/utils/folders.d.cts +49 -0
  194. package/dist/utils/folders.d.cts.map +1 -0
  195. package/dist/utils/folders.d.ts +49 -0
  196. package/dist/utils/folders.d.ts.map +1 -0
  197. package/dist/utils/folders.js +223 -0
  198. package/dist/utils/header-action.cjs +12 -8
  199. package/dist/utils/infer-kind.cjs +12 -8
  200. package/dist/utils/registry.cjs +36 -17
  201. package/dist/utils/registry.d.cts +21 -1
  202. package/dist/utils/registry.d.cts.map +1 -1
  203. package/dist/utils/registry.d.ts +21 -1
  204. package/dist/utils/registry.d.ts.map +1 -1
  205. package/dist/utils/registry.js +20 -11
  206. package/dist/utils/resolver.cjs +9 -5
  207. package/dist/utils/retry.cjs +13 -9
  208. package/dist/utils/studio-asset-source.cjs +14 -7
  209. package/dist/utils/studio-asset-source.d.cts +6 -1
  210. package/dist/utils/studio-asset-source.d.cts.map +1 -1
  211. package/dist/utils/studio-asset-source.d.ts +6 -1
  212. package/dist/utils/studio-asset-source.d.ts.map +1 -1
  213. package/dist/utils/studio-asset-source.js +1 -1
  214. package/dist/utils/validate-upload-result.cjs +9 -5
  215. package/dist/utils/validate-upload-result.d.cts +2 -1
  216. package/dist/utils/validate-upload-result.d.cts.map +1 -1
  217. package/dist/utils/validate-upload-result.d.ts +2 -1
  218. package/dist/utils/validate-upload-result.d.ts.map +1 -1
  219. package/dist/version.cjs +12 -8
  220. package/dist/version.d.cts +1 -1
  221. package/dist/version.d.ts +1 -1
  222. package/dist/version.js +1 -1
  223. package/meta/config.json +1 -1
  224. package/package.json +19 -9
@@ -1,8 +1,10 @@
1
1
  "use client";
2
+ import { Button } from "@anvilkit/ui/button";
2
3
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@anvilkit/ui/card";
3
4
  import { Input } from "@anvilkit/ui/input";
4
- import { flushSync } from "react-dom";
5
+ import { Windowed } from "@anvilkit/ui/windowed";
5
6
  import { inferAssetKind } from "../utils/infer-kind.js";
7
+ import { ASSET_DRAG_MIME } from "./FolderTree.js";
6
8
  import * as __rspack_external_react from "react";
7
9
  const KIND_FILTERS = [
8
10
  "image",
@@ -15,20 +17,13 @@ const DEFAULT_VIRTUALIZE_THRESHOLD = 50;
15
17
  const DEFAULT_ITEM_HEIGHT = 56;
16
18
  const DEFAULT_MAX_HEIGHT = 400;
17
19
  const DEFAULT_PAGE_SIZE = 100;
18
- const OVERSCAN = 4;
19
- function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEnabled = false, pageSize = DEFAULT_PAGE_SIZE, virtualizeThreshold = DEFAULT_VIRTUALIZE_THRESHOLD, itemHeight = DEFAULT_ITEM_HEIGHT, maxHeight = DEFAULT_MAX_HEIGHT }) {
20
+ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEnabled = false, aboveFilters, draggableRows = false, pageSize = DEFAULT_PAGE_SIZE, virtualizeThreshold = DEFAULT_VIRTUALIZE_THRESHOLD, itemHeight = DEFAULT_ITEM_HEIGHT, maxHeight = DEFAULT_MAX_HEIGHT }) {
20
21
  const [activeIndex, setActiveIndex] = __rspack_external_react.useState(assets.length > 0 ? 0 : -1);
21
- const [scrollTop, setScrollTop] = __rspack_external_react.useState(0);
22
22
  const [query, setQuery] = __rspack_external_react.useState("");
23
23
  const [activeKinds, setActiveKinds] = __rspack_external_react.useState([]);
24
24
  const [pageLimit, setPageLimit] = __rspack_external_react.useState(pageSize);
25
25
  const buttonRefs = __rspack_external_react.useRef([]);
26
- const scrollContainerRef = __rspack_external_react.useRef(null);
27
- const scrollFrameRef = __rspack_external_react.useRef(null);
28
- const pendingScrollTopRef = __rspack_external_react.useRef(0);
29
- __rspack_external_react.useEffect(()=>()=>{
30
- if (null !== scrollFrameRef.current && "function" == typeof cancelAnimationFrame) cancelAnimationFrame(scrollFrameRef.current);
31
- }, []);
26
+ const pendingFocusRef = __rspack_external_react.useRef(null);
32
27
  const searchIndex = __rspack_external_react.useMemo(()=>{
33
28
  if (!searchEnabled) return null;
34
29
  return assets.map((asset)=>({
@@ -68,7 +63,6 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
68
63
  searchEnabled
69
64
  ]);
70
65
  const total = visibleSlice.length;
71
- const isVirtualized = total > virtualizeThreshold;
72
66
  const hasMore = searchEnabled && filteredAssets.length > visibleSlice.length;
73
67
  __rspack_external_react.useEffect(()=>{
74
68
  if (0 === total) return void setActiveIndex(-1);
@@ -76,31 +70,20 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
76
70
  }, [
77
71
  total
78
72
  ]);
73
+ function focusRow(index) {
74
+ const node = buttonRefs.current[index];
75
+ if (node) {
76
+ node.focus();
77
+ return true;
78
+ }
79
+ return false;
80
+ }
79
81
  function moveFocus(nextIndex) {
80
82
  if (0 === total) return;
81
83
  const clampedIndex = Math.max(0, Math.min(nextIndex, total - 1));
82
- if (isVirtualized && scrollContainerRef.current) {
83
- const targetTop = clampedIndex * itemHeight;
84
- const targetBottom = targetTop + itemHeight;
85
- const viewTop = scrollContainerRef.current.scrollTop;
86
- let nextScrollTop = viewTop;
87
- if (targetTop < viewTop) nextScrollTop = targetTop;
88
- else if (targetBottom > viewTop + maxHeight) nextScrollTop = targetBottom - maxHeight;
89
- if (null !== scrollFrameRef.current && "function" == typeof cancelAnimationFrame) {
90
- cancelAnimationFrame(scrollFrameRef.current);
91
- scrollFrameRef.current = null;
92
- }
93
- pendingScrollTopRef.current = nextScrollTop;
94
- flushSync(()=>{
95
- setActiveIndex(clampedIndex);
96
- setScrollTop(nextScrollTop);
97
- });
98
- scrollContainerRef.current.scrollTop = nextScrollTop;
99
- buttonRefs.current[clampedIndex]?.focus();
100
- return;
101
- }
84
+ pendingFocusRef.current = clampedIndex;
102
85
  setActiveIndex(clampedIndex);
103
- buttonRefs.current[clampedIndex]?.focus();
86
+ if (focusRow(clampedIndex)) pendingFocusRef.current = null;
104
87
  }
105
88
  function toggleKind(kind) {
106
89
  setActiveKinds((current)=>current.includes(kind) ? current.filter((entry)=>entry !== kind) : [
@@ -108,17 +91,16 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
108
91
  kind
109
92
  ]);
110
93
  }
111
- const firstVisible = isVirtualized ? Math.max(0, Math.floor(scrollTop / itemHeight) - OVERSCAN) : 0;
112
- const lastVisible = isVirtualized ? Math.min(total - 1, Math.ceil((scrollTop + maxHeight) / itemHeight) + OVERSCAN) : total - 1;
113
- const visibleAssets = 0 === total ? [] : isVirtualized ? visibleSlice.slice(firstVisible, lastVisible + 1) : visibleSlice;
114
- function renderRow(asset, index) {
115
- return /*#__PURE__*/ __rspack_external_react.createElement("li", {
116
- "aria-posinset": index + 1,
117
- "aria-setsize": total,
118
- key: asset.id,
119
- role: "listitem"
120
- }, /*#__PURE__*/ __rspack_external_react.createElement("button", {
94
+ const renderRow = (asset, index)=>/*#__PURE__*/ __rspack_external_react.createElement(__rspack_external_react.Fragment, null, /*#__PURE__*/ __rspack_external_react.createElement("button", {
121
95
  "aria-label": `Insert asset ${asset.id}`,
96
+ draggable: draggableRows,
97
+ "data-asset-draggable": draggableRows ? "" : void 0,
98
+ onDragStart: draggableRows ? (event)=>{
99
+ event.dataTransfer.setData(ASSET_DRAG_MIME, JSON.stringify([
100
+ asset.id
101
+ ]));
102
+ event.dataTransfer.effectAllowed = "move";
103
+ } : void 0,
122
104
  onClick: ()=>{
123
105
  onInsert(asset);
124
106
  },
@@ -153,33 +135,42 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
153
135
  },
154
136
  ref: (node)=>{
155
137
  buttonRefs.current[index] = node;
138
+ if (node && pendingFocusRef.current === index) {
139
+ pendingFocusRef.current = null;
140
+ node.focus();
141
+ }
156
142
  },
157
143
  tabIndex: activeIndex === index ? 0 : -1,
158
144
  type: "button"
159
- }, /*#__PURE__*/ __rspack_external_react.createElement("span", null, asset.id), /*#__PURE__*/ __rspack_external_react.createElement("span", null, asset.meta?.mimeType ?? "unknown type")), void 0 !== onEdit ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
145
+ }, /*#__PURE__*/ __rspack_external_react.createElement("span", null, asset.id), /*#__PURE__*/ __rspack_external_react.createElement("span", null, asset.meta?.mimeType ?? "unknown type")), void 0 !== onEdit ? /*#__PURE__*/ __rspack_external_react.createElement(Button, {
160
146
  "aria-label": `Edit asset ${asset.id}`,
161
147
  "data-asset-action": "edit",
162
148
  onClick: ()=>{
163
149
  onEdit(asset);
164
150
  },
165
- type: "button"
166
- }, "Edit") : null, void 0 !== onReplace ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
151
+ type: "button",
152
+ variant: "ghost",
153
+ size: "sm"
154
+ }, "Edit") : null, void 0 !== onReplace ? /*#__PURE__*/ __rspack_external_react.createElement(Button, {
167
155
  "aria-label": `Replace asset ${asset.id}`,
168
156
  "data-asset-action": "replace",
169
157
  onClick: ()=>{
170
158
  onReplace(asset);
171
159
  },
172
- type: "button"
173
- }, "Replace") : null, void 0 !== onDelete ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
160
+ type: "button",
161
+ variant: "ghost",
162
+ size: "sm"
163
+ }, "Replace") : null, void 0 !== onDelete ? /*#__PURE__*/ __rspack_external_react.createElement(Button, {
174
164
  "aria-label": `Delete asset ${asset.id}`,
175
165
  "data-asset-action": "delete",
176
166
  onClick: ()=>{
177
167
  onDelete(asset);
178
168
  },
179
- type: "button"
169
+ type: "button",
170
+ variant: "ghost",
171
+ size: "sm"
180
172
  }, "Delete") : null);
181
- }
182
- const filterRow = searchEnabled ? /*#__PURE__*/ __rspack_external_react.createElement("div", {
173
+ const searchRow = searchEnabled ? /*#__PURE__*/ __rspack_external_react.createElement("div", {
183
174
  "data-asset-manager-filters": true
184
175
  }, /*#__PURE__*/ __rspack_external_react.createElement(Input, {
185
176
  "aria-label": "Search assets",
@@ -194,7 +185,7 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
194
185
  role: "group"
195
186
  }, KIND_FILTERS.map((kind)=>{
196
187
  const active = activeKinds.includes(kind);
197
- return /*#__PURE__*/ __rspack_external_react.createElement("button", {
188
+ return /*#__PURE__*/ __rspack_external_react.createElement(Button, {
198
189
  "aria-label": `Filter ${kind} assets`,
199
190
  "aria-pressed": active,
200
191
  "data-asset-kind-filter": kind,
@@ -203,9 +194,12 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
203
194
  toggleKind(kind);
204
195
  setPageLimit(pageSize);
205
196
  },
206
- type: "button"
197
+ type: "button",
198
+ variant: active ? "secondary" : "ghost",
199
+ size: "sm"
207
200
  }, kind);
208
201
  }))) : null;
202
+ const filterRow = /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external_react.Fragment, null, aboveFilters, searchRow);
209
203
  if (0 === total) {
210
204
  const emptyLabel = searchEnabled && ("" !== query || activeKinds.length > 0) ? "No assets match the current filters." : "No assets uploaded yet.";
211
205
  return /*#__PURE__*/ __rspack_external_react.createElement(Card, null, /*#__PURE__*/ __rspack_external_react.createElement(CardHeader, null, /*#__PURE__*/ __rspack_external_react.createElement(CardTitle, null, "Asset browser"), /*#__PURE__*/ __rspack_external_react.createElement(CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ __rspack_external_react.createElement(CardContent, null, filterRow, /*#__PURE__*/ __rspack_external_react.createElement("ul", {
@@ -215,58 +209,25 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
215
209
  role: "listitem"
216
210
  }, emptyLabel))));
217
211
  }
218
- if (!isVirtualized) return /*#__PURE__*/ __rspack_external_react.createElement(Card, null, /*#__PURE__*/ __rspack_external_react.createElement(CardHeader, null, /*#__PURE__*/ __rspack_external_react.createElement(CardTitle, null, "Asset browser"), /*#__PURE__*/ __rspack_external_react.createElement(CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ __rspack_external_react.createElement(CardContent, null, filterRow, /*#__PURE__*/ __rspack_external_react.createElement("ul", {
212
+ return /*#__PURE__*/ __rspack_external_react.createElement(Card, null, /*#__PURE__*/ __rspack_external_react.createElement(CardHeader, null, /*#__PURE__*/ __rspack_external_react.createElement(CardTitle, null, "Asset browser"), /*#__PURE__*/ __rspack_external_react.createElement(CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ __rspack_external_react.createElement(CardContent, null, filterRow, /*#__PURE__*/ __rspack_external_react.createElement(Windowed, {
213
+ activeIndex: activeIndex >= 0 ? activeIndex : void 0,
219
214
  "aria-label": "Assets",
220
- role: "list"
221
- }, visibleAssets.map((asset, offset)=>renderRow(asset, offset))), hasMore ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
222
- "data-asset-action": "load-more",
223
- onClick: ()=>{
224
- setPageLimit((current)=>current + pageSize);
225
- },
226
- type: "button"
227
- }, "Load more") : null));
228
- const totalHeight = total * itemHeight;
229
- const offsetY = firstVisible * itemHeight;
230
- return /*#__PURE__*/ __rspack_external_react.createElement(Card, null, /*#__PURE__*/ __rspack_external_react.createElement(CardHeader, null, /*#__PURE__*/ __rspack_external_react.createElement(CardTitle, null, "Asset browser"), /*#__PURE__*/ __rspack_external_react.createElement(CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ __rspack_external_react.createElement(CardContent, null, filterRow, /*#__PURE__*/ __rspack_external_react.createElement("div", {
231
- "data-asset-manager-virtual": true,
232
- onScroll: (event)=>{
233
- const next = event.currentTarget.scrollTop;
234
- if ("function" != typeof requestAnimationFrame) return void setScrollTop(next);
235
- pendingScrollTopRef.current = next;
236
- if (null !== scrollFrameRef.current) return;
237
- scrollFrameRef.current = requestAnimationFrame(()=>{
238
- scrollFrameRef.current = null;
239
- setScrollTop(pendingScrollTopRef.current);
240
- });
241
- },
242
- ref: scrollContainerRef,
243
- style: {
244
- height: maxHeight,
245
- overflowY: "auto",
246
- position: "relative"
247
- }
248
- }, /*#__PURE__*/ __rspack_external_react.createElement("div", {
249
- style: {
250
- height: totalHeight,
251
- position: "relative"
252
- }
253
- }, /*#__PURE__*/ __rspack_external_react.createElement("ul", {
254
- "aria-label": "Assets",
255
- role: "list",
256
- style: {
257
- margin: 0,
258
- padding: 0,
259
- position: "absolute",
260
- top: offsetY,
261
- left: 0,
262
- right: 0
263
- }
264
- }, visibleAssets.map((asset, offset)=>renderRow(asset, firstVisible + offset))))), hasMore ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
215
+ as: "ul",
216
+ "data-testid": "asset-browser-virtualized",
217
+ estimateSize: itemHeight,
218
+ items: visibleSlice,
219
+ itemKey: (asset)=>asset.id,
220
+ maxHeight: maxHeight,
221
+ renderItem: renderRow,
222
+ threshold: virtualizeThreshold
223
+ }), hasMore ? /*#__PURE__*/ __rspack_external_react.createElement(Button, {
265
224
  "data-asset-action": "load-more",
266
225
  onClick: ()=>{
267
226
  setPageLimit((current)=>current + pageSize);
268
227
  },
269
- type: "button"
228
+ type: "button",
229
+ variant: "outline",
230
+ size: "sm"
270
231
  }, "Load more") : null));
271
232
  }
272
233
  export { AssetBrowser };
@@ -2,11 +2,15 @@
2
2
  "use client";
3
3
  var __webpack_require__ = {};
4
4
  (()=>{
5
- __webpack_require__.d = (exports1, definition)=>{
6
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- get: definition[key]
9
- });
5
+ __webpack_require__.d = (exports1, getters, values)=>{
6
+ var define = (defs, kind)=>{
7
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
8
+ enumerable: true,
9
+ [kind]: defs[key]
10
+ });
11
+ };
12
+ define(getters, "get");
13
+ define(values, "value");
10
14
  };
11
15
  })();
12
16
  (()=>{
@@ -2,11 +2,15 @@
2
2
  "use client";
3
3
  var __webpack_require__ = {};
4
4
  (()=>{
5
- __webpack_require__.d = (exports1, definition)=>{
6
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- get: definition[key]
9
- });
5
+ __webpack_require__.d = (exports1, getters, values)=>{
6
+ var define = (defs, kind)=>{
7
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
8
+ enumerable: true,
9
+ [kind]: defs[key]
10
+ });
11
+ };
12
+ define(getters, "get");
13
+ define(values, "value");
10
14
  };
11
15
  })();
12
16
  (()=>{
@@ -37,7 +41,7 @@ const external_DeleteAssetDialog_cjs_namespaceObject = require("./DeleteAssetDia
37
41
  const external_MetadataPanel_cjs_namespaceObject = require("./MetadataPanel.cjs");
38
42
  const external_ReplaceAssetDialog_cjs_namespaceObject = require("./ReplaceAssetDialog.cjs");
39
43
  const external_UploadButton_cjs_namespaceObject = require("./UploadButton.cjs");
40
- function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlAllowlistOptIn, maxFileSize, onAssetInserted, registry, searchEnabled = true, uploader }) {
44
+ function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, aboveFilters, dataUrlAllowlistOptIn, draggableRows, maxFileSize, onAssetInserted, registry, searchEnabled = true, uploader }) {
41
45
  const [assets, setAssets] = external_react_namespaceObject.useState(()=>registry.list());
42
46
  const [progress, setProgress] = external_react_namespaceObject.useState(null);
43
47
  const [pendingDelete, setPendingDelete] = external_react_namespaceObject.useState(null);
@@ -131,7 +135,13 @@ function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlA
131
135
  onReplace: (asset)=>{
132
136
  setPendingReplace(asset);
133
137
  },
134
- searchEnabled: searchEnabled
138
+ searchEnabled: searchEnabled,
139
+ ...void 0 !== aboveFilters ? {
140
+ aboveFilters
141
+ } : {},
142
+ ...void 0 !== draggableRows ? {
143
+ draggableRows
144
+ } : {}
135
145
  }), /*#__PURE__*/ external_react_namespaceObject.createElement(external_DeleteAssetDialog_cjs_namespaceObject.DeleteAssetDialog, {
136
146
  asset: pendingDelete,
137
147
  onCancel: ()=>{
@@ -1,5 +1,13 @@
1
- import type { AssetManagerOptions, AssetRegistry, UploadResult } from "../types/types.js";
2
- export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "acceptedMimeTypes" | "maxFileSize" | "uploader" | "dataUrlAllowlistOptIn" | "allowMixedScriptHostnames"> {
1
+ import * as React from "react";
2
+ import type { AssetManagerOptions } from "../types/options.js";
3
+ import type { AssetRegistry, UploadAdapter, UploadResult } from "../types/types.js";
4
+ export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "acceptedMimeTypes" | "maxFileSize" | "dataUrlAllowlistOptIn" | "allowMixedScriptHostnames"> {
5
+ /**
6
+ * Binary uploader. Required at the UI boundary even though
7
+ * `AssetManagerOptions.uploader` is optional — the plugin passes the
8
+ * resolved (defaulted) uploader.
9
+ */
10
+ readonly uploader: UploadAdapter;
3
11
  readonly registry: AssetRegistry;
4
12
  readonly onAssetInserted?: (asset: UploadResult) => void;
5
13
  /**
@@ -10,6 +18,14 @@ export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "accepted
10
18
  * chrome can opt out.
11
19
  */
12
20
  readonly searchEnabled?: boolean;
21
+ /**
22
+ * Optional content rendered above the browser's filter row — e.g. a
23
+ * `FolderBreadcrumb` + `FolderTree` for folder navigation (PRD 0002 §7.4).
24
+ * The host wires these to the resolved data source / composite source.
25
+ */
26
+ readonly aboveFilters?: React.ReactNode;
27
+ /** Make asset rows draggable so they can be dropped onto a `FolderTree`. */
28
+ readonly draggableRows?: boolean;
13
29
  }
14
- export declare function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlAllowlistOptIn, maxFileSize, onAssetInserted, registry, searchEnabled, uploader, }: AssetManagerUIProps): import("react/jsx-runtime").JSX.Element;
30
+ export declare function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, aboveFilters, dataUrlAllowlistOptIn, draggableRows, maxFileSize, onAssetInserted, registry, searchEnabled, uploader, }: AssetManagerUIProps): import("react/jsx-runtime").JSX.Element;
15
31
  //# sourceMappingURL=AssetManagerUI.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssetManagerUI.d.cts","sourceRoot":"","sources":["../../src/ui/AssetManagerUI.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACX,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,mBAChB,SAAQ,IAAI,CACX,mBAAmB,EACjB,mBAAmB,GACnB,aAAa,GACb,UAAU,GACV,uBAAuB,GACvB,2BAA2B,CAC7B;IACD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,cAAc,CAAC,EAC9B,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAoB,EACpB,QAAQ,GACR,EAAE,mBAAmB,2CAiKrB"}
1
+ {"version":3,"file":"AssetManagerUI.d.cts","sourceRoot":"","sources":["../../src/ui/AssetManagerUI.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,mBAChB,SAAQ,IAAI,CACX,mBAAmB,EACjB,mBAAmB,GACnB,aAAa,GACb,uBAAuB,GACvB,2BAA2B,CAC7B;IACD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,cAAc,CAAC,EAC9B,iBAAiB,EACjB,yBAAyB,EACzB,YAAY,EACZ,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAoB,EACpB,QAAQ,GACR,EAAE,mBAAmB,2CAmKrB"}
@@ -1,5 +1,13 @@
1
- import type { AssetManagerOptions, AssetRegistry, UploadResult } from "../types/types.js";
2
- export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "acceptedMimeTypes" | "maxFileSize" | "uploader" | "dataUrlAllowlistOptIn" | "allowMixedScriptHostnames"> {
1
+ import * as React from "react";
2
+ import type { AssetManagerOptions } from "../types/options.js";
3
+ import type { AssetRegistry, UploadAdapter, UploadResult } from "../types/types.js";
4
+ export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "acceptedMimeTypes" | "maxFileSize" | "dataUrlAllowlistOptIn" | "allowMixedScriptHostnames"> {
5
+ /**
6
+ * Binary uploader. Required at the UI boundary even though
7
+ * `AssetManagerOptions.uploader` is optional — the plugin passes the
8
+ * resolved (defaulted) uploader.
9
+ */
10
+ readonly uploader: UploadAdapter;
3
11
  readonly registry: AssetRegistry;
4
12
  readonly onAssetInserted?: (asset: UploadResult) => void;
5
13
  /**
@@ -10,6 +18,14 @@ export interface AssetManagerUIProps extends Pick<AssetManagerOptions, "accepted
10
18
  * chrome can opt out.
11
19
  */
12
20
  readonly searchEnabled?: boolean;
21
+ /**
22
+ * Optional content rendered above the browser's filter row — e.g. a
23
+ * `FolderBreadcrumb` + `FolderTree` for folder navigation (PRD 0002 §7.4).
24
+ * The host wires these to the resolved data source / composite source.
25
+ */
26
+ readonly aboveFilters?: React.ReactNode;
27
+ /** Make asset rows draggable so they can be dropped onto a `FolderTree`. */
28
+ readonly draggableRows?: boolean;
13
29
  }
14
- export declare function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlAllowlistOptIn, maxFileSize, onAssetInserted, registry, searchEnabled, uploader, }: AssetManagerUIProps): import("react/jsx-runtime").JSX.Element;
30
+ export declare function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, aboveFilters, dataUrlAllowlistOptIn, draggableRows, maxFileSize, onAssetInserted, registry, searchEnabled, uploader, }: AssetManagerUIProps): import("react/jsx-runtime").JSX.Element;
15
31
  //# sourceMappingURL=AssetManagerUI.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssetManagerUI.d.ts","sourceRoot":"","sources":["../../src/ui/AssetManagerUI.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACX,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,mBAChB,SAAQ,IAAI,CACX,mBAAmB,EACjB,mBAAmB,GACnB,aAAa,GACb,UAAU,GACV,uBAAuB,GACvB,2BAA2B,CAC7B;IACD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,cAAc,CAAC,EAC9B,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAoB,EACpB,QAAQ,GACR,EAAE,mBAAmB,2CAiKrB"}
1
+ {"version":3,"file":"AssetManagerUI.d.ts","sourceRoot":"","sources":["../../src/ui/AssetManagerUI.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,mBAChB,SAAQ,IAAI,CACX,mBAAmB,EACjB,mBAAmB,GACnB,aAAa,GACb,uBAAuB,GACvB,2BAA2B,CAC7B;IACD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,cAAc,CAAC,EAC9B,iBAAiB,EACjB,yBAAyB,EACzB,YAAY,EACZ,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAoB,EACpB,QAAQ,GACR,EAAE,mBAAmB,2CAmKrB"}
@@ -9,7 +9,7 @@ import { MetadataPanel } from "./MetadataPanel.js";
9
9
  import { ReplaceAssetDialog } from "./ReplaceAssetDialog.js";
10
10
  import { UploadButton } from "./UploadButton.js";
11
11
  import * as __rspack_external_react from "react";
12
- function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlAllowlistOptIn, maxFileSize, onAssetInserted, registry, searchEnabled = true, uploader }) {
12
+ function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, aboveFilters, dataUrlAllowlistOptIn, draggableRows, maxFileSize, onAssetInserted, registry, searchEnabled = true, uploader }) {
13
13
  const [assets, setAssets] = __rspack_external_react.useState(()=>registry.list());
14
14
  const [progress, setProgress] = __rspack_external_react.useState(null);
15
15
  const [pendingDelete, setPendingDelete] = __rspack_external_react.useState(null);
@@ -103,7 +103,13 @@ function AssetManagerUI({ acceptedMimeTypes, allowMixedScriptHostnames, dataUrlA
103
103
  onReplace: (asset)=>{
104
104
  setPendingReplace(asset);
105
105
  },
106
- searchEnabled: searchEnabled
106
+ searchEnabled: searchEnabled,
107
+ ...void 0 !== aboveFilters ? {
108
+ aboveFilters
109
+ } : {},
110
+ ...void 0 !== draggableRows ? {
111
+ draggableRows
112
+ } : {}
107
113
  }), /*#__PURE__*/ __rspack_external_react.createElement(DeleteAssetDialog, {
108
114
  asset: pendingDelete,
109
115
  onCancel: ()=>{
@@ -2,11 +2,15 @@
2
2
  "use client";
3
3
  var __webpack_require__ = {};
4
4
  (()=>{
5
- __webpack_require__.d = (exports1, definition)=>{
6
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- get: definition[key]
9
- });
5
+ __webpack_require__.d = (exports1, getters, values)=>{
6
+ var define = (defs, kind)=>{
7
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
8
+ enumerable: true,
9
+ [kind]: defs[key]
10
+ });
11
+ };
12
+ define(getters, "get");
13
+ define(values, "value");
10
14
  };
11
15
  })();
12
16
  (()=>{
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ "use client";
3
+ var __webpack_require__ = {};
4
+ (()=>{
5
+ __webpack_require__.d = (exports1, getters, values)=>{
6
+ var define = (defs, kind)=>{
7
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
8
+ enumerable: true,
9
+ [kind]: defs[key]
10
+ });
11
+ };
12
+ define(getters, "get");
13
+ define(values, "value");
14
+ };
15
+ })();
16
+ (()=>{
17
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
18
+ })();
19
+ (()=>{
20
+ __webpack_require__.r = (exports1)=>{
21
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
22
+ value: 'Module'
23
+ });
24
+ Object.defineProperty(exports1, '__esModule', {
25
+ value: true
26
+ });
27
+ };
28
+ })();
29
+ var __webpack_exports__ = {};
30
+ __webpack_require__.r(__webpack_exports__);
31
+ __webpack_require__.d(__webpack_exports__, {
32
+ DeleteFolderDialog: ()=>DeleteFolderDialog
33
+ });
34
+ const button_namespaceObject = require("@anvilkit/ui/button");
35
+ const dialog_namespaceObject = require("@anvilkit/ui/dialog");
36
+ const external_react_namespaceObject = require("react");
37
+ function DeleteFolderDialog({ folder, onConfirm, onCancel }) {
38
+ const [busy, setBusy] = external_react_namespaceObject.useState(false);
39
+ async function confirm(cascade) {
40
+ if (null === folder || busy) return;
41
+ setBusy(true);
42
+ try {
43
+ await onConfirm(folder, cascade);
44
+ } finally{
45
+ setBusy(false);
46
+ }
47
+ }
48
+ const open = null !== folder;
49
+ const assetCount = folder?.counts.assets ?? 0;
50
+ return /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.Dialog, {
51
+ open: open,
52
+ onOpenChange: (next)=>{
53
+ if (!next && !busy) onCancel();
54
+ }
55
+ }, /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.DialogContent, null, /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.DialogHeader, null, /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.DialogTitle, null, "Delete folder?"), /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.DialogDescription, null, "“", folder?.name, "” will be removed. By default its contents move up to the parent folder — nothing is deleted. Choose “Delete contents” to remove its ", assetCount, " ", 1 === assetCount ? "asset" : "assets", " too.")), /*#__PURE__*/ external_react_namespaceObject.createElement(dialog_namespaceObject.DialogFooter, null, /*#__PURE__*/ external_react_namespaceObject.createElement(button_namespaceObject.Button, {
56
+ type: "button",
57
+ variant: "outline",
58
+ disabled: busy,
59
+ onClick: onCancel
60
+ }, "Cancel"), /*#__PURE__*/ external_react_namespaceObject.createElement(button_namespaceObject.Button, {
61
+ type: "button",
62
+ variant: "outline",
63
+ disabled: busy || null === folder,
64
+ onClick: ()=>void confirm(false)
65
+ }, busy ? "Removing…" : "Remove folder"), /*#__PURE__*/ external_react_namespaceObject.createElement(button_namespaceObject.Button, {
66
+ type: "button",
67
+ variant: "destructive",
68
+ disabled: busy || null === folder,
69
+ onClick: ()=>void confirm(true)
70
+ }, "Delete contents"))));
71
+ }
72
+ exports.DeleteFolderDialog = __webpack_exports__.DeleteFolderDialog;
73
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
74
+ "DeleteFolderDialog"
75
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
76
+ Object.defineProperty(exports, '__esModule', {
77
+ value: true
78
+ });
@@ -0,0 +1,11 @@
1
+ import type { AssetFolder } from "../types/folders.js";
2
+ export interface DeleteFolderDialogProps {
3
+ /** Folder to delete. `null` ⇒ closed. */
4
+ readonly folder: AssetFolder | null;
5
+ /** Confirm. `cascade=false` reparents children to the parent (default, safe);
6
+ * `cascade=true` also deletes the descendant assets. */
7
+ readonly onConfirm: (folder: AssetFolder, cascade: boolean) => void | Promise<void>;
8
+ readonly onCancel: () => void;
9
+ }
10
+ export declare function DeleteFolderDialog({ folder, onConfirm, onCancel, }: DeleteFolderDialogProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=DeleteFolderDialog.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteFolderDialog.d.cts","sourceRoot":"","sources":["../../src/ui/DeleteFolderDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACvC,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,CACnB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,OAAO,KACZ,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,EAClC,MAAM,EACN,SAAS,EACT,QAAQ,GACR,EAAE,uBAAuB,2CA6DzB"}
@@ -0,0 +1,11 @@
1
+ import type { AssetFolder } from "../types/folders.js";
2
+ export interface DeleteFolderDialogProps {
3
+ /** Folder to delete. `null` ⇒ closed. */
4
+ readonly folder: AssetFolder | null;
5
+ /** Confirm. `cascade=false` reparents children to the parent (default, safe);
6
+ * `cascade=true` also deletes the descendant assets. */
7
+ readonly onConfirm: (folder: AssetFolder, cascade: boolean) => void | Promise<void>;
8
+ readonly onCancel: () => void;
9
+ }
10
+ export declare function DeleteFolderDialog({ folder, onConfirm, onCancel, }: DeleteFolderDialogProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=DeleteFolderDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteFolderDialog.d.ts","sourceRoot":"","sources":["../../src/ui/DeleteFolderDialog.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACvC,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,CACnB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,OAAO,KACZ,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,EAClC,MAAM,EACN,SAAS,EACT,QAAQ,GACR,EAAE,uBAAuB,2CA6DzB"}
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { Button } from "@anvilkit/ui/button";
3
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@anvilkit/ui/dialog";
4
+ import * as __rspack_external_react from "react";
5
+ function DeleteFolderDialog({ folder, onConfirm, onCancel }) {
6
+ const [busy, setBusy] = __rspack_external_react.useState(false);
7
+ async function confirm(cascade) {
8
+ if (null === folder || busy) return;
9
+ setBusy(true);
10
+ try {
11
+ await onConfirm(folder, cascade);
12
+ } finally{
13
+ setBusy(false);
14
+ }
15
+ }
16
+ const open = null !== folder;
17
+ const assetCount = folder?.counts.assets ?? 0;
18
+ return /*#__PURE__*/ __rspack_external_react.createElement(Dialog, {
19
+ open: open,
20
+ onOpenChange: (next)=>{
21
+ if (!next && !busy) onCancel();
22
+ }
23
+ }, /*#__PURE__*/ __rspack_external_react.createElement(DialogContent, null, /*#__PURE__*/ __rspack_external_react.createElement(DialogHeader, null, /*#__PURE__*/ __rspack_external_react.createElement(DialogTitle, null, "Delete folder?"), /*#__PURE__*/ __rspack_external_react.createElement(DialogDescription, null, "“", folder?.name, "” will be removed. By default its contents move up to the parent folder — nothing is deleted. Choose “Delete contents” to remove its ", assetCount, " ", 1 === assetCount ? "asset" : "assets", " too.")), /*#__PURE__*/ __rspack_external_react.createElement(DialogFooter, null, /*#__PURE__*/ __rspack_external_react.createElement(Button, {
24
+ type: "button",
25
+ variant: "outline",
26
+ disabled: busy,
27
+ onClick: onCancel
28
+ }, "Cancel"), /*#__PURE__*/ __rspack_external_react.createElement(Button, {
29
+ type: "button",
30
+ variant: "outline",
31
+ disabled: busy || null === folder,
32
+ onClick: ()=>void confirm(false)
33
+ }, busy ? "Removing…" : "Remove folder"), /*#__PURE__*/ __rspack_external_react.createElement(Button, {
34
+ type: "button",
35
+ variant: "destructive",
36
+ disabled: busy || null === folder,
37
+ onClick: ()=>void confirm(true)
38
+ }, "Delete contents"))));
39
+ }
40
+ export { DeleteFolderDialog };