jupyterlab_tabular_data_viewer_extension 1.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Stellars Henson
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # jupyterlab_tabular_data_viewer_extension
2
+
3
+ ![GitHub Actions](https://github.com/stellarshenson/jupyterlab_tabular_data_viewer_extension/actions/workflows/build.yml/badge.svg)
4
+ [![npm version](https://badge.fury.io/js/jupyterlab_tabular_data_viewer_extension.svg)](https://www.npmjs.com/package/jupyterlab_tabular_data_viewer_extension)
5
+ [![PyPI version](https://badge.fury.io/py/jupyterlab-tabular-data-viewer-extension.svg)](https://pypi.org/project/jupyterlab-tabular-data-viewer-extension/)
6
+ [![Total PyPI downloads](https://static.pepy.tech/badge/jupyterlab-tabular-data-viewer-extension)](https://pepy.tech/project/jupyterlab-tabular-data-viewer-extension)
7
+ ![JL4 Ready](https://img.shields.io/badge/Jupyterlab%204-ready-blue)
8
+
9
+ View and browse Parquet, Excel, CSV, and TSV files directly in JupyterLab. Double-click any .parquet, .xlsx, .csv, or .tsv file to open it in a simple, spreadsheet-like table view - no code required. Navigate through your data, inspect values, and explore the structure of your tabular data files with interactive column resizing and advanced filtering capabilities.
10
+
11
+ ![Parquet Viewer](.resources/screenshot.png)
12
+
13
+ ## Features
14
+
15
+ **Supported File Formats:**
16
+ - **Parquet files** (.parquet) - Full support with efficient columnar data reading
17
+ - **Excel files** (.xlsx) - Reads first worksheet only. Excel files must be simple tabular data without merged cells, complex formulas, or advanced formatting. Files with these features may not display correctly or fail to load
18
+ - **CSV files** (.csv) - Comma-separated values with UTF-8 encoding (fallback to latin1)
19
+ - **TSV files** (.tsv) - Tab-separated values with UTF-8 encoding (fallback to latin1)
20
+
21
+ **Core viewing and navigation:**
22
+ - Simple table display showing your data in familiar spreadsheet format
23
+ - Column headers with field names and simplified datatype indicators
24
+ - Interactive column resizing - drag column borders to adjust width independently
25
+ - Progressive loading - starts with 500 rows, automatically loads more as you scroll
26
+ - File statistics (column count, row count, file size) at a glance
27
+ - Fixed status bar remains visible during horizontal scrolling
28
+ - Handles large files efficiently with server-side processing
29
+
30
+ **Advanced filtering and sorting:**
31
+ - Column sorting with three-state toggle (ascending, descending, off)
32
+ - Per-column filtering with substring or regex pattern matching
33
+ - Case-insensitive search option
34
+ - Numerical filters supporting comparison operators (`>`, `<`, `>=`, `<=`, `=`)
35
+ - Clear filters functionality to reset all active filters
36
+ - Multiple filters work together to narrow down results
37
+
38
+ **Additional features:**
39
+ - Right-click context menu on rows to copy data as JSON
40
+ - Configurable file type support via Settings - Enable/disable Parquet, Excel, or CSV/TSV handling
41
+ - All features work seamlessly across all supported file formats
42
+
43
+ ## Installation
44
+
45
+ Requires JupyterLab 4.0.0 or higher.
46
+
47
+ ```bash
48
+ pip install jupyterlab_tabular_data_viewer_extension
49
+ ```
50
+
51
+ Uninstall:
52
+ ```bash
53
+ pip uninstall jupyterlab_tabular_data_viewer_extension
54
+ ```
55
+
56
+ ## Configuration
57
+
58
+ Configure file type support through JupyterLab Settings:
59
+
60
+ 1. Open **Settings → Settings Editor**
61
+ 2. Search for "Parquet Viewer Extension"
62
+ 3. Configure options:
63
+ - **Enable Parquet files** - Default: enabled
64
+ - **Enable Excel files** - Default: disabled (enable to view .xlsx files)
65
+
66
+ When a file type is disabled, files open with JupyterLab's default handler instead.
67
+
68
+ ## Troubleshooting
69
+
70
+ Verify both extension components are enabled if the extension doesn't work:
71
+
72
+ ```bash
73
+ # Check server extension
74
+ jupyter server extension list
75
+
76
+ # Check frontend extension
77
+ jupyter labextension list
78
+ ```
79
+
80
+ Both commands should show `jupyterlab_tabular_data_viewer_extension` as enabled. Reinstall if either is missing or disabled.
81
+
82
+ ## Development Setup
83
+
84
+ Requires NodeJS for building TypeScript frontend. Uses `jlpm` (JupyterLab's pinned yarn version) for consistency.
85
+
86
+ **Initial setup:**
87
+
88
+ ```bash
89
+ # Create virtual environment
90
+ python -m venv .venv
91
+ source .venv/bin/activate
92
+
93
+ # Install in editable mode
94
+ pip install --editable ".[dev,test]"
95
+
96
+ # Link frontend and enable server extension
97
+ jupyter labextension develop . --overwrite
98
+ jupyter server extension enable jupyterlab_tabular_data_viewer_extension
99
+ ```
100
+
101
+ **Development workflow:**
102
+
103
+ Use two terminals for efficient development:
104
+ - Terminal 1: `jlpm watch` (auto-rebuild on file changes)
105
+ - Terminal 2: `jupyter lab` (run development instance)
106
+
107
+ Refresh browser after changes to see updates. Build generates source maps for debugging.
108
+
109
+ Enable deeper debugging with unminimized JupyterLab build:
110
+ ```bash
111
+ jupyter lab build --minimize=False
112
+ ```
113
+
114
+ **Removing development installation:**
115
+
116
+ ```bash
117
+ jupyter server extension disable jupyterlab_tabular_data_viewer_extension
118
+ pip uninstall jupyterlab_tabular_data_viewer_extension
119
+ ```
120
+
121
+ Then delete the `jupyterlab_tabular_data_viewer_extension` symlink from your `labextensions` directory (find with `jupyter labextension list`).
122
+
123
+ ## Testing
124
+
125
+ Three-tier testing strategy: Python backend, TypeScript frontend, and integration tests.
126
+
127
+ **Python tests** (pytest with coverage):
128
+ ```bash
129
+ pip install -e ".[test]"
130
+ jupyter labextension develop . --overwrite
131
+ pytest -vv -r ap --cov jupyterlab_tabular_data_viewer_extension
132
+ ```
133
+
134
+ **TypeScript tests** (Jest):
135
+ ```bash
136
+ jlpm
137
+ jlpm test
138
+ ```
139
+
140
+ **Integration tests** (Playwright + Galata):
141
+ Simulates real user interactions to validate complete workflows. See [ui-tests README](./ui-tests/README.md) for detailed instructions.
142
+
143
+ ## Packaging and Release
144
+
145
+ See [RELEASE.md](RELEASE.md) for instructions on building distributable packages and publishing releases.
@@ -0,0 +1,8 @@
1
+ import { DocumentWidget } from '@jupyterlab/docregistry';
2
+ import { TabularDataViewer } from './widget';
3
+ /**
4
+ * A document widget for tabular data files (Parquet, Excel)
5
+ */
6
+ export declare class TabularDataDocument extends DocumentWidget<TabularDataViewer> {
7
+ constructor(options: DocumentWidget.IOptions<TabularDataViewer>);
8
+ }
@@ -0,0 +1,9 @@
1
+ import { DocumentWidget } from '@jupyterlab/docregistry';
2
+ /**
3
+ * A document widget for tabular data files (Parquet, Excel)
4
+ */
5
+ export class TabularDataDocument extends DocumentWidget {
6
+ constructor(options) {
7
+ super(options);
8
+ }
9
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ /**
3
+ * Initialization data for the jupyterlab_tabular_data_viewer_extension extension.
4
+ */
5
+ declare const plugin: JupyterFrontEndPlugin<void>;
6
+ export default plugin;
package/lib/index.js ADDED
@@ -0,0 +1,214 @@
1
+ import { ABCWidgetFactory } from '@jupyterlab/docregistry';
2
+ import { ISettingRegistry } from '@jupyterlab/settingregistry';
3
+ import { TabularDataViewer } from './widget';
4
+ import { TabularDataDocument } from './document';
5
+ /**
6
+ * A widget factory for Parquet files
7
+ */
8
+ class TabularDataWidgetFactory extends ABCWidgetFactory {
9
+ constructor(options, setLastContextMenuRow, setActiveWidget) {
10
+ super(options);
11
+ this._setLastContextMenuRow = setLastContextMenuRow;
12
+ this._setActiveWidget = setActiveWidget;
13
+ }
14
+ /**
15
+ * Create a new widget given a context
16
+ */
17
+ createNewWidget(context) {
18
+ // console.log(`[Tabular Data Viewer] Creating widget for file: ${context.path}`);
19
+ // console.log(`[Tabular Data Viewer] File type: ${context.contentsModel?.type}, Format: ${context.contentsModel?.format}`);
20
+ const content = new TabularDataViewer(context.path, this._setLastContextMenuRow);
21
+ const widget = new TabularDataDocument({ content, context });
22
+ widget.title.label = context.path.split('/').pop() || 'Tabular Data File';
23
+ // Track this as the active widget when context menu is used
24
+ this._setActiveWidget(content);
25
+ return widget;
26
+ }
27
+ }
28
+ /**
29
+ * Initialization data for the jupyterlab_tabular_data_viewer_extension extension.
30
+ */
31
+ const plugin = {
32
+ id: 'jupyterlab_tabular_data_viewer_extension:plugin',
33
+ description: 'Jupyterlab extension to allow simple browsing of tabular data files (Parquet, Excel) with filtering and sorting capabilities',
34
+ autoStart: true,
35
+ requires: [ISettingRegistry],
36
+ activate: async (app, settingRegistry) => {
37
+ // console.log(
38
+ // 'JupyterLab extension jupyterlab_tabular_data_viewer_extension is activated!'
39
+ // );
40
+ const { docRegistry, commands, contextMenu } = app;
41
+ // Track last right-clicked row for context menu
42
+ let lastContextMenuRow = null;
43
+ let activeWidget = null;
44
+ // Load settings
45
+ let settings = {
46
+ enableParquet: true,
47
+ enableExcel: true,
48
+ enableCSV: true,
49
+ enableTSV: true
50
+ };
51
+ // console.log('[Tabular Data Viewer] Default settings:', settings);
52
+ try {
53
+ // console.log('[Tabular Data Viewer] Loading settings from registry with id:', plugin.id);
54
+ const pluginSettings = await settingRegistry.load(plugin.id);
55
+ settings = pluginSettings.composite;
56
+ // console.log('[Tabular Data Viewer] Loaded settings:', settings);
57
+ // console.log('[Tabular Data Viewer] Settings detail - enableParquet:', settings.enableParquet, 'enableExcel:', settings.enableExcel);
58
+ // Watch for settings changes
59
+ pluginSettings.changed.connect(() => {
60
+ settings = pluginSettings.composite;
61
+ // console.log('[Tabular Data Viewer] Settings changed:', settings);
62
+ });
63
+ }
64
+ catch (error) {
65
+ console.error('[Tabular Data Viewer] Failed to load settings:', error);
66
+ // console.log('[Tabular Data Viewer] Using default settings:', settings);
67
+ }
68
+ // Command to copy row as JSON
69
+ const copyRowCommand = 'tabular-data-viewer:copy-row-json';
70
+ commands.addCommand(copyRowCommand, {
71
+ label: 'Copy Row as JSON',
72
+ caption: 'Copy the row data as JSON to clipboard',
73
+ isEnabled: () => {
74
+ return lastContextMenuRow !== null;
75
+ },
76
+ execute: async () => {
77
+ if (lastContextMenuRow) {
78
+ const jsonString = JSON.stringify(lastContextMenuRow, null, 2);
79
+ await navigator.clipboard.writeText(jsonString);
80
+ // console.log('Row copied to clipboard as JSON');
81
+ // Clean up highlight after copy
82
+ if (activeWidget) {
83
+ activeWidget.getCleanupHighlight()();
84
+ }
85
+ }
86
+ }
87
+ });
88
+ // Add to context menu for tabular data viewer rows
89
+ contextMenu.addItem({
90
+ command: copyRowCommand,
91
+ selector: '.jp-TabularDataViewer-row',
92
+ rank: 10
93
+ });
94
+ // Register file types based on settings
95
+ // console.log('[Tabular Data Viewer] Starting file type registration...');
96
+ // console.log('[Tabular Data Viewer] Current settings state:', settings);
97
+ const binaryFileTypes = [];
98
+ const textFileTypes = [];
99
+ // Register Parquet file type if enabled
100
+ if (settings.enableParquet) {
101
+ try {
102
+ docRegistry.addFileType({
103
+ name: 'parquet',
104
+ displayName: 'Parquet',
105
+ extensions: ['.parquet'],
106
+ mimeTypes: ['application/x-parquet'],
107
+ iconClass: 'jp-MaterialIcon jp-SpreadsheetIcon',
108
+ contentType: 'file',
109
+ fileFormat: 'base64'
110
+ });
111
+ binaryFileTypes.push('parquet');
112
+ // console.log('[Tabular Data Viewer] Parquet file type registered');
113
+ }
114
+ catch (e) {
115
+ console.warn('[Tabular Data Viewer] Parquet file type already registered', e);
116
+ }
117
+ }
118
+ // Register Excel file type if enabled
119
+ if (settings.enableExcel) {
120
+ try {
121
+ docRegistry.addFileType({
122
+ name: 'xlsx-parquet-viewer',
123
+ displayName: 'Excel (Parquet Viewer)',
124
+ extensions: ['.xlsx'],
125
+ mimeTypes: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
126
+ iconClass: 'jp-MaterialIcon jp-SpreadsheetIcon',
127
+ contentType: 'file',
128
+ fileFormat: 'base64'
129
+ });
130
+ binaryFileTypes.push('xlsx-parquet-viewer');
131
+ // console.log('[Tabular Data Viewer] Excel file type registered');
132
+ }
133
+ catch (e) {
134
+ console.warn('[Tabular Data Viewer] Excel file type already registered', e);
135
+ }
136
+ }
137
+ // Register CSV file type if enabled
138
+ if (settings.enableCSV) {
139
+ try {
140
+ docRegistry.addFileType({
141
+ name: 'csv-tabular-viewer',
142
+ displayName: 'CSV (Tabular Viewer)',
143
+ extensions: ['.csv'],
144
+ mimeTypes: ['text/csv'],
145
+ iconClass: 'jp-MaterialIcon jp-SpreadsheetIcon',
146
+ contentType: 'file',
147
+ fileFormat: 'text'
148
+ });
149
+ textFileTypes.push('csv-tabular-viewer');
150
+ // console.log('[Tabular Data Viewer] CSV file type registered');
151
+ }
152
+ catch (e) {
153
+ console.warn('[Tabular Data Viewer] CSV file type already registered', e);
154
+ }
155
+ }
156
+ // Register TSV file type if enabled
157
+ if (settings.enableTSV) {
158
+ try {
159
+ docRegistry.addFileType({
160
+ name: 'tsv-tabular-viewer',
161
+ displayName: 'TSV (Tabular Viewer)',
162
+ extensions: ['.tsv'],
163
+ mimeTypes: ['text/tab-separated-values'],
164
+ iconClass: 'jp-MaterialIcon jp-SpreadsheetIcon',
165
+ contentType: 'file',
166
+ fileFormat: 'text'
167
+ });
168
+ textFileTypes.push('tsv-tabular-viewer');
169
+ // console.log('[Tabular Data Viewer] TSV file type registered');
170
+ }
171
+ catch (e) {
172
+ console.warn('[Tabular Data Viewer] TSV file type already registered', e);
173
+ }
174
+ }
175
+ // Create binary factory for Parquet and Excel files
176
+ if (binaryFileTypes.length > 0) {
177
+ const binaryFactory = new TabularDataWidgetFactory({
178
+ name: 'Tabular Data Viewer (Binary)',
179
+ modelName: 'base64',
180
+ fileTypes: binaryFileTypes,
181
+ defaultFor: binaryFileTypes,
182
+ defaultRendered: binaryFileTypes,
183
+ readOnly: true
184
+ }, (row) => {
185
+ lastContextMenuRow = row;
186
+ }, (widget) => {
187
+ activeWidget = widget;
188
+ });
189
+ docRegistry.addWidgetFactory(binaryFactory);
190
+ // console.log(`[Tabular Data Viewer] Binary factory registered for: ${binaryFileTypes.join(', ')}`);
191
+ }
192
+ // Create text factory for CSV and TSV files
193
+ if (textFileTypes.length > 0) {
194
+ const textFactory = new TabularDataWidgetFactory({
195
+ name: 'Tabular Data Viewer (Text)',
196
+ modelName: 'text',
197
+ fileTypes: textFileTypes,
198
+ defaultFor: textFileTypes,
199
+ defaultRendered: textFileTypes,
200
+ readOnly: true
201
+ }, (row) => {
202
+ lastContextMenuRow = row;
203
+ }, (widget) => {
204
+ activeWidget = widget;
205
+ });
206
+ docRegistry.addWidgetFactory(textFactory);
207
+ // console.log(`[Tabular Data Viewer] Text factory registered for: ${textFileTypes.join(', ')}`);
208
+ }
209
+ if (binaryFileTypes.length === 0 && textFileTypes.length === 0) {
210
+ console.warn('[Tabular Data Viewer] No file types enabled in settings');
211
+ }
212
+ }
213
+ };
214
+ export default plugin;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Call the server extension
3
+ *
4
+ * @param endPoint API REST end point for the extension
5
+ * @param init Initial values for the request
6
+ * @returns The response body interpreted as JSON
7
+ */
8
+ export declare function requestAPI<T>(endPoint?: string, init?: RequestInit): Promise<T>;
package/lib/request.js ADDED
@@ -0,0 +1,35 @@
1
+ import { URLExt } from '@jupyterlab/coreutils';
2
+ import { ServerConnection } from '@jupyterlab/services';
3
+ /**
4
+ * Call the server extension
5
+ *
6
+ * @param endPoint API REST end point for the extension
7
+ * @param init Initial values for the request
8
+ * @returns The response body interpreted as JSON
9
+ */
10
+ export async function requestAPI(endPoint = '', init = {}) {
11
+ // Make request to Jupyter API
12
+ const settings = ServerConnection.makeSettings();
13
+ const requestUrl = URLExt.join(settings.baseUrl, 'jupyterlab-tabular-data-viewer-extension', // our server extension's API namespace
14
+ endPoint);
15
+ let response;
16
+ try {
17
+ response = await ServerConnection.makeRequest(requestUrl, init, settings);
18
+ }
19
+ catch (error) {
20
+ throw new ServerConnection.NetworkError(error);
21
+ }
22
+ let data = await response.text();
23
+ if (data.length > 0) {
24
+ try {
25
+ data = JSON.parse(data);
26
+ }
27
+ catch (error) {
28
+ console.log('Not a JSON response body.', response);
29
+ }
30
+ }
31
+ if (!response.ok) {
32
+ throw new ServerConnection.ResponseError(response, data.message || data);
33
+ }
34
+ return data;
35
+ }
@@ -0,0 +1,127 @@
1
+ import { Widget } from '@lumino/widgets';
2
+ /**
3
+ * Parquet viewer widget
4
+ */
5
+ export declare class TabularDataViewer extends Widget {
6
+ private _filePath;
7
+ private _columns;
8
+ private _data;
9
+ private _totalRows;
10
+ private _unfilteredTotalRows;
11
+ private _currentOffset;
12
+ private _limit;
13
+ private _loading;
14
+ private _hasMore;
15
+ private _filters;
16
+ private _sortBy;
17
+ private _sortOrder;
18
+ private _fileSize;
19
+ private _caseInsensitive;
20
+ private _useRegex;
21
+ private _contextMenuOpen;
22
+ private _columnWidths;
23
+ private _resizing;
24
+ private _tableContainer;
25
+ private _table;
26
+ private _thead;
27
+ private _tbody;
28
+ private _filterRow;
29
+ private _headerRow;
30
+ private _statusBar;
31
+ private _statusLeft;
32
+ private _statusRight;
33
+ private _caseInsensitiveCheckbox;
34
+ private _regexCheckbox;
35
+ private _setLastContextMenuRow;
36
+ private _cleanupHighlight;
37
+ private _menuObserver;
38
+ constructor(filePath: string, setLastContextMenuRow: (row: any) => void);
39
+ /**
40
+ * Start observing for menu removal when context menu opens
41
+ */
42
+ private _startMenuObserver;
43
+ /**
44
+ * Get cleanup function to clear highlight (for external use)
45
+ */
46
+ getCleanupHighlight(): () => void;
47
+ /**
48
+ * Initialize the viewer by loading metadata and initial data
49
+ */
50
+ private _initialize;
51
+ /**
52
+ * Load file metadata (columns, types, row count)
53
+ */
54
+ private _loadMetadata;
55
+ /**
56
+ * Load data from server
57
+ */
58
+ private _loadData;
59
+ /**
60
+ * Render table headers with filter inputs
61
+ */
62
+ private _renderHeaders;
63
+ /**
64
+ * Render data rows
65
+ */
66
+ private _renderData;
67
+ /**
68
+ * Start column resize
69
+ */
70
+ private _startResize;
71
+ /**
72
+ * Handle column resize drag
73
+ */
74
+ private _doResize;
75
+ /**
76
+ * Stop column resize
77
+ */
78
+ private _stopResize;
79
+ /**
80
+ * Apply filter to a column
81
+ */
82
+ private _applyFilter;
83
+ /**
84
+ * Simplify type names for display
85
+ */
86
+ private _simplifyType;
87
+ /**
88
+ * Check if column type is numeric
89
+ */
90
+ private _isNumericType;
91
+ /**
92
+ * Get filter placeholder based on column type
93
+ */
94
+ private _getFilterPlaceholder;
95
+ /**
96
+ * Handle scroll event for progressive loading
97
+ */
98
+ private _onScroll;
99
+ /**
100
+ * Toggle sort on a column
101
+ */
102
+ private _toggleSort;
103
+ /**
104
+ * Update sort indicators in column headers
105
+ */
106
+ private _updateSortIndicators;
107
+ /**
108
+ * Clear all filters
109
+ */
110
+ private _clearFilters;
111
+ /**
112
+ * Format file size to human-readable string
113
+ */
114
+ private _formatFileSize;
115
+ /**
116
+ * Update status bar
117
+ */
118
+ private _updateStatusBar;
119
+ /**
120
+ * Show error message
121
+ */
122
+ private _showError;
123
+ /**
124
+ * Dispose of the widget
125
+ */
126
+ dispose(): void;
127
+ }