vue2-excel-grid 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -74,6 +74,7 @@ export default {
74
74
  - `col.onSelect` callback — fires when a value is picked in a `select`/`treeSelect` column
75
75
  - `col.enableSearch` — search box in the `select`/`treeSelect` dropdown; treeSelect searches every level
76
76
  - Toolbar — `toolbar` prop: Undo/Redo, Export/Import, theme picker, size switcher, Lock (read-only mode), and Fullscreen; add custom buttons via `toolbarButtons` or the `#toolbar-extra` slot
77
+ - `localSyncKey` prop — autosaves `v-model` data to the browser's IndexedDB in the background (debounced), with a toolbar button + modal to Save/Restore/Delete the local copy, plus a full CRUD `ref` API (`saveLocalSnapshot`, `getLocalSnapshot`, `restoreLocalSnapshot`, `clearLocalSnapshot`) for building your own custom UI
77
78
 
78
79
  ## Documentation
79
80
 
@@ -95,6 +96,7 @@ Full documentation: [docs/](./docs/)
95
96
  - [Excel Export](./docs/excel-export.md)
96
97
  - [Excel Import](./docs/excel-import.md)
97
98
  - [Toolbar](./docs/toolbar.md)
99
+ - [Local Sync](./docs/local-sync.md)
98
100
  - [API Reference](./docs/api-reference.md)
99
101
 
100
102
  ## Demo
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * vue2-excel-grid v1.7.0
2
+ * vue2-excel-grid v1.7.1
3
3
  * (c) 2026
4
4
  * Released under the MIT License.
5
5
  */
@@ -6910,7 +6910,7 @@ __vue_render__$1._withStripped = true;
6910
6910
  /* style */
6911
6911
  const __vue_inject_styles__$1 = function (inject) {
6912
6912
  if (!inject) return
6913
- inject("data-v-76755314_0", { source: "\n.eg-lsm-overlay {\n position: fixed;\n inset: 0;\n background: var(--eg-color-overlay-bg, var(--eg-color-overlay-bg-default));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n.eg-lsm-dialog {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n box-shadow: var(--eg-shadow-dialog, var(--eg-shadow-dialog-default));\n width: min(720px, 92vw);\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n font-family: inherit;\n}\n.eg-lsm-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-close {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n padding: 4px 6px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n}\n.eg-lsm-close:hover {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-body {\n padding: 16px 18px;\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n}\n.eg-lsm-empty {\n text-align: center;\n padding: 32px 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n}\n.eg-lsm-meta {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-bottom: 10px;\n}\n.eg-lsm-table-wrap {\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n overflow: auto;\n max-height: 45vh;\n}\n.eg-lsm-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-table th,\n.eg-lsm-table td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n text-align: left;\n white-space: nowrap;\n}\n.eg-lsm-table th {\n position: sticky;\n top: 0;\n background: var(--eg-color-header-bg, var(--eg-color-header-bg-default));\n font-weight: 600;\n z-index: 1;\n}\n.eg-lsm-table tbody tr:last-child td {\n border-bottom: none;\n}\n.eg-lsm-more {\n padding: 8px 10px;\n font-size: 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n text-align: center;\n}\n.eg-lsm-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 14px 18px;\n border-top: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-confirm-text {\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-right: auto;\n}\n.eg-lsm-btn {\n padding: 6px 14px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n border: 1px solid var(--eg-color-border, var(--eg-color-border-default));\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n cursor: pointer;\n}\n.eg-lsm-btn:hover:not(:disabled) {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.eg-lsm-btn-accent {\n background: var(--eg-color-accent, var(--eg-color-accent-default));\n border-color: var(--eg-color-accent, var(--eg-color-accent-default));\n color: #fff;\n}\n.eg-lsm-btn-accent:hover:not(:disabled) {\n background: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n border-color: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n}\n.eg-lsm-btn-danger {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border-color: var(--eg-color-error, var(--eg-color-error-default));\n color: var(--eg-color-error, var(--eg-color-error-default));\n}\n.eg-lsm-btn-danger:hover:not(:disabled) {\n background: var(--eg-color-error-soft, var(--eg-color-error-soft-default));\n}\n", map: {"version":3,"sources":["/Users/macmini/Projects/Realsoft/vue2-excel-grid/src/components/EgLocalSyncModal.vue"],"names":[],"mappings":";AAyHA;EACA,eAAA;EACA,QAAA;EACA,0EAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,cAAA;AACA;AACA;EACA,oEAAA;EACA,kFAAA;EACA,yDAAA;EACA,oEAAA;EACA,uBAAA;EACA,gBAAA;EACA,aAAA;EACA,sBAAA;EACA,oBAAA;AACA;AACA;EACA,aAAA;EACA,mBAAA;EACA,8BAAA;EACA,kBAAA;EACA,yFAAA;EACA,cAAA;AACA;AACA;EACA,eAAA;EACA,gBAAA;EACA,yDAAA;AACA;AACA;EACA,gBAAA;EACA,YAAA;EACA,eAAA;EACA,eAAA;EACA,cAAA;EACA,6EAAA;EACA,gBAAA;EACA,yDAAA;AACA;AACA;EACA,oFAAA;AACA;AACA;EACA,kBAAA;EACA,gBAAA;EACA,OAAA;EACA,aAAA;AACA;AACA;EACA,kBAAA;EACA,kBAAA;EACA,qEAAA;EACA,2DAAA;AACA;AACA;EACA,aAAA;EACA,8BAAA;EACA,eAAA;EACA,6EAAA;EACA,mBAAA;AACA;AACA;EACA,kFAAA;EACA,yDAAA;EACA,cAAA;EACA,gBAAA;AACA;AACA;EACA,WAAA;EACA,yBAAA;EACA,2DAAA;EACA,yDAAA;AACA;AACA;;EAEA,iBAAA;EACA,yFAAA;EACA,gBAAA;EACA,mBAAA;AACA;AACA;EACA,gBAAA;EACA,MAAA;EACA,wEAAA;EACA,gBAAA;EACA,UAAA;AACA;AACA;EACA,mBAAA;AACA;AACA;EACA,iBAAA;EACA,eAAA;EACA,qEAAA;EACA,kBAAA;AACA;AACA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,SAAA;EACA,kBAAA;EACA,sFAAA;EACA,cAAA;AACA;AACA;EACA,eAAA;EACA,6EAAA;EACA,kBAAA;AACA;AACA;EACA,iBAAA;EACA,yDAAA;EACA,wEAAA;EACA,oEAAA;EACA,yDAAA;EACA,2DAAA;EACA,eAAA;AACA;AACA;EACA,oFAAA;AACA;AACA;EACA,YAAA;EACA,eAAA;AACA;AACA;EACA,kEAAA;EACA,oEAAA;EACA,WAAA;AACA;AACA;EACA,4EAAA;EACA,8EAAA;AACA;AACA;EACA,oEAAA;EACA,kEAAA;EACA,2DAAA;AACA;AACA;EACA,0EAAA;AACA","file":"EgLocalSyncModal.vue","sourcesContent":["<template>\n <div v-if=\"visible\" class=\"eg-lsm-overlay\" @click.self=\"$emit('close')\">\n <div class=\"eg-lsm-dialog\">\n <div class=\"eg-lsm-header\">\n <span class=\"eg-lsm-title\">{{ t.localSyncTitle }}</span>\n <button type=\"button\" class=\"eg-lsm-close\" @click=\"$emit('close')\" :title=\"t.localSyncClose\">✕</button>\n </div>\n\n <div class=\"eg-lsm-body\">\n <div v-if=\"!snapshot\" class=\"eg-lsm-empty\">{{ t.localSyncEmpty }}</div>\n <template v-else>\n <div class=\"eg-lsm-meta\">\n <span>{{ t.localSyncSavedAt }}: {{ savedAtText }}</span>\n <span>{{ snapshot.data.length }} {{ t.localSyncRows }}</span>\n </div>\n <div class=\"eg-lsm-table-wrap\">\n <table class=\"eg-lsm-table\">\n <thead>\n <tr>\n <th v-for=\"col in columns\" :key=\"col.key\">{{ col.title || col.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, ri) in previewRows\" :key=\"ri\">\n <td v-for=\"col in columns\" :key=\"col.key\">{{ resolveCellDisplay(row, col) }}</td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"hiddenRowCount > 0\" class=\"eg-lsm-more\">{{ moreRowsText }}</div>\n </div>\n </template>\n </div>\n\n <div class=\"eg-lsm-footer\">\n <template v-if=\"confirmingClear\">\n <span class=\"eg-lsm-confirm-text\">{{ t.localSyncConfirmClear }}</span>\n <button type=\"button\" class=\"eg-lsm-btn\" @click=\"confirmingClear = false\">{{ t.localSyncConfirmNo }}</button>\n <button type=\"button\" class=\"eg-lsm-btn eg-lsm-btn-danger\" @click=\"onConfirmClear\">{{ t.localSyncConfirmYes }}</button>\n </template>\n <template v-else>\n <button\n type=\"button\"\n class=\"eg-lsm-btn eg-lsm-btn-danger\"\n :disabled=\"!snapshot\"\n @click=\"confirmingClear = true\"\n >{{ t.localSyncClear }}</button>\n <button\n type=\"button\"\n class=\"eg-lsm-btn\"\n :title=\"t.localSyncSaveHint\"\n @click=\"$emit('save')\"\n >{{ t.localSyncSave }}</button>\n <button\n type=\"button\"\n class=\"eg-lsm-btn eg-lsm-btn-accent\"\n :disabled=\"!snapshot\"\n :title=\"t.localSyncRestoreHint\"\n @click=\"$emit('restore')\"\n >{{ t.localSyncRestore }}</button>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script>\n// \"Dumb\" presentation component for ExcelGrid.vue's localSyncKey feature —\n// shows the last IndexedDB-saved v-model snapshot (see src/utils/idbStore.js)\n// and lets the host Restore it back into the grid or delete it. Not exported\n// from src/index.js (same \"internal-only\" convention as EgDatePicker.vue /\n// EgCheckbox.vue) — purpose-built for ExcelGrid.vue, not meant for standalone use.\nconst PREVIEW_ROW_LIMIT = 200\n\nimport { getMessages } from '../utils/i18n.js'\n\nexport default {\n name: 'EgLocalSyncModal',\n props: {\n visible: { type: Boolean, default: false },\n columns: { type: Array, default: () => [] },\n snapshot: { type: Object, default: null }, // { data, updatedAt } | null\n resolveCellDisplay: { type: Function, required: true },\n locale: { type: String, default: 'en' }\n },\n data() {\n return { confirmingClear: false }\n },\n computed: {\n t() { return getMessages(this.locale) },\n savedAtText() {\n if (!this.snapshot) return ''\n return new Date(this.snapshot.updatedAt).toLocaleString()\n },\n previewRows() {\n if (!this.snapshot) return []\n return this.snapshot.data.slice(0, PREVIEW_ROW_LIMIT)\n },\n hiddenRowCount() {\n if (!this.snapshot) return 0\n return Math.max(0, this.snapshot.data.length - PREVIEW_ROW_LIMIT)\n },\n moreRowsText() {\n return (this.t.localSyncMoreRows || '').replace('{n}', this.hiddenRowCount)\n }\n },\n watch: {\n // A freshly opened modal (or a snapshot that just got deleted/restored)\n // should never inherit a stale \"are you sure?\" state from last time.\n visible(val) { if (!val) this.confirmingClear = false },\n snapshot() { this.confirmingClear = false }\n },\n methods: {\n onConfirmClear() {\n this.confirmingClear = false\n this.$emit('clear')\n }\n }\n}\n</script>\n\n<style>\n.eg-lsm-overlay {\n position: fixed;\n inset: 0;\n background: var(--eg-color-overlay-bg, var(--eg-color-overlay-bg-default));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n.eg-lsm-dialog {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n box-shadow: var(--eg-shadow-dialog, var(--eg-shadow-dialog-default));\n width: min(720px, 92vw);\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n font-family: inherit;\n}\n.eg-lsm-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-close {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n padding: 4px 6px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n}\n.eg-lsm-close:hover {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-body {\n padding: 16px 18px;\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n}\n.eg-lsm-empty {\n text-align: center;\n padding: 32px 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n}\n.eg-lsm-meta {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-bottom: 10px;\n}\n.eg-lsm-table-wrap {\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n overflow: auto;\n max-height: 45vh;\n}\n.eg-lsm-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-table th,\n.eg-lsm-table td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n text-align: left;\n white-space: nowrap;\n}\n.eg-lsm-table th {\n position: sticky;\n top: 0;\n background: var(--eg-color-header-bg, var(--eg-color-header-bg-default));\n font-weight: 600;\n z-index: 1;\n}\n.eg-lsm-table tbody tr:last-child td {\n border-bottom: none;\n}\n.eg-lsm-more {\n padding: 8px 10px;\n font-size: 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n text-align: center;\n}\n.eg-lsm-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 14px 18px;\n border-top: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-confirm-text {\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-right: auto;\n}\n.eg-lsm-btn {\n padding: 6px 14px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n border: 1px solid var(--eg-color-border, var(--eg-color-border-default));\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n cursor: pointer;\n}\n.eg-lsm-btn:hover:not(:disabled) {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.eg-lsm-btn-accent {\n background: var(--eg-color-accent, var(--eg-color-accent-default));\n border-color: var(--eg-color-accent, var(--eg-color-accent-default));\n color: #fff;\n}\n.eg-lsm-btn-accent:hover:not(:disabled) {\n background: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n border-color: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n}\n.eg-lsm-btn-danger {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border-color: var(--eg-color-error, var(--eg-color-error-default));\n color: var(--eg-color-error, var(--eg-color-error-default));\n}\n.eg-lsm-btn-danger:hover:not(:disabled) {\n background: var(--eg-color-error-soft, var(--eg-color-error-soft-default));\n}\n</style>\n"]}, media: undefined });
6913
+ inject("data-v-417e3990_0", { source: "\n.eg-lsm-overlay {\n position: fixed;\n inset: 0;\n background: var(--eg-color-overlay-bg, var(--eg-color-overlay-bg-default));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n.eg-lsm-dialog {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n box-shadow: var(--eg-shadow-dialog, var(--eg-shadow-dialog-default));\n width: min(1200px, 94vw);\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n font-family: inherit;\n}\n.eg-lsm-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-close {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n padding: 4px 6px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n}\n.eg-lsm-close:hover {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-body {\n padding: 16px 18px;\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n}\n.eg-lsm-empty {\n text-align: center;\n padding: 32px 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n}\n.eg-lsm-meta {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-bottom: 10px;\n}\n.eg-lsm-table-wrap {\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n overflow: auto;\n max-height: 45vh;\n}\n.eg-lsm-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-table th,\n.eg-lsm-table td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n text-align: left;\n white-space: nowrap;\n}\n.eg-lsm-table th {\n position: sticky;\n top: 0;\n background: var(--eg-color-header-bg, var(--eg-color-header-bg-default));\n font-weight: 600;\n z-index: 1;\n}\n.eg-lsm-table tbody tr:last-child td {\n border-bottom: none;\n}\n.eg-lsm-more {\n padding: 8px 10px;\n font-size: 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n text-align: center;\n}\n.eg-lsm-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 14px 18px;\n border-top: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-confirm-text {\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-right: auto;\n}\n.eg-lsm-btn {\n padding: 6px 14px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n border: 1px solid var(--eg-color-border, var(--eg-color-border-default));\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n cursor: pointer;\n}\n.eg-lsm-btn:hover:not(:disabled) {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.eg-lsm-btn-accent {\n background: var(--eg-color-accent, var(--eg-color-accent-default));\n border-color: var(--eg-color-accent, var(--eg-color-accent-default));\n color: #fff;\n}\n.eg-lsm-btn-accent:hover:not(:disabled) {\n background: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n border-color: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n}\n.eg-lsm-btn-danger {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border-color: var(--eg-color-error, var(--eg-color-error-default));\n color: var(--eg-color-error, var(--eg-color-error-default));\n}\n.eg-lsm-btn-danger:hover:not(:disabled) {\n background: var(--eg-color-error-soft, var(--eg-color-error-soft-default));\n}\n", map: {"version":3,"sources":["/Users/macmini/Projects/Realsoft/vue2-excel-grid/src/components/EgLocalSyncModal.vue"],"names":[],"mappings":";AAyHA;EACA,eAAA;EACA,QAAA;EACA,0EAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,cAAA;AACA;AACA;EACA,oEAAA;EACA,kFAAA;EACA,yDAAA;EACA,oEAAA;EACA,wBAAA;EACA,gBAAA;EACA,aAAA;EACA,sBAAA;EACA,oBAAA;AACA;AACA;EACA,aAAA;EACA,mBAAA;EACA,8BAAA;EACA,kBAAA;EACA,yFAAA;EACA,cAAA;AACA;AACA;EACA,eAAA;EACA,gBAAA;EACA,yDAAA;AACA;AACA;EACA,gBAAA;EACA,YAAA;EACA,eAAA;EACA,eAAA;EACA,cAAA;EACA,6EAAA;EACA,gBAAA;EACA,yDAAA;AACA;AACA;EACA,oFAAA;AACA;AACA;EACA,kBAAA;EACA,gBAAA;EACA,OAAA;EACA,aAAA;AACA;AACA;EACA,kBAAA;EACA,kBAAA;EACA,qEAAA;EACA,2DAAA;AACA;AACA;EACA,aAAA;EACA,8BAAA;EACA,eAAA;EACA,6EAAA;EACA,mBAAA;AACA;AACA;EACA,kFAAA;EACA,yDAAA;EACA,cAAA;EACA,gBAAA;AACA;AACA;EACA,WAAA;EACA,yBAAA;EACA,2DAAA;EACA,yDAAA;AACA;AACA;;EAEA,iBAAA;EACA,yFAAA;EACA,gBAAA;EACA,mBAAA;AACA;AACA;EACA,gBAAA;EACA,MAAA;EACA,wEAAA;EACA,gBAAA;EACA,UAAA;AACA;AACA;EACA,mBAAA;AACA;AACA;EACA,iBAAA;EACA,eAAA;EACA,qEAAA;EACA,kBAAA;AACA;AACA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,SAAA;EACA,kBAAA;EACA,sFAAA;EACA,cAAA;AACA;AACA;EACA,eAAA;EACA,6EAAA;EACA,kBAAA;AACA;AACA;EACA,iBAAA;EACA,yDAAA;EACA,wEAAA;EACA,oEAAA;EACA,yDAAA;EACA,2DAAA;EACA,eAAA;AACA;AACA;EACA,oFAAA;AACA;AACA;EACA,YAAA;EACA,eAAA;AACA;AACA;EACA,kEAAA;EACA,oEAAA;EACA,WAAA;AACA;AACA;EACA,4EAAA;EACA,8EAAA;AACA;AACA;EACA,oEAAA;EACA,kEAAA;EACA,2DAAA;AACA;AACA;EACA,0EAAA;AACA","file":"EgLocalSyncModal.vue","sourcesContent":["<template>\n <div v-if=\"visible\" class=\"eg-lsm-overlay\" @click.self=\"$emit('close')\">\n <div class=\"eg-lsm-dialog\">\n <div class=\"eg-lsm-header\">\n <span class=\"eg-lsm-title\">{{ t.localSyncTitle }}</span>\n <button type=\"button\" class=\"eg-lsm-close\" @click=\"$emit('close')\" :title=\"t.localSyncClose\">✕</button>\n </div>\n\n <div class=\"eg-lsm-body\">\n <div v-if=\"!snapshot\" class=\"eg-lsm-empty\">{{ t.localSyncEmpty }}</div>\n <template v-else>\n <div class=\"eg-lsm-meta\">\n <span>{{ t.localSyncSavedAt }}: {{ savedAtText }}</span>\n <span>{{ snapshot.data.length }} {{ t.localSyncRows }}</span>\n </div>\n <div class=\"eg-lsm-table-wrap\">\n <table class=\"eg-lsm-table\">\n <thead>\n <tr>\n <th v-for=\"col in columns\" :key=\"col.key\">{{ col.title || col.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, ri) in previewRows\" :key=\"ri\">\n <td v-for=\"col in columns\" :key=\"col.key\">{{ resolveCellDisplay(row, col) }}</td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"hiddenRowCount > 0\" class=\"eg-lsm-more\">{{ moreRowsText }}</div>\n </div>\n </template>\n </div>\n\n <div class=\"eg-lsm-footer\">\n <template v-if=\"confirmingClear\">\n <span class=\"eg-lsm-confirm-text\">{{ t.localSyncConfirmClear }}</span>\n <button type=\"button\" class=\"eg-lsm-btn\" @click=\"confirmingClear = false\">{{ t.localSyncConfirmNo }}</button>\n <button type=\"button\" class=\"eg-lsm-btn eg-lsm-btn-danger\" @click=\"onConfirmClear\">{{ t.localSyncConfirmYes }}</button>\n </template>\n <template v-else>\n <button\n type=\"button\"\n class=\"eg-lsm-btn eg-lsm-btn-danger\"\n :disabled=\"!snapshot\"\n @click=\"confirmingClear = true\"\n >{{ t.localSyncClear }}</button>\n <button\n type=\"button\"\n class=\"eg-lsm-btn\"\n :title=\"t.localSyncSaveHint\"\n @click=\"$emit('save')\"\n >{{ t.localSyncSave }}</button>\n <button\n type=\"button\"\n class=\"eg-lsm-btn eg-lsm-btn-accent\"\n :disabled=\"!snapshot\"\n :title=\"t.localSyncRestoreHint\"\n @click=\"$emit('restore')\"\n >{{ t.localSyncRestore }}</button>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script>\n// \"Dumb\" presentation component for ExcelGrid.vue's localSyncKey feature —\n// shows the last IndexedDB-saved v-model snapshot (see src/utils/idbStore.js)\n// and lets the host Restore it back into the grid or delete it. Not exported\n// from src/index.js (same \"internal-only\" convention as EgDatePicker.vue /\n// EgCheckbox.vue) — purpose-built for ExcelGrid.vue, not meant for standalone use.\nconst PREVIEW_ROW_LIMIT = 200\n\nimport { getMessages } from '../utils/i18n.js'\n\nexport default {\n name: 'EgLocalSyncModal',\n props: {\n visible: { type: Boolean, default: false },\n columns: { type: Array, default: () => [] },\n snapshot: { type: Object, default: null }, // { data, updatedAt } | null\n resolveCellDisplay: { type: Function, required: true },\n locale: { type: String, default: 'en' }\n },\n data() {\n return { confirmingClear: false }\n },\n computed: {\n t() { return getMessages(this.locale) },\n savedAtText() {\n if (!this.snapshot) return ''\n return new Date(this.snapshot.updatedAt).toLocaleString()\n },\n previewRows() {\n if (!this.snapshot) return []\n return this.snapshot.data.slice(0, PREVIEW_ROW_LIMIT)\n },\n hiddenRowCount() {\n if (!this.snapshot) return 0\n return Math.max(0, this.snapshot.data.length - PREVIEW_ROW_LIMIT)\n },\n moreRowsText() {\n return (this.t.localSyncMoreRows || '').replace('{n}', this.hiddenRowCount)\n }\n },\n watch: {\n // A freshly opened modal (or a snapshot that just got deleted/restored)\n // should never inherit a stale \"are you sure?\" state from last time.\n visible(val) { if (!val) this.confirmingClear = false },\n snapshot() { this.confirmingClear = false }\n },\n methods: {\n onConfirmClear() {\n this.confirmingClear = false\n this.$emit('clear')\n }\n }\n}\n</script>\n\n<style>\n.eg-lsm-overlay {\n position: fixed;\n inset: 0;\n background: var(--eg-color-overlay-bg, var(--eg-color-overlay-bg-default));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n.eg-lsm-dialog {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n box-shadow: var(--eg-shadow-dialog, var(--eg-shadow-dialog-default));\n width: min(1200px, 94vw);\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n font-family: inherit;\n}\n.eg-lsm-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-close {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n padding: 4px 6px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n}\n.eg-lsm-close:hover {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-body {\n padding: 16px 18px;\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n}\n.eg-lsm-empty {\n text-align: center;\n padding: 32px 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n}\n.eg-lsm-meta {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-bottom: 10px;\n}\n.eg-lsm-table-wrap {\n border: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n border-radius: var(--eg-radius, var(--eg-radius-default));\n overflow: auto;\n max-height: 45vh;\n}\n.eg-lsm-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n}\n.eg-lsm-table th,\n.eg-lsm-table td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n text-align: left;\n white-space: nowrap;\n}\n.eg-lsm-table th {\n position: sticky;\n top: 0;\n background: var(--eg-color-header-bg, var(--eg-color-header-bg-default));\n font-weight: 600;\n z-index: 1;\n}\n.eg-lsm-table tbody tr:last-child td {\n border-bottom: none;\n}\n.eg-lsm-more {\n padding: 8px 10px;\n font-size: 12px;\n color: var(--eg-color-text-muted, var(--eg-color-text-muted-default));\n text-align: center;\n}\n.eg-lsm-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 14px 18px;\n border-top: 1px solid var(--eg-color-border-cell, var(--eg-color-border-cell-default));\n flex-shrink: 0;\n}\n.eg-lsm-confirm-text {\n font-size: 12px;\n color: var(--eg-color-text-secondary, var(--eg-color-text-secondary-default));\n margin-right: auto;\n}\n.eg-lsm-btn {\n padding: 6px 14px;\n border-radius: var(--eg-radius, var(--eg-radius-default));\n border: 1px solid var(--eg-color-border, var(--eg-color-border-default));\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n color: var(--eg-color-text, var(--eg-color-text-default));\n font-size: var(--eg-font-size, var(--eg-font-size-default));\n cursor: pointer;\n}\n.eg-lsm-btn:hover:not(:disabled) {\n background: var(--eg-color-option-hover-bg, var(--eg-color-option-hover-bg-default));\n}\n.eg-lsm-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.eg-lsm-btn-accent {\n background: var(--eg-color-accent, var(--eg-color-accent-default));\n border-color: var(--eg-color-accent, var(--eg-color-accent-default));\n color: #fff;\n}\n.eg-lsm-btn-accent:hover:not(:disabled) {\n background: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n border-color: var(--eg-color-accent-dark, var(--eg-color-accent-dark-default));\n}\n.eg-lsm-btn-danger {\n background: var(--eg-color-cell-bg, var(--eg-color-cell-bg-default));\n border-color: var(--eg-color-error, var(--eg-color-error-default));\n color: var(--eg-color-error, var(--eg-color-error-default));\n}\n.eg-lsm-btn-danger:hover:not(:disabled) {\n background: var(--eg-color-error-soft, var(--eg-color-error-soft-default));\n}\n</style>\n"]}, media: undefined });
6914
6914
 
6915
6915
  };
6916
6916
  /* scoped */
@@ -18111,7 +18111,7 @@ __vue_render__._withStripped = true;
18111
18111
  undefined
18112
18112
  );
18113
18113
 
18114
- var version = "1.7.0";
18114
+ var version = "1.7.1";
18115
18115
 
18116
18116
  var index = {
18117
18117
  version: version,