Solid
Solid keys <For> rows by item reference. Passing newly allocated entry objects directly would remount retained rows, so the adapter exposes stable primitive keys.
Live before-and-after
Section titled “Live before-and-after”Executed source
Section titled “Executed source”Imported verbatim with ?raw from every implementation file shown below. Playback timing and FLIP controls come from the shared demo harness.
import { createLikftc } from "@vp-tw/likftc/solid";
import { For, createMemo, createSignal, type Accessor } from "solid-js";
import { render } from "solid-js/web";
import {
createAfterRows,
createBeforeRows,
describeRow,
mountFrameworkDemo,
type DemoFrameState,
type DemoRenderedRow,
type DemoRuntime,
} from "../shared/demo.js";
function requireRow(rows: readonly DemoRenderedRow[], key: number | string): DemoRenderedRow {
const row = rows.find((candidate) => candidate.key === key);
if (row === undefined) throw new Error(`Missing Solid demo row ${key}`);
return row;
}
function Row(props: { readonly row: Accessor<DemoRenderedRow> }) {
return (
<li
class="runtime-row"
data-collision={String(props.row().kind === "collision")}
data-id={props.row().item.id}
data-key={props.row().keyText}
data-kind={props.row().kind}
data-phase={props.row().kind === "exiting" ? "exiting" : "current"}
data-slot={String(props.row().slot)}
>
<b>{props.row().item.id.toUpperCase()}</b>
<span>{props.row().item.label}</span>
<code>{props.row().keyText}</code>
<em>{describeRow(props.row().kind)}</em>
</li>
);
}
await mountFrameworkDemo("Solid", (target, initialState): DemoRuntime => {
const [frame, setFrame] = createSignal<DemoFrameState>(initialState);
const dispose = render(() => {
const list = createLikftc(() => frame().items, { getId: (item) => item.id });
const beforeRows = createMemo(() => createBeforeRows(frame()));
const afterRows = createMemo(() => createAfterRows(frame(), list.entries()));
return (
<div class="runtime-grid">
<article class="runtime-panel">
<small>WITHOUT</small>
<h3>Logical ID key</h3>
<ol data-list="before">
<For each={beforeRows().map((row) => row.key)}>
{(key) => <Row row={() => requireRow(beforeRows(), key)} />}
</For>
</ol>
</article>
<article class="runtime-panel">
<small>WITH @LIKFTC/SOLID</small>
<h3>Presence identity</h3>
<ol data-list="after">
<For each={afterRows().map((row) => row.key)}>
{(key) => <Row row={() => requireRow(afterRows(), key)} />}
</For>
</ol>
</article>
</div>
);
}, target);
return {
destroy: dispose,
update: (nextState) => {
setFrame(nextState);
},
};
});
entry(key) retains the old value while an exiting keyed child remains owned.