refactor(dragdrop): generalize createBlockDragDrop<T extends { id: string }>
Removes the hard-typed TranscriptionBlockData constraint so JourneyEditor can reuse the pointer-drag module without importing transcription types. Selector contract (data-block-wrapper / data-drag-handle) unchanged. Adds type-regression guard test verified via tsc --noEmit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,33 @@
|
|||||||
import { describe, it, expect, vi } from 'vitest';
|
import { describe, it, expect, vi, expectTypeOf } from 'vitest';
|
||||||
import { createBlockDragDrop } from './useBlockDragDrop.svelte';
|
import { createBlockDragDrop } from './useBlockDragDrop.svelte';
|
||||||
import type { TranscriptionBlockData } from '$lib/shared/types';
|
import type { TranscriptionBlockData } from '$lib/shared/types';
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Type-regression guard: createBlockDragDrop must accept any T extends {id: string}
|
||||||
|
// so JourneyEditor can reuse it without importing TranscriptionBlockData.
|
||||||
|
// This test fails with "Expected 0 type arguments, but got 1" via tsc --noEmit
|
||||||
|
// until the function is made generic.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('createBlockDragDrop — generic type guard', () => {
|
||||||
|
it('accepts items shaped as { id: string; position: number } — not only TranscriptionBlockData', () => {
|
||||||
|
type SimpleItem = { id: string; position: number };
|
||||||
|
const items: SimpleItem[] = [
|
||||||
|
{ id: 'item-1', position: 0 },
|
||||||
|
{ id: 'item-2', position: 1 }
|
||||||
|
];
|
||||||
|
const onReorder = vi.fn();
|
||||||
|
const dd = createBlockDragDrop<SimpleItem>({ getSortedBlocks: () => items, onReorder });
|
||||||
|
// Verify the hook is functional with the new type — state reads must work
|
||||||
|
expect(dd.draggedBlockId).toBeNull();
|
||||||
|
expect(dd.dragOffsetY).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('TranscriptionBlockData caller still compiles — regression guard for existing transcription editor', () => {
|
||||||
|
// If the generic constraint is wrong this line fails tsc --noEmit
|
||||||
|
expectTypeOf(createBlockDragDrop<TranscriptionBlockData>).toBeFunction();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function makeBlock(id: string, sortOrder: number): TranscriptionBlockData {
|
function makeBlock(id: string, sortOrder: number): TranscriptionBlockData {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import type { TranscriptionBlockData } from '$lib/shared/types';
|
type Options<T extends { id: string }> = {
|
||||||
|
getSortedBlocks: () => T[];
|
||||||
type Options = {
|
|
||||||
getSortedBlocks: () => TranscriptionBlockData[];
|
|
||||||
onReorder: (blockIds: string[]) => void;
|
onReorder: (blockIds: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createBlockDragDrop({ getSortedBlocks, onReorder }: Options) {
|
export function createBlockDragDrop<T extends { id: string }>({
|
||||||
|
getSortedBlocks,
|
||||||
|
onReorder
|
||||||
|
}: Options<T>) {
|
||||||
let draggedBlockId = $state<string | null>(null);
|
let draggedBlockId = $state<string | null>(null);
|
||||||
let dropTargetIdx = $state<number | null>(null);
|
let dropTargetIdx = $state<number | null>(null);
|
||||||
let dragOffsetY = $state(0);
|
let dragOffsetY = $state(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user