{"_id":"@craftthingy-digital-innovation/cty-smart-merge-sync-web","_rev":"3-c041056f91a04249e4466e160cd970cf","name":"@craftthingy-digital-innovation/cty-smart-merge-sync-web","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@craftthingy-digital-innovation/cty-smart-merge-sync-web","version":"1.0.0","_id":"@craftthingy-digital-innovation/cty-smart-merge-sync-web@1.0.0","maintainers":[{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"}],"homepage":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web#readme","bugs":{"url":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web/issues"},"dist":{"shasum":"cc634edcd457036e4fe39b7a603565aeb645030c","tarball":"https://registry.npmjs.org/@craftthingy-digital-innovation/cty-smart-merge-sync-web/-/cty-smart-merge-sync-web-1.0.0.tgz","fileCount":6,"integrity":"sha512-EYZEVn+w1KLfexada2nzcpJiGDpuvQcyYnuzQv1AIC8JMVW2ZRAuRClN7WzaPPnW2Tp1ui11ImMHdghHlLdLIw==","signatures":[{"sig":"MEYCIQCEM13qQQfFbU9/qumDiknlBAAjP2+cO26VhsaYJEdATQIhAIF6TWjRImYmHoBSHirAeL2STeXuUT9csfiMpyGtEuYB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15474},"main":"./dist/cty-smart-merge-sync.umd.js","type":"module","module":"./dist/cty-smart-merge-sync.es.js","exports":{".":{"import":"./dist/cty-smart-merge-sync.es.js","require":"./dist/cty-smart-merge-sync.umd.js"}},"gitHead":"5ab30522434a1be876ed5b83a240fbfcfb3a65f4","scripts":{"build":"vite build"},"_npmUser":{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"},"repository":{"url":"git+https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web.git","type":"git"},"_npmVersion":"10.8.2","description":"Bilingual documentation: [Bahasa Indonesia](#bahasa-indonesia) | [English](#english)","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cty-smart-merge-sync-web_1.0.0_1783079518870_0.5003300326575413","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@craftthingy-digital-innovation/cty-smart-merge-sync-web","version":"1.0.1","_id":"@craftthingy-digital-innovation/cty-smart-merge-sync-web@1.0.1","maintainers":[{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"}],"homepage":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web#readme","bugs":{"url":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web/issues"},"dist":{"shasum":"0176797e969748528cf24f821ff48eabbb1311ef","tarball":"https://registry.npmjs.org/@craftthingy-digital-innovation/cty-smart-merge-sync-web/-/cty-smart-merge-sync-web-1.0.1.tgz","fileCount":6,"integrity":"sha512-TPtga9Jr1XDilwXdOrQAxoIg8o3mOfTW8TvM4PmT/+1+/JYL7Mx3/8AMPGeIm6gN1jCE46bU+xOYCUrEJxCB9A==","signatures":[{"sig":"MEUCIECQz/3LYIYcKsJFbrGC5WQ4JK0VHD4wr7Wi7pGCRmqyAiEAlSz6hxkCmfOQA7PIT7cHaUnR0SOFiBLwcxKGHLdY0zQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15796},"main":"./dist/cty-smart-merge-sync.umd.js","type":"module","module":"./dist/cty-smart-merge-sync.es.js","exports":{".":{"import":"./dist/cty-smart-merge-sync.es.js","require":"./dist/cty-smart-merge-sync.umd.js"}},"gitHead":"6fb72415872056cc2ab154106fef1962cd66410a","scripts":{"build":"vite build"},"_npmUser":{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"},"repository":{"url":"git+https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web.git","type":"git"},"_npmVersion":"10.8.2","description":"Bilingual documentation: [Bahasa Indonesia](#bahasa-indonesia) | [English](#english)","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.2.0"},"_npmOperationalInternal":{"tmp":"tmp/cty-smart-merge-sync-web_1.0.1_1783090833695_0.07352778881843358","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@craftthingy-digital-innovation/cty-smart-merge-sync-web","version":"1.0.2","license":"SEE LICENSE IN LICENSE","type":"module","repository":{"type":"git","url":"git+https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web.git"},"bugs":{"url":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web/issues"},"homepage":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web#readme","main":"./dist/cty-smart-merge-sync.umd.js","module":"./dist/cty-smart-merge-sync.es.js","exports":{".":{"import":"./dist/cty-smart-merge-sync.es.js","require":"./dist/cty-smart-merge-sync.umd.js"}},"scripts":{"build":"vite build"},"publishConfig":{"access":"public"},"dependencies":{},"devDependencies":{"vite":"^5.2.0"},"_id":"@craftthingy-digital-innovation/cty-smart-merge-sync-web@1.0.2","gitHead":"24f20b76a003da637a5f6cadea33c4701baf336f","description":"Bilingual documentation: [Bahasa Indonesia](#bahasa-indonesia) | [English](#english)","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-BeA4A7YpN7DQ790oNZgowy8BaosSOiHJqXGA/HSgsI+hDmOFW8FuTj1OyAYaS/svzqBoyPeOWQcqH6XrP2QGsA==","shasum":"3716afe8d014cad7a4a978a837805685b388c6b7","tarball":"https://registry.npmjs.org/@craftthingy-digital-innovation/cty-smart-merge-sync-web/-/cty-smart-merge-sync-web-1.0.2.tgz","fileCount":6,"unpackedSize":15800,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD6ecdoTyVyuecUIolfCeG49Y5yEPpoQEnPqolJe37mtAIhAKUQv+91/nPBYeflVw+gDJAbU6R9pZrHQpaZbbRxve1y"}]},"_npmUser":{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"},"directories":{},"maintainers":[{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cty-smart-merge-sync-web_1.0.2_1783146514558_0.562095155092766"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-03T11:51:58.628Z","modified":"2026-07-04T06:28:34.828Z","1.0.0":"2026-07-03T11:51:59.040Z","1.0.1":"2026-07-03T15:00:33.833Z","1.0.2":"2026-07-04T06:28:34.704Z"},"bugs":{"url":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web/issues"},"homepage":"https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web#readme","repository":{"type":"git","url":"git+https://github.com/CraftThingy-Digital-Innovation/cty-smart-merge-sync-web.git"},"description":"Bilingual documentation: [Bahasa Indonesia](#bahasa-indonesia) | [English](#english)","maintainers":[{"name":"killerking69","email":"alifnurhidayatwork@gmail.com"}],"readme":"# @craftthingy-digital-innovation/cty-smart-merge-sync-web\n\nBilingual documentation: [Bahasa Indonesia](#bahasa-indonesia) | [English](#english)\n\n---\n\n## Bahasa Indonesia\n\nLibrary client-side Javascript untuk menangani kolaborasi sinkronisasi data real-time multi-user. Menggunakan algoritma **Smart Merge** untuk menyinkronkan data perubahan server tanpa merusak kursor ketik aktif pengguna (`document.activeElement`) dan tanpa menimpa perubahan lokal yang sedang mengantre di outbox.\n\nSangat cocok untuk merancang UI kolaboratif seperti Google Sheets, dashboard multi-user, atau sistem input data bersama.\n\n### Instalasi\n```bash\nnpm install @craftthingy-digital-innovation/cty-smart-merge-sync-web\n```\n\n### Cara Penggunaan\n```javascript\nimport { SmartSyncEngine } from '@craftthingy-digital-innovation/cty-smart-merge-sync-web';\n\nconst syncEngine = new SmartSyncEngine({\n  interval: 4000, // Ambil data dari server setiap 4 detik\n  fetchData: async () => {\n    const res = await fetch('/api/entries');\n    const result = await res.json();\n    return result.data; // Mengembalikan array data terbaru\n  },\n  isPendingLocal: (uuid, field) => {\n    // Return true jika baris/kolom ini sedang memiliki antrean simpan offline\n    return myOfflineQueue.hasPending(uuid, field);\n  },\n  fields: ['no_paspor', 'nama_pemohon', 'tempat_lahir'] // Kolom yang disinkronkan\n});\n\n// Jalankan polling sinkronisasi\nsyncEngine.start();\n\nsyncEngine.on('sync', (remoteList) => {\n  // Gabungkan data remote ke state lokal & perbarui DOM secara aman\n  syncEngine.merge(localEntries, remoteList, {\n    onAdd: (newItem) => {\n      // Tambahkan baris baru ke tabel DOM Anda\n      appendRowToTableDOM(newItem);\n    },\n    onDelete: (uuid) => {\n      // Hapus baris dari tabel DOM Anda\n      removeRowFromTableDOM(uuid);\n    },\n    onUpdateField: (uuid, field, val) => {\n      // Perbarui nilai input kolom spesifik di DOM\n      const input = document.querySelector(`tr[data-uuid=\"${uuid}\"] .field-${field}`);\n      if (input) input.value = val;\n    }\n  });\n});\n```\n\n---\n\n## English\n\nA client-side JavaScript library to coordinate real-time multi-user data synchronization. Employs a **Smart Merge** algorithm to merge database updates without causing cursor jumps, losing user's focus (`document.activeElement`), or overwriting pending local outbox edits.\n\nPerfect for collaborative UIs such as shared spreadsheets, multi-user dashboards, or shared forms.\n\n### Installation\n```bash\nnpm install @craftthingy-digital-innovation/cty-smart-merge-sync-web\n```\n\n### Usage\n```javascript\nimport { SmartSyncEngine } from '@craftthingy-digital-innovation/cty-smart-merge-sync-web';\n\nconst syncEngine = new SmartSyncEngine({\n  interval: 4000, // Poll server every 4 seconds\n  fetchData: async () => {\n    const res = await fetch('/api/entries');\n    const result = await res.json();\n    return result.data; // Return latest remote array\n  },\n  isPendingLocal: (uuid, field) => {\n    // Return true if this row/field has pending local saves in your outbox\n    return myOfflineQueue.hasPending(uuid, field);\n  },\n  fields: ['no_paspor', 'nama_pemohon', 'tempat_lahir'] // Fields to merge\n});\n\n// Start collaboration polling\nsyncEngine.start();\n\nsyncEngine.on('sync', (remoteList) => {\n  // Merge remote data into local state & DOM safely\n  syncEngine.merge(localEntries, remoteList, {\n    onAdd: (newItem) => {\n      // Add new row to your table DOM\n      appendRowToTableDOM(newItem);\n    },\n    onDelete: (uuid) => {\n      // Remove row from your table DOM\n      removeRowFromTableDOM(uuid);\n    },\n    onUpdateField: (uuid, field, val) => {\n      // Update specific input element value in the DOM\n      const input = document.querySelector(`tr[data-uuid=\"${uuid}\"] .field-${field}`);\n      if (input) input.value = val;\n    }\n  });\n});\n```\n","readmeFilename":"README.md","license":"SEE LICENSE IN LICENSE"}