vue2-excel-grid 2.2.0 → 2.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-excel-grid",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "Excel-style grid component for Vue 2.6.14 with virtual scrolling",
5
5
  "license": "MIT",
6
6
  "author": "Fozilbek Raimberdiyev",
@@ -1292,6 +1292,19 @@ const ExcelGridComponent = {
1292
1292
  /** Extra custom toolbar buttons: [{ key, icon, title, onClick(event, gridApi) }] */
1293
1293
  toolbarButtons: { type: Array, default: () => [] },
1294
1294
 
1295
+ /**
1296
+ * Print (`printGrid()`/toolbar "Print" tugmasi) chiqishida jadval tepasida,
1297
+ * markazda ko'rinadigan sarlavha. `null` (standart) — sarlavha umuman
1298
+ * render qilinmaydi.
1299
+ * @property {String} title - sarlavha matni (bo'sh/undefined bo'lsa render qilinmaydi)
1300
+ * @property {Object} [style] - Vue :style uslubidagi obyekt (camelCase),
1301
+ * standart markazlashtirilgan/qalin uslub USTIGA qo'shiladi
1302
+ * @property {String} [class] - qo'shimcha CSS klass nomi(lari)
1303
+ * @example
1304
+ * <excel-grid :print-title="{ title: 'Talabalar ro\'yxati', style: { color: '#1a73e8' } }" />
1305
+ */
1306
+ printTitle: { type: Object, default: null },
1307
+
1295
1308
  /**
1296
1309
  * Locks the entire grid: blocks all edits (typing, paste, fill, delete,
1297
1310
  * checkbox, select/treeSelect) and structural changes (resize, column
@@ -3635,46 +3648,57 @@ const ExcelGridComponent = {
3635
3648
  return
3636
3649
  }
3637
3650
  const key = e.key
3638
-
3639
- if ((e.ctrlKey || e.metaKey) && key === 'z' && !e.shiftKey) {
3651
+ // Layout-independent letter for the Ctrl/Cmd shortcuts below (z/y/a/c/x/v/d/r).
3652
+ // e.key reports the character a layout PRODUCES — on a non-Latin layout
3653
+ // (Cyrillic, etc.) the physical C key can report e.key: 'с' (Cyrillic es)
3654
+ // even with Ctrl held and the physical key/position unchanged, silently
3655
+ // breaking `key === 'c'`. e.code is the physical key position and is
3656
+ // immune to layout, so it's used here instead wherever available;
3657
+ // falls back to e.key when e.code is missing (e.g. synthetic events in
3658
+ // tests that don't set it).
3659
+ const shortcutKey = (e.code && e.code.length === 4 && e.code.slice(0, 3) === 'Key')
3660
+ ? e.code.charAt(3).toLowerCase()
3661
+ : key
3662
+
3663
+ if ((e.ctrlKey || e.metaKey) && shortcutKey === 'z' && !e.shiftKey) {
3640
3664
  e.preventDefault()
3641
3665
  this.undo()
3642
3666
  return
3643
3667
  }
3644
- if ((e.ctrlKey || e.metaKey) && (key === 'y' || (key === 'z' && e.shiftKey))) {
3668
+ if ((e.ctrlKey || e.metaKey) && (shortcutKey === 'y' || (shortcutKey === 'z' && e.shiftKey))) {
3645
3669
  e.preventDefault()
3646
3670
  this.redo()
3647
3671
  return
3648
3672
  }
3649
3673
 
3650
- if (key === 'a' && (e.ctrlKey || e.metaKey)) {
3674
+ if (shortcutKey === 'a' && (e.ctrlKey || e.metaKey)) {
3651
3675
  e.preventDefault()
3652
3676
  this.selectAll()
3653
3677
  return
3654
3678
  }
3655
3679
 
3656
- if (key === 'c' && (e.ctrlKey || e.metaKey)) {
3680
+ if (shortcutKey === 'c' && (e.ctrlKey || e.metaKey)) {
3657
3681
  e.preventDefault()
3658
3682
  this.copySelection()
3659
3683
  return
3660
3684
  }
3661
- if (key === 'x' && (e.ctrlKey || e.metaKey)) {
3685
+ if (shortcutKey === 'x' && (e.ctrlKey || e.metaKey)) {
3662
3686
  e.preventDefault()
3663
3687
  this.cutSelection()
3664
3688
  return
3665
3689
  }
3666
- if (key === 'v' && (e.ctrlKey || e.metaKey)) {
3690
+ if (shortcutKey === 'v' && (e.ctrlKey || e.metaKey)) {
3667
3691
  e.preventDefault()
3668
3692
  this.pasteAt(this.activeCell.row, this.activeCell.col)
3669
3693
  return
3670
3694
  }
3671
3695
 
3672
- if (key === 'd' && (e.ctrlKey || e.metaKey)) {
3696
+ if (shortcutKey === 'd' && (e.ctrlKey || e.metaKey)) {
3673
3697
  e.preventDefault()
3674
3698
  this.fillDown()
3675
3699
  return
3676
3700
  }
3677
- if (key === 'r' && (e.ctrlKey || e.metaKey)) {
3701
+ if (shortcutKey === 'r' && (e.ctrlKey || e.metaKey)) {
3678
3702
  e.preventDefault()
3679
3703
  this.fillRight()
3680
3704
  return
@@ -6098,7 +6122,8 @@ const ExcelGridComponent = {
6098
6122
  return String(this.getCellDisplayValue(ci, this.getCellValue(ri, ci), ri))
6099
6123
  },
6100
6124
  showFooter: this.hasFooter,
6101
- getFooterText: ci => this.getColumnTotalDisplay(ci)
6125
+ getFooterText: ci => this.getColumnTotalDisplay(ci),
6126
+ printTitle: this.printTitle
6102
6127
  })
6103
6128
  this._openPrintFrame(html)
6104
6129
  },
@@ -14,6 +14,15 @@ function escapeHtml(value) {
14
14
  .replace(/"/g, '&quot;')
15
15
  }
16
16
 
17
+ // Serializes a Vue :style-shaped object (camelCase keys) into a CSS string —
18
+ // this file builds a raw HTML document, so there's no Vue runtime here to do
19
+ // the :style -> style="" conversion automatically.
20
+ function styleObjToCss(styleObj) {
21
+ return Object.entries(styleObj)
22
+ .map(([k, v]) => `${k.replace(/[A-Z]/g, m => '-' + m.toLowerCase())}:${v}`)
23
+ .join(';')
24
+ }
25
+
17
26
  // Above this many visible columns, a portrait page can't fit them without
18
27
  // crushing every column to near-zero width — switch to landscape instead.
19
28
  const LANDSCAPE_COL_THRESHOLD = 6
@@ -38,6 +47,8 @@ function sizeTierFor(colCount) {
38
47
  * @param {(rowIndex:number, colIndex:number) => string} opts.getCellText
39
48
  * @param {boolean} opts.showFooter
40
49
  * @param {(colIndex:number) => string} opts.getFooterText
50
+ * @param {Object} [opts.printTitle] - { title, style, class } — rendered centered above the
51
+ * table when `title` is non-empty; omitted (or empty title) renders nothing
41
52
  * @returns {string} full HTML document
42
53
  */
43
54
  export function buildPrintTableHtml({
@@ -49,7 +60,8 @@ export function buildPrintTableHtml({
49
60
  colWidths,
50
61
  getCellText,
51
62
  showFooter = false,
52
- getFooterText
63
+ getFooterText,
64
+ printTitle = null
53
65
  }) {
54
66
  const exportCols = leafCols.filter((col, idx) => !hiddenColSet.has(idx))
55
67
  const exportKeySet = new Set(exportCols.map(c => c.key))
@@ -161,6 +173,15 @@ export function buildPrintTableHtml({
161
173
  const totalWidth = adjustedWidths.reduce((sum, w) => sum + w, 0) || 1
162
174
  const colgroupHtml = '<colgroup>' + adjustedWidths.map(w => `<col style="width:${(w / totalWidth * 100).toFixed(3)}%">`).join('') + '</colgroup>'
163
175
 
176
+ // ── Optional host-supplied title, centered above the table. The default
177
+ // .eg-print-title rule (below) sets the centered/bold look; a host style
178
+ // object is serialized as this element's OWN inline style, which wins over
179
+ // the stylesheet rule per normal CSS cascade — so it only overrides what
180
+ // the host actually specifies, the rest of the default look stays. ────────
181
+ const titleHtml = (printTitle && printTitle.title)
182
+ ? `<div class="eg-print-title${printTitle.class ? ' ' + escapeHtml(printTitle.class) : ''}"${printTitle.style ? ` style="${escapeHtml(styleObjToCss(printTitle.style))}"` : ''}>${escapeHtml(printTitle.title)}</div>`
183
+ : ''
184
+
164
185
  return `<!DOCTYPE html>
165
186
  <html>
166
187
  <head>
@@ -188,10 +209,12 @@ th { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
188
209
  td { word-break: normal; overflow-wrap: break-word; }
189
210
  thead th { background: #f0f0f0; font-weight: bold; text-align: center; }
190
211
  tfoot td { font-weight: bold; background: #f7f7f7; }
212
+ .eg-print-title { text-align: center; font-weight: bold; font-size: 20px; margin-bottom: 12px; }
191
213
  @page { size: ${orientation}; margin: 12mm; }
192
214
  </style>
193
215
  </head>
194
216
  <body>
217
+ ${titleHtml}
195
218
  <table>
196
219
  ${colgroupHtml}
197
220
  <thead>${theadRowsHtml}</thead>