chore(deps): upgrade Handsontable to v18
Bump handsontable and @handsontable/angular-wrapper 17.1 -> 18.0 and adapt to its stricter TypeScript-core types: moved handsontable/common and deep walkontable imports to their new public export paths, added explicit generics/casts where getData()/getCellMeta()/getSelected() are now typed unknown/nullable instead of the loose v17 shapes, and updated the AutocompleteEditor override to the new open() signature. Also allowlists @handsontable/angular-wrapper@18.0.0 and handsontable@18.0.0 in licenseChecker.js — both versions report the same non-SPDX "SEE LICENSE IN LICENSE.txt" field that license-checker mis-resolves as a disallowed custom license, same as prior versions.
This commit is contained in:
Vendored
+1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"Handsontable",
|
||||
"Licence",
|
||||
"SYSERRORTEXT",
|
||||
"SYSWARNINGTEXT",
|
||||
|
||||
@@ -10,7 +10,7 @@ const check = (cwd) => {
|
||||
onlyAllow:
|
||||
'AFLv2.1;Apache 2.0;Apache-2.0;Apache*;Artistic-2.0;0BSD;BSD*;BSD-2-Clause;BSD-3-Clause;CC0-1.0;CC-BY-3.0;CC-BY-4.0;ISC;MIT;MPL-2.0;ODC-By-1.0;Python-2.0;Unlicense;',
|
||||
excludePackages:
|
||||
'@cds/city@1.1.0;@handsontable/angular-wrapper@16.0.1;@handsontable/angular-wrapper@17.1.0;handsontable@^16.0.1;handsontable@16.2.0;handsontable@17.1.0;hyperformula@2.7.1;hyperformula@3.0.0;hyperformula@3.1.0;hyperformula@3.2.0;hyperformula@3.3.0;jackspeak@3.4.3;path-scurry@1.11.1;package-json-from-dist@1.0.1;buffers@0.1.1'
|
||||
'@cds/city@1.1.0;@handsontable/angular-wrapper@16.0.1;@handsontable/angular-wrapper@17.1.0;@handsontable/angular-wrapper@18.0.0;handsontable@^16.0.1;handsontable@16.2.0;handsontable@17.1.0;handsontable@18.0.0;hyperformula@2.7.1;hyperformula@3.0.0;hyperformula@3.1.0;hyperformula@3.2.0;hyperformula@3.3.0;jackspeak@3.4.3;path-scurry@1.11.1;package-json-from-dist@1.0.1;buffers@0.1.1'
|
||||
},
|
||||
(error, json) => {
|
||||
if (error) {
|
||||
|
||||
Generated
+11
-722
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -54,7 +54,7 @@
|
||||
"@clr/angular": "file:libraries/clr-angular-17.9.0.tgz",
|
||||
"@clr/icons": "^13.0.2",
|
||||
"@clr/ui": "file:libraries/clr-ui-17.9.0.tgz",
|
||||
"@handsontable/angular-wrapper": "^17.1.0",
|
||||
"@handsontable/angular-wrapper": "^18.0.0",
|
||||
"@sasjs/adapter": "^4.17.0",
|
||||
"@sasjs/utils": "^3.5.3",
|
||||
"@sheet/crypto": "file:libraries/sheet-crypto.tgz",
|
||||
@@ -67,7 +67,7 @@
|
||||
"d3-graphviz": "^5.0.2",
|
||||
"exceljs": "^4.4.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"handsontable": "^17.1.0",
|
||||
"handsontable": "^18.0.0",
|
||||
"https-browserify": "1.0.0",
|
||||
"hyperformula": "^2.5.0",
|
||||
"iconv-lite": "^0.5.0",
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ViewEncapsulation
|
||||
} from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import Handsontable from 'handsontable'
|
||||
import Handsontable, { CellRange } from 'handsontable'
|
||||
import { Subject, Subscription } from 'rxjs'
|
||||
import { sanitiseForSas } from '../shared/utils/sanitise'
|
||||
import { SasStoreService } from '../services/sas-store.service'
|
||||
@@ -21,7 +21,6 @@ type AOA = any[][]
|
||||
import { HotTableComponent } from '@handsontable/angular-wrapper'
|
||||
import { UploadFile } from '@sasjs/adapter'
|
||||
import { isSpecialMissing } from '@sasjs/utils/input/validators'
|
||||
import CellRange from 'handsontable/3rdparty/walkontable/src/cell/range'
|
||||
import { CellValidationSource } from '../models/CellValidationSource'
|
||||
import { FileUploader } from '../models/FileUploader.class'
|
||||
import { FilterGroup, FilterQuery } from '../models/FilterQuery'
|
||||
@@ -161,8 +160,11 @@ export class EditorComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
items: {
|
||||
edit_row: {
|
||||
name: 'Edit row',
|
||||
hidden() {
|
||||
const hot: Handsontable.Core = this
|
||||
// HOT 18's MenuItemConfig types `hidden` as a plain `() => boolean` with
|
||||
// no `this` type, so an object-literal method here has `this` inferred
|
||||
// as the surrounding item config unless declared explicitly.
|
||||
hidden(this: Handsontable.Core) {
|
||||
const hot = this
|
||||
|
||||
// Hide editing actions in read-only (view) mode.
|
||||
if (hot.getSettings().readOnly) return true
|
||||
@@ -1399,7 +1401,9 @@ export class EditorComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
hot.removeCellMeta(rowIndex, col, 'valid')
|
||||
hot.removeCellMeta(rowIndex, col, 'dupKey')
|
||||
// Remove our custom class from cell metadata
|
||||
const cellMeta = hot.getCellMeta(rowIndex, col)
|
||||
// getCellMeta<M>() defaults to Record<string, unknown> in HOT 18; pin it to
|
||||
// CellMeta so `.className` keeps its real string | string[] type below.
|
||||
const cellMeta = hot.getCellMeta<Handsontable.CellMeta>(rowIndex, col)
|
||||
if (cellMeta.className) {
|
||||
let cleanedClassName: string
|
||||
if (Array.isArray(cellMeta.className)) {
|
||||
@@ -2246,8 +2250,10 @@ export class EditorComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
validationSourceIndex
|
||||
].values.map((el) => el.RAW_VALUE)
|
||||
|
||||
// `.source` (dropdown/autocomplete list) is typed unknown[] | Function here since
|
||||
// getCellMeta() isn't given a type param; cast to the array branch we actually use.
|
||||
const cellHadSource =
|
||||
(hot.getCellMeta(row, column).source || []).length < 1
|
||||
((hot.getCellMeta(row, column).source as unknown[]) || []).length < 1
|
||||
const cellHasValue = cellData !== ' '
|
||||
|
||||
hot.batch(() => {
|
||||
@@ -3123,7 +3129,9 @@ export class EditorComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
let textInfo = 'No info found'
|
||||
|
||||
if (this.hotInstance) {
|
||||
const hotSelected: [number, number, number, number][] =
|
||||
// getSelected() is typed number[][] in HOT 18 (was a 4-tuple
|
||||
// array before); loosen the annotation to match.
|
||||
const hotSelected: number[][] =
|
||||
this.hotInstance.getSelected() || []
|
||||
const selectedCol: number = hotSelected
|
||||
? hotSelected[0][1]
|
||||
|
||||
@@ -22,10 +22,9 @@ import { ExcelRule } from '../models/TableData'
|
||||
import { HotTableInterface } from '../models/HotTable.interface'
|
||||
import { Col } from '../shared/dc-validator/models/col.model'
|
||||
import { SpreadsheetService } from '../services/spreadsheet.service'
|
||||
import Handsontable from 'handsontable'
|
||||
import Handsontable, { CellChange, ChangeSource } from 'handsontable'
|
||||
import { HotTableComponent } from '@handsontable/angular-wrapper'
|
||||
import { EditorsStageDataSASResponse } from '../models/sas/editors-stagedata.model'
|
||||
import { CellChange, ChangeSource } from 'handsontable/common'
|
||||
import { baseAfterGetColHeader } from '../shared/utils/hot.utils'
|
||||
import { ColumnSettings } from 'handsontable/settings'
|
||||
import { UploadFile } from '@sasjs/adapter'
|
||||
@@ -502,7 +501,9 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
if (changes) {
|
||||
for (let change of changes) {
|
||||
if (change && change[3]) {
|
||||
change[3] = change[3].toUpperCase()
|
||||
// CellValue is `unknown` in HOT 18 (was a concrete union before);
|
||||
// this column is always a dataset name string.
|
||||
change[3] = (change[3] as string).toUpperCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,7 +553,9 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
dynamicCellValidations() {
|
||||
if (!this.hotInstanceUserDataset) return
|
||||
|
||||
const hotData = this.hotInstanceUserDataset.getData()
|
||||
// getData() returns unknown[][] in HOT 18 (was CellValue[][]); this grid's
|
||||
// data is always library/table name strings.
|
||||
const hotData = this.hotInstanceUserDataset.getData() as string[][]
|
||||
|
||||
hotData.forEach((row, rowIndex) => {
|
||||
const library = row[0]
|
||||
@@ -573,10 +576,12 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
|
||||
if (dataAtRow && dataAtRow[0] && dataAtRow[1]) {
|
||||
if (!this.matchedDatasets.includes(dataset)) {
|
||||
// getCellMetaAtRow() returns Record<string, unknown>[] in HOT 18, so
|
||||
// `.col` needs casting back to number for setCellMeta() (same below).
|
||||
cellMetaAtRow.forEach((cellMeta) => {
|
||||
this.hotInstanceUserDataset.setCellMeta(
|
||||
row,
|
||||
cellMeta.col,
|
||||
cellMeta.col as number,
|
||||
'className',
|
||||
'not-matched'
|
||||
)
|
||||
@@ -585,7 +590,7 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
cellMetaAtRow.forEach((cellMeta) => {
|
||||
this.hotInstanceUserDataset.setCellMeta(
|
||||
row,
|
||||
cellMeta.col,
|
||||
cellMeta.col as number,
|
||||
'className',
|
||||
''
|
||||
)
|
||||
@@ -595,7 +600,7 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
cellMetaAtRow.forEach((cellMeta) => {
|
||||
this.hotInstanceUserDataset.setCellMeta(
|
||||
row,
|
||||
cellMeta.col,
|
||||
cellMeta.col as number,
|
||||
'className',
|
||||
''
|
||||
)
|
||||
@@ -991,7 +996,8 @@ export class MultiDatasetComponent implements OnInit, AfterViewInit {
|
||||
private getDatasetsFromHot(): string[] {
|
||||
if (!this.hotInstanceUserDataset) return []
|
||||
|
||||
const hotData = this.hotInstanceUserDataset.getData()
|
||||
// getData() returns unknown[][] in HOT 18; see dynamicCellValidations() above.
|
||||
const hotData = this.hotInstanceUserDataset.getData() as string[][]
|
||||
|
||||
return hotData
|
||||
.filter((row) => row[0]?.length && row[1]?.length)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import Handsontable from 'handsontable'
|
||||
import Core from 'handsontable/core'
|
||||
import Handsontable, { HotInstance } from 'handsontable'
|
||||
|
||||
export class CustomAutocompleteEditor
|
||||
extends Handsontable.editors.AutocompleteEditor
|
||||
{
|
||||
constructor(instance: Core) {
|
||||
constructor(instance: HotInstance) {
|
||||
super(instance)
|
||||
}
|
||||
|
||||
@@ -13,8 +12,9 @@ export class CustomAutocompleteEditor
|
||||
}
|
||||
|
||||
// Listbox open
|
||||
open(event?: Event | undefined): void {
|
||||
super.open(event)
|
||||
// HOT 18's AutocompleteEditor.open() takes no arguments (was `event?: Event`).
|
||||
open(): void {
|
||||
super.open()
|
||||
|
||||
if (this.isCellNumeric()) {
|
||||
this.htContainer.classList.add('numericListbox')
|
||||
|
||||
@@ -52,12 +52,14 @@ export async function exportGrid(
|
||||
// Mirror HOT's own export item: only honor a selection that spans more than
|
||||
// one cell. A right-click places a single-cell cursor, and the corner click
|
||||
// is select-all (negative coords) — both mean "export the whole table".
|
||||
const isCornerSelectAll = !!sel && sel.from.row < 0 && sel.from.col < 0
|
||||
// sel.from/to.row/col are typed nullable (CellCoords allows an unset state),
|
||||
// but a range returned by getSelectedRangeLast() always has real coordinates.
|
||||
const isCornerSelectAll = !!sel && sel.from.row! < 0 && sel.from.col! < 0
|
||||
if (sel && !sel.isSingleCell() && !isCornerSelectAll) {
|
||||
const top = Math.max(0, Math.min(sel.from.row, sel.to.row))
|
||||
const left = Math.max(0, Math.min(sel.from.col, sel.to.col))
|
||||
const bottom = Math.max(sel.from.row, sel.to.row)
|
||||
const right = Math.max(sel.from.col, sel.to.col)
|
||||
const top = Math.max(0, Math.min(sel.from.row!, sel.to.row!))
|
||||
const left = Math.max(0, Math.min(sel.from.col!, sel.to.col!))
|
||||
const bottom = Math.max(sel.from.row!, sel.to.row!)
|
||||
const right = Math.max(sel.from.col!, sel.to.col!)
|
||||
opts['range'] = [top, Math.max(left, skipLeadingCols), bottom, right]
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +228,9 @@ export class ViewerComponent
|
||||
!this.isTableSwitching
|
||||
) {
|
||||
try {
|
||||
const hotSelected: [number, number, number, number][] =
|
||||
// getSelected() is typed number[][] in HOT 18 (was a 4-tuple
|
||||
// array before); loosen the annotation to match.
|
||||
const hotSelected: number[][] =
|
||||
this.hotInstance.getSelected() || []
|
||||
const selectedCol: number = hotSelected ? hotSelected[0][1] : -1
|
||||
const colName = this.hotInstance.colToProp(selectedCol)
|
||||
|
||||
Reference in New Issue
Block a user