From 98f6969156438b09a5c7f88432d6b14c4412b021 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 24 May 2021 13:45:49 -0700 Subject: [PATCH 01/20] Bump lumino deps Signed-off-by: Itay Dafna --- package-lock.json | 189 +++++++++++++++++++++++++++++++++------------- package.json | 18 ++--- 2 files changed, 144 insertions(+), 63 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7cd69d56..5b86e3e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3198,9 +3198,9 @@ } }, "@lumino/algorithm": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.5.0.tgz", - "integrity": "sha512-sieI5sD2A5rFrxLLYuWgiJOjttDWX7held6IJ5ECUJl4PAzVPUYSL7ZaMTzLXqILCzjcOF61C4fDmSY7u2vqyA==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.6.0.tgz", + "integrity": "sha512-NMOcm5Yr9nXz5gokS/K4jHBbUMQYBkvDXl1n51XWdcz0LY+oGuIKPhjazhUgmbNRehzdZBj5hMMd1+htYWeVKQ==" }, "@lumino/application": { "version": "1.18.0", @@ -3214,31 +3214,50 @@ } }, "@lumino/collections": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.5.0.tgz", - "integrity": "sha512-m3lNCQuv0WgHURc1C/nHjF/5Yxok8TJy8L8p7F+iRKXjkfWR66Uj4CZVdT2sYoj4MKBpeBvqrwL4j4i3DqS27g==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.6.0.tgz", + "integrity": "sha512-ZETm0/xF0oUHV03sOXNOfFI1EEpS317HvN5n+fZBJvCNZIrJkWmKD8QuxcfwHb7AChKUhXlVHhDbWlb1LKnd7g==", "requires": { - "@lumino/algorithm": "^1.5.0" + "@lumino/algorithm": "^1.6.0" } }, "@lumino/commands": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-1.14.0.tgz", - "integrity": "sha512-pjQHlYrzNCvqtoOMr5uwSGlenPFR+k9uR7isuA/i8jzlGP8z/ehzQBQSxZCpghmupIkS4NC/ZKKeTfTwfQ1FhA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-1.15.0.tgz", + "integrity": "sha512-JOE68KfbR9xw5YTfcwo+9E0PSWidifEMAcOC/aXd7iSzfsCRknMTcMQIUGL277IU7J7CJvoe10DUE5QKwTmX+g==", "requires": { - "@lumino/algorithm": "^1.5.0", - "@lumino/coreutils": "^1.7.0", - "@lumino/disposable": "^1.6.0", - "@lumino/domutils": "^1.4.0", - "@lumino/keyboard": "^1.4.0", - "@lumino/signaling": "^1.6.0", - "@lumino/virtualdom": "^1.10.0" + "@lumino/algorithm": "^1.6.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/domutils": "^1.5.0", + "@lumino/keyboard": "^1.5.0", + "@lumino/signaling": "^1.7.0", + "@lumino/virtualdom": "^1.11.0" + }, + "dependencies": { + "@lumino/disposable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", + "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/signaling": "^1.7.0" + } + }, + "@lumino/signaling": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", + "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + } } }, "@lumino/coreutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-1.7.0.tgz", - "integrity": "sha512-KDZr3HI8Hrp9v+ps4rgBMN/ZtaHjKB3D96VOaLgbeWHjuJRRvP74V8nRpe9lHg+kGbjsvp1wuF/m3UHhbmqYKw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-1.8.0.tgz", + "integrity": "sha512-OvCsaASUqOE7R6Dxngyk4/b5QMOjyRUNxuZuuL+fx+JvGKZFZ/B2c9LYtAJ9mDmQ1BQiGNV/qSpL4o7x8PCfjw==" }, "@lumino/datagrid": { "version": "0.25.1", @@ -3367,12 +3386,40 @@ } }, "@lumino/default-theme": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@lumino/default-theme/-/default-theme-0.12.0.tgz", - "integrity": "sha512-5GHmhvjqIMOqMpa5I4/x3+fAS/r7cA7X3/by5uKTQ8EwOC+ZyANCUpYnAtnx13XI2f9TGI8HoL2wGqzRNa07Bw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@lumino/default-theme/-/default-theme-0.14.0.tgz", + "integrity": "sha512-gsNNOOzTkdlSRtfPAYQBWgUBMhF60w0NKC1SKBFKZ/3DavWa3acqGxoT0oFAO1WIFI50yJ8jKQrO36nffuc7Fw==", "requires": { - "@lumino/dragdrop": "^1.9.0", - "@lumino/widgets": "^1.21.0" + "@lumino/dragdrop": "^1.10.0", + "@lumino/widgets": "^1.23.0" + }, + "dependencies": { + "@lumino/disposable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", + "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/signaling": "^1.7.0" + } + }, + "@lumino/dragdrop": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", + "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", + "requires": { + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0" + } + }, + "@lumino/signaling": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", + "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + } } }, "@lumino/disposable": { @@ -3385,31 +3432,32 @@ } }, "@lumino/domutils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-1.4.0.tgz", - "integrity": "sha512-CjdvsGjoBNNunTx2rQtZBiUTkiaiO7jvJsYMmrX+8I5DOt2f43/778EcdSbyzX5aRzrcRXc/nJ3QTHpoye0XtA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-1.5.0.tgz", + "integrity": "sha512-dZ0Aa+/qhvfPc1aa5kX4LLGE3B6BW1XmJa0R1XVCEpAFY3cZiujuQWmhYHJtZPrOiqn0UtioT2OpqnWdtCWc0A==" }, "@lumino/dragdrop": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.9.0.tgz", "integrity": "sha512-GZozTtQCK6naGo2wYGqJP8YpZSTDhonOeoxMsyVx/batv9cXUlW0oCmBfoMJ6N3vHYrsnPbslR/sE7+lk2/xGw==", + "dev": true, "requires": { "@lumino/coreutils": "^1.7.0", "@lumino/disposable": "^1.6.0" } }, "@lumino/keyboard": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-1.4.0.tgz", - "integrity": "sha512-jphYUNzYHOMCaKlgdWbqe93H7I+lJKAWiEumTlCQnrx/X+aUGTryyJQ09PdZKZBencVyZwylAey0hc8bUQ7Ktw==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-1.5.0.tgz", + "integrity": "sha512-/uF9xqHYVbIkser2Q6UIv7VWrzThr1fxAmSOShjSoKGocL0XHeaBaCOMezSaVxnJ1wm1ciNdhMsjscVM8Inp7g==" }, "@lumino/messaging": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.6.0.tgz", - "integrity": "sha512-yr52Vye8PgcNnnpnH5TiJyAT9rGZ9DRLtsAEZKDfNN3k21AsfeUwzKfCBrTefqF1uhbt4id8Rx6YgScdWSYwrg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.7.0.tgz", + "integrity": "sha512-QYWf9QGIGD0Oes104zw7mVln4S8yRije2mZhNNRBjkYcDuQlPW+eRSuC5LwAMsFnGymBlUPwPbKOUEO2RbhAtg==", "requires": { - "@lumino/algorithm": "^1.5.0", - "@lumino/collections": "^1.5.0" + "@lumino/algorithm": "^1.6.0", + "@lumino/collections": "^1.6.0" } }, "@lumino/polling": { @@ -3436,29 +3484,62 @@ } }, "@lumino/virtualdom": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-1.10.0.tgz", - "integrity": "sha512-VIqzjMhr/xUVvn6z3jcpGa/8XV1qRaWL2NBOcsEbxR9WNy8bmsNNEP27VlvLAROdgL4k/QTFEiewKM6xTAczFw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-1.11.0.tgz", + "integrity": "sha512-G0sIx4pLYbgJ4w+SIgsCYQgKP/GBrWgjh8wcumD6XpaYZNivJv4c01xITYYlh7FU61jZmMWMrxtZztArNRDSqg==", "requires": { - "@lumino/algorithm": "^1.5.0" + "@lumino/algorithm": "^1.6.0" } }, "@lumino/widgets": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-1.21.0.tgz", - "integrity": "sha512-jtZsrBh1+ZbpmpkHagNksLWpkOSRQryHOKvQoa1eSVVC4TYTtZ+7f8CZlZNz9aowzTu/nFsUoH69atZkSDt79w==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-1.23.0.tgz", + "integrity": "sha512-0Akt9ESgc06SJ3EJG3VK1Liw+AAjRWkKMfm8VUTwT/1QJYYGZ8kfHNO97mkBLv+0EkLEkZIeaQb8fIoU6vh7bw==", "requires": { - "@lumino/algorithm": "^1.5.0", - "@lumino/commands": "^1.14.0", - "@lumino/coreutils": "^1.7.0", - "@lumino/disposable": "^1.6.0", - "@lumino/domutils": "^1.4.0", - "@lumino/dragdrop": "^1.9.0", - "@lumino/keyboard": "^1.4.0", - "@lumino/messaging": "^1.6.0", - "@lumino/properties": "^1.4.0", - "@lumino/signaling": "^1.6.0", - "@lumino/virtualdom": "^1.10.0" + "@lumino/algorithm": "^1.6.0", + "@lumino/commands": "^1.15.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/domutils": "^1.5.0", + "@lumino/dragdrop": "^1.10.0", + "@lumino/keyboard": "^1.5.0", + "@lumino/messaging": "^1.7.0", + "@lumino/properties": "^1.5.0", + "@lumino/signaling": "^1.7.0", + "@lumino/virtualdom": "^1.11.0" + }, + "dependencies": { + "@lumino/disposable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", + "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/signaling": "^1.7.0" + } + }, + "@lumino/dragdrop": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", + "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", + "requires": { + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0" + } + }, + "@lumino/properties": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.5.0.tgz", + "integrity": "sha512-YqpJE6/1Wkjrie0E+ypu+yzd55B5RlvKYMnQs3Ox+SrJsnNBhA6Oj44EhVf8SUTuHgn1t/mm+LvbswKN5RM4+g==" + }, + "@lumino/signaling": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", + "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + } } }, "@nicolo-ribaudo/chokidar-2": { diff --git a/package.json b/package.json index c4d0348e..a42b2869 100644 --- a/package.json +++ b/package.json @@ -56,15 +56,15 @@ "dependencies": { "@jupyter-widgets/base": "^2 || ^3 || ^4", "@jupyterlab/apputils": "^3.0.2", - "@lumino/algorithm": "^1.5.0", - "@lumino/commands": "^1.14.0", - "@lumino/coreutils": "^1.7.0", - "@lumino/datagrid": "^0.25.1", - "@lumino/default-theme": "^0.12.0", - "@lumino/domutils": "^1.4.0", - "@lumino/messaging": "^1.6.0", - "@lumino/virtualdom": "^1.10.0", - "@lumino/widgets": "^1.21.0", + "@lumino/algorithm": "^1.6.0", + "@lumino/commands": "^1.15.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/datagrid": "^0.25.0", + "@lumino/default-theme": "^0.14.0", + "@lumino/domutils": "^1.5.0", + "@lumino/messaging": "^1.7.0", + "@lumino/virtualdom": "^1.11.0", + "@lumino/widgets": "^1.23.0", "bqplot": "^0.4.6", "d3-array": "^2.2.0", "d3-color": "^1.3.0", From f69730bf0ab448434f6eb5c1568e64f7815fd1e1 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 24 May 2021 13:49:07 -0700 Subject: [PATCH 02/20] Update imports to use upstream DataGrid Signed-off-by: Itay Dafna --- js/core/filterMenu.ts | 2 +- js/core/gridContextMenu.ts | 2 +- js/feathergrid.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/core/filterMenu.ts b/js/core/filterMenu.ts index 03480add..60cfb591 100644 --- a/js/core/filterMenu.ts +++ b/js/core/filterMenu.ts @@ -2,7 +2,7 @@ import { Transform } from './transform'; import { ViewBasedJSONModel } from './viewbasedjsonmodel'; -import { DataGrid } from './datagrid'; +import { DataGrid } from '@lumino/datagrid'; import { DataModel } from '@lumino/datagrid'; diff --git a/js/core/gridContextMenu.ts b/js/core/gridContextMenu.ts index d8e26f72..6f6acbc8 100644 --- a/js/core/gridContextMenu.ts +++ b/js/core/gridContextMenu.ts @@ -1,4 +1,4 @@ -import { DataGrid } from './datagrid'; +import { DataGrid } from '@lumino/datagrid'; import { DataModel } from '@lumino/datagrid'; diff --git a/js/feathergrid.ts b/js/feathergrid.ts index d8ecc9b4..40d7d266 100644 --- a/js/feathergrid.ts +++ b/js/feathergrid.ts @@ -11,7 +11,7 @@ import { import { CommandRegistry } from '@lumino/commands'; import { toArray } from '@lumino/algorithm'; import { Signal, ISignal } from '@lumino/signaling'; -import { DataGrid } from './core/datagrid'; +import { DataGrid } from '@lumino/datagrid'; import { HeaderRenderer } from './core/headerRenderer'; import { InteractiveFilterDialog } from './core/filterMenu'; import { FeatherGridContextMenu } from './core/gridContextMenu'; From a94c6f90afb9bc7969e8065bc1efd38ea7a58571 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 24 May 2021 14:08:28 -0700 Subject: [PATCH 03/20] Bump TypeScript version and update package-lock Signed-off-by: Itay Dafna --- package-lock.json | 2023 +++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 859 insertions(+), 1166 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b86e3e7..3ba32342 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@babel/cli": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.13.16.tgz", - "integrity": "sha512-cL9tllhqvsQ6r1+d9Invf7nNXg/3BlfL1vvvL/AdH9fZ2l5j0CeBcoq6UjsqHpvyN1v5nXSZgqJZoGeK+ZOAbw==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.14.3.tgz", + "integrity": "sha512-zU4JLvwk32ay1lhhyGfqiRUSPoltVDjhYkA3aQq8+Yby9z30s/EsFw1EPOHxWG9YZo2pAGfgdRNeHZQAYU5m9A==", "dev": true, "requires": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents", @@ -45,26 +45,26 @@ } }, "@babel/compat-data": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.15.tgz", - "integrity": "sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz", + "integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==", "dev": true }, "@babel/core": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.16.tgz", - "integrity": "sha512-sXHpixBiWWFti0AV2Zq7avpTasr6sIAu7Y396c608541qAU2ui4a193m0KSQmfPSKFZLnQ3cvlKDOm3XkuXm3Q==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.3.tgz", + "integrity": "sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.13.16", + "@babel/generator": "^7.14.3", "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-module-transforms": "^7.13.14", - "@babel/helpers": "^7.13.16", - "@babel/parser": "^7.13.16", + "@babel/helper-module-transforms": "^7.14.2", + "@babel/helpers": "^7.14.0", + "@babel/parser": "^7.14.3", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.15", - "@babel/types": "^7.13.16", + "@babel/traverse": "^7.14.2", + "@babel/types": "^7.14.2", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -103,12 +103,12 @@ } }, "@babel/generator": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.16.tgz", - "integrity": "sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", + "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", "dev": true, "requires": { - "@babel/types": "^7.13.16", + "@babel/types": "^7.14.2", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -161,22 +161,23 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.13.11", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz", - "integrity": "sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.3.tgz", + "integrity": "sha512-BnEfi5+6J2Lte9LeiL6TxLWdIlEv9Woacc1qXzXBgbikcOzMRM2Oya5XGg/f/ngotv1ej2A/b+3iJH8wbS1+lQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-function-name": "^7.14.2", + "@babel/helper-member-expression-to-functions": "^7.13.12", "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-replace-supers": "^7.14.3", "@babel/helper-split-export-declaration": "^7.12.13" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", - "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.3.tgz", + "integrity": "sha512-JIB2+XJrb7v3zceV2XzDhGIB902CmKGSpSl4q2C6agU9SNLG/2V1RtFRGPG1Ajh9STj3+q6zJMOC+N/pp2P9DA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.12.13", @@ -184,9 +185,9 @@ } }, "@babel/helper-define-polyfill-provider": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.0.tgz", - "integrity": "sha512-JT8tHuFjKBo8NnaUbblz7mIu1nnvUDiHVjXXkulZULyidvo/7P6TY7+YqpV37IfF+KUFxmlK04elKtGKXaiVgw==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.1.tgz", + "integrity": "sha512-x3AUTVZNPunaw1opRTa5OwVA5N0YxGlIad9xQ5QflK1uIS7PnAGGU5O2Dj/G183fR//N8AzTq+Q8+oiu9m0VFg==", "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.13.0", @@ -232,14 +233,14 @@ } }, "@babel/helper-function-name": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", - "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", + "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/types": "^7.14.2" } }, "@babel/helper-get-function-arity": { @@ -280,19 +281,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.13.14", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz", - "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz", + "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.13.12", "@babel/helper-replace-supers": "^7.13.12", "@babel/helper-simple-access": "^7.13.12", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.13", - "@babel/types": "^7.13.14" + "@babel/traverse": "^7.14.2", + "@babel/types": "^7.14.2" } }, "@babel/helper-optimise-call-expression": { @@ -322,15 +323,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", - "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.3.tgz", + "integrity": "sha512-Rlh8qEWZSTfdz+tgNV/N4gz1a0TMNwCUcENhMjHTHKp3LseYH5Jha0NSlyTQWMnjbYcwFt+bqAMqSLHVXkQ6UA==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.13.12", "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.12" + "@babel/traverse": "^7.14.2", + "@babel/types": "^7.14.2" } }, "@babel/helper-simple-access": { @@ -361,9 +362,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, "@babel/helper-validator-option": { @@ -385,31 +386,31 @@ } }, "@babel/helpers": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.16.tgz", - "integrity": "sha512-x5otxUaLpdWHl02P4L94wBU+2BJXBkvO+6d6uzQ+xD9/h2hTSAwA5O8QV8GqKx/l8i+VYmKKQg9e2QGTa2Wu3Q==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", + "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", "dev": true, "requires": { "@babel/template": "^7.12.13", - "@babel/traverse": "^7.13.15", - "@babel/types": "^7.13.16" + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0" } }, "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.16.tgz", - "integrity": "sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", + "integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", "dev": true }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { @@ -424,9 +425,9 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.15.tgz", - "integrity": "sha512-VapibkWzFeoa6ubXy/NgV5U2U4MVnUlvnx6wo1XhlsaTrLYWE0UFpDQsVrmn22q5CzeloqJ8gEMHSKxuee6ZdA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.2.tgz", + "integrity": "sha512-b1AM4F6fwck4N8ItZ/AtC4FP/cqZqmKRQ4FaTDutwSYyjuhtvsGEMLK4N/ztV/ImP40BjIDyMgBQAeAMsQYVFQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -444,10 +445,21 @@ "@babel/helper-plugin-utils": "^7.13.0" } }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.3.tgz", + "integrity": "sha512-HEjzp5q+lWSjAgJtSluFDrGGosmwTgKwCXdDQZvhKsRlwv3YdkUEqxNrrjesJd+B9E9zvr1PVPVBvhYZ9msjvQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.3", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-class-static-block": "^7.12.13" + } + }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz", - "integrity": "sha512-ONWKj0H6+wIRCkZi9zSbZtE/r73uOhMVHh256ys0UzfM7I3d4n+spZNWjOnJv2gzopumP2Wxi186vI8N0Y2JyQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.2.tgz", + "integrity": "sha512-oxVQZIWFh91vuNEMKltqNsKLFWkOIyJc95k2Gv9lWVyDfPUQGSSlbDEgWuJUU1afGE9WwlzpucMZ3yDRHIItkA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -455,19 +467,19 @@ } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.13.tgz", - "integrity": "sha512-INAgtFo4OnLN3Y/j0VwAgw3HDXcDtX+C/erMvWzuV9v71r7urb6iyMXu7eM9IgLr1ElLlOkaHjJ0SbCmdOQ3Iw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.2.tgz", + "integrity": "sha512-sRxW3z3Zp3pFfLAgVEvzTFutTXax837oOatUIvSG9o5gRj9mKwm3br1Se5f4QalTQs9x4AzlA/HrCWbQIHASUQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.13.8.tgz", - "integrity": "sha512-w4zOPKUFPX1mgvTmL/fcEqy34hrQ1CRcGxdphBc6snDnnqJ47EZDIyop6IwXzAC8G916hsIuXB2ZMBCExC5k7Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.2.tgz", + "integrity": "sha512-w2DtsfXBBJddJacXMBhElGEYqCZQqN99Se1qeYn8DVLB33owlrlLftIbMzn5nz1OITfDVknXF433tBrLEAOEjA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -475,9 +487,9 @@ } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz", - "integrity": "sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.2.tgz", + "integrity": "sha512-1JAZtUrqYyGsS7IDmFeaem+/LJqujfLZ2weLR9ugB0ufUPjzf8cguyVT1g5im7f7RXxuLq1xUxEzvm68uYRtGg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -485,9 +497,9 @@ } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz", - "integrity": "sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz", + "integrity": "sha512-ebR0zU9OvI2N4qiAC38KIAK75KItpIPTpAtd2r4OZmMFeKbKJpUFLYP2EuDut82+BmYi8sz42B+TfTptJ9iG5Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -495,32 +507,32 @@ } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.13.tgz", - "integrity": "sha512-O1jFia9R8BUCl3ZGB7eitaAPu62TXJRHn7rh+ojNERCFyqRwJMTmhz+tJ+k0CwI6CLjX/ee4qW74FSqlq9I35w==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.2.tgz", + "integrity": "sha512-DcTQY9syxu9BpU3Uo94fjCB3LN9/hgPS8oUL7KrSW3bA2ePrKZZPJcc5y0hoJAM9dft3pGfErtEUvxXQcfLxUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz", - "integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz", + "integrity": "sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.8", - "@babel/helper-compilation-targets": "^7.13.8", + "@babel/compat-data": "^7.14.0", + "@babel/helper-compilation-targets": "^7.13.16", "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.13.0" + "@babel/plugin-transform-parameters": "^7.14.2" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.13.8.tgz", - "integrity": "sha512-0wS/4DUF1CuTmGo+NiaHfHcVSeSLj5S3e6RivPTg/2k3wOv3jO35tZ6/ZWsQhQMvdgI7CwphjQa/ccarLymHVA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.2.tgz", + "integrity": "sha512-XtkJsmJtBaUbOxZsNk0Fvrv8eiqgneug0A6aqLFZ4TSkar2L5dSXWcnUKHgmjJt49pyB/6ZHvkr3dPgl9MOWRQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -528,9 +540,9 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz", - "integrity": "sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz", + "integrity": "sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", @@ -548,6 +560,18 @@ "@babel/helper-plugin-utils": "^7.13.0" } }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.0.tgz", + "integrity": "sha512-59ANdmEwwRUkLjB7CRtwJxxwtjESw+X2IePItA+RGQh+oy5RmpCh/EvVVvh5XQc3yxsm5gtv0+i9oBZhaDNVTg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-create-class-features-plugin": "^7.14.0", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-private-property-in-object": "^7.14.0" + } + }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz", @@ -585,6 +609,15 @@ "@babel/helper-plugin-utils": "^7.12.13" } }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.12.13.tgz", + "integrity": "sha512-ZmKQ0ZXR0nYpHZIIuj9zE7oIqCx2hw9TKi+lIo73NNrMPAZGHfS92/VRV0ZmPj6H2ffBgyFHXvJ5NYsNeEaP2A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", @@ -675,6 +708,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.0.tgz", + "integrity": "sha512-bda3xF8wGl5/5btF794utNOL0Jw+9jE5C1sLZcoK7c4uonE/y3iQiyG+KbkF3WBV/paX58VCpjhxLPkdj5Fe4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.13.0" + } + }, "@babel/plugin-syntax-top-level-await": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz", @@ -723,25 +765,25 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.13.16.tgz", - "integrity": "sha512-ad3PHUxGnfWF4Efd3qFuznEtZKoBp0spS+DgqzVzRPV7urEBvPLue3y2j80w4Jf2YLzZHj8TOv/Lmvdmh3b2xg==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.2.tgz", + "integrity": "sha512-neZZcP19NugZZqNwMTH+KoBjx5WyvESPSIOQb4JHpfd+zPfqcH65RMu5xJju5+6q/Y2VzYrleQTr+b6METyyxg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-classes": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.13.0.tgz", - "integrity": "sha512-9BtHCPUARyVH1oXGcSJD3YpsqRLROJx5ZNP6tN5vnk17N0SVf9WCtf8Nuh1CFmgByKKAIMstitKduoCmsaDK5g==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.2.tgz", + "integrity": "sha512-7oafAVcucHquA/VZCsXv/gmuiHeYd64UJyyTYU+MPfNu0KeNlxw06IeENBO8bJjXVbolu+j1MM5aKQtH1OMCNg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.12.13", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-optimise-call-expression": "^7.12.13", "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-replace-supers": "^7.13.12", "@babel/helper-split-export-declaration": "^7.12.13", "globals": "^11.1.0" } @@ -756,9 +798,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.0.tgz", - "integrity": "sha512-zym5em7tePoNT9s964c0/KU3JPPnuq7VhIxPRefJ4/s82cD+q1mgKfuGRDMCPL0HTyKz4dISuQlCusfgCJ86HA==", + "version": "7.13.17", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz", + "integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0" @@ -831,25 +873,25 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.13.0.tgz", - "integrity": "sha512-EKy/E2NHhY/6Vw5d1k3rgoobftcNUmp9fGjb9XZwQLtTctsRBOTRO7RHHxfIky1ogMN5BxN7p9uMA3SzPfotMQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.2.tgz", + "integrity": "sha512-hPC6XBswt8P3G2D1tSV2HzdKvkqOpmbyoy+g73JG0qlF/qx2y3KaMmXb1fLrpmWGLZYA0ojCvaHdzFWjlmV+Pw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-module-transforms": "^7.14.2", "@babel/helper-plugin-utils": "^7.13.0", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.13.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz", - "integrity": "sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz", + "integrity": "sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-module-transforms": "^7.14.0", "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-simple-access": "^7.12.13", + "@babel/helper-simple-access": "^7.13.12", "babel-plugin-dynamic-import-node": "^2.3.3" } }, @@ -867,12 +909,12 @@ } }, "@babel/plugin-transform-modules-umd": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.13.0.tgz", - "integrity": "sha512-D/ILzAh6uyvkWjKKyFE/W0FzWwasv6vPTSqPcjxFqn6QpX3u8DjRVliq4F2BamO2Wee/om06Vyy+vPkNrd4wxw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz", + "integrity": "sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-module-transforms": "^7.14.0", "@babel/helper-plugin-utils": "^7.13.0" } }, @@ -905,9 +947,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz", - "integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz", + "integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0" @@ -987,12 +1029,12 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz", - "integrity": "sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.3.tgz", + "integrity": "sha512-G5Bb5pY6tJRTC4ag1visSgiDoGgJ1u1fMUgmc2ijLkcIdzP83Q1qyZX4ggFQ/SkR+PNOatkaYC+nKcTlpsX4ag==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-create-class-features-plugin": "^7.14.3", "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-typescript": "^7.12.13" } @@ -1017,31 +1059,34 @@ } }, "@babel/preset-env": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.15.tgz", - "integrity": "sha512-D4JAPMXcxk69PKe81jRJ21/fP/uYdcTZ3hJDF5QX2HSI9bBxxYw/dumdR6dGumhjxlprHPE4XWoPaqzZUVy2MA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.2.tgz", + "integrity": "sha512-7dD7lVT8GMrE73v4lvDEb85cgcQhdES91BSD7jS/xjC6QY8PnRhux35ac+GCpbiRhp8crexBvZZqnaL6VrY8TQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.15", - "@babel/helper-compilation-targets": "^7.13.13", + "@babel/compat-data": "^7.14.0", + "@babel/helper-compilation-targets": "^7.13.16", "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-option": "^7.12.17", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.13.12", - "@babel/plugin-proposal-async-generator-functions": "^7.13.15", + "@babel/plugin-proposal-async-generator-functions": "^7.14.2", "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-dynamic-import": "^7.13.8", - "@babel/plugin-proposal-export-namespace-from": "^7.12.13", - "@babel/plugin-proposal-json-strings": "^7.13.8", - "@babel/plugin-proposal-logical-assignment-operators": "^7.13.8", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", - "@babel/plugin-proposal-numeric-separator": "^7.12.13", - "@babel/plugin-proposal-object-rest-spread": "^7.13.8", - "@babel/plugin-proposal-optional-catch-binding": "^7.13.8", - "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-proposal-class-static-block": "^7.13.11", + "@babel/plugin-proposal-dynamic-import": "^7.14.2", + "@babel/plugin-proposal-export-namespace-from": "^7.14.2", + "@babel/plugin-proposal-json-strings": "^7.14.2", + "@babel/plugin-proposal-logical-assignment-operators": "^7.14.2", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.2", + "@babel/plugin-proposal-numeric-separator": "^7.14.2", + "@babel/plugin-proposal-object-rest-spread": "^7.14.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.14.2", + "@babel/plugin-proposal-optional-chaining": "^7.14.2", "@babel/plugin-proposal-private-methods": "^7.13.0", + "@babel/plugin-proposal-private-property-in-object": "^7.14.0", "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.12.13", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", @@ -1051,14 +1096,15 @@ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.0", "@babel/plugin-syntax-top-level-await": "^7.12.13", "@babel/plugin-transform-arrow-functions": "^7.13.0", "@babel/plugin-transform-async-to-generator": "^7.13.0", "@babel/plugin-transform-block-scoped-functions": "^7.12.13", - "@babel/plugin-transform-block-scoping": "^7.12.13", - "@babel/plugin-transform-classes": "^7.13.0", + "@babel/plugin-transform-block-scoping": "^7.14.2", + "@babel/plugin-transform-classes": "^7.14.2", "@babel/plugin-transform-computed-properties": "^7.13.0", - "@babel/plugin-transform-destructuring": "^7.13.0", + "@babel/plugin-transform-destructuring": "^7.13.17", "@babel/plugin-transform-dotall-regex": "^7.12.13", "@babel/plugin-transform-duplicate-keys": "^7.12.13", "@babel/plugin-transform-exponentiation-operator": "^7.12.13", @@ -1066,14 +1112,14 @@ "@babel/plugin-transform-function-name": "^7.12.13", "@babel/plugin-transform-literals": "^7.12.13", "@babel/plugin-transform-member-expression-literals": "^7.12.13", - "@babel/plugin-transform-modules-amd": "^7.13.0", - "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/plugin-transform-modules-amd": "^7.14.2", + "@babel/plugin-transform-modules-commonjs": "^7.14.0", "@babel/plugin-transform-modules-systemjs": "^7.13.8", - "@babel/plugin-transform-modules-umd": "^7.13.0", + "@babel/plugin-transform-modules-umd": "^7.14.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", "@babel/plugin-transform-new-target": "^7.12.13", "@babel/plugin-transform-object-super": "^7.12.13", - "@babel/plugin-transform-parameters": "^7.13.0", + "@babel/plugin-transform-parameters": "^7.14.2", "@babel/plugin-transform-property-literals": "^7.12.13", "@babel/plugin-transform-regenerator": "^7.13.15", "@babel/plugin-transform-reserved-words": "^7.12.13", @@ -1085,7 +1131,7 @@ "@babel/plugin-transform-unicode-escapes": "^7.12.13", "@babel/plugin-transform-unicode-regex": "^7.12.13", "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.13.14", + "@babel/types": "^7.14.2", "babel-plugin-polyfill-corejs2": "^0.2.0", "babel-plugin-polyfill-corejs3": "^0.2.0", "babel-plugin-polyfill-regenerator": "^0.2.0", @@ -1126,9 +1172,9 @@ } }, "@babel/runtime": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.16.tgz", - "integrity": "sha512-7VsWJsI5USRhBLE/3of+VU2DDNWtYHQlq2IHu2iL15+Yx4qVqP8KllR6JMHQlTKWRyDk9Tw6unkqSusaHXt//A==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -1145,17 +1191,17 @@ } }, "@babel/traverse": { - "version": "7.13.15", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz", - "integrity": "sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", + "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.13.9", - "@babel/helper-function-name": "^7.12.13", + "@babel/generator": "^7.14.2", + "@babel/helper-function-name": "^7.14.2", "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.13.15", - "@babel/types": "^7.13.14", + "@babel/parser": "^7.14.2", + "@babel/types": "^7.14.2", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1178,12 +1224,12 @@ } }, "@babel/types": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.16.tgz", - "integrity": "sha512-7enM8Wxhrl1hB1+k6+xO6RmxpNkaveRWkdpyii8DkrLWRgr0l3x29/SEuhTIkP+ynHsU/Hpjn8Evd/axv/ll6Q==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "to-fast-properties": "^2.0.0" } }, @@ -1194,11 +1240,11 @@ "dev": true }, "@blueprintjs/core": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.44.0.tgz", - "integrity": "sha512-QjRa4LvygTJn5v75O1bvKQtxcs9u2sl2CXoQ3Hd2KLQwzAz8kongWyc2xOw/wiFE4gRyRZQK44c43bEPkoeKhA==", + "version": "3.44.3", + "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.44.3.tgz", + "integrity": "sha512-95BYF5xI7d47jKJKQFXJ+UkJ8pS6qT6/U4Hj/UCuHPJhtBTfUQKaCeHYroA+LtCAEEb9p9oFkQwlXI+QHMmZeA==", "requires": { - "@blueprintjs/icons": "^3.26.0", + "@blueprintjs/icons": "^3.26.1", "@types/dom4": "^2.0.1", "classnames": "^2.2", "dom4": "^2.1.5", @@ -1212,20 +1258,20 @@ } }, "@blueprintjs/icons": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.26.0.tgz", - "integrity": "sha512-1+yhYH1Fjj5qGx8drZUL2L1R42MiN0WVHTTKYqGEV9TAzhvFHCSZgALD7WNQa+FEibw/8B4U+79IRgUPJNEjow==", + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.26.1.tgz", + "integrity": "sha512-qxAnqhzt5WqYuWN+7p3Pk7bOrhj56YXzD8n79Met8+VIQ14IpKnxr7YAYmNB5X/dVweqXpEk6tKyUjnDjBhulw==", "requires": { "classnames": "^2.2", "tslib": "~1.13.0" } }, "@blueprintjs/select": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.16.0.tgz", - "integrity": "sha512-x6ocSC1sxRfKtVGDIzP83xSWQvikzcq7Vpl+HvlonbpDWu4a9Ybx8wV5AM2Twjwp0laF8XSSUWFh75iA/g6rsg==", + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.16.3.tgz", + "integrity": "sha512-V7agrVgvWVFyRXUv8OFjTJB5ZfUnYAAqzxvpdx6WQcdQTkMjRD0B7pWcZol+grbP1MJGFVAXP1Mqj2PW3BVCbg==", "requires": { - "@blueprintjs/core": "^3.44.0", + "@blueprintjs/core": "^3.44.3", "classnames": "^2.2", "tslib": "~1.13.0" } @@ -1241,15 +1287,15 @@ } }, "@discoveryjs/json-ext": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", - "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", + "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", "dev": true }, "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -1327,14 +1373,6 @@ "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } } }, "@istanbuljs/schema": { @@ -1518,9 +1556,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -1839,9 +1877,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2057,9 +2095,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2259,9 +2297,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2616,9 +2654,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2852,16 +2890,16 @@ } }, "@jupyterlab/apputils": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jupyterlab/apputils/-/apputils-3.0.7.tgz", - "integrity": "sha512-53JwXwhqqFdzOCmbzFhpBWheA+EiQrkKxKSOk1Re2FpseiuB2bgvgwFNSYaFrSG37HlBKSnqlgWAdPF+gnGGJQ==", - "requires": { - "@jupyterlab/coreutils": "^5.0.5", - "@jupyterlab/services": "^6.0.7", - "@jupyterlab/settingregistry": "^3.0.5", - "@jupyterlab/statedb": "^3.0.5", - "@jupyterlab/translation": "^3.0.7", - "@jupyterlab/ui-components": "^3.0.6", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/apputils/-/apputils-3.0.9.tgz", + "integrity": "sha512-fsJjl+NX2+e+1FM7SMfpI1VsaPQsaIPnPGsdpQoboJJqdQJHuj1oPXNwc/aI1daEElirB15fYGCUGc2oUrv6RQ==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/services": "^6.0.9", + "@jupyterlab/settingregistry": "^3.0.6", + "@jupyterlab/statedb": "^3.0.6", + "@jupyterlab/translation": "^3.0.9", + "@jupyterlab/ui-components": "^3.0.7", "@lumino/algorithm": "^1.3.3", "@lumino/commands": "^1.12.0", "@lumino/coreutils": "^1.5.3", @@ -2876,17 +2914,17 @@ "buffer": "^5.6.0", "react": "^17.0.1", "react-dom": "^17.0.1", - "sanitize-html": "~1.27.4", + "sanitize-html": "~2.3.3", "url": "^0.11.0" } }, "@jupyterlab/builder": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jupyterlab/builder/-/builder-3.0.8.tgz", - "integrity": "sha512-f5HPbH+oxxZGRt+/hxeuW/217cGyD2jCE2ksy8758WgQGspfQHSNWhshGgGufs/6PfUoKx8vIYY8dmPMn5WdeQ==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/builder/-/builder-3.0.9.tgz", + "integrity": "sha512-IjWHk/xTgufTyggbT/0tGFeRdsHe3rNMQkOMqDN5+8YqFV4uCTUNokgvyysedgwB7JP+tcPclN/a3QoIPjAq/w==", "dev": true, "requires": { - "@jupyterlab/buildutils": "^3.0.6", + "@jupyterlab/buildutils": "^3.0.7", "@lumino/algorithm": "^1.3.3", "@lumino/application": "^1.13.1", "@lumino/commands": "^1.12.0", @@ -2929,15 +2967,14 @@ "dev": true }, "css-loader": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.4.tgz", - "integrity": "sha512-OFYGyINCKkdQsTrSYxzGSFnGS4gNjcXkKkQgWxK138jgnPt+lepxdjSZNc8sHAl5vP3DhsJUxufWIjOwI8PMMw==", + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz", + "integrity": "sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==", "dev": true, "requires": { - "camelcase": "^6.2.0", "icss-utils": "^5.1.0", "loader-utils": "^2.0.0", - "postcss": "^8.2.10", + "postcss": "^8.2.15", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", @@ -2988,17 +3025,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "postcss": { - "version": "8.2.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.10.tgz", - "integrity": "sha512-b/h7CPV7QEdrqIxtAf2j31U5ef05uBDuvoXv6L51Q4rcS1jdlXAVKJv+atCFdUXYl9dyTHGyoMzIepwowRJjFw==", - "dev": true, - "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.22", - "source-map": "^0.6.1" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -3040,9 +3066,9 @@ } }, "@jupyterlab/buildutils": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@jupyterlab/buildutils/-/buildutils-3.0.6.tgz", - "integrity": "sha512-S6Hnop5A5KjCCHQt1ob3ABy1VQ94ssbRPsYa04R7mUjVQu5NsIS8Kd0O/+yqtuSaWIJOqCKhRZEev3rgG+dHqw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jupyterlab/buildutils/-/buildutils-3.0.7.tgz", + "integrity": "sha512-V3A9foBIP9CJcblyZTEKHtkY6o/3pRodxNAZqveiDDpBdQhM8xv4uOLBKkkMxroa5Eh5Goub4fw+JHxI2nKGXw==", "dev": true, "requires": { "@lumino/coreutils": "^1.5.3", @@ -3087,13 +3113,19 @@ "requires": { "lru-cache": "^6.0.0" } + }, + "typescript": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", + "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "dev": true } } }, "@jupyterlab/coreutils": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-5.0.5.tgz", - "integrity": "sha512-dUlAK4XCTzqJjLNYzDQG0//j5Eq6oJAFS9I9iww0HAX4jj7r1Ozoh7TkMO7rUQG49KnVsp8fg23ewyn/tF7voA==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-5.0.6.tgz", + "integrity": "sha512-nXGpI1IJw+4pNq6Afy+oI3LrTsaQ14xG7Kxbhg9UPfoDgsNt2rdG4pwYe4NZyj2GJHAkUj00lcUD9eBTrxMWvw==", "requires": { "@lumino/coreutils": "^1.5.3", "@lumino/disposable": "^1.4.3", @@ -3101,21 +3133,21 @@ "minimist": "~1.2.0", "moment": "^2.24.0", "path-browserify": "^1.0.0", - "url-parse": "~1.4.7" + "url-parse": "~1.5.1" } }, "@jupyterlab/nbformat": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-3.0.5.tgz", - "integrity": "sha512-OnkeTuBLBc/2hOqO5N43DJjNhAabzEAVQvVmyteBUCRInAlCRgRbCyv0leCO+pYWBIBQAUTwddkf5lyOV/rv9Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-3.0.6.tgz", + "integrity": "sha512-4+u770JYPmRpLyEPpnG0crj8ePUkg/vCF1W4hnDDxnLTVjzKw5kv6KVb5yJGEHAihUOf51bjceNUOp/+nLVBTg==", "requires": { "@lumino/coreutils": "^1.5.3" } }, "@jupyterlab/observables": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-4.0.5.tgz", - "integrity": "sha512-fvz9aN3S3ypPLdz69Jy0JckiUsNkU3WXeY48DB2nX3gBIPjnJLHuETAik6JrD0nkes17e9dWsafkox2643TIqQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-4.0.6.tgz", + "integrity": "sha512-PYJosNXGSkLExaEXqpUuDjEXTEcxTpvM6kG8I6NFJyDQVD6E50LggC6NofY5EIcEsJsO771BLvI4kwNk7LRQSA==", "requires": { "@lumino/algorithm": "^1.3.3", "@lumino/coreutils": "^1.5.3", @@ -3125,15 +3157,15 @@ } }, "@jupyterlab/services": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-6.0.7.tgz", - "integrity": "sha512-wO27obxOibDs5BJ6+l7kciFbqbEOS5W2q1MZpVst4YYYjp9/gS8EfGNi/84NqwOKg3vb8ZW+xq0Amf2o6gnxXA==", - "requires": { - "@jupyterlab/coreutils": "^5.0.5", - "@jupyterlab/nbformat": "^3.0.5", - "@jupyterlab/observables": "^4.0.5", - "@jupyterlab/settingregistry": "^3.0.5", - "@jupyterlab/statedb": "^3.0.5", + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-6.0.9.tgz", + "integrity": "sha512-zeN9roqwbYo6b2I5BXWx+Mr4KzTpe2UcVwrcAGw9NXqIieb0ZnvtHqtNj/vcHCM2xQKuPup9W1X1bE5b3wF5Yw==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/nbformat": "^3.0.6", + "@jupyterlab/observables": "^4.0.6", + "@jupyterlab/settingregistry": "^3.0.6", + "@jupyterlab/statedb": "^3.0.6", "@lumino/algorithm": "^1.3.3", "@lumino/coreutils": "^1.5.3", "@lumino/disposable": "^1.4.3", @@ -3144,11 +3176,11 @@ } }, "@jupyterlab/settingregistry": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/settingregistry/-/settingregistry-3.0.5.tgz", - "integrity": "sha512-H86y+CKUxObPA/g8kafmoK23rRsKaXnYCkp4qDx5Vl932/rN6wJUezQ1POe4iFW8MHiniUJpKB8WCknVGc/AUg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/settingregistry/-/settingregistry-3.0.6.tgz", + "integrity": "sha512-fIeVJjkaf8FYSJ4jwJobwNeco8J2CEuWzmEJKiDjhmzmRZApS9Jjx+CJXDkTxoSMDQ41ELxQKJq5bcbih/90zQ==", "requires": { - "@jupyterlab/statedb": "^3.0.5", + "@jupyterlab/statedb": "^3.0.6", "@lumino/commands": "^1.12.0", "@lumino/coreutils": "^1.5.3", "@lumino/disposable": "^1.4.3", @@ -3158,9 +3190,9 @@ } }, "@jupyterlab/statedb": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/statedb/-/statedb-3.0.5.tgz", - "integrity": "sha512-lzFDEaGtn3movHoL2Z7umsUXjTcSJZaWxBfSbm0OBhtoZ9OG+KmQfkln00ThOAboMZT2zmTxfRBGwkDwi6wDSw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/statedb/-/statedb-3.0.6.tgz", + "integrity": "sha512-hXewp5TAKneWJcYXenTZuzSUagGjyWv5vRHDFarw1O4pkEg7zz8IyN2yAvbYH6+GDqIhF/91rgGu9alkx/yjjA==", "requires": { "@lumino/commands": "^1.12.0", "@lumino/coreutils": "^1.5.3", @@ -3170,24 +3202,24 @@ } }, "@jupyterlab/translation": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jupyterlab/translation/-/translation-3.0.7.tgz", - "integrity": "sha512-ZJEcmEdd6sSlhiYSpPtzE8EjzigaHKzarzziD8GwJfMVOu+bUF/nLX9RFjr5tS7CuZDIKqD08t3z1hDgQ4EfMg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/translation/-/translation-3.0.9.tgz", + "integrity": "sha512-XsIUt08HDpA2zqhJFmNV9iuxMriV4sAdx4rM1rA0tEUuvWSXerLvpzNUw4LAz+iaJgyUgqqV1gKrOgoMTjtvWA==", "requires": { - "@jupyterlab/coreutils": "^5.0.5", - "@jupyterlab/services": "^6.0.7", - "@jupyterlab/statedb": "^3.0.5", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/services": "^6.0.9", + "@jupyterlab/statedb": "^3.0.6", "@lumino/coreutils": "^1.5.3" } }, "@jupyterlab/ui-components": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@jupyterlab/ui-components/-/ui-components-3.0.6.tgz", - "integrity": "sha512-1zRAFKNF2mdY9qT5/OFwL2MO+rXgM2slKg5lwDAK7GToV043GqPseqeONET4On8wR5m9eYsB1meL9mGEUiA6uQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jupyterlab/ui-components/-/ui-components-3.0.7.tgz", + "integrity": "sha512-kuq2aZ3DcCQNqf5ucsXWREHxbYq23+S12zMertOs+74KQr8jm8chX9HmqpmefNKnSIqqi/RKVSS2PWuSTpkEEw==", "requires": { "@blueprintjs/core": "^3.36.0", "@blueprintjs/select": "^3.15.0", - "@jupyterlab/coreutils": "^5.0.5", + "@jupyterlab/coreutils": "^5.0.6", "@lumino/coreutils": "^1.5.3", "@lumino/signaling": "^1.4.3", "@lumino/virtualdom": "^1.8.0", @@ -3203,14 +3235,14 @@ "integrity": "sha512-NMOcm5Yr9nXz5gokS/K4jHBbUMQYBkvDXl1n51XWdcz0LY+oGuIKPhjazhUgmbNRehzdZBj5hMMd1+htYWeVKQ==" }, "@lumino/application": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@lumino/application/-/application-1.18.0.tgz", - "integrity": "sha512-UswdpqDkeOGjxLaVLnHMqXbHc7eTeibhi6xHhcC7HfwCkTDoAJ3qs+Yap5E9i0RpS7kKt+f2LbBCq9jfrHvfIw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@lumino/application/-/application-1.20.0.tgz", + "integrity": "sha512-FAoQcq4L3ZswTK0lWfLKnG1ecG26cwqjzg2fyoBeuWGBi1TG9BYjFBdV7ErTFMxW8jE1CLOLuxsZaKFLNErcKA==", "dev": true, "requires": { - "@lumino/commands": "^1.14.0", - "@lumino/coreutils": "^1.7.0", - "@lumino/widgets": "^1.21.0" + "@lumino/commands": "^1.15.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/widgets": "^1.23.0" } }, "@lumino/collections": { @@ -3233,25 +3265,6 @@ "@lumino/keyboard": "^1.5.0", "@lumino/signaling": "^1.7.0", "@lumino/virtualdom": "^1.11.0" - }, - "dependencies": { - "@lumino/disposable": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", - "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/signaling": "^1.7.0" - } - }, - "@lumino/signaling": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", - "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - } } }, "@lumino/coreutils": { @@ -3273,116 +3286,6 @@ "@lumino/messaging": "^1.7.0", "@lumino/signaling": "^1.7.0", "@lumino/widgets": "^1.23.0" - }, - "dependencies": { - "@lumino/algorithm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.6.0.tgz", - "integrity": "sha512-NMOcm5Yr9nXz5gokS/K4jHBbUMQYBkvDXl1n51XWdcz0LY+oGuIKPhjazhUgmbNRehzdZBj5hMMd1+htYWeVKQ==" - }, - "@lumino/collections": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.6.0.tgz", - "integrity": "sha512-ZETm0/xF0oUHV03sOXNOfFI1EEpS317HvN5n+fZBJvCNZIrJkWmKD8QuxcfwHb7AChKUhXlVHhDbWlb1LKnd7g==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - }, - "@lumino/commands": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-1.15.0.tgz", - "integrity": "sha512-JOE68KfbR9xw5YTfcwo+9E0PSWidifEMAcOC/aXd7iSzfsCRknMTcMQIUGL277IU7J7CJvoe10DUE5QKwTmX+g==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/coreutils": "^1.8.0", - "@lumino/disposable": "^1.7.0", - "@lumino/domutils": "^1.5.0", - "@lumino/keyboard": "^1.5.0", - "@lumino/signaling": "^1.7.0", - "@lumino/virtualdom": "^1.11.0" - } - }, - "@lumino/coreutils": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-1.8.0.tgz", - "integrity": "sha512-OvCsaASUqOE7R6Dxngyk4/b5QMOjyRUNxuZuuL+fx+JvGKZFZ/B2c9LYtAJ9mDmQ1BQiGNV/qSpL4o7x8PCfjw==" - }, - "@lumino/disposable": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", - "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/signaling": "^1.7.0" - } - }, - "@lumino/domutils": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-1.5.0.tgz", - "integrity": "sha512-dZ0Aa+/qhvfPc1aa5kX4LLGE3B6BW1XmJa0R1XVCEpAFY3cZiujuQWmhYHJtZPrOiqn0UtioT2OpqnWdtCWc0A==" - }, - "@lumino/dragdrop": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", - "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", - "requires": { - "@lumino/coreutils": "^1.8.0", - "@lumino/disposable": "^1.7.0" - } - }, - "@lumino/keyboard": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-1.5.0.tgz", - "integrity": "sha512-/uF9xqHYVbIkser2Q6UIv7VWrzThr1fxAmSOShjSoKGocL0XHeaBaCOMezSaVxnJ1wm1ciNdhMsjscVM8Inp7g==" - }, - "@lumino/messaging": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.7.0.tgz", - "integrity": "sha512-QYWf9QGIGD0Oes104zw7mVln4S8yRije2mZhNNRBjkYcDuQlPW+eRSuC5LwAMsFnGymBlUPwPbKOUEO2RbhAtg==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/collections": "^1.6.0" - } - }, - "@lumino/properties": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.5.0.tgz", - "integrity": "sha512-YqpJE6/1Wkjrie0E+ypu+yzd55B5RlvKYMnQs3Ox+SrJsnNBhA6Oj44EhVf8SUTuHgn1t/mm+LvbswKN5RM4+g==" - }, - "@lumino/signaling": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", - "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - }, - "@lumino/virtualdom": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-1.11.0.tgz", - "integrity": "sha512-G0sIx4pLYbgJ4w+SIgsCYQgKP/GBrWgjh8wcumD6XpaYZNivJv4c01xITYYlh7FU61jZmMWMrxtZztArNRDSqg==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - }, - "@lumino/widgets": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-1.23.0.tgz", - "integrity": "sha512-0Akt9ESgc06SJ3EJG3VK1Liw+AAjRWkKMfm8VUTwT/1QJYYGZ8kfHNO97mkBLv+0EkLEkZIeaQb8fIoU6vh7bw==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/commands": "^1.15.0", - "@lumino/coreutils": "^1.8.0", - "@lumino/disposable": "^1.7.0", - "@lumino/domutils": "^1.5.0", - "@lumino/dragdrop": "^1.10.0", - "@lumino/keyboard": "^1.5.0", - "@lumino/messaging": "^1.7.0", - "@lumino/properties": "^1.5.0", - "@lumino/signaling": "^1.7.0", - "@lumino/virtualdom": "^1.11.0" - } - } } }, "@lumino/default-theme": { @@ -3392,43 +3295,15 @@ "requires": { "@lumino/dragdrop": "^1.10.0", "@lumino/widgets": "^1.23.0" - }, - "dependencies": { - "@lumino/disposable": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", - "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/signaling": "^1.7.0" - } - }, - "@lumino/dragdrop": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", - "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", - "requires": { - "@lumino/coreutils": "^1.8.0", - "@lumino/disposable": "^1.7.0" - } - }, - "@lumino/signaling": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", - "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - } } }, "@lumino/disposable": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.6.0.tgz", - "integrity": "sha512-UIx/2zXOxpwkU3avWoqCjKsAPzSRhaAW0whmaCw8F9gIVqOVafCUjEk2RMHifAjYAHJsS/5FKAOm+sISBy81Tw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", + "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", "requires": { - "@lumino/algorithm": "^1.5.0", - "@lumino/signaling": "^1.6.0" + "@lumino/algorithm": "^1.6.0", + "@lumino/signaling": "^1.7.0" } }, "@lumino/domutils": { @@ -3437,13 +3312,12 @@ "integrity": "sha512-dZ0Aa+/qhvfPc1aa5kX4LLGE3B6BW1XmJa0R1XVCEpAFY3cZiujuQWmhYHJtZPrOiqn0UtioT2OpqnWdtCWc0A==" }, "@lumino/dragdrop": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.9.0.tgz", - "integrity": "sha512-GZozTtQCK6naGo2wYGqJP8YpZSTDhonOeoxMsyVx/batv9cXUlW0oCmBfoMJ6N3vHYrsnPbslR/sE7+lk2/xGw==", - "dev": true, + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", + "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", "requires": { - "@lumino/coreutils": "^1.7.0", - "@lumino/disposable": "^1.6.0" + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0" } }, "@lumino/keyboard": { @@ -3461,26 +3335,26 @@ } }, "@lumino/polling": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/polling/-/polling-1.5.0.tgz", - "integrity": "sha512-jH/L7I8dncv3un4hP6MAzBYUTaKty2KRdVK1yDzJ/5PzVIVs5ZTbIU31Ii8oN7DGJcbnwcl5rDtsV0aOjt3qvg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/polling/-/polling-1.6.0.tgz", + "integrity": "sha512-jG1nqw6UO5XEN7QamOr6iDW8WvYeZQcBVRjM38fszz62dwJ/VGPvO2hlNl6QWWIfCynbJudms0LQm+z0BT1EdA==", "requires": { - "@lumino/coreutils": "^1.7.0", - "@lumino/disposable": "^1.6.0", - "@lumino/signaling": "^1.6.0" + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/signaling": "^1.7.0" } }, "@lumino/properties": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.4.0.tgz", - "integrity": "sha512-wRQ8wF0Rftt8QKjI2p19T1ywJjsMmZDIWajrw8Bz7WUEaRjfaXJ93Ju0nRtXlrbXGntfhIVM3t4ypGowJCF5cA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.5.0.tgz", + "integrity": "sha512-YqpJE6/1Wkjrie0E+ypu+yzd55B5RlvKYMnQs3Ox+SrJsnNBhA6Oj44EhVf8SUTuHgn1t/mm+LvbswKN5RM4+g==" }, "@lumino/signaling": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.6.0.tgz", - "integrity": "sha512-DlgUmjQR7Osqmy8eBiay0LQHP32QJJAxBIOvOLnmeaTwhvxEIg8+zIlnRKcw3hHGff1OaPtWxLqs5UwoGZaiHQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", + "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", "requires": { - "@lumino/algorithm": "^1.5.0" + "@lumino/algorithm": "^1.6.0" } }, "@lumino/virtualdom": { @@ -3507,39 +3381,6 @@ "@lumino/properties": "^1.5.0", "@lumino/signaling": "^1.7.0", "@lumino/virtualdom": "^1.11.0" - }, - "dependencies": { - "@lumino/disposable": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", - "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", - "requires": { - "@lumino/algorithm": "^1.6.0", - "@lumino/signaling": "^1.7.0" - } - }, - "@lumino/dragdrop": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", - "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", - "requires": { - "@lumino/coreutils": "^1.8.0", - "@lumino/disposable": "^1.7.0" - } - }, - "@lumino/properties": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.5.0.tgz", - "integrity": "sha512-YqpJE6/1Wkjrie0E+ypu+yzd55B5RlvKYMnQs3Ox+SrJsnNBhA6Oj44EhVf8SUTuHgn1t/mm+LvbswKN5RM4+g==" - }, - "@lumino/signaling": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", - "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", - "requires": { - "@lumino/algorithm": "^1.6.0" - } - } } }, "@nicolo-ribaudo/chokidar-2": { @@ -3755,6 +3596,12 @@ "defer-to-connect": "^1.0.1" } }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/babel__core": { "version": "7.1.14", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", @@ -3811,9 +3658,9 @@ "integrity": "sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA==" }, "@types/eslint": { - "version": "7.2.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.10.tgz", - "integrity": "sha512-kUEPnMKrqbtpCq/KTaGFFKAcz6Ethm2EjCoKIDaCmfRBWLbFuTcOJfTlorwbnboXBzahqWLgUp1BQeKHiJzPUQ==", + "version": "7.2.11", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.11.tgz", + "integrity": "sha512-WYhv//5K8kQtsSc9F1Kn2vHzhYor6KpwPbARH7hwYe3C3ETD0EVx/3P5qQybUoaBEuUa9f/02JjBiXFWalYUmw==", "dev": true, "requires": { "@types/estree": "*", @@ -3910,9 +3757,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.168", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", - "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" + "version": "4.14.170", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", + "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==" }, "@types/minimatch": { "version": "3.0.4", @@ -3921,9 +3768,9 @@ "dev": true }, "@types/node": { - "version": "10.17.58", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.58.tgz", - "integrity": "sha512-Dn5RBxLohjdHFj17dVVw3rtrZAeXeWg+LQfvxDIW/fdPkSiuQk7h3frKMYtsQhtIW42wkErDcy9UMVxhGW4O7w==", + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", "dev": true }, "@types/normalize-package-data": { @@ -3950,9 +3797,9 @@ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz", - "integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==", + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.6.tgz", + "integrity": "sha512-u/TtPoF/hrvb63LdukET6ncaplYsvCvmkceasx8oG84/ZCsoLxz9Z/raPBP4lTAiWW1Jb889Y9svHmv8R26dWw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3972,9 +3819,9 @@ "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" }, "@types/sizzle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", - "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" }, "@types/stack-utils": { "version": "1.0.1", @@ -3983,9 +3830,9 @@ "dev": true }, "@types/underscore": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.1.tgz", - "integrity": "sha512-mW23Xkp9HYgdMV7gnwuzqnPx6aG0J7xg/b7erQszOcyOizWylwCr9cgYM/BVVJHezUDxwyigG6+wCFQwCvyMBw==" + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.2.tgz", + "integrity": "sha512-Ls2ylbo7++ITrWk2Yc3G/jijwSq5V3GT0tlgVXEl2kKYXY3ImrtmTCoE2uyTWFRI5owMBriloZFWbE1SXOsE7w==" }, "@types/webpack-env": { "version": "1.16.0", @@ -4278,24 +4125,24 @@ } }, "@webpack-cli/configtest": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.2.tgz", - "integrity": "sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.3.tgz", + "integrity": "sha512-WQs0ep98FXX2XBAfQpRbY0Ma6ADw8JR6xoIkaIiJIzClGOMqVRvPCWqndTxf28DgFopWan0EKtHtg/5W1h0Zkw==", "dev": true }, "@webpack-cli/info": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.3.tgz", - "integrity": "sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.4.tgz", + "integrity": "sha512-ogE2T4+pLhTTPS/8MM3IjHn0IYplKM4HbVNMCWA9N4NrdPzunwenpCsqKEXyejMfRu6K8mhauIPYf8ZxWG5O6g==", "dev": true, "requires": { "envinfo": "^7.7.3" } }, "@webpack-cli/serve": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.1.tgz", - "integrity": "sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.4.0.tgz", + "integrity": "sha512-xgT/HqJ+uLWGX+Mzufusl3cgjAcnqYYskaB7o0vRcwOEfuu6hMzSILQpnIzFMGsTaeaX4Nnekl+6fadLbl1/Vg==", "dev": true }, "@xtuc/ieee754": { @@ -4358,6 +4205,32 @@ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -4416,6 +4289,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -4480,21 +4354,6 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -4541,18 +4400,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -4589,6 +4436,12 @@ "supports-color": "^2.0.0" } }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -4712,13 +4565,13 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.0.tgz", - "integrity": "sha512-9bNwiR0dS881c5SHnzCmmGlMkJLl0OUZvxrxHo9w/iNoRuqaPjqlvBf4HrovXtQs/au5yKkpcdgfT1cC5PAZwg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.1.tgz", + "integrity": "sha512-hXGSPbr6IbjeMyGew+3uGIAkRjBFSOJ9FLDZNOfHuyJZCcoia4nd/72J0bSgvfytcVfUcP/dxEVcUhVJuQRtSw==", "dev": true, "requires": { "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.0", + "@babel/helper-define-polyfill-provider": "^0.2.1", "semver": "^6.1.1" }, "dependencies": { @@ -4731,22 +4584,22 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.0.tgz", - "integrity": "sha512-zZyi7p3BCUyzNxLx8KV61zTINkkV65zVkDAFNZmrTCRVhjo1jAS+YLvDJ9Jgd/w2tsAviCwFHReYfxO3Iql8Yg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.1.tgz", + "integrity": "sha512-WZCqF3DLUhdTD/P381MDJfuP18hdCZ+iqJ+wHtzhWENpsiof284JJ1tMQg1CE+hfCWyG48F7e5gDMk2c3Laz7w==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.0", + "@babel/helper-define-polyfill-provider": "^0.2.1", "core-js-compat": "^3.9.1" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.0.tgz", - "integrity": "sha512-J7vKbCuD2Xi/eEHxquHN14bXAW9CXtecwuLrOIDJtcZzTaPzV1VdEfoUf9AzcRBMolKUQKM9/GVojeh0hFiqMg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.1.tgz", + "integrity": "sha512-T3bYyL3Sll2EtC94v3f+fA8M28q7YPTOZdB++SRHjvYZTvtd+WorMUq3tDTD4Q7Kjk1LG0gGromslKjcO5p2TA==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.0" + "@babel/helper-define-polyfill-provider": "^0.2.1" } }, "babel-plugin-transform-es2015-modules-commonjs": { @@ -4957,15 +4810,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -5052,6 +4896,15 @@ "node-fetch": "^2.6.0", "ws": "^7.0.0" } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } } } }, @@ -5112,14 +4965,14 @@ "dev": true }, "browserslist": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.4.tgz", - "integrity": "sha512-d7rCxYV8I9kj41RH8UKYnvDYCRENUlHRgyXy/Rhr/1BaeLGfiCptEdFE8MIrvGfWbBFNjVYx76SQWvNX1j+/cQ==", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001208", + "caniuse-lite": "^1.0.30001219", "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.712", + "electron-to-chromium": "^1.3.723", "escalade": "^3.1.1", "node-releases": "^1.1.71" } @@ -5162,9 +5015,9 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "cacache": { - "version": "15.0.6", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", - "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.1.0.tgz", + "integrity": "sha512-mfx0C+mCfWjD1PnwQ9yaOrwG1ou9FkKnx0SvzUHWdFt7r7GaRtzT+9M8HAvLu62zIHtnpQ/1m93nWNDCckJGXQ==", "dev": true, "requires": { "@npmcli/move-file": "^1.0.1", @@ -5268,15 +5121,15 @@ "dev": true }, "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "caniuse-lite": { - "version": "1.0.30001214", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001214.tgz", - "integrity": "sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg==", + "version": "1.0.30001228", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", + "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", "dev": true }, "capture-exit": { @@ -5288,29 +5141,22 @@ "rsvp": "^4.8.4" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true } } }, @@ -5576,6 +5422,17 @@ "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } } }, "clone-response": { @@ -5613,6 +5470,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -5620,13 +5478,13 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "colorette": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" }, "combined-stream": { "version": "1.0.8", @@ -5692,12 +5550,12 @@ "dev": true }, "core-js-compat": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.10.2.tgz", - "integrity": "sha512-IGHnpuaM1N++gLSPI1F1wu3WXICPxSyj/Q++clcwsIOnUVp5uKUIPl/+6h0TQ112KU3fMiSxqJuM+OrCyKj5+A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz", + "integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==", "dev": true, "requires": { - "browserslist": "^4.16.4", + "browserslist": "^4.16.6", "semver": "7.0.0" }, "dependencies": { @@ -5779,12 +5637,6 @@ "semver": "^6.3.0" }, "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", @@ -5814,6 +5666,17 @@ "json5": "^1.0.1" } }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, "postcss-modules-extract-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", @@ -5871,6 +5734,15 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -6028,15 +5900,6 @@ } } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -6117,8 +5980,7 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, "defer-to-connect": { "version": "1.1.3", @@ -6232,23 +6094,13 @@ } }, "dom-serializer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz", - "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", "requires": { "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", + "domhandler": "^4.2.0", "entities": "^2.0.0" - }, - "dependencies": { - "domhandler": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", - "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", - "requires": { - "domelementtype": "^2.2.0" - } - } } }, "dom4": { @@ -6279,11 +6131,11 @@ } }, "domhandler": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", - "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", "requires": { - "domelementtype": "^2.0.1" + "domelementtype": "^2.2.0" } }, "domutils": { @@ -6294,16 +6146,6 @@ "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" - }, - "dependencies": { - "domhandler": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", - "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", - "requires": { - "domelementtype": "^2.2.0" - } - } } }, "duplexer2": { @@ -6332,20 +6174,10 @@ "semver": "^5.4.1" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "electron-to-chromium": { - "version": "1.3.717", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.717.tgz", - "integrity": "sha512-OfzVPIqD1MkJ7fX+yTl2nKyOE4FReeVfMCzzxQS+Kp43hZYwHwThlGP+EGIZRXJsxCM7dqo8Y65NOX/HP12iXQ==", + "version": "1.3.736", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.736.tgz", + "integrity": "sha512-DY8dA7gR51MSo66DqitEQoUMQ0Z+A2DSXFi7tK304bdTVqczCAfUuyQw6Wdg8hIoo5zIxkU1L24RQtUce1Ioig==", "dev": true }, "emittery": { @@ -6376,9 +6208,9 @@ } }, "enhanced-resolve": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.0.tgz", - "integrity": "sha512-Sl3KRpJA8OpprrtaIswVki3cWPiPKxXuFxJXBp+zNb6s6VwNWwFRUdtmzd2ReUut8n+sCPx7QCtQ7w5wfJhSgQ==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", + "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -6448,9 +6280,9 @@ }, "dependencies": { "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", "dev": true } } @@ -6479,9 +6311,9 @@ "dev": true }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "1.9.1", @@ -6496,25 +6328,27 @@ } }, "eslint": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", - "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.27.0.tgz", + "integrity": "sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", @@ -6526,7 +6360,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.21", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -6535,7 +6369,7 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, @@ -6559,9 +6393,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -6593,9 +6427,9 @@ } }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, "glob-parent": { @@ -6964,9 +6798,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -7107,12 +6941,6 @@ } } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -7131,6 +6959,15 @@ "requires": { "is-plain-object": "^2.0.4" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } } } }, @@ -7221,12 +7058,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "falafel": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.4.tgz", @@ -7370,6 +7201,14 @@ "dev": true, "requires": { "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } } }, "file-entry-cache": { @@ -7538,20 +7377,14 @@ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, @@ -7691,15 +7524,6 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "git-hooks-list": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", @@ -7707,9 +7531,9 @@ "dev": true }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7816,22 +7640,6 @@ "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -7866,7 +7674,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbols": { "version": "1.0.2", @@ -7927,31 +7736,75 @@ "dev": true }, "htmlparser2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", - "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "requires": { "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", "entities": "^2.0.0" } }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, "human-signals": { @@ -8080,9 +7933,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -8176,9 +8029,9 @@ "dev": true }, "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", "dev": true }, "is-binary-path": { @@ -8192,12 +8045,12 @@ } }, "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", "dev": true, "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2" } }, "is-buffer": { @@ -8222,9 +8075,9 @@ } }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", "requires": { "has": "^1.0.3" } @@ -8250,9 +8103,9 @@ } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" }, "is-descriptor": { "version": "0.1.6", @@ -8340,9 +8193,9 @@ } }, "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", "dev": true }, "is-obj": { @@ -8358,13 +8211,9 @@ "dev": true }, "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" }, "is-potential-custom-element-name": { "version": "1.0.1", @@ -8373,12 +8222,12 @@ "dev": true }, "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-regexp": { @@ -8394,18 +8243,18 @@ "dev": true }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", "dev": true }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typedarray": { @@ -8453,12 +8302,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", @@ -8674,9 +8517,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -8892,9 +8735,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -9125,9 +8968,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -9413,9 +9256,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -9611,9 +9454,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -9850,9 +9693,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10047,6 +9890,15 @@ "merge-stream": "^2.0.0", "supports-color": "^6.1.0" } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -10169,9 +10021,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10365,9 +10217,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10483,9 +10335,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10669,9 +10521,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10865,9 +10717,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -11032,9 +10884,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -11403,9 +11255,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -11745,9 +11597,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -12035,10 +11887,16 @@ "color-convert": "^2.0.1" } }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -12198,9 +12056,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -12399,20 +12257,14 @@ } } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, "jsdom": { - "version": "16.5.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz", - "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==", + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", + "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", "dev": true, "requires": { "abab": "^2.0.5", - "acorn": "^8.1.0", + "acorn": "^8.2.4", "acorn-globals": "^6.0.0", "cssom": "^0.4.4", "cssstyle": "^2.3.0", @@ -12420,12 +12272,13 @@ "decimal.js": "^10.2.1", "domexception": "^2.0.1", "escodegen": "^2.0.0", + "form-data": "^3.0.0", "html-encoding-sniffer": "^2.0.1", - "is-potential-custom-element-name": "^1.0.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.0", "parse5": "6.0.1", - "request": "^2.88.2", - "request-promise-native": "^1.0.9", "saxes": "^5.0.1", "symbol-tree": "^3.2.4", "tough-cookie": "^4.0.0", @@ -12435,14 +12288,14 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.4", + "ws": "^7.4.5", "xml-name-validator": "^3.0.0" }, "dependencies": { "acorn": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz", - "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", + "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==", "dev": true }, "escodegen": { @@ -12496,12 +12349,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -12513,12 +12360,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -12537,18 +12378,6 @@ "universalify": "^2.0.0" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -12570,6 +12399,11 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -12633,9 +12467,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -12762,18 +12596,18 @@ } }, "listr2": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.7.1.tgz", - "integrity": "sha512-cNd368GTrk8351/ov/IV+BSwyf9sJRgI0UIvfORonCZA1u9UHAtAlqSEv9dgafoQIA1CgB3nu4No79pJtK2LHw==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.8.3.tgz", + "integrity": "sha512-2NUXrFxPeccawyOpJXfUuV7FmKG4ummQjY+ByPkhTFJ5dVxU9EQbLh0PzaNSXlgbIK7Kmam18oz+ev8sbukzBA==", "dev": true, "requires": { - "chalk": "^4.1.0", "cli-truncate": "^2.1.0", + "colorette": "^1.2.2", "figures": "^3.2.0", "indent-string": "^4.0.0", "log-update": "^4.0.0", "p-map": "^4.0.0", - "rxjs": "^6.6.7", + "rxjs": "^7.1.0", "through": "^2.3.8", "wrap-ansi": "^7.0.0" }, @@ -12787,16 +12621,6 @@ "color-convert": "^2.0.1" } }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -12812,21 +12636,21 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "rxjs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.1.0.tgz", + "integrity": "sha512-gCFO5iHIbRPwznl6hAYuwNFld8W4S2shtSJIqG27ReWXo9IWrCyEICxUA+6vJHwSR/OakoenC4QsDxq50tzYmw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "tslib": "~2.1.0" } }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -12903,10 +12727,10 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "lodash.truncate": { @@ -12935,9 +12759,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -13239,6 +13063,15 @@ "requires": { "is-plain-object": "^2.0.4" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } } } }, @@ -13269,10 +13102,9 @@ "dev": true }, "nanoid": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", - "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==", - "dev": true + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" }, "nanomatch": { "version": "1.2.13", @@ -13356,9 +13188,9 @@ } }, "node-releases": { - "version": "1.1.71", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", - "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "version": "1.1.72", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", + "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", "dev": true }, "normalize-package-data": { @@ -13380,9 +13212,9 @@ "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, "normalize.css": { @@ -13467,12 +13299,6 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -13778,16 +13604,10 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pidtree": { @@ -13841,13 +13661,13 @@ "dev": true }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", + "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" } }, "postcss-modules-extract-imports": { @@ -13886,9 +13706,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.5.tgz", - "integrity": "sha512-aFYPoYmXbZ1V6HZaSvat08M97A8HqO6Pjz+PiNpw/DhuRrC72XWAdp3hL6wusDCN31sSmcZyMGa2hZEuX+Xfhg==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -13913,9 +13733,9 @@ "dev": true }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true }, "prettier-linter-helpers": { @@ -14017,12 +13837,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -14388,84 +14202,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "dev": true, - "requires": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -14711,14 +14447,17 @@ } }, "sanitize-html": { - "version": "1.27.5", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.5.tgz", - "integrity": "sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.3.3.tgz", + "integrity": "sha512-DCFXPt7Di0c6JUnlT90eIgrjs6TsJl/8HYU3KLdmrVclFN4O0heTcVbJiMa23OKVr6aR051XYtsgd8EWwEBwUA==", "requires": { - "htmlparser2": "^4.1.0", - "lodash": "^4.17.15", + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^6.0.0", + "is-plain-object": "^5.0.0", + "klona": "^2.0.3", "parse-srcset": "^1.0.2", - "postcss": "^7.0.27" + "postcss": "^8.0.2" } }, "saxes": { @@ -14797,6 +14536,15 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } } } }, @@ -15058,6 +14806,11 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==" + }, "source-map-loader": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", @@ -15146,9 +14899,9 @@ } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", "dev": true }, "split-string": { @@ -15166,23 +14919,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -15278,12 +15014,6 @@ "through2": "~2.0.3" } }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -15438,9 +15168,10 @@ } }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -15517,26 +15248,23 @@ "dev": true }, "table": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.3.1.tgz", - "integrity": "sha512-kNpMVSN4fj9KY4G6tNDVIT59uaG8ZELGQ+cmFSqivmWkCXJLd00VfRmtyHa8X7AeM75PQ/6/TtEtWjTDs1jXJw==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", "dev": true, "requires": { "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ajv": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", - "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", + "integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -15592,9 +15320,9 @@ } }, "terser": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.1.tgz", - "integrity": "sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", + "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", "dev": true, "requires": { "commander": "^2.20.0", @@ -15807,18 +15535,18 @@ } }, "tr46": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", - "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, "requires": { "punycode": "^2.1.1" } }, "ts-jest": { - "version": "26.5.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.5.tgz", - "integrity": "sha512-7tP4m+silwt1NHqzNRAPjW1BswnAhopTdc2K3HEkRZjF0ZG2F/e/ypVH0xiZIMfItFtD3CX0XFbwPzp9fIEUVg==", + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -15883,9 +15611,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -16108,21 +15836,6 @@ "tslib": "^1.8.1" } }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -16163,9 +15876,9 @@ } }, "typescript": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", - "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true }, "typestyle": { @@ -16347,9 +16060,9 @@ } }, "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -16402,9 +16115,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.1.tgz", - "integrity": "sha512-p0BB09E5FRjx0ELN6RgusIPsSPhtgexSRcKETybEs6IGOTXJSZqfwxp7r//55nnu0f1AxltY5VvdVqy2vZf9AA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz", + "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -16592,17 +16305,6 @@ "resolved": "https://registry.npmjs.org/vega-util/-/vega-util-1.16.1.tgz", "integrity": "sha512-FdgD72fmZMPJE99FxvFXth0IL4BbLA93WmBg/lvcJmfkK4Uf90WIlvGwaIUdSePIsdpkZjBPyQcHMQ8OcS8Smg==" }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", @@ -16644,9 +16346,9 @@ } }, "watchpack": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", - "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", + "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -16660,9 +16362,9 @@ "dev": true }, "webpack": { - "version": "5.34.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.34.0.tgz", - "integrity": "sha512-+WiFMgaZqhu7zKN64LQ7z0Ml4WWI+9RwG6zmS0wJDQXiCeg3hpN8fYFNJ+6WlosDT55yVxTfK7XHUAOVR4rLyA==", + "version": "5.37.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.37.1.tgz", + "integrity": "sha512-btZjGy/hSjCAAVHw+cKG+L0M+rstlyxbO2C+BOTaQ5/XAnxkDrP5sVbqWhXgo4pL3X2dcOib6rqCP20Zr9PLow==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -16670,7 +16372,7 @@ "@webassemblyjs/ast": "1.11.0", "@webassemblyjs/wasm-edit": "1.11.0", "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.0.4", + "acorn": "^8.2.1", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.8.0", @@ -16691,15 +16393,15 @@ }, "dependencies": { "acorn": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz", - "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", + "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==", "dev": true }, "terser-webpack-plugin": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", - "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-6QhDaAiVHIQr5Ab3XUWZyDmrIPCHMiqJVljMF91YKyqwKkL5QHnYMkrMBy96v9Z7ev1hGhSEw1HQZc2p/s5Z8Q==", "dev": true, "requires": { "jest-worker": "^26.6.2", @@ -16707,7 +16409,7 @@ "schema-utils": "^3.0.0", "serialize-javascript": "^5.0.1", "source-map": "^0.6.1", - "terser": "^5.5.1" + "terser": "^5.7.0" } }, "webpack-sources": { @@ -16723,18 +16425,17 @@ } }, "webpack-cli": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.6.0.tgz", - "integrity": "sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.0.tgz", + "integrity": "sha512-7bKr9182/sGfjFm+xdZSwgQuFjgEcy0iCTIBxRUeteJ2Kr8/Wz0qNJX+jw60LU36jApt4nmMkep6+W5AKhok6g==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.2", - "@webpack-cli/info": "^1.2.3", - "@webpack-cli/serve": "^1.3.1", + "@webpack-cli/configtest": "^1.0.3", + "@webpack-cli/info": "^1.2.4", + "@webpack-cli/serve": "^1.4.0", "colorette": "^1.2.1", "commander": "^7.0.0", - "enquirer": "^2.3.6", "execa": "^5.0.0", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", @@ -16984,14 +16685,6 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } } }, "yocto-queue": { diff --git a/package.json b/package.json index a42b2869..d8db7461 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "svg-url-loader": "~3.0.3", "ts-jest": "^26.5.0", "ts-loader": "^6.0.4", - "typescript": "~4.1.3", + "typescript": "~4.2.4", "url-loader": "^4.1.0", "webpack": "^5", "webpack-cli": "^4.4.0" From 40636d56c3ae32d0b8dd9d6dd94ad0789f54121a Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Thu, 27 May 2021 01:38:24 -0700 Subject: [PATCH 04/20] Nested columns rendering using TextRenderer Signed-off-by: Itay Dafna --- js/core/viewbasedjsonmodel.ts | 52 ++++++++++++++++++++++++++++++++--- js/utils.ts | 17 ++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/js/core/viewbasedjsonmodel.ts b/js/core/viewbasedjsonmodel.ts index 1b06e854..b9ac66b4 100644 --- a/js/core/viewbasedjsonmodel.ts +++ b/js/core/viewbasedjsonmodel.ts @@ -1,4 +1,4 @@ -import { DataModel, MutableDataModel } from '@lumino/datagrid'; +import { CellGroup, DataModel, MutableDataModel } from '@lumino/datagrid'; import { each } from '@lumino/algorithm'; @@ -30,6 +30,8 @@ export class ViewBasedJSONModel extends MutableDataModel { constructor(data: ViewBasedJSONModel.IData) { super(); this.updateDataset(data); + //@ts-ignore + window.jsonview = this; this._transformState = new TransformStateManager(); // Repaint grid on transform state update // Note: This will also result in the `model-reset` signal being sent. @@ -39,9 +41,8 @@ export class ViewBasedJSONModel extends MutableDataModel { }); // first run: generate a list of indices corresponding // to the locations of multi-index arrays. - const multiIndexArrayLocations = ArrayUtils.generateMultiIndexArrayLocations( - this, - ); + const multiIndexArrayLocations = + ArrayUtils.generateMultiIndexArrayLocations(this); // second run: map the index locations generated above to // the dataset so we have access to the multi index arrays // only. @@ -57,6 +58,11 @@ export class ViewBasedJSONModel extends MutableDataModel { retVal = []; } this._mergedCellLocations = retVal; + + // Creating merged cell groups from index locations + this._columnCellGroups = ArrayUtils.generateCellGroups( + this._mergedCellLocations, + ); } /** @@ -143,6 +149,43 @@ export class ViewBasedJSONModel extends MutableDataModel { return this.currentView.columnCount(region); } + /** + * Get the group count for each region + * @param region + * @returns + */ + groupCount(region: DataModel.RowRegion): number { + if (region === 'body') { + return 0; + } else if (region === 'column-header') { + return this._columnCellGroups.length; + } else if (region === 'row-header') { + return 2; + } + return 0; + } + + /** + * Specify merged cell groups for each region + * @param region + * @param groupIndex + * @returns + */ + group(region: DataModel.CellRegion, groupIndex: number): CellGroup | null { + if (region === 'column-header') { + return this._columnCellGroups[groupIndex]; + } + + if (region === 'row-header') { + return [ + { r1: 0, c1: 0, r2: 1, c2: 0 }, + { r1: 2, c1: 0, r2: 3, c2: 0 }, + ][groupIndex]; + } + + return null; + } + /** * Get the metadata for a column in the data model. * @@ -569,6 +612,7 @@ export class ViewBasedJSONModel extends MutableDataModel { protected _dataset: ViewBasedJSONModel.IData; protected readonly _transformState: TransformStateManager; private _mergedCellLocations: any[]; + private _columnCellGroups: CellGroup[]; } /** diff --git a/js/utils.ts b/js/utils.ts index bb89303b..ac0d6c78 100644 --- a/js/utils.ts +++ b/js/utils.ts @@ -1,4 +1,5 @@ const d3Color: any = require('d3-color'); +import { CellGroup } from '@lumino/datagrid'; export namespace ArrayUtils { /** @@ -94,6 +95,22 @@ export namespace ArrayUtils { } return true; } + + export function generateCellGroups(indexLists: number[][][][]): CellGroup[] { + const columnGroup = []; + for (let curRow = 0; curRow < indexLists.length; curRow++) { + for (let groupNum = 0; groupNum < indexLists[curRow].length; groupNum++) { + if (indexLists[curRow][groupNum].length > 1) { + const groupLength = indexLists[curRow][groupNum].length; + const c1 = indexLists[curRow][groupNum][0][1]; + const c2 = indexLists[curRow][groupNum][groupLength - 1][1]; + columnGroup.push({ r1: curRow, c1, r2: curRow, c2 }); + } + } + } + + return columnGroup; + } } // Scalar type From e9f789b62b9af325fefb3eea820938b37cffc354 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Thu, 27 May 2021 01:43:14 -0700 Subject: [PATCH 05/20] Add merged columns test Signed-off-by: Itay Dafna --- tests/js/arrayUtils.test.ts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tests/js/arrayUtils.test.ts b/tests/js/arrayUtils.test.ts index fdcd6b43..9b01db45 100644 --- a/tests/js/arrayUtils.test.ts +++ b/tests/js/arrayUtils.test.ts @@ -53,19 +53,19 @@ describe('Test multi index array utilities', () => { // Creating a model const testModel = new ViewBasedJSONModel(testData); // Generating an array with location of nested level headers - const mutltiIndexArrayLocations = ArrayUtils.generateMultiIndexArrayLocations( - testModel, - ); + const mutltiIndexArrayLocations = + ArrayUtils.generateMultiIndexArrayLocations(testModel); test('Test .generateMultiIndexArrayLocations()', async () => { expect(mutltiIndexArrayLocations).toEqual([2, 3, 4, 5, 6, 7]); }); // Generating an array with location of nested level headers - const nestedColumnDataGridIndices = ArrayUtils.generateDataGridMergedCellLocations( - testModel, - mutltiIndexArrayLocations, - ); + const nestedColumnDataGridIndices = + ArrayUtils.generateDataGridMergedCellLocations( + testModel, + mutltiIndexArrayLocations, + ); test('Test .mergedCellLocations()', async () => { expect(nestedColumnDataGridIndices).toEqual([ @@ -92,4 +92,15 @@ describe('Test multi index array utilities', () => { ArrayUtils.validateMergingHierarchy(nestedColumnDataGridIndices), ).toBe(true); }); + + test('Test .generateCellGroups()', async () => { + const expected = [ + { r1: 0, c1: 0, r2: 0, c2: 1 }, + { r1: 0, c1: 2, r2: 0, c2: 3 }, + { r1: 0, c1: 4, r2: 0, c2: 5 }, + ]; + + const actual = ArrayUtils.generateCellGroups(nestedColumnDataGridIndices); + expect(actual).toEqual(expected); + }); }); From 0c7388c6b0c3fc6785efdda74bf9e2ba98784b9f Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 31 May 2021 06:30:59 -0700 Subject: [PATCH 06/20] Add merged row groups logic to utils Signed-off-by: Itay Dafna --- js/utils.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/js/utils.ts b/js/utils.ts index ac0d6c78..82ceb293 100644 --- a/js/utils.ts +++ b/js/utils.ts @@ -32,7 +32,7 @@ export namespace ArrayUtils { * @param model the data model. * @param multiIndexArrayLocations index-based locations of all mutli-index coulmns. */ - export function generateDataGridMergedCellLocations( + export function generateColMergedCellLocations( model: any, multiIndexArrayLocations: number[], ): any[] { @@ -72,6 +72,44 @@ export namespace ArrayUtils { } return retArr; } + + export function generateRowMergedCellLocations(dataset: any): any { + // Removing internal primary key identifier. + const primaryKey = dataset.schema.primaryKey.slice( + 0, + dataset.schema.primaryKey.length - 1, + ); + + // Terminate if we're not dealing with nested row headers. + if (!(primaryKey.length > 1)) { + return []; + } + + const data = dataset.data; + const retArr = []; + let curCol = []; + + let prevVal = undefined; + for (let i = 0; i < primaryKey.length; i++) { + let curMergedRange: any = []; + for (let j = 0; j < data.length; j++) { + const curVal = data[j][primaryKey[i]]; + if (curMergedRange.length == 0 || prevVal == curVal) { + curMergedRange.push([j, i]); + } else { + curCol.push(curMergedRange); + curMergedRange = [[j, i]]; + } + prevVal = curVal; + } + curCol.push(curMergedRange); + retArr.push(curCol); + curCol = []; + } + + return retArr; + } + /** * Checks whether the merged cell ranges conform to a valid hierarchy. * @param retVal boolean @@ -96,7 +134,9 @@ export namespace ArrayUtils { return true; } - export function generateCellGroups(indexLists: number[][][][]): CellGroup[] { + export function generateColumnCellGroups( + indexLists: number[][][][], + ): CellGroup[] { const columnGroup = []; for (let curRow = 0; curRow < indexLists.length; curRow++) { for (let groupNum = 0; groupNum < indexLists[curRow].length; groupNum++) { @@ -113,6 +153,22 @@ export namespace ArrayUtils { } } +function generateRowCellGroups(indexLists: number[][][][]): CellGroup[] { + const rowGroup = []; + for (let curCol = 0; curCol < indexLists.length; curCol++) { + for (let groupNum = 0; groupNum < indexLists[curCol].length; groupNum++) { + if (indexLists[curCol][groupNum].length > 1) { + const groupLength = indexLists[curCol][groupNum].length; + const r1 = indexLists[curCol][groupNum][0][0]; + const r2 = indexLists[curCol][groupNum][groupLength - 1][0]; + rowGroup.push({ r1: r1, c1: curCol, r2: r2, c2: curCol }); + } + } + } + + return rowGroup; +} + // Scalar type export type Scalar = null | boolean | number | string; From 8b4c4cb4c69edd43719759cc5dba01520da75f5b Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 31 May 2021 13:04:53 -0700 Subject: [PATCH 07/20] Add more cell merging logic Signed-off-by: Itay Dafna --- js/core/viewbasedjsonmodel.ts | 39 ++++++++++++++---------- js/utils.ts | 56 +++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/js/core/viewbasedjsonmodel.ts b/js/core/viewbasedjsonmodel.ts index b9ac66b4..a47f2d3e 100644 --- a/js/core/viewbasedjsonmodel.ts +++ b/js/core/viewbasedjsonmodel.ts @@ -46,7 +46,7 @@ export class ViewBasedJSONModel extends MutableDataModel { // second run: map the index locations generated above to // the dataset so we have access to the multi index arrays // only. - let retVal = ArrayUtils.generateDataGridMergedCellLocations( + let mergedColumnLocations = ArrayUtils.generateColMergedCellLocations( this, multiIndexArrayLocations, ); @@ -54,15 +54,22 @@ export class ViewBasedJSONModel extends MutableDataModel { // want to render a merged range below a non-merged range. This function will check // that this requirement is met. If it is not, we simply render each cell individually // as if it wasn't grouped. - if (!ArrayUtils.validateMergingHierarchy(retVal)) { - retVal = []; + if (!ArrayUtils.validateMergingHierarchy(mergedColumnLocations)) { + mergedColumnLocations = []; } - this._mergedCellLocations = retVal; + this._mergedColumnCellLocations = mergedColumnLocations; - // Creating merged cell groups from index locations - this._columnCellGroups = ArrayUtils.generateCellGroups( - this._mergedCellLocations, + // Creating column merged cell groups from index locations + this._columnCellGroups = ArrayUtils.generateColumnCellGroups( + this._mergedColumnCellLocations, ); + + // Creating merged row cell groups + let mergedRowLocations = ArrayUtils.generateRowMergedCellLocations(this); + if (!ArrayUtils.validateMergingHierarchy(mergedColumnLocations)) { + mergedRowLocations = []; + } + this._rowCellGroups = ArrayUtils.generateRowCellGroups(mergedRowLocations); } /** @@ -112,11 +119,15 @@ export class ViewBasedJSONModel extends MutableDataModel { */ getMergedSiblingCells(cell: number[]): any[] { const [row, column] = cell; - if (row < 0 || column < 0 || row >= this._mergedCellLocations.length) { + if ( + row < 0 || + column < 0 || + row >= this._mergedColumnCellLocations.length + ) { return []; } - for (const cellGroup of this._mergedCellLocations[row]) { + for (const cellGroup of this._mergedColumnCellLocations[row]) { for (const rowCell of cellGroup) { const [rowIndex, columnIndex] = rowCell; if (row === rowIndex && column == columnIndex) { @@ -160,7 +171,7 @@ export class ViewBasedJSONModel extends MutableDataModel { } else if (region === 'column-header') { return this._columnCellGroups.length; } else if (region === 'row-header') { - return 2; + return this._rowCellGroups.length; } return 0; } @@ -177,10 +188,7 @@ export class ViewBasedJSONModel extends MutableDataModel { } if (region === 'row-header') { - return [ - { r1: 0, c1: 0, r2: 1, c2: 0 }, - { r1: 2, c1: 0, r2: 3, c2: 0 }, - ][groupIndex]; + return this._rowCellGroups[groupIndex]; } return null; @@ -611,7 +619,8 @@ export class ViewBasedJSONModel extends MutableDataModel { protected _dataset: ViewBasedJSONModel.IData; protected readonly _transformState: TransformStateManager; - private _mergedCellLocations: any[]; + private _mergedColumnCellLocations: any[]; + private _rowCellGroups: CellGroup[]; private _columnCellGroups: CellGroup[]; } diff --git a/js/utils.ts b/js/utils.ts index 82ceb293..e5d8f9c8 100644 --- a/js/utils.ts +++ b/js/utils.ts @@ -30,12 +30,12 @@ export namespace ArrayUtils { * Returns an array of [mergedCellSiblingGroup]. Each element represents a row of columns. * The 0th row will be the top level group, and the n-th will be the last. * @param model the data model. - * @param multiIndexArrayLocations index-based locations of all mutli-index coulmns. + * @param multiIndexArrayLocations index-based locations of all mutli-index columns. */ export function generateColMergedCellLocations( model: any, multiIndexArrayLocations: number[], - ): any[] { + ): number[][][][] { // Terminating if no locations are passed. if (multiIndexArrayLocations.length === 0) { return []; @@ -73,11 +73,17 @@ export namespace ArrayUtils { return retArr; } - export function generateRowMergedCellLocations(dataset: any): any { + /** + * Returns an array of [mergedCellSiblingGroup]. Each element represents a column of rows. + * The 0th row will be the top level group, and the n-th will be the last. + * @param model data model with schema and data fields + * @returns index-based locations of all mutli-index rows. + */ + export function generateRowMergedCellLocations(model: any): number[][][][] { // Removing internal primary key identifier. - const primaryKey = dataset.schema.primaryKey.slice( + const primaryKey = model._dataset.schema.primaryKey.slice( 0, - dataset.schema.primaryKey.length - 1, + model._dataset.schema.primaryKey.length - 1, ); // Terminate if we're not dealing with nested row headers. @@ -85,7 +91,7 @@ export namespace ArrayUtils { return []; } - const data = dataset.data; + const data = model._dataset.data; const retArr = []; let curCol = []; @@ -114,7 +120,7 @@ export namespace ArrayUtils { * Checks whether the merged cell ranges conform to a valid hierarchy. * @param retVal boolean */ - export function validateMergingHierarchy(retVal: number[][]): boolean { + export function validateMergingHierarchy(retVal: number[][][][]): boolean { let prevLevelLength; for (const mergeRange of retVal) { // First element - setting up the value of prevLevelLength @@ -134,6 +140,11 @@ export namespace ArrayUtils { return true; } + /** + * Generates a list of merged column cell groups for use in the data model. + * @param indexLists index-based location of merged columns + * @returns CellGroup[] + */ export function generateColumnCellGroups( indexLists: number[][][][], ): CellGroup[] { @@ -151,22 +162,29 @@ export namespace ArrayUtils { return columnGroup; } -} -function generateRowCellGroups(indexLists: number[][][][]): CellGroup[] { - const rowGroup = []; - for (let curCol = 0; curCol < indexLists.length; curCol++) { - for (let groupNum = 0; groupNum < indexLists[curCol].length; groupNum++) { - if (indexLists[curCol][groupNum].length > 1) { - const groupLength = indexLists[curCol][groupNum].length; - const r1 = indexLists[curCol][groupNum][0][0]; - const r2 = indexLists[curCol][groupNum][groupLength - 1][0]; - rowGroup.push({ r1: r1, c1: curCol, r2: r2, c2: curCol }); + /** + * Generates a list of merged row cell groups for use in the data model. + * @param indexLists index-based location of merged rows. + * @returns CellGroup[] + */ + export function generateRowCellGroups( + indexLists: number[][][][], + ): CellGroup[] { + const rowGroup = []; + for (let curCol = 0; curCol < indexLists.length; curCol++) { + for (let groupNum = 0; groupNum < indexLists[curCol].length; groupNum++) { + if (indexLists[curCol][groupNum].length > 1) { + const groupLength = indexLists[curCol][groupNum].length; + const r1 = indexLists[curCol][groupNum][0][0]; + const r2 = indexLists[curCol][groupNum][groupLength - 1][0]; + rowGroup.push({ r1: r1, c1: curCol, r2: r2, c2: curCol }); + } } } - } - return rowGroup; + return rowGroup; + } } // Scalar type From 80790ecc9074dfec3b72ce5a190fe3c704d3e27a Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 14 Jun 2021 13:47:19 -0700 Subject: [PATCH 08/20] Remove local DataGrid fork Signed-off-by: Itay Dafna --- js/core/headerRenderer.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/js/core/headerRenderer.ts b/js/core/headerRenderer.ts index 90523d7b..80ed4bf8 100644 --- a/js/core/headerRenderer.ts +++ b/js/core/headerRenderer.ts @@ -6,7 +6,7 @@ import { Theme } from '../utils'; import { TransformStateManager } from './transformStateManager'; -import { DataGrid } from './datagrid'; +import { DataGrid } from '@lumino/datagrid'; /** * A custom cell renderer for headers that provides a menu icon. @@ -266,9 +266,8 @@ export class HeaderRenderer extends TextRenderer { config.column, ); - const colMetaData: - | TransformStateManager.IColumn - | undefined = this.model.transformMetadata(schemaIndex); + const colMetaData: TransformStateManager.IColumn | undefined = + this.model.transformMetadata(schemaIndex); // Fill filter icon if filter applied if (colMetaData && colMetaData['filter']) { From 68b0fe05d57ac6193d3dfe859c9cd6aa4775066e Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Mon, 21 Jun 2021 18:40:53 -0700 Subject: [PATCH 09/20] Appease ESLint Signed-off-by: Itay Dafna --- js/core/barrenderer.ts | 9 ++------- js/feathergrid.ts | 16 +++++++++------- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/js/core/barrenderer.ts b/js/core/barrenderer.ts index 7140bae6..d861a522 100644 --- a/js/core/barrenderer.ts +++ b/js/core/barrenderer.ts @@ -77,13 +77,8 @@ export class BarRenderer extends TextRenderer { */ prepare(gc: GraphicsContext, config: CellRenderer.CellConfig): void { // Look up the default state from the renderer. - const { - font, - textColor, - barColor, - backgroundColor, - horizontalAlignment, - } = this; + const { font, textColor, barColor, backgroundColor, horizontalAlignment } = + this; // Set up the default font. if (font && typeof font === 'string') { diff --git a/js/feathergrid.ts b/js/feathergrid.ts index 40d7d266..393083ef 100644 --- a/js/feathergrid.ts +++ b/js/feathergrid.ts @@ -245,11 +245,11 @@ export class FeatherGrid extends Widget { messageHook(handler: IMessageHandler, msg: Message): boolean { if (handler === this.grid.viewport) { // //@ts-ignore added so we don't have to add basicmousehandler.ts fork - const mouseHandler = (this.grid - .mouseHandler as unknown) as FeatherGridMouseHandler; + const mouseHandler = this.grid + .mouseHandler as unknown as FeatherGridMouseHandler; if (msg.type === 'column-resize-request' && mouseHandler.mouseIsDown) { - const resizeMsg = (msg as unknown) as FeatherGridColumnResizeMessage; + const resizeMsg = msg as unknown as FeatherGridColumnResizeMessage; const columnName: string = this.dataModel.columnIndexToName( resizeMsg.index, resizeMsg.region, @@ -869,7 +869,8 @@ export class FeatherGrid extends Widget { iconClass: 'ipydatagrid-filterMenuIcon ipydatagrid-filterMenuIcon-sortAsc', execute: (args): void => { - const cellClick: FeatherGridContextMenu.CommandArgs = args as FeatherGridContextMenu.CommandArgs; + const cellClick: FeatherGridContextMenu.CommandArgs = + args as FeatherGridContextMenu.CommandArgs; const colIndex = this._dataModel.getSchemaIndex( cellClick.region, cellClick.columnIndex, @@ -887,7 +888,8 @@ export class FeatherGrid extends Widget { iconClass: 'ipydatagrid-filterMenuIcon ipydatagrid-filterMenuIcon-sortDesc', execute: (args) => { - const cellClick: FeatherGridContextMenu.CommandArgs = args as FeatherGridContextMenu.CommandArgs; + const cellClick: FeatherGridContextMenu.CommandArgs = + args as FeatherGridContextMenu.CommandArgs; const colIndex = this._dataModel.getSchemaIndex( cellClick.region, cellClick.columnIndex, @@ -917,8 +919,8 @@ export class FeatherGrid extends Widget { label: 'Clear Filters in All Columns', mnemonic: -1, execute: (args) => { - const activeTransforms: Transform.TransformSpec[] = this._dataModel - .activeTransforms; + const activeTransforms: Transform.TransformSpec[] = + this._dataModel.activeTransforms; const newTransforms = activeTransforms.filter( (val) => val.type !== 'filter', ); diff --git a/package-lock.json b/package-lock.json index 3ba32342..2ead6ee8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ipydatagrid", - "version": "1.0.6", + "version": "1.0.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d8db7461..6f9f26a5 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@lumino/algorithm": "^1.6.0", "@lumino/commands": "^1.15.0", "@lumino/coreutils": "^1.8.0", - "@lumino/datagrid": "^0.25.0", + "@lumino/datagrid": "^0.25.1", "@lumino/default-theme": "^0.14.0", "@lumino/domutils": "^1.5.0", "@lumino/messaging": "^1.7.0", From f5411aba1076c181c79eb31ba49ec47d8cb96b4a Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 12:12:25 -0700 Subject: [PATCH 10/20] Update GH actions/ESLint version Signed-off-by: Itay Dafna --- .github/workflows/check.yml | 5 ++--- .pre-commit-config.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 17189d52..2ec1381b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,7 +1,6 @@ name: check -on: - push: - pull_request: + +on: [push, pull_request] jobs: lint: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c08875e7..0015fc76 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,17 +41,17 @@ repos: - id: tox-ini-fmt args: ['-p', 'fix_lint'] - repo: https://github.com/pre-commit/mirrors-eslint - rev: 'v7.19.0' + rev: 'v7.29.0' hooks: - id: eslint files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx types: [file] args: ['--fix'] additional_dependencies: - - eslint@7.19.0 - - eslint-config-prettier@7.2.0 # prettier used with eslint directly - - eslint-plugin-prettier@3.3.1 + - eslint@7.29.0 + - eslint-config-prettier@8.3.0 # prettier used with eslint directly + - eslint-plugin-prettier@3.4.0 - typescript@4.1.4 - - prettier@2.2.1 + - prettier@2.3.1 - '@typescript-eslint/eslint-plugin' - '@typescript-eslint/parser' From 9104b2ed6af3a10f35aadb422a5f29cb2af010da Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 12:20:44 -0700 Subject: [PATCH 11/20] Fix merged column region test Signed-off-by: Itay Dafna --- tests/js/arrayUtils.test.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/js/arrayUtils.test.ts b/tests/js/arrayUtils.test.ts index 9b01db45..8af175b3 100644 --- a/tests/js/arrayUtils.test.ts +++ b/tests/js/arrayUtils.test.ts @@ -61,11 +61,10 @@ describe('Test multi index array utilities', () => { }); // Generating an array with location of nested level headers - const nestedColumnDataGridIndices = - ArrayUtils.generateDataGridMergedCellLocations( - testModel, - mutltiIndexArrayLocations, - ); + const nestedColumnDataGridIndices = ArrayUtils.generateColMergedCellLocations( + testModel, + mutltiIndexArrayLocations, + ); test('Test .mergedCellLocations()', async () => { expect(nestedColumnDataGridIndices).toEqual([ @@ -100,7 +99,9 @@ describe('Test multi index array utilities', () => { { r1: 0, c1: 4, r2: 0, c2: 5 }, ]; - const actual = ArrayUtils.generateCellGroups(nestedColumnDataGridIndices); + const actual = ArrayUtils.generateColumnCellGroups( + nestedColumnDataGridIndices, + ); expect(actual).toEqual(expected); }); }); From 1afca54a97da53523b5f5b74e048c13bda742d28 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 12:29:22 -0700 Subject: [PATCH 12/20] Rename tests to reflect columns vs rows Signed-off-by: Itay Dafna --- tests/js/arrayUtils.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/js/arrayUtils.test.ts b/tests/js/arrayUtils.test.ts index 8af175b3..ecb3085b 100644 --- a/tests/js/arrayUtils.test.ts +++ b/tests/js/arrayUtils.test.ts @@ -66,7 +66,7 @@ describe('Test multi index array utilities', () => { mutltiIndexArrayLocations, ); - test('Test .mergedCellLocations()', async () => { + test('Test .generateColMergedCellLocations()', async () => { expect(nestedColumnDataGridIndices).toEqual([ [ [ @@ -86,13 +86,13 @@ describe('Test multi index array utilities', () => { ]); }); - test('Test .validateMergingHierarchy()', async () => { + test('Test .validateMergingHierarchy() for nested columns', async () => { expect( ArrayUtils.validateMergingHierarchy(nestedColumnDataGridIndices), ).toBe(true); }); - test('Test .generateCellGroups()', async () => { + test('Test .generateColumnCellGroups()', async () => { const expected = [ { r1: 0, c1: 0, r2: 0, c2: 1 }, { r1: 0, c1: 2, r2: 0, c2: 3 }, From e93fcc4f16d7871c01d5fb9d3374e3dfd22ab156 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 12:40:42 -0700 Subject: [PATCH 13/20] Update ESLint config Signed-off-by: Itay Dafna --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index ce17a45d..62659010 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,8 +6,8 @@ module.exports = { }, extends: [ 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from @typescript-eslint/eslint-plugin - 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + 'prettier', ], rules: { // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs From 3bb7593770b73b1c20da66498574e64b1f7a3260 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 20:10:49 -0700 Subject: [PATCH 14/20] Delete datagrid.ts fork file Signed-off-by: Itay Dafna --- js/core/datagrid.ts | 6166 ------------------------------------------- 1 file changed, 6166 deletions(-) delete mode 100644 js/core/datagrid.ts diff --git a/js/core/datagrid.ts b/js/core/datagrid.ts deleted file mode 100644 index 04f656b1..00000000 --- a/js/core/datagrid.ts +++ /dev/null @@ -1,6166 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2019, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { - toArray -} from '@lumino/algorithm'; - -import { - IDisposable -} from '@lumino/disposable'; - -import { - ClipboardExt, ElementExt, Platform -} from '@lumino/domutils'; - -import { - ConflatableMessage, IMessageHandler, Message, MessageLoop -} from '@lumino/messaging'; - -import { - GridLayout, ScrollBar, Widget -} from '@lumino/widgets'; - -import { - CellRenderer -} from '@lumino/datagrid'; - -import { - DataModel, MutableDataModel -} from '@lumino/datagrid'; - -import { - GraphicsContext -} from '@lumino/datagrid'; - -import { - RendererMap -} from '@lumino/datagrid'; - -import { - SectionList -} from '@lumino/datagrid'; - -import { - SelectionModel -} from '@lumino/datagrid'; - -import { - ICellEditorController, - CellEditorController -} from '@lumino/datagrid'; - -import { ViewBasedJSONModel } from './viewbasedjsonmodel'; - -/** - * A widget which implements a high-performance tabular data grid. - * - * #### Notes - * A data grid is implemented as a composition of child widgets. These - * child widgets are considered an implementation detail. Manipulating - * the child widgets of a data grid directly is undefined behavior. - * - * This class is not designed to be subclassed. - */ -export -class DataGrid extends Widget { - /** - * Construct a new data grid. - * - * @param options - The options for initializing the data grid. - */ - constructor(options: DataGrid.IOptions = {}) { - super(); - this.addClass('lm-DataGrid'); - /* */ - this.addClass('p-DataGrid'); - /* */ - - // Parse the simple options. - this._style = options.style || DataGrid.defaultStyle; - this._stretchLastRow = options.stretchLastRow || false; - this._stretchLastColumn = options.stretchLastColumn || false; - this._headerVisibility = options.headerVisibility || 'all'; - this._cellRenderers = options.cellRenderers || new RendererMap(); - this._copyConfig = options.copyConfig || DataGrid.defaultCopyConfig; - - // Connect to the renderer map changed signal. - this._cellRenderers.changed.connect(this._onRenderersChanged, this); - - // Parse the default sizes. - let defaultSizes = options.defaultSizes || DataGrid.defaultSizes; - let minimumSizes = options.minimumSizes || DataGrid.minimumSizes; - - // Set up the sections lists. - this._rowSections = new SectionList({ defaultSize: defaultSizes.rowHeight, - minimumSize: minimumSizes.rowHeight }); - this._columnSections = new SectionList({ defaultSize: defaultSizes.columnWidth, - minimumSize: minimumSizes.columnWidth}); - this._rowHeaderSections = new SectionList({ defaultSize: defaultSizes.rowHeaderWidth, - minimumSize: minimumSizes.rowHeaderWidth}); - this._columnHeaderSections = new SectionList({ defaultSize: defaultSizes.columnHeaderHeight, - minimumSize: minimumSizes.columnHeaderHeight}); - - // Create the canvas, buffer, and overlay objects. - this._canvas = Private.createCanvas(); - this._buffer = Private.createCanvas(); - this._overlay = Private.createCanvas(); - - // Get the graphics contexts for the canvases. - this._canvasGC = this._canvas.getContext('2d')!; - this._bufferGC = this._buffer.getContext('2d')!; - this._overlayGC = this._overlay.getContext('2d')!; - - // Set up the on-screen canvas. - this._canvas.style.position = 'absolute'; - this._canvas.style.top = '0px'; - this._canvas.style.left = '0px'; - this._canvas.style.width = '0px'; - this._canvas.style.height = '0px'; - - // Set up the on-screen overlay. - this._overlay.style.position = 'absolute'; - this._overlay.style.top = '0px'; - this._overlay.style.left = '0px'; - this._overlay.style.width = '0px'; - this._overlay.style.height = '0px'; - - // Create the internal widgets for the data grid. - this._viewport = new Widget(); - this._viewport.node.tabIndex = -1; - this._viewport.node.style.outline = 'none'; - this._vScrollBar = new ScrollBar({ orientation: 'vertical' }); - this._hScrollBar = new ScrollBar({ orientation: 'horizontal' }); - this._scrollCorner = new Widget(); - - this._editorController = new CellEditorController(); - - // Add the extra class names to the child widgets. - this._viewport.addClass('lm-DataGrid-viewport'); - this._vScrollBar.addClass('lm-DataGrid-scrollBar'); - this._hScrollBar.addClass('lm-DataGrid-scrollBar'); - this._scrollCorner.addClass('lm-DataGrid-scrollCorner'); - /* */ - this._viewport.addClass('p-DataGrid-viewport'); - this._vScrollBar.addClass('p-DataGrid-scrollBar'); - this._hScrollBar.addClass('p-DataGrid-scrollBar'); - this._scrollCorner.addClass('p-DataGrid-scrollCorner'); - /* */ - - // Add the on-screen canvas to the viewport node. - this._viewport.node.appendChild(this._canvas); - - // Add the on-screen overlay to the viewport node. - this._viewport.node.appendChild(this._overlay); - - // Install the message hooks. - MessageLoop.installMessageHook(this._viewport, this); - MessageLoop.installMessageHook(this._hScrollBar, this); - MessageLoop.installMessageHook(this._vScrollBar, this); - - // Hide the scroll bars and corner from the outset. - this._vScrollBar.hide(); - this._hScrollBar.hide(); - this._scrollCorner.hide(); - - // Connect to the scroll bar signals. - this._vScrollBar.thumbMoved.connect(this._onThumbMoved, this); - this._hScrollBar.thumbMoved.connect(this._onThumbMoved, this); - this._vScrollBar.pageRequested.connect(this._onPageRequested, this); - this._hScrollBar.pageRequested.connect(this._onPageRequested, this); - this._vScrollBar.stepRequested.connect(this._onStepRequested, this); - this._hScrollBar.stepRequested.connect(this._onStepRequested, this); - - // Set the layout cell config for the child widgets. - GridLayout.setCellConfig(this._viewport, { row: 0, column: 0 }); - GridLayout.setCellConfig(this._vScrollBar, { row: 0, column: 1 }); - GridLayout.setCellConfig(this._hScrollBar, { row: 1, column: 0 }); - GridLayout.setCellConfig(this._scrollCorner, { row: 1, column: 1 }); - - // Create the layout for the data grid. - let layout = new GridLayout({ - rowCount: 2, - columnCount: 2, - rowSpacing: 0, - columnSpacing: 0, - fitPolicy: 'set-no-constraint' - }); - - // Set the stretch factors for the grid. - layout.setRowStretch(0, 1); - layout.setRowStretch(1, 0); - layout.setColumnStretch(0, 1); - layout.setColumnStretch(1, 0); - - // Add the child widgets to the layout. - layout.addWidget(this._viewport); - layout.addWidget(this._vScrollBar); - layout.addWidget(this._hScrollBar); - layout.addWidget(this._scrollCorner); - - // Install the layout on the data grid. - this.layout = layout; - } - - /** - * Dispose of the resources held by the widgets. - */ - dispose(): void { - // Release the mouse. - this._releaseMouse(); - - // Dispose of the handlers. - if (this._keyHandler) { - this._keyHandler.dispose(); - } - if (this._mouseHandler) { - this._mouseHandler.dispose(); - } - this._keyHandler = null; - this._mouseHandler = null; - - // Clear the models. - this._dataModel = null; - this._selectionModel = null; - - // Clear the section lists. - this._rowSections.clear(); - this._columnSections.clear(); - this._rowHeaderSections.clear(); - this._columnHeaderSections.clear(); - - // Dispose of the base class. - super.dispose(); - } - - /** - * Get the data model for the data grid. - */ - get dataModel(): DataModel | null { - return this._dataModel; - } - - /** - * Set the data model for the data grid. - * - * #### Notes - * This will automatically remove the current selection model. - */ - set dataModel(value: DataModel | null) { - // Do nothing if the model does not change. - if (this._dataModel === value) { - return; - } - - // Release the mouse. - this._releaseMouse(); - - // Clear the selection model. - this.selectionModel = null; - - // Disconnect the change handler from the old model. - if (this._dataModel) { - this._dataModel.changed.disconnect(this._onDataModelChanged, this); - } - - // Connect the change handler for the new model. - if (value) { - value.changed.connect(this._onDataModelChanged, this); - } - - // Update the internal model reference. - this._dataModel = value; - - // Clear the section lists. - this._rowSections.clear(); - this._columnSections.clear(); - this._rowHeaderSections.clear(); - this._columnHeaderSections.clear(); - - // Populate the section lists. - if (value) { - this._rowSections.insert(0, value.rowCount('body')); - this._columnSections.insert(0, value.columnCount('body')); - this._rowHeaderSections.insert(0, value.columnCount('row-header')); - this._columnHeaderSections.insert(0, value.rowCount('column-header')); - } - - // Reset the scroll position. - this._scrollX = 0; - this._scrollY = 0; - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Get the selection model for the data grid. - */ - get selectionModel(): SelectionModel | null { - return this._selectionModel; - } - - /** - * Set the selection model for the data grid. - */ - set selectionModel(value: SelectionModel | null) { - // Do nothing if the selection model does not change. - if (this._selectionModel === value) { - return; - } - - // Release the mouse. - this._releaseMouse(); - - // Ensure the data models are a match. - if (value && value.dataModel !== this._dataModel) { - throw new Error('SelectionModel.dataModel !== DataGrid.dataModel'); - } - - // Disconnect the change handler from the old model. - if (this._selectionModel) { - this._selectionModel.changed.disconnect(this._onSelectionsChanged, this); - } - - // Connect the change handler for the new model. - if (value) { - value.changed.connect(this._onSelectionsChanged, this); - } - - // Update the internal selection model reference. - this._selectionModel = value; - - // Schedule a repaint of the overlay. - this.repaintOverlay(); - } - - /** - * Get the key handler for the data grid. - */ - get keyHandler(): DataGrid.IKeyHandler | null { - return this._keyHandler; - } - - /** - * Set the key handler for the data grid. - */ - set keyHandler(value: DataGrid.IKeyHandler | null) { - this._keyHandler = value; - } - - /** - * Get the mouse handler for the data grid. - */ - get mouseHandler(): DataGrid.IMouseHandler | null { - return this._mouseHandler; - } - - /** - * Set the mouse handler for the data grid. - */ - set mouseHandler(value: DataGrid.IMouseHandler | null) { - // Bail early if the mouse handler does not change. - if (this._mouseHandler === value) { - return; - } - - // Release the mouse. - this._releaseMouse(); - - // Update the internal mouse handler. - this._mouseHandler = value; - } - - /** - * Get the style for the data grid. - */ - get style(): DataGrid.Style { - return this._style; - } - - /** - * Set the style for the data grid. - */ - set style(value: DataGrid.Style) { - // Bail if the style does not change. - if (this._style === value) { - return; - } - - // Update the internal style. - this._style = { ...value }; - - // Schedule a repaint of the content. - this.repaintContent(); - - // Schedule a repaint of the overlay. - this.repaintOverlay(); - } - - /** - * Get the cell renderer map for the data grid. - */ - get cellRenderers(): RendererMap { - return this._cellRenderers; - } - - /** - * Set the cell renderer map for the data grid. - */ - set cellRenderers(value: RendererMap) { - // Bail if the renderer map does not change. - if (this._cellRenderers === value) { - return; - } - - // Disconnect the old map. - this._cellRenderers.changed.disconnect(this._onRenderersChanged, this); - - // Connect the new map. - value.changed.connect(this._onRenderersChanged, this); - - // Update the internal renderer map. - this._cellRenderers = value; - - // Schedule a repaint of the grid content. - this.repaintContent(); - } - - /** - * Get the header visibility for the data grid. - */ - get headerVisibility(): DataGrid.HeaderVisibility { - return this._headerVisibility; - } - - /** - * Set the header visibility for the data grid. - */ - set headerVisibility(value: DataGrid.HeaderVisibility) { - // Bail if the visibility does not change. - if (this._headerVisibility === value) { - return; - } - - // Update the internal visibility. - this._headerVisibility = value; - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Get the default sizes for the various sections of the data grid. - */ - get defaultSizes(): DataGrid.DefaultSizes { - let rowHeight = this._rowSections.defaultSize; - let columnWidth = this._columnSections.defaultSize; - let rowHeaderWidth = this._rowHeaderSections.defaultSize; - let columnHeaderHeight = this._columnHeaderSections.defaultSize; - return { rowHeight, columnWidth, rowHeaderWidth, columnHeaderHeight }; - } - - /** - * Set the default sizes for the various sections of the data grid. - */ - set defaultSizes(value: DataGrid.DefaultSizes) { - // Update the section default sizes. - this._rowSections.defaultSize = value.rowHeight; - this._columnSections.defaultSize = value.columnWidth; - this._rowHeaderSections.defaultSize = value.rowHeaderWidth; - this._columnHeaderSections.defaultSize = value.columnHeaderHeight; - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Get the minimum sizes for the various sections of the data grid. - */ - get minimumSizes(): DataGrid.DefaultSizes { - let rowHeight = this._rowSections.minimumSize; - let columnWidth = this._columnSections.minimumSize; - let rowHeaderWidth = this._rowHeaderSections.minimumSize; - let columnHeaderHeight = this._columnHeaderSections.minimumSize; - return { rowHeight, columnWidth, rowHeaderWidth, columnHeaderHeight }; - } - - /** - * Set the minimum sizes for the various sections of the data grid. - */ - set minimumSizes(value: DataGrid.DefaultSizes) { - // Update the section default sizes. - this._rowSections.minimumSize = value.rowHeight; - this._columnSections.minimumSize = value.columnWidth; - this._rowHeaderSections.minimumSize = value.rowHeaderWidth; - this._columnHeaderSections.minimumSize = value.columnHeaderHeight; - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Get the copy configuration for the data grid. - */ - get copyConfig(): DataGrid.CopyConfig { - return this._copyConfig; - } - - /** - * Set the copy configuration for the data grid. - */ - set copyConfig(value: DataGrid.CopyConfig) { - this._copyConfig = value; - } - - /** - * Get whether the last row is stretched. - */ - get stretchLastRow(): boolean { - return this._stretchLastRow; - } - - /** - * Set whether the last row is stretched. - */ - set stretchLastRow(value: boolean) { - // Bail early if the value does not change. - if (value === this._stretchLastRow) { - return; - } - - // Update the internal value. - this._stretchLastRow = value; - - // Sync the viewport - this._syncViewport(); - } - - /** - * Get whether the last column is stretched. - */ - get stretchLastColumn(): boolean { - return this._stretchLastColumn; - } - - /** - * Set whether the last column is stretched. - */ - set stretchLastColumn(value: boolean) { - // Bail early if the value does not change. - if (value === this._stretchLastColumn) { - return; - } - - // Update the internal value. - this._stretchLastColumn = value; - - // Sync the viewport - this._syncViewport(); - } - - /** - * The virtual width of the row headers. - */ - get headerWidth(): number { - if (this._headerVisibility === 'none') { - return 0; - } - if (this._headerVisibility === 'column') { - return 0; - } - return this._rowHeaderSections.length; - } - - /** - * The virtual height of the column headers. - */ - get headerHeight(): number { - if (this._headerVisibility === 'none') { - return 0; - } - if (this._headerVisibility === 'row') { - return 0; - } - return this._columnHeaderSections.length; - } - - /** - * The virtual width of the grid body. - * - * #### Notes - * This does *not* account for a stretched last column. - */ - get bodyWidth(): number { - return this._columnSections.length; - } - - /** - * The virtual height of the grid body. - * - * #### Notes - * This does *not* account for a stretched last row. - */ - get bodyHeight(): number { - return this._rowSections.length; - } - - /** - * The virtual width of the entire grid. - * - * #### Notes - * This does *not* account for a stretched last column. - */ - get totalWidth(): number { - return this.headerWidth + this.bodyWidth; - } - - /** - * The virtual height of the entire grid. - * - * #### Notes - * This does *not* account for a stretched last row. - */ - get totalHeight(): number { - return this.headerHeight + this.bodyHeight; - } - - /** - * The actual width of the viewport. - */ - get viewportWidth(): number { - return this._viewportWidth; - } - - /** - * The actual height of the viewport. - */ - get viewportHeight(): number { - return this._viewportHeight; - } - - /** - * The width of the visible portion of the grid body. - */ - get pageWidth(): number { - return Math.max(0, this.viewportWidth - this.headerWidth); - } - - /** - * The height of the visible portion of the grid body. - */ - get pageHeight(): number { - return Math.max(0, this.viewportHeight - this.headerHeight); - } - - /** - * The current scroll X position of the viewport. - */ - get scrollX(): number { - return this._hScrollBar.value; - } - - /** - * The current scroll Y position of the viewport. - */ - get scrollY(): number { - return this._vScrollBar.value; - } - - /** - * The maximum scroll X position for the grid. - */ - get maxScrollX(): number { - return Math.max(0, this.bodyWidth - this.pageWidth - 1); - } - - /** - * The maximum scroll Y position for the grid. - */ - get maxScrollY(): number { - return Math.max(0, this.bodyHeight - this.pageHeight - 1); - } - - /** - * The viewport widget for the data grid. - */ - get viewport(): Widget { - return this._viewport; - } - - /** - * The cell editor controller object for the data grid. - */ - get editorController(): ICellEditorController | null { - return this._editorController; - } - - set editorController(controller: ICellEditorController | null) { - this._editorController = controller; - } - - /** - * Whether the cell editing is enabled for the data grid. - */ - get editingEnabled(): boolean { - return this._editingEnabled; - } - - set editingEnabled(enabled: boolean) { - this._editingEnabled = enabled; - } - - /** - * Whether the grid cells are editable. - * - * `editingEnabled` flag must be on and grid must have required - * selection model, editor controller and data model properties. - */ - get editable(): boolean { - return this._editingEnabled && - this._selectionModel !== null && - this._editorController !== null && - this.dataModel instanceof MutableDataModel; - } - - /** - * The rendering context for painting the data grid. - */ - protected get canvasGC(): CanvasRenderingContext2D { - return this._canvasGC; - } - - /** - * The row sections of the data grid. - */ - protected get rowSections(): SectionList { - return this._rowSections; - } - - /** - * The column sections of the data grid. - */ - protected get columnSections(): SectionList { - return this._columnSections; - } - - /** - * The row header sections of the data grid. - */ - protected get rowHeaderSections(): SectionList { - return this._rowHeaderSections; - } - - /** - * The column header sections of the data grid. - */ - protected get columnHeaderSections(): SectionList { - return this._columnHeaderSections; - } - - /** - * Scroll the grid to the specified row. - * - * @param row - The row index of the cell. - * - * #### Notes - * This is a no-op if the row is already visible. - */ - scrollToRow(row: number): void { - // Fetch the row count. - let nr = this._rowSections.count; - - // Bail early if there is no content. - if (nr === 0) { - return; - } - - // Floor the row index. - row = Math.floor(row); - - // Clamp the row index. - row = Math.max(0, Math.min(row, nr - 1)); - - // Get the virtual bounds of the row. - let y1 = this._rowSections.offsetOf(row); - let y2 = this._rowSections.extentOf(row); - - // Get the virtual bounds of the viewport. - let vy1 = this._scrollY; - let vy2 = this._scrollY + this.pageHeight - 1; - - // Set up the delta variables. - let dy = 0; - - // Compute the delta Y scroll. - if (y1 < vy1) { - dy = y1 - vy1 - 10; - } else if (y2 > vy2) { - dy = y2 - vy2 + 10; - } - - // Bail early if no scroll is needed. - if (dy === 0) { - return; - } - - // Scroll by the computed delta. - this.scrollBy(0, dy); - } - - /** - * Scroll the grid to the specified column. - * - * @param column - The column index of the cell. - * - * #### Notes - * This is a no-op if the column is already visible. - */ - scrollToColumn(column: number): void { - // Fetch the column count. - let nc = this._columnSections.count; - - // Bail early if there is no content. - if (nc === 0) { - return; - } - - // Floor the column index. - column = Math.floor(column); - - // Clamp the column index. - column = Math.max(0, Math.min(column, nc - 1)); - - // Get the virtual bounds of the column. - let x1 = this._columnSections.offsetOf(column); - let x2 = this._columnSections.extentOf(column); - - // Get the virtual bounds of the viewport. - let vx1 = this._scrollX; - let vx2 = this._scrollX + this.pageWidth - 1; - - // Set up the delta variables. - let dx = 0; - - // Compute the delta X scroll. - if (x1 < vx1) { - dx = x1 - vx1 - 10; - } else if (x2 > vx2) { - dx = x2 - vx2 + 10; - } - - // Bail early if no scroll is needed. - if (dx === 0) { - return; - } - - // Scroll by the computed delta. - this.scrollBy(dx, 0); - } - - /** - * Scroll the grid to the specified cell. - * - * @param row - The row index of the cell. - * - * @param column - The column index of the cell. - * - * #### Notes - * This is a no-op if the cell is already visible. - */ - scrollToCell(row: number, column: number): void { - // Fetch the row and column count. - let nr = this._rowSections.count; - let nc = this._columnSections.count; - - // Bail early if there is no content. - if (nr === 0 || nc === 0) { - return; - } - - // Floor the cell index. - row = Math.floor(row); - column = Math.floor(column); - - // Clamp the cell index. - row = Math.max(0, Math.min(row, nr - 1)); - column = Math.max(0, Math.min(column, nc - 1)); - - // Get the virtual bounds of the cell. - let x1 = this._columnSections.offsetOf(column); - let x2 = this._columnSections.extentOf(column); - let y1 = this._rowSections.offsetOf(row); - let y2 = this._rowSections.extentOf(row); - - // Get the virtual bounds of the viewport. - let vx1 = this._scrollX; - let vx2 = this._scrollX + this.pageWidth - 1; - let vy1 = this._scrollY; - let vy2 = this._scrollY + this.pageHeight - 1; - - // Set up the delta variables. - let dx = 0; - let dy = 0; - - // Compute the delta X scroll. - if (x1 < vx1) { - dx = x1 - vx1 - 10; - } else if (x2 > vx2) { - dx = x2 - vx2 + 10; - } - - // Compute the delta Y scroll. - if (y1 < vy1) { - dy = y1 - vy1 - 10; - } else if (y2 > vy2) { - dy = y2 - vy2 + 10; - } - - // Bail early if no scroll is needed. - if (dx === 0 && dy === 0) { - return; - } - - // Scroll by the computed delta. - this.scrollBy(dx, dy); - } - - /** - * Move cursor down/up/left/right while making sure it remains - * within the bounds of selected rectangles - * - * @param direction - The direction of the movement. - */ - moveCursor(direction: SelectionModel.CursorMoveDirection): void { - // Bail early if there is no selection - if (!this.dataModel || - !this._selectionModel || - this._selectionModel.isEmpty) { - return; - } - - const iter = this._selectionModel.selections(); - const onlyOne = iter.next() && !iter.next(); - - // if there is a single selection that is a single cell selection - // then move the selection and cursor within grid bounds - if (onlyOne) { - const currentSel = this._selectionModel.currentSelection()!; - if (currentSel.r1 === currentSel.r2 && - currentSel.c1 === currentSel.c2 - ) { - const dr = direction === 'down' ? 1 : direction === 'up' ? -1 : 0; - const dc = direction === 'right' ? 1 : direction === 'left' ? -1 : 0; - let newRow = currentSel.r1 + dr; - let newColumn = currentSel.c1 + dc; - const rowCount = this.dataModel.rowCount('body'); - const columnCount = this.dataModel.columnCount('body'); - if (newRow >= rowCount) { - newRow = 0; - newColumn += 1; - } else if (newRow === -1) { - newRow = rowCount - 1; - newColumn -= 1; - } - if (newColumn >= columnCount) { - newColumn = 0; - newRow += 1; - if (newRow >= rowCount) { - newRow = 0; - } - } else if (newColumn === -1) { - newColumn = columnCount - 1; - newRow -= 1; - if (newRow === -1) { - newRow = rowCount - 1; - } - } - - this._selectionModel.select({ - r1: newRow, c1: newColumn, - r2: newRow, c2: newColumn, - cursorRow: newRow, cursorColumn: newColumn, - clear: 'all' - }); - - return; - } - } - - // if there are multiple selections, move cursor - // within selection rectangles - this._selectionModel.moveCursorWithinSelections(direction); - } - - /** - * Scroll the grid to the current cursor position. - * - * #### Notes - * This is a no-op if the cursor is already visible or - * if there is no selection model installed on the grid. - */ - scrollToCursor(): void { - // Bail early if there is no selection model. - if (!this._selectionModel) { - return; - } - - // Fetch the cursor row and column. - let row = this._selectionModel.cursorRow; - let column = this._selectionModel.cursorColumn; - - // Scroll to the cursor cell. - this.scrollToCell(row, column); - } - - /** - * Scroll the viewport by the specified amount. - * - * @param dx - The X scroll amount. - * - * @param dy - The Y scroll amount. - */ - scrollBy(dx: number, dy: number): void { - this.scrollTo(this.scrollX + dx, this.scrollY + dy); - } - - /** - * Scroll the viewport by one page. - * - * @param dir - The desired direction of the scroll. - */ - scrollByPage(dir: 'up' | 'down' | 'left' | 'right'): void { - let dx = 0; - let dy = 0; - switch (dir) { - case 'up': - dy = -this.pageHeight; - break; - case 'down': - dy = this.pageHeight; - break; - case 'left': - dx = -this.pageWidth; - break; - case 'right': - dx = this.pageWidth; - break; - default: - throw 'unreachable'; - } - this.scrollTo(this.scrollX + dx, this.scrollY + dy); - } - - /** - * Scroll the viewport by one cell-aligned step. - * - * @param dir - The desired direction of the scroll. - */ - scrollByStep(dir: 'up' | 'down' | 'left' | 'right'): void { - let r: number; - let c: number; - let x = this.scrollX; - let y = this.scrollY; - let rows = this._rowSections; - let columns = this._columnSections; - switch (dir) { - case 'up': - r = rows.indexOf(y - 1); - y = r < 0 ? y : rows.offsetOf(r); - break; - case 'down': - r = rows.indexOf(y); - y = r < 0 ? y : rows.offsetOf(r) + rows.sizeOf(r); - break; - case 'left': - c = columns.indexOf(x - 1); - x = c < 0 ? x : columns.offsetOf(c); - break; - case 'right': - c = columns.indexOf(x); - x = c < 0 ? x : columns.offsetOf(c) + columns.sizeOf(c); - break; - default: - throw 'unreachable'; - } - this.scrollTo(x, y); - } - - /** - * Scroll to the specified offset position. - * - * @param x - The desired X position. - * - * @param y - The desired Y position. - */ - scrollTo(x: number, y: number): void { - // Floor and clamp the position to the allowable range. - x = Math.max(0, Math.min(Math.floor(x), this.maxScrollX)); - y = Math.max(0, Math.min(Math.floor(y), this.maxScrollY)); - - // Update the scroll bar values with the desired position. - this._hScrollBar.value = x; - this._vScrollBar.value = y; - - // Post a scroll request message to the viewport. - MessageLoop.postMessage(this._viewport, Private.ScrollRequest); - } - - /** - * Get the row count for a particular region in the data grid. - * - * @param region - The row region of interest. - * - * @returns The row count for the specified region. - */ - rowCount(region: DataModel.RowRegion): number { - let count: number; - if (region === 'body') { - count = this._rowSections.count; - } else { - count = this._columnHeaderSections.count; - } - return count; - } - - /** - * Get the column count for a particular region in the data grid. - * - * @param region - The column region of interest. - * - * @returns The column count for the specified region. - */ - columnCount(region: DataModel.ColumnRegion): number { - let count: number; - if (region === 'body') { - count = this._columnSections.count; - } else { - count = this._rowHeaderSections.count; - } - return count; - } - - /** - * Get the row at a virtual offset in the data grid. - * - * @param region - The region which holds the row of interest. - * - * @param offset - The virtual offset of the row of interest. - * - * @returns The index of the row, or `-1` if the offset is out of range. - * - * #### Notes - * This method accounts for a stretched last row. - */ - rowAt(region: DataModel.RowRegion, offset: number): number { - // Bail early if the offset is negative. - if (offset < 0) { - return -1; - } - - // Return early for the column header region. - if (region === 'column-header') { - return this._columnHeaderSections.indexOf(offset); - } - - // Fetch the index. - let index = this._rowSections.indexOf(offset); - - // Return early if the section is found. - if (index >= 0) { - return index; - } - - // Bail early if the last row is not stretched. - if (!this._stretchLastRow) { - return -1; - } - - // Fetch the geometry. - let bh = this.bodyHeight; - let ph = this.pageHeight; - - // Bail early if no row stretching is required. - if (ph <= bh) { - return -1; - } - - // Bail early if the offset is out of bounds. - if (offset >= ph) { - return -1; - } - - // Otherwise, return the last row. - return this._rowSections.count - 1; - } - - /** - * Get the column at a virtual offset in the data grid. - * - * @param region - The region which holds the column of interest. - * - * @param offset - The virtual offset of the column of interest. - * - * @returns The index of the column, or `-1` if the offset is out of range. - * - * #### Notes - * This method accounts for a stretched last column. - */ - columnAt(region: DataModel.ColumnRegion, offset: number): number { - if (offset < 0) { - return -1; - } - - // Return early for the row header region. - if (region === 'row-header') { - return this._rowHeaderSections.indexOf(offset); - } - - // Fetch the index. - let index = this._columnSections.indexOf(offset); - - // Return early if the section is found. - if (index >= 0) { - return index; - } - - // Bail early if the last column is not stretched. - if (!this._stretchLastColumn) { - return -1; - } - - // Fetch the geometry. - let bw = this.bodyWidth; - let pw = this.pageWidth; - - // Bail early if no column stretching is required. - if (pw <= bw) { - return -1; - } - - // Bail early if the offset is out of bounds. - if (offset >= pw) { - return -1; - } - - // Otherwise, return the last column. - return this._columnSections.count - 1; - } - - /** - * Get the offset of a row in the data grid. - * - * @param region - The region which holds the row of interest. - * - * @param index - The index of the row of interest. - * - * @returns The offset of the row, or `-1` if the index is out of range. - * - * #### Notes - * A stretched last row has no effect on the return value. - */ - rowOffset(region: DataModel.RowRegion, index: number): number { - let offset: number; - if (region === 'body') { - offset = this._rowSections.offsetOf(index); - } else { - offset = this._columnHeaderSections.offsetOf(index); - } - return offset; - } - - /** - * Get the offset of a column in the data grid. - * - * @param region - The region which holds the column of interest. - * - * @param index - The index of the column of interest. - * - * @returns The offset of the column, or `-1` if the index is out of range. - * - * #### Notes - * A stretched last column has no effect on the return value. - */ - columnOffset(region: DataModel.ColumnRegion, index: number): number { - let offset: number; - if (region === 'body') { - offset = this._columnSections.offsetOf(index); - } else { - offset = this._rowHeaderSections.offsetOf(index); - } - return offset; - } - - /** - * Get the size of a row in the data grid. - * - * @param region - The region which holds the row of interest. - * - * @param index - The index of the row of interest. - * - * @returns The size of the row, or `-1` if the index is out of range. - * - * #### Notes - * This method accounts for a stretched last row. - */ - rowSize(region: DataModel.RowRegion, index: number): number { - // Return early for the column header region. - if (region === 'column-header') { - return this._columnHeaderSections.sizeOf(index); - } - - // Fetch the row size. - let size = this._rowSections.sizeOf(index); - - // Bail early if the index is out of bounds. - if (size < 0) { - return size; - } - - // Return early if the last row is not stretched. - if (!this._stretchLastRow) { - return size; - } - - // Return early if its not the last row. - if (index < this._rowSections.count - 1) { - return size; - } - - // Fetch the geometry. - let bh = this.bodyHeight; - let ph = this.pageHeight; - - // Return early if no stretching is needed. - if (ph <= bh) { - return size; - } - - // Return the adjusted size. - return size + (ph - bh); - } - - /** - * Get the size of a column in the data grid. - * - * @param region - The region which holds the column of interest. - * - * @param index - The index of the column of interest. - * - * @returns The size of the column, or `-1` if the index is out of range. - * - * #### Notes - * This method accounts for a stretched last column. - */ - columnSize(region: DataModel.ColumnRegion, index: number): number { - // Return early for the row header region. - if (region === 'row-header') { - return this._rowHeaderSections.sizeOf(index); - } - - // Fetch the column size. - let size = this._columnSections.sizeOf(index); - - // Bail early if the index is out of bounds. - if (size < 0) { - return size; - } - - // Return early if the last column is not stretched. - if (!this._stretchLastColumn) { - return size; - } - - // Return early if its not the last column. - if (index < this._columnSections.count - 1) { - return size; - } - - // Fetch the geometry. - let bw = this.bodyWidth; - let pw = this.pageWidth; - - // Return early if no stretching is needed. - if (pw <= bw) { - return size; - } - - // Return the adjusted size. - return size + (pw - bw); - } - - /** - * Resize a row in the data grid. - * - * @param region - The region which holds the row of interest. - * - * @param index - The index of the row of interest. - * - * @param size - The desired size of the row. - */ - resizeRow(region: DataModel.RowRegion, index: number, size: number): void { - let msg = new Private.RowResizeRequest(region, index, size); - MessageLoop.postMessage(this._viewport, msg); - } - - /** - * Resize a column in the data grid. - * - * @param region - The region which holds the column of interest. - * - * @param index - The index of the column of interest. - * - * @param size - The desired size of the column. - */ - resizeColumn(region: DataModel.ColumnRegion, index: number, size: number): void { - let msg = new Private.ColumnResizeRequest(region, index, size); - MessageLoop.postMessage(this._viewport, msg); - } - - /** - * Reset modified rows to their default size. - * - * @param region - The row region of interest. - */ - resetRows(region: DataModel.RowRegion | 'all'): void { - switch (region) { - case 'all': - this._rowSections.reset(); - this._columnHeaderSections.reset(); - break; - case 'body': - this._rowSections.reset(); - break; - case 'column-header': - this._columnHeaderSections.reset(); - break; - default: - throw 'unreachable'; - } - this.repaintContent(); - this.repaintOverlay(); - } - - /** - * Reset modified columns to their default size. - * - * @param region - The column region of interest. - */ - resetColumns(region: DataModel.ColumnRegion | 'all'): void { - switch (region) { - case 'all': - this._columnSections.reset(); - this._rowHeaderSections.reset(); - break; - case 'body': - this._columnSections.reset(); - break; - case 'row-header': - this._rowHeaderSections.reset(); - break; - default: - throw 'unreachable'; - } - this.repaintContent(); - this.repaintOverlay(); - } - - /** - * Map a client position to local viewport coordinates. - * - * @param clientX - The client X position of the mouse. - * - * @param clientY - The client Y position of the mouse. - * - * @returns The local viewport coordinates for the position. - */ - mapToLocal(clientX: number, clientY: number): { lx: number, ly: number } { - // Fetch the viewport rect. - let rect = this._viewport.node.getBoundingClientRect(); - - // Extract the rect coordinates. - let { left, top } = rect; - - // Round the rect coordinates for sub-pixel positioning. - left = Math.floor(left); - top = Math.floor(top); - - // Convert to local coordinates. - let lx = clientX - left; - let ly = clientY - top; - - // Return the local coordinates. - return { lx, ly }; - } - - /** - * Map a client position to virtual grid coordinates. - * - * @param clientX - The client X position of the mouse. - * - * @param clientY - The client Y position of the mouse. - * - * @returns The virtual grid coordinates for the position. - */ - mapToVirtual(clientX: number, clientY: number): { vx: number, vy: number } { - // Convert to local coordiates. - let { lx, ly } = this.mapToLocal(clientX, clientY); - - // Convert to virtual coordinates. - let vx = lx + this.scrollX - this.headerWidth; - let vy = ly + this.scrollY - this.headerHeight; - - // Return the local coordinates. - return { vx, vy }; - } - - /** - * Hit test the viewport for the given client position. - * - * @param clientX - The client X position of the mouse. - * - * @param clientY - The client Y position of the mouse. - * - * @returns The hit test result, or `null` if the client - * position is out of bounds. - * - * #### Notes - * This method accounts for a stretched last row and/or column. - */ - hitTest(clientX: number, clientY: number): DataGrid.HitTestResult { - // Convert the mouse position into local coordinates. - let { lx, ly } = this.mapToLocal(clientX, clientY); - - // Fetch the header and body dimensions. - let hw = this.headerWidth; - let hh = this.headerHeight; - let bw = this.bodyWidth; - let bh = this.bodyHeight; - let ph = this.pageHeight; - let pw = this.pageWidth; - - // Adjust the body width for a stretched last column. - if (this._stretchLastColumn && pw > bw) { - bw = pw; - } - - // Adjust the body height for a stretched last row. - if (this._stretchLastRow && ph > bh) { - bh = ph; - } - - // Check for a corner header hit. - if (lx >= 0 && lx < hw && ly >= 0 && ly < hh) { - // Convert to unscrolled virtual coordinates. - let vx = lx; - let vy = ly; - - // Fetch the row and column index. - let row = this.rowAt('column-header', vy); - let column = this.columnAt('row-header', vx); - - // Fetch the cell offset position. - let ox = this.columnOffset('row-header', column); - let oy = this.rowOffset('column-header', row); - - // Fetch cell width and height. - let width = this.columnSize('row-header', column); - let height = this.rowSize('column-header', row); - - // Compute the leading and trailing positions. - let x = vx - ox; - let y = vy - oy; - - // Return the hit test result. - return { region: 'corner-header', row, column, x, y, width, height }; - } - - // Check for a column header hit. - if (ly >= 0 && ly < hh && lx >= 0 && lx < (hw + bw)) { - // Convert to unscrolled virtual coordinates. - let vx = lx + this._scrollX - hw; - let vy = ly - - // Fetch the row and column index. - let row = this.rowAt('column-header', vy); - let column = this.columnAt('body', vx); - - // Fetch the cell offset position. - let ox = this.columnOffset('body', column); - let oy = this.rowOffset('column-header', row); - - // Fetch the cell width and height. - let width = this.columnSize('body', column); - let height = this.rowSize('column-header', row); - - // Compute the leading and trailing positions. - let x = vx - ox; - let y = vy - oy; - - // Return the hit test result. - return { region: 'column-header', row, column, x, y, width, height }; - } - - // Check for a row header hit. - if (lx >= 0 && lx < hw && ly >= 0 && ly < (hh + bh)) { - // Convert to unscrolled virtual coordinates. - let vx = lx - let vy = ly + this._scrollY - hh; - - // Fetch the row and column index. - let row = this.rowAt('body', vy); - let column = this.columnAt('row-header', vx); - - // Fetch the cell offset position. - let ox = this.columnOffset('row-header', column); - let oy = this.rowOffset('body', row); - - // Fetch the cell width and height. - let width = this.columnSize('row-header', column); - let height = this.rowSize('body', row); - - // Compute the leading and trailing positions. - let x = vx - ox; - let y = vy - oy; - - // Return the hit test result. - return { region: 'row-header', row, column, x, y, width, height }; - } - - // Check for a body hit. - if (lx >= hw && lx < (hw + bw) && ly >= hh && ly < (hh + bh)) { - // Convert to unscrolled virtual coordinates. - let vx = lx + this._scrollX - hw - let vy = ly + this._scrollY - hh; - - // Fetch the row and column index. - let row = this.rowAt('body', vy); - let column = this.columnAt('body', vx); - - // Fetch the cell offset position. - let ox = this.columnOffset('body', column); - let oy = this.rowOffset('body', row); - - // Fetch the cell width and height. - let width = this.columnSize('body', column); - let height = this.rowSize('body', row); - - // Compute the part coordinates. - let x = vx - ox; - let y = vy - oy; - - // Return the result. - return { region: 'body', row, column, x, y, width, height }; - } - - // Otherwise, it's a void space hit. - let row = -1; - let column = -1; - let x = -1; - let y = -1; - let width = -1; - let height = -1; - - // Return the hit test result. - return { region: 'void', row, column, x, y, width, height }; - } - - /** - * Copy the current selection to the system clipboard. - * - * #### Notes - * The grid must have a data model and a selection model. - * - * The behavior can be configured via `DataGrid.copyConfig`. - */ - copyToClipboard(): void { - // Fetch the data model. - let dataModel = this._dataModel; - - // Bail early if there is no data model. - if (!dataModel) { - return; - } - - // Fetch the selection model. - let selectionModel = this._selectionModel; - - // Bail early if there is no selection model. - if (!selectionModel) { - return; - } - - // Coerce the selections to an array. - let selections = toArray(selectionModel.selections()); - - // Bail early if there are no selections. - if (selections.length === 0) { - return; - } - - // Alert that multiple selections cannot be copied. - if (selections.length > 1) { - alert('Cannot copy multiple grid selections.'); - return; - } - - // Fetch the model counts. - let br = dataModel.rowCount('body'); - let bc = dataModel.columnCount('body'); - - // Bail early if there is nothing to copy. - if (br === 0 || bc === 0) { - return; - } - - // Unpack the selection. - let { r1, c1, r2, c2 } = selections[0]; - - // Clamp the selection to the model bounds. - r1 = Math.max(0, Math.min(r1, br - 1)); - c1 = Math.max(0, Math.min(c1, bc - 1)); - r2 = Math.max(0, Math.min(r2, br - 1)); - c2 = Math.max(0, Math.min(c2, bc - 1)); - - // Ensure the limits are well-orderd. - if (r2 < r1) [r1, r2] = [r2, r1]; - if (c2 < c1) [c1, c2] = [c2, c1]; - - // Fetch the header counts. - let rhc = dataModel.columnCount('row-header'); - let chr = dataModel.rowCount('column-header'); - - // Unpack the copy config. - let separator = this._copyConfig.separator; - let format = this._copyConfig.format; - let headers = this._copyConfig.headers; - let warningThreshold = this._copyConfig.warningThreshold; - - // Compute the number of cells to be copied. - let rowCount = r2 - r1 + 1; - let colCount = c2 - c1 + 1; - switch (headers) { - case 'none': - rhc = 0; - chr = 0; - break; - case 'row': - chr = 0; - colCount += rhc; - break; - case 'column': - rhc = 0; - rowCount += chr; - break; - case 'all': - rowCount += chr; - colCount += rhc; - break; - default: - throw 'unreachable'; - } - - // Compute the total cell count. - let cellCount = rowCount * colCount; - - // Allow the user to cancel a large copy request. - if (cellCount > warningThreshold) { - let msg = `Copying ${cellCount} cells may take a while. Continue?`; - if (!window.confirm(msg)) { - return; - } - } - - // Set up the format args. - let args = { - region: 'body' as DataModel.CellRegion, - row: 0, - column: 0, - value: null as any, - metadata: {} as DataModel.Metadata - }; - - // Allocate the array of rows. - let rows = new Array(rowCount); - - // Iterate over the rows. - for (let j = 0; j < rowCount; ++j) { - // Allocate the array of cells. - let cells = new Array(colCount); - - // Iterate over the columns. - for (let i = 0; i < colCount; ++i) { - // Set up the format variables. - let region: DataModel.CellRegion; - let row: number; - let column: number; - - // Populate the format variables. - if (j < chr && i < rhc) { - region = 'corner-header'; - row = j; - column = i; - } else if (j < chr) { - region = 'column-header'; - row = j; - column = i - rhc + c1; - } else if (i < rhc) { - region = 'row-header'; - row = j - chr + r1; - column = i; - } else { - region = 'body'; - row = j - chr + r1; - column = i - rhc + c1; - } - - // Populate the format args. - args.region = region; - args.row = row; - args.column = column; - args.value = dataModel.data(region, row, column); - args.metadata = dataModel.metadata(region, row, column); - - // Format the cell. - cells[i] = format(args); - } - - // Save the row of cells. - rows[j] = cells; - } - - // Convert the cells into lines. - let lines = rows.map(cells => cells.join(separator)); - - // Convert the lines into text. - let text = lines.join('\n'); - - // Copy the text to the clipboard. - ClipboardExt.copyText(text); - } - - /** - * Process a message sent to the widget. - * - * @param msg - The message sent to the widget. - */ - processMessage(msg: Message): void { - // Ignore child show/hide messages. The data grid controls the - // visibility of its children, and will manually dispatch the - // fit-request messages as a result of visibility change. - if (msg.type === 'child-shown' || msg.type === 'child-hidden') { - return; - } - - // Recompute the scroll bar minimums before the layout refits. - if (msg.type === 'fit-request') { - let vsbLimits = ElementExt.sizeLimits(this._vScrollBar.node); - let hsbLimits = ElementExt.sizeLimits(this._hScrollBar.node); - this._vScrollBarMinWidth = vsbLimits.minWidth; - this._hScrollBarMinHeight = hsbLimits.minHeight; - } - - // Process all other messages as normal. - super.processMessage(msg); - } - - /** - * Intercept a message sent to a message handler. - * - * @param handler - The target handler of the message. - * - * @param msg - The message to be sent to the handler. - * - * @returns `true` if the message should continue to be processed - * as normal, or `false` if processing should cease immediately. - */ - messageHook(handler: IMessageHandler, msg: Message): boolean { - // Process viewport messages. - if (handler === this._viewport) { - this._processViewportMessage(msg); - return true; - } - - // Process horizontal scroll bar messages. - if (handler === this._hScrollBar && msg.type === 'activate-request') { - this.activate(); - return false; - } - - // Process vertical scroll bar messages. - if (handler === this._vScrollBar && msg.type === 'activate-request') { - this.activate(); - return false; - } - - // Ignore all other messages. - return true; - } - - /** - * Handle the DOM events for the data grid. - * - * @param event - The DOM event sent to the data grid. - * - * #### Notes - * This method implements the DOM `EventListener` interface and is - * called in response to events on the data grid's DOM node. It - * should not be called directly by user code. - */ - handleEvent(event: Event): void { - switch (event.type) { - case 'keydown': - this._evtKeyDown(event as KeyboardEvent); - break; - case 'mousedown': - this._evtMouseDown(event as MouseEvent); - break; - case 'mousemove': - this._evtMouseMove(event as MouseEvent); - break; - case 'mouseup': - this._evtMouseUp(event as MouseEvent); - break; - case 'dblclick': - this._evtMouseDoubleClick(event as MouseEvent); - break; - case 'mouseleave': - this._evtMouseLeave(event as MouseEvent); - break; - case 'contextmenu': - this._evtContextMenu(event as MouseEvent); - break; - case 'wheel': - this._evtWheel(event as WheelEvent); - break; - case 'resize': - this._refreshDPI(); - break; - } - } - - /** - * A message handler invoked on an `'activate-request'` message. - */ - protected onActivateRequest(msg: Message): void { - this.viewport.node.focus({preventScroll: true}); - } - - /** - * A message handler invoked on a `'before-attach'` message. - */ - protected onBeforeAttach(msg: Message): void { - window.addEventListener('resize', this); - this.node.addEventListener('wheel', this); - this._viewport.node.addEventListener('keydown', this); - this._viewport.node.addEventListener('mousedown', this); - this._viewport.node.addEventListener('mousemove', this); - this._viewport.node.addEventListener('dblclick', this); - this._viewport.node.addEventListener('mouseleave', this); - this._viewport.node.addEventListener('contextmenu', this); - this.repaintContent(); - this.repaintOverlay(); - } - - /** - * A message handler invoked on an `'after-detach'` message. - */ - protected onAfterDetach(msg: Message): void { - window.removeEventListener('resize', this); - this.node.removeEventListener('wheel', this); - this._viewport.node.removeEventListener('keydown', this); - this._viewport.node.removeEventListener('mousedown', this); - this._viewport.node.removeEventListener('mousemove', this); - this._viewport.node.removeEventListener('mouseleave', this); - this._viewport.node.removeEventListener('dblclick', this); - this._viewport.node.removeEventListener('contextmenu', this); - this._releaseMouse(); - } - - /** - * A message handler invoked on a `'before-show'` message. - */ - protected onBeforeShow(msg: Message): void { - this.repaintContent(); - this.repaintOverlay(); - } - - /** - * A message handler invoked on a `'resize'` message. - */ - protected onResize(msg: Widget.ResizeMessage): void { - if (this._editorController) { - this._editorController.cancel(); - } - - this._syncScrollState(); - } - - /** - * Schedule a repaint of all of the grid content. - */ - protected repaintContent(): void { - let msg = new Private.PaintRequest('all', 0, 0, 0, 0); - MessageLoop.postMessage(this._viewport, msg); - } - - /** - * Schedule a repaint of specific grid content. - */ - protected repaintRegion(region: DataModel.CellRegion, r1: number, c1: number, r2: number, c2: number): void { - let msg = new Private.PaintRequest(region, r1, c1, r2, c2); - MessageLoop.postMessage(this._viewport, msg); - } - - /** - * Schedule a repaint of the overlay. - */ - protected repaintOverlay(): void { - MessageLoop.postMessage(this._viewport, Private.OverlayPaintRequest); - } - - /** - * Ensure the canvas is at least the specified size. - * - * This method will retain the valid canvas content. - */ - private _resizeCanvasIfNeeded(width: number, height: number): void { - // Scale the size by the dpi ratio. - width = width * this._dpiRatio; - height = height * this._dpiRatio; - - // Compute the maximum canvas size for the given width and height. - let maxW = (Math.ceil((width + 1) / 512) + 1) * 512; - let maxH = (Math.ceil((height + 1) / 512) + 1) * 512; - - // Get the current size of the canvas. - let curW = this._canvas.width; - let curH = this._canvas.height; - - // Bail early if the canvas size is within bounds. - if (curW >= width && curH >= height && curW <= maxW && curH <= maxH) { - return; - } - - // Compute the expanded canvas size. - let expW = maxW - 512; - let expH = maxH - 512; - - // Set the transforms to the identity matrix. - this._canvasGC.setTransform(1, 0, 0, 1, 0, 0); - this._bufferGC.setTransform(1, 0, 0, 1, 0, 0); - this._overlayGC.setTransform(1, 0, 0, 1, 0, 0); - - // Resize the buffer if needed. - if (curW < width) { - this._buffer.width = expW; - } else if (curW > maxW) { - this._buffer.width = maxW; - } - - // Resize the buffer height if needed. - if (curH < height) { - this._buffer.height = expH; - } else if (curH > maxH) { - this._buffer.height = maxH; - } - - // Test whether there is content to blit. - let needBlit = curH > 0 && curH > 0 && width > 0 && height > 0; - - // Copy the valid canvas content into the buffer if needed. - if (needBlit) { - this._bufferGC.drawImage(this._canvas, 0, 0); - } - - // Resize the canvas width if needed. - if (curW < width) { - this._canvas.width = expW; - this._canvas.style.width = `${expW / this._dpiRatio}px`; - } else if (curW > maxW) { - this._canvas.width = maxW; - this._canvas.style.width = `${maxW / this._dpiRatio}px`; - } - - // Resize the canvas height if needed. - if (curH < height) { - this._canvas.height = expH; - this._canvas.style.height = `${expH / this._dpiRatio}px`; - } else if (curH > maxH) { - this._canvas.height = maxH; - this._canvas.style.height = `${maxH / this._dpiRatio}px`; - } - - // Copy the valid canvas content from the buffer if needed. - if (needBlit) { - this._canvasGC.drawImage(this._buffer, 0, 0); - } - - // Copy the valid overlay content into the buffer if needed. - if (needBlit) { - this._bufferGC.drawImage(this._overlay, 0, 0); - } - - // Resize the overlay width if needed. - if (curW < width) { - this._overlay.width = expW; - this._overlay.style.width = `${expW / this._dpiRatio}px`; - } else if (curW > maxW) { - this._overlay.width = maxW; - this._overlay.style.width = `${maxW / this._dpiRatio}px`; - } - - // Resize the overlay height if needed. - if (curH < height) { - this._overlay.height = expH; - this._overlay.style.height = `${expH / this._dpiRatio}px`; - } else if (curH > maxH) { - this._overlay.height = maxH; - this._overlay.style.height = `${maxH / this._dpiRatio}px`; - } - - // Copy the valid overlay content from the buffer if needed. - if (needBlit) { - this._overlayGC.drawImage(this._buffer, 0, 0); - } - } - - /** - * Sync the scroll bars and scroll state with the viewport. - * - * #### Notes - * If the visibility of either scroll bar changes, a synchronous - * fit-request will be dispatched to the data grid to immediately - * resize the viewport. - */ - private _syncScrollState(): void { - // Fetch the viewport dimensions. - let bw = this.bodyWidth; - let bh = this.bodyHeight; - let pw = this.pageWidth; - let ph = this.pageHeight; - - // Get the current scroll bar visibility. - let hasVScroll = !this._vScrollBar.isHidden; - let hasHScroll = !this._hScrollBar.isHidden; - - // Get the minimum sizes of the scroll bars. - let vsw = this._vScrollBarMinWidth; - let hsh = this._hScrollBarMinHeight; - - // Get the page size as if no scroll bars are visible. - let apw = pw + (hasVScroll ? vsw : 0); - let aph = ph + (hasHScroll ? hsh : 0); - - // Test whether scroll bars are needed for the adjusted size. - let needVScroll = aph < bh - 1; - let needHScroll = apw < bw - 1; - - // Re-test the horizontal scroll if a vertical scroll is needed. - if (needVScroll && !needHScroll) { - needHScroll = (apw - vsw) < bw - 1; - } - - // Re-test the vertical scroll if a horizontal scroll is needed. - if (needHScroll && !needVScroll) { - needVScroll = (aph - hsh) < bh - 1; - } - - // If the visibility changes, immediately refit the grid. - if (needVScroll !== hasVScroll || needHScroll !== hasHScroll) { - this._vScrollBar.setHidden(!needVScroll); - this._hScrollBar.setHidden(!needHScroll); - this._scrollCorner.setHidden(!needVScroll || !needHScroll); - MessageLoop.sendMessage(this, Widget.Msg.FitRequest); - } - - // Update the scroll bar limits. - this._vScrollBar.maximum = this.maxScrollY; - this._vScrollBar.page = this.pageHeight; - this._hScrollBar.maximum = this.maxScrollX; - this._hScrollBar.page = this.pageWidth; - - // Re-clamp the scroll position. - this._scrollTo(this._scrollX, this._scrollY); - } - - /** - * Sync the viewport to the given scroll position. - * - * #### Notes - * This schedules a full repaint and syncs the scroll state. - */ - private _syncViewport(): void { - this.repaintContent(); - this.repaintOverlay(); - this._syncScrollState(); - } - - /** - * Process a message sent to the viewport - */ - private _processViewportMessage(msg: Message): void { - switch (msg.type) { - case 'resize': - this._onViewportResize(msg as Widget.ResizeMessage); - break; - case 'scroll-request': - this._onViewportScrollRequest(msg); - break; - case 'paint-request': - this._onViewportPaintRequest(msg as Private.PaintRequest); - break; - case 'overlay-paint-request': - this._onViewportOverlayPaintRequest(msg); - break; - case 'row-resize-request': - this._onViewportRowResizeRequest(msg as Private.RowResizeRequest); - break; - case 'column-resize-request': - this._onViewportColumnResizeRequest(msg as Private.ColumnResizeRequest); - break; - default: - break; - } - } - - /** - * A message hook invoked on a viewport `'resize'` message. - */ - private _onViewportResize(msg: Widget.ResizeMessage): void { - // Bail early if the viewport is not visible. - if (!this._viewport.isVisible) { - return; - } - - // Unpack the message data. - let { width, height } = msg; - - // Measure the viewport node if the dimensions are unknown. - if (width === -1) { - width = this._viewport.node.offsetWidth; - } - if (height === -1) { - height = this._viewport.node.offsetHeight; - } - - // Round the dimensions to the nearest pixel. - width = Math.round(width); - height = Math.round(height); - - // Get the current size of the viewport. - let oldWidth = this._viewportWidth; - let oldHeight = this._viewportHeight; - - // Updated internal viewport size. - this._viewportWidth = width; - this._viewportHeight = height; - - // Resize the canvas if needed. - this._resizeCanvasIfNeeded(width, height); - - // Bail early if there is nothing to paint. - if (width === 0 || height === 0) { - return; - } - - // Paint the whole grid if the old size was zero. - if (oldWidth === 0 || oldHeight === 0) { - this.paintContent(0, 0, width, height); - this._paintOverlay(); - return; - } - - // Paint the right edge as needed. - if (this._stretchLastColumn && this.pageWidth > this.bodyWidth) { - let bx = this._columnSections.offsetOf(this._columnSections.count - 1); - let x = Math.min(this.headerWidth + bx, oldWidth); - this.paintContent(x, 0, width - x, height); - } else if (width > oldWidth) { - this.paintContent(oldWidth, 0, width - oldWidth, height); - } - - // Paint the bottom edge as needed. - if (this._stretchLastRow && this.pageHeight > this.bodyHeight) { - let by = this._rowSections.offsetOf(this._rowSections.count - 1); - let y = Math.min(this.headerHeight + by, oldHeight); - this.paintContent(0, y, width, height - y); - } else if (height > oldHeight) { - this.paintContent(0, oldHeight, width, height - oldHeight); - } - - // Paint the overlay. - this._paintOverlay(); - } - - /** - * A message hook invoked on a viewport `'scroll-request'` message. - */ - private _onViewportScrollRequest(msg: Message): void { - this._scrollTo(this._hScrollBar.value, this._vScrollBar.value); - } - - /** - * A message hook invoked on a viewport `'paint-request'` message. - */ - private _onViewportPaintRequest(msg: Private.PaintRequest): void { - // Bail early if the viewport is not visible. - if (!this._viewport.isVisible) { - return; - } - - // Bail early if the viewport has zero area. - if (this._viewportWidth === 0 || this._viewportHeight === 0) { - return; - } - - // Set up the paint limits. - let xMin = 0; - let yMin = 0; - let xMax = this._viewportWidth - 1; - let yMax = this._viewportHeight - 1; - - // Fetch the scroll position. - let sx = this._scrollX; - let sy = this._scrollY; - - // Fetch the header dimensions. - let hw = this.headerWidth; - let hh = this.headerHeight; - - // Fetch the section lists. - let rs = this._rowSections; - let cs = this._columnSections; - let rhs = this._rowHeaderSections; - let chs = this._columnHeaderSections; - - // Unpack the message data. - let { region, r1, c1, r2, c2 } = msg; - - // Set up the paint variables. - let x1: number; - let y1: number; - let x2: number; - let y2: number; - - // Fill the paint variables based on the paint region. - switch (region) { - case 'all': - x1 = xMin; - y1 = yMin; - x2 = xMax; - y2 = yMax; - break; - case 'body': - r1 = Math.max(0, Math.min(r1, rs.count)); - c1 = Math.max(0, Math.min(c1, cs.count)); - r2 = Math.max(0, Math.min(r2, rs.count)); - c2 = Math.max(0, Math.min(c2, cs.count)); - x1 = cs.offsetOf(c1) - sx + hw; - y1 = rs.offsetOf(r1) - sy + hh; - x2 = cs.extentOf(c2) - sx + hw; - y2 = rs.extentOf(r2) - sy + hh; - break; - case 'row-header': - r1 = Math.max(0, Math.min(r1, rs.count)); - c1 = Math.max(0, Math.min(c1, rhs.count)); - r2 = Math.max(0, Math.min(r2, rs.count)); - c2 = Math.max(0, Math.min(c2, rhs.count)); - x1 = rhs.offsetOf(c1); - y1 = rs.offsetOf(r1) - sy + hh; - x2 = rhs.extentOf(c2); - y2 = rs.extentOf(r2) - sy + hh; - break; - case 'column-header': - r1 = Math.max(0, Math.min(r1, chs.count)); - c1 = Math.max(0, Math.min(c1, cs.count)); - r2 = Math.max(0, Math.min(r2, chs.count)); - c2 = Math.max(0, Math.min(c2, cs.count)); - x1 = cs.offsetOf(c1) - sx + hw; - y1 = chs.offsetOf(r1); - x2 = cs.extentOf(c2) - sx + hw; - y2 = chs.extentOf(r2); - break; - case 'corner-header': - r1 = Math.max(0, Math.min(r1, chs.count)); - c1 = Math.max(0, Math.min(c1, rhs.count)); - r2 = Math.max(0, Math.min(r2, chs.count)); - c2 = Math.max(0, Math.min(c2, rhs.count)); - x1 = rhs.offsetOf(c1); - y1 = chs.offsetOf(r1); - x2 = rhs.extentOf(c2); - y2 = chs.extentOf(r2); - break; - default: - throw 'unreachable'; - } - - // Bail early if the dirty rect is outside the bounds. - if (x2 < xMin || y2 < yMin || x1 > xMax || y1 > yMax) { - return; - } - - // Clamp the dirty rect to the paint bounds. - x1 = Math.max(xMin, Math.min(x1, xMax)); - y1 = Math.max(yMin, Math.min(y1, yMax)); - x2 = Math.max(xMin, Math.min(x2, xMax)); - y2 = Math.max(yMin, Math.min(y2, yMax)); - - // Paint the content of the dirty rect. - this.paintContent(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } - - /** - * A message hook invoked on a viewport `'overlay-paint-request'` message. - */ - private _onViewportOverlayPaintRequest(msg: Message): void { - // Bail early if the viewport is not visible. - if (!this._viewport.isVisible) { - return; - } - - // Bail early if the viewport has zero area. - if (this._viewportWidth === 0 || this._viewportHeight === 0) { - return; - } - - // Paint the content of the overlay. - this._paintOverlay(); - } - - /** - * A message hook invoked on a viewport `'row-resize-request'` message. - */ - private _onViewportRowResizeRequest(msg: Private.RowResizeRequest): void { - if (msg.region === 'body') { - this._resizeRow(msg.index, msg.size); - } else { - this._resizeColumnHeader(msg.index, msg.size); - } - } - - /** - * A message hook invoked on a viewport `'column-resize-request'` message. - */ - private _onViewportColumnResizeRequest(msg: Private.ColumnResizeRequest): void { - if (msg.region === 'body') { - this._resizeColumn(msg.index, msg.size); - } else { - this._resizeRowHeader(msg.index, msg.size); - } - } - - /** - * Handle the `thumbMoved` signal from a scroll bar. - */ - private _onThumbMoved(sender: ScrollBar): void { - MessageLoop.postMessage(this._viewport, Private.ScrollRequest); - } - - /** - * Handle the `pageRequested` signal from a scroll bar. - */ - private _onPageRequested(sender: ScrollBar, dir: 'decrement' | 'increment'): void { - if (sender === this._vScrollBar) { - this.scrollByPage(dir === 'decrement' ? 'up' : 'down'); - } else { - this.scrollByPage(dir === 'decrement' ? 'left' : 'right'); - } - } - - /** - * Handle the `stepRequested` signal from a scroll bar. - */ - private _onStepRequested(sender: ScrollBar, dir: 'decrement' | 'increment'): void { - if (sender === this._vScrollBar) { - this.scrollByStep(dir === 'decrement' ? 'up' : 'down'); - } else { - this.scrollByStep(dir === 'decrement' ? 'left' : 'right'); - } - } - - /** - * A signal handler for the data model `changed` signal. - */ - private _onDataModelChanged(sender: DataModel, args: DataModel.ChangedArgs): void { - switch (args.type) { - case 'rows-inserted': - this._onRowsInserted(args); - break; - case 'columns-inserted': - this._onColumnsInserted(args); - break; - case 'rows-removed': - this._onRowsRemoved(args); - break; - case 'columns-removed': - this._onColumnsRemoved(args); - break; - case 'rows-moved': - this._onRowsMoved(args); - break; - case 'columns-moved': - this._onColumnsMoved(args); - break; - case 'cells-changed': - this._onCellsChanged(args); - break; - case 'model-reset': - this._onModelReset(args); - break; - default: - throw 'unreachable'; - } - } - - /** - * A signal handler for the selection model `changed` signal. - */ - private _onSelectionsChanged(sender: SelectionModel): void { - this.repaintOverlay(); - } - - /** - * Handle rows being inserted in the data model. - */ - private _onRowsInserted(args: DataModel.RowsChangedArgs): void { - // Unpack the arg data. - let { region, index, span } = args; - - // Bail early if there are no sections to insert. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._rowSections; - } else { - list = this._columnHeaderSections; - } - - // Insert the span, maintaining the scroll position as needed. - if (this._scrollY === this.maxScrollY && this.maxScrollY > 0) { - list.insert(index, span); - this._scrollY = this.maxScrollY; - } else { - list.insert(index, span); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle columns being inserted into the data model. - */ - private _onColumnsInserted(args: DataModel.ColumnsChangedArgs): void { - // Unpack the arg data. - let { region, index, span } = args; - - // Bail early if there are no sections to insert. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._columnSections; - } else { - list = this._rowHeaderSections; - } - - // Insert the span, maintaining the scroll position as needed. - if (this._scrollX === this.maxScrollX && this.maxScrollX > 0) { - list.insert(index, span); - this._scrollX = this.maxScrollX; - } else { - list.insert(index, span); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle rows being removed from the data model. - */ - private _onRowsRemoved(args: DataModel.RowsChangedArgs): void { - // Unpack the arg data. - let { region, index, span } = args; - - // Bail early if there are no sections to remove. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._rowSections; - } else { - list = this._columnHeaderSections; - } - - // Bail if the index or is invalid - if (index < 0 || index >= list.count) { - return; - } - - // Remove the span, maintaining the scroll position as needed. - if (this._scrollY === this.maxScrollY && this.maxScrollY > 0) { - list.remove(index, span); - this._scrollY = this.maxScrollY; - } else { - list.remove(index, span); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle columns being removed from the data model. - */ - private _onColumnsRemoved(args: DataModel.ColumnsChangedArgs): void { - // Unpack the arg data. - let { region, index, span } = args; - - // Bail early if there are no sections to remove. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._columnSections; - } else { - list = this._rowHeaderSections; - } - - // Bail if the index or is invalid - if (index < 0 || index >= list.count) { - return; - } - - // Remove the span, maintaining the scroll position as needed. - if (this._scrollX === this.maxScrollX && this.maxScrollX > 0) { - list.remove(index, span); - this._scrollX = this.maxScrollX; - } else { - list.remove(index, span); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle rows moving in the data model. - */ - private _onRowsMoved(args: DataModel.RowsMovedArgs): void { - // Unpack the arg data. - let { region, index, span, destination } = args; - - // Bail early if there are no sections to move. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._rowSections; - } else { - list = this._columnHeaderSections; - } - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Clamp the move span to the limit. - span = Math.min(span, list.count - index); - - // Clamp the destination index to the limit. - destination = Math.min(Math.max(0, destination), list.count - span); - - // Bail early if there is no effective move. - if (index === destination) { - return; - } - - // Compute the first affected index. - let r1 = Math.min(index, destination); - - // Compute the last affected index. - let r2 = Math.max(index + span - 1, destination + span - 1); - - // Move the sections in the list. - list.move(index, span, destination); - - // Schedule a repaint of the dirty cells. - if (region === 'body') { - this.repaintRegion('body', r1, 0, r2, Infinity); - this.repaintRegion('row-header', r1, 0, r2, Infinity); - } else { - this.repaintRegion('column-header', r1, 0, r2, Infinity); - this.repaintRegion('corner-header', r1, 0, r2, Infinity); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle columns moving in the data model. - */ - private _onColumnsMoved(args: DataModel.ColumnsMovedArgs): void { - // Unpack the arg data. - let { region, index, span, destination } = args; - - // Bail early if there are no sections to move. - if (span <= 0) { - return; - } - - // Look up the relevant section list. - let list: SectionList; - if (region === 'body') { - list = this._columnSections; - } else { - list = this._rowHeaderSections; - } - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Clamp the move span to the limit. - span = Math.min(span, list.count - index); - - // Clamp the destination index to the limit. - destination = Math.min(Math.max(0, destination), list.count - span); - - // Bail early if there is no effective move. - if (index === destination) { - return; - } - - // Move the sections in the list. - list.move(index, span, destination); - - // Compute the first affected index. - let c1 = Math.min(index, destination); - - // Compute the last affected index. - let c2 = Math.max(index + span - 1, destination + span - 1); - - // Schedule a repaint of the dirty cells. - if (region === 'body') { - this.repaintRegion('body', 0, c1, Infinity, c2); - this.repaintRegion('column-header', 0, c1, Infinity, c2); - } else { - this.repaintRegion('row-header', 0, c1, Infinity, c2); - this.repaintRegion('corner-header', 0, c1, Infinity, c2); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * Handle cells changing in the data model. - */ - private _onCellsChanged(args: DataModel.CellsChangedArgs): void { - // Unpack the arg data. - let { region, row, column, rowSpan, columnSpan } = args; - - // Bail early if there are no cells to modify. - if (rowSpan <= 0 && columnSpan <= 0) { - return; - } - - // Compute the changed cell bounds. - let r1 = row; - let c1 = column; - let r2 = r1 + rowSpan - 1; - let c2 = c1 + columnSpan - 1; - - // Schedule a repaint of the cell content. - this.repaintRegion(region, r1, c1, r2, c2); - } - - /** - * Handle a full data model reset. - */ - private _onModelReset(args: DataModel.ModelResetArgs): void { - // Look up the various current section counts. - let nr = this._rowSections.count; - let nc = this._columnSections.count; - let nrh = this._rowHeaderSections.count; - let nch = this._columnHeaderSections.count; - - // Compute the delta count for each region. - let dr = this._dataModel!.rowCount('body') - nr; - let dc = this._dataModel!.columnCount('body') - nc; - let drh = this._dataModel!.columnCount('row-header') - nrh; - let dch = this._dataModel!.rowCount('column-header') - nch; - - // Update the row sections, if needed. - if (dr > 0) { - this._rowSections.insert(nr, dr); - } else if (dr < 0) { - this._rowSections.remove(nr + dr, -dr); - } - - // Update the column sections, if needed. - if (dc > 0) { - this._columnSections.insert(nc, dc); - } else if (dc < 0) { - this._columnSections.remove(nc + dc, -dc); - } - - // Update the row header sections, if needed. - if (drh > 0) { - this._rowHeaderSections.insert(nrh, drh); - } else if (drh < 0) { - this._rowHeaderSections.remove(nrh + drh, -drh); - } - - // Update the column header sections, if needed. - if (dch > 0) { - this._columnHeaderSections.insert(nch, dch); - } else if (dch < 0) { - this._columnHeaderSections.remove(nch + dch, -dch); - } - - // Sync the viewport. - this._syncViewport(); - } - - /** - * A signal handler for the renderer map `changed` signal. - */ - private _onRenderersChanged(): void { - this.repaintContent(); - } - - /** - * Handle the `'keydown'` event for the data grid. - */ - private _evtKeyDown(event: KeyboardEvent): void { - if (this._mousedown) { - event.preventDefault(); - event.stopPropagation(); - } else if (this._keyHandler) { - this._keyHandler.onKeyDown(this, event); - } - } - - /** - * Handle the `'mousedown'` event for the data grid. - */ - private _evtMouseDown(event: MouseEvent): void { - // Ignore everything except the left mouse button. - if (event.button !== 0) { - return; - } - - // Activate the grid. - this.activate(); - - // Stop the event propagation. - event.preventDefault(); - event.stopPropagation(); - - // Add the extra document listeners. - document.addEventListener('keydown', this, true); - document.addEventListener('mouseup', this, true); - document.addEventListener('mousedown', this, true); - document.addEventListener('mousemove', this, true); - document.addEventListener('contextmenu', this, true); - - // Flip the mousedown flag. - this._mousedown = true; - - // Dispatch to the mouse handler. - if (this._mouseHandler) { - this._mouseHandler.onMouseDown(this, event); - } - } - - /** - * Handle the `'mousemove'` event for the data grid. - */ - private _evtMouseMove(event: MouseEvent): void { - // Stop the event propagation if the mouse is down. - if (this._mousedown) { - event.preventDefault(); - event.stopPropagation(); - } - - // Bail if there is no mouse handler. - if (!this._mouseHandler) { - return; - } - - // Dispatch to the mouse handler. - if (this._mousedown) { - this._mouseHandler.onMouseMove(this, event); - } else { - this._mouseHandler.onMouseHover(this, event); - } - } - - /** - * Handle the `'mouseup'` event for the data grid. - */ - private _evtMouseUp(event: MouseEvent): void { - // Ignore everything except the left mouse button. - if (event.button !== 0) { - return; - } - - // Stop the event propagation. - event.preventDefault(); - event.stopPropagation(); - - // Dispatch to the mouse handler. - if (this._mouseHandler) { - this._mouseHandler.onMouseUp(this, event); - } - - // Release the mouse. - this._releaseMouse(); - } - - /** - * Handle the `'dblclick'` event for the data grid. - */ - private _evtMouseDoubleClick(event: MouseEvent): void { - // Ignore everything except the left mouse button. - if (event.button !== 0) { - return; - } - - // Stop the event propagation. - event.preventDefault(); - event.stopPropagation(); - - // Dispatch to the mouse handler. - if (this._mouseHandler) { - this._mouseHandler.onMouseDoubleClick(this, event); - } - - // Release the mouse. - this._releaseMouse(); - } - - /** - * Handle the `'mouseleave'` event for the data grid. - */ - private _evtMouseLeave(event: MouseEvent): void { - if (this._mousedown) { - event.preventDefault(); - event.stopPropagation(); - } else if (this._mouseHandler) { - this._mouseHandler.onMouseLeave(this, event); - } - } - - /** - * Handle the `'contextmenu'` event for the data grid. - */ - private _evtContextMenu(event: MouseEvent): void { - if (this._mousedown) { - event.preventDefault(); - event.stopPropagation(); - } else if (this._mouseHandler) { - this._mouseHandler.onContextMenu(this, event); - } - } - - /** - * Handle the `'wheel'` event for the data grid. - */ - private _evtWheel(event: WheelEvent): void { - // Ignore the event if `accel` is held. - if (Platform.accelKey(event)) { - return; - } - - // Bail early if there is no mouse handler. - if (!this._mouseHandler) { - return; - } - - // Stop the event propagation. - event.preventDefault(); - event.stopPropagation(); - - // Dispatch to the mouse handler. - this._mouseHandler.onWheel(this, event); - } - - /** - * Release the mouse grab. - */ - private _releaseMouse(): void { - // Clear the mousedown flag. - this._mousedown = false; - - // Relase the mouse handler. - if (this._mouseHandler) { - this._mouseHandler.release(); - } - - // Remove the document listeners. - document.removeEventListener('keydown', this, true); - document.removeEventListener('mouseup', this, true); - document.removeEventListener('mousedown', this, true); - document.removeEventListener('mousemove', this, true); - document.removeEventListener('contextmenu', this, true); - } - - /** - * Refresh the dpi ratio. - */ - private _refreshDPI(): void { - // Get the best integral value for the dpi ratio. - let dpiRatio = Math.ceil(window.devicePixelRatio); - - // Bail early if the computed dpi ratio has not changed. - if (this._dpiRatio === dpiRatio) { - return; - } - - // Update the internal dpi ratio. - this._dpiRatio = dpiRatio; - - // Schedule a repaint of the content. - this.repaintContent(); - - // Schedule a repaint of the overlay. - this.repaintOverlay(); - - // Update the canvas size for the new dpi ratio. - this._resizeCanvasIfNeeded(this._viewportWidth, this._viewportHeight); - - // Ensure the canvas style is scaled for the new ratio. - this._canvas.style.width = `${this._canvas.width / this._dpiRatio}px`; - this._canvas.style.height = `${this._canvas.height / this._dpiRatio}px`; - - // Ensure the overlay style is scaled for the new ratio. - this._overlay.style.width = `${this._overlay.width / this._dpiRatio}px`; - this._overlay.style.height = `${this._overlay.height / this._dpiRatio}px`; - } - - /** - * Resize a row section immediately. - */ - private _resizeRow(index: number, size: number): void { - // Look up the target section list. - let list = this._rowSections; - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Look up the old size of the section. - let oldSize = list.sizeOf(index); - - // Normalize the new size of the section. - let newSize = list.clampSize(size); - - // Bail early if the size does not change. - if (oldSize === newSize) { - return; - } - - // Resize the section in the list. - list.resize(index, newSize); - - // Get the current size of the viewport. - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // If there is nothing to paint, sync the scroll state. - if (!this._viewport.isVisible || vw === 0 || vh === 0) { - this._syncScrollState(); - return; - } - - // Compute the size delta. - let delta = newSize - oldSize; - - // Look up the column header height. - let hh = this.headerHeight; - - // Compute the viewport offset of the section. - let offset = list.offsetOf(index) + hh - this._scrollY; - - // Bail early if there is nothing to paint. - if (hh >= vh || offset >= vh) { - this._syncScrollState(); - return; - } - - // Update the scroll position if the section is not visible. - if (offset + oldSize <= hh) { - this._scrollY += delta; - this._syncScrollState(); - return; - } - - // Compute the paint origin of the section. - let pos = Math.max(hh, offset); - - // Paint from the section onward if it spans the viewport. - if (offset + oldSize >= vh || offset + newSize >= vh) { - this.paintContent(0, pos, vw, vh - pos); - this._paintOverlay(); - this._syncScrollState(); - return; - } - - // Compute the X blit dimensions. - let sx = 0; - let sw = vw; - let dx = 0; - - // Compute the Y blit dimensions. - let sy: number; - let sh: number; - let dy: number; - if (offset + newSize <= hh) { - sy = hh - delta; - sh = vh - sy; - dy = hh; - } else { - sy = offset + oldSize; - sh = vh - sy; - dy = sy + delta; - } - - // Blit the valid content to the destination. - this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); - - // Repaint the section if needed. - if (newSize > 0 && offset + newSize > hh) { - this.paintContent(0, pos, vw, offset + newSize - pos); - } - - // Paint the trailing space as needed. - if (this._stretchLastRow && this.pageHeight > this.bodyHeight) { - let r = this._rowSections.count - 1; - let y = hh + this._rowSections.offsetOf(r); - this.paintContent(0, y, vw, vh - y); - } else if (delta < 0) { - this.paintContent(0, vh + delta, vw, -delta); - } - - // Paint the overlay. - this._paintOverlay(); - - // Sync the scroll state. - this._syncScrollState(); - } - - /** - * Resize a column section immediately. - */ - private _resizeColumn(index: number, size: number): void { - // Look up the target section list. - let list = this._columnSections; - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Look up the old size of the section. - let oldSize = list.sizeOf(index); - - // Normalize the new size of the section. - let newSize = list.clampSize(size); - - // Bail early if the size does not change. - if (oldSize === newSize) { - return; - } - - // Resize the section in the list. - list.resize(index, newSize); - - // Get the current size of the viewport. - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // If there is nothing to paint, sync the scroll state. - if (!this._viewport.isVisible || vw === 0 || vh === 0) { - this._syncScrollState(); - return; - } - - // Compute the size delta. - let delta = newSize - oldSize; - - // Look up the row header width. - let hw = this.headerWidth; - - // Compute the viewport offset of the section. - let offset = list.offsetOf(index) + hw - this._scrollX; - - // Bail early if there is nothing to paint. - if (hw >= vw || offset >= vw) { - this._syncScrollState(); - return; - } - - // Update the scroll position if the section is not visible. - if (offset + oldSize <= hw) { - this._scrollX += delta; - this._syncScrollState(); - this._drawColumnHeaderRegion(-this.scrollX, -this.scrollY, this.totalWidth, this.headerHeight); - return; - } - - // Compute the paint origin of the section. - let pos = Math.max(hw, offset); - - // Paint from the section onward if it spans the viewport. - if (offset + oldSize >= vw || offset + newSize >= vw) { - this.paintContent(pos, 0, vw - pos, vh, false); - this._drawColumnHeaderRegion(-this.scrollX, -this.scrollY, this.totalWidth, this.headerHeight); - this._paintOverlay(); - this._syncScrollState(); - return; - } - - // Compute the Y blit dimensions. - let sy = 0; - let sh = vh; - let dy = 0; - - // Compute the X blit dimensions. - let sx: number; - let sw: number; - let dx: number; - if (offset + newSize <= hw) { - sx = hw - delta; - sw = vw - sx; - dx = hw; - } else { - sx = offset + oldSize; - sw = vw - sx; - dx = sx + delta; - } - - // Blit the valid content to the destination. - this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); - - // Repaint the section if needed. - if (newSize > 0 && offset + newSize > hw) { - this.paintContent(pos, 0, offset + newSize - pos, vh, false); - } - - // Paint the trailing space as needed. - if (this._stretchLastColumn && this.pageWidth > this.bodyWidth) { - let c = this._columnSections.count - 1; - let x = hw + this._columnSections.offsetOf(c); - this.paintContent(x, 0, vw - x, vh, false); - } else if (delta < 0) { - this.paintContent(vw + delta, 0, -delta, vh, false); - } - - // Draw the column header region. - this._drawColumnHeaderRegion(-this.scrollX, 0, this.totalWidth, this.headerHeight); - - // Paint the overlay. - this._paintOverlay(); - - // Sync the scroll state after painting. - this._syncScrollState(); - } - - /** - * Resize a row header section immediately. - */ - private _resizeRowHeader(index: number, size: number): void { - // Look up the target section list. - let list = this._rowHeaderSections; - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Look up the old size of the section. - let oldSize = list.sizeOf(index); - - // Normalize the new size of the section. - let newSize = list.clampSize(size); - - // Bail early if the size does not change. - if (oldSize === newSize) { - return; - } - - // Resize the section in the list. - list.resize(index, newSize); - - // Get the current size of the viewport. - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // If there is nothing to paint, sync the scroll state. - if (!this._viewport.isVisible || vw === 0 || vh === 0) { - this._syncScrollState(); - return; - } - - // Compute the size delta. - let delta = newSize - oldSize; - - // Look up the offset of the section. - let offset = list.offsetOf(index); - - // Bail early if the section is fully outside the viewport. - if (offset >= vw) { - this._syncScrollState(); - return; - } - - // Paint the entire tail if the section spans the viewport. - if (offset + oldSize >= vw || offset + newSize >= vw) { - this.paintContent(offset, 0, vw - offset, vh); - this._paintOverlay(); - this._syncScrollState(); - return; - } - - // Compute the blit content dimensions. - let sx = offset + oldSize; - let sy = 0; - let sw = vw - sx; - let sh = vh; - let dx = sx + delta; - let dy = 0; - - // Blit the valid contents to the destination. - this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); - - // Repaint the header section if needed. - if (newSize > 0) { - this.paintContent(offset, 0, newSize, vh); - } - - // Paint the trailing space as needed. - if (this._stretchLastColumn && this.pageWidth > this.bodyWidth) { - let c = this._columnSections.count - 1; - let x = this.headerWidth + this._columnSections.offsetOf(c); - this.paintContent(x, 0, vw - x, vh); - } else if (delta < 0) { - this.paintContent(vw + delta, 0, -delta, vh); - } - - // Paint the overlay. - this._paintOverlay(); - - // Sync the scroll state after painting. - this._syncScrollState(); - } - - /** - * Resize a column header section immediately. - */ - private _resizeColumnHeader(index: number, size: number): void { - // Look up the target section list. - let list = this._columnHeaderSections; - - // Bail early if the index is out of range. - if (index < 0 || index >= list.count) { - return; - } - - // Look up the old size of the section. - let oldSize = list.sizeOf(index); - - // Normalize the new size of the section. - let newSize = list.clampSize(size); - - // Bail early if the size does not change. - if (oldSize === newSize) { - return; - } - - // Resize the section in the list. - list.resize(index, newSize); - - // Get the current size of the viewport. - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // If there is nothing to paint, sync the scroll state. - if (!this._viewport.isVisible || vw === 0 || vh === 0) { - this._syncScrollState(); - return; - } - - // Paint the overlay. - this._paintOverlay(); - - // Compute the size delta. - let delta = newSize - oldSize; - - // Look up the offset of the section. - let offset = list.offsetOf(index); - - // Bail early if the section is fully outside the viewport. - if (offset >= vh) { - this._syncScrollState(); - return; - } - - // Paint the entire tail if the section spans the viewport. - if (offset + oldSize >= vh || offset + newSize >= vh) { - this.paintContent(0, offset, vw, vh - offset); - this._paintOverlay(); - this._syncScrollState(); - return; - } - - // Compute the blit content dimensions. - let sx = 0; - let sy = offset + oldSize; - let sw = vw; - let sh = vh - sy; - let dx = 0; - let dy = sy + delta; - - // Blit the valid contents to the destination. - this._blitContent(this._canvas, sx, sy, sw, sh, dx, dy); - - // Repaint the header section if needed. - if (newSize > 0) { - this.paintContent(0, offset, vw, newSize); - } - - // Paint the trailing space as needed. - if (this._stretchLastRow && this.pageHeight > this.bodyHeight) { - let r = this._rowSections.count - 1; - let y = this.headerHeight + this._rowSections.offsetOf(r); - this.paintContent(0, y, vw, vh - y); - } else if (delta < 0) { - this.paintContent(0, vh + delta, vw, -delta); - } - - // Paint the overlay. - this._paintOverlay(); - - // Sync the scroll state after painting. - this._syncScrollState(); - } - - /** - * Scroll immediately to the specified offset position. - */ - private _scrollTo(x: number, y: number): void { - // Floor and clamp the position to the allowable range. - x = Math.max(0, Math.min(Math.floor(x), this.maxScrollX)); - y = Math.max(0, Math.min(Math.floor(y), this.maxScrollY)); - - // Synchronize the scroll bar values. - this._hScrollBar.value = x; - this._vScrollBar.value = y; - - // Compute the delta scroll amount. - let dx = x - this._scrollX; - let dy = y - this._scrollY; - - // Bail early if there is no effective scroll. - if (dx === 0 && dy === 0) { - return; - } - - // Bail early if the viewport is not visible. - if (!this._viewport.isVisible) { - this._scrollX = x; - this._scrollY = y; - return; - } - - // Get the current size of the viewport. - let width = this._viewportWidth; - let height = this._viewportHeight; - - // Bail early if the viewport is empty. - if (width === 0 || height === 0) { - this._scrollX = x; - this._scrollY = y; - return; - } - - // Get the visible content origin. - let contentX = this.headerWidth; - let contentY = this.headerHeight; - - // Get the visible content dimensions. - let contentWidth = width - contentX; - let contentHeight = height - contentY; - - // Bail early if there is no content to draw. - if (contentWidth <= 0 && contentHeight <= 0) { - this._scrollX = x; - this._scrollY = y; - return; - } - - // Compute the area which needs painting for the `dx` scroll. - let dxArea = 0; - if (dx !== 0 && contentWidth > 0) { - if (Math.abs(dx) >= contentWidth) { - dxArea = contentWidth * height; - } else { - dxArea = Math.abs(dx) * height; - } - } - - // Compute the area which needs painting for the `dy` scroll. - let dyArea = 0; - if (dy !== 0 && contentHeight > 0) { - if (Math.abs(dy) >= contentHeight) { - dyArea = width * contentHeight; - } else { - dyArea = width * Math.abs(dy); - } - } - - // If the area sum is larger than the total, paint everything. - if ((dxArea + dyArea) >= (width * height)) { - this._scrollX = x; - this._scrollY = y; - this.paintContent(0, 0, width, height); - this._paintOverlay(); - return; - } - - // Update the internal Y scroll position. - this._scrollY = y; - - // Scroll the Y axis if needed. If the scroll distance exceeds - // the visible height, paint everything. Otherwise, blit the - // valid content and paint the dirty region. - if (dy !== 0 && contentHeight > 0) { - if (Math.abs(dy) >= contentHeight) { - this.paintContent(0, contentY, width, contentHeight); - } else { - let x = 0; - let y = dy < 0 ? contentY : contentY + dy; - let w = width; - let h = contentHeight - Math.abs(dy); - this._blitContent(this._canvas, x, y, w, h, x, y - dy); - this.paintContent(0, dy < 0 ? contentY : height - dy, width, Math.abs(dy)); - } - } - - // Update the internal X scroll position. - this._scrollX = x; - - // Scroll the X axis if needed. If the scroll distance exceeds - // the visible width, paint everything. Otherwise, blit the - // valid content and paint the dirty region. - if (dx !== 0 && contentWidth > 0) { - if (Math.abs(dx) >= contentWidth) { - this.paintContent(contentX, 0, contentWidth, height, false); - } else { - let x = dx < 0 ? contentX : contentX + dx; - let y = 0; - let w = contentWidth - Math.abs(dx); - let h = height; - this._blitContent(this._canvas, x, y, w, h, x - dx, y); - this.paintContent(dx < 0 ? contentX : width - dx, 0, Math.abs(dx), height, false); - } - } - - this._drawColumnHeaderRegion(-this.scrollX, 0, this.totalWidth, this.headerHeight); - - // Paint the overlay. - this._paintOverlay(); - } - - /** - * Blit content into the on-screen grid canvas. - * - * The rect should be expressed in viewport coordinates. - * - * This automatically accounts for the dpi ratio. - */ - private _blitContent(source: HTMLCanvasElement, x: number, y: number, w: number, h: number, dx: number, dy: number): void { - // Scale the blit coordinates by the dpi ratio. - x *= this._dpiRatio; - y *= this._dpiRatio; - w *= this._dpiRatio; - h *= this._dpiRatio; - dx *= this._dpiRatio; - dy *= this._dpiRatio; - - // Save the current gc state. - this._canvasGC.save(); - - // Set the transform to the identity matrix. - this._canvasGC.setTransform(1, 0, 0, 1, 0, 0); - - // Draw the specified content. - this._canvasGC.drawImage(source, x, y, w, h, dx, dy, w, h); - - // Restore the gc state. - this._canvasGC.restore(); - } - - /** - * Paint the grid content for the given dirty rect. - * - * The rect should be expressed in valid viewport coordinates. - * - * This is the primary paint entry point. The individual `_draw*` - * methods should not be invoked directly. This method dispatches - * to the drawing methods in the correct order. - */ - private paintContent(rx: number, ry: number, rw: number, rh: number, renderColumnHeaders: boolean = true): void { - // Scale the canvas and buffer GC for the dpi ratio. - this._canvasGC.setTransform(this._dpiRatio, 0, 0, this._dpiRatio, 0, 0); - this._bufferGC.setTransform(this._dpiRatio, 0, 0, this._dpiRatio, 0, 0); - - // Clear the dirty rect of all content. - this._canvasGC.clearRect(rx, ry, rw, rh); - - // Draw the void region. - this._drawVoidRegion(rx, ry, rw, rh); - - // Draw the body region. - this._drawBodyRegion(rx, ry, rw, rh); - - // Draw the row header region. - this._drawRowHeaderRegion(rx, ry, rw, rh); - - // Draw the column header region. - if (renderColumnHeaders) { - this._drawColumnHeaderRegion(rx, ry, rw, rh); - } - - // Draw the corner header region. - this.drawCornerHeaderRegion(rx, ry, rw, rh); - } - - /** - * Paint the overlay content for the entire grid. - * - * This is the primary overlay paint entry point. The individual - * `_draw*` methods should not be invoked directly. This method - * dispatches to the drawing methods in the correct order. - */ - private _paintOverlay(): void { - // Scale the overlay GC for the dpi ratio. - this._overlayGC.setTransform(this._dpiRatio, 0, 0, this._dpiRatio, 0, 0); - - // Clear the overlay of all content. - this._overlayGC.clearRect(0, 0, this._overlay.width, this._overlay.height); - - // Draw the body selections. - this._drawBodySelections(); - - // Draw the row header selections. - this._drawRowHeaderSelections(); - - // Draw the column header selections. - this._drawColumnHeaderSelections(); - - // Draw the cursor. - this._drawCursor(); - - // Draw the shadows. - this._drawShadows(); - } - - /** - * Draw the void region for the dirty rect. - */ - private _drawVoidRegion(rx: number, ry: number, rw: number, rh: number): void { - // Look up the void color. - let color = this._style.voidColor; - - // Bail if there is no void color. - if (!color) { - return; - } - - // Fill the dirty rect with the void color. - this._canvasGC.fillStyle = color; - this._canvasGC.fillRect(rx, ry, rw, rh); - } - - /** - * Draw the body region which intersects the dirty rect. - */ - private _drawBodyRegion(rx: number, ry: number, rw: number, rh: number): void { - // Get the visible content dimensions. - let contentW = this._columnSections.length - this._scrollX; - let contentH = this._rowSections.length - this._scrollY; - - // Bail if there is no content to draw. - if (contentW <= 0 || contentH <= 0) { - return; - } - - // Get the visible content origin. - let contentX = this.headerWidth; - let contentY = this.headerHeight; - - // Bail if the dirty rect does not intersect the content area. - if (rx + rw <= contentX) { - return; - } - if (ry + rh <= contentY) { - return; - } - if (rx >= contentX + contentW) { - return; - } - if (ry >= contentY + contentH) { - return; - } - - // Fetch the geometry. - let bh = this.bodyHeight; - let bw = this.bodyWidth; - let ph = this.pageHeight; - let pw = this.pageWidth; - - // Get the upper and lower bounds of the dirty content area. - let x1 = Math.max(rx, contentX); - let y1 = Math.max(ry, contentY); - let x2 = Math.min(rx + rw - 1, contentX + contentW - 1); - let y2 = Math.min(ry + rh - 1, contentY + contentH - 1); - - // Convert the dirty content bounds into cell bounds. - let r1 = this._rowSections.indexOf(y1 - contentY + this._scrollY); - let c1 = this._columnSections.indexOf(x1 - contentX + this._scrollX); - let r2 = this._rowSections.indexOf(y2 - contentY + this._scrollY); - let c2 = this._columnSections.indexOf(x2 - contentX + this._scrollX); - - // Fetch the max row and column. - let maxRow = this._rowSections.count - 1; - let maxColumn = this._columnSections.count - 1; - - // Handle a dirty content area larger than the cell count. - if (r2 < 0) { - r2 = maxRow; - } - if (c2 < 0) { - c2 = maxColumn; - } - - // Convert the cell bounds back to visible coordinates. - let x = this._columnSections.offsetOf(c1) + contentX - this._scrollX; - let y = this._rowSections.offsetOf(r1) + contentY - this._scrollY; - - // Set up the paint region size variables. - let width = 0; - let height = 0; - - // Allocate the section sizes arrays. - let rowSizes = new Array(r2 - r1 + 1); - let columnSizes = new Array(c2 - c1 + 1); - - // Get the row sizes for the region. - for (let j = r1; j <= r2; ++j) { - let size = this._rowSections.sizeOf(j); - rowSizes[j - r1] = size; - height += size; - } - - // Get the column sizes for the region. - for (let i = c1; i <= c2; ++i) { - let size = this._columnSections.sizeOf(i); - columnSizes[i - c1] = size; - width += size; - } - - // Adjust the geometry if the last row is streched. - if (this._stretchLastRow && ph > bh && r2 === maxRow) { - let dh = this.pageHeight - this.bodyHeight; - rowSizes[rowSizes.length - 1] += dh; - height += dh; - y2 += dh; - } - - // Adjust the geometry if the last column is streched. - if (this._stretchLastColumn && pw > bw && c2 === maxColumn) { - let dw = this.pageWidth - this.bodyWidth; - columnSizes[columnSizes.length - 1] += dw; - width += dw; - x2 += dw; - } - - // Create the paint region object. - let rgn: Private.PaintRegion = { - region: 'body', - xMin: x1, yMin: y1, - xMax: x2, yMax: y2, - x, y, width, height, - row: r1, column: c1, - rowSizes, columnSizes - }; - - // Draw the background. - this._drawBackground(rgn, this._style.backgroundColor); - - // Draw the row background. - this._drawRowBackground(rgn, this._style.rowBackgroundColor); - - // Draw the column background. - this._drawColumnBackground(rgn, this._style.columnBackgroundColor); - - // Draw the cell content for the paint region. - this._drawCells(rgn); - - // Draw the horizontal grid lines. - this._drawHorizontalGridLines(rgn, - this._style.horizontalGridLineColor || - this._style.gridLineColor - ); - - // Draw the vertical grid lines. - this._drawVerticalGridLines(rgn, - this._style.verticalGridLineColor || - this._style.gridLineColor - ); - } - - /** - * Draw the row header region which intersects the dirty rect. - */ - private _drawRowHeaderRegion(rx: number, ry: number, rw: number, rh: number): void { - // Get the visible content dimensions. - let contentW = this.headerWidth; - let contentH = this.bodyHeight - this._scrollY; - - // Bail if there is no content to draw. - if (contentW <= 0 || contentH <= 0) { - return; - } - - // Get the visible content origin. - let contentX = 0; - let contentY = this.headerHeight; - - // Bail if the dirty rect does not intersect the content area. - if (rx + rw <= contentX) { - return; - } - if (ry + rh <= contentY) { - return; - } - if (rx >= contentX + contentW) { - return; - } - if (ry >= contentY + contentH) { - return; - } - - // Fetch the geometry. - let bh = this.bodyHeight; - let ph = this.pageHeight; - - // Get the upper and lower bounds of the dirty content area. - let x1 = rx; - let y1 = Math.max(ry, contentY); - let x2 = Math.min(rx + rw - 1, contentX + contentW - 1); - let y2 = Math.min(ry + rh - 1, contentY + contentH - 1); - - // Convert the dirty content bounds into cell bounds. - let r1 = this._rowSections.indexOf(y1 - contentY + this._scrollY); - let c1 = this._rowHeaderSections.indexOf(x1); - let r2 = this._rowSections.indexOf(y2 - contentY + this._scrollY); - let c2 = this._rowHeaderSections.indexOf(x2); - - // Fetch max row and column. - let maxRow = this._rowSections.count - 1; - let maxColumn = this._rowHeaderSections.count - 1; - - // Handle a dirty content area larger than the cell count. - if (r2 < 0) { - r2 = maxRow; - } - if (c2 < 0) { - c2 = maxColumn; - } - - // Convert the cell bounds back to visible coordinates. - let x = this._rowHeaderSections.offsetOf(c1); - let y = this._rowSections.offsetOf(r1) + contentY - this._scrollY; - - // Set up the paint region size variables. - let width = 0; - let height = 0; - - // Allocate the section sizes arrays. - let rowSizes = new Array(r2 - r1 + 1); - let columnSizes = new Array(c2 - c1 + 1); - - // Get the row sizes for the region. - for (let j = r1; j <= r2; ++j) { - let size = this._rowSections.sizeOf(j); - rowSizes[j - r1] = size; - height += size; - } - - // Get the column sizes for the region. - for (let i = c1; i <= c2; ++i) { - let size = this._rowHeaderSections.sizeOf(i); - columnSizes[i - c1] = size; - width += size; - } - - // Adjust the geometry if the last row is stretched. - if (this._stretchLastRow && ph > bh && r2 === maxRow) { - let dh = this.pageHeight - this.bodyHeight; - rowSizes[rowSizes.length - 1] += dh; - height += dh; - y2 += dh; - } - - // Create the paint region object. - let rgn: Private.PaintRegion = { - region: 'row-header', - xMin: x1, yMin: y1, - xMax: x2, yMax: y2, - x, y, width, height, - row: r1, column: c1, - rowSizes, columnSizes - }; - - // Draw the background. - this._drawBackground(rgn, this._style.headerBackgroundColor); - - // Draw the cell content for the paint region. - this._drawCells(rgn); - - // Draw the horizontal grid lines. - this._drawHorizontalGridLines(rgn, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor - ); - - // Draw the vertical grid lines. - this._drawVerticalGridLines(rgn, - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor - ); - } - - /** - * Draw the column header region which intersects the dirty rect. - */ - private _drawColumnHeaderRegion(rx: number, ry: number, rw: number, rh: number): void { - // Get the visible content dimensions. - let contentW = this.bodyWidth - this._scrollX; - let contentH = this.headerHeight; - - // Bail if there is no content to draw. - if (contentW <= 0 || contentH <= 0) { - return; - } - - // Get the visible content origin. - let contentX = this.headerWidth; - let contentY = 0; - - // Bail if the dirty rect does not intersect the content area. - if (rx + rw <= contentX) { - return; - } - if (ry + rh <= contentY) { - return; - } - if (rx >= contentX + contentW) { - return; - } - if (ry >= contentY + contentH) { - return; - } - - // Fetch the geometry. - let bw = this.bodyWidth; - let pw = this.pageWidth; - - // Get the upper and lower bounds of the dirty content area. - let x1 = Math.max(rx, contentX); - let y1 = ry; - let x2 = Math.min(rx + rw - 1, contentX + contentW - 1); - let y2 = Math.min(ry + rh - 1, contentY + contentH - 1); - - // Convert the dirty content bounds into cell bounds. - let r1 = this._columnHeaderSections.indexOf(y1); - let c1 = this._columnSections.indexOf(x1 - contentX + this._scrollX); - let r2 = this._columnHeaderSections.indexOf(y2); - let c2 = this._columnSections.indexOf(x2 - contentX + this._scrollX); - - // Fetch the max row and column. - let maxRow = this._columnHeaderSections.count - 1; - let maxColumn = this._columnSections.count - 1; - - // Handle a dirty content area larger than the cell count. - if (r2 < 0) { - r2 = maxRow; - } - if (c2 < 0) { - c2 = maxColumn; - } - - // Convert the cell bounds back to visible coordinates. - let x = this._columnSections.offsetOf(c1) + contentX - this._scrollX; - let y = this._columnHeaderSections.offsetOf(r1); - - // Set up the paint region size variables. - let width = 0; - let height = 0; - - // Allocate the section sizes arrays. - let rowSizes = new Array(r2 - r1 + 1); - let columnSizes = new Array(c2 - c1 + 1); - - // Get the row sizes for the region. - for (let j = r1; j <= r2; ++j) { - let size = this._columnHeaderSections.sizeOf(j); - rowSizes[j - r1] = size; - height += size; - } - - // Get the column sizes for the region. - for (let i = c1; i <= c2; ++i) { - let size = this._columnSections.sizeOf(i); - columnSizes[i - c1] = size; - width += size; - } - - // Adjust the geometry if the last column is stretched. - if (this._stretchLastColumn && pw > bw && c2 === maxColumn) { - let dw = this.pageWidth - this.bodyWidth; - columnSizes[columnSizes.length - 1] += dw; - width += dw; - x2 += dw; - } - - // Create the paint region object. - let rgn: Private.PaintRegion = { - region: 'column-header', - xMin: x1, yMin: y1, - xMax: x2, yMax: y2, - x, y, width, height, - row: r1, column: c1, - rowSizes, columnSizes - }; - - // Draw the background. - this._drawBackground(rgn, this._style.headerBackgroundColor); - - // Draw the cell content for the paint region. - this._drawCells(rgn); - - // Draw the horizontal grid lines. - this._drawHorizontalGridLines(rgn, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor - ); - - // Draw the vertical grid lines. - this._drawVerticalGridLines(rgn, - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor - ); - } - - /** - * Draw the corner header region which intersects the dirty rect. - */ - protected drawCornerHeaderRegion(rx: number, ry: number, rw: number, rh: number): void { - // Get the visible content dimensions. - let contentW = this.headerWidth; - let contentH = this.headerHeight; - - // Bail if there is no content to draw. - if (contentW <= 0 || contentH <= 0) { - return; - } - - // Get the visible content origin. - let contentX = 0; - let contentY = 0; - - // Bail if the dirty rect does not intersect the content area. - if (rx + rw <= contentX) { - return; - } - if (ry + rh <= contentY) { - return; - } - if (rx >= contentX + contentW) { - return; - } - if (ry >= contentY + contentH) { - return; - } - - // Get the upper and lower bounds of the dirty content area. - let x1 = rx; - let y1 = ry; - let x2 = Math.min(rx + rw - 1, contentX + contentW - 1); - let y2 = Math.min(ry + rh - 1, contentY + contentH - 1); - - // Convert the dirty content bounds into cell bounds. - let r1 = this._columnHeaderSections.indexOf(y1); - let c1 = this._rowHeaderSections.indexOf(x1); - let r2 = this._columnHeaderSections.indexOf(y2); - let c2 = this._rowHeaderSections.indexOf(x2); - - // Handle a dirty content area larger than the cell count. - if (r2 < 0) { - r2 = this._columnHeaderSections.count - 1; - } - if (c2 < 0) { - c2 = this._rowHeaderSections.count - 1; - } - - // Convert the cell bounds back to visible coordinates. - let x = this._rowHeaderSections.offsetOf(c1); - let y = this._columnHeaderSections.offsetOf(r1); - - // Set up the paint region size variables. - let width = 0; - let height = 0; - - // Allocate the section sizes arrays. - let rowSizes = new Array(r2 - r1 + 1); - let columnSizes = new Array(c2 - c1 + 1); - - // Get the row sizes for the region. - for (let j = r1; j <= r2; ++j) { - let size = this._columnHeaderSections.sizeOf(j); - rowSizes[j - r1] = size; - height += size; - } - - // Get the column sizes for the region. - for (let i = c1; i <= c2; ++i) { - let size = this._rowHeaderSections.sizeOf(i); - columnSizes[i - c1] = size; - width += size; - } - - // Create the paint region object. - let rgn: Private.PaintRegion = { - region: 'corner-header', - xMin: x1, yMin: y1, - xMax: x2, yMax: y2, - x, y, width, height, - row: r1, column: c1, - rowSizes, columnSizes - }; - - // Draw the background. - this._drawBackground(rgn, this._style.headerBackgroundColor); - - // Draw the cell content for the paint region. - this._drawCells(rgn); - - // Draw the horizontal grid lines. - this._drawHorizontalGridLines(rgn, - this._style.headerHorizontalGridLineColor || - this._style.headerGridLineColor - ); - - // Draw the vertical grid lines. - this._drawVerticalGridLines(rgn, - this._style.headerVerticalGridLineColor || - this._style.headerGridLineColor - ); - } - - /** - * Draw the background for the given paint region. - */ - private _drawBackground(rgn: Private.PaintRegion, color: string | undefined): void { - // Bail if there is no color to draw. - if (!color) { - return; - } - - // Unpack the region. - let { xMin, yMin, xMax, yMax } = rgn; - - // Fill the region with the specified color. - this._canvasGC.fillStyle = color; - this._canvasGC.fillRect(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); - } - - /** - * Draw the row background for the given paint region. - */ - private _drawRowBackground(rgn: Private.PaintRegion, colorFn: ((i: number) => string) | undefined): void { - // Bail if there is no color function. - if (!colorFn) { - return; - } - - // Compute the X bounds for the row. - let x1 = Math.max(rgn.xMin, rgn.x); - let x2 = Math.min(rgn.x + rgn.width - 1, rgn.xMax); - - // Draw the background for the rows in the region. - for (let y = rgn.y, j = 0, n = rgn.rowSizes.length; j < n; ++j) { - // Fetch the size of the row. - let size = rgn.rowSizes[j]; - - // Skip zero sized rows. - if (size === 0) { - continue; - } - - // Get the background color for the row. - let color = colorFn(rgn.row + j); - - // Fill the row with the background color if needed. - if (color) { - let y1 = Math.max(rgn.yMin, y); - let y2 = Math.min(y + size - 1, rgn.yMax); - this._canvasGC.fillStyle = color; - this._canvasGC.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } - - // Increment the running Y coordinate. - y += size; - } - } - - /** - * Draw the column background for the given paint region. - */ - private _drawColumnBackground(rgn: Private.PaintRegion, colorFn: ((i: number) => string) | undefined): void { - // Bail if there is no color function. - if (!colorFn) { - return; - } - - // Compute the Y bounds for the column. - let y1 = Math.max(rgn.yMin, rgn.y); - let y2 = Math.min(rgn.y + rgn.height - 1, rgn.yMax); - - // Draw the background for the columns in the region. - for (let x = rgn.x, i = 0, n = rgn.columnSizes.length; i < n; ++i) { - // Fetch the size of the column. - let size = rgn.columnSizes[i]; - - // Skip zero sized columns. - if (size === 0) { - continue; - } - - // Get the background color for the column. - let color = colorFn(rgn.column + i); - - // Fill the column with the background color if needed. - if (color) { - let x1 = Math.max(rgn.xMin, x); - let x2 = Math.min(x + size - 1, rgn.xMax); - this._canvasGC.fillStyle = color; - this._canvasGC.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } - - // Increment the running X coordinate. - x += size; - } - } - - /** - * Draw the cells for the given paint region. - */ - private _drawCells(rgn: Private.PaintRegion): void { - // Bail if there is no data model. - if (!this._dataModel) { - return; - } - - // Set up the cell config object for rendering. - let config = { - x: 0, y: 0, width: 0, height: 0, - region: rgn.region, row: 0, column: 0, - value: (null as any), metadata: DataModel.emptyMetadata - }; - - // Save the buffer gc before wrapping. - this._bufferGC.save(); - - // Wrap the buffer gc for painting the cells. - let gc = new GraphicsContext(this._bufferGC); - - // Compute the actual Y bounds for the cell range. - let y1 = Math.max(rgn.yMin, rgn.y); - let y2 = Math.min(rgn.y + rgn.height - 1, rgn.yMax); - - // Loop over the columns in the region. - for (let x = rgn.x, i = 0, n = rgn.columnSizes.length; i < n; ++i) { - // Fetch the size of the column. - let width = rgn.columnSizes[i]; - - // Skip zero sized columns. - if (width === 0) { - continue; - } - - // Compute the column index. - let column = rgn.column + i; - - // Update the config for the current column. - config.x = x; - config.width = width; - config.column = column; - - // Clear the buffer rect for the column. - gc.clearRect(x, rgn.y, width, rgn.height); - - // Save the GC state. - gc.save(); - - // Loop over the rows in the column. - for (let y = rgn.y, j = 0, n = rgn.rowSizes.length; j < n; ++j) { - // Fetch the size of the row. - let height = rgn.rowSizes[j]; - - // Skip zero sized rows. - if (height === 0) { - continue; - } - - // Compute the row index. - let row = rgn.row + j; - - // Get the value for the cell. - let value: any; - try { - value = this._dataModel.data(rgn.region, row, column); - } catch (err) { - value = undefined; - console.error(err); - } - - // Get the metadata for the cell. - let metadata: DataModel.Metadata; - try { - metadata = this._dataModel.metadata(rgn.region, row, column); - } catch (err) { - metadata = DataModel.emptyMetadata; - console.error(err); - } - - // Update the config for the current cell. - config.y = y; - config.height = height; - config.row = row; - config.value = value; - config.metadata = metadata; - - // Get the renderer for the cell. - let renderer = this._cellRenderers.get(config); - - // Save the GC state. - gc.save(); - - // Paint the cell into the off-screen buffer. - try { - renderer.paint(gc, config); - } catch (err) { - console.error(err); - } - - // Restore the GC state. - gc.restore(); - - // Increment the running Y coordinate. - y += height; - } - - // Restore the GC state. - gc.restore(); - - // Compute the actual X bounds for the column. - let x1 = Math.max(rgn.xMin, x); - let x2 = Math.min(x + width - 1, rgn.xMax); - - // Blit the off-screen buffer column into the on-screen canvas. - // - // This is *much* faster than drawing directly into the on-screen - // canvas with a clip rect on the column. Managed column clipping - // is required to prevent cell renderers from needing to set up a - // clip rect for handling horizontal overflow text (slow!). - this._blitContent(this._buffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, x1, y1); - - // Increment the running X coordinate. - x += width; - } - - // Dispose of the wrapped gc. - gc.dispose(); - - // Restore the final buffer gc state. - this._bufferGC.restore(); - } - - /** - * Draw the horizontal grid lines for the given paint region. - */ - private _drawHorizontalGridLines(rgn: Private.PaintRegion, color: string | undefined): void { - // Bail if there is no color to draw. - if (!color) { - return; - } - - // Compute the X bounds for the horizontal lines. - let x1 = Math.max(rgn.xMin, rgn.x); - let x2 = Math.min(rgn.x + rgn.width, rgn.xMax + 1); - - // Begin the path for the grid lines. - this._canvasGC.beginPath(); - - // Set the line width for the grid lines. - this._canvasGC.lineWidth = 1; - - // Fetch the geometry. - let bh = this.bodyHeight; - let ph = this.pageHeight; - - // Fetch the number of grid lines to be drawn. - let n = rgn.rowSizes.length; - - // Adjust the count down if the last line shouldn't be drawn. - if (this._stretchLastRow && ph > bh) { - if (rgn.row + n === this._rowSections.count) { - n -= 1; - } - } - - // Draw the horizontal grid lines. - for (let y = rgn.y, j = 0; j < n; ++j) { - // Fetch the size of the row. - let size = rgn.rowSizes[j]; - - // Skip zero sized rows. - if (size === 0) { - continue; - } - - // Compute the Y position of the line. - let pos = y + size - 1; - - // Draw the line if it's in range of the dirty rect. - if (pos >= rgn.yMin && pos <= rgn.yMax) { - this._canvasGC.moveTo(x1, pos + 0.5); - this._canvasGC.lineTo(x2, pos + 0.5); - } - - // Increment the running Y coordinate. - y += size; - } - - // Stroke the lines with the specified color. - this._canvasGC.strokeStyle = color; - this._canvasGC.stroke(); - } - - /** - * Draw the vertical grid lines for the given paint region. - */ - private _drawVerticalGridLines(rgn: Private.PaintRegion, color: string | undefined): void { - // Bail if there is no color to draw. - if (!color) { - return; - } - - // Merged cell range indieces - const model = this.dataModel as ViewBasedJSONModel; - - // Compute the Y bounds for the vertical lines. - let y1 = Math.max(rgn.yMin, rgn.y); - let y2 = Math.min(rgn.y + rgn.height, rgn.yMax + 1); - - // Begin the path for the grid lines - this._canvasGC.beginPath(); - - // Set the line width for the grid lines. - this._canvasGC.lineWidth = 1; - - // Fetch the geometry. - let bw = this.bodyWidth; - let pw = this.pageWidth; - - // Fetch the number of grid lines to be drawn. - let n = rgn.columnSizes.length; - - // Adjust the count down if the last line shouldn't be drawn. - if (this._stretchLastColumn && pw > bw) { - if (rgn.column + n === this._columnSections.count) { - n -= 1; - } - } - - const isColumnHeader = rgn.region === 'column-header'; - - // Draw the vertical grid lines. - for (let x = rgn.x, i = 0; i < n; ++i) { - let yStart = y1; - - if (isColumnHeader) { - for (let r = rgn.row; r < rgn.row + rgn.rowSizes.length; r++) { - const cellLeft = [r, rgn.column + i]; - const cellRight = [r, rgn.column + i + 1]; - - if (model.areCellsMerged(cellLeft, cellRight)) { - yStart += rgn.rowSizes[r - rgn.row]; - } - } - } - - // Fetch the size of the column. - let size = rgn.columnSizes[i]; - - // Skip zero sized columns. - if (size === 0) { - continue; - } - - // Compute the X position of the line. - let pos = x + size - 1; - - // Draw the line if it's in range of the dirty rect. - if (pos >= rgn.xMin && pos <= rgn.xMax) { - this._canvasGC.moveTo(pos + 0.5, yStart); - this._canvasGC.lineTo(pos + 0.5, y2); - } - - // Increment the running X coordinate. - x += size; - } - - // Stroke the lines with the specified color. - this._canvasGC.strokeStyle = color; - this._canvasGC.stroke(); - } - - /** - * Draw the body selections for the data grid. - */ - private _drawBodySelections(): void { - // Fetch the selection model. - let model = this._selectionModel; - - // Bail early if there are no selections. - if (!model || model.isEmpty) { - return; - } - - // Fetch the selection colors. - let fill = this._style.selectionFillColor; - let stroke = this._style.selectionBorderColor; - - // Bail early if there is nothing to draw. - if (!fill && !stroke) { - return; - } - - // Fetch the scroll geometry. - let sx = this._scrollX; - let sy = this._scrollY; - - // Get the first visible cell of the grid. - let r1 = this._rowSections.indexOf(sy); - let c1 = this._columnSections.indexOf(sx); - - // Bail early if there are no visible cells. - if (r1 < 0 || c1 < 0) { - return; - } - - // Fetch the extra geometry. - let bw = this.bodyWidth; - let bh = this.bodyHeight; - let pw = this.pageWidth; - let ph = this.pageHeight; - let hw = this.headerWidth; - let hh = this.headerHeight; - - // Get the last visible cell of the grid. - let r2 = this._rowSections.indexOf(sy + ph); - let c2 = this._columnSections.indexOf(sx + pw); - - // Fetch the max row and column. - let maxRow = this._rowSections.count - 1; - let maxColumn = this._columnSections.count - 1; - - // Clamp the last cell if the void space is visible. - r2 = r2 < 0 ? maxRow : r2; - c2 = c2 < 0 ? maxColumn : c2; - - // Fetch the overlay gc. - let gc = this._overlayGC; - - // Save the gc state. - gc.save(); - - // Set up the body clipping rect. - gc.beginPath(); - gc.rect(hw, hh, pw, ph); - gc.clip(); - - // Set up the gc style. - if (fill) { - gc.fillStyle = fill; - } - if (stroke) { - gc.strokeStyle = stroke; - gc.lineWidth = 1; - } - - // Iterate over the selections. - let it = model.selections(); - let s: SelectionModel.Selection | undefined; - while ((s = it.next()) !== undefined) { - // Skip the section if it's not visible. - if (s.r1 < r1 && s.r2 < r1) { - continue; - } - if (s.r1 > r2 && s.r2 > r2) { - continue - } - if (s.c1 < c1 && s.c2 < c1) { - continue; - } - if (s.c1 > c2 && s.c2 > c2) { - continue - } - - // Clamp the cell to the model bounds. - let sr1 = Math.max(0, Math.min(s.r1, maxRow)); - let sc1 = Math.max(0, Math.min(s.c1, maxColumn)); - let sr2 = Math.max(0, Math.min(s.r2, maxRow)); - let sc2 = Math.max(0, Math.min(s.c2, maxColumn)); - - // Swap index order if needed. - let tmp: number; - if (sr1 > sr2) { - tmp = sr1; - sr1 = sr2; - sr2 = tmp; - } - if (sc1 > sc2) { - tmp = sc1; - sc1 = sc2; - sc2 = tmp; - } - - // Convert to pixel coordinates. - let x1 = this._columnSections.offsetOf(sc1) - sx + hw; - let y1 = this._rowSections.offsetOf(sr1) - sy + hh; - let x2 = this._columnSections.extentOf(sc2) - sx + hw; - let y2 = this._rowSections.extentOf(sr2) - sy + hh; - - // Adjust the trailing X coordinate for column stretch. - if (this._stretchLastColumn && pw > bw && sc2 === maxColumn) { - x2 = hw + pw - 1; - } - - // Adjust the trailing Y coordinate for row stretch. - if (this._stretchLastRow && ph > bh && sr2 === maxRow) { - y2 = hh + ph - 1; - } - - // Clamp the bounds to just outside of the clipping rect. - x1 = Math.max(hw - 1, x1); - y1 = Math.max(hh - 1, y1); - x2 = Math.min(hw + pw + 1, x2); - y2 = Math.min(hh + ph + 1, y2); - - // Skip zero sized ranges. - if (x2 < x1 || y2 < y1) { - continue; - } - - // Fill the rect if needed. - if (fill) { - gc.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } - - // Stroke the rect if needed. - if (stroke) { - gc.strokeRect(x1 - .5, y1 - .5, x2 - x1 + 1, y2 - y1 + 1); - } - } - - // Restore the gc state. - gc.restore(); - } - - /** - * Draw the row header selections for the data grid. - */ - private _drawRowHeaderSelections(): void { - // Fetch the selection model. - let model = this._selectionModel; - - // Bail early if there are no selections or if the selectionMode is the entire column. - if (!model || model.isEmpty || model.selectionMode == 'column') { - return; - } - - // Bail early if the row headers are not visible. - if (this.headerWidth === 0 || this.pageHeight === 0) { - return; - } - - // Fetch the selection colors. - let fill = this._style.headerSelectionFillColor; - let stroke = this._style.headerSelectionBorderColor; - - // Bail early if there is nothing to draw. - if (!fill && !stroke) { - return; - } - - // Fetch common geometry. - let sy = this._scrollY; - let bh = this.bodyHeight; - let ph = this.pageHeight; - let hw = this.headerWidth; - let hh = this.headerHeight; - let rs = this._rowSections; - - // Fetch the overlay gc. - let gc = this._overlayGC; - - // Save the gc state. - gc.save(); - - // Set up the header clipping rect. - gc.beginPath(); - gc.rect(0, hh, hw, ph); - gc.clip(); - - // Set up the gc style. - if (fill) { - gc.fillStyle = fill; - } - if (stroke) { - gc.strokeStyle = stroke; - gc.lineWidth = 1; - } - - // Fetch the max row. - let maxRow = rs.count - 1; - - // Fetch the visible rows. - let r1 = rs.indexOf(sy); - let r2 = rs.indexOf(sy + ph - 1); - r2 = r2 < 0 ? maxRow : r2; - - // Iterate over the visible rows. - for (let j = r1; j <= r2; ++j) { - // Skip rows which aren't selected. - if (!model.isRowSelected(j)) { - continue; - } - - // Get the dimensions of the row. - let y = rs.offsetOf(j) - sy + hh; - let h = rs.sizeOf(j); - - // Adjust the height for row stretch. - if (this._stretchLastRow && ph > bh && j === maxRow) { - h = hh + ph - y; - } - - // Skip zero sized rows. - if (h === 0) { - continue; - } - - // Fill the rect if needed. - if (fill) { - gc.fillRect(0, y, hw, h); - } - - // Draw the border if needed. - if (stroke) { - gc.beginPath(); - gc.moveTo(hw - .5, y - 1); - gc.lineTo(hw - .5, y + h); - gc.stroke(); - } - } - - // Restore the gc state. - gc.restore(); - } - - /** - * Draw the column header selections for the data grid. - */ - private _drawColumnHeaderSelections(): void { - // Fetch the selection model. - let model = this._selectionModel; - - // Bail early if there are no selections or if the selectionMode is the entire row - if (!model || model.isEmpty || model.selectionMode == 'row') { - return; - } - - // Bail early if the column headers are not visible. - if (this.headerHeight === 0 || this.pageWidth === 0) { - return; - } - - // Fetch the selection colors. - let fill = this._style.headerSelectionFillColor; - let stroke = this._style.headerSelectionBorderColor; - - // Bail early if there is nothing to draw. - if (!fill && !stroke) { - return; - } - - // Fetch common geometry. - let sx = this._scrollX; - let bw = this.bodyWidth; - let pw = this.pageWidth; - let hw = this.headerWidth; - let hh = this.headerHeight; - let cs = this._columnSections; - - // Fetch the overlay gc. - let gc = this._overlayGC; - - // Save the gc state. - gc.save(); - - // Set up the header clipping rect. - gc.beginPath(); - gc.rect(hw, 0, pw, hh); - gc.clip(); - - // Set up the gc style. - if (fill) { - gc.fillStyle = fill; - } - if (stroke) { - gc.strokeStyle = stroke; - gc.lineWidth = 1; - } - - // Fetch the max column. - let maxCol = cs.count - 1; - - // Fetch the visible columns. - let c1 = cs.indexOf(sx); - let c2 = cs.indexOf(sx + pw - 1); - c2 = c2 < 0 ? maxCol : c2; - - // Iterate over the visible columns. - for (let i = c1; i <= c2; ++i) { - // Skip columns which aren't selected. - if (!model.isColumnSelected(i)) { - continue; - } - - // Get the dimensions of the column. - let x = cs.offsetOf(i) - sx + hw; - let w = cs.sizeOf(i); - - // Adjust the width for column stretch. - if (this._stretchLastColumn && pw > bw && i === maxCol) { - w = hw + pw - x; - } - - // Skip zero sized columns. - if (w === 0) { - continue; - } - - // Fill the rect if needed. - if (fill) { - gc.fillRect(x, 0, w, hh); - } - - // Draw the border if needed. - if (stroke) { - gc.beginPath(); - gc.moveTo(x - 1, hh - .5); - gc.lineTo(x + w, hh - .5); - gc.stroke(); - } - } - - // Restore the gc state. - gc.restore(); - } - - /** - * Draw the overlay cursor for the data grid. - */ - private _drawCursor(): void { - // Fetch the selection model. - let model = this._selectionModel; - - // Bail early if there is no cursor. - if (!model || model.isEmpty || model.selectionMode !== 'cell') { - return; - } - - // Extract the style information. - let fill = this._style.cursorFillColor; - let stroke = this._style.cursorBorderColor; - - // Bail early if there is nothing to draw. - if (!fill && !stroke) { - return; - } - - // Fetch the cursor location. - let row = model.cursorRow; - let column = model.cursorColumn; - - // Fetch the max row and column. - let maxRow = this._rowSections.count - 1; - let maxColumn = this._columnSections.count - 1; - - // Bail early if the cursor is out of bounds. - if (row < 0 || row > maxRow) { - return; - } - if (column < 0 || column > maxColumn) { - return; - } - - // Fetch geometry. - let sx = this._scrollX; - let sy = this._scrollY; - let bw = this.bodyWidth; - let bh = this.bodyHeight; - let pw = this.pageWidth; - let ph = this.pageHeight; - let hw = this.headerWidth; - let hh = this.headerHeight; - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // Get the cursor bounds in viewport coordinates. - let x1 = this._columnSections.offsetOf(column) - sx + hw; - let x2 = this._columnSections.extentOf(column) - sx + hw; - let y1 = this._rowSections.offsetOf(row) - sy + hh; - let y2 = this._rowSections.extentOf(row) - sy + hh; - - // Adjust the trailing X coordinate for column stretch. - if (this._stretchLastColumn && pw > bw && column === maxColumn) { - x2 = vw - 1; - } - - // Adjust the trailing Y coordinate for row stretch. - if (this._stretchLastRow && ph > bh && row === maxRow) { - y2 = vh - 1; - } - - // Skip zero sized cursors. - if (x2 < x1 || y2 < y1) { - return; - } - - // Bail early if the cursor is off the screen. - if ((x1 - 1) >= vw || (y1 - 1) >= vh || (x2 + 1) < hw || (y2 + 1) < hh) { - return; - } - - // Fetch the overlay gc. - let gc = this._overlayGC; - - // Save the gc state. - gc.save(); - - // Set up the body clipping rect. - gc.beginPath(); - gc.rect(hw, hh, pw, ph); - gc.clip(); - - // Clear any existing overlay content. - gc.clearRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); - - // Fill the cursor rect if needed. - if (fill) { - // Set up the fill style. - gc.fillStyle = fill; - - // Fill the cursor rect. - gc.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1) - } - - // Stroke the cursor border if needed. - if (stroke) { - // Set up the stroke style. - gc.strokeStyle = stroke; - gc.lineWidth = 2; - - // Stroke the cursor rect. - gc.strokeRect(x1, y1, x2 - x1, y2 - y1); - } - - // Restore the gc state. - gc.restore(); - } - - /** - * Draw the overlay shadows for the data grid. - */ - private _drawShadows(): void { - // Fetch the scroll shadow from the style. - let shadow = this._style.scrollShadow; - - // Bail early if there is no shadow to draw. - if (!shadow) { - return; - } - - // Fetch the scroll position. - let sx = this._scrollX; - let sy = this._scrollY; - - // Fetch maximum scroll position. - let sxMax = this.maxScrollX; - let syMax = this.maxScrollY; - - // Fetch the header width and height. - let hw = this.headerWidth; - let hh = this.headerHeight; - - // Fetch the page width and height. - let pw = this.pageWidth; - let ph = this.pageHeight; - - // Fetch the viewport width and height. - let vw = this._viewportWidth; - let vh = this._viewportHeight; - - // Fetch the body width and height. - let bw = this.bodyWidth; - let bh = this.bodyHeight; - - // Adjust the body size for row and column stretch. - if (this._stretchLastRow && ph > bh) { - bh = ph; - } - if (this._stretchLastColumn && pw > bw) { - bw = pw; - } - - // Fetch the gc object. - let gc = this._overlayGC; - - // Save the gc state. - gc.save(); - - // Draw the column header shadow if needed. - if (sy > 0) { - // Set up the gradient coordinates. - let x0 = 0; - let y0 = hh; - let x1 = 0; - let y1 = y0 + shadow.size; - - // Create the gradient object. - let grad = gc.createLinearGradient(x0, y0, x1, y1); - - // Set the gradient stops. - grad.addColorStop(0, shadow.color1); - grad.addColorStop(0.5, shadow.color2); - grad.addColorStop(1, shadow.color3); - - // Set up the rect coordinates. - let x = 0; - let y = hh; - let w = hw + Math.min(pw, bw - sx); - let h = shadow.size; - - // Fill the shadow rect with the fill style. - gc.fillStyle = grad; - gc.fillRect(x, y, w, h); - } - - // Draw the row header shadow if needed. - if (sx > 0) { - // Set up the gradient coordinates. - let x0 = hw; - let y0 = 0; - let x1 = x0 + shadow.size; - let y1 = 0; - - // Create the gradient object. - let grad = gc.createLinearGradient(x0, y0, x1, y1); - - // Set the gradient stops. - grad.addColorStop(0, shadow.color1); - grad.addColorStop(0.5, shadow.color2); - grad.addColorStop(1, shadow.color3); - - // Set up the rect coordinates. - let x = hw; - let y = 0; - let w = shadow.size; - let h = hh + Math.min(ph, bh - sy); - - // Fill the shadow rect with the fill style. - gc.fillStyle = grad; - gc.fillRect(x, y, w, h); - } - - // Draw the column footer shadow if needed. - if (sy < syMax) { - // Set up the gradient coordinates. - let x0 = 0; - let y0 = vh; - let x1 = 0; - let y1 = vh - shadow.size; - - // Create the gradient object. - let grad = gc.createLinearGradient(x0, y0, x1, y1); - - // Set the gradient stops. - grad.addColorStop(0, shadow.color1); - grad.addColorStop(0.5, shadow.color2); - grad.addColorStop(1, shadow.color3); - - // Set up the rect coordinates. - let x = 0; - let y = vh - shadow.size; - let w = hw + Math.min(pw, bw - sx); - let h = shadow.size; - - // Fill the shadow rect with the fill style. - gc.fillStyle = grad; - gc.fillRect(x, y, w, h); - } - - // Draw the row footer shadow if needed. - if (sx < sxMax) { - // Set up the gradient coordinates. - let x0 = vw; - let y0 = 0; - let x1 = vw - shadow.size; - let y1 = 0; - - // Create the gradient object. - let grad = gc.createLinearGradient(x0, y0, x1, y1); - - // Set the gradient stops. - grad.addColorStop(0, shadow.color1); - grad.addColorStop(0.5, shadow.color2); - grad.addColorStop(1, shadow.color3); - - // Set up the rect coordinates. - let x = vw - shadow.size; - let y = 0; - let w = shadow.size; - let h = hh + Math.min(ph, bh - sy); - - // Fill the shadow rect with the fill style. - gc.fillStyle = grad; - gc.fillRect(x, y, w, h); - } - - // Restore the gc state. - gc.restore(); - } - - private _viewport: Widget; - private _vScrollBar: ScrollBar; - private _hScrollBar: ScrollBar; - private _scrollCorner: Widget; - - private _scrollX = 0; - private _scrollY = 0; - private _viewportWidth = 0; - private _viewportHeight = 0; - - private _mousedown = false; - private _keyHandler: DataGrid.IKeyHandler | null = null; - private _mouseHandler: DataGrid.IMouseHandler | null = null; - - private _vScrollBarMinWidth = 0; - private _hScrollBarMinHeight = 0; - private _dpiRatio = Math.ceil(window.devicePixelRatio); - - private _canvas: HTMLCanvasElement; - private _buffer: HTMLCanvasElement; - private _overlay: HTMLCanvasElement; - private _canvasGC: CanvasRenderingContext2D; - private _bufferGC: CanvasRenderingContext2D; - private _overlayGC: CanvasRenderingContext2D; - - private _rowSections: SectionList; - private _columnSections: SectionList; - private _rowHeaderSections: SectionList; - private _columnHeaderSections: SectionList; - - private _dataModel: DataModel | null = null; - private _selectionModel: SelectionModel | null = null; - - private _stretchLastRow: boolean; - private _stretchLastColumn: boolean; - - private _style: DataGrid.Style; - private _cellRenderers: RendererMap; - private _copyConfig: DataGrid.CopyConfig; - private _headerVisibility: DataGrid.HeaderVisibility; - private _editorController: ICellEditorController | null; - private _editingEnabled: boolean = false; -} - - -/** - * The namespace for the `DataGrid` class statics. - */ -export -namespace DataGrid { - /** - * An object which defines the style for a data grid. - * - * #### Notes - * All style colors support the full CSS color syntax. - */ - export - type Style = { - /** - * The void color for the data grid. - * - * This is the base fill color for the entire data grid. - */ - readonly voidColor?: string; - - /** - * The background color for the body cells. - * - * This color is layered on top of the `voidColor`. - */ - readonly backgroundColor?: string; - - /** - * A function which returns the background color for a row. - * - * This color is layered on top of the `backgroundColor` and can - * be used to implement "zebra striping" of the grid rows. - */ - readonly rowBackgroundColor?: (index: number) => string; - - /** - * A function which returns the background color for a column. - * - * This color is layered on top of the `backgroundColor` and can - * be used to implement "zebra striping" of the grid columns. - */ - readonly columnBackgroundColor?: (index: number) => string; - - /** - * The color for the grid lines of the body cells. - * - * The grid lines are draw on top of the cell contents. - */ - readonly gridLineColor?: string; - - /** - * The color for the vertical grid lines of the body cells. - * - * This overrides the `gridLineColor` option. - */ - readonly verticalGridLineColor?: string; - - /** - * The color for the horizontal grid lines of the body cells. - * - * This overrides the `gridLineColor` option. - */ - readonly horizontalGridLineColor?: string; - - /** - * The background color for the header cells. - * - * This color is layered on top of the `voidColor`. - */ - readonly headerBackgroundColor?: string; - - /** - * The color for the grid lines of the header cells. - * - * The grid lines are draw on top of the cell contents. - */ - readonly headerGridLineColor?: string; - - /** - * The color for the vertical grid lines of the header cells. - * - * This overrides the `headerGridLineColor` option. - */ - readonly headerVerticalGridLineColor?: string; - - /** - * The color for the horizontal grid lines of the header cells. - * - * This overrides the `headerGridLineColor` option. - */ - readonly headerHorizontalGridLineColor?: string; - - /** - * The fill color for a selection. - */ - readonly selectionFillColor?: string; - - /** - * The border color for a selection. - */ - readonly selectionBorderColor?: string; - - /** - * The fill color for the cursor. - */ - readonly cursorFillColor?: string; - - /** - * The border color for the cursor. - */ - readonly cursorBorderColor?: string; - - /** - * The fill color for a header selection. - */ - readonly headerSelectionFillColor?: string; - - /** - * The border color for a header selection. - */ - readonly headerSelectionBorderColor?: string; - - /** - * The drop shadow effect when the grid is scrolled. - */ - readonly scrollShadow?: { - /** - * The size of the shadow, in pixels. - */ - readonly size: number; - - /** - * The first color stop for the shadow. - */ - readonly color1: string; - - /** - * The second color stop for the shadow. - */ - readonly color2: string; - - /** - * The third color stop for the shadow. - */ - readonly color3: string; - }; - }; - - /** - * An object which defines the default sizes for a data grid. - */ - export - type DefaultSizes = { - /** - * The default height of a row. - */ - readonly rowHeight: number; - - /** - * The default width of a column. - */ - readonly columnWidth: number; - - /** - * The default width of a row header. - */ - readonly rowHeaderWidth: number; - - /** - * The default height of a column header. - */ - readonly columnHeaderHeight: number; - }; - - /** - * An object which defines the minimum sizes for a data grid. - */ - export - type MinimumSizes = { - /** - * The minimum height of a row. - */ - readonly rowHeight: number; - - /** - * The minimum width of a column. - */ - readonly columnWidth: number; - - /** - * The minimum width of a row header. - */ - readonly rowHeaderWidth: number; - - /** - * The minimum height of a column header. - */ - readonly columnHeaderHeight: number; - }; - - /** - * A type alias for the supported header visibility modes. - */ - export - type HeaderVisibility = 'all' | 'row' | 'column' | 'none'; - - /** - * A type alias for the arguments to a copy format function. - */ - export - type CopyFormatArgs = { - /** - * The cell region for the value. - */ - region: DataModel.CellRegion; - - /** - * The row index of the value. - */ - row: number; - - /** - * The column index of the value. - */ - column: number; - - /** - * The value for the cell. - */ - value: any; - - /** - * The metadata for the cell. - */ - metadata: DataModel.Metadata; - }; - - /** - * A type alias for a copy format function. - */ - export - type CopyFormatFunc = (args: CopyFormatArgs) => string; - - /** - * A type alias for the data grid copy config. - */ - export - type CopyConfig = { - /** - * The separator to use between values. - */ - readonly separator: string; - - /** - * The headers to included in the copied output. - */ - readonly headers: 'none' | 'row' | 'column' | 'all'; - - /** - * The function for formatting the data values. - */ - readonly format: CopyFormatFunc; - - /** - * The cell count threshold for a copy to be considered "large". - */ - readonly warningThreshold: number; - }; - - /** - * An options object for initializing a data grid. - */ - export - interface IOptions { - /** - * The style for the data grid. - * - * The default is `DataGrid.defaultStyle`. - */ - style?: Style; - - /** - * The default sizes for the data grid. - * - * The default is `DataGrid.defaultSizes`. - */ - defaultSizes?: DefaultSizes; - - /** - * The minimum sizes for the data grid. - * - * The default is `DataGrid.minimumSizes`. - */ - minimumSizes?: MinimumSizes; - - /** - * The header visibility for the data grid. - * - * The default is `'all'`. - */ - headerVisibility?: HeaderVisibility; - - /** - * The cell renderer map for the data grid. - * - * The default is an empty renderer map. - */ - cellRenderers?: RendererMap; - - /** - * The default cell renderer for the data grid. - * - * The default is a new `TextRenderer`. - */ - defaultRenderer?: CellRenderer; - - /** - * The copy configuration data for the grid. - * - * The default is `DataGrid.defaultCopyConfig`. - */ - copyConfig?: CopyConfig; - - /** - * Whether to stretch the last row of the grid. - * - * The default is `false`. - */ - stretchLastRow?: boolean; - - /** - * Whether to stretch the last column of the grid. - * - * The default is `false`. - */ - stretchLastColumn?: boolean; - } - - /** - * An object which handles keydown events for the data grid. - */ - export - interface IKeyHandler extends IDisposable { - /** - * Handle the key down event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The keydown event of interest. - * - * #### Notes - * This will not be called if the mouse button is pressed. - */ - onKeyDown(grid: DataGrid, event: KeyboardEvent): void; - } - - /** - * An object which handles mouse events for the data grid. - */ - export - interface IMouseHandler extends IDisposable { - /** - * Release any resources acquired during a mouse press. - * - * #### Notes - * This method is called when the mouse should be released - * independent of a mouseup event, such as an early detach. - */ - release(): void; - - /** - * Handle the mouse hover event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse hover event of interest. - */ - onMouseHover(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the mouse leave event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse hover event of interest. - */ - onMouseLeave(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the mouse down event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse down event of interest. - */ - onMouseDown(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the mouse move event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse move event of interest. - */ - onMouseMove(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the mouse up event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse up event of interest. - */ - onMouseUp(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the mouse double click event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The mouse double click event of interest. - */ - onMouseDoubleClick(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the context menu event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The context menu event of interest. - */ - onContextMenu(grid: DataGrid, event: MouseEvent): void; - - /** - * Handle the wheel event for the data grid. - * - * @param grid - The data grid of interest. - * - * @param event - The wheel event of interest. - */ - onWheel(grid: DataGrid, event: WheelEvent): void; - } - - /** - * An object which holds the result of a grid hit test. - */ - export - type HitTestResult = { - /** - * The region of the data grid that was hit. - */ - readonly region: DataModel.CellRegion | 'void'; - - /** - * The row index of the cell that was hit. - * - * This is `-1` for the `void` region. - */ - readonly row: number; - - /** - * The column index of the cell that was hit. - * - * This is `-1` for the `void` region. - */ - readonly column: number; - - /** - * The X coordinate of the mouse in cell coordinates. - * - * This is `-1` for the `void` region. - */ - readonly x: number; - - /** - * The Y coordinate of the mouse in cell coordinates. - * - * This is `-1` for the `void` region. - */ - readonly y: number; - - /** - * The width of the cell. - * - * This is `-1` for the `void` region. - */ - readonly width: number; - - /** - * The height of the cell. - * - * This is `-1` for the `void` region. - */ - readonly height: number; - }; - - /** - * A generic format function for the copy handler. - * - * @param args - The format args for the function. - * - * @returns The string representation of the value. - * - * #### Notes - * This function uses `String()` to coerce a value to a string. - */ - export - function copyFormatGeneric(args: CopyFormatArgs): string { - if (args.value === null || args.value === undefined) { - return ''; - } - return String(args.value); - } - - /** - * The default theme for a data grid. - */ - export - const defaultStyle: Style = { - voidColor: '#F3F3F3', - backgroundColor: '#FFFFFF', - gridLineColor: 'rgba(20, 20, 20, 0.15)', - headerBackgroundColor: '#F3F3F3', - headerGridLineColor: 'rgba(20, 20, 20, 0.25)', - selectionFillColor: 'rgba(49, 119, 229, 0.2)', - selectionBorderColor: 'rgba(0, 107, 247, 1.0)', - cursorBorderColor: 'rgba(0, 107, 247, 1.0)', - headerSelectionFillColor: 'rgba(20, 20, 20, 0.1)', - headerSelectionBorderColor: 'rgba(0, 107, 247, 1.0)', - scrollShadow: { - size: 10, - color1: 'rgba(0, 0, 0, 0.20)', - color2: 'rgba(0, 0, 0, 0.05)', - color3: 'rgba(0, 0, 0, 0.00)' } - }; - - /** - * The default sizes for a data grid. - */ - export - const defaultSizes: DefaultSizes = { - rowHeight: 20, - columnWidth: 64, - rowHeaderWidth: 64, - columnHeaderHeight: 20 - }; - - /** - * The default minimum sizes for a data grid. - */ - export - const minimumSizes: MinimumSizes = { - rowHeight: 20, - columnWidth: 10, - rowHeaderWidth: 10, - columnHeaderHeight: 20 - }; - - /** - * The default copy config for a data grid. - */ - export - const defaultCopyConfig: CopyConfig = { - separator: '\t', - format: copyFormatGeneric, - headers: 'none', - warningThreshold: 1e6 - }; -} - - -/** - * The namespace for the module implementation details. - */ -namespace Private { - /** - * A singleton `scroll-request` conflatable message. - */ - export - const ScrollRequest = new ConflatableMessage('scroll-request'); - - /** - * A singleton `section-resize-request` conflatable message. - */ - export - const SectionResizeRequest = new ConflatableMessage('section-resize-request'); - - /** - * A singleton `overlay-paint-request` conflatable message. - */ - export - const OverlayPaintRequest = new ConflatableMessage('overlay-paint-request'); - - /** - * Create a new zero-sized canvas element. - */ - export - function createCanvas(): HTMLCanvasElement { - let canvas = document.createElement('canvas'); - canvas.width = 0; - canvas.height = 0; - return canvas; - } - - /** - * Clamp a section size to the limits. - */ - export - function clampSectionSize(size: number): number { - return Math.max(10, Math.floor(size)); - } - - /** - * An object which represents a region to be painted. - */ - export - type PaintRegion = { - /** - * The min X coordinate the of the dirty viewport rect. - * - * #### Notes - * The data grid must not draw outside of this boundary. - */ - xMin: number; - - /** - * The min Y coordinate the of the dirty viewport rect. - * - * #### Notes - * The data grid must not draw outside of this boundary. - */ - yMin: number; - - /** - * The max X coordinate the of the dirty viewport rect. - * - * #### Notes - * The data grid must not draw outside of this boundary. - */ - xMax: number; - - /** - * The max Y coordinate the of the dirty viewport rect. - * - * #### Notes - * The data grid must not draw outside of this boundary. - */ - yMax: number; - - /** - * The X coordinate the of the region, in viewport coordinates. - * - * #### Notes - * This is aligned to the first cell boundary. - */ - x: number; - - /** - * The Y coordinate the of the region, in viewport coordinates. - * - * #### Notes - * This is aligned to the first cell boundary. - */ - y: number; - - /** - * The total width of the region. - * - * #### Notes - * This is aligned to the cell boundaries. - */ - width: number; - - /** - * The total height of the region. - * - * #### Notes - * This is aligned to the cell boundaries. - */ - height: number; - - /** - * The cell region being painted. - */ - region: DataModel.CellRegion; - - /** - * The row index of the first cell in the region. - */ - row: number; - - /** - * The column index of the first cell in the region. - */ - column: number; - - /** - * The row sizes for the rows in the region. - */ - rowSizes: number[]; - - /** - * The column sizes for the columns in the region. - */ - columnSizes: number[]; - }; - - /** - * A conflatable message which merges dirty paint regions. - */ - export - class PaintRequest extends ConflatableMessage { - /** - * Construct a new paint request messages. - * - * @param region - The cell region for the paint. - * - * @param r1 - The top-left row of the dirty region. - * - * @param c1 - The top-left column of the dirty region. - * - * @param r2 - The bottom-right row of the dirty region. - * - * @param c2 - The bottom-right column of the dirty region. - */ - constructor(region: DataModel.CellRegion | 'all', r1: number, c1: number, r2: number, c2: number) { - super('paint-request'); - this._region = region; - this._r1 = r1; - this._c1 = c1; - this._r2 = r2; - this._c2 = c2; - } - - /** - * The cell region for the paint. - */ - get region(): DataModel.CellRegion | 'all' { - return this._region; - } - - /** - * The top-left row of the dirty region. - */ - get r1(): number { - return this._r1; - } - - /** - * The top-left column of the dirty region. - */ - get c1(): number { - return this._c1; - } - - /** - * The bottom-right row of the dirty region. - */ - get r2(): number { - return this._r2; - } - - /** - * The bottom-right column of the dirty region. - */ - get c2(): number { - return this._c2; - } - - /** - * Conflate this message with another paint request. - */ - conflate(other: PaintRequest): boolean { - // Bail early if the request is already painting everything. - if (this._region === 'all') { - return true; - } - - // Any region can conflate with the `'all'` region. - if (other._region === 'all') { - this._region = 'all'; - return true; - } - - // Otherwise, do not conflate with a different region. - if (this._region !== other._region) { - return false; - } - - // Conflate the region to the total boundary. - this._r1 = Math.min(this._r1, other._r1); - this._c1 = Math.min(this._c1, other._c1); - this._r2 = Math.max(this._r2, other._r2); - this._c2 = Math.max(this._c2, other._c2); - return true; - } - - private _region: DataModel.CellRegion | 'all'; - private _r1: number; - private _c1: number; - private _r2: number; - private _c2: number; - } - - /** - * A conflatable message for resizing rows. - */ - export - class RowResizeRequest extends ConflatableMessage { - /** - * Construct a new row resize request. - * - * @param region - The row region which holds the section. - * - * @param index - The index of row in the region. - * - * @param size - The target size of the section. - */ - constructor(region: DataModel.RowRegion, index: number, size: number) { - super('row-resize-request'); - this._region = region; - this._index = index; - this._size = size; - } - - /** - * The row region which holds the section. - */ - get region(): DataModel.RowRegion { - return this._region; - } - - /** - * The index of the row in the region. - */ - get index(): number { - return this._index; - } - - /** - * The target size of the section. - */ - get size(): number { - return this._size; - } - - /** - * Conflate this message with another row resize request. - */ - conflate(other: RowResizeRequest): boolean { - if (this._region !== other._region || this._index !== other._index) { - return false; - } - this._size = other._size; - return true; - } - - private _region: DataModel.RowRegion; - private _index: number; - private _size: number; - } - - /** - * A conflatable message for resizing columns. - */ - export - class ColumnResizeRequest extends ConflatableMessage { - /** - * Construct a new column resize request. - * - * @param region - The column region which holds the section. - * - * @param index - The index of column in the region. - * - * @param size - The target size of the section. - */ - constructor(region: DataModel.ColumnRegion, index: number, size: number) { - super('column-resize-request'); - this._region = region; - this._index = index; - this._size = size; - } - - /** - * The column region which holds the section. - */ - get region(): DataModel.ColumnRegion { - return this._region; - } - - /** - * The index of the column in the region. - */ - get index(): number { - return this._index; - } - - /** - * The target size of the section. - */ - get size(): number { - return this._size; - } - - /** - * Conflate this message with another column resize request. - */ - conflate(other: ColumnResizeRequest): boolean { - if (this._region !== other._region || this._index !== other._index) { - return false; - } - this._size = other._size; - return true; - } - - private _region: DataModel.ColumnRegion; - private _index: number; - private _size: number; - } -} From 9ec394f15bf4e99ed8929b2fddaf0e6324f9fd76 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 20:11:24 -0700 Subject: [PATCH 15/20] Remove custom nested columns rendering logic in headerrenderer.ts Signed-off-by: Itay Dafna --- js/core/headerRenderer.ts | 115 +++----------------------------------- 1 file changed, 8 insertions(+), 107 deletions(-) diff --git a/js/core/headerRenderer.ts b/js/core/headerRenderer.ts index 80ed4bf8..22cd960f 100644 --- a/js/core/headerRenderer.ts +++ b/js/core/headerRenderer.ts @@ -25,65 +25,6 @@ export class HeaderRenderer extends TextRenderer { return this._grid.dataModel as ViewBasedJSONModel; } - /** - * Draw the background for the cell. - * - * @param gc - The graphics context to use for drawing. - * - * @param config - The configuration data for the cell. - */ - drawBackground(gc: GraphicsContext, config: CellRenderer.CellConfig): void { - const merges = - config.region === 'column-header' - ? this.model.getMergedSiblingCells([config.row, config.column]) - : []; - - // Resolve the background color for the cell. - const color = CellRenderer.resolveOption(this.backgroundColor, config); - - // Bail if there is no background color to draw. - if (!color) { - return; - } - - if (merges.length > 1) { - let xStart = Number.MAX_SAFE_INTEGER; - let yStart = Number.MAX_SAFE_INTEGER; - let xEnd = Number.MIN_SAFE_INTEGER; - let yEnd = Number.MIN_SAFE_INTEGER; - - const grid = this._grid!; - for (const merge of merges) { - const [row, column] = merge; - - const headerOffset = - config.region === 'corner-header' - ? 0 - : this._grid!.headerWidth - this._grid.scrollX; - const x1 = grid.columnOffset('body', column) + headerOffset; - const y1 = grid.rowOffset('column-header', row); - const x2 = x1 + grid.columnSize('body', column); - const y2 = y1 + grid.rowSize('column-header', row); - xStart = Math.min(xStart, x1); - yStart = Math.min(yStart, y1); - xEnd = Math.max(xEnd, x2); - yEnd = Math.max(yEnd, y2); - } - - const width = xEnd - xStart; - const height = yEnd - yStart; - - // Fill the cell with the background color. - gc.fillStyle = color; - - gc.fillRect(xStart, yStart, width, height); - } else { - // Fill the cell with the background color. - gc.fillStyle = color; - gc.fillRect(config.x, config.y, config.width, config.height); - } - } - /** * Draw the text for the cell. * @@ -117,52 +58,12 @@ export class HeaderRenderer extends TextRenderer { return; } - const merges = - config.region === 'column-header' - ? this.model.getMergedSiblingCells([config.row, config.column]) - : []; - - let width = config.width; - let height = config.height; - let x = config.x; - let y = config.y; - - if (merges.length > 1) { - let xStart = Number.MAX_SAFE_INTEGER; - let yStart = Number.MAX_SAFE_INTEGER; - let xEnd = Number.MIN_SAFE_INTEGER; - let yEnd = Number.MIN_SAFE_INTEGER; - - for (const merge of merges) { - const [row, column] = merge; - const grid = this._grid!; - - const offsetX = - config.region === 'corner-header' - ? 0 - : this._grid!.headerWidth - this._grid.scrollX; - const x1 = grid.columnOffset('body', column) + offsetX; - const y1 = grid.rowOffset('column-header', row); - const x2 = x1 + grid.columnSize('body', column); - const y2 = y1 + grid.rowSize('column-header', row); - xStart = Math.min(xStart, x1); - yStart = Math.min(yStart, y1); - xEnd = Math.max(xEnd, x2); - yEnd = Math.max(yEnd, y2); - - width = xEnd - xStart; - height = yEnd - yStart; - x = xStart; - y = yStart; - } - } - // Resolve the vertical and horizontal alignment. const vAlign = CellRenderer.resolveOption(this.verticalAlignment, config); const hAlign = CellRenderer.resolveOption(this.horizontalAlignment, config); // Compute the padded text box height for the specified alignment. - const boxHeight = height - (vAlign === 'center' ? 1 : 2); + const boxHeight = config.height - (vAlign === 'center' ? 1 : 2); // Bail if the text box has no effective size. if (boxHeight <= 0) { @@ -179,13 +80,13 @@ export class HeaderRenderer extends TextRenderer { // Compute the Y position for the text. switch (vAlign) { case 'top': - textY = y + 2 + textHeight; + textY = config.y + 2 + textHeight; break; case 'center': - textY = y + height / 2 + textHeight / 2; + textY = config.y + config.height / 2 + textHeight / 2; break; case 'bottom': - textY = y + height - 2; + textY = config.y + config.height - 2; break; default: throw 'unreachable'; @@ -194,13 +95,13 @@ export class HeaderRenderer extends TextRenderer { // Compute the X position for the text. switch (hAlign) { case 'left': - textX = x + 2; + textX = config.x + 2; break; case 'center': - textX = x + width / 2; + textX = config.x + config.width / 2; break; case 'right': - textX = x + width - 3; + textX = config.x + config.width - 3; break; default: throw 'unreachable'; @@ -209,7 +110,7 @@ export class HeaderRenderer extends TextRenderer { // Clip the cell if the text is taller than the text box height. if (textHeight > boxHeight) { gc.beginPath(); - gc.rect(x, y, width, height - 1); + gc.rect(config.x, config.y, config.width, config.height - 1); gc.clip(); } From 06e69e8f01db1232b6a9588ed72cf842d708bda5 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 20:22:41 -0700 Subject: [PATCH 16/20] Remove graphicscontext.ts fork Signed-off-by: Itay Dafna --- js/core/graphicscontext.ts | 558 ------------------------------------- 1 file changed, 558 deletions(-) delete mode 100644 js/core/graphicscontext.ts diff --git a/js/core/graphicscontext.ts b/js/core/graphicscontext.ts deleted file mode 100644 index e866c920..00000000 --- a/js/core/graphicscontext.ts +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (c) Jupyter Development Team. -// Distributed under the terms of the Modified BSD License. -/*----------------------------------------------------------------------------- -| Copyright (c) 2014-2019, PhosphorJS Contributors -| -| Distributed under the terms of the BSD 3-Clause License. -| -| The full license is in the file LICENSE, distributed with this software. -|----------------------------------------------------------------------------*/ -import { - IDisposable -} from '@lumino/disposable'; - - -/** - * A thin caching wrapper around a 2D canvas rendering context. - * - * #### Notes - * This class is mostly a transparent wrapper around a canvas rendering - * context which improves performance when writing context state. - * - * For best performance, avoid reading state from the `gc`. Writes are - * cached based on the previously written value. - * - * Unless otherwise specified, the API and semantics of this class are - * identical to the builtin 2D canvas rendering context: - * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D - * - * The wrapped canvas context should not be manipulated externally - * until the wrapping `GraphicsContext` object is disposed. - */ -export -class GraphicsContext implements IDisposable { - /** - * Create a new graphics context object. - * - * @param context - The 2D canvas rendering context to wrap. - */ - constructor(context: CanvasRenderingContext2D) { - this._context = context; - this._state = Private.State.create(context); - } - - dispose(): void { - // Bail if the gc is already disposed. - if (this._disposed) { - return; - } - - // Mark the gc as disposed. - this._disposed = true; - - // Pop any unrestored saves. - while (this._state.next) { - this._state = this._state.next; - this._context.restore(); - } - } - - get isDisposed(): boolean { - return this._disposed; - } - - get fillStyle(): string | CanvasGradient | CanvasPattern { - return this._context.fillStyle; - } - - set fillStyle(value: string | CanvasGradient | CanvasPattern) { - if (this._state.fillStyle !== value) { - this._state.fillStyle = value; - this._context.fillStyle = value; - } - } - - get strokeStyle(): string | CanvasGradient | CanvasPattern { - return this._context.strokeStyle; - } - - set strokeStyle(value: string | CanvasGradient | CanvasPattern) { - if (this._state.strokeStyle !== value) { - this._state.strokeStyle = value; - this._context.strokeStyle = value; - } - } - - get font(): string { - return this._context.font; - } - - set font(value: string) { - if (this._state.font !== value) { - this._state.font = value; - this._context.font = value; - } - } - - get textAlign(): CanvasTextAlign { - return this._context.textAlign; - } - - set textAlign(value: CanvasTextAlign) { - if (this._state.textAlign !== value) { - this._state.textAlign = value; - this._context.textAlign = value; - } - } - - get textBaseline(): CanvasTextBaseline { - return this._context.textBaseline; - } - - set textBaseline(value: CanvasTextBaseline) { - if (this._state.textBaseline !== value) { - this._state.textBaseline = value; - this._context.textBaseline = value; - } - } - - get lineCap(): CanvasLineCap { - return this._context.lineCap; - } - - set lineCap(value: CanvasLineCap) { - if (this._state.lineCap !== value) { - this._state.lineCap = value; - this._context.lineCap = value; - } - } - - get lineDashOffset(): number { - return this._context.lineDashOffset; - } - - set lineDashOffset(value: number) { - if (this._state.lineDashOffset !== value) { - this._state.lineDashOffset = value; - this._context.lineDashOffset = value; - } - } - - get lineJoin(): CanvasLineJoin { - return this._context.lineJoin; - } - - set lineJoin(value: CanvasLineJoin) { - if (this._state.lineJoin !== value) { - this._state.lineJoin = value; - this._context.lineJoin = value; - } - } - - get lineWidth(): number { - return this._context.lineWidth; - } - - set lineWidth(value: number) { - if (this._state.lineWidth !== value) { - this._state.lineWidth = value; - this._context.lineWidth = value; - } - } - - get miterLimit(): number { - return this._context.miterLimit; - } - - set miterLimit(value: number) { - if (this._state.miterLimit !== value) { - this._state.miterLimit = value; - this._context.miterLimit = value; - } - } - - get shadowBlur(): number { - return this._context.shadowBlur; - } - - set shadowBlur(value: number) { - if (this._state.shadowBlur !== value) { - this._state.shadowBlur = value; - this._context.shadowBlur = value; - } - } - - get shadowColor(): string { - return this._context.shadowColor; - } - - set shadowColor(value: string) { - if (this._state.shadowColor !== value) { - this._state.shadowColor = value; - this._context.shadowColor = value; - } - } - - get shadowOffsetX(): number { - return this._context.shadowOffsetX; - } - - set shadowOffsetX(value: number) { - if (this._state.shadowOffsetX !== value) { - this._state.shadowOffsetX = value; - this._context.shadowOffsetX = value; - } - } - - get shadowOffsetY(): number { - return this._context.shadowOffsetY; - } - - set shadowOffsetY(value: number) { - if (this._state.shadowOffsetY !== value) { - this._state.shadowOffsetY = value; - this._context.shadowOffsetY = value; - } - } - - get imageSmoothingEnabled(): boolean { - return this._context.imageSmoothingEnabled; - } - - set imageSmoothingEnabled(value: boolean) { - if (this._state.imageSmoothingEnabled !== value) { - this._state.imageSmoothingEnabled = value; - this._context.imageSmoothingEnabled = value; - } - } - - get globalAlpha(): number { - return this._context.globalAlpha; - } - - set globalAlpha(value: number) { - if (this._state.globalAlpha !== value) { - this._state.globalAlpha = value; - this._context.globalAlpha = value; - } - } - - get globalCompositeOperation(): string { - return this._context.globalCompositeOperation; - } - - set globalCompositeOperation(value: string) { - if (this._state.globalCompositeOperation !== value) { - this._state.globalCompositeOperation = value; - this._context.globalCompositeOperation = value; - } - } - - getLineDash(): number[] { - return this._context.getLineDash(); - } - - setLineDash(segments: number[]): void { - this._context.setLineDash(segments); - } - - rotate(angle: number): void { - this._context.rotate(angle); - } - - scale(x: number, y: number): void { - this._context.scale(x, y); - } - - transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void { - this._context.transform(m11, m12, m21, m22, dx, dy); - } - - translate(x: number, y: number): void { - this._context.translate(x, y); - } - - setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void { - this._context.setTransform(m11, m12, m21, m22, dx, dy); - } - - save(): void { - // Clone an push the current state to the stack. - this._state = Private.State.push(this._state); - - // Save the wrapped context state. - this._context.save(); - } - - restore(): void { - // Bail if there is no state to restore. - if (!this._state.next) { - return; - } - - // Pop the saved state from the stack. - this._state = Private.State.pop(this._state); - - // Restore the wrapped context state. - this._context.restore(); - } - - beginPath(): void { - return this._context.beginPath(); - } - - closePath(): void { - this._context.closePath(); - } - - isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean { - let result: boolean; - if (arguments.length === 2) { - result = this._context.isPointInPath(x, y); - } else { - result = this._context.isPointInPath(x, y, fillRule); - } - return result; - } - - arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { - if (arguments.length === 5) { - this._context.arc(x, y, radius, startAngle, endAngle); - } else { - this._context.arc(x, y, radius, startAngle, endAngle, anticlockwise); - } - } - - arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { - this._context.arcTo(x1, y1, x2, y2, radius); - } - - bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void { - this._context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - } - - ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { - if (arguments.length === 7) { - this._context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle); - } else { - this._context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise); - } - } - - lineTo(x: number, y: number): void { - this._context.lineTo(x, y); - } - - moveTo(x: number, y: number): void { - this._context.moveTo(x, y); - } - - quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { - this._context.quadraticCurveTo(cpx, cpy, x, y); - } - - rect(x: number, y: number, w: number, h: number): void { - this._context.rect(x, y, w, h); - } - - clip(fillRule?: CanvasFillRule): void { - if (arguments.length === 0) { - this._context.clip(); - } else { - this._context.clip(fillRule); - } - } - - fill(fillRule?: CanvasFillRule): void { - if (arguments.length === 0) { - this._context.fill(); - } else { - this._context.fill(fillRule); - } - } - - stroke(): void { - this._context.stroke(); - } - - clearRect(x: number, y: number, w: number, h: number): void { - return this._context.clearRect(x, y, w, h); - } - - fillRect(x: number, y: number, w: number, h: number): void { - this._context.fillRect(x, y, w, h); - } - - fillText(text: string, x: number, y: number, maxWidth?: number): void { - if (arguments.length === 3) { - this._context.fillText(text, x, y); - } else { - this._context.fillText(text, x, y, maxWidth); - } - } - - strokeRect(x: number, y: number, w: number, h: number): void { - this._context.strokeRect(x, y, w, h); - } - - strokeText(text: string, x: number, y: number, maxWidth?: number): void { - if (arguments.length === 3) { - this._context.strokeText(text, x, y); - } else { - this._context.strokeText(text, x, y, maxWidth); - } - } - - measureText(text: string): TextMetrics { - return this._context.measureText(text); - } - - createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient { - return this._context.createLinearGradient(x0, y0, x1, y1); - } - - createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient { - return this._context.createRadialGradient(x0, y0, r0, x1, y1, r1); - } - - createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern | null { - return this._context.createPattern(image, repetition); - } - - createImageData(imageData: ImageData): ImageData; - createImageData(sw: number, sh: number): ImageData; - createImageData() { - return this._context.createImageData.apply(this._context, arguments as any); - } - - getImageData(sx: number, sy: number, sw: number, sh: number): ImageData { - return this._context.getImageData(sx, sy, sw, sh); - } - - putImageData(imagedata: ImageData, dx: number, dy: number): void - putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX: number, dirtyY: number, dirtyWidth: number, dirtyHeight: number): void - putImageData(): void { - this._context.putImageData.apply(this._context, arguments as any); - } - - drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number): void; - drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number, dstW: number, dstH: number): void; - drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, srcX: number, srcY: number, srcW: number, srcH: number, dstX: number, dstY: number, dstW: number, dstH: number): void; - drawImage(): void { - this._context.drawImage.apply(this._context, arguments as any); - } - - drawFocusIfNeeded(element: Element): void { - this._context.drawFocusIfNeeded(element); - } - - private _disposed = false; - private _state: Private.State; - private _context: CanvasRenderingContext2D; -} - - -/** - * The namespace for the module implementation details. - */ -namespace Private { - /** - * The index of next valid pool object. - */ - let pi = -1; - - /** - * A state object allocation pool. - */ - const pool: State[] = []; - - /** - * An object which holds the state for a gc. - */ - export - class State { - /** - * Create a gc state object from a 2D canvas context. - */ - static create(context: CanvasRenderingContext2D): State { - let state = pi < 0 ? new State() : pool[pi--]; - state.next = null; - state.fillStyle = context.fillStyle; - state.font = context.font; - state.globalAlpha = context.globalAlpha; - state.globalCompositeOperation = context.globalCompositeOperation; - state.imageSmoothingEnabled = context.imageSmoothingEnabled; - state.lineCap = context.lineCap; - state.lineDashOffset = context.lineDashOffset; - state.lineJoin = context.lineJoin; - state.lineWidth = context.lineWidth; - state.miterLimit = context.miterLimit; - state.shadowBlur = context.shadowBlur; - state.shadowColor = context.shadowColor; - state.shadowOffsetX = context.shadowOffsetX; - state.shadowOffsetY = context.shadowOffsetY; - state.strokeStyle = context.strokeStyle; - state.textAlign = context.textAlign; - state.textBaseline = context.textBaseline; - return state; - } - - /** - * Clone an existing gc state object and add it to the state stack. - */ - static push(other: State): State { - let state = pi < 0 ? new State() : pool[pi--]; - state.next = other; - state.fillStyle = other.fillStyle; - state.font = other.font; - state.globalAlpha = other.globalAlpha; - state.globalCompositeOperation = other.globalCompositeOperation; - state.imageSmoothingEnabled = other.imageSmoothingEnabled; - state.lineCap = other.lineCap; - state.lineDashOffset = other.lineDashOffset; - state.lineJoin = other.lineJoin; - state.lineWidth = other.lineWidth; - state.miterLimit = other.miterLimit; - state.shadowBlur = other.shadowBlur; - state.shadowColor = other.shadowColor; - state.shadowOffsetX = other.shadowOffsetX; - state.shadowOffsetY = other.shadowOffsetY; - state.strokeStyle = other.strokeStyle; - state.textAlign = other.textAlign; - state.textBaseline = other.textBaseline; - return state; - } - - /** - * Pop the next state object and return the current to the pool - */ - static pop(state: State): State { - state.fillStyle = ''; - state.strokeStyle = ''; - pool[++pi] = state; - return state.next!; - } - - next: State | null; - - fillStyle: string | CanvasGradient | CanvasPattern; - font: string; - globalAlpha: number; - globalCompositeOperation: string; - imageSmoothingEnabled: boolean; - lineCap: string; - lineDashOffset: number; - lineJoin: string; - lineWidth: number; - miterLimit: number; - shadowBlur: number; - shadowColor: string; - shadowOffsetX: number; - shadowOffsetY: number; - strokeStyle: string | CanvasGradient | CanvasPattern; - textAlign: string; - textBaseline: string; - - private constructor() { } - } -} From 4bf60af63e405d079240d131746ae4e24ad89ccf Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Tue, 22 Jun 2021 21:27:53 -0700 Subject: [PATCH 17/20] Update headerRenderer with latest features Signed-off-by: Itay Dafna --- js/core/headerRenderer.ts | 131 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/js/core/headerRenderer.ts b/js/core/headerRenderer.ts index 22cd960f..34318458 100644 --- a/js/core/headerRenderer.ts +++ b/js/core/headerRenderer.ts @@ -51,7 +51,7 @@ export class HeaderRenderer extends TextRenderer { // Format the cell value to text. const format = this.format; - const text = format(config); + let text = format(config); // Bail if there is no text to draw. if (!text) { @@ -62,6 +62,15 @@ export class HeaderRenderer extends TextRenderer { const vAlign = CellRenderer.resolveOption(this.verticalAlignment, config); const hAlign = CellRenderer.resolveOption(this.horizontalAlignment, config); + // Resolve the elision direction + const elideDirection = CellRenderer.resolveOption( + this.elideDirection, + config, + ); + + // Resolve the text wrapping flag + const wrapText = CellRenderer.resolveOption(this.wrapText, config); + // Compute the padded text box height for the specified alignment. const boxHeight = config.height - (vAlign === 'center' ? 1 : 2); @@ -76,6 +85,7 @@ export class HeaderRenderer extends TextRenderer { // Set up the text position variables. let textX: number; let textY: number; + let boxWidth: number; // Compute the Y position for the text. switch (vAlign) { @@ -95,13 +105,16 @@ export class HeaderRenderer extends TextRenderer { // Compute the X position for the text. switch (hAlign) { case 'left': - textX = config.x + 2; + textX = config.x + 8; + boxWidth = config.width - 14; break; case 'center': textX = config.x + config.width / 2; + boxWidth = config.width; break; case 'right': - textX = config.x + config.width - 3; + textX = config.x + config.width - 8; + boxWidth = config.width - 14; break; default: throw 'unreachable'; @@ -120,7 +133,117 @@ export class HeaderRenderer extends TextRenderer { gc.textAlign = hAlign; gc.textBaseline = 'bottom'; - // Draw the text + // The current text width in pixels. + let textWidth = gc.measureText(text).width; + + // Apply text wrapping if enabled. + if (wrapText && textWidth > boxWidth) { + // Make sure box clipping happens. + gc.beginPath(); + gc.rect(config.x, config.y, config.width, config.height - 1); + gc.clip(); + + // Split column name to words based on + // whitespace preceding a word boundary. + // "Hello world" --> ["Hello ", "world"] + const wordsInColumn = text.split(/\s(?=\b)/); + + // Y-coordinate offset for any additional lines + let curY = textY; + let textInCurrentLine = wordsInColumn.shift()!; + + // Single word. Applying text wrap on word by splitting + // it into characters and fitting the maximum number of + // characters possible per line (box width). + if (wordsInColumn.length === 0) { + let curLineTextWidth = gc.measureText(textInCurrentLine).width; + while (curLineTextWidth > boxWidth && textInCurrentLine !== '') { + // Iterating from the end of the string until we find a + // substring (0,i) which has a width less than the box width. + for (let i = textInCurrentLine.length; i > 0; i--) { + const curSubString = textInCurrentLine.substring(0, i); + const curSubStringWidth = gc.measureText(curSubString).width; + if (curSubStringWidth < boxWidth || curSubString.length === 1) { + // Found a substring which has a width less than the current + // box width. Rendering that substring on the current line + // and setting the remainder of the parent string as the next + // string to iterate on for the next line. + const nextLineText = textInCurrentLine.substring( + i, + textInCurrentLine.length, + ); + textInCurrentLine = nextLineText; + curLineTextWidth = gc.measureText(textInCurrentLine).width; + gc.fillText(curSubString, textX, curY); + curY += textHeight; + // No need to continue iterating after we identified + // an index to break the string on. + break; + } + } + } + } + + // Multiple words in column header. Fitting maximum + // number of words possible per line (box width). + else { + while (wordsInColumn.length !== 0) { + // Processing the next word in the queue. + const curWord = wordsInColumn.shift(); + // Joining that word with the existing text for + // the current line. + const incrementedText = [textInCurrentLine, curWord].join(' '); + const incrementedTextWidth = gc.measureText(incrementedText).width; + if (incrementedTextWidth > boxWidth) { + // If the newly combined text has a width larger than + // the box width, we render the line before the current + // word was added. We set the current word as the next + // line. + gc.fillText(textInCurrentLine, textX, curY); + curY += textHeight; + textInCurrentLine = curWord!; + } else { + // The combined text hasd a width less than the box width. We + // set the the current line text to be the new combined text. + textInCurrentLine = incrementedText; + } + } + } + gc.fillText(textInCurrentLine!, textX, curY); + // Terminating the call here as we don't want + // to apply text eliding when wrapping is active. + return; + } + + // Elide text that is too long + const elide = '\u2026'; + + // Compute elided text + if (elideDirection === 'right') { + while (textWidth > boxWidth && text.length > 1) { + if (text.length > 4 && textWidth >= 2 * boxWidth) { + // If text width is substantially bigger, take half the string + text = text.substring(0, text.length / 2 + 1) + elide; + } else { + // Otherwise incrementally remove the last character + text = text.substring(0, text.length - 2) + elide; + } + textWidth = gc.measureText(text).width; + } + } else { + while (textWidth > boxWidth && text.length > 1) { + if (text.length > 4 && textWidth >= 2 * boxWidth) { + // If text width is substantially bigger, take half the string + text = elide + text.substring(text.length / 2); + } else { + // Otherwise incrementally remove the last character + text = elide + text.substring(2); + } + textWidth = gc.measureText(text).width; + } + } + + // Draw the text for the cell. gc.fillText(text, textX, textY); // Check if not bottom row of 'column-header' CellRegion From 005febdd321db80357f4f75895fd6e87c1510b74 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Fri, 16 Jul 2021 15:36:37 -0700 Subject: [PATCH 18/20] Add traitlets for text wrapping and eliding Signed-off-by: Itay Dafna --- js/cellrenderer.ts | 10 ++++++++++ js/feathergrid.ts | 2 ++ 2 files changed, 12 insertions(+) diff --git a/js/cellrenderer.ts b/js/cellrenderer.ts index dff8559f..faaad5c0 100644 --- a/js/cellrenderer.ts +++ b/js/cellrenderer.ts @@ -232,6 +232,8 @@ export class TextRendererModel extends CellRendererModel { _view_name: TextRendererModel.view_name, font: '12px sans-serif', text_color: null, + text_wrap: false, + text_elide_direction: 'right', text_value: null, background_color: null, vertical_alignment: 'center', @@ -245,6 +247,12 @@ export class TextRendererModel extends CellRendererModel { get_attrs(): ICellRendererAttribute[] { return [ { name: 'font', phosphorName: 'font', defaultValue: '12px sans-serif' }, + { name: 'text_wrap', phosphorName: 'wrapText', defaultValue: false }, + { + name: 'text_elide_direction', + phosphorName: 'elideDirection', + defaultValue: 'right', + }, { name: 'text_color', phosphorName: 'textColor', @@ -274,6 +282,8 @@ export class TextRendererModel extends CellRendererModel { ...CellRendererModel.serializers, font: { deserialize: unpack_models as any }, text_color: { deserialize: unpack_models as any }, + text_wrap: { deserialize: unpack_models as any }, + text_elide_direction: { deserialize: unpack_models as any }, text_value: { deserialize: unpack_models as any }, background_color: { deserialize: unpack_models as any }, vertical_alignment: { deserialize: unpack_models as any }, diff --git a/js/feathergrid.ts b/js/feathergrid.ts index 393083ef..891254af 100644 --- a/js/feathergrid.ts +++ b/js/feathergrid.ts @@ -395,6 +395,8 @@ export class FeatherGrid extends Widget { this._columnHeaderRenderer = new HeaderRenderer({ textOptions: { font: textRenderer.font, + wrapText: textRenderer.wrapText, + elideDirection: textRenderer.elideDirection, textColor: textRenderer.textColor, backgroundColor: textRenderer.backgroundColor, verticalAlignment: textRenderer.verticalAlignment, From 945801025606200be9f99a89bae53959101bc638 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Fri, 16 Jul 2021 15:50:53 -0700 Subject: [PATCH 19/20] Add Python-side text wrapping and eliding traitlets Signed-off-by: Itay Dafna --- ipydatagrid/cellrenderer.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ipydatagrid/cellrenderer.py b/ipydatagrid/cellrenderer.py index 4caa35f2..e4b3e99e 100644 --- a/ipydatagrid/cellrenderer.py +++ b/ipydatagrid/cellrenderer.py @@ -57,6 +57,10 @@ class TextRenderer(CellRenderer): allow_none=True, default_value=None, ).tag(sync=True, **widget_serialization) + text_wrap = Bool(default_value=False).tag(sync=True, **widget_serialization) + text_elide_direction = Enum( + values=["right", "left"], default_value='right' + ).tag(sync=True, **widget_serialization) font = Union( (Unicode(), Instance(VegaExpr), Instance(Scale)), default_value="12px sans-serif", From 00e59847e2dcc8e70b0db31399f43607a56465c0 Mon Sep 17 00:00:00 2001 From: Itay Dafna Date: Fri, 16 Jul 2021 15:59:03 -0700 Subject: [PATCH 20/20] Run linter Signed-off-by: Itay Dafna --- ipydatagrid/cellrenderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipydatagrid/cellrenderer.py b/ipydatagrid/cellrenderer.py index e4b3e99e..5e37d8d3 100644 --- a/ipydatagrid/cellrenderer.py +++ b/ipydatagrid/cellrenderer.py @@ -59,7 +59,7 @@ class TextRenderer(CellRenderer): ).tag(sync=True, **widget_serialization) text_wrap = Bool(default_value=False).tag(sync=True, **widget_serialization) text_elide_direction = Enum( - values=["right", "left"], default_value='right' + values=["right", "left"], default_value="right" ).tag(sync=True, **widget_serialization) font = Union( (Unicode(), Instance(VegaExpr), Instance(Scale)),