You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by vo...@apache.org on 2023/02/07 07:13:08 UTC

[druid] branch master updated: Upgrade typescript and other dependencies (#13762)

This is an automated email from the ASF dual-hosted git repository.

vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new b33962cab7 Upgrade typescript and other dependencies (#13762)
b33962cab7 is described below

commit b33962cab7809a750e7af5c0e0b6fdf009b347b3
Author: John Gozde <jo...@gozde.ca>
AuthorDate: Tue Feb 7 00:12:54 2023 -0700

    Upgrade typescript and other dependencies (#13762)
    
    * Bump zustand, licenses
    
    * Bump TypeScript, Eslint, use type imports
    
    * Switch to react-shallow-renderer from enzyme
    
    * Update ts-loader
---
 licenses.yaml                                      |   12 +-
 licenses/bin/use-sync-external-store.MIT           |   21 +
 web-console/.eslintrc.js                           |    1 +
 web-console/e2e-tests/auto-compaction.spec.ts      |    4 +-
 web-console/e2e-tests/cancel-query.spec.ts         |    2 +-
 .../e2e-tests/component/datasources/compaction.ts  |    2 +-
 .../e2e-tests/component/datasources/overview.ts    |    2 +-
 .../e2e-tests/component/ingestion/overview.ts      |    2 +-
 .../component/load-data/config/partition.ts        |    2 +-
 .../load-data/data-connector/data-connector.ts     |    2 +-
 .../load-data/data-connector/local-file.ts         |    5 +-
 .../component/load-data/data-connector/reindex.ts  |    5 +-
 .../e2e-tests/component/load-data/data-loader.ts   |   12 +-
 web-console/e2e-tests/component/query/overview.ts  |    2 +-
 .../e2e-tests/component/workbench/overview.ts      |    2 +-
 web-console/e2e-tests/multi-stage-query.spec.ts    |    2 +-
 web-console/e2e-tests/reindexing.spec.ts           |    2 +-
 web-console/e2e-tests/tutorial-batch.spec.ts       |    2 +-
 web-console/e2e-tests/util/debug.ts                |    2 +-
 web-console/e2e-tests/util/table.ts                |    2 +-
 web-console/jest.unit.config.js                    |    1 -
 web-console/package-lock.json                      | 2600 +++-----------------
 web-console/package.json                           |   15 +-
 web-console/script/mkcomp                          |    5 +-
 web-console/src/bootstrap/react-table-defaults.tsx |    3 +-
 .../src/components/action-cell/action-cell.tsx     |    3 +-
 .../src/components/action-icon/action-icon.tsx     |    3 +-
 .../src/components/array-input/array-input.tsx     |    6 +-
 .../__snapshots__/auto-form.spec.tsx.snap          |   15 +-
 .../src/components/auto-form/auto-form.spec.tsx    |    2 +-
 web-console/src/components/auto-form/auto-form.tsx |    2 +-
 .../components/braced-text/braced-text.spec.tsx    |    3 +-
 .../cell-filter-menu/cell-filter-menu.tsx          |   16 +-
 .../components/center-message/center-message.tsx   |    3 +-
 .../date-range-selector/date-range-selector.tsx    |    3 +-
 .../src/components/external-link/external-link.tsx |    3 +-
 .../components/fancy-tab-pane/fancy-tab-pane.tsx   |    6 +-
 .../form-json-selector/form-json-selector.spec.tsx |    3 +-
 .../components/formatted-input/formatted-input.tsx |    5 +-
 .../src/components/header-bar/header-bar.spec.tsx  |    2 +-
 .../highlight-text/highlight-text.spec.tsx         |    3 +-
 .../components/interval-input/interval-input.tsx   |    6 +-
 .../json-collapse/json-collapse.spec.tsx           |    3 +-
 .../src/components/json-input/json-input.tsx       |    2 +-
 .../src/components/menu-checkbox/menu-checkbox.tsx |    3 +-
 .../src/components/menu-tristate/menu-tristate.tsx |    3 +-
 .../numeric-input-with-default.spec.tsx            |    3 +-
 .../numeric-input-with-default.tsx                 |    3 +-
 .../query-error-pane/query-error-pane.spec.tsx     |    3 +-
 .../query-error-pane/query-error-pane.tsx          |    2 +-
 .../record-table-pane/record-table-pane.tsx        |    7 +-
 .../components/refresh-button/refresh-button.tsx   |    5 +-
 .../src/components/rule-editor/rule-editor.tsx     |    3 +-
 .../src/components/segment-timeline/bar-group.tsx  |    4 +-
 .../segment-timeline/segment-timeline.tsx          |   17 +-
 .../segment-timeline/stacked-bar-chart.tsx         |    3 +-
 .../src/components/show-history/show-history.tsx   |    3 +-
 .../suggestible-input/suggestible-input.tsx        |    6 +-
 .../table-clickable-cell/table-clickable-cell.tsx  |    6 +-
 .../table-filterable-cell.tsx                      |    8 +-
 .../components/timed-button/timed-button.spec.tsx  |    3 +-
 .../src/components/timed-button/timed-button.tsx   |    6 +-
 .../view-control-bar/view-control-bar.tsx          |    3 +-
 .../warning-checklist/warning-checklist.tsx        |    3 +-
 web-console/src/console-application.tsx            |    8 +-
 .../async-action-dialog/async-action-dialog.tsx    |   17 +-
 .../compaction-dialog/compaction-dialog.spec.tsx   |    3 +-
 .../compaction-dialog/compaction-dialog.tsx        |    9 +-
 .../coordinator-dynamic-config-dialog.spec.tsx     |    3 +-
 .../coordinator-dynamic-config-dialog.tsx          |   15 +-
 .../datasource-columns-table.spec.tsx              |    5 +-
 .../datasource-columns-table.tsx                   |    3 +-
 .../datasource-preview-pane.tsx                    |    3 +-
 .../datasource-table-action-dialog.tsx             |    5 +-
 .../src/dialogs/diff-dialog/diff-dialog.tsx        |    3 +-
 .../src/dialogs/doctor-dialog/doctor-dialog.tsx    |    2 +-
 .../edit-context-dialog/edit-context-dialog.tsx    |    2 +-
 .../index-spec-dialog/index-spec-dialog.spec.tsx   |    3 +-
 .../index-spec-dialog/index-spec-dialog.tsx        |    6 +-
 .../__snapshots__/lookup-edit-dialog.spec.tsx.snap |    2 -
 .../lookup-edit-dialog/lookup-edit-dialog.spec.tsx |    3 +-
 .../lookup-edit-dialog/lookup-edit-dialog.tsx      |    6 +-
 .../lookup-table-action-dialog.tsx                 |    5 +-
 .../overload-dynamic-config-dialog.spec.tsx        |    3 +-
 .../overlord-dynamic-config-dialog.tsx             |    3 +-
 .../dialogs/retention-dialog/retention-dialog.tsx  |    7 +-
 .../segment-table-action-dialog.tsx                |    5 +-
 .../segments-preview-pane.tsx                      |    3 +-
 .../src/dialogs/snitch-dialog/snitch-dialog.tsx    |    4 +-
 .../src/dialogs/spec-dialog/spec-dialog.tsx        |    4 +-
 .../src/dialogs/status-dialog/status-dialog.tsx    |    3 +-
 .../supervisor-statistics-table.spec.tsx           |    4 +-
 .../supervisor-statistics-table.tsx                |    3 +-
 .../supervisor-table-action-dialog.tsx             |    5 +-
 .../table-action-dialog/table-action-dialog.tsx    |    9 +-
 .../task-table-action-dialog.tsx                   |    5 +-
 .../compaction-config/compaction-config.tsx        |    2 +-
 .../compaction-status/compaction-status.spec.ts    |    5 +-
 .../compaction-status/compaction-status.ts         |    6 +-
 .../coordinator-dynamic-config.tsx                 |    2 +-
 .../druid-models/dimension-spec/dimension-spec.ts  |    4 +-
 .../src/druid-models/execution/execution.ts        |    5 +-
 .../external-config/external-config.ts             |    6 +-
 web-console/src/druid-models/filter/filter.tsx     |    5 +-
 .../src/druid-models/flatten-spec/flatten-spec.tsx |    3 +-
 .../src/druid-models/index-spec/index-spec.tsx     |    2 +-
 .../ingest-query-pattern/ingest-query-pattern.ts   |    2 +-
 .../ingestion-spec/ingestion-spec.spec.ts          |    2 +-
 .../druid-models/ingestion-spec/ingestion-spec.tsx |   26 +-
 .../src/druid-models/input-format/input-format.tsx |    5 +-
 .../src/druid-models/input-source/input-source.tsx |    3 +-
 .../src/druid-models/lookup-spec/lookup-spec.tsx   |    3 +-
 .../src/druid-models/metric-spec/metric-spec.tsx   |    5 +-
 .../overlord-dynamic-config.tsx                    |    2 +-
 web-console/src/druid-models/stages/stages.ts      |    4 +-
 .../druid-models/timestamp-spec/timestamp-spec.tsx |    7 +-
 .../druid-models/transform-spec/transform-spec.tsx |    3 +-
 .../workbench-query/workbench-query-part.ts        |    9 +-
 .../workbench-query/workbench-query.ts             |   22 +-
 web-console/src/entry.ts                           |    5 +-
 web-console/src/helpers/capacity.ts                |    2 +-
 web-console/src/helpers/execution/general.ts       |    6 +-
 .../src/helpers/execution/sql-task-execution.ts    |    5 +-
 web-console/src/helpers/spec-conversion.ts         |    5 +-
 web-console/src/hooks/use-local-storage-state.ts   |    6 +-
 web-console/src/hooks/use-query-manager.ts         |    3 +-
 web-console/src/react-table/react-table-inputs.tsx |    2 +-
 web-console/src/react-table/react-table-utils.ts   |    7 +-
 web-console/src/setup-tests.ts                     |    5 -
 .../src/singletons/ace-editor-state-cache.ts       |    2 +-
 web-console/src/singletons/api.ts                  |    3 +-
 .../src/singletons/execution-state-cache.ts        |    4 +-
 .../src/singletons/workbench-running-promises.ts   |    2 +-
 web-console/src/utils/basic-action.tsx             |    3 +-
 web-console/src/utils/date.ts                      |    2 +-
 web-console/src/utils/download.ts                  |    2 +-
 web-console/src/utils/druid-query.ts               |    5 +-
 web-console/src/utils/general.tsx                  |    5 +-
 .../src/utils/local-storage-backed-visibility.tsx  |    3 +-
 web-console/src/utils/query-action.ts              |    2 +-
 web-console/src/utils/query-cursor.ts              |    3 +-
 web-console/src/utils/query-manager.tsx            |   13 +-
 web-console/src/utils/sample-query.tsx             |    5 +-
 web-console/src/utils/sampler.mock.ts              |    2 +-
 web-console/src/utils/sampler.ts                   |   18 +-
 .../utils/shallow-renderer.ts}                     |   28 +-
 web-console/src/utils/table-helpers.ts             |    2 +-
 web-console/src/utils/types.ts                     |    4 +-
 web-console/src/utils/utils.spec.ts                |    2 +-
 .../datasources-view/datasources-view.spec.tsx     |    2 +-
 .../views/datasources-view/datasources-view.tsx    |   20 +-
 .../__snapshots__/home-view.spec.tsx.snap          |  168 +-
 .../datasources-card/datasources-card.tsx          |    2 +-
 .../home-view/home-view-card/home-view-card.tsx    |    6 +-
 web-console/src/views/home-view/home-view.spec.tsx |    2 +-
 web-console/src/views/home-view/home-view.tsx      |    2 +-
 .../views/home-view/lookups-card/lookups-card.tsx  |    2 +-
 .../home-view/segments-card/segments-card.tsx      |    2 +-
 .../home-view/services-card/services-card.tsx      |    2 +-
 .../supervisors-card/supervisors-card.tsx          |    2 +-
 .../src/views/home-view/tasks-card/tasks-card.tsx  |    5 +-
 .../__snapshots__/ingestion-view.spec.tsx.snap     |  126 +-
 .../views/ingestion-view/ingestion-view.spec.tsx   |    2 +-
 .../src/views/ingestion-view/ingestion-view.tsx    |    9 +-
 .../__snapshots__/load-data-view.spec.tsx.snap     |  106 +-
 .../example-picker/example-picker.tsx              |    2 +-
 .../load-data-view/filter-table/filter-table.tsx   |    8 +-
 .../load-data-view/form-editor/form-editor.tsx     |    5 +-
 .../src/views/load-data-view/info-messages.tsx     |    3 +-
 .../views/load-data-view/load-data-view.spec.tsx   |    3 +-
 .../src/views/load-data-view/load-data-view.tsx    |   44 +-
 .../parse-data-table/parse-data-table.tsx          |    7 +-
 .../parse-time-table/parse-time-table.spec.tsx     |    3 +-
 .../parse-time-table/parse-time-table.tsx          |    8 +-
 .../load-data-view/schema-table/schema-table.tsx   |   10 +-
 .../transform-table/transform-table.tsx            |    7 +-
 .../src/views/lookups-view/lookups-view.spec.tsx   |    3 +-
 .../src/views/lookups-view/lookups-view.tsx        |   12 +-
 .../__snapshots__/segments-view.spec.tsx.snap      |    8 +-
 .../src/views/segments-view/segments-view.spec.tsx |    2 +-
 .../src/views/segments-view/segments-view.tsx      |   11 +-
 .../__snapshots__/services-view.spec.tsx.snap      |    4 +-
 .../src/views/services-view/services-view.spec.tsx |    2 +-
 .../src/views/services-view/services-view.tsx      |   11 +-
 .../column-actions/column-actions.tsx              |    6 +-
 .../column-editor/column-editor.tsx                |    3 +-
 .../destination-dialog/destination-dialog.tsx      |    3 +-
 .../destination-form/destination-form.tsx          |    2 +-
 .../ingestion-progress-dialog.tsx                  |    2 +-
 .../schema-step/column-list/column-list.tsx        |    2 +-
 .../expression-entry/expression-entry.tsx          |    3 +-
 .../schema-step/preview-table/preview-table.tsx    |   15 +-
 .../rollup-analysis-pane/rollup-analysis-pane.tsx  |    7 +-
 .../schema-step/schema-step.tsx                    |   13 +-
 .../sql-data-loader-view/sql-data-loader-view.tsx  |   10 +-
 .../title-frame/title-frame.tsx                    |    3 +-
 .../capacity-alert/capacity-alert.tsx              |    2 +-
 .../__snapshots__/column-tree.spec.tsx.snap        |    2 -
 .../number-menu-items/number-menu-items.tsx        |    3 +-
 .../string-menu-items/string-menu-items.tsx        |    3 +-
 .../time-menu-items/time-menu-items.tsx            |    3 +-
 .../column-tree/column-tree.spec.tsx               |    4 +-
 .../workbench-view/column-tree/column-tree.tsx     |   18 +-
 .../connect-external-data-dialog.tsx               |    4 +-
 .../src/views/workbench-view/demo-queries.ts       |    3 +-
 .../execution-details-dialog.tsx                   |    4 +-
 .../execution-details-pane-loader.tsx              |    8 +-
 .../execution-details-pane.spec.tsx                |    2 +-
 .../execution-details-pane.tsx                     |    2 +-
 .../execution-error-pane.spec.tsx.snap             |   26 +-
 .../execution-error-pane.spec.tsx                  |    2 +-
 .../execution-error-pane/execution-error-pane.tsx  |    2 +-
 .../execution-progress-bar-pane.spec.tsx.snap      |   21 +-
 .../execution-progress-bar-pane.spec.tsx           |    2 +-
 .../execution-progress-pane.tsx                    |    2 +-
 .../execution-stages-pane-loader.tsx               |    2 +-
 .../execution-stages-pane.spec.tsx                 |    2 +-
 .../execution-stages-pane.tsx                      |   11 +-
 .../execution-summary-panel.tsx                    |    2 +-
 .../execution-timer-panel.tsx                      |    2 +-
 .../execution-warnings-pane.tsx                    |    2 +-
 .../execution-warnings-pane/warning-callout.tsx    |    2 +-
 .../__snapshots__/explain-dialog.spec.tsx.snap     |    2 -
 .../explain-dialog/explain-dialog.spec.tsx         |    5 +-
 .../explain-dialog/explain-dialog.tsx              |    5 +-
 .../flexible-query-input/flexible-query-input.tsx  |    5 +-
 .../workbench-view/helper-query/helper-query.tsx   |   35 +-
 .../ingest-success-pane.spec.tsx                   |    2 +-
 .../ingest-success-pane/ingest-success-pane.tsx    |    5 +-
 .../input-format-step/input-format-step.tsx        |   15 +-
 .../input-source-step/example-inputs.ts            |    2 +-
 .../input-source-step/input-source-info.tsx        |    2 +-
 .../input-source-step/input-source-step.tsx        |   10 +-
 .../__snapshots__/max-tasks-button.spec.tsx.snap   |    4 +-
 .../max-tasks-button/max-tasks-button.spec.tsx     |    3 +-
 .../max-tasks-button/max-tasks-button.tsx          |    5 +-
 .../workbench-view/metadata-change-detector.tsx    |   10 +-
 .../views/workbench-view/metadata-state-store.ts   |    6 +-
 .../views/workbench-view/query-tab/query-tab.tsx   |   39 +-
 .../recent-query-task-panel.tsx                    |   25 +-
 .../result-table-pane/result-table-pane.tsx        |   20 +-
 .../views/workbench-view/run-panel/run-panel.tsx   |   15 +-
 .../time-floor-menu-item/time-floor-menu-item.tsx  |    3 +-
 .../src/views/workbench-view/work-state-store.ts   |    6 +-
 .../workbench-history-dialog.tsx                   |    8 +-
 .../src/views/workbench-view/workbench-view.tsx    |   25 +-
 web-console/tsconfig.json                          |    2 +-
 .../react-shallow-renderer.d.ts}                   |   10 +-
 248 files changed, 1325 insertions(+), 3103 deletions(-)

diff --git a/licenses.yaml b/licenses.yaml
index ba21f0b045..696478d851 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -6537,6 +6537,16 @@ license_file_path: licenses/bin/upper-case.MIT
 
 ---
 
+name: "use-sync-external-store"
+license_category: binary
+module: web-console
+license_name: MIT License
+copyright: Facebook, Inc. and its affiliates.
+version: 1.2.0
+license_file_path: licenses/bin/use-sync-external-store.MIT
+
+---
+
 name: "value-equal"
 license_category: binary
 module: web-console
@@ -6572,6 +6582,6 @@ license_category: binary
 module: web-console
 license_name: MIT License
 copyright: Paul Henschel
-version: 3.7.2
+version: 4.3.2
 license_file_path: licenses/bin/zustand.MIT
 # Web console modules end
diff --git a/licenses/bin/use-sync-external-store.MIT b/licenses/bin/use-sync-external-store.MIT
new file mode 100644
index 0000000000..b96dcb0480
--- /dev/null
+++ b/licenses/bin/use-sync-external-store.MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Facebook, Inc. and its affiliates.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/web-console/.eslintrc.js b/web-console/.eslintrc.js
index f52c50e2da..52ed448e7e 100644
--- a/web-console/.eslintrc.js
+++ b/web-console/.eslintrc.js
@@ -30,6 +30,7 @@ module.exports = {
     },
   },
   rules: {
+    '@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports' }],
     'header/header': [
       2,
       'block',
diff --git a/web-console/e2e-tests/auto-compaction.spec.ts b/web-console/e2e-tests/auto-compaction.spec.ts
index 54b6184d28..58aa047d03 100644
--- a/web-console/e2e-tests/auto-compaction.spec.ts
+++ b/web-console/e2e-tests/auto-compaction.spec.ts
@@ -17,10 +17,10 @@
  */
 
 import path from 'path';
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { CompactionConfig } from './component/datasources/compaction';
-import { Datasource } from './component/datasources/datasource';
+import type { Datasource } from './component/datasources/datasource';
 import { DatasourcesOverview } from './component/datasources/overview';
 import { HashedPartitionsSpec } from './component/load-data/config/partition';
 import { saveScreenshotIfError } from './util/debug';
diff --git a/web-console/e2e-tests/cancel-query.spec.ts b/web-console/e2e-tests/cancel-query.spec.ts
index fc6822e46a..e17ab36fc7 100644
--- a/web-console/e2e-tests/cancel-query.spec.ts
+++ b/web-console/e2e-tests/cancel-query.spec.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { QueryOverview } from './component/query/overview';
 import { saveScreenshotIfError } from './util/debug';
diff --git a/web-console/e2e-tests/component/datasources/compaction.ts b/web-console/e2e-tests/component/datasources/compaction.ts
index 9463620690..175050406f 100644
--- a/web-console/e2e-tests/component/datasources/compaction.ts
+++ b/web-console/e2e-tests/component/datasources/compaction.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { PartitionsSpec } from '../load-data/config/partition';
+import type { PartitionsSpec } from '../load-data/config/partition';
 
 /**
  * Datasource compaction configuration
diff --git a/web-console/e2e-tests/component/datasources/overview.ts b/web-console/e2e-tests/component/datasources/overview.ts
index 1fa83c3672..95d6d630c9 100644
--- a/web-console/e2e-tests/component/datasources/overview.ts
+++ b/web-console/e2e-tests/component/datasources/overview.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { clickButton, getLabeledInput, setLabeledInput } from '../../util/playwright';
 import { extractTable } from '../../util/table';
diff --git a/web-console/e2e-tests/component/ingestion/overview.ts b/web-console/e2e-tests/component/ingestion/overview.ts
index 3d1a7f2997..4b160d374c 100644
--- a/web-console/e2e-tests/component/ingestion/overview.ts
+++ b/web-console/e2e-tests/component/ingestion/overview.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { extractTable } from '../../util/table';
 
diff --git a/web-console/e2e-tests/component/load-data/config/partition.ts b/web-console/e2e-tests/component/load-data/config/partition.ts
index 320f6fce27..8c45e923c8 100644
--- a/web-console/e2e-tests/component/load-data/config/partition.ts
+++ b/web-console/e2e-tests/component/load-data/config/partition.ts
@@ -18,7 +18,7 @@
 
 /* eslint-disable max-classes-per-file */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import {
   getLabeledInput,
diff --git a/web-console/e2e-tests/component/load-data/data-connector/data-connector.ts b/web-console/e2e-tests/component/load-data/data-connector/data-connector.ts
index bb7c55fad5..c0da3f9ae9 100644
--- a/web-console/e2e-tests/component/load-data/data-connector/data-connector.ts
+++ b/web-console/e2e-tests/component/load-data/data-connector/data-connector.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { clickButton } from '../../../util/playwright';
 
diff --git a/web-console/e2e-tests/component/load-data/data-connector/local-file.ts b/web-console/e2e-tests/component/load-data/data-connector/local-file.ts
index 2e89a33c15..cd33b7766e 100644
--- a/web-console/e2e-tests/component/load-data/data-connector/local-file.ts
+++ b/web-console/e2e-tests/component/load-data/data-connector/local-file.ts
@@ -16,11 +16,12 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { setLabeledInput } from '../../../util/playwright';
 
-import { clickApplyButton, DataConnector } from './data-connector';
+import type { DataConnector } from './data-connector';
+import { clickApplyButton } from './data-connector';
 
 /**
  * Local file connector for data loader input data.
diff --git a/web-console/e2e-tests/component/load-data/data-connector/reindex.ts b/web-console/e2e-tests/component/load-data/data-connector/reindex.ts
index 98d8ba1879..35f1dc3d9b 100644
--- a/web-console/e2e-tests/component/load-data/data-connector/reindex.ts
+++ b/web-console/e2e-tests/component/load-data/data-connector/reindex.ts
@@ -16,11 +16,12 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { setLabeledInput } from '../../../util/playwright';
 
-import { clickApplyButton, DataConnector } from './data-connector';
+import type { DataConnector } from './data-connector';
+import { clickApplyButton } from './data-connector';
 
 /**
  * Reindexing connector for data loader input data.
diff --git a/web-console/e2e-tests/component/load-data/data-loader.ts b/web-console/e2e-tests/component/load-data/data-loader.ts
index 37586a22bb..71601467f5 100644
--- a/web-console/e2e-tests/component/load-data/data-loader.ts
+++ b/web-console/e2e-tests/component/load-data/data-loader.ts
@@ -16,15 +16,15 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { clickButton, setLabeledInput, setLabeledTextarea } from '../../util/playwright';
 
-import { ConfigureSchemaConfig } from './config/configure-schema';
-import { ConfigureTimestampConfig } from './config/configure-timestamp';
-import { PartitionConfig } from './config/partition';
-import { PublishConfig } from './config/publish';
-import { DataConnector } from './data-connector/data-connector';
+import type { ConfigureSchemaConfig } from './config/configure-schema';
+import type { ConfigureTimestampConfig } from './config/configure-timestamp';
+import type { PartitionConfig } from './config/partition';
+import type { PublishConfig } from './config/publish';
+import type { DataConnector } from './data-connector/data-connector';
 
 /**
  * Represents load data tab.
diff --git a/web-console/e2e-tests/component/query/overview.ts b/web-console/e2e-tests/component/query/overview.ts
index 9ae4badcf1..82d3e8a630 100644
--- a/web-console/e2e-tests/component/query/overview.ts
+++ b/web-console/e2e-tests/component/query/overview.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { clickButton, clickText } from '../../util/playwright';
 import { extractTable } from '../../util/table';
diff --git a/web-console/e2e-tests/component/workbench/overview.ts b/web-console/e2e-tests/component/workbench/overview.ts
index e0f3c7debd..9660cd354d 100644
--- a/web-console/e2e-tests/component/workbench/overview.ts
+++ b/web-console/e2e-tests/component/workbench/overview.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { clickButton } from '../../util/playwright';
 import { extractTable } from '../../util/table';
diff --git a/web-console/e2e-tests/multi-stage-query.spec.ts b/web-console/e2e-tests/multi-stage-query.spec.ts
index 2766c5c8ff..8c0678ce3f 100644
--- a/web-console/e2e-tests/multi-stage-query.spec.ts
+++ b/web-console/e2e-tests/multi-stage-query.spec.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { WorkbenchOverview } from './component/workbench/overview';
 import { saveScreenshotIfError } from './util/debug';
diff --git a/web-console/e2e-tests/reindexing.spec.ts b/web-console/e2e-tests/reindexing.spec.ts
index d49bb57743..ebf75c0e78 100644
--- a/web-console/e2e-tests/reindexing.spec.ts
+++ b/web-console/e2e-tests/reindexing.spec.ts
@@ -17,7 +17,7 @@
  */
 
 import path from 'path';
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { DatasourcesOverview } from './component/datasources/overview';
 import { IngestionOverview } from './component/ingestion/overview';
diff --git a/web-console/e2e-tests/tutorial-batch.spec.ts b/web-console/e2e-tests/tutorial-batch.spec.ts
index 914850a96a..5c9e437dad 100644
--- a/web-console/e2e-tests/tutorial-batch.spec.ts
+++ b/web-console/e2e-tests/tutorial-batch.spec.ts
@@ -17,7 +17,7 @@
  */
 
 import { T } from 'druid-query-toolkit';
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 import { DatasourcesOverview } from './component/datasources/overview';
 import { IngestionOverview } from './component/ingestion/overview';
diff --git a/web-console/e2e-tests/util/debug.ts b/web-console/e2e-tests/util/debug.ts
index 9ea97a1be5..fee93a39a7 100644
--- a/web-console/e2e-tests/util/debug.ts
+++ b/web-console/e2e-tests/util/debug.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 export async function saveScreenshotIfError(
   filenamePrefix: string,
diff --git a/web-console/e2e-tests/util/table.ts b/web-console/e2e-tests/util/table.ts
index ab115b6f36..e40148f42a 100644
--- a/web-console/e2e-tests/util/table.ts
+++ b/web-console/e2e-tests/util/table.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import * as playwright from 'playwright-chromium';
+import type * as playwright from 'playwright-chromium';
 
 /**
  * Extracts an HTML table into a text representation.
diff --git a/web-console/jest.unit.config.js b/web-console/jest.unit.config.js
index 5d31b299bd..2819ba86ca 100644
--- a/web-console/jest.unit.config.js
+++ b/web-console/jest.unit.config.js
@@ -22,7 +22,6 @@ module.exports = Object.assign(common, {
   moduleNameMapper: {
     '\\.s?css$': 'identity-obj-proxy',
   },
-  snapshotSerializers: ['enzyme-to-json/serializer'],
   setupFilesAfterEnv: ['<rootDir>src/setup-tests.ts'],
   testMatch: ['**/src/**/?(*.)+(spec).(ts|tsx)'],
 });
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index 8776b62e3b..46d83a8e94 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -44,10 +44,10 @@
         "react-table": "~6.10.3",
         "regenerator-runtime": "^0.13.7",
         "tslib": "^2.3.1",
-        "zustand": "^3.6.5"
+        "zustand": "^4.3.2"
       },
       "devDependencies": {
-        "@awesome-code-style/eslint-config": "^4.0.0",
+        "@awesome-code-style/eslint-config": "^4.1.0",
         "@awesome-code-style/prettier-config": "^4.0.0",
         "@awesome-code-style/stylelint-config": "^4.0.0",
         "@babel/core": "^7.14.3",
@@ -74,15 +74,13 @@
         "@types/react-splitter-layout": "^3.0.0",
         "@types/react-table": "6.8.5",
         "@types/uuid": "^7.0.2",
-        "@typescript-eslint/eslint-plugin": "^5.11.0",
+        "@typescript-eslint/eslint-plugin": "^5.51.0",
+        "@typescript-eslint/parser": "^5.51.0",
         "autoprefixer": "^10.2.6",
         "babel-loader": "^8.2.2",
         "browserslist": "^4.16.6",
         "codecov": "^3.8.2",
         "css-loader": "^5.2.1",
-        "enzyme": "^3.10.0",
-        "enzyme-adapter-react-16": "^1.15.1",
-        "enzyme-to-json": "^3.4.3",
         "eslint": "^8.8.0",
         "eslint-config-prettier": "^8.3.0",
         "eslint-plugin-header": "^3.1.1",
@@ -103,15 +101,16 @@
         "postcss-loader": "^5.3.0",
         "postcss-preset-env": "^6.7.0",
         "prettier": "^2.5.1",
+        "react-shallow-renderer": "^16.15.0",
         "replace": "^1.2.2",
         "sass-loader": "^11.1.0",
         "snarkdown": "^2.0.0",
         "style-loader": "^2.0.0",
         "stylelint": "^13.12.0",
         "ts-jest": "^27.1.3",
-        "ts-loader": "^8.1.0",
+        "ts-loader": "^9.4.2",
         "ts-node": "^10.9.1",
-        "typescript": "^4.5.5",
+        "typescript": "^4.9.5",
         "uuid": "^7.0.2",
         "webpack": "^5.33.2",
         "webpack-bundle-analyzer": "^4.4.1",
@@ -123,9 +122,9 @@
       }
     },
     "node_modules/@awesome-code-style/eslint-config": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@awesome-code-style/eslint-config/-/eslint-config-4.0.0.tgz",
-      "integrity": "sha512-hLtTlWXXNU/56e1hYCNsP6ptJco7G84kzKx13u1sXb7ORihfjGWV0NEMAG2dlRbBQlo63Oxefr5A5D0tHnBWXg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@awesome-code-style/eslint-config/-/eslint-config-4.1.0.tgz",
+      "integrity": "sha512-exq+8wS8mTM+2M6w7KR1ajVvYTH1jgR5nHR8XYa+qD2YoFSpE4bGgVugIm1+GlVFl8jkhy2erCiHyc97l8NOzA==",
       "dev": true,
       "dependencies": {
         "@typescript-eslint/parser": "^5.3.0"
@@ -137,8 +136,7 @@
         "eslint-plugin-import": "^2.25.2",
         "eslint-plugin-react": "^7.26.1",
         "eslint-plugin-react-hooks": "^4.2.0",
-        "eslint-plugin-simple-import-sort": "^7.0.0",
-        "eslint-plugin-unicorn": "^38.0.0",
+        "eslint-plugin-simple-import-sort": "^7.0.0 || ^8.0.0",
         "eslint-plugin-unused-imports": "^2.0.0"
       },
       "peerDependenciesMeta": {
@@ -3288,12 +3286,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/@jest/core/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/@jest/core/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3861,12 +3853,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/@jest/reporters/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/@jest/reporters/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3940,12 +3926,6 @@
         "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
       }
     },
-    "node_modules/@jest/source-map/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/@jest/source-map/node_modules/source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -4089,12 +4069,6 @@
         "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
       }
     },
-    "node_modules/@jest/test-sequencer/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/@jest/transform": {
       "version": "27.5.0",
       "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.0.tgz",
@@ -4228,12 +4202,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/@jest/transform/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/@jest/transform/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -4799,9 +4767,9 @@
       "dev": true
     },
     "node_modules/@types/json-schema": {
-      "version": "7.0.7",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
-      "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
       "dev": true
     },
     "node_modules/@types/json5": {
@@ -4961,6 +4929,12 @@
       "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==",
       "dev": true
     },
+    "node_modules/@types/semver": {
+      "version": "7.3.13",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+      "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+      "dev": true
+    },
     "node_modules/@types/stack-utils": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
@@ -4995,19 +4969,20 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.11.0.tgz",
-      "integrity": "sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz",
+      "integrity": "sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/type-utils": "5.11.0",
-        "@typescript-eslint/utils": "5.11.0",
-        "debug": "^4.3.2",
-        "functional-red-black-tree": "^1.0.1",
-        "ignore": "^5.1.8",
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/type-utils": "5.51.0",
+        "@typescript-eslint/utils": "5.51.0",
+        "debug": "^4.3.4",
+        "grapheme-splitter": "^1.0.4",
+        "ignore": "^5.2.0",
+        "natural-compare-lite": "^1.4.0",
         "regexpp": "^3.2.0",
-        "semver": "^7.3.5",
+        "semver": "^7.3.7",
         "tsutils": "^3.21.0"
       },
       "engines": {
@@ -5028,9 +5003,9 @@
       }
     },
     "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
-      "version": "4.3.3",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -5051,9 +5026,9 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
-      "version": "7.3.5",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-      "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+      "version": "7.3.8",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
       "dev": true,
       "dependencies": {
         "lru-cache": "^6.0.0"
@@ -5066,15 +5041,15 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.11.0.tgz",
-      "integrity": "sha512-x0DCjetHZYBRovJdr3U0zG9OOdNXUaFLJ82ehr1AlkArljJuwEsgnud+Q7umlGDFLFrs8tU8ybQDFocp/eX8mQ==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.51.0.tgz",
+      "integrity": "sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/typescript-estree": "5.11.0",
-        "debug": "^4.3.2"
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/typescript-estree": "5.51.0",
+        "debug": "^4.3.4"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5093,9 +5068,9 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/debug": {
-      "version": "4.3.3",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -5116,13 +5091,13 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz",
-      "integrity": "sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz",
+      "integrity": "sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/visitor-keys": "5.11.0"
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/visitor-keys": "5.51.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5133,13 +5108,14 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz",
-      "integrity": "sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz",
+      "integrity": "sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/utils": "5.11.0",
-        "debug": "^4.3.2",
+        "@typescript-eslint/typescript-estree": "5.51.0",
+        "@typescript-eslint/utils": "5.51.0",
+        "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       },
       "engines": {
@@ -5159,9 +5135,9 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils/node_modules/debug": {
-      "version": "4.3.3",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -5182,9 +5158,9 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.11.0.tgz",
-      "integrity": "sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.51.0.tgz",
+      "integrity": "sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5195,17 +5171,17 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz",
-      "integrity": "sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz",
+      "integrity": "sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/visitor-keys": "5.11.0",
-        "debug": "^4.3.2",
-        "globby": "^11.0.4",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/visitor-keys": "5.51.0",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
         "is-glob": "^4.0.3",
-        "semver": "^7.3.5",
+        "semver": "^7.3.7",
         "tsutils": "^3.21.0"
       },
       "engines": {
@@ -5230,22 +5206,10 @@
         "node": ">=8"
       }
     },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "dependencies": {
-        "fill-range": "^7.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
-      "version": "4.3.3",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -5259,46 +5223,6 @@
         }
       }
     },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": {
-      "version": "3.2.11",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
-      "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      },
-      "engines": {
-        "node": ">=8.6.0"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
     "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": {
       "version": "11.1.0",
       "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
@@ -5319,49 +5243,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/ignore": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-      "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/micromatch": {
-      "version": "4.0.4",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
-      "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
-      "dev": true,
-      "dependencies": {
-        "braces": "^3.0.1",
-        "picomatch": "^2.2.3"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
     "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -5369,9 +5250,9 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
-      "version": "7.3.5",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-      "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+      "version": "7.3.8",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
       "dev": true,
       "dependencies": {
         "lru-cache": "^6.0.0"
@@ -5383,30 +5264,20 @@
         "node": ">=10"
       }
     },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
     "node_modules/@typescript-eslint/utils": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.11.0.tgz",
-      "integrity": "sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.51.0.tgz",
+      "integrity": "sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==",
       "dev": true,
       "dependencies": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/typescript-estree": "5.11.0",
+        "@types/semver": "^7.3.12",
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/typescript-estree": "5.51.0",
         "eslint-scope": "^5.1.1",
-        "eslint-utils": "^3.0.0"
+        "eslint-utils": "^3.0.0",
+        "semver": "^7.3.7"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5419,20 +5290,29 @@
         "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
       }
     },
-    "node_modules/@typescript-eslint/utils/node_modules/@types/json-schema": {
-      "version": "7.0.9",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-      "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
-      "dev": true
+    "node_modules/@typescript-eslint/utils/node_modules/semver": {
+      "version": "7.3.8",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz",
-      "integrity": "sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz",
+      "integrity": "sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.11.0",
-        "eslint-visitor-keys": "^3.0.0"
+        "@typescript-eslint/types": "5.51.0",
+        "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5762,33 +5642,6 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
       "dev": true
     },
-    "node_modules/airbnb-prop-types": {
-      "version": "2.15.0",
-      "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz",
-      "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==",
-      "dev": true,
-      "dependencies": {
-        "array.prototype.find": "^2.1.0",
-        "function.prototype.name": "^1.1.1",
-        "has": "^1.0.3",
-        "is-regex": "^1.0.4",
-        "object-is": "^1.0.1",
-        "object.assign": "^4.1.0",
-        "object.entries": "^1.1.0",
-        "prop-types": "^15.7.2",
-        "prop-types-exact": "^1.2.0",
-        "react-is": "^16.9.0"
-      },
-      "peerDependencies": {
-        "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha"
-      }
-    },
-    "node_modules/airbnb-prop-types/node_modules/react-is": {
-      "version": "16.11.0",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
-      "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==",
-      "dev": true
-    },
     "node_modules/ajv": {
       "version": "6.12.6",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -6029,12 +5882,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/array-filter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
-      "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=",
-      "dev": true
-    },
     "node_modules/array-find-index": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
@@ -6232,30 +6079,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/array.prototype.find": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.0.tgz",
-      "integrity": "sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.13.0"
-      }
-    },
-    "node_modules/array.prototype.flat": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
-      "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.2",
-        "es-abstract": "^1.10.0",
-        "function-bind": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/array.prototype.flatmap": {
       "version": "1.2.5",
       "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz",
@@ -6676,12 +6499,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/babel-jest/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/babel-jest/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -7096,12 +6913,6 @@
         "multicast-dns-service-types": "^1.1.0"
       }
     },
-    "node_modules/boolbase": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
-      "dev": true
-    },
     "node_modules/brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -7419,236 +7230,6 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/cheerio": {
-      "version": "1.0.0-rc.10",
-      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
-      "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
-      "dev": true,
-      "dependencies": {
-        "cheerio-select": "^1.5.0",
-        "dom-serializer": "^1.3.2",
-        "domhandler": "^4.2.0",
-        "htmlparser2": "^6.1.0",
-        "parse5": "^6.0.1",
-        "parse5-htmlparser2-tree-adapter": "^6.0.1",
-        "tslib": "^2.2.0"
-      },
-      "engines": {
-        "node": ">= 6"
-      },
-      "funding": {
-        "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
-      }
-    },
-    "node_modules/cheerio-select": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
-      "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
-      "dev": true,
-      "dependencies": {
-        "css-select": "^4.1.3",
-        "css-what": "^5.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0",
-        "domutils": "^2.7.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/fb55"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/css-select": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
-      "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
-      "dev": true,
-      "dependencies": {
-        "boolbase": "^1.0.0",
-        "css-what": "^5.1.0",
-        "domhandler": "^4.3.0",
-        "domutils": "^2.8.0",
-        "nth-check": "^2.0.1"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/fb55"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/css-what": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-      "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/fb55"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/dom-serializer": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.0",
-        "entities": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/domelementtype": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ]
-    },
-    "node_modules/cheerio-select/node_modules/domhandler": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-      "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.2.0"
-      },
-      "engines": {
-        "node": ">= 4"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domhandler?sponsor=1"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/domutils": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-      "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-      "dev": true,
-      "dependencies": {
-        "dom-serializer": "^1.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domutils?sponsor=1"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/entities": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/fb55/entities?sponsor=1"
-      }
-    },
-    "node_modules/cheerio-select/node_modules/nth-check": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
-      "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
-      "dev": true,
-      "dependencies": {
-        "boolbase": "^1.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/nth-check?sponsor=1"
-      }
-    },
-    "node_modules/cheerio/node_modules/dom-serializer": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.0",
-        "entities": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-      }
-    },
-    "node_modules/cheerio/node_modules/domelementtype": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ]
-    },
-    "node_modules/cheerio/node_modules/domhandler": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-      "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.2.0"
-      },
-      "engines": {
-        "node": ">= 4"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domhandler?sponsor=1"
-      }
-    },
-    "node_modules/cheerio/node_modules/domutils": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-      "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-      "dev": true,
-      "dependencies": {
-        "dom-serializer": "^1.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domutils?sponsor=1"
-      }
-    },
-    "node_modules/cheerio/node_modules/entities": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/fb55/entities?sponsor=1"
-      }
-    },
-    "node_modules/cheerio/node_modules/htmlparser2": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-      "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-      "dev": true,
-      "funding": [
-        "https://github.com/fb55/htmlparser2?sponsor=1",
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ],
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.0.0",
-        "domutils": "^2.5.2",
-        "entities": "^2.0.0"
-      }
-    },
-    "node_modules/cheerio/node_modules/parse5": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-      "dev": true
-    },
     "node_modules/chokidar": {
       "version": "2.1.8",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
@@ -8833,12 +8414,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/discontinuous-range": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
-      "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
-      "dev": true
-    },
     "node_modules/dns-equal": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -9060,17 +8635,16 @@
       }
     },
     "node_modules/enhanced-resolve": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
-      "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+      "version": "5.12.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
+      "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
       "dev": true,
       "dependencies": {
-        "graceful-fs": "^4.1.2",
-        "memory-fs": "^0.5.0",
-        "tapable": "^1.0.0"
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": ">=10.13.0"
       }
     },
     "node_modules/enquirer": {
@@ -9112,105 +8686,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/enzyme": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.10.0.tgz",
-      "integrity": "sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg==",
-      "dev": true,
-      "dependencies": {
-        "array.prototype.flat": "^1.2.1",
-        "cheerio": "^1.0.0-rc.2",
-        "function.prototype.name": "^1.1.0",
-        "has": "^1.0.3",
-        "html-element-map": "^1.0.0",
-        "is-boolean-object": "^1.0.0",
-        "is-callable": "^1.1.4",
-        "is-number-object": "^1.0.3",
-        "is-regex": "^1.0.4",
-        "is-string": "^1.0.4",
-        "is-subset": "^0.1.1",
-        "lodash.escape": "^4.0.1",
-        "lodash.isequal": "^4.5.0",
-        "object-inspect": "^1.6.0",
-        "object-is": "^1.0.1",
-        "object.assign": "^4.1.0",
-        "object.entries": "^1.0.4",
-        "object.values": "^1.0.4",
-        "raf": "^3.4.0",
-        "rst-selector-parser": "^2.2.3",
-        "string.prototype.trim": "^1.1.2"
-      }
-    },
-    "node_modules/enzyme-adapter-react-16": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.1.tgz",
-      "integrity": "sha512-yMPxrP3vjJP+4wL/qqfkT6JAIctcwKF+zXO6utlGPgUJT2l4tzrdjMDWGd/Pp1BjHBcljhN24OzNEGRteibJhA==",
-      "dev": true,
-      "dependencies": {
-        "enzyme-adapter-utils": "^1.12.1",
-        "enzyme-shallow-equal": "^1.0.0",
-        "has": "^1.0.3",
-        "object.assign": "^4.1.0",
-        "object.values": "^1.1.0",
-        "prop-types": "^15.7.2",
-        "react-is": "^16.10.2",
-        "react-test-renderer": "^16.0.0-0",
-        "semver": "^5.7.0"
-      },
-      "peerDependencies": {
-        "enzyme": "^3.0.0",
-        "react": "^16.0.0-0",
-        "react-dom": "^16.0.0-0"
-      }
-    },
-    "node_modules/enzyme-adapter-react-16/node_modules/react-is": {
-      "version": "16.11.0",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
-      "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==",
-      "dev": true
-    },
-    "node_modules/enzyme-adapter-utils": {
-      "version": "1.12.1",
-      "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.1.tgz",
-      "integrity": "sha512-KWiHzSjZaLEoDCOxY8Z1RAbUResbqKN5bZvenPbfKtWorJFVETUw754ebkuCQ3JKm0adx1kF8JaiR+PHPiP47g==",
-      "dev": true,
-      "dependencies": {
-        "airbnb-prop-types": "^2.15.0",
-        "function.prototype.name": "^1.1.1",
-        "object.assign": "^4.1.0",
-        "object.fromentries": "^2.0.1",
-        "prop-types": "^15.7.2",
-        "semver": "^5.7.0"
-      },
-      "peerDependencies": {
-        "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0"
-      }
-    },
-    "node_modules/enzyme-shallow-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz",
-      "integrity": "sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ==",
-      "dev": true,
-      "dependencies": {
-        "has": "^1.0.3",
-        "object-is": "^1.0.1"
-      }
-    },
-    "node_modules/enzyme-to-json": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.4.3.tgz",
-      "integrity": "sha512-jqNEZlHqLdz7OTpXSzzghArSS3vigj67IU/fWkPyl1c0TCj9P5s6Ze0kRkYZWNEoCqCR79xlQbigYlMx5erh8A==",
-      "dev": true,
-      "dependencies": {
-        "lodash": "^4.17.15"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      },
-      "peerDependencies": {
-        "enzyme": "^3.4.0"
-      }
-    },
     "node_modules/errno": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
@@ -9231,43 +8706,12 @@
         "is-arrayish": "^0.2.1"
       }
     },
-    "node_modules/es-abstract": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
-      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
-      "dev": true,
-      "dependencies": {
-        "es-to-primitive": "^1.2.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "is-callable": "^1.1.4",
-        "is-regex": "^1.0.4",
-        "object-keys": "^1.0.12"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/es-module-lexer": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz",
       "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==",
       "dev": true
     },
-    "node_modules/es-to-primitive": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
-      "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
-      "dev": true,
-      "dependencies": {
-        "is-callable": "^1.1.4",
-        "is-date-object": "^1.0.1",
-        "is-symbol": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -9724,18 +9168,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/eslint-plugin-import/node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/eslint-plugin-import/node_modules/is-regex": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -10262,9 +9694,9 @@
       }
     },
     "node_modules/eslint-visitor-keys": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz",
-      "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+      "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -10411,18 +9843,6 @@
         "node": ">=10.13.0"
       }
     },
-    "node_modules/eslint/node_modules/glob-parent/node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/eslint/node_modules/globals": {
       "version": "13.12.1",
       "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz",
@@ -10447,15 +9867,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/eslint/node_modules/ignore": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-      "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
     "node_modules/eslint/node_modules/js-yaml": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -11085,20 +10496,19 @@
       "dev": true
     },
     "node_modules/fast-glob": {
-      "version": "3.2.5",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
-      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+      "version": "3.2.12",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+      "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
       "dev": true,
       "dependencies": {
         "@nodelib/fs.stat": "^2.0.2",
         "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.0",
+        "glob-parent": "^5.1.2",
         "merge2": "^1.3.0",
-        "micromatch": "^4.0.2",
-        "picomatch": "^2.2.1"
+        "micromatch": "^4.0.4"
       },
       "engines": {
-        "node": ">=8"
+        "node": ">=8.6.0"
       }
     },
     "node_modules/fast-glob/node_modules/braces": {
@@ -11598,33 +11008,12 @@
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
-    "node_modules/function.prototype.name": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.1.tgz",
-      "integrity": "sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1",
-        "functions-have-names": "^1.1.1",
-        "is-callable": "^1.1.4"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/functional-red-black-tree": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
       "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
       "dev": true
     },
-    "node_modules/functions-have-names": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.1.1.tgz",
-      "integrity": "sha512-U0kNHUoxwPNPWOJaMG7Z00d4a/qZVrFtzWJRaK8V9goaVOCXBSQSJpt3MYGNtkScKEBKovxLjnNdC9MlXwo5Pw==",
-      "dev": true
-    },
     "node_modules/gauge": {
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -11928,9 +11317,15 @@
       }
     },
     "node_modules/graceful-fs": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz",
-      "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==",
+      "version": "4.2.10",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+      "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+      "dev": true
+    },
+    "node_modules/grapheme-splitter": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+      "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
       "dev": true
     },
     "node_modules/gud": {
@@ -12227,15 +11622,6 @@
         "safe-buffer": "~5.1.0"
       }
     },
-    "node_modules/html-element-map": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.1.0.tgz",
-      "integrity": "sha512-iqiG3dTZmy+uUaTmHarTL+3/A2VW9ox/9uasKEZC+R/wAtUrTcRlXPSaPqsnWPfIu8wqn09jQNwMRqzL54jSYA==",
-      "dev": true,
-      "dependencies": {
-        "array-filter": "^1.0.0"
-      }
-    },
     "node_modules/html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -12480,9 +11866,9 @@
       }
     },
     "node_modules/ignore": {
-      "version": "5.1.8",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
-      "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
       "dev": true,
       "engines": {
         "node": ">= 4"
@@ -12748,15 +12134,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-boolean-object": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz",
-      "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/is-buffer": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
@@ -12792,15 +12169,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/is-callable": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/is-core-module": {
       "version": "2.10.0",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
@@ -12921,9 +12289,9 @@
       }
     },
     "node_modules/is-glob": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
       "dev": true,
       "dependencies": {
         "is-extglob": "^2.1.1"
@@ -12966,15 +12334,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-number-object": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz",
-      "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/is-number/node_modules/is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -13091,21 +12450,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-string": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz",
-      "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/is-subset": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
-      "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
-      "dev": true
-    },
     "node_modules/is-symbol": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
@@ -13919,12 +13263,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/jest-config/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-config/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -14723,12 +14061,6 @@
         "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
       }
     },
-    "node_modules/jest-haste-map/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-haste-map/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -15363,12 +14695,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/jest-message-util/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-message-util/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -15809,12 +15135,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/jest-resolve/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-resolve/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -15968,12 +15288,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/jest-runner/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-runner/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -16189,12 +15503,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/jest-runtime/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-runtime/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -16313,12 +15621,6 @@
         "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
       }
     },
-    "node_modules/jest-serializer/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-snapshot": {
       "version": "27.5.0",
       "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.0.tgz",
@@ -16444,12 +15746,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/jest-snapshot/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-snapshot/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -16618,12 +15914,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/jest-util/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest-util/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -17079,12 +16369,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/jest/node_modules/graceful-fs": {
-      "version": "4.2.9",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-      "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-      "dev": true
-    },
     "node_modules/jest/node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -17618,12 +16902,6 @@
       "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
       "dev": true
     },
-    "node_modules/lodash.flattendeep": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
-      "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
-      "dev": true
-    },
     "node_modules/lodash.get": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -17949,49 +17227,6 @@
       "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
       "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
     },
-    "node_modules/memory-fs": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
-      "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
-      "dev": true,
-      "dependencies": {
-        "errno": "^0.1.3",
-        "readable-stream": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=4.3.0 <5.0.0 || >=5.10"
-      }
-    },
-    "node_modules/memory-fs/node_modules/isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
-    },
-    "node_modules/memory-fs/node_modules/readable-stream": {
-      "version": "2.3.7",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-      "dev": true,
-      "dependencies": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "node_modules/memory-fs/node_modules/string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "~5.1.0"
-      }
-    },
     "node_modules/meow": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -18340,12 +17575,6 @@
         "mkdirp": "bin/cmd.js"
       }
     },
-    "node_modules/moo": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
-      "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
-      "dev": true
-    },
     "node_modules/ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -18423,24 +17652,11 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
-    "node_modules/nearley": {
-      "version": "2.18.0",
-      "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.18.0.tgz",
-      "integrity": "sha512-/zQOMCeJcioI0xJtd5RpBiWw2WP7wLe6vq8/3Yu0rEwgus/G/+pViX80oA87JdVgjRt2895mZSv2VfZmy4W1uw==",
-      "dev": true,
-      "dependencies": {
-        "commander": "^2.19.0",
-        "moo": "^0.4.3",
-        "railroad-diagrams": "^1.0.0",
-        "randexp": "0.4.6",
-        "semver": "^5.4.1"
-      },
-      "bin": {
-        "nearley-railroad": "bin/nearley-railroad.js",
-        "nearley-test": "bin/nearley-test.js",
-        "nearley-unparse": "bin/nearley-unparse.js",
-        "nearleyc": "bin/nearleyc.js"
-      }
+    "node_modules/natural-compare-lite": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+      "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+      "dev": true
     },
     "node_modules/negotiator": {
       "version": "0.6.2",
@@ -18547,12 +17763,6 @@
         "node": ">= 10.12.0"
       }
     },
-    "node_modules/node-gyp/node_modules/graceful-fs": {
-      "version": "4.2.6",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-      "dev": true
-    },
     "node_modules/node-gyp/node_modules/nopt": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -18916,12 +18126,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/object-inspect": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
-      "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
-      "dev": true
-    },
     "node_modules/object-is": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
@@ -18965,57 +18169,6 @@
         "node": ">= 0.4"
       }
     },
-    "node_modules/object.entries": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
-      "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.12.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/object.fromentries": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.1.tgz",
-      "integrity": "sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.15.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/object.fromentries/node_modules/es-abstract": {
-      "version": "1.16.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz",
-      "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==",
-      "dev": true,
-      "dependencies": {
-        "es-to-primitive": "^1.2.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.0",
-        "is-callable": "^1.1.4",
-        "is-regex": "^1.0.4",
-        "object-inspect": "^1.6.0",
-        "object-keys": "^1.1.1",
-        "string.prototype.trimleft": "^2.1.0",
-        "string.prototype.trimright": "^2.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/object.hasown": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz",
@@ -19174,21 +18327,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/object.values": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
-      "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.12.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/obuf": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
@@ -19433,21 +18571,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/parse5-htmlparser2-tree-adapter": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
-      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
-      "dev": true,
-      "dependencies": {
-        "parse5": "^6.0.1"
-      }
-    },
-    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-      "dev": true
-    },
     "node_modules/parseurl": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -21464,17 +20587,6 @@
         "react-is": "^16.8.1"
       }
     },
-    "node_modules/prop-types-exact": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz",
-      "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==",
-      "dev": true,
-      "dependencies": {
-        "has": "^1.0.3",
-        "object.assign": "^4.1.0",
-        "reflect.ownkeys": "^0.2.0"
-      }
-    },
     "node_modules/proxy-addr": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@@ -21573,34 +20685,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/raf": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
-      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
-      "dev": true,
-      "dependencies": {
-        "performance-now": "^2.1.0"
-      }
-    },
-    "node_modules/railroad-diagrams": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
-      "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
-      "dev": true
-    },
-    "node_modules/randexp": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
-      "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
-      "dev": true,
-      "dependencies": {
-        "discontinuous-range": "1.0.0",
-        "ret": "~0.1.10"
-      },
-      "engines": {
-        "node": ">=0.12"
-      }
-    },
     "node_modules/randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -21717,15 +20801,6 @@
         "react": "^16.14.0"
       }
     },
-    "node_modules/react-dom/node_modules/scheduler": {
-      "version": "0.19.1",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
-      "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
-      "dependencies": {
-        "loose-envify": "^1.1.0",
-        "object-assign": "^4.1.1"
-      }
-    },
     "node_modules/react-fast-compare": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
@@ -21790,6 +20865,25 @@
         "react": ">=15"
       }
     },
+    "node_modules/react-shallow-renderer": {
+      "version": "16.15.0",
+      "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
+      "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==",
+      "dev": true,
+      "dependencies": {
+        "object-assign": "^4.1.1",
+        "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
+      },
+      "peerDependencies": {
+        "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/react-shallow-renderer/node_modules/react-is": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+      "dev": true
+    },
     "node_modules/react-splitter-layout": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/react-splitter-layout/-/react-splitter-layout-4.0.0.tgz",
@@ -21812,21 +20906,6 @@
         "react-dom": "^15.x.x || ^16.x.x"
       }
     },
-    "node_modules/react-test-renderer": {
-      "version": "16.11.0",
-      "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.11.0.tgz",
-      "integrity": "sha512-nh9gDl8R4ut+ZNNb2EeKO5VMvTKxwzurbSMuGBoKtjpjbg8JK/u3eVPVNi1h1Ue+eYK9oSzJjb+K3lzLxyA4ag==",
-      "dev": true,
-      "dependencies": {
-        "object-assign": "^4.1.1",
-        "prop-types": "^15.6.2",
-        "react-is": "^16.8.6",
-        "scheduler": "^0.17.0"
-      },
-      "peerDependencies": {
-        "react": "^16.0.0"
-      }
-    },
     "node_modules/react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@@ -22074,12 +21153,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/reflect.ownkeys": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz",
-      "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=",
-      "dev": true
-    },
     "node_modules/regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -22659,16 +21732,6 @@
         "rimraf": "bin.js"
       }
     },
-    "node_modules/rst-selector-parser": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
-      "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
-      "dev": true,
-      "dependencies": {
-        "lodash.flattendeep": "^4.4.0",
-        "nearley": "^2.7.10"
-      }
-    },
     "node_modules/run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -22774,10 +21837,9 @@
       }
     },
     "node_modules/scheduler": {
-      "version": "0.17.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz",
-      "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==",
-      "dev": true,
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
+      "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
       "dependencies": {
         "loose-envify": "^1.1.0",
         "object-assign": "^4.1.1"
@@ -24000,20 +23062,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/string.prototype.trim": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz",
-      "integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.13.0",
-        "function-bind": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/string.prototype.trimend": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
@@ -24027,32 +23075,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/string.prototype.trimleft": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
-      "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/string.prototype.trimright": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
-      "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
     "node_modules/string.prototype.trimstart": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
@@ -24849,9 +23871,9 @@
       }
     },
     "node_modules/tapable": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-      "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
       "dev": true,
       "engines": {
         "node": ">=6"
@@ -25295,23 +24317,22 @@
       }
     },
     "node_modules/ts-loader": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.1.0.tgz",
-      "integrity": "sha512-YiQipGGAFj2zBfqLhp28yUvPP9jUGqHxRzrGYuc82Z2wM27YIHbElXiaZDc93c3x0mz4zvBmS6q/DgExpdj37A==",
+      "version": "9.4.2",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz",
+      "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==",
       "dev": true,
       "dependencies": {
         "chalk": "^4.1.0",
-        "enhanced-resolve": "^4.0.0",
-        "loader-utils": "^2.0.0",
+        "enhanced-resolve": "^5.0.0",
         "micromatch": "^4.0.0",
         "semver": "^7.3.4"
       },
       "engines": {
-        "node": ">=10.0.0"
+        "node": ">=12.0.0"
       },
       "peerDependencies": {
         "typescript": "*",
-        "webpack": "*"
+        "webpack": "^5.0.0"
       }
     },
     "node_modules/ts-loader/node_modules/ansi-styles": {
@@ -25405,35 +24426,6 @@
         "node": ">=0.12.0"
       }
     },
-    "node_modules/ts-loader/node_modules/json5": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
-      "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.5"
-      },
-      "bin": {
-        "json5": "lib/cli.js"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/ts-loader/node_modules/loader-utils": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-      "dev": true,
-      "dependencies": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^2.1.2"
-      },
-      "engines": {
-        "node": ">=8.9.0"
-      }
-    },
     "node_modules/ts-loader/node_modules/micromatch": {
       "version": "4.0.4",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -25646,9 +24638,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "4.5.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
-      "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+      "version": "4.9.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+      "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
       "dev": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -25955,6 +24947,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/use-sync-external-store": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+      "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
     "node_modules/util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -26783,25 +25783,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/webpack/node_modules/enhanced-resolve": {
-      "version": "5.7.0",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz",
-      "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.2.4",
-        "tapable": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/webpack/node_modules/graceful-fs": {
-      "version": "4.2.6",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-      "dev": true
-    },
     "node_modules/webpack/node_modules/mime-db": {
       "version": "1.47.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
@@ -26841,15 +25822,6 @@
         "url": "https://opencollective.com/webpack"
       }
     },
-    "node_modules/webpack/node_modules/tapable": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz",
-      "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/websocket-driver": {
       "version": "0.7.4",
       "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
@@ -27232,16 +26204,23 @@
       }
     },
     "node_modules/zustand": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
-      "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.2.tgz",
+      "integrity": "sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==",
+      "dependencies": {
+        "use-sync-external-store": "1.2.0"
+      },
       "engines": {
         "node": ">=12.7.0"
       },
       "peerDependencies": {
+        "immer": ">=9.0",
         "react": ">=16.8"
       },
       "peerDependenciesMeta": {
+        "immer": {
+          "optional": true
+        },
         "react": {
           "optional": true
         }
@@ -27260,9 +26239,9 @@
   },
   "dependencies": {
     "@awesome-code-style/eslint-config": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@awesome-code-style/eslint-config/-/eslint-config-4.0.0.tgz",
-      "integrity": "sha512-hLtTlWXXNU/56e1hYCNsP6ptJco7G84kzKx13u1sXb7ORihfjGWV0NEMAG2dlRbBQlo63Oxefr5A5D0tHnBWXg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@awesome-code-style/eslint-config/-/eslint-config-4.1.0.tgz",
+      "integrity": "sha512-exq+8wS8mTM+2M6w7KR1ajVvYTH1jgR5nHR8XYa+qD2YoFSpE4bGgVugIm1+GlVFl8jkhy2erCiHyc97l8NOzA==",
       "dev": true,
       "requires": {
         "@typescript-eslint/parser": "^5.3.0"
@@ -30056,12 +29035,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -30503,12 +29476,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -30565,12 +29532,6 @@
         "source-map": "^0.6.0"
       },
       "dependencies": {
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -30683,14 +29644,6 @@
         "graceful-fs": "^4.2.9",
         "jest-haste-map": "^27.5.0",
         "jest-runtime": "^27.5.0"
-      },
-      "dependencies": {
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        }
       }
     },
     "@jest/transform": {
@@ -30799,12 +29752,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -31297,9 +30244,9 @@
       }
     },
     "@types/json-schema": {
-      "version": "7.0.7",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
-      "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
       "dev": true
     },
     "@types/json5": {
@@ -31459,6 +30406,12 @@
       "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==",
       "dev": true
     },
+    "@types/semver": {
+      "version": "7.3.13",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+      "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+      "dev": true
+    },
     "@types/stack-utils": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
@@ -31493,26 +30446,27 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.11.0.tgz",
-      "integrity": "sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz",
+      "integrity": "sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/type-utils": "5.11.0",
-        "@typescript-eslint/utils": "5.11.0",
-        "debug": "^4.3.2",
-        "functional-red-black-tree": "^1.0.1",
-        "ignore": "^5.1.8",
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/type-utils": "5.51.0",
+        "@typescript-eslint/utils": "5.51.0",
+        "debug": "^4.3.4",
+        "grapheme-splitter": "^1.0.4",
+        "ignore": "^5.2.0",
+        "natural-compare-lite": "^1.4.0",
         "regexpp": "^3.2.0",
-        "semver": "^7.3.5",
+        "semver": "^7.3.7",
         "tsutils": "^3.21.0"
       },
       "dependencies": {
         "debug": {
-          "version": "4.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-          "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -31525,9 +30479,9 @@
           "dev": true
         },
         "semver": {
-          "version": "7.3.5",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "version": "7.3.8",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+          "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
           "dev": true,
           "requires": {
             "lru-cache": "^6.0.0"
@@ -31536,21 +30490,21 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.11.0.tgz",
-      "integrity": "sha512-x0DCjetHZYBRovJdr3U0zG9OOdNXUaFLJ82ehr1AlkArljJuwEsgnud+Q7umlGDFLFrs8tU8ybQDFocp/eX8mQ==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.51.0.tgz",
+      "integrity": "sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/typescript-estree": "5.11.0",
-        "debug": "^4.3.2"
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/typescript-estree": "5.51.0",
+        "debug": "^4.3.4"
       },
       "dependencies": {
         "debug": {
-          "version": "4.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-          "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -31565,30 +30519,31 @@
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz",
-      "integrity": "sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz",
+      "integrity": "sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/visitor-keys": "5.11.0"
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/visitor-keys": "5.51.0"
       }
     },
     "@typescript-eslint/type-utils": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz",
-      "integrity": "sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz",
+      "integrity": "sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/utils": "5.11.0",
-        "debug": "^4.3.2",
+        "@typescript-eslint/typescript-estree": "5.51.0",
+        "@typescript-eslint/utils": "5.51.0",
+        "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       },
       "dependencies": {
         "debug": {
-          "version": "4.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-          "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -31603,23 +30558,23 @@
       }
     },
     "@typescript-eslint/types": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.11.0.tgz",
-      "integrity": "sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.51.0.tgz",
+      "integrity": "sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz",
-      "integrity": "sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz",
+      "integrity": "sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/visitor-keys": "5.11.0",
-        "debug": "^4.3.2",
-        "globby": "^11.0.4",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/visitor-keys": "5.51.0",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
         "is-glob": "^4.0.3",
-        "semver": "^7.3.5",
+        "semver": "^7.3.7",
         "tsutils": "^3.21.0"
       },
       "dependencies": {
@@ -31629,55 +30584,15 @@
           "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
           "dev": true
         },
-        "braces": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-          "dev": true,
-          "requires": {
-            "fill-range": "^7.0.1"
-          }
-        },
         "debug": {
-          "version": "4.3.3",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-          "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+          "version": "4.3.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
           }
         },
-        "fast-glob": {
-          "version": "3.2.11",
-          "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
-          "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
-          "dev": true,
-          "requires": {
-            "@nodelib/fs.stat": "^2.0.2",
-            "@nodelib/fs.walk": "^1.2.3",
-            "glob-parent": "^5.1.2",
-            "merge2": "^1.3.0",
-            "micromatch": "^4.0.4"
-          }
-        },
-        "fill-range": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-          "dev": true,
-          "requires": {
-            "to-regex-range": "^5.0.1"
-          }
-        },
-        "glob-parent": {
-          "version": "5.1.2",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-          "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
         "globby": {
           "version": "11.1.0",
           "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
@@ -31692,37 +30607,6 @@
             "slash": "^3.0.0"
           }
         },
-        "ignore": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-          "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "4.0.3",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-          "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.1"
-          }
-        },
-        "is-number": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-          "dev": true
-        },
-        "micromatch": {
-          "version": "4.0.4",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
-          "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
-          "dev": true,
-          "requires": {
-            "braces": "^3.0.1",
-            "picomatch": "^2.2.3"
-          }
-        },
         "ms": {
           "version": "2.1.2",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -31730,55 +30614,51 @@
           "dev": true
         },
         "semver": {
-          "version": "7.3.5",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "version": "7.3.8",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+          "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
           "dev": true,
           "requires": {
             "lru-cache": "^6.0.0"
           }
-        },
-        "to-regex-range": {
-          "version": "5.0.1",
-          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-          "dev": true,
-          "requires": {
-            "is-number": "^7.0.0"
-          }
         }
       }
     },
     "@typescript-eslint/utils": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.11.0.tgz",
-      "integrity": "sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.51.0.tgz",
+      "integrity": "sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==",
       "dev": true,
       "requires": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.11.0",
-        "@typescript-eslint/types": "5.11.0",
-        "@typescript-eslint/typescript-estree": "5.11.0",
+        "@types/semver": "^7.3.12",
+        "@typescript-eslint/scope-manager": "5.51.0",
+        "@typescript-eslint/types": "5.51.0",
+        "@typescript-eslint/typescript-estree": "5.51.0",
         "eslint-scope": "^5.1.1",
-        "eslint-utils": "^3.0.0"
+        "eslint-utils": "^3.0.0",
+        "semver": "^7.3.7"
       },
       "dependencies": {
-        "@types/json-schema": {
-          "version": "7.0.9",
-          "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-          "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
-          "dev": true
+        "semver": {
+          "version": "7.3.8",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+          "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
         }
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "5.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz",
-      "integrity": "sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA==",
+      "version": "5.51.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz",
+      "integrity": "sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.11.0",
-        "eslint-visitor-keys": "^3.0.0"
+        "@typescript-eslint/types": "5.51.0",
+        "eslint-visitor-keys": "^3.3.0"
       }
     },
     "@webassemblyjs/ast": {
@@ -32058,32 +30938,6 @@
         }
       }
     },
-    "airbnb-prop-types": {
-      "version": "2.15.0",
-      "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz",
-      "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==",
-      "dev": true,
-      "requires": {
-        "array.prototype.find": "^2.1.0",
-        "function.prototype.name": "^1.1.1",
-        "has": "^1.0.3",
-        "is-regex": "^1.0.4",
-        "object-is": "^1.0.1",
-        "object.assign": "^4.1.0",
-        "object.entries": "^1.1.0",
-        "prop-types": "^15.7.2",
-        "prop-types-exact": "^1.2.0",
-        "react-is": "^16.9.0"
-      },
-      "dependencies": {
-        "react-is": {
-          "version": "16.11.0",
-          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
-          "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==",
-          "dev": true
-        }
-      }
-    },
     "ajv": {
       "version": "6.12.6",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -32277,12 +31131,6 @@
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
       "dev": true
     },
-    "array-filter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
-      "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=",
-      "dev": true
-    },
     "array-find-index": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
@@ -32419,27 +31267,6 @@
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
       "dev": true
     },
-    "array.prototype.find": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.0.tgz",
-      "integrity": "sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.13.0"
-      }
-    },
-    "array.prototype.flat": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
-      "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.2",
-        "es-abstract": "^1.10.0",
-        "function-bind": "^1.1.1"
-      }
-    },
     "array.prototype.flatmap": {
       "version": "1.2.5",
       "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz",
@@ -32748,12 +31575,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -33098,12 +31919,6 @@
         "multicast-dns-service-types": "^1.1.0"
       }
     },
-    "boolbase": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
-      "dev": true
-    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -33353,170 +32168,6 @@
       "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
       "dev": true
     },
-    "cheerio": {
-      "version": "1.0.0-rc.10",
-      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
-      "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
-      "dev": true,
-      "requires": {
-        "cheerio-select": "^1.5.0",
-        "dom-serializer": "^1.3.2",
-        "domhandler": "^4.2.0",
-        "htmlparser2": "^6.1.0",
-        "parse5": "^6.0.1",
-        "parse5-htmlparser2-tree-adapter": "^6.0.1",
-        "tslib": "^2.2.0"
-      },
-      "dependencies": {
-        "dom-serializer": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.0.1",
-            "domhandler": "^4.2.0",
-            "entities": "^2.0.0"
-          }
-        },
-        "domelementtype": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-          "dev": true
-        },
-        "domhandler": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-          "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.2.0"
-          }
-        },
-        "domutils": {
-          "version": "2.8.0",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-          "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-          "dev": true,
-          "requires": {
-            "dom-serializer": "^1.0.1",
-            "domelementtype": "^2.2.0",
-            "domhandler": "^4.2.0"
-          }
-        },
-        "entities": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-          "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-          "dev": true
-        },
-        "htmlparser2": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-          "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.0.1",
-            "domhandler": "^4.0.0",
-            "domutils": "^2.5.2",
-            "entities": "^2.0.0"
-          }
-        },
-        "parse5": {
-          "version": "6.0.1",
-          "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-          "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-          "dev": true
-        }
-      }
-    },
-    "cheerio-select": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
-      "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
-      "dev": true,
-      "requires": {
-        "css-select": "^4.1.3",
-        "css-what": "^5.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0",
-        "domutils": "^2.7.0"
-      },
-      "dependencies": {
-        "css-select": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
-          "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
-          "dev": true,
-          "requires": {
-            "boolbase": "^1.0.0",
-            "css-what": "^5.1.0",
-            "domhandler": "^4.3.0",
-            "domutils": "^2.8.0",
-            "nth-check": "^2.0.1"
-          }
-        },
-        "css-what": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-          "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
-          "dev": true
-        },
-        "dom-serializer": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-          "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.0.1",
-            "domhandler": "^4.2.0",
-            "entities": "^2.0.0"
-          }
-        },
-        "domelementtype": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-          "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
-          "dev": true
-        },
-        "domhandler": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-          "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
-          "dev": true,
-          "requires": {
-            "domelementtype": "^2.2.0"
-          }
-        },
-        "domutils": {
-          "version": "2.8.0",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-          "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-          "dev": true,
-          "requires": {
-            "dom-serializer": "^1.0.1",
-            "domelementtype": "^2.2.0",
-            "domhandler": "^4.2.0"
-          }
-        },
-        "entities": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-          "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-          "dev": true
-        },
-        "nth-check": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
-          "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
-          "dev": true,
-          "requires": {
-            "boolbase": "^1.0.0"
-          }
-        }
-      }
-    },
     "chokidar": {
       "version": "2.1.8",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
@@ -34465,12 +33116,6 @@
         "path-type": "^4.0.0"
       }
     },
-    "discontinuous-range": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
-      "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
-      "dev": true
-    },
     "dns-equal": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -34669,14 +33314,13 @@
       }
     },
     "enhanced-resolve": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
-      "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+      "version": "5.12.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
+      "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^4.1.2",
-        "memory-fs": "^0.5.0",
-        "tapable": "^1.0.0"
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
       }
     },
     "enquirer": {
@@ -34706,93 +33350,6 @@
       "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
       "dev": true
     },
-    "enzyme": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.10.0.tgz",
-      "integrity": "sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg==",
-      "dev": true,
-      "requires": {
-        "array.prototype.flat": "^1.2.1",
-        "cheerio": "^1.0.0-rc.2",
-        "function.prototype.name": "^1.1.0",
-        "has": "^1.0.3",
-        "html-element-map": "^1.0.0",
-        "is-boolean-object": "^1.0.0",
-        "is-callable": "^1.1.4",
-        "is-number-object": "^1.0.3",
-        "is-regex": "^1.0.4",
-        "is-string": "^1.0.4",
-        "is-subset": "^0.1.1",
-        "lodash.escape": "^4.0.1",
-        "lodash.isequal": "^4.5.0",
-        "object-inspect": "^1.6.0",
-        "object-is": "^1.0.1",
-        "object.assign": "^4.1.0",
-        "object.entries": "^1.0.4",
-        "object.values": "^1.0.4",
-        "raf": "^3.4.0",
-        "rst-selector-parser": "^2.2.3",
-        "string.prototype.trim": "^1.1.2"
-      }
-    },
-    "enzyme-adapter-react-16": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.1.tgz",
-      "integrity": "sha512-yMPxrP3vjJP+4wL/qqfkT6JAIctcwKF+zXO6utlGPgUJT2l4tzrdjMDWGd/Pp1BjHBcljhN24OzNEGRteibJhA==",
-      "dev": true,
-      "requires": {
-        "enzyme-adapter-utils": "^1.12.1",
-        "enzyme-shallow-equal": "^1.0.0",
-        "has": "^1.0.3",
-        "object.assign": "^4.1.0",
-        "object.values": "^1.1.0",
-        "prop-types": "^15.7.2",
-        "react-is": "^16.10.2",
-        "react-test-renderer": "^16.0.0-0",
-        "semver": "^5.7.0"
-      },
-      "dependencies": {
-        "react-is": {
-          "version": "16.11.0",
-          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
-          "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==",
-          "dev": true
-        }
-      }
-    },
-    "enzyme-adapter-utils": {
-      "version": "1.12.1",
-      "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.1.tgz",
-      "integrity": "sha512-KWiHzSjZaLEoDCOxY8Z1RAbUResbqKN5bZvenPbfKtWorJFVETUw754ebkuCQ3JKm0adx1kF8JaiR+PHPiP47g==",
-      "dev": true,
-      "requires": {
-        "airbnb-prop-types": "^2.15.0",
-        "function.prototype.name": "^1.1.1",
-        "object.assign": "^4.1.0",
-        "object.fromentries": "^2.0.1",
-        "prop-types": "^15.7.2",
-        "semver": "^5.7.0"
-      }
-    },
-    "enzyme-shallow-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz",
-      "integrity": "sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ==",
-      "dev": true,
-      "requires": {
-        "has": "^1.0.3",
-        "object-is": "^1.0.1"
-      }
-    },
-    "enzyme-to-json": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.4.3.tgz",
-      "integrity": "sha512-jqNEZlHqLdz7OTpXSzzghArSS3vigj67IU/fWkPyl1c0TCj9P5s6Ze0kRkYZWNEoCqCR79xlQbigYlMx5erh8A==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.15"
-      }
-    },
     "errno": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
@@ -34810,37 +33367,12 @@
         "is-arrayish": "^0.2.1"
       }
     },
-    "es-abstract": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
-      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
-      "dev": true,
-      "requires": {
-        "es-to-primitive": "^1.2.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "is-callable": "^1.1.4",
-        "is-regex": "^1.0.4",
-        "object-keys": "^1.0.12"
-      }
-    },
     "es-module-lexer": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz",
       "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==",
       "dev": true
     },
-    "es-to-primitive": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
-      "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
-      "dev": true,
-      "requires": {
-        "is-callable": "^1.1.4",
-        "is-date-object": "^1.0.1",
-        "is-symbol": "^1.0.2"
-      }
-    },
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -35063,17 +33595,6 @@
           "dev": true,
           "requires": {
             "is-glob": "^4.0.3"
-          },
-          "dependencies": {
-            "is-glob": {
-              "version": "4.0.3",
-              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-              "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-              "dev": true,
-              "requires": {
-                "is-extglob": "^2.1.1"
-              }
-            }
           }
         },
         "globals": {
@@ -35091,12 +33612,6 @@
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "ignore": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-          "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-          "dev": true
-        },
         "js-yaml": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -35391,15 +33906,6 @@
           "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
           "dev": true
         },
-        "is-glob": {
-          "version": "4.0.3",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-          "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.1"
-          }
-        },
         "is-regex": {
           "version": "1.1.4",
           "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -35764,9 +34270,9 @@
       }
     },
     "eslint-visitor-keys": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz",
-      "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+      "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
       "dev": true
     },
     "espree": {
@@ -36198,17 +34704,16 @@
       "dev": true
     },
     "fast-glob": {
-      "version": "3.2.5",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
-      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+      "version": "3.2.12",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+      "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
       "dev": true,
       "requires": {
         "@nodelib/fs.stat": "^2.0.2",
         "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.0",
+        "glob-parent": "^5.1.2",
         "merge2": "^1.3.0",
-        "micromatch": "^4.0.2",
-        "picomatch": "^2.2.1"
+        "micromatch": "^4.0.4"
       },
       "dependencies": {
         "braces": {
@@ -36583,30 +35088,12 @@
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
-    "function.prototype.name": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.1.tgz",
-      "integrity": "sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1",
-        "functions-have-names": "^1.1.1",
-        "is-callable": "^1.1.4"
-      }
-    },
     "functional-red-black-tree": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
       "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
       "dev": true
     },
-    "functions-have-names": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.1.1.tgz",
-      "integrity": "sha512-U0kNHUoxwPNPWOJaMG7Z00d4a/qZVrFtzWJRaK8V9goaVOCXBSQSJpt3MYGNtkScKEBKovxLjnNdC9MlXwo5Pw==",
-      "dev": true
-    },
     "gauge": {
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -36846,9 +35333,15 @@
       }
     },
     "graceful-fs": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz",
-      "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==",
+      "version": "4.2.10",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+      "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+      "dev": true
+    },
+    "grapheme-splitter": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+      "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
       "dev": true
     },
     "gud": {
@@ -37092,15 +35585,6 @@
         }
       }
     },
-    "html-element-map": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.1.0.tgz",
-      "integrity": "sha512-iqiG3dTZmy+uUaTmHarTL+3/A2VW9ox/9uasKEZC+R/wAtUrTcRlXPSaPqsnWPfIu8wqn09jQNwMRqzL54jSYA==",
-      "dev": true,
-      "requires": {
-        "array-filter": "^1.0.0"
-      }
-    },
     "html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -37296,9 +35780,9 @@
       }
     },
     "ignore": {
-      "version": "5.1.8",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
-      "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
       "dev": true
     },
     "ignore-walk": {
@@ -37501,12 +35985,6 @@
         "binary-extensions": "^1.0.0"
       }
     },
-    "is-boolean-object": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz",
-      "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=",
-      "dev": true
-    },
     "is-buffer": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
@@ -37522,12 +36000,6 @@
         "builtin-modules": "^3.0.0"
       }
     },
-    "is-callable": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
-      "dev": true
-    },
     "is-core-module": {
       "version": "2.10.0",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
@@ -37618,9 +36090,9 @@
       "dev": true
     },
     "is-glob": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
       "dev": true,
       "requires": {
         "is-extglob": "^2.1.1"
@@ -37664,12 +36136,6 @@
         }
       }
     },
-    "is-number-object": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz",
-      "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=",
-      "dev": true
-    },
     "is-path-cwd": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
@@ -37741,18 +36207,6 @@
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
       "dev": true
     },
-    "is-string": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz",
-      "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=",
-      "dev": true
-    },
-    "is-subset": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
-      "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
-      "dev": true
-    },
     "is-symbol": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
@@ -38010,12 +36464,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -38554,12 +37002,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -39176,12 +37618,6 @@
           "dev": true,
           "optional": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -39675,12 +38111,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -39927,12 +38357,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -40148,12 +38572,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -40322,12 +38740,6 @@
           "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -40410,14 +38822,6 @@
       "requires": {
         "@types/node": "*",
         "graceful-fs": "^4.2.9"
-      },
-      "dependencies": {
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        }
       }
     },
     "jest-snapshot": {
@@ -40521,12 +38925,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -40657,12 +39055,6 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "graceful-fs": {
-          "version": "4.2.9",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-          "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-          "dev": true
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -41263,12 +39655,6 @@
       "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
       "dev": true
     },
-    "lodash.flattendeep": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
-      "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
-      "dev": true
-    },
     "lodash.get": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -41517,48 +39903,6 @@
       "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
       "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
     },
-    "memory-fs": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
-      "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
-      "dev": true,
-      "requires": {
-        "errno": "^0.1.3",
-        "readable-stream": "^2.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "2.3.7",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-          "dev": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "dev": true,
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        }
-      }
-    },
     "meow": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -41821,12 +40165,6 @@
         "minimist": "^1.2.5"
       }
     },
-    "moo": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
-      "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
-      "dev": true
-    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -41892,18 +40230,11 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
-    "nearley": {
-      "version": "2.18.0",
-      "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.18.0.tgz",
-      "integrity": "sha512-/zQOMCeJcioI0xJtd5RpBiWw2WP7wLe6vq8/3Yu0rEwgus/G/+pViX80oA87JdVgjRt2895mZSv2VfZmy4W1uw==",
-      "dev": true,
-      "requires": {
-        "commander": "^2.19.0",
-        "moo": "^0.4.3",
-        "railroad-diagrams": "^1.0.0",
-        "randexp": "0.4.6",
-        "semver": "^5.4.1"
-      }
+    "natural-compare-lite": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+      "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+      "dev": true
     },
     "negotiator": {
       "version": "0.6.2",
@@ -41989,12 +40320,6 @@
         "which": "^2.0.2"
       },
       "dependencies": {
-        "graceful-fs": {
-          "version": "4.2.6",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-          "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-          "dev": true
-        },
         "nopt": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -42273,12 +40598,6 @@
         }
       }
     },
-    "object-inspect": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
-      "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
-      "dev": true
-    },
     "object-is": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
@@ -42310,50 +40629,6 @@
         "object-keys": "^1.0.11"
       }
     },
-    "object.entries": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
-      "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.12.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      }
-    },
-    "object.fromentries": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.1.tgz",
-      "integrity": "sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.15.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.16.0",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz",
-          "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.0",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.0",
-            "is-callable": "^1.1.4",
-            "is-regex": "^1.0.4",
-            "object-inspect": "^1.6.0",
-            "object-keys": "^1.1.1",
-            "string.prototype.trimleft": "^2.1.0",
-            "string.prototype.trimright": "^2.1.0"
-          }
-        }
-      }
-    },
     "object.hasown": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz",
@@ -42463,18 +40738,6 @@
         "isobject": "^3.0.1"
       }
     },
-    "object.values": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
-      "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.12.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      }
-    },
     "obuf": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
@@ -42661,23 +40924,6 @@
         "lines-and-columns": "^1.1.6"
       }
     },
-    "parse5-htmlparser2-tree-adapter": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
-      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
-      "dev": true,
-      "requires": {
-        "parse5": "^6.0.1"
-      },
-      "dependencies": {
-        "parse5": {
-          "version": "6.0.1",
-          "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-          "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-          "dev": true
-        }
-      }
-    },
     "parseurl": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -44156,17 +42402,6 @@
         "react-is": "^16.8.1"
       }
     },
-    "prop-types-exact": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz",
-      "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==",
-      "dev": true,
-      "requires": {
-        "has": "^1.0.3",
-        "object.assign": "^4.1.0",
-        "reflect.ownkeys": "^0.2.0"
-      }
-    },
     "proxy-addr": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@@ -44235,31 +42470,6 @@
       "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
       "dev": true
     },
-    "raf": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
-      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
-      "dev": true,
-      "requires": {
-        "performance-now": "^2.1.0"
-      }
-    },
-    "railroad-diagrams": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
-      "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
-      "dev": true
-    },
-    "randexp": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
-      "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
-      "dev": true,
-      "requires": {
-        "discontinuous-range": "1.0.0",
-        "ret": "~0.1.10"
-      }
-    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -44347,17 +42557,6 @@
         "object-assign": "^4.1.1",
         "prop-types": "^15.6.2",
         "scheduler": "^0.19.1"
-      },
-      "dependencies": {
-        "scheduler": {
-          "version": "0.19.1",
-          "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
-          "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
-          "requires": {
-            "loose-envify": "^1.1.0",
-            "object-assign": "^4.1.1"
-          }
-        }
       }
     },
     "react-fast-compare": {
@@ -44415,6 +42614,24 @@
         "tiny-warning": "^1.0.0"
       }
     },
+    "react-shallow-renderer": {
+      "version": "16.15.0",
+      "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
+      "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.1.1",
+        "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
+      },
+      "dependencies": {
+        "react-is": {
+          "version": "18.2.0",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+          "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+          "dev": true
+        }
+      }
+    },
     "react-splitter-layout": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/react-splitter-layout/-/react-splitter-layout-4.0.0.tgz",
@@ -44429,18 +42646,6 @@
         "classnames": "^2.2.5"
       }
     },
-    "react-test-renderer": {
-      "version": "16.11.0",
-      "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.11.0.tgz",
-      "integrity": "sha512-nh9gDl8R4ut+ZNNb2EeKO5VMvTKxwzurbSMuGBoKtjpjbg8JK/u3eVPVNi1h1Ue+eYK9oSzJjb+K3lzLxyA4ag==",
-      "dev": true,
-      "requires": {
-        "object-assign": "^4.1.1",
-        "prop-types": "^15.6.2",
-        "react-is": "^16.8.6",
-        "scheduler": "^0.17.0"
-      }
-    },
     "react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@@ -44646,12 +42851,6 @@
         "strip-indent": "^3.0.0"
       }
     },
-    "reflect.ownkeys": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz",
-      "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=",
-      "dev": true
-    },
     "regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -45104,16 +43303,6 @@
         "glob": "^7.1.3"
       }
     },
-    "rst-selector-parser": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
-      "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
-      "dev": true,
-      "requires": {
-        "lodash.flattendeep": "^4.4.0",
-        "nearley": "^2.7.10"
-      }
-    },
     "run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -45175,10 +43364,9 @@
       }
     },
     "scheduler": {
-      "version": "0.17.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz",
-      "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==",
-      "dev": true,
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
+      "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
       "requires": {
         "loose-envify": "^1.1.0",
         "object-assign": "^4.1.1"
@@ -46199,17 +44387,6 @@
         }
       }
     },
-    "string.prototype.trim": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz",
-      "integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.13.0",
-        "function-bind": "^1.1.1"
-      }
-    },
     "string.prototype.trimend": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
@@ -46220,26 +44397,6 @@
         "define-properties": "^1.1.3"
       }
     },
-    "string.prototype.trimleft": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
-      "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
-      }
-    },
-    "string.prototype.trimright": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
-      "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
-      "dev": true,
-      "requires": {
-        "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
-      }
-    },
     "string.prototype.trimstart": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
@@ -46820,9 +44977,9 @@
       }
     },
     "tapable": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-      "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
       "dev": true
     },
     "tar": {
@@ -47137,14 +45294,13 @@
       }
     },
     "ts-loader": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.1.0.tgz",
-      "integrity": "sha512-YiQipGGAFj2zBfqLhp28yUvPP9jUGqHxRzrGYuc82Z2wM27YIHbElXiaZDc93c3x0mz4zvBmS6q/DgExpdj37A==",
+      "version": "9.4.2",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz",
+      "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==",
       "dev": true,
       "requires": {
         "chalk": "^4.1.0",
-        "enhanced-resolve": "^4.0.0",
-        "loader-utils": "^2.0.0",
+        "enhanced-resolve": "^5.0.0",
         "micromatch": "^4.0.0",
         "semver": "^7.3.4"
       },
@@ -47213,26 +45369,6 @@
           "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
           "dev": true
         },
-        "json5": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
-          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.5"
-          }
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
         "micromatch": {
           "version": "4.0.4",
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@@ -47388,9 +45524,9 @@
       }
     },
     "typescript": {
-      "version": "4.5.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
-      "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+      "version": "4.9.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+      "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
       "dev": true
     },
     "unbox-primitive": {
@@ -47632,6 +45768,12 @@
       "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
       "dev": true
     },
+    "use-sync-external-store": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+      "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+      "requires": {}
+    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -47838,22 +45980,6 @@
         "webpack-sources": "^2.1.1"
       },
       "dependencies": {
-        "enhanced-resolve": {
-          "version": "5.7.0",
-          "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz",
-          "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==",
-          "dev": true,
-          "requires": {
-            "graceful-fs": "^4.2.4",
-            "tapable": "^2.2.0"
-          }
-        },
-        "graceful-fs": {
-          "version": "4.2.6",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-          "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
-          "dev": true
-        },
         "mime-db": {
           "version": "1.47.0",
           "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
@@ -47879,12 +46005,6 @@
             "ajv": "^6.12.5",
             "ajv-keywords": "^3.5.2"
           }
-        },
-        "tapable": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz",
-          "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==",
-          "dev": true
         }
       }
     },
@@ -48610,10 +46730,12 @@
       "dev": true
     },
     "zustand": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
-      "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
-      "requires": {}
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.2.tgz",
+      "integrity": "sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==",
+      "requires": {
+        "use-sync-external-store": "1.2.0"
+      }
     },
     "zwitch": {
       "version": "1.0.5",
diff --git a/web-console/package.json b/web-console/package.json
index b8c33c6fda..9f902c0a60 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -101,10 +101,10 @@
     "react-table": "~6.10.3",
     "regenerator-runtime": "^0.13.7",
     "tslib": "^2.3.1",
-    "zustand": "^3.6.5"
+    "zustand": "^4.3.2"
   },
   "devDependencies": {
-    "@awesome-code-style/eslint-config": "^4.0.0",
+    "@awesome-code-style/eslint-config": "^4.1.0",
     "@awesome-code-style/prettier-config": "^4.0.0",
     "@awesome-code-style/stylelint-config": "^4.0.0",
     "@babel/core": "^7.14.3",
@@ -131,15 +131,13 @@
     "@types/react-splitter-layout": "^3.0.0",
     "@types/react-table": "6.8.5",
     "@types/uuid": "^7.0.2",
-    "@typescript-eslint/eslint-plugin": "^5.11.0",
+    "@typescript-eslint/eslint-plugin": "^5.51.0",
+    "@typescript-eslint/parser": "^5.51.0",
     "autoprefixer": "^10.2.6",
     "babel-loader": "^8.2.2",
     "browserslist": "^4.16.6",
     "codecov": "^3.8.2",
     "css-loader": "^5.2.1",
-    "enzyme": "^3.10.0",
-    "enzyme-adapter-react-16": "^1.15.1",
-    "enzyme-to-json": "^3.4.3",
     "eslint": "^8.8.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-plugin-header": "^3.1.1",
@@ -160,15 +158,16 @@
     "postcss-loader": "^5.3.0",
     "postcss-preset-env": "^6.7.0",
     "prettier": "^2.5.1",
+    "react-shallow-renderer": "^16.15.0",
     "replace": "^1.2.2",
     "sass-loader": "^11.1.0",
     "snarkdown": "^2.0.0",
     "style-loader": "^2.0.0",
     "stylelint": "^13.12.0",
     "ts-jest": "^27.1.3",
-    "ts-loader": "^8.1.0",
+    "ts-loader": "^9.4.2",
     "ts-node": "^10.9.1",
-    "typescript": "^4.5.5",
+    "typescript": "^4.9.5",
     "uuid": "^7.0.2",
     "webpack": "^5.33.2",
     "webpack-bundle-analyzer": "^4.4.1",
diff --git a/web-console/script/mkcomp b/web-console/script/mkcomp
index 1f15960378..418224fc84 100755
--- a/web-console/script/mkcomp
+++ b/web-console/script/mkcomp
@@ -143,9 +143,10 @@ writeFile(
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { ${camelName} } from './${name}';
 
 describe('${camelName}', () => {
@@ -153,7 +154,7 @@ describe('${camelName}', () => {
     const ${snakeName} = shallow(
       <${camelName}/>
     );
-   
+
     expect(${snakeName}).toMatchSnapshot();
   });
 });
diff --git a/web-console/src/bootstrap/react-table-defaults.tsx b/web-console/src/bootstrap/react-table-defaults.tsx
index 89370866b2..42039b36da 100644
--- a/web-console/src/bootstrap/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -17,7 +17,8 @@
  */
 
 import React from 'react';
-import { Filter, ReactTableDefaults } from 'react-table';
+import type { Filter } from 'react-table';
+import { ReactTableDefaults } from 'react-table';
 
 import { Loader } from '../components';
 import {
diff --git a/web-console/src/components/action-cell/action-cell.tsx b/web-console/src/components/action-cell/action-cell.tsx
index 0433eca2b0..f241d2bf6e 100644
--- a/web-console/src/components/action-cell/action-cell.tsx
+++ b/web-console/src/components/action-cell/action-cell.tsx
@@ -21,7 +21,8 @@ import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import React from 'react';
 
-import { BasicAction, basicActionsToMenu } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
+import { basicActionsToMenu } from '../../utils/basic-action';
 import { ActionIcon } from '../action-icon/action-icon';
 
 import './action-cell.scss';
diff --git a/web-console/src/components/action-icon/action-icon.tsx b/web-console/src/components/action-icon/action-icon.tsx
index 6e16883a89..023d898622 100644
--- a/web-console/src/components/action-icon/action-icon.tsx
+++ b/web-console/src/components/action-icon/action-icon.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { Icon, IconName } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Icon } from '@blueprintjs/core';
 import classNames from 'classnames';
 import React from 'react';
 
diff --git a/web-console/src/components/array-input/array-input.tsx b/web-console/src/components/array-input/array-input.tsx
index b5b40c1754..c5a0ee1245 100644
--- a/web-console/src/components/array-input/array-input.tsx
+++ b/web-console/src/components/array-input/array-input.tsx
@@ -16,14 +16,16 @@
  * limitations under the License.
  */
 
-import { Button, Intent, Position, TextArea } from '@blueprintjs/core';
+import type { Intent } from '@blueprintjs/core';
+import { Button, Position, TextArea } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React, { useState } from 'react';
 
 import { compact } from '../../utils';
-import { Suggestion, SuggestionMenu } from '../suggestion-menu/suggestion-menu';
+import type { Suggestion } from '../suggestion-menu/suggestion-menu';
+import { SuggestionMenu } from '../suggestion-menu/suggestion-menu';
 
 import './array-input.scss';
 
diff --git a/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
index 5d2cf24413..f55beba4ba 100644
--- a/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
+++ b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
@@ -5,7 +5,6 @@ exports[`AutoForm matches snapshot 1`] = `
   className="auto-form"
 >
   <Memo(FormGroupWithInfo)
-    key="testNumber"
     label="Test number"
   >
     <Memo(NumericInputWithDefault)
@@ -18,7 +17,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testSizeBytes"
     label="Test size bytes"
   >
     <Blueprint4.NumericInput
@@ -40,7 +38,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testString"
     label="Test string"
   >
     <Memo(SuggestibleInput)
@@ -53,7 +50,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testStringWithDefault"
     label="Test string with default"
   >
     <Memo(SuggestibleInput)
@@ -66,7 +62,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testStringWithMultiline"
     label="Test string with multiline"
   >
     <Memo(SuggestibleInput)
@@ -79,7 +74,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testBoolean"
     label="Test boolean"
   >
     <Blueprint4.ButtonGroup>
@@ -100,7 +94,6 @@ exports[`AutoForm matches snapshot 1`] = `
     </Blueprint4.ButtonGroup>
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testBooleanWithDefault"
     label="Test boolean with default"
   >
     <Blueprint4.ButtonGroup>
@@ -121,7 +114,6 @@ exports[`AutoForm matches snapshot 1`] = `
     </Blueprint4.ButtonGroup>
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testStringArray"
     label="Test string array"
   >
     <Memo(ArrayInput)
@@ -132,7 +124,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testStringArrayWithDefault"
     label="Test string array with default"
   >
     <Memo(ArrayInput)
@@ -148,7 +139,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testJson"
     label="Test json"
   >
     <Memo(JsonInput)
@@ -157,7 +147,6 @@ exports[`AutoForm matches snapshot 1`] = `
     />
   </Memo(FormGroupWithInfo)>
   <Memo(FormGroupWithInfo)
-    key="testStringRequiredAndDefaultValue"
     label="Test string required and default value"
   >
     <Memo(SuggestibleInput)
@@ -170,9 +159,7 @@ exports[`AutoForm matches snapshot 1`] = `
       value=""
     />
   </Memo(FormGroupWithInfo)>
-  <Blueprint4.FormGroup
-    key="more-or-less"
-  >
+  <Blueprint4.FormGroup>
     <Blueprint4.Button
       fill={true}
       minimal={true}
diff --git a/web-console/src/components/auto-form/auto-form.spec.tsx b/web-console/src/components/auto-form/auto-form.spec.tsx
index f345d514bb..3529a5c3de 100644
--- a/web-console/src/components/auto-form/auto-form.spec.tsx
+++ b/web-console/src/components/auto-form/auto-form.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { COMPACTION_CONFIG_FIELDS } from '../../druid-models';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { AutoForm } from './auto-form';
 
diff --git a/web-console/src/components/auto-form/auto-form.tsx b/web-console/src/components/auto-form/auto-form.tsx
index 146de61b62..5c2a229a4f 100644
--- a/web-console/src/components/auto-form/auto-form.tsx
+++ b/web-console/src/components/auto-form/auto-form.tsx
@@ -35,7 +35,7 @@ import { JsonInput } from '../json-input/json-input';
 import { NumericInputWithDefault } from '../numeric-input-with-default/numeric-input-with-default';
 import { PopoverText } from '../popover-text/popover-text';
 import { SuggestibleInput } from '../suggestible-input/suggestible-input';
-import { Suggestion } from '../suggestion-menu/suggestion-menu';
+import type { Suggestion } from '../suggestion-menu/suggestion-menu';
 
 import './auto-form.scss';
 
diff --git a/web-console/src/components/braced-text/braced-text.spec.tsx b/web-console/src/components/braced-text/braced-text.spec.tsx
index 2df4be704f..b98b30b696 100644
--- a/web-console/src/components/braced-text/braced-text.spec.tsx
+++ b/web-console/src/components/braced-text/braced-text.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { BracedText } from './braced-text';
 
 describe('BracedText', () => {
diff --git a/web-console/src/components/cell-filter-menu/cell-filter-menu.tsx b/web-console/src/components/cell-filter-menu/cell-filter-menu.tsx
index 20d200b6f9..181c83e39c 100644
--- a/web-console/src/components/cell-filter-menu/cell-filter-menu.tsx
+++ b/web-console/src/components/cell-filter-menu/cell-filter-menu.tsx
@@ -18,20 +18,12 @@
 
 import { Menu, MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import {
-  C,
-  Column,
-  L,
-  SqlComparison,
-  SqlExpression,
-  SqlLiteral,
-  SqlQuery,
-  SqlRecord,
-  trimString,
-} from 'druid-query-toolkit';
+import type { Column, SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import { C, L, SqlComparison, SqlLiteral, SqlRecord, trimString } from 'druid-query-toolkit';
 import React from 'react';
 
-import { copyAndAlert, prettyPrintSql, QueryAction, stringifyValue } from '../../utils';
+import type { QueryAction } from '../../utils';
+import { copyAndAlert, prettyPrintSql, stringifyValue } from '../../utils';
 
 function sqlLiteralForColumnValue(column: Column, value: unknown): SqlLiteral | undefined {
   if (column.sqlType === 'TIMESTAMP') {
diff --git a/web-console/src/components/center-message/center-message.tsx b/web-console/src/components/center-message/center-message.tsx
index bc622769ae..eeee622b31 100644
--- a/web-console/src/components/center-message/center-message.tsx
+++ b/web-console/src/components/center-message/center-message.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import './center-message.scss';
 
diff --git a/web-console/src/components/date-range-selector/date-range-selector.tsx b/web-console/src/components/date-range-selector/date-range-selector.tsx
index b58daecb30..26da957114 100644
--- a/web-console/src/components/date-range-selector/date-range-selector.tsx
+++ b/web-console/src/components/date-range-selector/date-range-selector.tsx
@@ -17,7 +17,8 @@
  */
 
 import { Button, InputGroup, Popover, Position } from '@blueprintjs/core';
-import { DateRange, DateRangePicker } from '@blueprintjs/datetime';
+import type { DateRange } from '@blueprintjs/datetime';
+import { DateRangePicker } from '@blueprintjs/datetime';
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
diff --git a/web-console/src/components/external-link/external-link.tsx b/web-console/src/components/external-link/external-link.tsx
index f79d7507ef..8ddd5a5630 100644
--- a/web-console/src/components/external-link/external-link.tsx
+++ b/web-console/src/components/external-link/external-link.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 export interface ExternalLinkProps {
   href: string;
diff --git a/web-console/src/components/fancy-tab-pane/fancy-tab-pane.tsx b/web-console/src/components/fancy-tab-pane/fancy-tab-pane.tsx
index 500c0f24dc..19576a2224 100644
--- a/web-console/src/components/fancy-tab-pane/fancy-tab-pane.tsx
+++ b/web-console/src/components/fancy-tab-pane/fancy-tab-pane.tsx
@@ -34,9 +34,11 @@
  * limitations under the License.
  */
 
-import { Button, Icon, IconName, Intent } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Button, Icon, Intent } from '@blueprintjs/core';
 import classNames from 'classnames';
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import { filterMap } from '../../utils';
 
diff --git a/web-console/src/components/form-json-selector/form-json-selector.spec.tsx b/web-console/src/components/form-json-selector/form-json-selector.spec.tsx
index ae7c3a9ee5..2626a17004 100644
--- a/web-console/src/components/form-json-selector/form-json-selector.spec.tsx
+++ b/web-console/src/components/form-json-selector/form-json-selector.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { FormJsonSelector } from './form-json-selector';
 
 describe('FormJsonSelector', () => {
diff --git a/web-console/src/components/formatted-input/formatted-input.tsx b/web-console/src/components/formatted-input/formatted-input.tsx
index aee9ddcea3..a8620e11c5 100644
--- a/web-console/src/components/formatted-input/formatted-input.tsx
+++ b/web-console/src/components/formatted-input/formatted-input.tsx
@@ -16,12 +16,13 @@
  * limitations under the License.
  */
 
-import { InputGroup, InputGroupProps2, Intent, TextArea } from '@blueprintjs/core';
+import type { InputGroupProps2 } from '@blueprintjs/core';
+import { InputGroup, Intent, TextArea } from '@blueprintjs/core';
 import { Tooltip2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React, { useState } from 'react';
 
-import { Formatter } from '../../utils';
+import type { Formatter } from '../../utils';
 
 import './formatted-input.scss';
 
diff --git a/web-console/src/components/header-bar/header-bar.spec.tsx b/web-console/src/components/header-bar/header-bar.spec.tsx
index a185110436..3b68cc9a5e 100644
--- a/web-console/src/components/header-bar/header-bar.spec.tsx
+++ b/web-console/src/components/header-bar/header-bar.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { HeaderBar } from './header-bar';
 
diff --git a/web-console/src/components/highlight-text/highlight-text.spec.tsx b/web-console/src/components/highlight-text/highlight-text.spec.tsx
index ef8931236e..dc969f6b30 100644
--- a/web-console/src/components/highlight-text/highlight-text.spec.tsx
+++ b/web-console/src/components/highlight-text/highlight-text.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { HighlightText } from './highlight-text';
 
 describe('HighlightText', () => {
diff --git a/web-console/src/components/interval-input/interval-input.tsx b/web-console/src/components/interval-input/interval-input.tsx
index ccbe212dcc..7cc4413356 100644
--- a/web-console/src/components/interval-input/interval-input.tsx
+++ b/web-console/src/components/interval-input/interval-input.tsx
@@ -16,8 +16,10 @@
  * limitations under the License.
  */
 
-import { Button, InputGroup, Intent, Position } from '@blueprintjs/core';
-import { DateRange, DateRangePicker, TimePrecision } from '@blueprintjs/datetime';
+import type { Intent } from '@blueprintjs/core';
+import { Button, InputGroup, Position } from '@blueprintjs/core';
+import type { DateRange } from '@blueprintjs/datetime';
+import { DateRangePicker, TimePrecision } from '@blueprintjs/datetime';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import React from 'react';
diff --git a/web-console/src/components/json-collapse/json-collapse.spec.tsx b/web-console/src/components/json-collapse/json-collapse.spec.tsx
index e33783a1c3..1783f9e1b8 100644
--- a/web-console/src/components/json-collapse/json-collapse.spec.tsx
+++ b/web-console/src/components/json-collapse/json-collapse.spec.tsx
@@ -16,10 +16,11 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import * as JSONBig from 'json-bigint-native';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { JsonCollapse } from './json-collapse';
 
 describe('JsonCollapse', () => {
diff --git a/web-console/src/components/json-input/json-input.tsx b/web-console/src/components/json-input/json-input.tsx
index 9539c71877..e3467303e3 100644
--- a/web-console/src/components/json-input/json-input.tsx
+++ b/web-console/src/components/json-input/json-input.tsx
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { Ace } from 'ace-builds';
+import type { Ace } from 'ace-builds';
 import classNames from 'classnames';
 import Hjson from 'hjson';
 import * as JSONBig from 'json-bigint-native';
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/components/menu-checkbox/menu-checkbox.tsx
index 33aa72b7d5..d305249bdb 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/components/menu-checkbox/menu-checkbox.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { MenuItem, MenuItemProps } from '@blueprintjs/core';
+import type { MenuItemProps } from '@blueprintjs/core';
+import { MenuItem } from '@blueprintjs/core';
 import classNames from 'classnames';
 import React from 'react';
 
diff --git a/web-console/src/components/menu-tristate/menu-tristate.tsx b/web-console/src/components/menu-tristate/menu-tristate.tsx
index 7f54d1a319..783cdc7e8e 100644
--- a/web-console/src/components/menu-tristate/menu-tristate.tsx
+++ b/web-console/src/components/menu-tristate/menu-tristate.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { MenuItem, MenuItemProps } from '@blueprintjs/core';
+import type { MenuItemProps } from '@blueprintjs/core';
+import { MenuItem } from '@blueprintjs/core';
 import classNames from 'classnames';
 import React from 'react';
 
diff --git a/web-console/src/components/numeric-input-with-default/numeric-input-with-default.spec.tsx b/web-console/src/components/numeric-input-with-default/numeric-input-with-default.spec.tsx
index b0d2b61d2c..dff5bd0665 100644
--- a/web-console/src/components/numeric-input-with-default/numeric-input-with-default.spec.tsx
+++ b/web-console/src/components/numeric-input-with-default/numeric-input-with-default.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { NumericInputWithDefault } from './numeric-input-with-default';
 
 describe('NumericInputWithDefault', () => {
diff --git a/web-console/src/components/numeric-input-with-default/numeric-input-with-default.tsx b/web-console/src/components/numeric-input-with-default/numeric-input-with-default.tsx
index 7574f1d45c..d995384d56 100644
--- a/web-console/src/components/numeric-input-with-default/numeric-input-with-default.tsx
+++ b/web-console/src/components/numeric-input-with-default/numeric-input-with-default.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { HTMLInputProps, NumericInput, NumericInputProps } from '@blueprintjs/core';
+import type { HTMLInputProps, NumericInputProps } from '@blueprintjs/core';
+import { NumericInput } from '@blueprintjs/core';
 import React, { useState } from 'react';
 
 export type NumericInputWithDefaultProps = HTMLInputProps & NumericInputProps;
diff --git a/web-console/src/components/query-error-pane/query-error-pane.spec.tsx b/web-console/src/components/query-error-pane/query-error-pane.spec.tsx
index b85c2da6cc..4dfc4aa467 100644
--- a/web-console/src/components/query-error-pane/query-error-pane.spec.tsx
+++ b/web-console/src/components/query-error-pane/query-error-pane.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { QueryErrorPane } from './query-error-pane';
 
 describe('QueryErrorPane', () => {
diff --git a/web-console/src/components/query-error-pane/query-error-pane.tsx b/web-console/src/components/query-error-pane/query-error-pane.tsx
index f2e23172dd..3ddb722c34 100644
--- a/web-console/src/components/query-error-pane/query-error-pane.tsx
+++ b/web-console/src/components/query-error-pane/query-error-pane.tsx
@@ -18,7 +18,7 @@
 
 import React, { useState } from 'react';
 
-import { DruidError, RowColumn } from '../../utils';
+import type { DruidError, RowColumn } from '../../utils';
 import { HighlightText } from '../highlight-text/highlight-text';
 
 import './query-error-pane.scss';
diff --git a/web-console/src/components/record-table-pane/record-table-pane.tsx b/web-console/src/components/record-table-pane/record-table-pane.tsx
index e3f26ad18d..b8629eb736 100644
--- a/web-console/src/components/record-table-pane/record-table-pane.tsx
+++ b/web-console/src/components/record-table-pane/record-table-pane.tsx
@@ -20,19 +20,20 @@ import { Button, Icon } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
-import { Column, QueryResult } from 'druid-query-toolkit';
+import type { Column, QueryResult } from 'druid-query-toolkit';
 import React, { useEffect, useState } from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog';
 import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
+import type { Pagination } from '../../utils';
 import {
   columnToIcon,
   columnToWidth,
   filterMap,
   formatNumber,
   getNumericColumnBraces,
-  Pagination,
 } from '../../utils';
 import { BracedText } from '../braced-text/braced-text';
 import { CellFilterMenu } from '../cell-filter-menu/cell-filter-menu';
@@ -149,7 +150,7 @@ export const RecordTablePane = React.memo(function RecordTablePane(props: Record
               },
               headerClassName: getHeaderClassName(h),
               accessor: String(i),
-              Cell(row) {
+              Cell(row: RowRenderProps) {
                 const value = row.value;
                 return (
                   <div>
diff --git a/web-console/src/components/refresh-button/refresh-button.tsx b/web-console/src/components/refresh-button/refresh-button.tsx
index a21fe0b150..d2c38ac506 100644
--- a/web-console/src/components/refresh-button/refresh-button.tsx
+++ b/web-console/src/components/refresh-button/refresh-button.tsx
@@ -19,8 +19,9 @@
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
-import { LocalStorageKeys } from '../../utils';
-import { DelayLabel, TimedButton } from '../timed-button/timed-button';
+import type { LocalStorageKeys } from '../../utils';
+import type { DelayLabel } from '../timed-button/timed-button';
+import { TimedButton } from '../timed-button/timed-button';
 
 const DELAYS: DelayLabel[] = [
   { label: '5 seconds', delay: 5000 },
diff --git a/web-console/src/components/rule-editor/rule-editor.tsx b/web-console/src/components/rule-editor/rule-editor.tsx
index 2556c891f5..7704adfe8b 100644
--- a/web-console/src/components/rule-editor/rule-editor.tsx
+++ b/web-console/src/components/rule-editor/rule-editor.tsx
@@ -31,7 +31,8 @@ import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
 import { durationSanitizer } from '../../utils';
-import { Rule, RuleUtil } from '../../utils/load-rule';
+import type { Rule } from '../../utils/load-rule';
+import { RuleUtil } from '../../utils/load-rule';
 import { SuggestibleInput } from '../suggestible-input/suggestible-input';
 
 import './rule-editor.scss';
diff --git a/web-console/src/components/segment-timeline/bar-group.tsx b/web-console/src/components/segment-timeline/bar-group.tsx
index 442df4ba73..6c335d5c28 100644
--- a/web-console/src/components/segment-timeline/bar-group.tsx
+++ b/web-console/src/components/segment-timeline/bar-group.tsx
@@ -16,11 +16,11 @@
  * limitations under the License.
  */
 
-import { AxisScale } from 'd3-axis';
+import type { AxisScale } from 'd3-axis';
 import React from 'react';
 
 import { BarUnit } from './bar-unit';
-import { BarUnitData, HoveredBarInfo } from './stacked-bar-chart';
+import type { BarUnitData, HoveredBarInfo } from './stacked-bar-chart';
 
 interface BarGroupProps {
   dataToRender: BarUnitData[];
diff --git a/web-console/src/components/segment-timeline/segment-timeline.tsx b/web-console/src/components/segment-timeline/segment-timeline.tsx
index 006b84e660..27fb9b9bfd 100644
--- a/web-console/src/components/segment-timeline/segment-timeline.tsx
+++ b/web-console/src/components/segment-timeline/segment-timeline.tsx
@@ -16,19 +16,13 @@
  * limitations under the License.
  */
 
-import {
-  FormGroup,
-  HTMLSelect,
-  IResizeEntry,
-  Radio,
-  RadioGroup,
-  ResizeSensor,
-} from '@blueprintjs/core';
-import { AxisScale } from 'd3-axis';
+import type { IResizeEntry } from '@blueprintjs/core';
+import { FormGroup, HTMLSelect, Radio, RadioGroup, ResizeSensor } from '@blueprintjs/core';
+import type { AxisScale } from 'd3-axis';
 import { scaleLinear, scaleUtc } from 'd3-scale';
 import React from 'react';
 
-import { Capabilities } from '../../helpers';
+import type { Capabilities } from '../../helpers';
 import { Api } from '../../singletons';
 import {
   ceilToUtcDay,
@@ -41,7 +35,8 @@ import {
 import { DateRangeSelector } from '../date-range-selector/date-range-selector';
 import { Loader } from '../loader/loader';
 
-import { BarUnitData, StackedBarChart } from './stacked-bar-chart';
+import type { BarUnitData } from './stacked-bar-chart';
+import { StackedBarChart } from './stacked-bar-chart';
 
 import './segment-timeline.scss';
 
diff --git a/web-console/src/components/segment-timeline/stacked-bar-chart.tsx b/web-console/src/components/segment-timeline/stacked-bar-chart.tsx
index 8bac38b5c8..4a0d1f4a5a 100644
--- a/web-console/src/components/segment-timeline/stacked-bar-chart.tsx
+++ b/web-console/src/components/segment-timeline/stacked-bar-chart.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { axisBottom, axisLeft, AxisScale } from 'd3-axis';
+import type { AxisScale } from 'd3-axis';
+import { axisBottom, axisLeft } from 'd3-axis';
 import React, { useState } from 'react';
 
 import { BarGroup } from './bar-group';
diff --git a/web-console/src/components/show-history/show-history.tsx b/web-console/src/components/show-history/show-history.tsx
index 303b373734..72ae421d33 100644
--- a/web-console/src/components/show-history/show-history.tsx
+++ b/web-console/src/components/show-history/show-history.tsx
@@ -21,7 +21,8 @@ import * as JSONBig from 'json-bigint-native';
 import React, { useState } from 'react';
 
 import { DiffDialog } from '../../dialogs';
-import { cleanSpec, IngestionSpec } from '../../druid-models';
+import type { IngestionSpec } from '../../druid-models';
+import { cleanSpec } from '../../druid-models';
 import { useQueryManager } from '../../hooks';
 import { Api } from '../../singletons';
 import { deepSet } from '../../utils';
diff --git a/web-console/src/components/suggestible-input/suggestible-input.tsx b/web-console/src/components/suggestible-input/suggestible-input.tsx
index 10c7d91186..3eac810730 100644
--- a/web-console/src/components/suggestible-input/suggestible-input.tsx
+++ b/web-console/src/components/suggestible-input/suggestible-input.tsx
@@ -23,8 +23,10 @@ import classNames from 'classnames';
 import React, { useRef } from 'react';
 
 import { JSON_STRING_FORMATTER } from '../../utils';
-import { FormattedInput, FormattedInputProps } from '../formatted-input/formatted-input';
-import { Suggestion, SuggestionMenu } from '../suggestion-menu/suggestion-menu';
+import type { FormattedInputProps } from '../formatted-input/formatted-input';
+import { FormattedInput } from '../formatted-input/formatted-input';
+import type { Suggestion } from '../suggestion-menu/suggestion-menu';
+import { SuggestionMenu } from '../suggestion-menu/suggestion-menu';
 
 export interface SuggestibleInputProps extends Omit<FormattedInputProps, 'formatter'> {
   onFinalize?: () => void;
diff --git a/web-console/src/components/table-clickable-cell/table-clickable-cell.tsx b/web-console/src/components/table-clickable-cell/table-clickable-cell.tsx
index 7e4c66fdd5..fa3d56982a 100644
--- a/web-console/src/components/table-clickable-cell/table-clickable-cell.tsx
+++ b/web-console/src/components/table-clickable-cell/table-clickable-cell.tsx
@@ -16,9 +16,11 @@
  * limitations under the License.
  */
 
-import { Icon, IconName } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Icon } from '@blueprintjs/core';
 import classNames from 'classnames';
-import React, { MouseEventHandler, ReactNode } from 'react';
+import type { MouseEventHandler, ReactNode } from 'react';
+import React from 'react';
 
 import './table-clickable-cell.scss';
 
diff --git a/web-console/src/components/table-filterable-cell/table-filterable-cell.tsx b/web-console/src/components/table-filterable-cell/table-filterable-cell.tsx
index 14f568013f..f29cc42a49 100644
--- a/web-console/src/components/table-filterable-cell/table-filterable-cell.tsx
+++ b/web-console/src/components/table-filterable-cell/table-filterable-cell.tsx
@@ -18,10 +18,12 @@
 
 import { Menu, MenuDivider, MenuItem } from '@blueprintjs/core';
 import { Popover2 } from '@blueprintjs/popover2';
-import React, { ReactNode } from 'react';
-import { Filter } from 'react-table';
+import type { ReactNode } from 'react';
+import React from 'react';
+import type { Filter } from 'react-table';
 
-import { addFilter, FilterMode, filterModeToIcon } from '../../react-table';
+import type { FilterMode } from '../../react-table';
+import { addFilter, filterModeToIcon } from '../../react-table';
 import { Deferred } from '../deferred/deferred';
 
 import './table-filterable-cell.scss';
diff --git a/web-console/src/components/timed-button/timed-button.spec.tsx b/web-console/src/components/timed-button/timed-button.spec.tsx
index 32b07c5e6e..644f0938b1 100644
--- a/web-console/src/components/timed-button/timed-button.spec.tsx
+++ b/web-console/src/components/timed-button/timed-button.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { TimedButton } from './timed-button';
 
 describe('TimedButton', () => {
diff --git a/web-console/src/components/timed-button/timed-button.tsx b/web-console/src/components/timed-button/timed-button.tsx
index 49ac9063db..0b339a8d0e 100644
--- a/web-console/src/components/timed-button/timed-button.tsx
+++ b/web-console/src/components/timed-button/timed-button.tsx
@@ -16,14 +16,16 @@
  * limitations under the License.
  */
 
-import { Button, ButtonGroup, ButtonProps, Menu, MenuDivider, MenuItem } from '@blueprintjs/core';
+import type { ButtonProps } from '@blueprintjs/core';
+import { Button, ButtonGroup, Menu, MenuDivider, MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React, { useState } from 'react';
 
 import { useInterval } from '../../hooks';
-import { isInBackground, localStorageGet, LocalStorageKeys, localStorageSet } from '../../utils';
+import type { LocalStorageKeys } from '../../utils';
+import { isInBackground, localStorageGet, localStorageSet } from '../../utils';
 
 export interface DelayLabel {
   label: string;
diff --git a/web-console/src/components/view-control-bar/view-control-bar.tsx b/web-console/src/components/view-control-bar/view-control-bar.tsx
index 435ecf8f5c..c83867f27c 100644
--- a/web-console/src/components/view-control-bar/view-control-bar.tsx
+++ b/web-console/src/components/view-control-bar/view-control-bar.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import './view-control-bar.scss';
 
diff --git a/web-console/src/components/warning-checklist/warning-checklist.tsx b/web-console/src/components/warning-checklist/warning-checklist.tsx
index 5c74cbdb08..351203fe72 100644
--- a/web-console/src/components/warning-checklist/warning-checklist.tsx
+++ b/web-console/src/components/warning-checklist/warning-checklist.tsx
@@ -17,7 +17,8 @@
  */
 
 import { Switch } from '@blueprintjs/core';
-import React, { ReactNode, useState } from 'react';
+import type { ReactNode } from 'react';
+import React, { useState } from 'react';
 
 export interface WarningChecklistProps {
   checks: ReactNode[];
diff --git a/web-console/src/console-application.tsx b/web-console/src/console-application.tsx
index 24947636d6..1ddd3676b4 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -20,11 +20,13 @@ import { HotkeysProvider, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
 import React from 'react';
-import { Redirect, RouteComponentProps } from 'react-router';
+import type { RouteComponentProps } from 'react-router';
+import { Redirect } from 'react-router';
 import { HashRouter, Route, Switch } from 'react-router-dom';
 
-import { HeaderActiveTab, HeaderBar, Loader } from './components';
-import { DruidEngine, QueryWithContext } from './druid-models';
+import type { HeaderActiveTab } from './components';
+import { HeaderBar, Loader } from './components';
+import type { DruidEngine, QueryWithContext } from './druid-models';
 import { Capabilities } from './helpers';
 import { AppToaster } from './singletons';
 import { localStorageGetJson, LocalStorageKeys, QueryManager } from './utils';
diff --git a/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx b/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
index 0d8cf385a5..e36ae51127 100644
--- a/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
+++ b/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
@@ -16,19 +16,12 @@
  * limitations under the License.
  */
 
-import {
-  Button,
-  Classes,
-  Dialog,
-  FormGroup,
-  Icon,
-  IconName,
-  Intent,
-  ProgressBar,
-} from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Button, Classes, Dialog, FormGroup, Icon, Intent, ProgressBar } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
-import React, { ReactNode, useState } from 'react';
+import type { ReactNode } from 'react';
+import React, { useState } from 'react';
 
 import { WarningChecklist } from '../../components';
 import { AppToaster } from '../../singletons';
@@ -132,7 +125,7 @@ export const AsyncActionDialog = React.memo(function AsyncActionDialog(
             <Button
               intent={intent}
               text={confirmButtonText}
-              onClick={handleConfirm}
+              onClick={() => void handleConfirm()}
               disabled={confirmButtonDisabled || needsMoreChecks}
             />
             <Button text={cancelButtonText || 'Cancel'} onClick={onClose} />
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx b/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
index 975a32b5f6..20b4b01470 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { CompactionDialog } from './compaction-dialog';
 
 describe('CompactionDialog', () => {
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
index 3b5456e7d0..f11132860c 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
@@ -19,10 +19,11 @@
 import { Button, Callout, Classes, Code, Dialog, Intent } from '@blueprintjs/core';
 import React, { useState } from 'react';
 
-import { AutoForm, FormJsonSelector, FormJsonTabs, JsonInput } from '../../components';
+import type { FormJsonTabs } from '../../components';
+import { AutoForm, FormJsonSelector, JsonInput } from '../../components';
+import type { CompactionConfig } from '../../druid-models';
 import {
   COMPACTION_CONFIG_FIELDS,
-  CompactionConfig,
   compactionConfigHasLegacyInputSegmentSizeBytesSet,
 } from '../../druid-models';
 import { deepDelete, formatBytesCompact } from '../../utils';
@@ -31,7 +32,7 @@ import './compaction-dialog.scss';
 
 export interface CompactionDialogProps {
   onClose: () => void;
-  onSave: (compactionConfig: CompactionConfig) => void;
+  onSave: (compactionConfig: CompactionConfig) => void | Promise<void>;
   onDelete: () => void;
   datasource: string;
   compactionConfig: CompactionConfig | undefined;
@@ -105,7 +106,7 @@ export const CompactionDialog = React.memo(function CompactionDialog(props: Comp
             text="Submit"
             intent={Intent.PRIMARY}
             disabled={disableSubmit}
-            onClick={() => onSave(currentConfig)}
+            onClick={() => void onSave(currentConfig)}
           />
         </div>
       </div>
diff --git a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.spec.tsx b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.spec.tsx
index 54d940da6d..8ec332a595 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.spec.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { CoordinatorDynamicConfigDialog } from './coordinator-dynamic-config-dialog';
 
 describe('CoordinatorDynamicConfigDialog', () => {
diff --git a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
index 7fa8925220..118f53aef5 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
@@ -20,15 +20,10 @@ import { Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import {
-  AutoForm,
-  ExternalLink,
-  FormJsonSelector,
-  FormJsonTabs,
-  JsonInput,
-  Loader,
-} from '../../components';
-import { COORDINATOR_DYNAMIC_CONFIG_FIELDS, CoordinatorDynamicConfig } from '../../druid-models';
+import type { FormJsonTabs } from '../../components';
+import { AutoForm, ExternalLink, FormJsonSelector, JsonInput, Loader } from '../../components';
+import type { CoordinatorDynamicConfig } from '../../druid-models';
+import { COORDINATOR_DYNAMIC_CONFIG_FIELDS } from '../../druid-models';
 import { useQueryManager } from '../../hooks';
 import { getLink } from '../../links';
 import { Api, AppToaster } from '../../singletons';
@@ -102,7 +97,7 @@ export const CoordinatorDynamicConfigDialog = React.memo(function CoordinatorDyn
     <SnitchDialog
       className="coordinator-dynamic-config-dialog"
       saveDisabled={Boolean(jsonError)}
-      onSave={saveConfig}
+      onSave={comment => void saveConfig(comment)}
       onClose={onClose}
       title="Coordinator dynamic config"
       historyRecords={historyRecordsState.data}
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.spec.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.spec.tsx
index 795b274d59..1820ce0007 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.spec.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.spec.tsx
@@ -16,12 +16,13 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { QueryState } from '../../../utils';
+import { shallow } from '../../../utils/shallow-renderer';
 
-import { DatasourceColumnsTable, DatasourceColumnsTableRow } from './datasource-columns-table';
+import type { DatasourceColumnsTableRow } from './datasource-columns-table';
+import { DatasourceColumnsTable } from './datasource-columns-table';
 
 let columnsState: QueryState<DatasourceColumnsTableRow[]> = QueryState.INIT;
 jest.mock('../../../hooks', () => {
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.tsx
index 242ca19378..e9b4f7a6ae 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-columns-table/datasource-columns-table.tsx
@@ -23,7 +23,8 @@ import ReactTable from 'react-table';
 import { Loader } from '../../../components';
 import { useQueryManager } from '../../../hooks';
 import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../../react-table';
-import { ColumnMetadata, queryDruidSql } from '../../../utils';
+import type { ColumnMetadata } from '../../../utils';
+import { queryDruidSql } from '../../../utils';
 
 import './datasource-columns-table.scss';
 
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-preview-pane/datasource-preview-pane.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-preview-pane/datasource-preview-pane.tsx
index 8f3d664e93..c48cbfa519 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-preview-pane/datasource-preview-pane.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-preview-pane/datasource-preview-pane.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { QueryResult, QueryRunner, T } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
+import { QueryRunner, T } from 'druid-query-toolkit';
 import React from 'react';
 
 import { Loader, RecordTablePane } from '../../../components';
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
index ae1698514b..b18d0dafe6 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
@@ -19,8 +19,9 @@
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import { BasicAction } from '../../utils/basic-action';
-import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
+import type { BasicAction } from '../../utils/basic-action';
+import type { SideButtonMetaData } from '../table-action-dialog/table-action-dialog';
+import { TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
 import { DatasourceColumnsTable } from './datasource-columns-table/datasource-columns-table';
 import { DatasourcePreviewPane } from './datasource-preview-pane/datasource-preview-pane';
diff --git a/web-console/src/dialogs/diff-dialog/diff-dialog.tsx b/web-console/src/dialogs/diff-dialog/diff-dialog.tsx
index 702c62b671..bb42f1db84 100644
--- a/web-console/src/dialogs/diff-dialog/diff-dialog.tsx
+++ b/web-console/src/dialogs/diff-dialog/diff-dialog.tsx
@@ -19,7 +19,8 @@
 import { Button, Classes, Dialog, HTMLSelect } from '@blueprintjs/core';
 import * as JSONBig from 'json-bigint-native';
 import React, { useState } from 'react';
-import ReactDiffViewer, { ReactDiffViewerStylesOverride } from 'react-diff-viewer';
+import type { ReactDiffViewerStylesOverride } from 'react-diff-viewer';
+import ReactDiffViewer from 'react-diff-viewer';
 
 import './diff-dialog.scss';
 
diff --git a/web-console/src/dialogs/doctor-dialog/doctor-dialog.tsx b/web-console/src/dialogs/doctor-dialog/doctor-dialog.tsx
index 3b26297638..47070bb7bd 100644
--- a/web-console/src/dialogs/doctor-dialog/doctor-dialog.tsx
+++ b/web-console/src/dialogs/doctor-dialog/doctor-dialog.tsx
@@ -168,7 +168,7 @@ export class DoctorDialog extends React.PureComponent<DoctorDialogProps, DoctorD
             text="Analyze Druid cluster"
             intent={Intent.PRIMARY}
             fill
-            onClick={() => this.doChecks()}
+            onClick={() => void this.doChecks()}
           />
         </div>
       );
diff --git a/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.tsx b/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.tsx
index 5eb85d5608..3632606508 100644
--- a/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.tsx
+++ b/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.tsx
@@ -21,7 +21,7 @@ import Hjson from 'hjson';
 import * as JSONBig from 'json-bigint-native';
 import React, { useState } from 'react';
 
-import { QueryContext } from '../../druid-models';
+import type { QueryContext } from '../../druid-models';
 
 import './edit-context-dialog.scss';
 
diff --git a/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.spec.tsx b/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.spec.tsx
index 68f7f56b88..2e1234b0a4 100644
--- a/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.spec.tsx
+++ b/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { IndexSpecDialog } from './index-spec-dialog';
 
 describe('IndexSpecDialog', () => {
diff --git a/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.tsx b/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.tsx
index 4c870df45a..daa9e06069 100644
--- a/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.tsx
+++ b/web-console/src/dialogs/index-spec-dialog/index-spec-dialog.tsx
@@ -19,8 +19,10 @@
 import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
 import React, { useState } from 'react';
 
-import { AutoForm, FormJsonSelector, FormJsonTabs, JsonInput } from '../../components';
-import { INDEX_SPEC_FIELDS, IndexSpec } from '../../druid-models';
+import type { FormJsonTabs } from '../../components';
+import { AutoForm, FormJsonSelector, JsonInput } from '../../components';
+import type { IndexSpec } from '../../druid-models';
+import { INDEX_SPEC_FIELDS } from '../../druid-models';
 
 import './index-spec-dialog.scss';
 
diff --git a/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
index ea356d5370..e0c415d7bf 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
@@ -31,13 +31,11 @@ exports[`LookupEditDialog matches snapshot 1`] = `
         value="test"
       >
         <option
-          key="__default"
           value="__default"
         >
           __default
         </option>
         <option
-          key="alt-tier"
           value="alt-tier"
         >
           alt-tier
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
index 882a454502..763a04b030 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { LookupEditDialog } from './lookup-edit-dialog';
 
 describe('LookupEditDialog', () => {
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
index fb70c6c72a..0903ede6f9 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
@@ -27,8 +27,10 @@ import {
 } from '@blueprintjs/core';
 import React, { useState } from 'react';
 
-import { AutoForm, FormJsonSelector, FormJsonTabs, JsonInput } from '../../components';
-import { isLookupInvalid, LOOKUP_FIELDS, LookupSpec } from '../../druid-models';
+import type { FormJsonTabs } from '../../components';
+import { AutoForm, FormJsonSelector, JsonInput } from '../../components';
+import type { LookupSpec } from '../../druid-models';
+import { isLookupInvalid, LOOKUP_FIELDS } from '../../druid-models';
 
 import './lookup-edit-dialog.scss';
 
diff --git a/web-console/src/dialogs/lookup-table-action-dialog/lookup-table-action-dialog.tsx b/web-console/src/dialogs/lookup-table-action-dialog/lookup-table-action-dialog.tsx
index e896d31f7f..9b655bac64 100644
--- a/web-console/src/dialogs/lookup-table-action-dialog/lookup-table-action-dialog.tsx
+++ b/web-console/src/dialogs/lookup-table-action-dialog/lookup-table-action-dialog.tsx
@@ -18,8 +18,9 @@
 
 import React, { useState } from 'react';
 
-import { BasicAction } from '../../utils/basic-action';
-import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
+import type { BasicAction } from '../../utils/basic-action';
+import type { SideButtonMetaData } from '../table-action-dialog/table-action-dialog';
+import { TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
 import { LookupValuesTable } from './lookup-values-table/lookup-values-table';
 
diff --git a/web-console/src/dialogs/overlord-dynamic-config-dialog/overload-dynamic-config-dialog.spec.tsx b/web-console/src/dialogs/overlord-dynamic-config-dialog/overload-dynamic-config-dialog.spec.tsx
index 3011872bec..87c94ebb6e 100644
--- a/web-console/src/dialogs/overlord-dynamic-config-dialog/overload-dynamic-config-dialog.spec.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config-dialog/overload-dynamic-config-dialog.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { OverlordDynamicConfigDialog } from './overlord-dynamic-config-dialog';
 
 describe('OverlordDynamicConfigDialog', () => {
diff --git a/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx b/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
index 76b2808450..65b32d3b43 100644
--- a/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
@@ -21,7 +21,8 @@ import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
 import { AutoForm, ExternalLink, Loader } from '../../components';
-import { OVERLORD_DYNAMIC_CONFIG_FIELDS, OverlordDynamicConfig } from '../../druid-models';
+import type { OverlordDynamicConfig } from '../../druid-models';
+import { OVERLORD_DYNAMIC_CONFIG_FIELDS } from '../../druid-models';
 import { useQueryManager } from '../../hooks';
 import { getLink } from '../../links';
 import { Api, AppToaster } from '../../singletons';
diff --git a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
index a09816955e..723bf23b9b 100644
--- a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
@@ -25,7 +25,8 @@ import { useQueryManager } from '../../hooks';
 import { getLink } from '../../links';
 import { Api } from '../../singletons';
 import { swapElements } from '../../utils';
-import { Rule, RuleUtil } from '../../utils/load-rule';
+import type { Rule } from '../../utils/load-rule';
+import { RuleUtil } from '../../utils/load-rule';
 import { SnitchDialog } from '..';
 
 import './retention-dialog.scss';
@@ -37,7 +38,7 @@ export interface RetentionDialogProps {
   tiers: string[];
   onEditDefaults: () => void;
   onCancel: () => void;
-  onSave: (datasource: string, newRules: Rule[], comment: string) => void;
+  onSave: (datasource: string, newRules: Rule[], comment: string) => void | Promise<void>;
 }
 
 export const RetentionDialog = React.memo(function RetentionDialog(props: RetentionDialogProps) {
@@ -58,7 +59,7 @@ export const RetentionDialog = React.memo(function RetentionDialog(props: Retent
 
   function saveHandler(comment: string) {
     const { datasource, onSave } = props;
-    onSave(datasource, currentRules, comment);
+    void onSave(datasource, currentRules, comment);
   }
 
   function addRule() {
diff --git a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
index cd031f3881..ac64decd5d 100644
--- a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
+++ b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
@@ -21,8 +21,9 @@ import React, { useState } from 'react';
 
 import { ShowJson } from '../../components';
 import { Api } from '../../singletons';
-import { BasicAction } from '../../utils/basic-action';
-import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
+import type { BasicAction } from '../../utils/basic-action';
+import type { SideButtonMetaData } from '../table-action-dialog/table-action-dialog';
+import { TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
 import { SegmentsPreviewPane } from './segments-preview-pane/segments-preview-pane';
 
diff --git a/web-console/src/dialogs/segments-table-action-dialog/segments-preview-pane/segments-preview-pane.tsx b/web-console/src/dialogs/segments-table-action-dialog/segments-preview-pane/segments-preview-pane.tsx
index 6c5ace1c5f..2925482d99 100644
--- a/web-console/src/dialogs/segments-table-action-dialog/segments-preview-pane/segments-preview-pane.tsx
+++ b/web-console/src/dialogs/segments-table-action-dialog/segments-preview-pane/segments-preview-pane.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { QueryResult, QueryRunner } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
+import { QueryRunner } from 'druid-query-toolkit';
 import React from 'react';
 
 import { Loader, RecordTablePane } from '../../../components';
diff --git a/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx b/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
index 2d2e4756ad..3eb8e89d55 100644
--- a/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
+++ b/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
@@ -28,7 +28,7 @@ import './snitch-dialog.scss';
 export interface SnitchDialogProps {
   title: string;
   className?: string;
-  onSave: (comment: string) => void;
+  onSave: (comment: string) => void | Promise<void>;
   saveDisabled?: boolean;
   onReset?: () => void;
   onClose: () => void;
@@ -56,7 +56,7 @@ export class SnitchDialog extends React.PureComponent<SnitchDialogProps, SnitchD
     const { onSave, onClose } = this.props;
     const { comment } = this.state;
 
-    onSave(comment);
+    void onSave(comment);
     if (onClose) onClose();
   };
 
diff --git a/web-console/src/dialogs/spec-dialog/spec-dialog.tsx b/web-console/src/dialogs/spec-dialog/spec-dialog.tsx
index 31e44d2ef2..c4bc5a3fa9 100644
--- a/web-console/src/dialogs/spec-dialog/spec-dialog.tsx
+++ b/web-console/src/dialogs/spec-dialog/spec-dialog.tsx
@@ -26,7 +26,7 @@ import { validJson } from '../../utils';
 import './spec-dialog.scss';
 
 export interface SpecDialogProps {
-  onSubmit: (spec: JSON) => void;
+  onSubmit: (spec: JSON) => void | Promise<void>;
   onClose: () => void;
   title: string;
   initSpec?: any;
@@ -40,7 +40,7 @@ export const SpecDialog = React.memo(function SpecDialog(props: SpecDialogProps)
 
   function postSpec(): void {
     if (!validJson(spec)) return;
-    onSubmit(JSON.parse(spec));
+    void onSubmit(JSON.parse(spec));
     onClose();
   }
 
diff --git a/web-console/src/dialogs/status-dialog/status-dialog.tsx b/web-console/src/dialogs/status-dialog/status-dialog.tsx
index c7da95e424..e59af0d9f1 100644
--- a/web-console/src/dialogs/status-dialog/status-dialog.tsx
+++ b/web-console/src/dialogs/status-dialog/status-dialog.tsx
@@ -18,7 +18,8 @@
 
 import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
 import React, { useState } from 'react';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import { Loader, TableFilterableCell } from '../../components';
 import { useQueryManager } from '../../hooks';
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.spec.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.spec.tsx
index ac71cd5a2c..3ea907dc0c 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.spec.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.spec.tsx
@@ -16,15 +16,15 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { QueryState } from '../../../utils';
+import { shallow } from '../../../utils/shallow-renderer';
 
+import type { SupervisorStatisticsTableRow } from './supervisor-statistics-table';
 import {
   normalizeSupervisorStatisticsResults,
   SupervisorStatisticsTable,
-  SupervisorStatisticsTableRow,
 } from './supervisor-statistics-table';
 
 let supervisorStatisticsState: QueryState<SupervisorStatisticsTableRow[]> = QueryState.INIT;
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.tsx
index 48c2f3f88a..09749f8525 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-statistics-table/supervisor-statistics-table.tsx
@@ -18,7 +18,8 @@
 
 import { Button, ButtonGroup } from '@blueprintjs/core';
 import React from 'react';
-import ReactTable, { CellInfo, Column } from 'react-table';
+import type { CellInfo, Column } from 'react-table';
+import ReactTable from 'react-table';
 
 import { Loader } from '../../../components/loader/loader';
 import { useQueryManager } from '../../../hooks';
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
index fba476fdce..2262859664 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
@@ -23,8 +23,9 @@ import { ShowHistory } from '../../components/show-history/show-history';
 import { cleanSpec } from '../../druid-models';
 import { Api } from '../../singletons';
 import { deepGet } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
-import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
+import type { BasicAction } from '../../utils/basic-action';
+import type { SideButtonMetaData } from '../table-action-dialog/table-action-dialog';
+import { TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
 import { SupervisorStatisticsTable } from './supervisor-statistics-table/supervisor-statistics-table';
 
diff --git a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
index d66b747afb..500bbb0f3a 100644
--- a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
+++ b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
@@ -16,12 +16,15 @@
  * limitations under the License.
  */
 
-import { Button, Classes, Dialog, Icon, IconName, Intent } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Button, Classes, Dialog, Icon, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
-import { BasicAction, basicActionsToMenu } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
+import { basicActionsToMenu } from '../../utils/basic-action';
 
 import './table-action-dialog.scss';
 
diff --git a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
index 40b84a3793..a0a5dbbf13 100644
--- a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
+++ b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
@@ -21,8 +21,9 @@ import React, { useState } from 'react';
 import { ShowJson, ShowLog } from '../../components';
 import { Api } from '../../singletons';
 import { deepGet } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
-import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
+import type { BasicAction } from '../../utils/basic-action';
+import type { SideButtonMetaData } from '../table-action-dialog/table-action-dialog';
+import { TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
 interface TaskTableActionDialogProps {
   taskId: string;
diff --git a/web-console/src/druid-models/compaction-config/compaction-config.tsx b/web-console/src/druid-models/compaction-config/compaction-config.tsx
index b03b66ea0e..f3c151e5ca 100644
--- a/web-console/src/druid-models/compaction-config/compaction-config.tsx
+++ b/web-console/src/druid-models/compaction-config/compaction-config.tsx
@@ -19,7 +19,7 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { Field } from '../../components';
+import type { Field } from '../../components';
 import { deepGet, deepSet, oneOf } from '../../utils';
 
 export interface CompactionConfig {
diff --git a/web-console/src/druid-models/compaction-status/compaction-status.spec.ts b/web-console/src/druid-models/compaction-status/compaction-status.spec.ts
index abe660e5c2..84b1c5f501 100644
--- a/web-console/src/druid-models/compaction-status/compaction-status.spec.ts
+++ b/web-console/src/druid-models/compaction-status/compaction-status.spec.ts
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { CompactionConfig } from '../compaction-config/compaction-config';
+import type { CompactionConfig } from '../compaction-config/compaction-config';
 
-import { CompactionStatus, formatCompactionInfo, zeroCompactionStatus } from './compaction-status';
+import type { CompactionStatus } from './compaction-status';
+import { formatCompactionInfo, zeroCompactionStatus } from './compaction-status';
 
 describe('compaction status', () => {
   const BASIC_CONFIG: CompactionConfig = {
diff --git a/web-console/src/druid-models/compaction-status/compaction-status.ts b/web-console/src/druid-models/compaction-status/compaction-status.ts
index c19cb26b6c..494918182d 100644
--- a/web-console/src/druid-models/compaction-status/compaction-status.ts
+++ b/web-console/src/druid-models/compaction-status/compaction-status.ts
@@ -17,10 +17,8 @@
  */
 
 import { formatBytesCompact, pluralIfNeeded } from '../../utils';
-import {
-  CompactionConfig,
-  compactionConfigHasLegacyInputSegmentSizeBytesSet,
-} from '../compaction-config/compaction-config';
+import type { CompactionConfig } from '../compaction-config/compaction-config';
+import { compactionConfigHasLegacyInputSegmentSizeBytesSet } from '../compaction-config/compaction-config';
 
 function capitalizeFirst(str: string): string {
   return str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
diff --git a/web-console/src/druid-models/coordinator-dynamic-config/coordinator-dynamic-config.tsx b/web-console/src/druid-models/coordinator-dynamic-config/coordinator-dynamic-config.tsx
index ca957309ff..1d1ad2c30b 100644
--- a/web-console/src/druid-models/coordinator-dynamic-config/coordinator-dynamic-config.tsx
+++ b/web-console/src/druid-models/coordinator-dynamic-config/coordinator-dynamic-config.tsx
@@ -19,7 +19,7 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { Field } from '../../components';
+import type { Field } from '../../components';
 
 export interface CoordinatorDynamicConfig {
   maxSegmentsToMove?: number;
diff --git a/web-console/src/druid-models/dimension-spec/dimension-spec.ts b/web-console/src/druid-models/dimension-spec/dimension-spec.ts
index 04144d545d..d679dc91d3 100644
--- a/web-console/src/druid-models/dimension-spec/dimension-spec.ts
+++ b/web-console/src/druid-models/dimension-spec/dimension-spec.ts
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import { Field } from '../../components';
+import type { Field } from '../../components';
 import { filterMap, typeIs } from '../../utils';
-import { SampleHeaderAndRows } from '../../utils/sampler';
+import type { SampleHeaderAndRows } from '../../utils/sampler';
 import { guessColumnTypeFromHeaderAndRows } from '../ingestion-spec/ingestion-spec';
 
 export interface DimensionsSpec {
diff --git a/web-console/src/druid-models/execution/execution.ts b/web-console/src/druid-models/execution/execution.ts
index 32c8e62056..9388d49283 100644
--- a/web-console/src/druid-models/execution/execution.ts
+++ b/web-console/src/druid-models/execution/execution.ts
@@ -26,8 +26,9 @@ import {
   oneOf,
   pluralIfNeeded,
 } from '../../utils';
-import { DruidEngine, validDruidEngine } from '../druid-engine/druid-engine';
-import { QueryContext } from '../query-context/query-context';
+import type { DruidEngine } from '../druid-engine/druid-engine';
+import { validDruidEngine } from '../druid-engine/druid-engine';
+import type { QueryContext } from '../query-context/query-context';
 import { Stages } from '../stages/stages';
 
 const IGNORE_CONTEXT_KEYS = [
diff --git a/web-console/src/druid-models/external-config/external-config.ts b/web-console/src/druid-models/external-config/external-config.ts
index 900551741c..012c7eef47 100644
--- a/web-console/src/druid-models/external-config/external-config.ts
+++ b/web-console/src/druid-models/external-config/external-config.ts
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import type { SqlQuery } from 'druid-query-toolkit';
 import {
   C,
   F,
@@ -24,14 +25,13 @@ import {
   SqlExpression,
   SqlFunction,
   SqlLiteral,
-  SqlQuery,
   SqlStar,
 } from 'druid-query-toolkit';
 import * as JSONBig from 'json-bigint-native';
 
 import { nonEmptyArray } from '../../utils';
-import { InputFormat } from '../input-format/input-format';
-import { InputSource } from '../input-source/input-source';
+import type { InputFormat } from '../input-format/input-format';
+import type { InputSource } from '../input-source/input-source';
 
 export const MULTI_STAGE_QUERY_MAX_COLUMNS = 2000;
 const MAX_LINES = 10;
diff --git a/web-console/src/druid-models/filter/filter.tsx b/web-console/src/druid-models/filter/filter.tsx
index 35b09a68c4..e577687ec2 100644
--- a/web-console/src/druid-models/filter/filter.tsx
+++ b/web-console/src/druid-models/filter/filter.tsx
@@ -18,10 +18,11 @@
 
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { deepGet, EMPTY_ARRAY, oneOf, typeIs } from '../../utils';
-import { IngestionSpec } from '../ingestion-spec/ingestion-spec';
+import type { IngestionSpec } from '../ingestion-spec/ingestion-spec';
 
 export interface DruidFilter {
   readonly type: string;
diff --git a/web-console/src/druid-models/flatten-spec/flatten-spec.tsx b/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
index 5cf1d7c06c..878f77331d 100644
--- a/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
+++ b/web-console/src/druid-models/flatten-spec/flatten-spec.tsx
@@ -18,7 +18,8 @@
 
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { typeIs } from '../../utils';
 
diff --git a/web-console/src/druid-models/index-spec/index-spec.tsx b/web-console/src/druid-models/index-spec/index-spec.tsx
index 1a42462996..b725948ad4 100644
--- a/web-console/src/druid-models/index-spec/index-spec.tsx
+++ b/web-console/src/druid-models/index-spec/index-spec.tsx
@@ -19,7 +19,7 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { Field } from '../../components';
+import type { Field } from '../../components';
 import { deepGet } from '../../utils';
 
 export interface IndexSpec {
diff --git a/web-console/src/druid-models/ingest-query-pattern/ingest-query-pattern.ts b/web-console/src/druid-models/ingest-query-pattern/ingest-query-pattern.ts
index 7bdcaae50a..9cb7d06725 100644
--- a/web-console/src/druid-models/ingest-query-pattern/ingest-query-pattern.ts
+++ b/web-console/src/druid-models/ingest-query-pattern/ingest-query-pattern.ts
@@ -28,8 +28,8 @@ import {
 } from 'druid-query-toolkit';
 
 import { filterMap, oneOf } from '../../utils';
+import type { ExternalConfig } from '../external-config/external-config';
 import {
-  ExternalConfig,
   externalConfigToInitDimensions,
   externalConfigToTableExpression,
   fitExternalConfigPattern,
diff --git a/web-console/src/druid-models/ingestion-spec/ingestion-spec.spec.ts b/web-console/src/druid-models/ingestion-spec/ingestion-spec.spec.ts
index 3f4be422c7..91bf75f35b 100644
--- a/web-console/src/druid-models/ingestion-spec/ingestion-spec.spec.ts
+++ b/web-console/src/druid-models/ingestion-spec/ingestion-spec.spec.ts
@@ -18,13 +18,13 @@
 
 import { CSV_SAMPLE } from '../../utils/sampler.mock';
 
+import type { IngestionSpec } from './ingestion-spec';
 import {
   adjustId,
   cleanSpec,
   guessColumnTypeFromHeaderAndRows,
   guessColumnTypeFromInput,
   guessInputFormat,
-  IngestionSpec,
   updateSchemaWithSample,
   upgradeSpec,
 } from './ingestion-spec';
diff --git a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
index b2bd24219b..9f3eb072b3 100644
--- a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
+++ b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
@@ -20,7 +20,8 @@ import { Code } from '@blueprintjs/core';
 import { range } from 'd3-array';
 import React from 'react';
 
-import { AutoForm, ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { AutoForm, ExternalLink } from '../../components';
 import { IndexSpecDialog } from '../../dialogs/index-spec-dialog/index-spec-dialog';
 import { getLink } from '../../links';
 import {
@@ -38,28 +39,27 @@ import {
   parseCsvLine,
   typeIs,
 } from '../../utils';
-import { SampleHeaderAndRows } from '../../utils/sampler';
+import type { SampleHeaderAndRows } from '../../utils/sampler';
+import type { DimensionsSpec } from '../dimension-spec/dimension-spec';
 import {
-  DimensionsSpec,
   getDimensionSpecName,
   getDimensionSpecs,
   getDimensionSpecType,
 } from '../dimension-spec/dimension-spec';
-import { IndexSpec, summarizeIndexSpec } from '../index-spec/index-spec';
-import { InputFormat, issueWithInputFormat } from '../input-format/input-format';
-import {
-  FILTER_SUGGESTIONS,
-  InputSource,
-  issueWithInputSource,
-} from '../input-source/input-source';
+import type { IndexSpec } from '../index-spec/index-spec';
+import { summarizeIndexSpec } from '../index-spec/index-spec';
+import type { InputFormat } from '../input-format/input-format';
+import { issueWithInputFormat } from '../input-format/input-format';
+import type { InputSource } from '../input-source/input-source';
+import { FILTER_SUGGESTIONS, issueWithInputSource } from '../input-source/input-source';
+import type { MetricSpec } from '../metric-spec/metric-spec';
 import {
   getMetricSpecOutputType,
   getMetricSpecs,
   getMetricSpecSingleFieldName,
-  MetricSpec,
 } from '../metric-spec/metric-spec';
-import { TimestampSpec } from '../timestamp-spec/timestamp-spec';
-import { TransformSpec } from '../transform-spec/transform-spec';
+import type { TimestampSpec } from '../timestamp-spec/timestamp-spec';
+import type { TransformSpec } from '../transform-spec/transform-spec';
 
 export const MAX_INLINE_DATA_LENGTH = 65536;
 
diff --git a/web-console/src/druid-models/input-format/input-format.tsx b/web-console/src/druid-models/input-format/input-format.tsx
index 417b3c3fd8..679f3bafb0 100644
--- a/web-console/src/druid-models/input-format/input-format.tsx
+++ b/web-console/src/druid-models/input-format/input-format.tsx
@@ -19,10 +19,11 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { AutoForm, ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { AutoForm, ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { compact, oneOf, typeIs } from '../../utils';
-import { FlattenSpec } from '../flatten-spec/flatten-spec';
+import type { FlattenSpec } from '../flatten-spec/flatten-spec';
 
 export interface InputFormat {
   readonly type: string;
diff --git a/web-console/src/druid-models/input-source/input-source.tsx b/web-console/src/druid-models/input-source/input-source.tsx
index 7f5ba63793..344510300a 100644
--- a/web-console/src/druid-models/input-source/input-source.tsx
+++ b/web-console/src/druid-models/input-source/input-source.tsx
@@ -18,7 +18,8 @@
 
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { deepGet, deepSet, nonEmptyArray, typeIs } from '../../utils';
 
diff --git a/web-console/src/druid-models/lookup-spec/lookup-spec.tsx b/web-console/src/druid-models/lookup-spec/lookup-spec.tsx
index 3e96494953..fb8ddb9c06 100644
--- a/web-console/src/druid-models/lookup-spec/lookup-spec.tsx
+++ b/web-console/src/druid-models/lookup-spec/lookup-spec.tsx
@@ -19,7 +19,8 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { AutoForm, Field } from '../../components';
+import type { Field } from '../../components';
+import { AutoForm } from '../../components';
 import { deepGet, deepSet, oneOf, pluralIfNeeded, typeIs } from '../../utils';
 
 export interface ExtractionNamespaceSpec {
diff --git a/web-console/src/druid-models/metric-spec/metric-spec.tsx b/web-console/src/druid-models/metric-spec/metric-spec.tsx
index 4295310486..3eb0a24d78 100644
--- a/web-console/src/druid-models/metric-spec/metric-spec.tsx
+++ b/web-console/src/druid-models/metric-spec/metric-spec.tsx
@@ -19,10 +19,11 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { filterMap, typeIs } from '../../utils';
-import { SampleHeaderAndRows } from '../../utils/sampler';
+import type { SampleHeaderAndRows } from '../../utils/sampler';
 import { guessColumnTypeFromHeaderAndRows } from '../ingestion-spec/ingestion-spec';
 
 export interface MetricSpec {
diff --git a/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx b/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
index 2b090acd9d..52132528fb 100644
--- a/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
+++ b/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { Field } from '../../components';
+import type { Field } from '../../components';
 
 export interface OverlordDynamicConfig {
   selectStrategy?: Record<string, any>;
diff --git a/web-console/src/druid-models/stages/stages.ts b/web-console/src/druid-models/stages/stages.ts
index 0304a93c91..7b3f719dbe 100644
--- a/web-console/src/druid-models/stages/stages.ts
+++ b/web-console/src/druid-models/stages/stages.ts
@@ -20,8 +20,8 @@ import { max, sum } from 'd3-array';
 import hasOwnProp from 'has-own-prop';
 
 import { deleteKeys, filterMap, oneOf, zeroDivide } from '../../utils';
-import { InputFormat } from '../input-format/input-format';
-import { InputSource } from '../input-source/input-source';
+import type { InputFormat } from '../input-format/input-format';
+import type { InputSource } from '../input-source/input-source';
 
 const SORT_WEIGHT = 0.5;
 const READING_INPUT_WITH_SORT_WEIGHT = 1 - SORT_WEIGHT;
diff --git a/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx b/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
index cc2a8eae44..fb133e58b4 100644
--- a/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
+++ b/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
@@ -18,16 +18,17 @@
 
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { deepGet, EMPTY_ARRAY, EMPTY_OBJECT } from '../../utils';
-import { IngestionSpec } from '../ingestion-spec/ingestion-spec';
+import type { IngestionSpec } from '../ingestion-spec/ingestion-spec';
 import {
   BASIC_TIME_FORMATS,
   DATE_ONLY_TIME_FORMATS,
   DATETIME_TIME_FORMATS,
   OTHER_TIME_FORMATS,
 } from '../time/time';
-import { Transform } from '../transform-spec/transform-spec';
+import type { Transform } from '../transform-spec/transform-spec';
 
 const NO_SUCH_COLUMN = '!!!_no_such_column_!!!';
 
diff --git a/web-console/src/druid-models/transform-spec/transform-spec.tsx b/web-console/src/druid-models/transform-spec/transform-spec.tsx
index 9b6f8952e6..ffb90d2226 100644
--- a/web-console/src/druid-models/transform-spec/transform-spec.tsx
+++ b/web-console/src/druid-models/transform-spec/transform-spec.tsx
@@ -19,7 +19,8 @@
 import { Code } from '@blueprintjs/core';
 import React from 'react';
 
-import { ExternalLink, Field } from '../../components';
+import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
 import { getLink } from '../../links';
 import { TIME_COLUMN } from '../timestamp-spec/timestamp-spec';
 
diff --git a/web-console/src/druid-models/workbench-query/workbench-query-part.ts b/web-console/src/druid-models/workbench-query/workbench-query-part.ts
index 8c5d2c9446..83a39a04c5 100644
--- a/web-console/src/druid-models/workbench-query/workbench-query-part.ts
+++ b/web-console/src/druid-models/workbench-query/workbench-query-part.ts
@@ -16,12 +16,15 @@
  * limitations under the License.
  */
 
-import { SqlExpression, SqlQuery, SqlValues, SqlWithQuery, T } from 'druid-query-toolkit';
+import type { SqlValues, SqlWithQuery } from 'druid-query-toolkit';
+import { SqlExpression, SqlQuery, T } from 'druid-query-toolkit';
 import Hjson from 'hjson';
 import * as JSONBig from 'json-bigint-native';
 
-import { ColumnMetadata, compact, filterMap, generate8HexId, sqlTypeFromDruid } from '../../utils';
-import { LastExecution, validateLastExecution } from '../execution/execution';
+import type { ColumnMetadata } from '../../utils';
+import { compact, filterMap, generate8HexId, sqlTypeFromDruid } from '../../utils';
+import type { LastExecution } from '../execution/execution';
+import { validateLastExecution } from '../execution/execution';
 import { fitExternalConfigPattern } from '../external-config/external-config';
 
 // -----------------------------
diff --git a/web-console/src/druid-models/workbench-query/workbench-query.ts b/web-console/src/druid-models/workbench-query/workbench-query.ts
index 32ef417c59..63e0aa0314 100644
--- a/web-console/src/druid-models/workbench-query/workbench-query.ts
+++ b/web-console/src/druid-models/workbench-query/workbench-query.ts
@@ -16,31 +16,35 @@
  * limitations under the License.
  */
 
+import type {
+  SqlClusteredByClause,
+  SqlExpression,
+  SqlPartitionedByClause,
+  SqlQuery,
+} from 'druid-query-toolkit';
 import {
   C,
   F,
-  SqlClusteredByClause,
-  SqlExpression,
   SqlLiteral,
   SqlOrderByClause,
   SqlOrderByExpression,
-  SqlPartitionedByClause,
-  SqlQuery,
   SqlTable,
 } from 'druid-query-toolkit';
 import Hjson from 'hjson';
 import * as JSONBig from 'json-bigint-native';
 import { v4 as uuidv4 } from 'uuid';
 
-import { ColumnMetadata, deleteKeys, generate8HexId } from '../../utils';
-import { DruidEngine, validDruidEngine } from '../druid-engine/druid-engine';
-import { LastExecution } from '../execution/execution';
-import { ExternalConfig } from '../external-config/external-config';
+import type { ColumnMetadata } from '../../utils';
+import { deleteKeys, generate8HexId } from '../../utils';
+import type { DruidEngine } from '../druid-engine/druid-engine';
+import { validDruidEngine } from '../druid-engine/druid-engine';
+import type { LastExecution } from '../execution/execution';
+import type { ExternalConfig } from '../external-config/external-config';
 import {
   externalConfigToIngestQueryPattern,
   ingestQueryPatternToQuery,
 } from '../ingest-query-pattern/ingest-query-pattern';
-import { QueryContext } from '../query-context/query-context';
+import type { QueryContext } from '../query-context/query-context';
 
 import { WorkbenchQueryPart } from './workbench-query-part';
 
diff --git a/web-console/src/entry.ts b/web-console/src/entry.ts
index 39e695d435..da267c172c 100644
--- a/web-console/src/entry.ts
+++ b/web-console/src/entry.ts
@@ -27,7 +27,8 @@ import ReactDOM from 'react-dom';
 import { bootstrapJsonParse } from './bootstrap/json-parser';
 import { bootstrapReactTable } from './bootstrap/react-table-defaults';
 import { ConsoleApplication } from './console-application';
-import { Links, setLinkOverrides } from './links';
+import type { Links } from './links';
+import { setLinkOverrides } from './links';
 import { Api, UrlBaser } from './singletons';
 import { setLocalStorageNamespace } from './utils';
 
@@ -84,7 +85,7 @@ if (consoleConfig.customHeaderName && consoleConfig.customHeaderValue) {
   apiConfig.headers![consoleConfig.customHeaderName] = consoleConfig.customHeaderValue;
 }
 if (consoleConfig.customHeaders) {
-  Object.assign(apiConfig.headers, consoleConfig.customHeaders);
+  Object.assign(apiConfig.headers!, consoleConfig.customHeaders);
 }
 
 Api.initialize(apiConfig);
diff --git a/web-console/src/helpers/capacity.ts b/web-console/src/helpers/capacity.ts
index 8a6a0fffa4..62fe306645 100644
--- a/web-console/src/helpers/capacity.ts
+++ b/web-console/src/helpers/capacity.ts
@@ -18,7 +18,7 @@
 
 import { sum } from 'd3-array';
 
-import { CapacityInfo } from '../druid-models';
+import type { CapacityInfo } from '../druid-models';
 import { Api } from '../singletons';
 
 export async function getClusterCapacity(): Promise<CapacityInfo> {
diff --git a/web-console/src/helpers/execution/general.ts b/web-console/src/helpers/execution/general.ts
index adf015883e..bbb2eead6f 100644
--- a/web-console/src/helpers/execution/general.ts
+++ b/web-console/src/helpers/execution/general.ts
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { CancelToken } from 'axios';
-import { QueryResult } from 'druid-query-toolkit';
+import type { CancelToken } from 'axios';
+import type { QueryResult } from 'druid-query-toolkit';
 
-import { Execution } from '../../druid-models';
+import type { Execution } from '../../druid-models';
 import { IntermediateQueryState } from '../../utils';
 
 import {
diff --git a/web-console/src/helpers/execution/sql-task-execution.ts b/web-console/src/helpers/execution/sql-task-execution.ts
index 358eee25c5..af5e40f315 100644
--- a/web-console/src/helpers/execution/sql-task-execution.ts
+++ b/web-console/src/helpers/execution/sql-task-execution.ts
@@ -16,10 +16,11 @@
  * limitations under the License.
  */
 
-import { AxiosResponse, CancelToken } from 'axios';
+import type { AxiosResponse, CancelToken } from 'axios';
 import { L } from 'druid-query-toolkit';
 
-import { Execution, QueryContext } from '../../druid-models';
+import type { QueryContext } from '../../druid-models';
+import { Execution } from '../../druid-models';
 import { Api } from '../../singletons';
 import {
   deepGet,
diff --git a/web-console/src/helpers/spec-conversion.ts b/web-console/src/helpers/spec-conversion.ts
index 9b76e787dd..c610866e29 100644
--- a/web-console/src/helpers/spec-conversion.ts
+++ b/web-console/src/helpers/spec-conversion.ts
@@ -19,16 +19,15 @@
 import { C, L, RefName, SqlExpression, T } from 'druid-query-toolkit';
 import * as JSONBig from 'json-bigint-native';
 
-import {
+import type {
   DimensionSpec,
-  inflateDimensionSpec,
   IngestionSpec,
   MetricSpec,
   QueryWithContext,
   TimestampSpec,
   Transform,
-  upgradeSpec,
 } from '../druid-models';
+import { inflateDimensionSpec, upgradeSpec } from '../druid-models';
 import { deepGet, filterMap, oneOf } from '../utils';
 
 export function getSpecDatasourceName(spec: IngestionSpec): string {
diff --git a/web-console/src/hooks/use-local-storage-state.ts b/web-console/src/hooks/use-local-storage-state.ts
index b9f40855ab..e3b408802b 100644
--- a/web-console/src/hooks/use-local-storage-state.ts
+++ b/web-console/src/hooks/use-local-storage-state.ts
@@ -16,9 +16,11 @@
  * limitations under the License.
  */
 
-import { Dispatch, SetStateAction, useState } from 'react';
+import type { Dispatch, SetStateAction } from 'react';
+import { useState } from 'react';
 
-import { localStorageGetJson, LocalStorageKeys, localStorageSetJson } from '../utils';
+import type { LocalStorageKeys } from '../utils';
+import { localStorageGetJson, localStorageSetJson } from '../utils';
 
 export function useLocalStorageState<T>(
   key: LocalStorageKeys,
diff --git a/web-console/src/hooks/use-query-manager.ts b/web-console/src/hooks/use-query-manager.ts
index 3704b18841..a21d7b6469 100644
--- a/web-console/src/hooks/use-query-manager.ts
+++ b/web-console/src/hooks/use-query-manager.ts
@@ -18,7 +18,8 @@
 
 import { useEffect, useState } from 'react';
 
-import { QueryManager, QueryManagerOptions, QueryState } from '../utils';
+import type { QueryManagerOptions } from '../utils';
+import { QueryManager, QueryState } from '../utils';
 
 import { usePermanentCallback } from './use-permanent-callback';
 
diff --git a/web-console/src/react-table/react-table-inputs.tsx b/web-console/src/react-table/react-table-inputs.tsx
index 7dbb69b18f..59587ce8cc 100644
--- a/web-console/src/react-table/react-table-inputs.tsx
+++ b/web-console/src/react-table/react-table-inputs.tsx
@@ -21,7 +21,7 @@ import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React, { useState } from 'react';
-import { Column, ReactTableFunction } from 'react-table';
+import type { Column, ReactTableFunction } from 'react-table';
 
 import {
   combineModeAndNeedle,
diff --git a/web-console/src/react-table/react-table-utils.ts b/web-console/src/react-table/react-table-utils.ts
index a87a733046..d83fb0cd5e 100644
--- a/web-console/src/react-table/react-table-utils.ts
+++ b/web-console/src/react-table/react-table-utils.ts
@@ -16,10 +16,11 @@
  * limitations under the License.
  */
 
-import { IconName } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { C, F, SqlExpression } from 'druid-query-toolkit';
-import { Filter } from 'react-table';
+import type { SqlExpression } from 'druid-query-toolkit';
+import { C, F } from 'druid-query-toolkit';
+import type { Filter } from 'react-table';
 
 import { addOrUpdate, caseInsensitiveContains } from '../utils';
 
diff --git a/web-console/src/setup-tests.ts b/web-console/src/setup-tests.ts
index fc8763dd31..e75cb3bffb 100644
--- a/web-console/src/setup-tests.ts
+++ b/web-console/src/setup-tests.ts
@@ -18,11 +18,6 @@
 
 import 'core-js/stable';
 
-import { configure } from 'enzyme';
-import enzymeAdapterReact16 from 'enzyme-adapter-react-16';
-
 import { UrlBaser } from './singletons';
 
-configure({ adapter: new (enzymeAdapterReact16 as any)() });
-
 UrlBaser.baseUrl = '/some/base_url';
diff --git a/web-console/src/singletons/ace-editor-state-cache.ts b/web-console/src/singletons/ace-editor-state-cache.ts
index 667afbde84..0a81173a19 100644
--- a/web-console/src/singletons/ace-editor-state-cache.ts
+++ b/web-console/src/singletons/ace-editor-state-cache.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { Ace } from 'ace-builds';
+import type { Ace } from 'ace-builds';
 
 interface EditorState {
   undoManager: Ace.UndoManager;
diff --git a/web-console/src/singletons/api.ts b/web-console/src/singletons/api.ts
index b7340ec073..6b49ac95a3 100644
--- a/web-console/src/singletons/api.ts
+++ b/web-console/src/singletons/api.ts
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
+import type { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
+import axios from 'axios';
 import * as JSONBig from 'json-bigint-native';
 
 import { nonEmptyString } from '../utils';
diff --git a/web-console/src/singletons/execution-state-cache.ts b/web-console/src/singletons/execution-state-cache.ts
index 0011a53e5a..233ed23f7b 100644
--- a/web-console/src/singletons/execution-state-cache.ts
+++ b/web-console/src/singletons/execution-state-cache.ts
@@ -16,8 +16,8 @@
  * limitations under the License.
  */
 
-import { Execution } from '../druid-models';
-import { DruidError, QueryState } from '../utils';
+import type { Execution } from '../druid-models';
+import type { DruidError, QueryState } from '../utils';
 
 export class ExecutionStateCache {
   private static readonly cache: Record<string, QueryState<Execution, DruidError, Execution>> = {};
diff --git a/web-console/src/singletons/workbench-running-promises.ts b/web-console/src/singletons/workbench-running-promises.ts
index 46592907de..b5d99ae5d8 100644
--- a/web-console/src/singletons/workbench-running-promises.ts
+++ b/web-console/src/singletons/workbench-running-promises.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { QueryResult } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
 
 export interface WorkbenchRunningPromise {
   promise: Promise<QueryResult>;
diff --git a/web-console/src/utils/basic-action.tsx b/web-console/src/utils/basic-action.tsx
index 2d0e4f8089..75461cc745 100644
--- a/web-console/src/utils/basic-action.tsx
+++ b/web-console/src/utils/basic-action.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { IconName, Intent, Menu, MenuItem } from '@blueprintjs/core';
+import type { IconName, Intent } from '@blueprintjs/core';
+import { Menu, MenuItem } from '@blueprintjs/core';
 import React from 'react';
 
 export interface BasicAction {
diff --git a/web-console/src/utils/date.ts b/web-console/src/utils/date.ts
index be548f7d65..3b4ec6fc7e 100644
--- a/web-console/src/utils/date.ts
+++ b/web-console/src/utils/date.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { DateRange } from '@blueprintjs/datetime';
+import type { DateRange } from '@blueprintjs/datetime';
 
 const CURRENT_YEAR = new Date().getUTCFullYear();
 
diff --git a/web-console/src/utils/download.ts b/web-console/src/utils/download.ts
index ad5dbd2750..95ca198066 100644
--- a/web-console/src/utils/download.ts
+++ b/web-console/src/utils/download.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { QueryResult } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
 import FileSaver from 'file-saver';
 import * as JSONBig from 'json-bigint-native';
 
diff --git a/web-console/src/utils/druid-query.ts b/web-console/src/utils/druid-query.ts
index 668d4703cf..e558931a3c 100644
--- a/web-console/src/utils/druid-query.ts
+++ b/web-console/src/utils/druid-query.ts
@@ -16,13 +16,14 @@
  * limitations under the License.
  */
 
-import axios, { AxiosResponse } from 'axios';
+import type { AxiosResponse } from 'axios';
+import axios from 'axios';
 import { C } from 'druid-query-toolkit';
 
 import { Api } from '../singletons';
 
 import { assemble } from './general';
-import { RowColumn } from './query-cursor';
+import type { RowColumn } from './query-cursor';
 
 const CANCELED_MESSAGE = 'Query canceled by user.';
 
diff --git a/web-console/src/utils/general.tsx b/web-console/src/utils/general.tsx
index 6e4ddcf6a1..65d912b634 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -17,7 +17,8 @@
  */
 
 import { Intent } from '@blueprintjs/core';
-import { IconName, IconNames } from '@blueprintjs/icons';
+import type { IconName } from '@blueprintjs/icons';
+import { IconNames } from '@blueprintjs/icons';
 import copy from 'copy-to-clipboard';
 import hasOwnProp from 'has-own-prop';
 import * as JSONBig from 'json-bigint-native';
@@ -30,7 +31,7 @@ import { AppToaster } from '../singletons';
 export const EMPTY_OBJECT: any = {};
 export const EMPTY_ARRAY: any[] = [];
 
-export type NumberLike = number | BigInt;
+export type NumberLike = number | bigint;
 
 export function isNumberLikeNaN(x: NumberLike): boolean {
   return isNaN(Number(x));
diff --git a/web-console/src/utils/local-storage-backed-visibility.tsx b/web-console/src/utils/local-storage-backed-visibility.tsx
index 61b2d0381e..df4dc10e70 100644
--- a/web-console/src/utils/local-storage-backed-visibility.tsx
+++ b/web-console/src/utils/local-storage-backed-visibility.tsx
@@ -18,7 +18,8 @@
 
 import hasOwnProp from 'has-own-prop';
 
-import { localStorageGetJson, LocalStorageKeys, localStorageSetJson } from './local-storage-keys';
+import type { LocalStorageKeys } from './local-storage-keys';
+import { localStorageGetJson, localStorageSetJson } from './local-storage-keys';
 
 type Visibility = Record<string, boolean>;
 
diff --git a/web-console/src/utils/query-action.ts b/web-console/src/utils/query-action.ts
index 40ba46e088..3f17f22b67 100644
--- a/web-console/src/utils/query-action.ts
+++ b/web-console/src/utils/query-action.ts
@@ -16,6 +16,6 @@
  * limitations under the License.
  */
 
-import { SqlQuery } from 'druid-query-toolkit';
+import type { SqlQuery } from 'druid-query-toolkit';
 
 export type QueryAction = (query: SqlQuery) => SqlQuery;
diff --git a/web-console/src/utils/query-cursor.ts b/web-console/src/utils/query-cursor.ts
index a881b515c4..909b0dea50 100644
--- a/web-console/src/utils/query-cursor.ts
+++ b/web-console/src/utils/query-cursor.ts
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { L, SqlBase, SqlQuery } from 'druid-query-toolkit';
+import type { SqlBase, SqlQuery } from 'druid-query-toolkit';
+import { L } from 'druid-query-toolkit';
 
 export const EMPTY_LITERAL = L('');
 
diff --git a/web-console/src/utils/query-manager.tsx b/web-console/src/utils/query-manager.tsx
index 71fc0a49a5..2cc9188eba 100644
--- a/web-console/src/utils/query-manager.tsx
+++ b/web-console/src/utils/query-manager.tsx
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import axios, { Canceler, CancelToken } from 'axios';
+import type { Canceler, CancelToken } from 'axios';
+import axios from 'axios';
 import debounce from 'lodash.debounce';
 
 import { wait } from './general';
@@ -71,8 +72,8 @@ export class QueryManager<Q, R, I = never, E extends Error = Error> {
   private state: QueryState<R, E, I>;
   private currentQueryId = 0;
 
-  private readonly runWhenIdle: () => void;
-  private readonly runWhenLoading: () => void;
+  private readonly runWhenIdle: () => void | Promise<void>;
+  private readonly runWhenLoading: () => void | Promise<void>;
 
   constructor(options: QueryManagerOptions<Q, R, I, E>) {
     this.processQuery = options.processQuery;
@@ -197,7 +198,7 @@ export class QueryManager<Q, R, I = never, E extends Error = Error> {
   private trigger() {
     if (this.currentRunCancelFn) {
       // Currently loading
-      this.runWhenLoading();
+      void this.runWhenLoading();
     } else {
       this.setState(
         new QueryState<R, E>({
@@ -206,7 +207,7 @@ export class QueryManager<Q, R, I = never, E extends Error = Error> {
         }),
       );
 
-      this.runWhenIdle();
+      void this.runWhenIdle();
     }
   }
 
@@ -220,7 +221,7 @@ export class QueryManager<Q, R, I = never, E extends Error = Error> {
     if (this.terminated) return;
     this.nextQuery = this.lastQuery;
     if (runInBackground) {
-      this.runWhenIdle();
+      void this.runWhenIdle();
     } else {
       this.trigger();
     }
diff --git a/web-console/src/utils/sample-query.tsx b/web-console/src/utils/sample-query.tsx
index 25765435e0..6ef9ddff90 100644
--- a/web-console/src/utils/sample-query.tsx
+++ b/web-console/src/utils/sample-query.tsx
@@ -16,17 +16,14 @@
  * limitations under the License.
  */
 
+import type { Column, LiteralValue, QueryResult, SqlExpression } from 'druid-query-toolkit';
 import {
   C,
-  Column,
   F,
   L,
-  LiteralValue,
-  QueryResult,
   RefName,
   SqlAlias,
   SqlColumnList,
-  SqlExpression,
   SqlQuery,
   SqlRecord,
   SqlValues,
diff --git a/web-console/src/utils/sampler.mock.ts b/web-console/src/utils/sampler.mock.ts
index 284b4a4e88..a95b73a945 100644
--- a/web-console/src/utils/sampler.mock.ts
+++ b/web-console/src/utils/sampler.mock.ts
@@ -17,7 +17,7 @@
  */
 
 // Just to make sure we are in a test context. This line will cause trouble if this file is ever compiled into the main build
-import { SampleHeaderAndRows } from './sampler';
+import type { SampleHeaderAndRows } from './sampler';
 
 expect(1).toEqual(1);
 
diff --git a/web-console/src/utils/sampler.ts b/web-console/src/utils/sampler.ts
index 56d6cceace..46f456d0f0 100644
--- a/web-console/src/utils/sampler.ts
+++ b/web-console/src/utils/sampler.ts
@@ -18,23 +18,25 @@
 
 import * as JSONBig from 'json-bigint-native';
 
-import {
+import type {
   DimensionsSpec,
-  getDimensionNamesFromTransforms,
-  getSpecType,
-  getTimestampSchema,
   IngestionSpec,
   IngestionType,
   InputFormat,
   IoConfig,
-  isDruidSource,
   MetricSpec,
-  PLACEHOLDER_TIMESTAMP_SPEC,
-  REINDEX_TIMESTAMP_SPEC,
-  TIME_COLUMN,
   TimestampSpec,
   Transform,
   TransformSpec,
+} from '../druid-models';
+import {
+  getDimensionNamesFromTransforms,
+  getSpecType,
+  getTimestampSchema,
+  isDruidSource,
+  PLACEHOLDER_TIMESTAMP_SPEC,
+  REINDEX_TIMESTAMP_SPEC,
+  TIME_COLUMN,
   upgradeSpec,
 } from '../druid-models';
 import { Api } from '../singletons';
diff --git a/web-console/e2e-tests/component/datasources/compaction.ts b/web-console/src/utils/shallow-renderer.ts
similarity index 52%
copy from web-console/e2e-tests/component/datasources/compaction.ts
copy to web-console/src/utils/shallow-renderer.ts
index 9463620690..b85e89a498 100644
--- a/web-console/e2e-tests/component/datasources/compaction.ts
+++ b/web-console/src/utils/shallow-renderer.ts
@@ -16,20 +16,26 @@
  * limitations under the License.
  */
 
-import { PartitionsSpec } from '../load-data/config/partition';
+import type React from 'react';
+import ShallowRenderer from 'react-shallow-renderer';
 
 /**
- * Datasource compaction configuration
+ * Shallowly renders a React element for the purpose snapshot testing.
+ *
+ * @param node - The React element to render.
+ * @returns - An opaque object that can be serialized to a snapshot.
  */
-export class CompactionConfig {
-  constructor(props: CompactionConfigProps) {
-    Object.assign(this, props);
+export function shallow(node: React.ReactElement): object {
+  const renderer = new ShallowRenderer();
+  renderer.render(node);
+
+  const instance = renderer.getMountedInstance();
+  if (instance?.componentDidMount) {
+    // Call componentDidMount if it exists -- this isn't done by default
+    // because DOM refs are not available in shallow rendering, but we
+    // don't rely on those in our tests.
+    instance.componentDidMount();
   }
-}
 
-interface CompactionConfigProps {
-  readonly skipOffsetFromLatest: string;
-  readonly partitionsSpec: PartitionsSpec;
+  return renderer.getRenderOutput();
 }
-
-export interface CompactionConfig extends CompactionConfigProps {}
diff --git a/web-console/src/utils/table-helpers.ts b/web-console/src/utils/table-helpers.ts
index e9718551cc..ad1dea9462 100644
--- a/web-console/src/utils/table-helpers.ts
+++ b/web-console/src/utils/table-helpers.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { QueryResult } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
 
 import { filterMap, formatNumber, oneOf } from './general';
 import { deepSet } from './object-change';
diff --git a/web-console/src/utils/types.ts b/web-console/src/utils/types.ts
index a762fc0803..d2c08525dc 100644
--- a/web-console/src/utils/types.ts
+++ b/web-console/src/utils/types.ts
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import { IconName } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { Column } from 'druid-query-toolkit';
+import type { Column } from 'druid-query-toolkit';
 
 function getEffectiveColumnType(column: Column): string | undefined {
   if (column.sqlType === 'TIMESTAMP') return column.sqlType;
diff --git a/web-console/src/utils/utils.spec.ts b/web-console/src/utils/utils.spec.ts
index a66e8bf6e5..2d5c1909dc 100644
--- a/web-console/src/utils/utils.spec.ts
+++ b/web-console/src/utils/utils.spec.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { IngestionSpec } from '../druid-models';
+import type { IngestionSpec } from '../druid-models';
 
 import { applyCache, headerFromSampleResponse } from './sampler';
 
diff --git a/web-console/src/views/datasources-view/datasources-view.spec.tsx b/web-console/src/views/datasources-view/datasources-view.spec.tsx
index 9eff979730..a0127ac314 100644
--- a/web-console/src/views/datasources-view/datasources-view.spec.tsx
+++ b/web-console/src/views/datasources-view/datasources-view.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { DatasourcesView } from './datasources-view';
 
diff --git a/web-console/src/views/datasources-view/datasources-view.tsx b/web-console/src/views/datasources-view/datasources-view.tsx
index ce3332d389..e109b02ac2 100644
--- a/web-console/src/views/datasources-view/datasources-view.tsx
+++ b/web-console/src/views/datasources-view/datasources-view.tsx
@@ -21,7 +21,8 @@ import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
 import { SqlQuery, T } from 'druid-query-toolkit';
 import React from 'react';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import {
   ACTION_COLUMN_ID,
@@ -43,17 +44,17 @@ import {
   RetentionDialog,
 } from '../../dialogs';
 import { DatasourceTableActionDialog } from '../../dialogs/datasource-table-action-dialog/datasource-table-action-dialog';
-import {
+import type {
   CompactionConfig,
   CompactionInfo,
   CompactionStatus,
-  formatCompactionInfo,
   QueryWithContext,
-  zeroCompactionStatus,
 } from '../../druid-models';
-import { Capabilities, CapabilitiesMode } from '../../helpers';
+import { formatCompactionInfo, zeroCompactionStatus } from '../../druid-models';
+import type { Capabilities, CapabilitiesMode } from '../../helpers';
 import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
+import type { NumberLike } from '../../utils';
 import {
   compact,
   countBy,
@@ -68,15 +69,15 @@ import {
   LocalStorageBackedVisibility,
   LocalStorageKeys,
   lookupBy,
-  NumberLike,
   pluralIfNeeded,
   queryDruidSql,
   QueryManager,
   QueryState,
   twoLines,
 } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
-import { Rule, RuleUtil } from '../../utils/load-rule';
+import type { BasicAction } from '../../utils/basic-action';
+import type { Rule } from '../../utils/load-rule';
+import { RuleUtil } from '../../utils/load-rule';
 
 import './datasources-view.scss';
 
@@ -377,7 +378,7 @@ ORDER BY 1`;
       actions: [],
     };
 
-    this.datasourceQueryManager = new QueryManager({
+    this.datasourceQueryManager = new QueryManager<DatasourceQuery, DatasourcesAndDefaultRules>({
       processQuery: async (
         { capabilities, visibleColumns, showUnused },
         _cancelToken,
@@ -817,6 +818,7 @@ ORDER BY 1`;
       intent: Intent.DANGER,
       action: {
         text: 'Confirm',
+        // eslint-disable-next-line @typescript-eslint/no-misused-promises
         onClick: async () => {
           try {
             await Api.instance.delete(
diff --git a/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap b/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
index c69a4777f9..640fe8900b 100644
--- a/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
+++ b/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
@@ -5,28 +5,30 @@ exports[`HomeView matches snapshot (coordinator) 1`] = `
   className="home-view app-view"
 >
   <Memo(StatusCard) />
-  <Memo(DatasourcesCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": false,
-        "overlord": false,
-        "queryType": "none",
+  <React.Fragment>
+    <Memo(DatasourcesCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": false,
+          "overlord": false,
+          "queryType": "none",
+        }
       }
-    }
-  />
-  <Memo(SegmentsCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": false,
-        "overlord": false,
-        "queryType": "none",
+    />
+    <Memo(SegmentsCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": false,
+          "overlord": false,
+          "queryType": "none",
+        }
       }
-    }
-  />
+    />
+  </React.Fragment>
   <Memo(ServicesCard)
     capabilities={
       Capabilities {
@@ -57,50 +59,54 @@ exports[`HomeView matches snapshot (full) 1`] = `
   className="home-view app-view"
 >
   <Memo(StatusCard) />
-  <Memo(DatasourcesCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": true,
-        "overlord": true,
-        "queryType": "nativeAndSql",
+  <React.Fragment>
+    <Memo(DatasourcesCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": true,
+          "overlord": true,
+          "queryType": "nativeAndSql",
+        }
       }
-    }
-  />
-  <Memo(SegmentsCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": true,
-        "overlord": true,
-        "queryType": "nativeAndSql",
+    />
+    <Memo(SegmentsCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": true,
+          "overlord": true,
+          "queryType": "nativeAndSql",
+        }
       }
-    }
-  />
-  <Memo(SupervisorsCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": true,
-        "overlord": true,
-        "queryType": "nativeAndSql",
+    />
+  </React.Fragment>
+  <React.Fragment>
+    <Memo(SupervisorsCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": true,
+          "overlord": true,
+          "queryType": "nativeAndSql",
+        }
       }
-    }
-  />
-  <Memo(TasksCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": true,
-        "multiStageQuery": true,
-        "overlord": true,
-        "queryType": "nativeAndSql",
+    />
+    <Memo(TasksCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": true,
+          "multiStageQuery": true,
+          "overlord": true,
+          "queryType": "nativeAndSql",
+        }
       }
-    }
-  />
+    />
+  </React.Fragment>
   <Memo(ServicesCard)
     capabilities={
       Capabilities {
@@ -131,27 +137,29 @@ exports[`HomeView matches snapshot (overlord) 1`] = `
   className="home-view app-view"
 >
   <Memo(StatusCard) />
-  <Memo(SupervisorsCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": false,
-        "multiStageQuery": false,
-        "overlord": true,
-        "queryType": "none",
+  <React.Fragment>
+    <Memo(SupervisorsCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": false,
+          "multiStageQuery": false,
+          "overlord": true,
+          "queryType": "none",
+        }
       }
-    }
-  />
-  <Memo(TasksCard)
-    capabilities={
-      Capabilities {
-        "clusterCapacity": undefined,
-        "coordinator": false,
-        "multiStageQuery": false,
-        "overlord": true,
-        "queryType": "none",
+    />
+    <Memo(TasksCard)
+      capabilities={
+        Capabilities {
+          "clusterCapacity": undefined,
+          "coordinator": false,
+          "multiStageQuery": false,
+          "overlord": true,
+          "queryType": "none",
+        }
       }
-    }
-  />
+    />
+  </React.Fragment>
 </div>
 `;
diff --git a/web-console/src/views/home-view/datasources-card/datasources-card.tsx b/web-console/src/views/home-view/datasources-card/datasources-card.tsx
index 15f5616e36..3f64e0476e 100644
--- a/web-console/src/views/home-view/datasources-card/datasources-card.tsx
+++ b/web-console/src/views/home-view/datasources-card/datasources-card.tsx
@@ -19,7 +19,7 @@
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
-import { Capabilities } from '../../../helpers';
+import type { Capabilities } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { pluralIfNeeded, queryDruidSql } from '../../../utils';
diff --git a/web-console/src/views/home-view/home-view-card/home-view-card.tsx b/web-console/src/views/home-view/home-view-card/home-view-card.tsx
index c23f73fe8e..4740413471 100644
--- a/web-console/src/views/home-view/home-view-card/home-view-card.tsx
+++ b/web-console/src/views/home-view/home-view-card/home-view-card.tsx
@@ -16,9 +16,11 @@
  * limitations under the License.
  */
 
-import { Card, H5, Icon, IconName } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Card, H5, Icon } from '@blueprintjs/core';
 import classNames from 'classnames';
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import './home-view-card.scss';
 
diff --git a/web-console/src/views/home-view/home-view.spec.tsx b/web-console/src/views/home-view/home-view.spec.tsx
index 81f46cc296..0abf64eaa7 100644
--- a/web-console/src/views/home-view/home-view.spec.tsx
+++ b/web-console/src/views/home-view/home-view.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { HomeView } from './home-view';
 
diff --git a/web-console/src/views/home-view/home-view.tsx b/web-console/src/views/home-view/home-view.tsx
index 08ef69b2f4..4a9158b9d4 100644
--- a/web-console/src/views/home-view/home-view.tsx
+++ b/web-console/src/views/home-view/home-view.tsx
@@ -18,7 +18,7 @@
 
 import React from 'react';
 
-import { Capabilities } from '../../helpers';
+import type { Capabilities } from '../../helpers';
 
 import { DatasourcesCard } from './datasources-card/datasources-card';
 import { LookupsCard } from './lookups-card/lookups-card';
diff --git a/web-console/src/views/home-view/lookups-card/lookups-card.tsx b/web-console/src/views/home-view/lookups-card/lookups-card.tsx
index e4f5f98b28..e99ef2ab67 100644
--- a/web-console/src/views/home-view/lookups-card/lookups-card.tsx
+++ b/web-console/src/views/home-view/lookups-card/lookups-card.tsx
@@ -20,7 +20,7 @@ import { IconNames } from '@blueprintjs/icons';
 import { sum } from 'd3-array';
 import React from 'react';
 
-import { Capabilities } from '../../../helpers';
+import type { Capabilities } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { isLookupsUninitialized, pluralIfNeeded } from '../../../utils';
diff --git a/web-console/src/views/home-view/segments-card/segments-card.tsx b/web-console/src/views/home-view/segments-card/segments-card.tsx
index 56c022fc01..331aab7f34 100644
--- a/web-console/src/views/home-view/segments-card/segments-card.tsx
+++ b/web-console/src/views/home-view/segments-card/segments-card.tsx
@@ -20,7 +20,7 @@ import { IconNames } from '@blueprintjs/icons';
 import { sum } from 'd3-array';
 import React from 'react';
 
-import { Capabilities } from '../../../helpers';
+import type { Capabilities } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { deepGet, pluralIfNeeded, queryDruidSql } from '../../../utils';
diff --git a/web-console/src/views/home-view/services-card/services-card.tsx b/web-console/src/views/home-view/services-card/services-card.tsx
index 88594bb69c..6018b5e91a 100644
--- a/web-console/src/views/home-view/services-card/services-card.tsx
+++ b/web-console/src/views/home-view/services-card/services-card.tsx
@@ -20,7 +20,7 @@ import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
 import { PluralPairIfNeeded } from '../../../components';
-import { Capabilities } from '../../../helpers';
+import type { Capabilities } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { lookupBy, queryDruidSql } from '../../../utils';
diff --git a/web-console/src/views/home-view/supervisors-card/supervisors-card.tsx b/web-console/src/views/home-view/supervisors-card/supervisors-card.tsx
index a04d7b5929..f6d1ba623f 100644
--- a/web-console/src/views/home-view/supervisors-card/supervisors-card.tsx
+++ b/web-console/src/views/home-view/supervisors-card/supervisors-card.tsx
@@ -19,7 +19,7 @@
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
-import { Capabilities } from '../../../helpers';
+import type { Capabilities } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { pluralIfNeeded, queryDruidSql } from '../../../utils';
diff --git a/web-console/src/views/home-view/tasks-card/tasks-card.tsx b/web-console/src/views/home-view/tasks-card/tasks-card.tsx
index b5cb5bfc0c..e684d5c02d 100644
--- a/web-console/src/views/home-view/tasks-card/tasks-card.tsx
+++ b/web-console/src/views/home-view/tasks-card/tasks-card.tsx
@@ -20,8 +20,9 @@ import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
 import { PluralPairIfNeeded } from '../../../components';
-import { CapacityInfo } from '../../../druid-models';
-import { Capabilities, getClusterCapacity } from '../../../helpers';
+import type { CapacityInfo } from '../../../druid-models';
+import type { Capabilities } from '../../../helpers';
+import { getClusterCapacity } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { lookupBy, pluralIfNeeded, queryDruidSql } from '../../../utils';
diff --git a/web-console/src/views/ingestion-view/__snapshots__/ingestion-view.spec.tsx.snap b/web-console/src/views/ingestion-view/__snapshots__/ingestion-view.spec.tsx.snap
index 028af2d9e1..961ec61792 100644
--- a/web-console/src/views/ingestion-view/__snapshots__/ingestion-view.spec.tsx.snap
+++ b/web-console/src/views/ingestion-view/__snapshots__/ingestion-view.spec.tsx.snap
@@ -1,7 +1,7 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`IngestionView matches snapshot 1`] = `
-<Fragment>
+<React.Fragment>
   <t
     customClassName="ingestion-view app-view"
     onDragEnd={null}
@@ -24,64 +24,66 @@ exports[`IngestionView matches snapshot 1`] = `
           localStorageKey="supervisors-refresh-rate"
           onRefresh={[Function]}
         />
-        <Memo(MoreButton)>
-          <Blueprint4.MenuItem
-            active={false}
-            disabled={false}
-            icon="application"
-            multiline={false}
-            onClick={[Function]}
-            popoverProps={Object {}}
-            selected={false}
-            shouldDismissPopover={true}
-            text="View SQL query for table"
-          />
-          <Blueprint4.MenuItem
-            active={false}
-            disabled={false}
-            icon="manually-entered-data"
-            multiline={false}
-            onClick={[Function]}
-            popoverProps={Object {}}
-            selected={false}
-            shouldDismissPopover={true}
-            text="Submit JSON supervisor"
-          />
-          <Blueprint4.MenuItem
-            active={false}
-            disabled={false}
-            icon="play"
-            multiline={false}
-            onClick={[Function]}
-            popoverProps={Object {}}
-            selected={false}
-            shouldDismissPopover={true}
-            text="Resume all supervisors"
-          />
-          <Blueprint4.MenuItem
-            active={false}
-            disabled={false}
-            icon="pause"
-            multiline={false}
-            onClick={[Function]}
-            popoverProps={Object {}}
-            selected={false}
-            shouldDismissPopover={true}
-            text="Suspend all supervisors"
-          />
-          <Blueprint4.MenuItem
-            active={false}
-            disabled={false}
-            icon="cross"
-            intent="danger"
-            multiline={false}
-            onClick={[Function]}
-            popoverProps={Object {}}
-            selected={false}
-            shouldDismissPopover={true}
-            text="Terminate all supervisors"
-          />
-        </Memo(MoreButton)>
+        <React.Fragment>
+          <Memo(MoreButton)>
+            <Blueprint4.MenuItem
+              active={false}
+              disabled={false}
+              icon="application"
+              multiline={false}
+              onClick={[Function]}
+              popoverProps={Object {}}
+              selected={false}
+              shouldDismissPopover={true}
+              text="View SQL query for table"
+            />
+            <Blueprint4.MenuItem
+              active={false}
+              disabled={false}
+              icon="manually-entered-data"
+              multiline={false}
+              onClick={[Function]}
+              popoverProps={Object {}}
+              selected={false}
+              shouldDismissPopover={true}
+              text="Submit JSON supervisor"
+            />
+            <Blueprint4.MenuItem
+              active={false}
+              disabled={false}
+              icon="play"
+              multiline={false}
+              onClick={[Function]}
+              popoverProps={Object {}}
+              selected={false}
+              shouldDismissPopover={true}
+              text="Resume all supervisors"
+            />
+            <Blueprint4.MenuItem
+              active={false}
+              disabled={false}
+              icon="pause"
+              multiline={false}
+              onClick={[Function]}
+              popoverProps={Object {}}
+              selected={false}
+              shouldDismissPopover={true}
+              text="Suspend all supervisors"
+            />
+            <Blueprint4.MenuItem
+              active={false}
+              disabled={false}
+              icon="cross"
+              intent="danger"
+              multiline={false}
+              onClick={[Function]}
+              popoverProps={Object {}}
+              selected={false}
+              shouldDismissPopover={true}
+              text="Terminate all supervisors"
+            />
+          </Memo(MoreButton)>
+        </React.Fragment>
         <Memo(TableColumnSelector)
           columns={
             Array [
@@ -289,9 +291,9 @@ exports[`IngestionView matches snapshot 1`] = `
       <Memo(ViewControlBar)
         label="Tasks"
       >
-        <Component>
+        <Unknown>
           Group by
-        </Component>
+        </Unknown>
         <Blueprint4.ButtonGroup>
           <Blueprint4.Button
             active={true}
@@ -618,5 +620,5 @@ exports[`IngestionView matches snapshot 1`] = `
   >
     <p />
   </Blueprint4.Alert>
-</Fragment>
+</React.Fragment>
 `;
diff --git a/web-console/src/views/ingestion-view/ingestion-view.spec.tsx b/web-console/src/views/ingestion-view/ingestion-view.spec.tsx
index 7c00f7c47b..9d53c2aec2 100644
--- a/web-console/src/views/ingestion-view/ingestion-view.spec.tsx
+++ b/web-console/src/views/ingestion-view/ingestion-view.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { IngestionView } from './ingestion-view';
 
diff --git a/web-console/src/views/ingestion-view/ingestion-view.tsx b/web-console/src/views/ingestion-view/ingestion-view.tsx
index f00c2bd479..05d1eeca7e 100644
--- a/web-console/src/views/ingestion-view/ingestion-view.tsx
+++ b/web-console/src/views/ingestion-view/ingestion-view.tsx
@@ -20,7 +20,8 @@ import { Alert, Button, ButtonGroup, Intent, Label, MenuItem } from '@blueprintj
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 import SplitterLayout from 'react-splitter-layout';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import {
   ACTION_COLUMN_ID,
@@ -40,8 +41,8 @@ import {
   SupervisorTableActionDialog,
   TaskTableActionDialog,
 } from '../../dialogs';
-import { QueryWithContext } from '../../druid-models';
-import { Capabilities } from '../../helpers';
+import type { QueryWithContext } from '../../druid-models';
+import type { Capabilities } from '../../helpers';
 import {
   SMALL_TABLE_PAGE_SIZE,
   SMALL_TABLE_PAGE_SIZE_OPTIONS,
@@ -62,7 +63,7 @@ import {
   QueryManager,
   QueryState,
 } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
 
 import './ingestion-view.scss';
 
diff --git a/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap b/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
index f6289c9d57..9cf8d12a9d 100644
--- a/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
+++ b/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
@@ -12,7 +12,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
     >
       <div
         className="step-section"
-        key="Connect and parse raw data"
       >
         <div
           className="step-nav-l1"
@@ -27,7 +26,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="welcome"
             disabled={false}
             icon={false}
-            key="welcome"
             onClick={[Function]}
             text="Start"
           />
@@ -36,7 +34,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="connect"
             disabled={true}
             icon={false}
-            key="connect"
             onClick={[Function]}
             text="Connect"
           />
@@ -45,7 +42,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="parser"
             disabled={true}
             icon={false}
-            key="parser"
             onClick={[Function]}
             text="Parse data"
           />
@@ -53,7 +49,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
       </div>
       <div
         className="step-section"
-        key="Transform data and configure schema"
       >
         <div
           className="step-nav-l1"
@@ -68,7 +63,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="timestamp"
             disabled={true}
             icon={false}
-            key="timestamp"
             onClick={[Function]}
             text="Parse time"
           />
@@ -77,7 +71,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="transform"
             disabled={true}
             icon={false}
-            key="transform"
             onClick={[Function]}
             text="Transform"
           />
@@ -86,7 +79,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="filter"
             disabled={true}
             icon={false}
-            key="filter"
             onClick={[Function]}
             text="Filter"
           />
@@ -95,7 +87,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="schema"
             disabled={true}
             icon={false}
-            key="schema"
             onClick={[Function]}
             text="Configure schema"
           />
@@ -103,7 +94,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
       </div>
       <div
         className="step-section"
-        key="Tune parameters"
       >
         <div
           className="step-nav-l1"
@@ -118,7 +108,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="partition"
             disabled={true}
             icon={false}
-            key="partition"
             onClick={[Function]}
             text="Partition"
           />
@@ -127,7 +116,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="tuning"
             disabled={true}
             icon={false}
-            key="tuning"
             onClick={[Function]}
             text="Tune"
           />
@@ -136,7 +124,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="publish"
             disabled={true}
             icon={false}
-            key="publish"
             onClick={[Function]}
             text="Publish"
           />
@@ -144,7 +131,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
       </div>
       <div
         className="step-section"
-        key="Verify and submit"
       >
         <div
           className="step-nav-l1"
@@ -159,7 +145,6 @@ exports[`LoadDataView matches snapshot batch 1`] = `
             className="spec"
             disabled={false}
             icon="manually-entered-data"
-            key="spec"
             onClick={[Function]}
             text="Edit spec"
           />
@@ -167,24 +152,28 @@ exports[`LoadDataView matches snapshot batch 1`] = `
       </div>
     </div>
   </div>
-  <div
-    className="main"
-  >
+  <React.Fragment>
     <div
-      className="ingestion-cards"
-    />
-  </div>
-  <div
-    className="control"
-  >
-    <Blueprint4.FormGroup>
-      <Blueprint4.Callout>
-        <p>
-          Please specify where your raw data is located.
-        </p>
-      </Blueprint4.Callout>
-    </Blueprint4.FormGroup>
-  </div>
+      className="main"
+    >
+      <div
+        className="ingestion-cards"
+      >
+        <React.Fragment />
+      </div>
+    </div>
+    <div
+      className="control"
+    >
+      <Blueprint4.FormGroup>
+        <Blueprint4.Callout>
+          <p>
+            Please specify where your raw data is located.
+          </p>
+        </Blueprint4.Callout>
+      </Blueprint4.FormGroup>
+    </div>
+  </React.Fragment>
 </div>
 `;
 
@@ -200,7 +189,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
     >
       <div
         className="step-section"
-        key="Connect and parse raw data"
       >
         <div
           className="step-nav-l1"
@@ -215,7 +203,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="welcome"
             disabled={false}
             icon={false}
-            key="welcome"
             onClick={[Function]}
             text="Start"
           />
@@ -224,7 +211,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="connect"
             disabled={true}
             icon={false}
-            key="connect"
             onClick={[Function]}
             text="Connect"
           />
@@ -233,7 +219,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="parser"
             disabled={true}
             icon={false}
-            key="parser"
             onClick={[Function]}
             text="Parse data"
           />
@@ -241,7 +226,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
       </div>
       <div
         className="step-section"
-        key="Transform data and configure schema"
       >
         <div
           className="step-nav-l1"
@@ -256,7 +240,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="timestamp"
             disabled={true}
             icon={false}
-            key="timestamp"
             onClick={[Function]}
             text="Parse time"
           />
@@ -265,7 +248,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="transform"
             disabled={true}
             icon={false}
-            key="transform"
             onClick={[Function]}
             text="Transform"
           />
@@ -274,7 +256,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="filter"
             disabled={true}
             icon={false}
-            key="filter"
             onClick={[Function]}
             text="Filter"
           />
@@ -283,7 +264,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="schema"
             disabled={true}
             icon={false}
-            key="schema"
             onClick={[Function]}
             text="Configure schema"
           />
@@ -291,7 +271,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
       </div>
       <div
         className="step-section"
-        key="Tune parameters"
       >
         <div
           className="step-nav-l1"
@@ -306,7 +285,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="partition"
             disabled={true}
             icon={false}
-            key="partition"
             onClick={[Function]}
             text="Partition"
           />
@@ -315,7 +293,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="tuning"
             disabled={true}
             icon={false}
-            key="tuning"
             onClick={[Function]}
             text="Tune"
           />
@@ -324,7 +301,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="publish"
             disabled={true}
             icon={false}
-            key="publish"
             onClick={[Function]}
             text="Publish"
           />
@@ -332,7 +308,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
       </div>
       <div
         className="step-section"
-        key="Verify and submit"
       >
         <div
           className="step-nav-l1"
@@ -347,7 +322,6 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
             className="spec"
             disabled={false}
             icon="manually-entered-data"
-            key="spec"
             onClick={[Function]}
             text="Edit spec"
           />
@@ -355,23 +329,27 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
       </div>
     </div>
   </div>
-  <div
-    className="main"
-  >
+  <React.Fragment>
     <div
-      className="ingestion-cards"
-    />
-  </div>
-  <div
-    className="control"
-  >
-    <Blueprint4.FormGroup>
-      <Blueprint4.Callout>
-        <p>
-          Please specify where your raw data is located.
-        </p>
-      </Blueprint4.Callout>
-    </Blueprint4.FormGroup>
-  </div>
+      className="main"
+    >
+      <div
+        className="ingestion-cards"
+      >
+        <React.Fragment />
+      </div>
+    </div>
+    <div
+      className="control"
+    >
+      <Blueprint4.FormGroup>
+        <Blueprint4.Callout>
+          <p>
+            Please specify where your raw data is located.
+          </p>
+        </Blueprint4.Callout>
+      </Blueprint4.FormGroup>
+    </div>
+  </React.Fragment>
 </div>
 `;
diff --git a/web-console/src/views/load-data-view/example-picker/example-picker.tsx b/web-console/src/views/load-data-view/example-picker/example-picker.tsx
index fa67b6b9c5..cf5c9bbe26 100644
--- a/web-console/src/views/load-data-view/example-picker/example-picker.tsx
+++ b/web-console/src/views/load-data-view/example-picker/example-picker.tsx
@@ -20,7 +20,7 @@ import { Button, Callout, FormGroup, HTMLSelect, Intent } from '@blueprintjs/cor
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import { ExampleManifest } from '../../../utils/sampler';
+import type { ExampleManifest } from '../../../utils/sampler';
 
 export interface ExamplePickerProps {
   exampleManifests: ExampleManifest[];
diff --git a/web-console/src/views/load-data-view/filter-table/filter-table.tsx b/web-console/src/views/load-data-view/filter-table/filter-table.tsx
index 4e82a482a9..86d10250e2 100644
--- a/web-console/src/views/load-data-view/filter-table/filter-table.tsx
+++ b/web-console/src/views/load-data-view/filter-table/filter-table.tsx
@@ -18,17 +18,19 @@
 
 import classNames from 'classnames';
 import React from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { TableCell } from '../../../components';
-import { DruidFilter, getFilterDimension } from '../../../druid-models';
+import type { DruidFilter } from '../../../druid-models';
+import { getFilterDimension } from '../../../druid-models';
 import {
   DEFAULT_TABLE_CLASS_NAME,
   STANDARD_TABLE_PAGE_SIZE,
   STANDARD_TABLE_PAGE_SIZE_OPTIONS,
 } from '../../../react-table';
 import { caseInsensitiveContains, filterMap } from '../../../utils';
-import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
+import type { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
 
 import './filter-table.scss';
 
@@ -97,7 +99,7 @@ export const FilterTable = React.memo(function FilterTable(props: FilterTablePro
           id: String(i),
           accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
           width: 140,
-          Cell: function FilterTableCell(row) {
+          Cell: function FilterTableCell(row: RowRenderProps) {
             return <TableCell value={timestamp ? new Date(row.value) : row.value} />;
           },
         };
diff --git a/web-console/src/views/load-data-view/form-editor/form-editor.tsx b/web-console/src/views/load-data-view/form-editor/form-editor.tsx
index 51d0c5e95d..28e4e6c848 100644
--- a/web-console/src/views/load-data-view/form-editor/form-editor.tsx
+++ b/web-console/src/views/load-data-view/form-editor/form-editor.tsx
@@ -20,7 +20,8 @@ import { Button, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import { AutoForm, Field } from '../../../components';
+import type { Field } from '../../../components';
+import { AutoForm } from '../../../components';
 
 import './form-editor.scss';
 
@@ -37,7 +38,7 @@ export interface FormEditorProps<T> {
   children?: any;
 }
 
-export function FormEditor<T>(props: FormEditorProps<T>) {
+export function FormEditor<T extends Record<string, any>>(props: FormEditorProps<T>) {
   const {
     fields,
     initValue,
diff --git a/web-console/src/views/load-data-view/info-messages.tsx b/web-console/src/views/load-data-view/info-messages.tsx
index 733ad34dbb..dbd08eb89c 100644
--- a/web-console/src/views/load-data-view/info-messages.tsx
+++ b/web-console/src/views/load-data-view/info-messages.tsx
@@ -20,7 +20,8 @@ import { Button, Callout, Code, FormGroup, Intent } from '@blueprintjs/core';
 import React from 'react';
 
 import { ExternalLink, LearnMore } from '../../components';
-import { DimensionMode, getIngestionDocLink, IngestionSpec } from '../../druid-models';
+import type { DimensionMode, IngestionSpec } from '../../druid-models';
+import { getIngestionDocLink } from '../../druid-models';
 import { getLink } from '../../links';
 import { deepGet, deepSet } from '../../utils';
 
diff --git a/web-console/src/views/load-data-view/load-data-view.spec.tsx b/web-console/src/views/load-data-view/load-data-view.spec.tsx
index ad6e48440b..e486e2aed1 100644
--- a/web-console/src/views/load-data-view/load-data-view.spec.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { LoadDataView } from './load-data-view';
 
 describe('LoadDataView', () => {
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index eb2a772339..d3d4a109a4 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import type { IconName } from '@blueprintjs/core';
 import {
   Alert,
   AnchorButton,
@@ -27,7 +28,6 @@ import {
   FormGroup,
   H5,
   Icon,
-  IconName,
   InputGroup,
   Intent,
   Menu,
@@ -55,6 +55,20 @@ import {
   PopoverText,
 } from '../../components';
 import { AsyncActionDialog } from '../../dialogs';
+import type {
+  DimensionMode,
+  DimensionSpec,
+  DruidFilter,
+  FlattenField,
+  IngestionComboTypeWithExtra,
+  IngestionSpec,
+  InputFormat,
+  IoConfig,
+  MetricSpec,
+  TimestampSpec,
+  Transform,
+  TuningConfig,
+} from '../../druid-models';
 import {
   addTimestampTransform,
   adjustForceGuaranteedRollup,
@@ -64,15 +78,11 @@ import {
   CONSTANT_TIMESTAMP_SPEC,
   CONSTANT_TIMESTAMP_SPEC_FIELDS,
   DIMENSION_SPEC_FIELDS,
-  DimensionMode,
-  DimensionSpec,
-  DruidFilter,
   fillDataSourceNameIfNeeded,
   fillInputFormatIfNeeded,
   FILTER_FIELDS,
   FILTERS_FIELDS,
   FLATTEN_FIELD_FIELDS,
-  FlattenField,
   getDimensionMode,
   getDimensionSpecName,
   getIngestionComboType,
@@ -88,14 +98,10 @@ import {
   getTimestampExpressionFields,
   getTimestampSchema,
   getTuningFormFields,
-  IngestionComboTypeWithExtra,
-  IngestionSpec,
   INPUT_FORMAT_FIELDS,
-  InputFormat,
   inputFormatCanProduceNestedData,
   invalidIoConfig,
   invalidPartitionConfig,
-  IoConfig,
   isDruidSource,
   isEmptyIngestionSpec,
   isStreamingSpec,
@@ -105,7 +111,6 @@ import {
   KNOWN_FILTER_TYPES,
   MAX_INLINE_DATA_LENGTH,
   METRIC_SPEC_FIELDS,
-  MetricSpec,
   normalizeSpec,
   NUMERIC_TIME_FORMATS,
   possibleDruidFormatForValues,
@@ -115,10 +120,7 @@ import {
   STREAMING_INPUT_FORMAT_FIELDS,
   TIME_COLUMN,
   TIMESTAMP_SPEC_FIELDS,
-  TimestampSpec,
-  Transform,
   TRANSFORM_FIELDS,
-  TuningConfig,
   updateIngestionType,
   updateSchemaWithSample,
   upgradeSpec,
@@ -143,13 +145,19 @@ import {
   pluralIfNeeded,
   QueryState,
 } from '../../utils';
-import {
+import type {
   CacheRows,
   ExampleManifest,
+  SampleEntry,
+  SampleHeaderAndRows,
+  SampleResponse,
+  SampleResponseWithExtraInfo,
+  SampleStrategy,
+} from '../../utils/sampler';
+import {
   getCacheRowsFromSampleResponse,
   getProxyOverlordModules,
   headerAndRowsFromSampleResponse,
-  SampleEntry,
   sampleForConnect,
   sampleForExampleManifests,
   sampleForFilter,
@@ -157,10 +165,6 @@ import {
   sampleForSchema,
   sampleForTimestamp,
   sampleForTransform,
-  SampleHeaderAndRows,
-  SampleResponse,
-  SampleResponseWithExtraInfo,
-  SampleStrategy,
 } from '../../utils/sampler';
 
 import { ExamplePicker } from './example-picker/example-picker';
@@ -3253,7 +3257,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
             rightIcon={IconNames.CLOUD_UPLOAD}
             intent={Intent.PRIMARY}
             disabled={submitting || Boolean(issueWithSpec)}
-            onClick={this.handleSubmit}
+            onClick={() => void this.handleSubmit()}
           />
         </div>
       </>
diff --git a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
index af2c2e2c5f..d494791dc4 100644
--- a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
@@ -19,17 +19,18 @@
 import classNames from 'classnames';
 import * as JSONBig from 'json-bigint-native';
 import React from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { TableCell, TableCellUnparseable } from '../../../components';
-import { FlattenField } from '../../../druid-models';
+import type { FlattenField } from '../../../druid-models';
 import {
   DEFAULT_TABLE_CLASS_NAME,
   STANDARD_TABLE_PAGE_SIZE,
   STANDARD_TABLE_PAGE_SIZE_OPTIONS,
 } from '../../../react-table';
 import { caseInsensitiveContains, filterMap } from '../../../utils';
-import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
+import type { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
 
 import './parse-data-table.scss';
 
@@ -86,7 +87,7 @@ export const ParseDataTable = React.memo(function ParseDataTable(props: ParseDat
           id: String(i),
           accessor: (row: SampleEntry) => (row[key] ? row[key]![columnName] : null),
           width: 140,
-          Cell: function ParseDataTableCell(row) {
+          Cell: function ParseDataTableCell(row: RowRenderProps) {
             if (row.original.unparseable) {
               return <TableCellUnparseable />;
             }
diff --git a/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
index 0c20f70145..f2354445fb 100644
--- a/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
+++ b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
@@ -19,7 +19,8 @@
 import { render } from '@testing-library/react';
 import React from 'react';
 
-import { IngestionSpec, PLACEHOLDER_TIMESTAMP_SPEC } from '../../../druid-models';
+import type { IngestionSpec } from '../../../druid-models';
+import { PLACEHOLDER_TIMESTAMP_SPEC } from '../../../druid-models';
 import { deepSet } from '../../../utils';
 
 import { ParseTimeTable } from './parse-time-table';
diff --git a/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx
index 7e1396b4de..36b0776641 100644
--- a/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx
+++ b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx
@@ -18,15 +18,15 @@
 
 import classNames from 'classnames';
 import React from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { TableCell, TableCellUnparseable } from '../../../components';
+import type { IngestionSpec, TimestampSpec } from '../../../druid-models';
 import {
   getTimestampDetailFromSpec,
   getTimestampSpecColumnFromSpec,
-  IngestionSpec,
   possibleDruidFormatForValues,
-  TimestampSpec,
 } from '../../../druid-models';
 import {
   DEFAULT_TABLE_CLASS_NAME,
@@ -34,7 +34,7 @@ import {
   STANDARD_TABLE_PAGE_SIZE_OPTIONS,
 } from '../../../react-table';
 import { caseInsensitiveContains, filterMap } from '../../../utils';
-import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
+import type { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
 
 import './parse-time-table.scss';
 
@@ -123,7 +123,7 @@ export const ParseTimeTable = React.memo(function ParseTimeTable(props: ParseTim
             className: columnClassName,
             id: String(i),
             accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
-            Cell: function ParseTimeTableCell(row) {
+            Cell: function ParseTimeTableCell(row: RowRenderProps) {
               if (columnName === '__error__') {
                 return <TableCell value={row.original.error} />;
               }
diff --git a/web-console/src/views/load-data-view/schema-table/schema-table.tsx b/web-console/src/views/load-data-view/schema-table/schema-table.tsx
index fcdf574c0b..caad1162e1 100644
--- a/web-console/src/views/load-data-view/schema-table/schema-table.tsx
+++ b/web-console/src/views/load-data-view/schema-table/schema-table.tsx
@@ -18,16 +18,16 @@
 
 import classNames from 'classnames';
 import React from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { TableCell } from '../../../components';
+import type { DimensionSpec, MetricSpec } from '../../../druid-models';
 import {
-  DimensionSpec,
   getDimensionSpecName,
   getDimensionSpecType,
   getMetricSpecName,
   inflateDimensionSpec,
-  MetricSpec,
 } from '../../../druid-models';
 import {
   DEFAULT_TABLE_CLASS_NAME,
@@ -35,7 +35,7 @@ import {
   STANDARD_TABLE_PAGE_SIZE_OPTIONS,
 } from '../../../react-table';
 import { caseInsensitiveContains, filterMap } from '../../../utils';
-import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
+import type { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
 
 import './schema-table.scss';
 
@@ -102,7 +102,7 @@ export const SchemaTable = React.memo(function SchemaTable(props: SchemaTablePro
             id: String(i),
             accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
             width: 120,
-            Cell: function SchemaTableCell({ value }) {
+            Cell: function SchemaTableCell({ value }: RowRenderProps) {
               return <TableCell value={value} />;
             },
           };
@@ -148,7 +148,7 @@ export const SchemaTable = React.memo(function SchemaTable(props: SchemaTablePro
             id: String(i),
             width: isTimestamp ? 200 : 140,
             accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
-            Cell: function SchemaTableCell(row) {
+            Cell: function SchemaTableCell(row: RowRenderProps) {
               return <TableCell value={isTimestamp ? new Date(row.value) : row.value} />;
             },
           };
diff --git a/web-console/src/views/load-data-view/transform-table/transform-table.tsx b/web-console/src/views/load-data-view/transform-table/transform-table.tsx
index fc85899c71..5244a7e42a 100644
--- a/web-console/src/views/load-data-view/transform-table/transform-table.tsx
+++ b/web-console/src/views/load-data-view/transform-table/transform-table.tsx
@@ -18,10 +18,11 @@
 
 import classNames from 'classnames';
 import React from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { TableCell } from '../../../components';
-import { Transform } from '../../../druid-models';
+import type { Transform } from '../../../druid-models';
 import {
   DEFAULT_TABLE_CLASS_NAME,
   STANDARD_TABLE_PAGE_SIZE,
@@ -29,7 +30,7 @@ import {
 } from '../../../react-table';
 import { caseInsensitiveContains, filterMap } from '../../../utils';
 import { escapeColumnName } from '../../../utils/druid-expression';
-import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
+import type { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
 
 import './transform-table.scss';
 
@@ -111,7 +112,7 @@ export const TransformTable = React.memo(function TransformTable(props: Transfor
           id: String(i),
           accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
           width: 140,
-          Cell: function TransformTableCell(row) {
+          Cell: function TransformTableCell(row: RowRenderProps) {
             return <TableCell value={timestamp ? new Date(row.value) : row.value} />;
           },
         };
diff --git a/web-console/src/views/lookups-view/lookups-view.spec.tsx b/web-console/src/views/lookups-view/lookups-view.spec.tsx
index 0daa0eab15..bbbb7397bf 100644
--- a/web-console/src/views/lookups-view/lookups-view.spec.tsx
+++ b/web-console/src/views/lookups-view/lookups-view.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../utils/shallow-renderer';
+
 import { LookupsView } from './lookups-view';
 
 describe('LookupsView', () => {
diff --git a/web-console/src/views/lookups-view/lookups-view.tsx b/web-console/src/views/lookups-view/lookups-view.tsx
index 8599f6d10f..70d0c3f6b1 100644
--- a/web-console/src/views/lookups-view/lookups-view.tsx
+++ b/web-console/src/views/lookups-view/lookups-view.tsx
@@ -19,7 +19,8 @@
 import { Button, Icon, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import {
   ACTION_COLUMN_ID,
@@ -34,7 +35,8 @@ import {
 } from '../../components';
 import { AsyncActionDialog, LookupEditDialog } from '../../dialogs/';
 import { LookupTableActionDialog } from '../../dialogs/lookup-table-action-dialog/lookup-table-action-dialog';
-import { LookupSpec, lookupSpecSummary } from '../../druid-models';
+import type { LookupSpec } from '../../druid-models';
+import { lookupSpecSummary } from '../../druid-models';
 import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
 import {
@@ -47,7 +49,7 @@ import {
   QueryManager,
   QueryState,
 } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
 
 import './lookups-view.scss';
 
@@ -343,7 +345,7 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
           <Button
             icon={IconNames.BUILD}
             text="Initialize lookups"
-            onClick={() => this.initializeLookup()}
+            onClick={() => void this.initializeLookup()}
           />
         </div>
       );
@@ -478,7 +480,7 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
     return (
       <LookupEditDialog
         onClose={() => this.setState({ lookupEdit: undefined })}
-        onSubmit={updateLookupVersion => this.submitLookupEdit(updateLookupVersion)}
+        onSubmit={updateLookupVersion => void this.submitLookupEdit(updateLookupVersion)}
         onChange={this.handleChangeLookup}
         lookupId={lookupEdit.id}
         lookupTier={lookupEdit.tier}
diff --git a/web-console/src/views/segments-view/__snapshots__/segments-view.spec.tsx.snap b/web-console/src/views/segments-view/__snapshots__/segments-view.spec.tsx.snap
index 5cb412b11c..e54a5dc7ba 100755
--- a/web-console/src/views/segments-view/__snapshots__/segments-view.spec.tsx.snap
+++ b/web-console/src/views/segments-view/__snapshots__/segments-view.spec.tsx.snap
@@ -1,7 +1,7 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`SegmentsView matches snapshot 1`] = `
-<Fragment>
+<React.Fragment>
   <div
     className="segments-view app-view"
   >
@@ -12,9 +12,9 @@ exports[`SegmentsView matches snapshot 1`] = `
         localStorageKey="segments-refresh-rate"
         onRefresh={[Function]}
       />
-      <Component>
+      <Unknown>
         Group by
-      </Component>
+      </Unknown>
       <Blueprint4.ButtonGroup>
         <Blueprint4.Button
           active={true}
@@ -434,5 +434,5 @@ exports[`SegmentsView matches snapshot 1`] = `
       subRowsKey="_subRows"
     />
   </div>
-</Fragment>
+</React.Fragment>
 `;
diff --git a/web-console/src/views/segments-view/segments-view.spec.tsx b/web-console/src/views/segments-view/segments-view.spec.tsx
index 5f19af2584..0191d05d0f 100644
--- a/web-console/src/views/segments-view/segments-view.spec.tsx
+++ b/web-console/src/views/segments-view/segments-view.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
+import { shallow } from '../../utils/shallow-renderer';
 import { SegmentsView } from '../segments-view/segments-view';
 
 describe('SegmentsView', () => {
diff --git a/web-console/src/views/segments-view/segments-view.tsx b/web-console/src/views/segments-view/segments-view.tsx
index 4f437a4004..415630bab5 100644
--- a/web-console/src/views/segments-view/segments-view.tsx
+++ b/web-console/src/views/segments-view/segments-view.tsx
@@ -22,7 +22,8 @@ import classNames from 'classnames';
 import { C, L, SqlComparison, SqlExpression } from 'druid-query-toolkit';
 import * as JSONBig from 'json-bigint-native';
 import React from 'react';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import {
   ACTION_COLUMN_ID,
@@ -41,8 +42,8 @@ import {
 import { AsyncActionDialog } from '../../dialogs';
 import { SegmentTableActionDialog } from '../../dialogs/segments-table-action-dialog/segment-table-action-dialog';
 import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog';
-import { QueryWithContext } from '../../druid-models';
-import { Capabilities, CapabilitiesMode } from '../../helpers';
+import type { QueryWithContext } from '../../druid-models';
+import type { Capabilities, CapabilitiesMode } from '../../helpers';
 import {
   booleanCustomTableFilter,
   BooleanFilterInput,
@@ -52,6 +53,7 @@ import {
   STANDARD_TABLE_PAGE_SIZE_OPTIONS,
 } from '../../react-table';
 import { Api } from '../../singletons';
+import type { NumberLike } from '../../utils';
 import {
   compact,
   deepGet,
@@ -62,13 +64,12 @@ import {
   isNumberLikeNaN,
   LocalStorageBackedVisibility,
   LocalStorageKeys,
-  NumberLike,
   queryDruidSql,
   QueryManager,
   QueryState,
   twoLines,
 } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
 
 import './segments-view.scss';
 
diff --git a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
index 19121a8a13..bfec768131 100644
--- a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
+++ b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
@@ -7,9 +7,9 @@ exports[`ServicesView renders data 1`] = `
   <Memo(ViewControlBar)
     label="Services"
   >
-    <Component>
+    <Unknown>
       Group by
-    </Component>
+    </Unknown>
     <Blueprint4.ButtonGroup>
       <Blueprint4.Button
         active={true}
diff --git a/web-console/src/views/services-view/services-view.spec.tsx b/web-console/src/views/services-view/services-view.spec.tsx
index dc3c678113..212ed5b12a 100644
--- a/web-console/src/views/services-view/services-view.spec.tsx
+++ b/web-console/src/views/services-view/services-view.spec.tsx
@@ -16,11 +16,11 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { Capabilities } from '../../helpers';
 import { QueryState } from '../../utils';
+import { shallow } from '../../utils/shallow-renderer';
 
 import { ServicesView } from './services-view';
 
diff --git a/web-console/src/views/services-view/services-view.tsx b/web-console/src/views/services-view/services-view.tsx
index d3e4ce9d43..636232cf7d 100644
--- a/web-console/src/views/services-view/services-view.tsx
+++ b/web-console/src/views/services-view/services-view.tsx
@@ -20,7 +20,8 @@ import { Button, ButtonGroup, Intent, Label, MenuItem } from '@blueprintjs/core'
 import { IconNames } from '@blueprintjs/icons';
 import { sum } from 'd3-array';
 import React from 'react';
-import ReactTable, { Filter } from 'react-table';
+import type { Filter } from 'react-table';
+import ReactTable from 'react-table';
 
 import {
   ACTION_COLUMN_ID,
@@ -34,10 +35,11 @@ import {
   ViewControlBar,
 } from '../../components';
 import { AsyncActionDialog } from '../../dialogs';
-import { QueryWithContext } from '../../druid-models';
-import { Capabilities, CapabilitiesMode } from '../../helpers';
+import type { QueryWithContext } from '../../druid-models';
+import type { Capabilities, CapabilitiesMode } from '../../helpers';
 import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
+import type { NumberLike } from '../../utils';
 import {
   deepGet,
   filterMap,
@@ -47,14 +49,13 @@ import {
   LocalStorageBackedVisibility,
   LocalStorageKeys,
   lookupBy,
-  NumberLike,
   oneOf,
   pluralIfNeeded,
   queryDruidSql,
   QueryManager,
   QueryState,
 } from '../../utils';
-import { BasicAction } from '../../utils/basic-action';
+import type { BasicAction } from '../../utils/basic-action';
 
 import './services-view.scss';
 
diff --git a/web-console/src/views/sql-data-loader-view/column-actions/column-actions.tsx b/web-console/src/views/sql-data-loader-view/column-actions/column-actions.tsx
index 363a6e290b..e6f62706d3 100644
--- a/web-console/src/views/sql-data-loader-view/column-actions/column-actions.tsx
+++ b/web-console/src/views/sql-data-loader-view/column-actions/column-actions.tsx
@@ -19,11 +19,13 @@
 import { Button, FormGroup, Menu, MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
-import { F, QueryResult, SqlExpression } from 'druid-query-toolkit';
+import type { QueryResult, SqlExpression } from 'druid-query-toolkit';
+import { F } from 'druid-query-toolkit';
 import React from 'react';
 
 import { possibleDruidFormatForValues, TIME_COLUMN } from '../../../druid-models';
-import { convertToGroupByExpression, oneOf, QueryAction, timeFormatToSql } from '../../../utils';
+import type { QueryAction } from '../../../utils';
+import { convertToGroupByExpression, oneOf, timeFormatToSql } from '../../../utils';
 import { TimeFloorMenuItem } from '../../workbench-view/time-floor-menu-item/time-floor-menu-item';
 
 import './column-actions.scss';
diff --git a/web-console/src/views/sql-data-loader-view/column-editor/column-editor.tsx b/web-console/src/views/sql-data-loader-view/column-editor/column-editor.tsx
index 9fe9f073b2..e431e447e5 100644
--- a/web-console/src/views/sql-data-loader-view/column-editor/column-editor.tsx
+++ b/web-console/src/views/sql-data-loader-view/column-editor/column-editor.tsx
@@ -19,7 +19,8 @@
 import { Button, FormGroup, InputGroup, Intent, Menu, MenuItem, Position } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
-import { QueryResult, SqlExpression, SqlFunction } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
+import { SqlExpression, SqlFunction } from 'druid-query-toolkit';
 import React, { useState } from 'react';
 
 import { AppToaster } from '../../../singletons';
diff --git a/web-console/src/views/sql-data-loader-view/destination-dialog/destination-dialog.tsx b/web-console/src/views/sql-data-loader-view/destination-dialog/destination-dialog.tsx
index 3ab3ed126b..b098a959ef 100644
--- a/web-console/src/views/sql-data-loader-view/destination-dialog/destination-dialog.tsx
+++ b/web-console/src/views/sql-data-loader-view/destination-dialog/destination-dialog.tsx
@@ -19,7 +19,8 @@
 import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
 import React, { useEffect, useState } from 'react';
 
-import { DestinationInfo, getDestinationInfo, IngestQueryPattern } from '../../../druid-models';
+import type { DestinationInfo, IngestQueryPattern } from '../../../druid-models';
+import { getDestinationInfo } from '../../../druid-models';
 import { DestinationForm } from '../destination-form/destination-form';
 
 import './destination-dialog.scss';
diff --git a/web-console/src/views/sql-data-loader-view/destination-form/destination-form.tsx b/web-console/src/views/sql-data-loader-view/destination-form/destination-form.tsx
index e0762b477c..64712105da 100644
--- a/web-console/src/views/sql-data-loader-view/destination-form/destination-form.tsx
+++ b/web-console/src/views/sql-data-loader-view/destination-form/destination-form.tsx
@@ -30,7 +30,7 @@ import { Tooltip2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React, { useState } from 'react';
 
-import { DestinationInfo, DestinationMode } from '../../../druid-models';
+import type { DestinationInfo, DestinationMode } from '../../../druid-models';
 
 import './destination-form.scss';
 
diff --git a/web-console/src/views/sql-data-loader-view/ingestion-progress-dialog/ingestion-progress-dialog.tsx b/web-console/src/views/sql-data-loader-view/ingestion-progress-dialog/ingestion-progress-dialog.tsx
index b7c8480e77..da9e084a26 100644
--- a/web-console/src/views/sql-data-loader-view/ingestion-progress-dialog/ingestion-progress-dialog.tsx
+++ b/web-console/src/views/sql-data-loader-view/ingestion-progress-dialog/ingestion-progress-dialog.tsx
@@ -22,7 +22,7 @@ import classNames from 'classnames';
 import { T } from 'druid-query-toolkit';
 import React, { useState } from 'react';
 
-import { Execution, QueryWithContext } from '../../../druid-models';
+import type { Execution, QueryWithContext } from '../../../druid-models';
 import { executionBackgroundStatusCheck, reattachTaskExecution } from '../../../helpers';
 import { useQueryManager } from '../../../hooks';
 import { ExecutionProgressBarPane } from '../../workbench-view/execution-progress-bar-pane/execution-progress-bar-pane';
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/column-list/column-list.tsx b/web-console/src/views/sql-data-loader-view/schema-step/column-list/column-list.tsx
index a09376aae5..0e28bb85f3 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/column-list/column-list.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/column-list/column-list.tsx
@@ -19,7 +19,7 @@
 import { Icon } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
-import { QueryResult, SqlExpression } from 'druid-query-toolkit';
+import type { QueryResult, SqlExpression } from 'druid-query-toolkit';
 import React, { useMemo } from 'react';
 
 import { LearnMore, PopoverText } from '../../../../components';
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/column-list/expression-entry/expression-entry.tsx b/web-console/src/views/sql-data-loader-view/schema-step/column-list/expression-entry/expression-entry.tsx
index 3a50976cc5..e345cfab62 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/column-list/expression-entry/expression-entry.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/column-list/expression-entry/expression-entry.tsx
@@ -18,7 +18,8 @@
 
 import { Icon } from '@blueprintjs/core';
 import classNames from 'classnames';
-import { Column, QueryResult, SqlColumn } from 'druid-query-toolkit';
+import type { Column, QueryResult } from 'druid-query-toolkit';
+import { SqlColumn } from 'druid-query-toolkit';
 import React from 'react';
 
 import { columnToIcon } from '../../../../../utils';
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/preview-table/preview-table.tsx b/web-console/src/views/sql-data-loader-view/schema-step/preview-table/preview-table.tsx
index aab5d9e4c9..810bc3bd74 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/preview-table/preview-table.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/preview-table/preview-table.tsx
@@ -20,20 +20,17 @@ import { Icon } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
-import { Column, QueryResult, SqlAlias, SqlQuery, SqlStar } from 'druid-query-toolkit';
+import type { Column, QueryResult, SqlQuery } from 'druid-query-toolkit';
+import { SqlAlias, SqlStar } from 'druid-query-toolkit';
 import React, { useState } from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { BracedText, Deferred, TableCell } from '../../../../components';
 import { CellFilterMenu } from '../../../../components/cell-filter-menu/cell-filter-menu';
 import { ShowValueDialog } from '../../../../dialogs/show-value-dialog/show-value-dialog';
-import {
-  columnToIcon,
-  columnToWidth,
-  filterMap,
-  getNumericColumnBraces,
-  QueryAction,
-} from '../../../../utils';
+import type { QueryAction } from '../../../../utils';
+import { columnToIcon, columnToWidth, filterMap, getNumericColumnBraces } from '../../../../utils';
 
 import './preview-table.scss';
 
@@ -142,7 +139,7 @@ export const PreviewTable = React.memo(function PreviewTable(props: PreviewTable
             className: columnClassName,
             width: columnToWidth(column),
             accessor: String(i),
-            Cell(row) {
+            Cell(row: RowRenderProps) {
               const value = row.value;
               return (
                 <div>
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/rollup-analysis-pane/rollup-analysis-pane.tsx b/web-console/src/views/sql-data-loader-view/schema-step/rollup-analysis-pane/rollup-analysis-pane.tsx
index f6112b26b8..e11dfb57fe 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/rollup-analysis-pane/rollup-analysis-pane.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/rollup-analysis-pane/rollup-analysis-pane.tsx
@@ -18,11 +18,12 @@
 
 import { Button, Callout, Intent, Tag } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { CancelToken } from 'axios';
-import { F, QueryResult, SqlExpression, SqlFunction, SqlQuery } from 'druid-query-toolkit';
+import type { CancelToken } from 'axios';
+import type { QueryResult, SqlQuery } from 'druid-query-toolkit';
+import { F, SqlExpression, SqlFunction } from 'druid-query-toolkit';
 import React, { useEffect } from 'react';
 
-import { Execution } from '../../../../druid-models';
+import type { Execution } from '../../../../druid-models';
 import { executionBackgroundStatusCheck, submitTaskQuery } from '../../../../helpers';
 import { useQueryManager } from '../../../../hooks';
 import { filterMap, formatPercentClapped, IntermediateQueryState } from '../../../../utils';
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
index d58e892cb0..0c9de245d5 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
@@ -32,20 +32,20 @@ import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import { select, selectAll } from 'd3-selection';
-import { C, F, QueryResult, QueryRunner, SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
+import { C, F, QueryRunner, SqlExpression, SqlQuery } from 'druid-query-toolkit';
 import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
 
 import { ClearableInput, LearnMore, Loader } from '../../../components';
 import { AsyncActionDialog } from '../../../dialogs';
+import type { Execution, IngestQueryPattern } from '../../../druid-models';
 import {
   changeQueryPatternExpression,
-  Execution,
   externalConfigToTableExpression,
   fitIngestQueryPattern,
   getDestinationMode,
   getQueryPatternExpression,
   getQueryPatternExpressionType,
-  IngestQueryPattern,
   ingestQueryPatternToQuery,
   possibleDruidFormatForValues,
   TIME_COLUMN,
@@ -59,6 +59,7 @@ import {
 import { useLastDefined, usePermanentCallback, useQueryManager } from '../../../hooks';
 import { getLink } from '../../../links';
 import { AppToaster } from '../../../singletons';
+import type { QueryAction } from '../../../utils';
 import {
   caseInsensitiveContains,
   change,
@@ -66,7 +67,6 @@ import {
   DruidError,
   filterMap,
   oneOf,
-  QueryAction,
   queryDruidSql,
   sampleDataToQuery,
   tickIcon,
@@ -239,7 +239,7 @@ export interface SchemaStepProps {
   enableAnalyze: boolean;
   goToQuery: () => void;
   onBack(): void;
-  onDone(): void;
+  onDone(): void | Promise<void>;
   extraCallout?: JSX.Element;
 }
 
@@ -447,6 +447,7 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
   useEffect(() => {
     if (!previewResultState.data) return;
     lastWorkingQueryPattern.current = ingestQueryPattern;
+    // eslint-disable-next-line react-hooks/exhaustive-deps -- excluding 'ingestQueryPattern'
   }, [previewResultState]);
 
   const unusedColumns = ingestQueryPattern
@@ -896,7 +897,7 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
                 icon={IconNames.CLOUD_UPLOAD}
                 text="Start loading data"
                 intent={Intent.PRIMARY}
-                onClick={onDone}
+                onClick={() => void onDone()}
               />
             </div>
           </div>
diff --git a/web-console/src/views/sql-data-loader-view/sql-data-loader-view.tsx b/web-console/src/views/sql-data-loader-view/sql-data-loader-view.tsx
index e2216719dd..743fc429f1 100644
--- a/web-console/src/views/sql-data-loader-view/sql-data-loader-view.tsx
+++ b/web-console/src/views/sql-data-loader-view/sql-data-loader-view.tsx
@@ -16,20 +16,20 @@
  * limitations under the License.
  */
 
-import { Card, Icon, IconName, Intent } from '@blueprintjs/core';
+import type { IconName } from '@blueprintjs/core';
+import { Card, Icon, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { SqlQuery } from 'druid-query-toolkit';
 import React, { useState } from 'react';
 
+import type { ExternalConfig, QueryContext, QueryWithContext } from '../../druid-models';
 import {
   Execution,
-  ExternalConfig,
   externalConfigToIngestQueryPattern,
   ingestQueryPatternToQuery,
-  QueryContext,
-  QueryWithContext,
 } from '../../druid-models';
-import { Capabilities, maybeGetClusterCapacity, submitTaskQuery } from '../../helpers';
+import type { Capabilities } from '../../helpers';
+import { maybeGetClusterCapacity, submitTaskQuery } from '../../helpers';
 import { useLocalStorageState } from '../../hooks';
 import { AppToaster } from '../../singletons';
 import { deepDelete, LocalStorageKeys } from '../../utils';
diff --git a/web-console/src/views/sql-data-loader-view/title-frame/title-frame.tsx b/web-console/src/views/sql-data-loader-view/title-frame/title-frame.tsx
index c037d4e890..7ef6a163f9 100644
--- a/web-console/src/views/sql-data-loader-view/title-frame/title-frame.tsx
+++ b/web-console/src/views/sql-data-loader-view/title-frame/title-frame.tsx
@@ -17,7 +17,8 @@
  */
 
 import classNames from 'classnames';
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import './title-frame.scss';
 
diff --git a/web-console/src/views/workbench-view/capacity-alert/capacity-alert.tsx b/web-console/src/views/workbench-view/capacity-alert/capacity-alert.tsx
index ae786b71ae..054e54f3ea 100644
--- a/web-console/src/views/workbench-view/capacity-alert/capacity-alert.tsx
+++ b/web-console/src/views/workbench-view/capacity-alert/capacity-alert.tsx
@@ -20,7 +20,7 @@ import { Alert, Code, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
-import { CapacityInfo } from '../../../druid-models';
+import type { CapacityInfo } from '../../../druid-models';
 import { formatInteger } from '../../../utils';
 
 export interface CapacityAlertProps {
diff --git a/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap b/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
index 33b2012eb0..98259aad6b 100644
--- a/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
@@ -13,13 +13,11 @@ exports[`ColumnTree matches snapshot 1`] = `
     value={0}
   >
     <option
-      key="0"
       value={0}
     >
       druid
     </option>
     <option
-      key="1"
       value={1}
     >
       sys
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree-menu/number-menu-items/number-menu-items.tsx b/web-console/src/views/workbench-view/column-tree/column-tree-menu/number-menu-items/number-menu-items.tsx
index 3be7164570..07970fa6b6 100644
--- a/web-console/src/views/workbench-view/column-tree/column-tree-menu/number-menu-items/number-menu-items.tsx
+++ b/web-console/src/views/workbench-view/column-tree/column-tree-menu/number-menu-items/number-menu-items.tsx
@@ -18,7 +18,8 @@
 
 import { MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { C, F, L, SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import type { SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import { C, F, L } from 'druid-query-toolkit';
 import React from 'react';
 
 import { prettyPrintSql } from '../../../../../utils';
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree-menu/string-menu-items/string-menu-items.tsx b/web-console/src/views/workbench-view/column-tree/column-tree-menu/string-menu-items/string-menu-items.tsx
index 04cc2fe7fd..04382efb15 100644
--- a/web-console/src/views/workbench-view/column-tree/column-tree-menu/string-menu-items/string-menu-items.tsx
+++ b/web-console/src/views/workbench-view/column-tree/column-tree-menu/string-menu-items/string-menu-items.tsx
@@ -18,7 +18,8 @@
 
 import { MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { C, F, N, SqlExpression, SqlJoinPart, SqlQuery, T } from 'druid-query-toolkit';
+import type { SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import { C, F, N, SqlJoinPart, T } from 'druid-query-toolkit';
 import React from 'react';
 
 import { EMPTY_LITERAL, prettyPrintSql } from '../../../../../utils';
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree-menu/time-menu-items/time-menu-items.tsx b/web-console/src/views/workbench-view/column-tree/column-tree-menu/time-menu-items/time-menu-items.tsx
index e9517c0097..c6919afc33 100644
--- a/web-console/src/views/workbench-view/column-tree/column-tree-menu/time-menu-items/time-menu-items.tsx
+++ b/web-console/src/views/workbench-view/column-tree/column-tree-menu/time-menu-items/time-menu-items.tsx
@@ -18,7 +18,8 @@
 
 import { MenuDivider, MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { C, F, SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import type { SqlQuery } from 'druid-query-toolkit';
+import { C, F, SqlExpression } from 'druid-query-toolkit';
 import React from 'react';
 
 import { prettyPrintSql } from '../../../../../utils';
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree.spec.tsx b/web-console/src/views/workbench-view/column-tree/column-tree.spec.tsx
index f06e02a98b..98baef9160 100644
--- a/web-console/src/views/workbench-view/column-tree/column-tree.spec.tsx
+++ b/web-console/src/views/workbench-view/column-tree/column-tree.spec.tsx
@@ -17,10 +17,10 @@
  */
 
 import { SqlQuery } from 'druid-query-toolkit';
-import { shallow } from 'enzyme';
 import React from 'react';
 
-import { ColumnMetadata } from '../../../utils';
+import type { ColumnMetadata } from '../../../utils';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ColumnTree } from './column-tree';
 
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree.tsx b/web-console/src/views/workbench-view/column-tree/column-tree.tsx
index d72f53d1b7..11ce577c20 100644
--- a/web-console/src/views/workbench-view/column-tree/column-tree.tsx
+++ b/web-console/src/views/workbench-view/column-tree/column-tree.tsx
@@ -16,32 +16,28 @@
  * limitations under the License.
  */
 
-import { HTMLSelect, Menu, MenuItem, Position, Tree, TreeNodeInfo } from '@blueprintjs/core';
+import type { TreeNodeInfo } from '@blueprintjs/core';
+import { HTMLSelect, Menu, MenuItem, Position, Tree } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
+import type { SqlExpression } from 'druid-query-toolkit';
 import {
   C,
   F,
   N,
   SqlColumn,
   SqlComparison,
-  SqlExpression,
   SqlJoinPart,
   SqlQuery,
   SqlTable,
   T,
 } from 'druid-query-toolkit';
-import React, { ChangeEvent } from 'react';
+import type { ChangeEvent } from 'react';
+import React from 'react';
 
 import { Deferred, Loader } from '../../../components';
-import {
-  ColumnMetadata,
-  copyAndAlert,
-  dataTypeToIcon,
-  groupBy,
-  oneOf,
-  prettyPrintSql,
-} from '../../../utils';
+import type { ColumnMetadata } from '../../../utils';
+import { copyAndAlert, dataTypeToIcon, groupBy, oneOf, prettyPrintSql } from '../../../utils';
 
 import { NumberMenuItems, StringMenuItems, TimeMenuItems } from './column-tree-menu';
 
diff --git a/web-console/src/views/workbench-view/connect-external-data-dialog/connect-external-data-dialog.tsx b/web-console/src/views/workbench-view/connect-external-data-dialog/connect-external-data-dialog.tsx
index e043cf1340..278743da54 100644
--- a/web-console/src/views/workbench-view/connect-external-data-dialog/connect-external-data-dialog.tsx
+++ b/web-console/src/views/workbench-view/connect-external-data-dialog/connect-external-data-dialog.tsx
@@ -17,10 +17,10 @@
  */
 
 import { Classes, Dialog } from '@blueprintjs/core';
-import { SqlExpression } from 'druid-query-toolkit';
+import type { SqlExpression } from 'druid-query-toolkit';
 import React, { useState } from 'react';
 
-import { ExternalConfig, InputFormat, InputSource } from '../../../druid-models';
+import type { ExternalConfig, InputFormat, InputSource } from '../../../druid-models';
 import { InputFormatStep } from '../input-format-step/input-format-step';
 import { InputSourceStep } from '../input-source-step/input-source-step';
 
diff --git a/web-console/src/views/workbench-view/demo-queries.ts b/web-console/src/views/workbench-view/demo-queries.ts
index 7345290938..6d36b7261d 100644
--- a/web-console/src/views/workbench-view/demo-queries.ts
+++ b/web-console/src/views/workbench-view/demo-queries.ts
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import { TabEntry, WorkbenchQuery } from '../../druid-models';
+import type { TabEntry } from '../../druid-models';
+import { WorkbenchQuery } from '../../druid-models';
 
 const BASE_QUERY = WorkbenchQuery.blank();
 
diff --git a/web-console/src/views/workbench-view/execution-details-dialog/execution-details-dialog.tsx b/web-console/src/views/workbench-view/execution-details-dialog/execution-details-dialog.tsx
index 61abc6ea7a..1a255fccc7 100644
--- a/web-console/src/views/workbench-view/execution-details-dialog/execution-details-dialog.tsx
+++ b/web-console/src/views/workbench-view/execution-details-dialog/execution-details-dialog.tsx
@@ -19,8 +19,8 @@
 import { Button, Classes, Dialog } from '@blueprintjs/core';
 import React from 'react';
 
-import { Execution } from '../../../druid-models';
-import { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
+import type { Execution } from '../../../druid-models';
+import type { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
 import { ExecutionDetailsPaneLoader } from '../execution-details-pane-loader/execution-details-pane-loader';
 
 import './execution-details-dialog.scss';
diff --git a/web-console/src/views/workbench-view/execution-details-pane-loader/execution-details-pane-loader.tsx b/web-console/src/views/workbench-view/execution-details-pane-loader/execution-details-pane-loader.tsx
index 5f6cba93f9..573c797957 100644
--- a/web-console/src/views/workbench-view/execution-details-pane-loader/execution-details-pane-loader.tsx
+++ b/web-console/src/views/workbench-view/execution-details-pane-loader/execution-details-pane-loader.tsx
@@ -19,14 +19,12 @@
 import React from 'react';
 
 import { Loader } from '../../../components';
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { getTaskExecution } from '../../../helpers';
 import { useInterval, useQueryManager } from '../../../hooks';
 import { QueryState } from '../../../utils';
-import {
-  ExecutionDetailsPane,
-  ExecutionDetailsTab,
-} from '../execution-details-pane/execution-details-pane';
+import type { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
+import { ExecutionDetailsPane } from '../execution-details-pane/execution-details-pane';
 
 export interface ExecutionDetailsPaneLoaderProps {
   id: string;
diff --git a/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.spec.tsx b/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.spec.tsx
index c1bddb6e8e..053bc7a583 100644
--- a/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.spec.tsx
+++ b/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { EXECUTION_INGEST_ERROR } from '../../../druid-models/execution/execution-ingest-error.mock';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ExecutionDetailsPane } from './execution-details-pane';
 
diff --git a/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.tsx b/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.tsx
index a19f901e73..a0729ec0fe 100644
--- a/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-details-pane/execution-details-pane.tsx
@@ -21,7 +21,7 @@ import * as JSONBig from 'json-bigint-native';
 import React, { useState } from 'react';
 
 import { FancyTabPane } from '../../../components';
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { ExecutionErrorPane } from '../execution-error-pane/execution-error-pane';
 import { ExecutionStagesPane } from '../execution-stages-pane/execution-stages-pane';
 import { ExecutionWarningsPane } from '../execution-warnings-pane/execution-warnings-pane';
diff --git a/web-console/src/views/workbench-view/execution-error-pane/__snapshots__/execution-error-pane.spec.tsx.snap b/web-console/src/views/workbench-view/execution-error-pane/__snapshots__/execution-error-pane.spec.tsx.snap
index 025c9a2946..e03498aa5b 100644
--- a/web-console/src/views/workbench-view/execution-error-pane/__snapshots__/execution-error-pane.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/execution-error-pane/__snapshots__/execution-error-pane.spec.tsx.snap
@@ -8,12 +8,14 @@ exports[`ExecutionErrorPane matches snapshot 1`] = `
   <p
     className="error-message-text"
   >
-    <Memo(ExternalLink)
-      href="https://druid.apache.org/docs/latest/multi-stage-query/reference.html#error_TooManyWarnings"
-    >
-      TooManyWarnings
-    </Memo(ExternalLink)>
-    : 
+    <React.Fragment>
+      <Memo(ExternalLink)
+        href="https://druid.apache.org/docs/latest/multi-stage-query/reference.html#error_TooManyWarnings"
+      >
+        TooManyWarnings
+      </Memo(ExternalLink)>
+      : 
+    </React.Fragment>
     Too many warnings of type CannotParseExternalData generated (max = 10)
   </p>
   <div>
@@ -21,11 +23,13 @@ exports[`ExecutionErrorPane matches snapshot 1`] = `
     <Memo(ClickToCopy)
       text="query-955fa5a2-0ae6-4912-bc39-cc9fc012de5a"
     />
-     (on host: 
-    <Memo(ClickToCopy)
-      text="localhost"
-    />
-    )
+    <React.Fragment>
+       (on host: 
+      <Memo(ClickToCopy)
+        text="localhost"
+      />
+      )
+    </React.Fragment>
   </div>
   <div>
     Debug: 
diff --git a/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.spec.tsx b/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.spec.tsx
index c9669840a6..ae7c0904e8 100644
--- a/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.spec.tsx
+++ b/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { EXECUTION_INGEST_ERROR } from '../../../druid-models/execution/execution-ingest-error.mock';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ExecutionErrorPane } from './execution-error-pane';
 
diff --git a/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.tsx b/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.tsx
index 967cea3b0e..f91d7bf9d5 100644
--- a/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-error-pane/execution-error-pane.tsx
@@ -22,7 +22,7 @@ import React, { useState } from 'react';
 
 import { ClickToCopy, ExternalLink } from '../../../components';
 import { ShowValueDialog } from '../../../dialogs/show-value-dialog/show-value-dialog';
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { getLink } from '../../../links';
 import { downloadQueryDetailArchive } from '../../../utils';
 
diff --git a/web-console/src/views/workbench-view/execution-progress-bar-pane/__snapshots__/execution-progress-bar-pane.spec.tsx.snap b/web-console/src/views/workbench-view/execution-progress-bar-pane/__snapshots__/execution-progress-bar-pane.spec.tsx.snap
index 5292023812..f2e9970e58 100644
--- a/web-console/src/views/workbench-view/execution-progress-bar-pane/__snapshots__/execution-progress-bar-pane.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/execution-progress-bar-pane/__snapshots__/execution-progress-bar-pane.spec.tsx.snap
@@ -4,20 +4,21 @@ exports[`ExecutionProgressBarPane matches snapshot 1`] = `
 <div
   className="execution-progress-bar-pane"
 >
-  <Component>
+  <Unknown>
     Query complete, waiting for segments to be loaded...
-     
-    <span
-      className="cancel"
-      onClick={[Function]}
-    >
-      (stop waiting)
-    </span>
-  </Component>
+    <React.Fragment>
+       
+      <span
+        className="cancel"
+        onClick={[Function]}
+      >
+        (stop waiting)
+      </span>
+    </React.Fragment>
+  </Unknown>
   <Blueprint4.ProgressBar
     className="overall"
     intent="primary"
-    key="actual"
   />
 </div>
 `;
diff --git a/web-console/src/views/workbench-view/execution-progress-bar-pane/execution-progress-bar-pane.spec.tsx b/web-console/src/views/workbench-view/execution-progress-bar-pane/execution-progress-bar-pane.spec.tsx
index a778abd78e..03362a3990 100644
--- a/web-console/src/views/workbench-view/execution-progress-bar-pane/execution-progress-bar-pane.spec.tsx
+++ b/web-console/src/views/workbench-view/execution-progress-bar-pane/execution-progress-bar-pane.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { EXECUTION_INGEST_COMPLETE } from '../../../druid-models/mocks';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ExecutionProgressBarPane } from './execution-progress-bar-pane';
 
diff --git a/web-console/src/views/workbench-view/execution-progress-pane/execution-progress-pane.tsx b/web-console/src/views/workbench-view/execution-progress-pane/execution-progress-pane.tsx
index 42ed0ab2a0..2cc86f8310 100644
--- a/web-console/src/views/workbench-view/execution-progress-pane/execution-progress-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-progress-pane/execution-progress-pane.tsx
@@ -19,7 +19,7 @@
 import classNames from 'classnames';
 import React, { useState } from 'react';
 
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { ExecutionProgressBarPane } from '../execution-progress-bar-pane/execution-progress-bar-pane';
 import { ExecutionStagesPane } from '../execution-stages-pane/execution-stages-pane';
 
diff --git a/web-console/src/views/workbench-view/execution-stages-pane-loader/execution-stages-pane-loader.tsx b/web-console/src/views/workbench-view/execution-stages-pane-loader/execution-stages-pane-loader.tsx
index eb700fe6ae..7529ba9b45 100644
--- a/web-console/src/views/workbench-view/execution-stages-pane-loader/execution-stages-pane-loader.tsx
+++ b/web-console/src/views/workbench-view/execution-stages-pane-loader/execution-stages-pane-loader.tsx
@@ -19,7 +19,7 @@
 import React from 'react';
 
 import { Loader } from '../../../components';
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { getTaskExecution } from '../../../helpers';
 import { useInterval, useQueryManager } from '../../../hooks';
 import { ExecutionStagesPane } from '../execution-stages-pane/execution-stages-pane';
diff --git a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.spec.tsx b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.spec.tsx
index 2fd1da98c1..2b2dd3ec0e 100644
--- a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.spec.tsx
+++ b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { EXECUTION_INGEST_COMPLETE } from '../../../druid-models/mocks';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ExecutionStagesPane } from './execution-stages-pane';
 
diff --git a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
index 7c5a593424..9464de13ea 100644
--- a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
@@ -21,22 +21,22 @@ import { IconNames } from '@blueprintjs/icons';
 import { Tooltip2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import React from 'react';
-import ReactTable, { Column } from 'react-table';
+import type { Column } from 'react-table';
+import ReactTable from 'react-table';
 
 import { BracedText, TableClickableCell } from '../../../components';
-import {
+import type {
   ChannelCounterName,
   ChannelFields,
   ClusterBy,
   CounterName,
   Execution,
-  formatClusterBy,
   SimpleWideCounter,
   StageDefinition,
-  Stages,
-  summarizeInputSource,
 } from '../../../druid-models';
+import { formatClusterBy, Stages, summarizeInputSource } from '../../../druid-models';
 import { DEFAULT_TABLE_CLASS_NAME } from '../../../react-table';
+import type { NumberLike } from '../../../utils';
 import {
   capitalizeFirst,
   clamp,
@@ -47,7 +47,6 @@ import {
   formatDurationWithMs,
   formatInteger,
   formatPercent,
-  NumberLike,
   oneOf,
   twoLines,
 } from '../../../utils';
diff --git a/web-console/src/views/workbench-view/execution-summary-panel/execution-summary-panel.tsx b/web-console/src/views/workbench-view/execution-summary-panel/execution-summary-panel.tsx
index d268861685..80066c0c10 100644
--- a/web-console/src/views/workbench-view/execution-summary-panel/execution-summary-panel.tsx
+++ b/web-console/src/views/workbench-view/execution-summary-panel/execution-summary-panel.tsx
@@ -21,7 +21,7 @@ import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import React from 'react';
 
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { downloadQueryResults, formatDurationHybrid, pluralIfNeeded } from '../../../utils';
 
 import './execution-summary-panel.scss';
diff --git a/web-console/src/views/workbench-view/execution-timer-panel/execution-timer-panel.tsx b/web-console/src/views/workbench-view/execution-timer-panel/execution-timer-panel.tsx
index bc539559ec..3202240ee2 100644
--- a/web-console/src/views/workbench-view/execution-timer-panel/execution-timer-panel.tsx
+++ b/web-console/src/views/workbench-view/execution-timer-panel/execution-timer-panel.tsx
@@ -20,7 +20,7 @@ import { Button, ButtonGroup } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 import { useInterval } from '../../../hooks';
 import { formatDurationHybrid } from '../../../utils';
 import { CancelQueryDialog } from '../cancel-query-dialog/cancel-query-dialog';
diff --git a/web-console/src/views/workbench-view/execution-warnings-pane/execution-warnings-pane.tsx b/web-console/src/views/workbench-view/execution-warnings-pane/execution-warnings-pane.tsx
index ddd87afee0..baf93811d6 100644
--- a/web-console/src/views/workbench-view/execution-warnings-pane/execution-warnings-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-warnings-pane/execution-warnings-pane.tsx
@@ -18,7 +18,7 @@
 
 import React from 'react';
 
-import { Execution } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
 
 import { WarningCallout } from './warning-callout';
 
diff --git a/web-console/src/views/workbench-view/execution-warnings-pane/warning-callout.tsx b/web-console/src/views/workbench-view/execution-warnings-pane/warning-callout.tsx
index 1c2103c971..cc60375651 100644
--- a/web-console/src/views/workbench-view/execution-warnings-pane/warning-callout.tsx
+++ b/web-console/src/views/workbench-view/execution-warnings-pane/warning-callout.tsx
@@ -20,7 +20,7 @@ import { Button, Callout, Collapse } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React, { useState } from 'react';
 
-import { ExecutionError } from '../../../druid-models';
+import type { ExecutionError } from '../../../druid-models';
 
 import './warning-callout.scss';
 
diff --git a/web-console/src/views/workbench-view/explain-dialog/__snapshots__/explain-dialog.spec.tsx.snap b/web-console/src/views/workbench-view/explain-dialog/__snapshots__/explain-dialog.spec.tsx.snap
index e581bbd3c4..53c2f5196c 100644
--- a/web-console/src/views/workbench-view/explain-dialog/__snapshots__/explain-dialog.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/explain-dialog/__snapshots__/explain-dialog.spec.tsx.snap
@@ -106,7 +106,6 @@ exports[`ExplainDialog matches snapshot on some data (many queries) 1`] = `
       <Blueprint4.Tab
         disabled={false}
         id={0}
-        key="0"
         panel={
           <div
             className="query-explanation"
@@ -205,7 +204,6 @@ exports[`ExplainDialog matches snapshot on some data (many queries) 1`] = `
       <Blueprint4.Tab
         disabled={false}
         id={1}
-        key="1"
         panel={
           <div
             className="query-explanation"
diff --git a/web-console/src/views/workbench-view/explain-dialog/explain-dialog.spec.tsx b/web-console/src/views/workbench-view/explain-dialog/explain-dialog.spec.tsx
index f64f357812..f3c140e691 100644
--- a/web-console/src/views/workbench-view/explain-dialog/explain-dialog.spec.tsx
+++ b/web-console/src/views/workbench-view/explain-dialog/explain-dialog.spec.tsx
@@ -16,10 +16,11 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
-import { QueryExplanation, QueryState } from '../../../utils';
+import type { QueryExplanation } from '../../../utils';
+import { QueryState } from '../../../utils';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { ExplainDialog } from './explain-dialog';
 
diff --git a/web-console/src/views/workbench-view/explain-dialog/explain-dialog.tsx b/web-console/src/views/workbench-view/explain-dialog/explain-dialog.tsx
index a60567c994..9104b55941 100644
--- a/web-console/src/views/workbench-view/explain-dialog/explain-dialog.tsx
+++ b/web-console/src/views/workbench-view/explain-dialog/explain-dialog.tsx
@@ -32,16 +32,17 @@ import React from 'react';
 import AceEditor from 'react-ace';
 
 import { Loader } from '../../../components';
-import { DruidEngine, isEmptyContext, QueryContext, QueryWithContext } from '../../../druid-models';
+import type { DruidEngine, QueryContext, QueryWithContext } from '../../../druid-models';
+import { isEmptyContext } from '../../../druid-models';
 import { useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
+import type { QueryExplanation } from '../../../utils';
 import {
   deepGet,
   formatSignature,
   getDruidErrorMessage,
   nonEmptyArray,
   queryDruidSql,
-  QueryExplanation,
 } from '../../../utils';
 
 import './explain-dialog.scss';
diff --git a/web-console/src/views/workbench-view/flexible-query-input/flexible-query-input.tsx b/web-console/src/views/workbench-view/flexible-query-input/flexible-query-input.tsx
index 7e73f4012d..8691a622da 100644
--- a/web-console/src/views/workbench-view/flexible-query-input/flexible-query-input.tsx
+++ b/web-console/src/views/workbench-view/flexible-query-input/flexible-query-input.tsx
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { ResizeEntry } from '@blueprintjs/core';
+import type { ResizeEntry } from '@blueprintjs/core';
 import { ResizeSensor2 } from '@blueprintjs/popover2';
 import type { Ace } from 'ace-builds';
 import ace from 'ace-builds';
@@ -34,7 +34,8 @@ import {
 } from '../../../../lib/keywords';
 import { SQL_DATA_TYPES, SQL_FUNCTIONS } from '../../../../lib/sql-docs';
 import { AceEditorStateCache } from '../../../singletons/ace-editor-state-cache';
-import { ColumnMetadata, RowColumn, uniq } from '../../../utils';
+import type { ColumnMetadata, RowColumn } from '../../../utils';
+import { uniq } from '../../../utils';
 
 import './flexible-query-input.scss';
 
diff --git a/web-console/src/views/workbench-view/helper-query/helper-query.tsx b/web-console/src/views/workbench-view/helper-query/helper-query.tsx
index 25bca62c4a..cc7f638c25 100644
--- a/web-console/src/views/workbench-view/helper-query/helper-query.tsx
+++ b/web-console/src/views/workbench-view/helper-query/helper-query.tsx
@@ -20,16 +20,16 @@ import { Button, ButtonGroup, InputGroup, Menu, MenuItem } from '@blueprintjs/co
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import axios from 'axios';
-import { QueryResult, QueryRunner, SqlQuery } from 'druid-query-toolkit';
-import React, { useEffect, useRef, useState } from 'react';
+import type { QueryResult } from 'druid-query-toolkit';
+import { QueryRunner, SqlQuery } from 'druid-query-toolkit';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import { useStore } from 'zustand';
 
 import { Loader, QueryErrorPane } from '../../../components';
+import type { DruidEngine, LastExecution, QueryContext } from '../../../druid-models';
 import {
-  DruidEngine,
   Execution,
   fitExternalConfigPattern,
-  LastExecution,
-  QueryContext,
   summarizeExternalConfig,
   WorkbenchQuery,
 } from '../../../druid-models';
@@ -43,13 +43,12 @@ import { usePermanentCallback, useQueryManager } from '../../../hooks';
 import { Api } from '../../../singletons';
 import { ExecutionStateCache } from '../../../singletons/execution-state-cache';
 import { WorkbenchHistory } from '../../../singletons/workbench-history';
-import {
-  WorkbenchRunningPromise,
-  WorkbenchRunningPromises,
-} from '../../../singletons/workbench-running-promises';
-import { ColumnMetadata, DruidError, QueryAction, QueryManager, RowColumn } from '../../../utils';
+import type { WorkbenchRunningPromise } from '../../../singletons/workbench-running-promises';
+import { WorkbenchRunningPromises } from '../../../singletons/workbench-running-promises';
+import type { ColumnMetadata, QueryAction, RowColumn } from '../../../utils';
+import { DruidError, QueryManager } from '../../../utils';
 import { CapacityAlert } from '../capacity-alert/capacity-alert';
-import { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
+import type { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
 import { ExecutionErrorPane } from '../execution-error-pane/execution-error-pane';
 import { ExecutionProgressPane } from '../execution-progress-pane/execution-progress-pane';
 import { ExecutionStagesPane } from '../execution-stages-pane/execution-stages-pane';
@@ -57,10 +56,10 @@ import { ExecutionSummaryPanel } from '../execution-summary-panel/execution-summ
 import { ExecutionTimerPanel } from '../execution-timer-panel/execution-timer-panel';
 import { FlexibleQueryInput } from '../flexible-query-input/flexible-query-input';
 import { IngestSuccessPane } from '../ingest-success-pane/ingest-success-pane';
-import { useMetadataStateStore } from '../metadata-state-store';
+import { metadataStateStore } from '../metadata-state-store';
 import { ResultTablePane } from '../result-table-pane/result-table-pane';
 import { RunPanel } from '../run-panel/run-panel';
-import { useWorkStateStore } from '../work-state-store';
+import { workStateStore } from '../work-state-store';
 
 import './helper-query.scss';
 
@@ -223,7 +222,10 @@ export const HelperQuery = React.memo(function HelperQuery(props: HelperQueryPro
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [executionState.data, executionState.error]);
 
-  const incrementWorkVersion = useWorkStateStore(state => state.increment);
+  const incrementWorkVersion = useStore(
+    workStateStore,
+    useCallback(state => state.increment, []),
+  );
   useEffect(() => {
     incrementWorkVersion();
     // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -231,7 +233,10 @@ export const HelperQuery = React.memo(function HelperQuery(props: HelperQueryPro
 
   const execution = executionState.data;
 
-  const incrementMetadataVersion = useMetadataStateStore(state => state.increment);
+  const incrementMetadataVersion = useStore(
+    metadataStateStore,
+    useCallback(state => state.increment, []),
+  );
   useEffect(() => {
     if (execution?.isSuccessfulInsert()) {
       incrementMetadataVersion();
diff --git a/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.spec.tsx b/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.spec.tsx
index 2bc2ace401..85d68476d4 100644
--- a/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.spec.tsx
+++ b/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.spec.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
 import { EXECUTION_INGEST_COMPLETE } from '../../../druid-models/mocks';
+import { shallow } from '../../../utils/shallow-renderer';
 
 import { IngestSuccessPane } from './ingest-success-pane';
 
diff --git a/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.tsx b/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.tsx
index 11c0d958b9..37639ae053 100644
--- a/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.tsx
+++ b/web-console/src/views/workbench-view/ingest-success-pane/ingest-success-pane.tsx
@@ -19,9 +19,10 @@
 import { T } from 'druid-query-toolkit';
 import React from 'react';
 
-import { Execution, WorkbenchQuery } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
+import { WorkbenchQuery } from '../../../druid-models';
 import { formatDuration, pluralIfNeeded } from '../../../utils';
-import { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
+import type { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
 
 import './ingest-success-pane.scss';
 
diff --git a/web-console/src/views/workbench-view/input-format-step/input-format-step.tsx b/web-console/src/views/workbench-view/input-format-step/input-format-step.tsx
index c6fce295dd..750b44215e 100644
--- a/web-console/src/views/workbench-view/input-format-step/input-format-step.tsx
+++ b/web-console/src/views/workbench-view/input-format-step/input-format-step.tsx
@@ -18,20 +18,19 @@
 
 import { Button, Callout, FormGroup, Icon, Intent, Tag } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
-import { C, SqlExpression } from 'druid-query-toolkit';
+import type { SqlExpression } from 'druid-query-toolkit';
+import { C } from 'druid-query-toolkit';
 import React, { useState } from 'react';
 
 import { AutoForm, CenterMessage, LearnMore, Loader } from '../../../components';
+import type { InputFormat, InputSource, SignatureColumn } from '../../../druid-models';
 import {
   guessColumnTypeFromHeaderAndRows,
   guessIsArrayFromHeaderAndRows,
   INPUT_FORMAT_FIELDS,
-  InputFormat,
   inputFormatOutputsNumericStrings,
-  InputSource,
   PLACEHOLDER_TIMESTAMP_SPEC,
   possibleDruidFormatForValues,
-  SignatureColumn,
 } from '../../../druid-models';
 import { useQueryManager } from '../../../hooks';
 import { getLink } from '../../../links';
@@ -42,12 +41,8 @@ import {
   filterMap,
   timeFormatToSql,
 } from '../../../utils';
-import {
-  headerAndRowsFromSampleResponse,
-  postToSampler,
-  SampleHeaderAndRows,
-  SampleSpec,
-} from '../../../utils/sampler';
+import type { SampleHeaderAndRows, SampleSpec } from '../../../utils/sampler';
+import { headerAndRowsFromSampleResponse, postToSampler } from '../../../utils/sampler';
 import { ParseDataTable } from '../../load-data-view/parse-data-table/parse-data-table';
 
 import './input-format-step.scss';
diff --git a/web-console/src/views/workbench-view/input-source-step/example-inputs.ts b/web-console/src/views/workbench-view/input-source-step/example-inputs.ts
index a6ad104c7f..efade906eb 100644
--- a/web-console/src/views/workbench-view/input-source-step/example-inputs.ts
+++ b/web-console/src/views/workbench-view/input-source-step/example-inputs.ts
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import { InputFormat, InputSource } from '../../../druid-models';
+import type { InputFormat, InputSource } from '../../../druid-models';
 
 export interface ExampleInput {
   name: string;
diff --git a/web-console/src/views/workbench-view/input-source-step/input-source-info.tsx b/web-console/src/views/workbench-view/input-source-step/input-source-info.tsx
index dbcbf7702d..2a7e2361d5 100644
--- a/web-console/src/views/workbench-view/input-source-step/input-source-info.tsx
+++ b/web-console/src/views/workbench-view/input-source-step/input-source-info.tsx
@@ -18,7 +18,7 @@
 
 import React from 'react';
 
-import { InputSource } from '../../../druid-models';
+import type { InputSource } from '../../../druid-models';
 
 export interface InputSourceInfoProps {
   inputSource: Partial<InputSource>;
diff --git a/web-console/src/views/workbench-view/input-source-step/input-source-step.tsx b/web-console/src/views/workbench-view/input-source-step/input-source-step.tsx
index 9ea55fd0d1..c4eaf8d0af 100644
--- a/web-console/src/views/workbench-view/input-source-step/input-source-step.tsx
+++ b/web-console/src/views/workbench-view/input-source-step/input-source-step.tsx
@@ -28,21 +28,18 @@ import {
 } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
-import { QueryResult } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
 import React, { useEffect, useState } from 'react';
 
 import { AutoForm, ExternalLink } from '../../../components';
 import { ShowValueDialog } from '../../../dialogs/show-value-dialog/show-value-dialog';
+import type { Execution, ExecutionError, InputFormat, InputSource } from '../../../druid-models';
 import {
-  Execution,
-  ExecutionError,
   externalConfigToTableExpression,
   getIngestionImage,
   getIngestionTitle,
   guessInputFormat,
   INPUT_SOURCE_FIELDS,
-  InputFormat,
-  InputSource,
   PLACEHOLDER_TIMESTAMP_SPEC,
 } from '../../../druid-models';
 import {
@@ -53,7 +50,8 @@ import {
 import { useQueryManager } from '../../../hooks';
 import { UrlBaser } from '../../../singletons';
 import { filterMap, IntermediateQueryState } from '../../../utils';
-import { postToSampler, SampleSpec } from '../../../utils/sampler';
+import type { SampleSpec } from '../../../utils/sampler';
+import { postToSampler } from '../../../utils/sampler';
 
 import { EXAMPLE_INPUTS } from './example-inputs';
 import { InputSourceInfo } from './input-source-info';
diff --git a/web-console/src/views/workbench-view/max-tasks-button/__snapshots__/max-tasks-button.spec.tsx.snap b/web-console/src/views/workbench-view/max-tasks-button/__snapshots__/max-tasks-button.spec.tsx.snap
index 70c7278a75..54f3900b9e 100644
--- a/web-console/src/views/workbench-view/max-tasks-button/__snapshots__/max-tasks-button.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/max-tasks-button/__snapshots__/max-tasks-button.spec.tsx.snap
@@ -1,7 +1,7 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`MaxTasksButton matches snapshot 1`] = `
-<Fragment>
+<React.Fragment>
   <Blueprint4.Popover2
     boundary="clippingParents"
     captureDismiss={false}
@@ -140,5 +140,5 @@ exports[`MaxTasksButton matches snapshot 1`] = `
       text="Max tasks: 6 (full cluster capacity)"
     />
   </Blueprint4.Popover2>
-</Fragment>
+</React.Fragment>
 `;
diff --git a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.spec.tsx b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.spec.tsx
index 719492546c..5954c1f3f9 100644
--- a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.spec.tsx
+++ b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.spec.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { shallow } from 'enzyme';
 import React from 'react';
 
+import { shallow } from '../../../utils/shallow-renderer';
+
 import { MaxTasksButton } from './max-tasks-button';
 
 describe('MaxTasksButton', () => {
diff --git a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx
index 04c01645d5..0500dca3ba 100644
--- a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx
+++ b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx
@@ -16,18 +16,19 @@
  * limitations under the License.
  */
 
-import { Button, ButtonProps, Menu, MenuDivider, MenuItem, Position } from '@blueprintjs/core';
+import type { ButtonProps } from '@blueprintjs/core';
+import { Button, Menu, MenuDivider, MenuItem, Position } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import React, { useState } from 'react';
 
 import { NumericInputDialog } from '../../../dialogs';
+import type { QueryContext } from '../../../druid-models';
 import {
   changeMaxNumTasks,
   changeTaskAssigment,
   getMaxNumTasks,
   getTaskAssigment,
-  QueryContext,
 } from '../../../druid-models';
 import { formatInteger, tickIcon } from '../../../utils';
 
diff --git a/web-console/src/views/workbench-view/metadata-change-detector.tsx b/web-console/src/views/workbench-view/metadata-change-detector.tsx
index 3dafa6c8ee..3f8e42f7b1 100644
--- a/web-console/src/views/workbench-view/metadata-change-detector.tsx
+++ b/web-console/src/views/workbench-view/metadata-change-detector.tsx
@@ -16,9 +16,10 @@
  * limitations under the License.
  */
 
-import { useEffect } from 'react';
+import { useCallback, useEffect } from 'react';
+import { useStore } from 'zustand';
 
-import { useMetadataStateStore } from './metadata-state-store';
+import { metadataStateStore } from './metadata-state-store';
 
 export interface MetadataChangeDetectorProps {
   onChange(): void;
@@ -29,7 +30,10 @@ export const MetadataChangeDetector = function MetadataChangeDetector(
 ) {
   const { onChange } = props;
 
-  const metadataStateVersion = useMetadataStateStore(state => state.version);
+  const metadataStateVersion = useStore(
+    metadataStateStore,
+    useCallback(state => state.version, []),
+  );
   useEffect(() => {
     onChange();
     // eslint-disable-next-line react-hooks/exhaustive-deps
diff --git a/web-console/src/views/workbench-view/metadata-state-store.ts b/web-console/src/views/workbench-view/metadata-state-store.ts
index f36fd8e694..7c7669e0db 100644
--- a/web-console/src/views/workbench-view/metadata-state-store.ts
+++ b/web-console/src/views/workbench-view/metadata-state-store.ts
@@ -16,14 +16,14 @@
  * limitations under the License.
  */
 
-import create, { State } from 'zustand';
+import { createStore } from 'zustand';
 
-interface MetadataState extends State {
+interface MetadataState {
   version: number;
   increment(): void;
 }
 
-export const useMetadataStateStore = create<MetadataState>(set => ({
+export const metadataStateStore = createStore<MetadataState>(set => ({
   version: 0,
   increment: () => set(state => ({ version: state.version + 1 })),
 }));
diff --git a/web-console/src/views/workbench-view/query-tab/query-tab.tsx b/web-console/src/views/workbench-view/query-tab/query-tab.tsx
index a56e9189aa..3fe362ab48 100644
--- a/web-console/src/views/workbench-view/query-tab/query-tab.tsx
+++ b/web-console/src/views/workbench-view/query-tab/query-tab.tsx
@@ -21,18 +21,15 @@ import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import axios from 'axios';
 import classNames from 'classnames';
-import { QueryResult, QueryRunner, SqlQuery } from 'druid-query-toolkit';
+import type { QueryResult } from 'druid-query-toolkit';
+import { QueryRunner, SqlQuery } from 'druid-query-toolkit';
 import React, { useCallback, useEffect, useRef, useState } from 'react';
 import SplitterLayout from 'react-splitter-layout';
+import { useStore } from 'zustand';
 
 import { Loader, QueryErrorPane } from '../../../components';
-import {
-  DruidEngine,
-  Execution,
-  LastExecution,
-  QueryContext,
-  WorkbenchQuery,
-} from '../../../druid-models';
+import type { DruidEngine, LastExecution, QueryContext } from '../../../druid-models';
+import { Execution, WorkbenchQuery } from '../../../druid-models';
 import {
   executionBackgroundStatusCheck,
   maybeGetClusterCapacity,
@@ -43,22 +40,18 @@ import { usePermanentCallback, useQueryManager } from '../../../hooks';
 import { Api, AppToaster } from '../../../singletons';
 import { ExecutionStateCache } from '../../../singletons/execution-state-cache';
 import { WorkbenchHistory } from '../../../singletons/workbench-history';
+import type { WorkbenchRunningPromise } from '../../../singletons/workbench-running-promises';
+import { WorkbenchRunningPromises } from '../../../singletons/workbench-running-promises';
+import type { ColumnMetadata, QueryAction, RowColumn } from '../../../utils';
 import {
-  WorkbenchRunningPromise,
-  WorkbenchRunningPromises,
-} from '../../../singletons/workbench-running-promises';
-import {
-  ColumnMetadata,
   DruidError,
   localStorageGet,
   LocalStorageKeys,
   localStorageSet,
-  QueryAction,
   QueryManager,
-  RowColumn,
 } from '../../../utils';
 import { CapacityAlert } from '../capacity-alert/capacity-alert';
-import { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
+import type { ExecutionDetailsTab } from '../execution-details-pane/execution-details-pane';
 import { ExecutionErrorPane } from '../execution-error-pane/execution-error-pane';
 import { ExecutionProgressPane } from '../execution-progress-pane/execution-progress-pane';
 import { ExecutionStagesPane } from '../execution-stages-pane/execution-stages-pane';
@@ -67,10 +60,10 @@ import { ExecutionTimerPanel } from '../execution-timer-panel/execution-timer-pa
 import { FlexibleQueryInput } from '../flexible-query-input/flexible-query-input';
 import { HelperQuery } from '../helper-query/helper-query';
 import { IngestSuccessPane } from '../ingest-success-pane/ingest-success-pane';
-import { useMetadataStateStore } from '../metadata-state-store';
+import { metadataStateStore } from '../metadata-state-store';
 import { ResultTablePane } from '../result-table-pane/result-table-pane';
 import { RunPanel } from '../run-panel/run-panel';
-import { useWorkStateStore } from '../work-state-store';
+import { workStateStore } from '../work-state-store';
 
 import './query-tab.scss';
 
@@ -252,7 +245,10 @@ export const QueryTab = React.memo(function QueryTab(props: QueryTabProps) {
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [executionState.data, executionState.error]);
 
-  const incrementWorkVersion = useWorkStateStore(state => state.increment);
+  const incrementWorkVersion = useStore(
+    workStateStore,
+    useCallback(state => state.increment, []),
+  );
   useEffect(() => {
     incrementWorkVersion();
     // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -260,7 +256,10 @@ export const QueryTab = React.memo(function QueryTab(props: QueryTabProps) {
 
   const execution = executionState.data;
 
-  const incrementMetadataVersion = useMetadataStateStore(state => state.increment);
+  const incrementMetadataVersion = useStore(
+    metadataStateStore,
+    useCallback(state => state.increment, []),
+  );
   useEffect(() => {
     if (execution?.isSuccessfulInsert()) {
       incrementMetadataVersion();
diff --git a/web-console/src/views/workbench-view/recent-query-task-panel/recent-query-task-panel.tsx b/web-console/src/views/workbench-view/recent-query-task-panel/recent-query-task-panel.tsx
index e6faced766..d57557e96c 100644
--- a/web-console/src/views/workbench-view/recent-query-task-panel/recent-query-task-panel.tsx
+++ b/web-console/src/views/workbench-view/recent-query-task-panel/recent-query-task-panel.tsx
@@ -17,21 +17,24 @@
  */
 
 import { Button, Icon, Intent, Menu, MenuDivider, MenuItem } from '@blueprintjs/core';
-import { IconName, IconNames } from '@blueprintjs/icons';
+import type { IconName } from '@blueprintjs/icons';
+import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
 import copy from 'copy-to-clipboard';
 import { T } from 'druid-query-toolkit';
-import React, { useState } from 'react';
+import React, { useCallback, useState } from 'react';
+import { useStore } from 'zustand';
 
 import { Loader } from '../../../components';
-import { Execution, WorkbenchQuery } from '../../../druid-models';
+import type { Execution } from '../../../druid-models';
+import { WorkbenchQuery } from '../../../druid-models';
 import { cancelTaskExecution, getTaskExecution } from '../../../helpers';
 import { useClock, useInterval, useQueryManager } from '../../../hooks';
 import { AppToaster } from '../../../singletons';
 import { downloadQueryDetailArchive, formatDuration, queryDruidSql } from '../../../utils';
 import { CancelQueryDialog } from '../cancel-query-dialog/cancel-query-dialog';
-import { useWorkStateStore } from '../work-state-store';
+import { workStateStore } from '../work-state-store';
 
 import './recent-query-task-panel.scss';
 
@@ -89,7 +92,10 @@ export const RecentQueryTaskPanel = React.memo(function RecentQueryTaskPanel(
 
   const [confirmCancelId, setConfirmCancelId] = useState<string | undefined>();
 
-  const workStateVersion = useWorkStateStore(state => state.version);
+  const workStateVersion = useStore(
+    workStateStore,
+    useCallback(state => state.version, []),
+  );
 
   const [queryTaskHistoryState, queryManager] = useQueryManager<number, RecentQueryEntry[]>({
     query: workStateVersion,
@@ -116,7 +122,10 @@ LIMIT 100`,
 
   const now = useClock();
 
-  const incrementWorkVersion = useWorkStateStore(state => state.increment);
+  const incrementWorkVersion = useStore(
+    workStateStore,
+    useCallback(state => state.increment, []),
+  );
 
   const queryTaskHistory = queryTaskHistoryState.getSomeData();
   return (
@@ -140,6 +149,7 @@ LIMIT 100`,
                 <MenuItem
                   icon={IconNames.DOCUMENT_OPEN}
                   text="Attach in new tab"
+                  // eslint-disable-next-line @typescript-eslint/no-misused-promises
                   onClick={async () => {
                     let execution: Execution;
                     try {
@@ -191,7 +201,7 @@ LIMIT 100`,
                 <MenuItem
                   icon={IconNames.ARCHIVE}
                   text="Get query detail archive"
-                  onClick={() => downloadQueryDetailArchive(w.taskId)}
+                  onClick={() => void downloadQueryDetailArchive(w.taskId)}
                 />
                 {w.taskStatus === 'RUNNING' && (
                   <>
@@ -256,6 +266,7 @@ LIMIT 100`,
       ) : undefined}
       {confirmCancelId && (
         <CancelQueryDialog
+          // eslint-disable-next-line @typescript-eslint/no-misused-promises
           onCancel={async () => {
             if (!confirmCancelId) return;
             try {
diff --git a/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx b/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
index c2b25b40d4..a5cd837f87 100644
--- a/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
+++ b/web-console/src/views/workbench-view/result-table-pane/result-table-pane.tsx
@@ -20,20 +20,11 @@ import { Button, Icon, Intent, Menu, MenuItem } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import { Popover2 } from '@blueprintjs/popover2';
 import classNames from 'classnames';
-import {
-  C,
-  Column,
-  F,
-  QueryResult,
-  SqlAlias,
-  SqlExpression,
-  SqlFunction,
-  SqlLiteral,
-  SqlQuery,
-  SqlStar,
-} from 'druid-query-toolkit';
+import type { Column, QueryResult, SqlExpression, SqlQuery } from 'druid-query-toolkit';
+import { C, F, SqlAlias, SqlFunction, SqlLiteral, SqlStar } from 'druid-query-toolkit';
 import * as JSONBig from 'json-bigint-native';
 import React, { useEffect, useState } from 'react';
+import type { RowRenderProps } from 'react-table';
 import ReactTable from 'react-table';
 
 import { BracedText, Deferred, TableCell } from '../../../components';
@@ -45,6 +36,7 @@ import {
   TIME_COLUMN,
 } from '../../../druid-models';
 import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../../react-table';
+import type { Pagination, QueryAction } from '../../../utils';
 import {
   columnToIcon,
   columnToWidth,
@@ -54,9 +46,7 @@ import {
   formatNumber,
... 236 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org