@lumino/widgets
Advanced tools
Comparing version 2.2.0 to 2.3.0
{ | ||
"name": "@lumino/widgets", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"description": "Lumino Widgets", | ||
@@ -57,17 +57,17 @@ "homepage": "https://github.com/jupyterlab/lumino", | ||
"dependencies": { | ||
"@lumino/algorithm": "^2.0.0", | ||
"@lumino/commands": "^2.1.2", | ||
"@lumino/coreutils": "^2.1.1", | ||
"@lumino/disposable": "^2.1.1", | ||
"@lumino/domutils": "^2.0.0", | ||
"@lumino/dragdrop": "^2.1.2", | ||
"@lumino/keyboard": "^2.0.0", | ||
"@lumino/messaging": "^2.0.0", | ||
"@lumino/properties": "^2.0.0", | ||
"@lumino/signaling": "^2.1.1", | ||
"@lumino/virtualdom": "^2.0.0" | ||
"@lumino/algorithm": "^2.0.1", | ||
"@lumino/commands": "^2.1.3", | ||
"@lumino/coreutils": "^2.1.2", | ||
"@lumino/disposable": "^2.1.2", | ||
"@lumino/domutils": "^2.0.1", | ||
"@lumino/dragdrop": "^2.1.3", | ||
"@lumino/keyboard": "^2.0.1", | ||
"@lumino/messaging": "^2.0.1", | ||
"@lumino/properties": "^2.0.1", | ||
"@lumino/signaling": "^2.1.2", | ||
"@lumino/virtualdom": "^2.0.1" | ||
}, | ||
"devDependencies": { | ||
"@lumino/buildutils": "^2.0.0", | ||
"@microsoft/api-extractor": "^7.6.0", | ||
"@lumino/buildutils": "^2.0.1", | ||
"@microsoft/api-extractor": "^7.36.0", | ||
"@rollup/plugin-commonjs": "^24.0.0", | ||
@@ -86,13 +86,12 @@ "@rollup/plugin-node-resolve": "^15.0.1", | ||
"mocha": "^9.0.3", | ||
"playwright": "^1.29.0", | ||
"postcss": "^8.4.14", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^3.9.1", | ||
"playwright": "^1.35.0", | ||
"postcss": "^8.4.24", | ||
"rimraf": "^5.0.1", | ||
"rollup": "^3.25.1", | ||
"rollup-plugin-postcss": "^4.0.2", | ||
"rollup-plugin-sourcemaps": "^0.6.3", | ||
"rollup-plugin-styles": "^4.0.0", | ||
"terser": "^5.7.1", | ||
"tslib": "^2.4.0", | ||
"typedoc": "^0.23.25", | ||
"typescript": "~4.9.4" | ||
"terser": "^5.18.1", | ||
"tslib": "^2.5.3", | ||
"typescript": "~5.1.3" | ||
}, | ||
@@ -99,0 +98,0 @@ "publishConfig": { |
@@ -6,2 +6,3 @@ // Copyright (c) Jupyter Development Team. | ||
import { Message } from '@lumino/messaging'; | ||
import { ISignal, Signal } from '@lumino/signaling'; | ||
import { AccordionLayout } from './accordionlayout'; | ||
@@ -58,2 +59,9 @@ import { SplitLayout } from './splitlayout'; | ||
/** | ||
* A signal emitted when a widget of the AccordionPanel is collapsed or expanded. | ||
*/ | ||
get expansionToggled(): ISignal<this, number> { | ||
return this._expansionToggled; | ||
} | ||
/** | ||
* Add a widget to the end of the panel. | ||
@@ -335,5 +343,9 @@ * | ||
} | ||
// Emit the expansion state signal. | ||
this._expansionToggled.emit(index); | ||
} | ||
private _widgetSizesCache: WeakMap<Widget, number> = new WeakMap(); | ||
private _expansionToggled = new Signal<this, number>(this); | ||
} | ||
@@ -340,0 +352,0 @@ |
@@ -10,2 +10,6 @@ // Copyright (c) Jupyter Development Team. | ||
|----------------------------------------------------------------------------*/ | ||
/** | ||
* @packageDocumentation | ||
* @module widgets | ||
*/ | ||
export * from './accordionlayout'; | ||
@@ -12,0 +16,0 @@ export * from './accordionpanel'; |
@@ -36,2 +36,11 @@ // Copyright (c) Jupyter Development Team. | ||
const ARROW_KEYS = [ | ||
'ArrowLeft', | ||
'ArrowUp', | ||
'ArrowRight', | ||
'ArrowDown', | ||
'Home', | ||
'End' | ||
]; | ||
/** | ||
@@ -605,3 +614,5 @@ * A widget which displays titles as a single row or column of tabs. | ||
case 'keydown': | ||
this._evtKeyDown(event as KeyboardEvent); | ||
event.eventPhase === Event.CAPTURING_PHASE | ||
? this._evtKeyDownCapturing(event as KeyboardEvent) | ||
: this._evtKeyDown(event as KeyboardEvent); | ||
break; | ||
@@ -621,2 +632,3 @@ case 'contextmenu': | ||
this.node.addEventListener('dblclick', this); | ||
this.node.addEventListener('keydown', this); | ||
} | ||
@@ -630,2 +642,3 @@ | ||
this.node.removeEventListener('dblclick', this); | ||
this.node.removeEventListener('keydown', this); | ||
this._releaseMouse(); | ||
@@ -642,2 +655,10 @@ } | ||
let content = new Array<VirtualElement>(titles.length); | ||
// Keep the tabindex="0" attribute to the tab which handled it before the update. | ||
// If the add button handles it, no need to do anything. If no element of the tab | ||
// bar handles it, set it on the current or the first tab to ensure one element | ||
// handles it after update. | ||
const tabHandlingTabindex = | ||
this._getCurrentTabindex() ?? | ||
(this._currentIndex > -1 ? this._currentIndex : 0); | ||
for (let i = 0, n = titles.length; i < n; ++i) { | ||
@@ -647,3 +668,4 @@ let title = titles[i]; | ||
let zIndex = current ? n : n - i - 1; | ||
content[i] = renderer.renderTab({ title, current, zIndex }); | ||
let tabIndex = tabHandlingTabindex === i ? 0 : -1; | ||
content[i] = renderer.renderTab({ title, current, zIndex, tabIndex }); | ||
} | ||
@@ -654,2 +676,21 @@ VirtualDOM.render(content, this.contentNode); | ||
/** | ||
* Get the index of the tab which handles tabindex="0". | ||
* If the add button handles tabindex="0", -1 is returned. | ||
* If none of the previous handles tabindex="0", null is returned. | ||
*/ | ||
private _getCurrentTabindex(): number | null { | ||
let index = null; | ||
const elemTabindex = this.contentNode.querySelector('li[tabindex="0"]'); | ||
if (elemTabindex) { | ||
index = [...this.contentNode.children].indexOf(elemTabindex); | ||
} else if ( | ||
this._addButtonEnabled && | ||
this.addButtonNode.getAttribute('tabindex') === '0' | ||
) { | ||
index = -1; | ||
} | ||
return index; | ||
} | ||
/** | ||
* Handle the `'dblclick'` event for the tab bar. | ||
@@ -665,3 +706,3 @@ */ | ||
// Find the index of the released tab. | ||
// Find the index of the targeted tab. | ||
let index = ArrayExt.findFirstIndex(tabs, tab => { | ||
@@ -693,2 +734,3 @@ return ElementExt.hitTest(tab, event.clientX, event.clientY); | ||
label.innerHTML = oldValue; | ||
this.node.addEventListener('keydown', this); | ||
}; | ||
@@ -710,2 +752,3 @@ | ||
}); | ||
this.node.removeEventListener('keydown', this); | ||
input.select(); | ||
@@ -721,5 +764,9 @@ input.focus(); | ||
/** | ||
* Handle the `'keydown'` event for the tab bar. | ||
* Handle the `'keydown'` event for the tab bar at capturing phase. | ||
*/ | ||
private _evtKeyDown(event: KeyboardEvent): void { | ||
private _evtKeyDownCapturing(event: KeyboardEvent): void { | ||
if (event.eventPhase !== Event.CAPTURING_PHASE) { | ||
return; | ||
} | ||
// Stop all input events during drag. | ||
@@ -730,3 +777,3 @@ event.preventDefault(); | ||
// Release the mouse if `Escape` is pressed. | ||
if (event.keyCode === 27) { | ||
if (event.key === 'Escape') { | ||
this._releaseMouse(); | ||
@@ -737,2 +784,86 @@ } | ||
/** | ||
* Handle the `'keydown'` event for the tab bar at target phase. | ||
*/ | ||
private _evtKeyDown(event: KeyboardEvent): void { | ||
// Allow for navigation using tab key | ||
if (event.key === 'Tab' || event.eventPhase === Event.CAPTURING_PHASE) { | ||
return; | ||
} | ||
// Check if Enter or Spacebar key has been pressed and open that tab | ||
if ( | ||
event.key === 'Enter' || | ||
event.key === 'Spacebar' || | ||
event.key === ' ' | ||
) { | ||
// Get focus element that is in focus by the tab key | ||
const focusedElement = document.activeElement; | ||
// Test first if the focus is on the add button node | ||
if ( | ||
this.addButtonEnabled && | ||
this.addButtonNode.contains(focusedElement) | ||
) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
this._addRequested.emit(); | ||
} else { | ||
const index = ArrayExt.findFirstIndex(this.contentNode.children, tab => | ||
tab.contains(focusedElement) | ||
); | ||
if (index >= 0) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
this.currentIndex = index; | ||
} | ||
} | ||
// Handle the arrow keys to switch tabs. | ||
} else if (ARROW_KEYS.includes(event.key)) { | ||
// Create a list of all focusable elements in the tab bar. | ||
const focusable: Element[] = [...this.contentNode.children]; | ||
if (this.addButtonEnabled) { | ||
focusable.push(this.addButtonNode); | ||
} | ||
// If the tab bar contains only one element, nothing to do. | ||
if (focusable.length <= 1) { | ||
return; | ||
} | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
// Get the current focused element. | ||
let focusedIndex = focusable.indexOf(document.activeElement as Element); | ||
if (focusedIndex === -1) { | ||
focusedIndex = this._currentIndex; | ||
} | ||
// Find the next element to focus on. | ||
let nextFocused: Element | null | undefined; | ||
if ( | ||
(event.key === 'ArrowRight' && this._orientation === 'horizontal') || | ||
(event.key === 'ArrowDown' && this._orientation === 'vertical') | ||
) { | ||
nextFocused = focusable[focusedIndex + 1] ?? focusable[0]; | ||
} else if ( | ||
(event.key === 'ArrowLeft' && this._orientation === 'horizontal') || | ||
(event.key === 'ArrowUp' && this._orientation === 'vertical') | ||
) { | ||
nextFocused = | ||
focusable[focusedIndex - 1] ?? focusable[focusable.length - 1]; | ||
} else if (event.key === 'Home') { | ||
nextFocused = focusable[0]; | ||
} else if (event.key === 'End') { | ||
nextFocused = focusable[focusable.length - 1]; | ||
} | ||
// Change the focused element and the tabindex value. | ||
if (nextFocused) { | ||
focusable[focusedIndex]?.setAttribute('tabindex', '-1'); | ||
nextFocused?.setAttribute('tabindex', '0'); | ||
(nextFocused as HTMLElement).focus(); | ||
} | ||
} | ||
} | ||
/** | ||
* Handle the `'pointerdown'` event for the tab bar. | ||
@@ -751,2 +882,9 @@ */ | ||
// Do nothing if a title editable input was clicked. | ||
if ( | ||
(event.target as HTMLElement).classList.contains('lm-TabBar-tabInput') | ||
) { | ||
return; | ||
} | ||
// Check if the add button was clicked. | ||
@@ -1525,2 +1663,7 @@ let addButtonClicked = | ||
readonly zIndex: number; | ||
/** | ||
* The tabindex value for the tab. | ||
*/ | ||
readonly tabIndex?: number; | ||
} | ||
@@ -1705,3 +1848,3 @@ | ||
'aria-selected': data.current.toString(), | ||
tabindex: '0' | ||
tabindex: `${data.tabIndex ?? '-1'}` | ||
}; | ||
@@ -1882,2 +2025,3 @@ } | ||
add.className = 'lm-TabBar-addButton lm-mod-hidden'; | ||
add.setAttribute('tabindex', '-1'); | ||
node.appendChild(add); | ||
@@ -1884,0 +2028,0 @@ return node; |
import { Message } from '@lumino/messaging'; | ||
import { ISignal } from '@lumino/signaling'; | ||
import { AccordionLayout } from './accordionlayout'; | ||
@@ -37,2 +38,6 @@ import { SplitLayout } from './splitlayout'; | ||
/** | ||
* A signal emitted when a widget of the AccordionPanel is collapsed or expanded. | ||
*/ | ||
get expansionToggled(): ISignal<this, number>; | ||
/** | ||
* Add a widget to the end of the panel. | ||
@@ -123,2 +128,3 @@ * | ||
private _widgetSizesCache; | ||
private _expansionToggled; | ||
} | ||
@@ -125,0 +131,0 @@ /** |
@@ -0,1 +1,5 @@ | ||
/** | ||
* @packageDocumentation | ||
* @module widgets | ||
*/ | ||
export * from './accordionlayout'; | ||
@@ -2,0 +6,0 @@ export * from './accordionpanel'; |
@@ -285,2 +285,8 @@ import { Message } from '@lumino/messaging'; | ||
/** | ||
* Get the index of the tab which handles tabindex="0". | ||
* If the add button handles tabindex="0", -1 is returned. | ||
* If none of the previous handles tabindex="0", null is returned. | ||
*/ | ||
private _getCurrentTabindex; | ||
/** | ||
* Handle the `'dblclick'` event for the tab bar. | ||
@@ -290,4 +296,8 @@ */ | ||
/** | ||
* Handle the `'keydown'` event for the tab bar. | ||
* Handle the `'keydown'` event for the tab bar at capturing phase. | ||
*/ | ||
private _evtKeyDownCapturing; | ||
/** | ||
* Handle the `'keydown'` event for the tab bar at target phase. | ||
*/ | ||
private _evtKeyDown; | ||
@@ -578,2 +588,6 @@ /** | ||
readonly zIndex: number; | ||
/** | ||
* The tabindex value for the tab. | ||
*/ | ||
readonly tabIndex?: number; | ||
} | ||
@@ -580,0 +594,0 @@ /** |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4661586
25
58024
Updated@lumino/algorithm@^2.0.1
Updated@lumino/commands@^2.1.3
Updated@lumino/coreutils@^2.1.2
Updated@lumino/disposable@^2.1.2
Updated@lumino/domutils@^2.0.1
Updated@lumino/dragdrop@^2.1.3
Updated@lumino/keyboard@^2.0.1
Updated@lumino/messaging@^2.0.1
Updated@lumino/properties@^2.0.1
Updated@lumino/signaling@^2.1.2
Updated@lumino/virtualdom@^2.0.1