@anvilkit/plugin-asset-manager 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/adapters/data-url.cjs +9 -5
- package/dist/adapters/extract-image-dimensions.cjs +12 -8
- package/dist/adapters/in-memory.cjs +9 -5
- package/dist/adapters/s3-presigned.cjs +9 -5
- package/dist/index.cjs +9 -5
- package/dist/plugin.cjs +9 -5
- package/dist/testing/index.cjs +9 -5
- package/dist/ui/AssetBrowser.cjs +37 -93
- package/dist/ui/AssetBrowser.d.cts +5 -6
- package/dist/ui/AssetBrowser.d.cts.map +1 -1
- package/dist/ui/AssetBrowser.d.ts +5 -6
- package/dist/ui/AssetBrowser.d.ts.map +1 -1
- package/dist/ui/AssetBrowser.js +28 -88
- package/dist/ui/AssetCommandPalette.cjs +9 -5
- package/dist/ui/AssetManagerUI.cjs +9 -5
- package/dist/ui/DeleteAssetDialog.cjs +9 -5
- package/dist/ui/MetadataPanel.cjs +9 -5
- package/dist/ui/ReplaceAssetDialog.cjs +9 -5
- package/dist/ui/UploadButton.cjs +9 -5
- package/dist/ui/index.cjs +9 -5
- package/dist/utils/asset-reference.cjs +12 -8
- package/dist/utils/csp.cjs +12 -8
- package/dist/utils/errors.cjs +13 -9
- package/dist/utils/header-action.cjs +12 -8
- package/dist/utils/infer-kind.cjs +12 -8
- package/dist/utils/registry.cjs +9 -5
- package/dist/utils/resolver.cjs +9 -5
- package/dist/utils/retry.cjs +13 -9
- package/dist/utils/studio-asset-source.cjs +9 -5
- package/dist/utils/validate-upload-result.cjs +9 -5
- package/dist/version.cjs +12 -8
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/meta/config.json +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @anvilkit/plugin-asset-manager
|
|
2
2
|
|
|
3
|
-
> **Alpha (`0.1.
|
|
3
|
+
> **Alpha (`0.1.6`).** Public surface may still shift before `v1.0`. Bundle budgets enforced in CI: headless ≤ 6 KB gzip, UI subpath ≤ 12 KB gzip.
|
|
4
4
|
|
|
5
5
|
Headless asset manager plugin for Anvilkit Studio. The host provides the upload backend; the plugin handles validation, registration, search, IR-time resolution, CSP guidance, and (optionally) a React UI for the upload + browse experience. Designed for pluggable production backends (S3, GCS, custom HTTP) with strict trust-boundary enforcement on every adapter response.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ Headless asset manager plugin for Anvilkit Studio. The host provides the upload
|
|
|
10
10
|
pnpm add @anvilkit/plugin-asset-manager @anvilkit/core react react-dom @puckeditor/core
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Non-optional peers: `react
|
|
13
|
+
Non-optional peers: `react >=19.0.0`, `react-dom >=19.0.0`, `@puckeditor/core ^0.21.2`.
|
|
14
14
|
|
|
15
15
|
Subpath imports:
|
|
16
16
|
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
|
@@ -23,9 +27,6 @@ var __webpack_require__ = {};
|
|
|
23
27
|
})();
|
|
24
28
|
var __webpack_exports__ = {};
|
|
25
29
|
__webpack_require__.r(__webpack_exports__);
|
|
26
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
-
extractImageDimensions: ()=>extractImageDimensions
|
|
28
|
-
});
|
|
29
30
|
const DEFAULT_TIMEOUT_MS = 3000;
|
|
30
31
|
async function extractImageDimensions(url, mimeType, options = {}) {
|
|
31
32
|
if (!mimeType || !mimeType.startsWith("image/")) return;
|
|
@@ -69,6 +70,9 @@ async function extractImageDimensions(url, mimeType, options = {}) {
|
|
|
69
70
|
image.src = url;
|
|
70
71
|
});
|
|
71
72
|
}
|
|
73
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
74
|
+
extractImageDimensions: ()=>extractImageDimensions
|
|
75
|
+
});
|
|
72
76
|
exports.extractImageDimensions = __webpack_exports__.extractImageDimensions;
|
|
73
77
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
74
78
|
"extractImageDimensions"
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
package/dist/plugin.cjs
CHANGED
|
@@ -10,11 +10,15 @@ var __webpack_require__ = {};
|
|
|
10
10
|
};
|
|
11
11
|
})();
|
|
12
12
|
(()=>{
|
|
13
|
-
__webpack_require__.d = (exports1,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
|
+
var define = (defs, kind)=>{
|
|
15
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
[kind]: defs[key]
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
define(getters, "get");
|
|
21
|
+
define(values, "value");
|
|
18
22
|
};
|
|
19
23
|
})();
|
|
20
24
|
(()=>{
|
package/dist/testing/index.cjs
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
package/dist/ui/AssetBrowser.cjs
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
var __webpack_require__ = {};
|
|
4
4
|
(()=>{
|
|
5
|
-
__webpack_require__.d = (exports1,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
(()=>{
|
|
@@ -29,8 +33,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
29
33
|
});
|
|
30
34
|
const card_namespaceObject = require("@anvilkit/ui/card");
|
|
31
35
|
const input_namespaceObject = require("@anvilkit/ui/input");
|
|
36
|
+
const windowed_namespaceObject = require("@anvilkit/ui/windowed");
|
|
32
37
|
const external_react_namespaceObject = require("react");
|
|
33
|
-
const external_react_dom_namespaceObject = require("react-dom");
|
|
34
38
|
const infer_kind_cjs_namespaceObject = require("../utils/infer-kind.cjs");
|
|
35
39
|
const KIND_FILTERS = [
|
|
36
40
|
"image",
|
|
@@ -43,20 +47,13 @@ const DEFAULT_VIRTUALIZE_THRESHOLD = 50;
|
|
|
43
47
|
const DEFAULT_ITEM_HEIGHT = 56;
|
|
44
48
|
const DEFAULT_MAX_HEIGHT = 400;
|
|
45
49
|
const DEFAULT_PAGE_SIZE = 100;
|
|
46
|
-
const OVERSCAN = 4;
|
|
47
50
|
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 }) {
|
|
48
51
|
const [activeIndex, setActiveIndex] = external_react_namespaceObject.useState(assets.length > 0 ? 0 : -1);
|
|
49
|
-
const [scrollTop, setScrollTop] = external_react_namespaceObject.useState(0);
|
|
50
52
|
const [query, setQuery] = external_react_namespaceObject.useState("");
|
|
51
53
|
const [activeKinds, setActiveKinds] = external_react_namespaceObject.useState([]);
|
|
52
54
|
const [pageLimit, setPageLimit] = external_react_namespaceObject.useState(pageSize);
|
|
53
55
|
const buttonRefs = external_react_namespaceObject.useRef([]);
|
|
54
|
-
const
|
|
55
|
-
const scrollFrameRef = external_react_namespaceObject.useRef(null);
|
|
56
|
-
const pendingScrollTopRef = external_react_namespaceObject.useRef(0);
|
|
57
|
-
external_react_namespaceObject.useEffect(()=>()=>{
|
|
58
|
-
if (null !== scrollFrameRef.current && "function" == typeof cancelAnimationFrame) cancelAnimationFrame(scrollFrameRef.current);
|
|
59
|
-
}, []);
|
|
56
|
+
const pendingFocusRef = external_react_namespaceObject.useRef(null);
|
|
60
57
|
const searchIndex = external_react_namespaceObject.useMemo(()=>{
|
|
61
58
|
if (!searchEnabled) return null;
|
|
62
59
|
return assets.map((asset)=>({
|
|
@@ -96,7 +93,6 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
96
93
|
searchEnabled
|
|
97
94
|
]);
|
|
98
95
|
const total = visibleSlice.length;
|
|
99
|
-
const isVirtualized = total > virtualizeThreshold;
|
|
100
96
|
const hasMore = searchEnabled && filteredAssets.length > visibleSlice.length;
|
|
101
97
|
external_react_namespaceObject.useEffect(()=>{
|
|
102
98
|
if (0 === total) return void setActiveIndex(-1);
|
|
@@ -104,31 +100,20 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
104
100
|
}, [
|
|
105
101
|
total
|
|
106
102
|
]);
|
|
103
|
+
function focusRow(index) {
|
|
104
|
+
const node = buttonRefs.current[index];
|
|
105
|
+
if (node) {
|
|
106
|
+
node.focus();
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
107
111
|
function moveFocus(nextIndex) {
|
|
108
112
|
if (0 === total) return;
|
|
109
113
|
const clampedIndex = Math.max(0, Math.min(nextIndex, total - 1));
|
|
110
|
-
|
|
111
|
-
const targetTop = clampedIndex * itemHeight;
|
|
112
|
-
const targetBottom = targetTop + itemHeight;
|
|
113
|
-
const viewTop = scrollContainerRef.current.scrollTop;
|
|
114
|
-
let nextScrollTop = viewTop;
|
|
115
|
-
if (targetTop < viewTop) nextScrollTop = targetTop;
|
|
116
|
-
else if (targetBottom > viewTop + maxHeight) nextScrollTop = targetBottom - maxHeight;
|
|
117
|
-
if (null !== scrollFrameRef.current && "function" == typeof cancelAnimationFrame) {
|
|
118
|
-
cancelAnimationFrame(scrollFrameRef.current);
|
|
119
|
-
scrollFrameRef.current = null;
|
|
120
|
-
}
|
|
121
|
-
pendingScrollTopRef.current = nextScrollTop;
|
|
122
|
-
(0, external_react_dom_namespaceObject.flushSync)(()=>{
|
|
123
|
-
setActiveIndex(clampedIndex);
|
|
124
|
-
setScrollTop(nextScrollTop);
|
|
125
|
-
});
|
|
126
|
-
scrollContainerRef.current.scrollTop = nextScrollTop;
|
|
127
|
-
buttonRefs.current[clampedIndex]?.focus();
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
114
|
+
pendingFocusRef.current = clampedIndex;
|
|
130
115
|
setActiveIndex(clampedIndex);
|
|
131
|
-
|
|
116
|
+
if (focusRow(clampedIndex)) pendingFocusRef.current = null;
|
|
132
117
|
}
|
|
133
118
|
function toggleKind(kind) {
|
|
134
119
|
setActiveKinds((current)=>current.includes(kind) ? current.filter((entry)=>entry !== kind) : [
|
|
@@ -136,16 +121,7 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
136
121
|
kind
|
|
137
122
|
]);
|
|
138
123
|
}
|
|
139
|
-
const
|
|
140
|
-
const lastVisible = isVirtualized ? Math.min(total - 1, Math.ceil((scrollTop + maxHeight) / itemHeight) + OVERSCAN) : total - 1;
|
|
141
|
-
const visibleAssets = 0 === total ? [] : isVirtualized ? visibleSlice.slice(firstVisible, lastVisible + 1) : visibleSlice;
|
|
142
|
-
function renderRow(asset, index) {
|
|
143
|
-
return /*#__PURE__*/ external_react_namespaceObject.createElement("li", {
|
|
144
|
-
"aria-posinset": index + 1,
|
|
145
|
-
"aria-setsize": total,
|
|
146
|
-
key: asset.id,
|
|
147
|
-
role: "listitem"
|
|
148
|
-
}, /*#__PURE__*/ external_react_namespaceObject.createElement("button", {
|
|
124
|
+
const renderRow = (asset, index)=>/*#__PURE__*/ external_react_namespaceObject.createElement(external_react_namespaceObject.Fragment, null, /*#__PURE__*/ external_react_namespaceObject.createElement("button", {
|
|
149
125
|
"aria-label": `Insert asset ${asset.id}`,
|
|
150
126
|
onClick: ()=>{
|
|
151
127
|
onInsert(asset);
|
|
@@ -181,6 +157,10 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
181
157
|
},
|
|
182
158
|
ref: (node)=>{
|
|
183
159
|
buttonRefs.current[index] = node;
|
|
160
|
+
if (node && pendingFocusRef.current === index) {
|
|
161
|
+
pendingFocusRef.current = null;
|
|
162
|
+
node.focus();
|
|
163
|
+
}
|
|
184
164
|
},
|
|
185
165
|
tabIndex: activeIndex === index ? 0 : -1,
|
|
186
166
|
type: "button"
|
|
@@ -206,7 +186,6 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
206
186
|
},
|
|
207
187
|
type: "button"
|
|
208
188
|
}, "Delete") : null);
|
|
209
|
-
}
|
|
210
189
|
const filterRow = searchEnabled ? /*#__PURE__*/ external_react_namespaceObject.createElement("div", {
|
|
211
190
|
"data-asset-manager-filters": true
|
|
212
191
|
}, /*#__PURE__*/ external_react_namespaceObject.createElement(input_namespaceObject.Input, {
|
|
@@ -243,53 +222,18 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
243
222
|
role: "listitem"
|
|
244
223
|
}, emptyLabel))));
|
|
245
224
|
}
|
|
246
|
-
|
|
225
|
+
return /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.Card, null, /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardHeader, null, /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardTitle, null, "Asset browser"), /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardContent, null, filterRow, /*#__PURE__*/ external_react_namespaceObject.createElement(windowed_namespaceObject.Windowed, {
|
|
226
|
+
activeIndex: activeIndex >= 0 ? activeIndex : void 0,
|
|
247
227
|
"aria-label": "Assets",
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const offsetY = firstVisible * itemHeight;
|
|
258
|
-
return /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.Card, null, /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardHeader, null, /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardTitle, null, "Asset browser"), /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardDescription, null, "Validated assets currently registered in memory.")), /*#__PURE__*/ external_react_namespaceObject.createElement(card_namespaceObject.CardContent, null, filterRow, /*#__PURE__*/ external_react_namespaceObject.createElement("div", {
|
|
259
|
-
"data-asset-manager-virtual": true,
|
|
260
|
-
onScroll: (event)=>{
|
|
261
|
-
const next = event.currentTarget.scrollTop;
|
|
262
|
-
if ("function" != typeof requestAnimationFrame) return void setScrollTop(next);
|
|
263
|
-
pendingScrollTopRef.current = next;
|
|
264
|
-
if (null !== scrollFrameRef.current) return;
|
|
265
|
-
scrollFrameRef.current = requestAnimationFrame(()=>{
|
|
266
|
-
scrollFrameRef.current = null;
|
|
267
|
-
setScrollTop(pendingScrollTopRef.current);
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
ref: scrollContainerRef,
|
|
271
|
-
style: {
|
|
272
|
-
height: maxHeight,
|
|
273
|
-
overflowY: "auto",
|
|
274
|
-
position: "relative"
|
|
275
|
-
}
|
|
276
|
-
}, /*#__PURE__*/ external_react_namespaceObject.createElement("div", {
|
|
277
|
-
style: {
|
|
278
|
-
height: totalHeight,
|
|
279
|
-
position: "relative"
|
|
280
|
-
}
|
|
281
|
-
}, /*#__PURE__*/ external_react_namespaceObject.createElement("ul", {
|
|
282
|
-
"aria-label": "Assets",
|
|
283
|
-
role: "list",
|
|
284
|
-
style: {
|
|
285
|
-
margin: 0,
|
|
286
|
-
padding: 0,
|
|
287
|
-
position: "absolute",
|
|
288
|
-
top: offsetY,
|
|
289
|
-
left: 0,
|
|
290
|
-
right: 0
|
|
291
|
-
}
|
|
292
|
-
}, visibleAssets.map((asset, offset)=>renderRow(asset, firstVisible + offset))))), hasMore ? /*#__PURE__*/ external_react_namespaceObject.createElement("button", {
|
|
228
|
+
as: "ul",
|
|
229
|
+
"data-testid": "asset-browser-virtualized",
|
|
230
|
+
estimateSize: itemHeight,
|
|
231
|
+
items: visibleSlice,
|
|
232
|
+
itemKey: (asset)=>asset.id,
|
|
233
|
+
maxHeight: maxHeight,
|
|
234
|
+
renderItem: renderRow,
|
|
235
|
+
threshold: virtualizeThreshold
|
|
236
|
+
}), hasMore ? /*#__PURE__*/ external_react_namespaceObject.createElement("button", {
|
|
293
237
|
"data-asset-action": "load-more",
|
|
294
238
|
onClick: ()=>{
|
|
295
239
|
setPageLimit((current)=>current + pageSize);
|
|
@@ -33,17 +33,16 @@ export interface AssetBrowserProps {
|
|
|
33
33
|
/**
|
|
34
34
|
* Threshold above which the list windows visible items. Below the
|
|
35
35
|
* threshold the entire list renders inline so small libraries skip
|
|
36
|
-
* scroll math entirely.
|
|
36
|
+
* scroll math entirely. Forwarded to the shared `Windowed` primitive.
|
|
37
37
|
*/
|
|
38
38
|
readonly virtualizeThreshold?: number;
|
|
39
39
|
/**
|
|
40
40
|
* Pixel height of a single row when virtualizing.
|
|
41
41
|
*
|
|
42
|
-
* **Fixed-height contract:** the windowing math
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* Keep rows uniform, or raise `virtualizeThreshold` so the list renders
|
|
42
|
+
* **Fixed-height contract:** the windowing math assumes every row is
|
|
43
|
+
* roughly `itemHeight` tall. Rows that wrap or vary in height (long
|
|
44
|
+
* names, thumbnails) will desync the scroll-into-view calculation. Keep
|
|
45
|
+
* rows uniform, or raise `virtualizeThreshold` so the list renders
|
|
47
46
|
* inline instead.
|
|
48
47
|
*/
|
|
49
48
|
readonly itemHeight?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetBrowser.d.cts","sourceRoot":"","sources":["../../src/ui/AssetBrowser.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC
|
|
1
|
+
{"version":3,"file":"AssetBrowser.d.cts","sourceRoot":"","sources":["../../src/ui/AssetBrowser.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAOD,wBAAgB,YAAY,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,MAAM,EACN,aAAqB,EACrB,QAA4B,EAC5B,mBAAkD,EAClD,UAAgC,EAChC,SAA8B,GAC9B,EAAE,iBAAiB,2CAuSnB"}
|
|
@@ -33,17 +33,16 @@ export interface AssetBrowserProps {
|
|
|
33
33
|
/**
|
|
34
34
|
* Threshold above which the list windows visible items. Below the
|
|
35
35
|
* threshold the entire list renders inline so small libraries skip
|
|
36
|
-
* scroll math entirely.
|
|
36
|
+
* scroll math entirely. Forwarded to the shared `Windowed` primitive.
|
|
37
37
|
*/
|
|
38
38
|
readonly virtualizeThreshold?: number;
|
|
39
39
|
/**
|
|
40
40
|
* Pixel height of a single row when virtualizing.
|
|
41
41
|
*
|
|
42
|
-
* **Fixed-height contract:** the windowing math
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* Keep rows uniform, or raise `virtualizeThreshold` so the list renders
|
|
42
|
+
* **Fixed-height contract:** the windowing math assumes every row is
|
|
43
|
+
* roughly `itemHeight` tall. Rows that wrap or vary in height (long
|
|
44
|
+
* names, thumbnails) will desync the scroll-into-view calculation. Keep
|
|
45
|
+
* rows uniform, or raise `virtualizeThreshold` so the list renders
|
|
47
46
|
* inline instead.
|
|
48
47
|
*/
|
|
49
48
|
readonly itemHeight?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetBrowser.d.ts","sourceRoot":"","sources":["../../src/ui/AssetBrowser.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC
|
|
1
|
+
{"version":3,"file":"AssetBrowser.d.ts","sourceRoot":"","sources":["../../src/ui/AssetBrowser.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAOD,wBAAgB,YAAY,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,MAAM,EACN,aAAqB,EACrB,QAA4B,EAC5B,mBAAkD,EAClD,UAAgC,EAChC,SAA8B,GAC9B,EAAE,iBAAiB,2CAuSnB"}
|
package/dist/ui/AssetBrowser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@anvilkit/ui/card";
|
|
3
3
|
import { Input } from "@anvilkit/ui/input";
|
|
4
|
-
import {
|
|
4
|
+
import { Windowed } from "@anvilkit/ui/windowed";
|
|
5
5
|
import { inferAssetKind } from "../utils/infer-kind.js";
|
|
6
6
|
import * as __rspack_external_react from "react";
|
|
7
7
|
const KIND_FILTERS = [
|
|
@@ -15,20 +15,13 @@ const DEFAULT_VIRTUALIZE_THRESHOLD = 50;
|
|
|
15
15
|
const DEFAULT_ITEM_HEIGHT = 56;
|
|
16
16
|
const DEFAULT_MAX_HEIGHT = 400;
|
|
17
17
|
const DEFAULT_PAGE_SIZE = 100;
|
|
18
|
-
const OVERSCAN = 4;
|
|
19
18
|
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
19
|
const [activeIndex, setActiveIndex] = __rspack_external_react.useState(assets.length > 0 ? 0 : -1);
|
|
21
|
-
const [scrollTop, setScrollTop] = __rspack_external_react.useState(0);
|
|
22
20
|
const [query, setQuery] = __rspack_external_react.useState("");
|
|
23
21
|
const [activeKinds, setActiveKinds] = __rspack_external_react.useState([]);
|
|
24
22
|
const [pageLimit, setPageLimit] = __rspack_external_react.useState(pageSize);
|
|
25
23
|
const buttonRefs = __rspack_external_react.useRef([]);
|
|
26
|
-
const
|
|
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
|
-
}, []);
|
|
24
|
+
const pendingFocusRef = __rspack_external_react.useRef(null);
|
|
32
25
|
const searchIndex = __rspack_external_react.useMemo(()=>{
|
|
33
26
|
if (!searchEnabled) return null;
|
|
34
27
|
return assets.map((asset)=>({
|
|
@@ -68,7 +61,6 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
68
61
|
searchEnabled
|
|
69
62
|
]);
|
|
70
63
|
const total = visibleSlice.length;
|
|
71
|
-
const isVirtualized = total > virtualizeThreshold;
|
|
72
64
|
const hasMore = searchEnabled && filteredAssets.length > visibleSlice.length;
|
|
73
65
|
__rspack_external_react.useEffect(()=>{
|
|
74
66
|
if (0 === total) return void setActiveIndex(-1);
|
|
@@ -76,31 +68,20 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
76
68
|
}, [
|
|
77
69
|
total
|
|
78
70
|
]);
|
|
71
|
+
function focusRow(index) {
|
|
72
|
+
const node = buttonRefs.current[index];
|
|
73
|
+
if (node) {
|
|
74
|
+
node.focus();
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
79
|
function moveFocus(nextIndex) {
|
|
80
80
|
if (0 === total) return;
|
|
81
81
|
const clampedIndex = Math.max(0, Math.min(nextIndex, total - 1));
|
|
82
|
-
|
|
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
|
-
}
|
|
82
|
+
pendingFocusRef.current = clampedIndex;
|
|
102
83
|
setActiveIndex(clampedIndex);
|
|
103
|
-
|
|
84
|
+
if (focusRow(clampedIndex)) pendingFocusRef.current = null;
|
|
104
85
|
}
|
|
105
86
|
function toggleKind(kind) {
|
|
106
87
|
setActiveKinds((current)=>current.includes(kind) ? current.filter((entry)=>entry !== kind) : [
|
|
@@ -108,16 +89,7 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
108
89
|
kind
|
|
109
90
|
]);
|
|
110
91
|
}
|
|
111
|
-
const
|
|
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", {
|
|
92
|
+
const renderRow = (asset, index)=>/*#__PURE__*/ __rspack_external_react.createElement(__rspack_external_react.Fragment, null, /*#__PURE__*/ __rspack_external_react.createElement("button", {
|
|
121
93
|
"aria-label": `Insert asset ${asset.id}`,
|
|
122
94
|
onClick: ()=>{
|
|
123
95
|
onInsert(asset);
|
|
@@ -153,6 +125,10 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
153
125
|
},
|
|
154
126
|
ref: (node)=>{
|
|
155
127
|
buttonRefs.current[index] = node;
|
|
128
|
+
if (node && pendingFocusRef.current === index) {
|
|
129
|
+
pendingFocusRef.current = null;
|
|
130
|
+
node.focus();
|
|
131
|
+
}
|
|
156
132
|
},
|
|
157
133
|
tabIndex: activeIndex === index ? 0 : -1,
|
|
158
134
|
type: "button"
|
|
@@ -178,7 +154,6 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
178
154
|
},
|
|
179
155
|
type: "button"
|
|
180
156
|
}, "Delete") : null);
|
|
181
|
-
}
|
|
182
157
|
const filterRow = searchEnabled ? /*#__PURE__*/ __rspack_external_react.createElement("div", {
|
|
183
158
|
"data-asset-manager-filters": true
|
|
184
159
|
}, /*#__PURE__*/ __rspack_external_react.createElement(Input, {
|
|
@@ -215,53 +190,18 @@ function AssetBrowser({ assets, onInsert, onDelete, onReplace, onEdit, searchEna
|
|
|
215
190
|
role: "listitem"
|
|
216
191
|
}, emptyLabel))));
|
|
217
192
|
}
|
|
218
|
-
|
|
193
|
+
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, {
|
|
194
|
+
activeIndex: activeIndex >= 0 ? activeIndex : void 0,
|
|
219
195
|
"aria-label": "Assets",
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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", {
|
|
196
|
+
as: "ul",
|
|
197
|
+
"data-testid": "asset-browser-virtualized",
|
|
198
|
+
estimateSize: itemHeight,
|
|
199
|
+
items: visibleSlice,
|
|
200
|
+
itemKey: (asset)=>asset.id,
|
|
201
|
+
maxHeight: maxHeight,
|
|
202
|
+
renderItem: renderRow,
|
|
203
|
+
threshold: virtualizeThreshold
|
|
204
|
+
}), hasMore ? /*#__PURE__*/ __rspack_external_react.createElement("button", {
|
|
265
205
|
"data-asset-action": "load-more",
|
|
266
206
|
onClick: ()=>{
|
|
267
207
|
setPageLimit((current)=>current + pageSize);
|