const DiffView = { oninit: function (vnode) { // Initialize indices in state vnode.state.leftIndex = vnode.attrs.versions.length - 1; // Earliest vnode.state.rightIndex = 0; // Latest }, view: function (vnode) { const versions = vnode.attrs.versions; return m("div", [ m("div.flex.gap-4.mb-4", [ m("div.flex-1", [ m("label.block.text-sm.font-medium.text-gray-700", "Left Version"), m( "select.mt-1.block.w-full.rounded-md.border-gray-300.shadow-sm", { onchange: (e) => { vnode.state.leftIndex = parseInt(e.target.value); vnode.state.leftVersion = versions[vnode.state.leftIndex]; vnode.state.updateDiff(); }, value: vnode.state.leftIndex, }, versions.map((v, idx) => m( "option", { value: idx }, `Version ${v.version_number} (${new Date( v.versioned_at ).toLocaleString()})` ) ) ), ]), m("div.flex-1", [ m("label.block.text-sm.font-medium.text-gray-700", "Right Version"), m( "select.mt-1.block.w-full.rounded-md.border-gray-300.shadow-sm", { onchange: (e) => { vnode.state.rightIndex = parseInt(e.target.value); vnode.state.rightVersion = versions[vnode.state.rightIndex]; vnode.state.updateDiff(); }, value: vnode.state.rightIndex, }, versions.map((v, idx) => m( "option", { value: idx }, `Version ${v.version_number} (${new Date( v.versioned_at ).toLocaleString()})` ) ) ), ]), ]), m("div", { id: "diff-container", style: "height: 500px; position: relative;", }), ]); }, oncreate: function (vnode) { const versions = vnode.attrs.versions; // Initialize with the earliest and most recent versions if available if (versions.length >= 2) { vnode.state.leftVersion = versions[versions.length - 1]; // Earliest version vnode.state.rightVersion = versions[0]; // Latest version } else if (versions.length === 1) { vnode.state.leftVersion = versions[0]; vnode.state.rightVersion = versions[0]; } vnode.state.updateDiff = function () { if (vnode.state.aceDiffer) { // Clean up previous instance vnode.state.aceDiffer.destroy(); } vnode.state.aceDiffer = new AceDiff({ element: "#diff-container", mode: "ace/mode/javascript", left: { content: vnode.state.leftVersion ? vnode.state.leftVersion.script : "", editable: false, }, right: { content: vnode.state.rightVersion ? vnode.state.rightVersion.script : "", editable: false, }, }); // Configure both editors const editors = vnode.state.aceDiffer.getEditors(); ["left", "right"].forEach((side) => { editors[side].setOptions({ maxLines: 20, autoScrollEditorIntoView: true, }); editors[side].session.setOption("useWorker", false); }); }; // Initial diff setup vnode.state.updateDiff(); }, onremove: function (vnode) { // Clean up AceDiff when component is removed if (vnode.state.aceDiffer) { vnode.state.aceDiffer.destroy(); } }, };