{
  "id": "diff-tool",
  "name": "Diff Tool",
  "category": "utilities",
  "tags": ["diff", "compare", "text", "difference"],
  "description": "Compare two text blocks and show differences.",
  "triggers": ["diff tool", "compare text", "difference", "text compare"],
  "defaultSize": { "w": 4, "h": 4 },
  "source": "const DiffTool = () => {\n  const [left, setLeft] = React.useState('line one\\nline two\\nline three\\ncommon line');\n  const [right, setRight] = React.useState('line one\\nmodified line\\nline three\\ncommon line\\nnew line');\n  const [diff, setDiff] = React.useState([]);\n\n  const computeDiff = () => {\n    const a = left.split('\\n');\n    const b = right.split('\\n');\n    const m = a.length, n = b.length;\n    const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));\n    for (let i = 1; i <= m; i++) for (let j = 1; j <= n; j++) dp[i][j] = a[i-1] === b[j-1] ? dp[i-1][j-1] + 1 : Math.max(dp[i-1][j], dp[i][j-1]);\n    const result = [];\n    let i = m, j = n;\n    while (i > 0 || j > 0) {\n      if (i > 0 && j > 0 && a[i-1] === b[j-1]) {\n        result.unshift({ type: 'same', left: a[i-1], right: b[j-1] });\n        i--; j--;\n      } else if (j > 0 && (i === 0 || dp[i][j-1] >= dp[i-1][j])) {\n        result.unshift({ type: 'add', right: b[j-1] });\n        j--;\n      } else {\n        result.unshift({ type: 'remove', left: a[i-1] });\n        i--;\n      }\n    }\n    setDiff(result);\n  };\n\n  React.useEffect(() => {\n    computeDiff();\n  }, [left, right]);\n\n  const clear = () => {\n    setLeft('');\n    setRight('');\n  };\n\n  const typeStyle = (t) => {\n    if (t === 'add') return { background: '#dcfce7' };\n    if (t === 'remove') return { background: '#fee2e2' };\n    return { background: '#f9fafb' };\n  };\n  const typeColor = (t) => {\n    if (t === 'add') return '#16a34a';\n    if (t === 'remove') return '#dc2626';\n    return '#6b7280';\n  };\n\n  return React.createElement('div', { style: { fontFamily: 'system-ui, sans-serif', padding: '16px', display: 'flex', flexDirection: 'column', gap: '14px', height: '100%', overflow: 'auto' } },\n    React.createElement('h3', { style: { margin: 0, fontSize: '16px', fontWeight: 600, color: '#111827' } }, 'Diff Tool'),\n    React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px' } },\n      React.createElement('div', null,\n        React.createElement('div', { style: { fontSize: '11px', fontWeight: 600, color: '#6b7280', marginBottom: '4px' } }, 'Original'),\n        React.createElement('textarea', {\n          value: left,\n          onChange: e => setLeft(e.target.value),\n          placeholder: 'Original text...',\n          style: { width: '100%', minHeight: '100px', fontSize: '12px', padding: '8px', borderRadius: '6px', border: '1px solid #d1d5db', resize: 'vertical', fontFamily: 'monospace', boxSizing: 'border-box' }\n        })\n      ),\n      React.createElement('div', null,\n        React.createElement('div', { style: { fontSize: '11px', fontWeight: 600, color: '#6b7280', marginBottom: '4px' } }, 'Modified'),\n        React.createElement('textarea', {\n          value: right,\n          onChange: e => setRight(e.target.value),\n          placeholder: 'Modified text...',\n          style: { width: '100%', minHeight: '100px', fontSize: '12px', padding: '8px', borderRadius: '6px', border: '1px solid #d1d5db', resize: 'vertical', fontFamily: 'monospace', boxSizing: 'border-box' }\n        })\n      )\n    ),\n    React.createElement('div', { style: { display: 'flex', gap: '8px' } },\n      React.createElement('button', { onClick: computeDiff, style: { fontSize: '12px', padding: '6px 14px', borderRadius: '4px', border: 'none', background: '#2563eb', color: '#fff', cursor: 'pointer', fontWeight: 600 } }, 'Compare'),\n      React.createElement('button', { onClick: clear, style: { fontSize: '12px', padding: '6px 14px', borderRadius: '4px', border: 'none', background: '#6b7280', color: '#fff', cursor: 'pointer', fontWeight: 600 } }, 'Clear')\n    ),\n    React.createElement('div', null,\n      React.createElement('div', { style: { fontSize: '11px', fontWeight: 600, color: '#6b7280', marginBottom: '4px' } }, 'Diff Output'),\n      React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '40px 1fr 1fr', gap: '0', border: '1px solid #e5e7eb', borderRadius: '6px', overflow: 'hidden' } },\n        React.createElement('div', { style: { background: '#f3f4f6', padding: '6px 8px', fontSize: '10px', fontWeight: 700, color: '#6b7280', borderBottom: '1px solid #e5e7eb' } }, '#'),\n        React.createElement('div', { style: { background: '#f3f4f6', padding: '6px 8px', fontSize: '10px', fontWeight: 700, color: '#6b7280', borderBottom: '1px solid #e5e7eb', borderLeft: '1px solid #e5e7eb' } }, 'Original'),\n        React.createElement('div', { style: { background: '#f3f4f6', padding: '6px 8px', fontSize: '10px', fontWeight: 700, color: '#6b7280', borderBottom: '1px solid #e5e7eb', borderLeft: '1px solid #e5e7eb' } }, 'Modified'),\n        diff.map((d, i) => React.createElement(React.Fragment, { key: i },\n          React.createElement('div', { style: { ...typeStyle(d.type), padding: '5px 8px', fontSize: '11px', fontWeight: 700, color: typeColor(d.type), fontFamily: 'monospace', borderBottom: '1px solid #f3f4f6' } }, d.type === 'add' ? '+' : d.type === 'remove' ? '-' : ' '),\n          React.createElement('div', { style: { ...typeStyle(d.type), padding: '5px 8px', fontSize: '12px', fontFamily: 'monospace', color: '#374151', borderLeft: '1px solid #f3f4f6', borderBottom: '1px solid #f3f4f6', whiteSpace: 'pre-wrap', wordBreak: 'break-all' } }, d.left || ''),\n          React.createElement('div', { style: { ...typeStyle(d.type), padding: '5px 8px', fontSize: '12px', fontFamily: 'monospace', color: '#374151', borderLeft: '1px solid #f3f4f6', borderBottom: '1px solid #f3f4f6', whiteSpace: 'pre-wrap', wordBreak: 'break-all' } }, d.right || '')\n        ))\n      )\n    )\n  );\n};\nrender(<DiffTool/>);",
  "placeholders": []
}
