feat: Model Browser — block library with category filter tabs, search, favorites, NAM/IR models
This commit is contained in:
+70
-4
@@ -163,17 +163,37 @@ function VertBracket({ height, direction }) {
|
||||
}
|
||||
|
||||
// ── Split Block Tile ─────────────────────────────
|
||||
function SplitBlockTile({ block, selected, onSelect, onToggle }) {
|
||||
function SplitBlockTile({ block, selected, onSelect, onToggle, onModelBrowser }) {
|
||||
const splitParams = block.params || {};
|
||||
const splitType = splitParams.splitType || "y";
|
||||
const st = SPLIT_TYPES[splitType] || SPLIT_TYPES.y;
|
||||
const enabled = !block.bypassed;
|
||||
const color = getBlockColor("split");
|
||||
const longPressRef = useRef(null);
|
||||
|
||||
const handleTouchStart = useCallback(() => {
|
||||
longPressRef.current = setTimeout(() => {
|
||||
longPressRef.current = null;
|
||||
onModelBrowser?.(block.id);
|
||||
}, 500);
|
||||
}, [block.id, onModelBrowser]);
|
||||
|
||||
const handleTouchEnd = useCallback(() => {
|
||||
if (longPressRef.current) {
|
||||
clearTimeout(longPressRef.current);
|
||||
longPressRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
draggable
|
||||
onClick={() => onSelect(block.id)}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
onTouchMove={handleTouchEnd}
|
||||
onMouseDown={handleTouchEnd}
|
||||
onMouseUp={handleTouchEnd}
|
||||
style={{
|
||||
minWidth: 130, width: 130, height: 76, borderRadius: 8,
|
||||
background: `linear-gradient(135deg, ${T.panel}, #1A1520)`,
|
||||
@@ -237,14 +257,34 @@ function SplitBlockTile({ block, selected, onSelect, onToggle }) {
|
||||
}
|
||||
|
||||
// ── Merge Block Tile ──────────────────────────────
|
||||
function MergeBlockTile({ block, selected, onSelect, onToggle }) {
|
||||
function MergeBlockTile({ block, selected, onSelect, onToggle, onModelBrowser }) {
|
||||
const mergeParams = block.params || {};
|
||||
const enabled = !block.bypassed;
|
||||
const longPressRef = useRef(null);
|
||||
|
||||
const handleTouchStart = useCallback(() => {
|
||||
longPressRef.current = setTimeout(() => {
|
||||
longPressRef.current = null;
|
||||
onModelBrowser?.(block.id);
|
||||
}, 500);
|
||||
}, [block.id, onModelBrowser]);
|
||||
|
||||
const handleTouchEnd = useCallback(() => {
|
||||
if (longPressRef.current) {
|
||||
clearTimeout(longPressRef.current);
|
||||
longPressRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
draggable
|
||||
onClick={() => onSelect(block.id)}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
onTouchMove={handleTouchEnd}
|
||||
onMouseDown={handleTouchEnd}
|
||||
onMouseUp={handleTouchEnd}
|
||||
style={{
|
||||
minWidth: 130, width: 130, height: 76, borderRadius: 8,
|
||||
background: `linear-gradient(135deg, #15201A, ${T.panel})`,
|
||||
@@ -304,14 +344,34 @@ function MergeBlockTile({ block, selected, onSelect, onToggle }) {
|
||||
}
|
||||
|
||||
// ── Regular Block Tile ────────────────────────────
|
||||
function BlockTile({ block, selected, onSelect, onToggle, pathLabel }) {
|
||||
function BlockTile({ block, selected, onSelect, onToggle, pathLabel, onModelBrowser }) {
|
||||
const color = getBlockColor(block.type);
|
||||
const enabled = !block.bypassed;
|
||||
const longPressRef = useRef(null);
|
||||
|
||||
const handleTouchStart = useCallback(() => {
|
||||
longPressRef.current = setTimeout(() => {
|
||||
longPressRef.current = null;
|
||||
onModelBrowser?.(block.id);
|
||||
}, 500);
|
||||
}, [block.id, onModelBrowser]);
|
||||
|
||||
const handleTouchEnd = useCallback(() => {
|
||||
if (longPressRef.current) {
|
||||
clearTimeout(longPressRef.current);
|
||||
longPressRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
draggable
|
||||
onClick={() => onSelect(block.id)}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
onTouchMove={handleTouchEnd}
|
||||
onMouseDown={handleTouchEnd}
|
||||
onMouseUp={handleTouchEnd}
|
||||
style={{
|
||||
minWidth: 120, width: 120, height: 76, borderRadius: 8,
|
||||
background: pathLabel === "B" ? "#1A1820" : T.panel,
|
||||
@@ -435,7 +495,7 @@ function buildChainModel(blocks) {
|
||||
// ── Block Chain (exported) ─────────────────────────
|
||||
export default function BlockChain({
|
||||
blocks, selectedBlockId, onSelectBlock, onToggleBlock,
|
||||
onReorder, onAddBlock, onRemoveBlock,
|
||||
onReorder, onAddBlock, onRemoveBlock, onModelBrowser,
|
||||
}) {
|
||||
const scrollRef = useRef(null);
|
||||
const scrollBRef = useRef(null);
|
||||
@@ -528,6 +588,7 @@ export default function BlockChain({
|
||||
index={idx}
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
@@ -585,6 +646,7 @@ export default function BlockChain({
|
||||
index={idx}
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
@@ -597,6 +659,7 @@ export default function BlockChain({
|
||||
selected={splitBlock.id === selectedBlockId}
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
@@ -611,6 +674,7 @@ export default function BlockChain({
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
pathLabel="A"
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
@@ -626,6 +690,7 @@ export default function BlockChain({
|
||||
selected={mergeBlock.id === selectedBlockId}
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
@@ -639,6 +704,7 @@ export default function BlockChain({
|
||||
index={idx}
|
||||
onSelect={onSelectBlock}
|
||||
onToggle={onToggleBlock}
|
||||
onModelBrowser={onModelBrowser}
|
||||
/>
|
||||
<ChainArrow />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user