@ckeditor/ckeditor5-ui
Advanced tools
Comparing version 0.0.0-nightly-20240730.0 to 0.0.0-nightly-20240731.0
@@ -12,3 +12,3 @@ /** | ||
*/ | ||
import { type ArrayOrItem, type FocusTracker, type KeystrokeHandler } from '@ckeditor/ckeditor5-utils'; | ||
import { type ArrayOrItem, type FocusTracker, type KeystrokeHandler, type KeystrokeHandlerOptions } from '@ckeditor/ckeditor5-utils'; | ||
import type View from './view.js'; | ||
@@ -113,2 +113,3 @@ import type ViewCollection from './viewcollection.js'; | ||
keystrokeHandler?: KeystrokeHandler; | ||
keystrokeHandlerOptions?: KeystrokeHandlerOptions; | ||
actions?: FocusCyclerActions; | ||
@@ -174,2 +175,50 @@ }); | ||
/** | ||
* Allows for creating continuous focus cycling across multiple focus cyclers and their collections of {@link #focusables}. | ||
* | ||
* It starts listening to the {@link module:ui/focuscycler~FocusCyclerForwardCycleEvent} and | ||
* {@link module:ui/focuscycler~FocusCyclerBackwardCycleEvent} events of the chained focus cycler and engages, | ||
* whenever the user reaches the last (forwards navigation) or first (backwards navigation) focusable view | ||
* and would normally start over. Instead, the navigation continues on the higher level (flattens). | ||
* | ||
* For instance, for the following nested focus navigation structure, the focus would get stuck the moment | ||
* the AB gets focused and its focus cycler starts managing it: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├───┐ │ │ │ | ||
* │ ├───► │ └─────┘ └─────┘ └─────┘ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ └──────────────────────────────┘ │ │ │ | ||
* │ │ │ │ │ │ | ||
* └────────────┘ └──────────────────────────────────┘ └────────────┘ | ||
* | ||
* Chaining a focus tracker that manages AA, AB, and AC with the focus tracker that manages ABA, ABB, and ABC | ||
* creates a seamless navigation experience instead: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├──┐ │ │ │ | ||
* ┌──► ├───┼─┘ └─────┘ └─────┘ └─────┘ └──┼───► ├──┐ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ └────────────┘ └──────────────────────────────────┘ └────────────┘ │ | ||
* │ │ | ||
* │ │ | ||
* └──────────────────────────────────────────────────────────────────────────┘ | ||
* | ||
* See {@link #unchain} to reverse the chaining. | ||
*/ | ||
chain(chainedFocusCycler: FocusCycler): void; | ||
/** | ||
* Reverses a chaining made by {@link #chain}. | ||
*/ | ||
unchain(otherFocusCycler: FocusCycler): void; | ||
/** | ||
* Focuses the given view if it exists. | ||
@@ -214,8 +263,5 @@ * | ||
}; | ||
export interface FocusCyclerActions { | ||
focusFirst?: ArrayOrItem<string>; | ||
focusLast?: ArrayOrItem<string>; | ||
focusNext?: ArrayOrItem<string>; | ||
focusPrevious?: ArrayOrItem<string>; | ||
} | ||
export type FocusCyclerActions = { | ||
[key in 'focusFirst' | 'focusLast' | 'focusPrevious' | 'focusNext']?: ArrayOrItem<string>; | ||
}; | ||
/** | ||
@@ -222,0 +268,0 @@ * Fired when the focus cycler is about to move the focus from the last focusable item |
{ | ||
"name": "@ckeditor/ckeditor5-ui", | ||
"version": "0.0.0-nightly-20240730.0", | ||
"version": "0.0.0-nightly-20240731.0", | ||
"description": "The UI framework and standard UI library of CKEditor 5.", | ||
@@ -15,4 +15,4 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-core": "0.0.0-nightly-20240730.0", | ||
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20240730.0", | ||
"@ckeditor/ckeditor5-core": "0.0.0-nightly-20240731.0", | ||
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20240731.0", | ||
"color-convert": "2.0.1", | ||
@@ -19,0 +19,0 @@ "color-parse": "1.4.2", |
@@ -27,3 +27,3 @@ /** | ||
/** | ||
* @inheritdoc | ||
* @inheritDoc | ||
*/ | ||
@@ -30,0 +30,0 @@ constructor(...args) { |
@@ -416,16 +416,3 @@ /** | ||
if (isViewWithFocusCycler(focusable)) { | ||
this.listenTo(focusable.focusCycler, 'forwardCycle', evt => { | ||
this._focusCycler.focusNext(); | ||
// Stop the event propagation only if there are more focusables. | ||
if (this._focusCycler.next !== this._focusCycler.focusables.get(this._focusCycler.current)) { | ||
evt.stop(); | ||
} | ||
}); | ||
this.listenTo(focusable.focusCycler, 'backwardCycle', evt => { | ||
this._focusCycler.focusPrevious(); | ||
// Stop the event propagation only if there are more focusables. | ||
if (this._focusCycler.previous !== this._focusCycler.focusables.get(this._focusCycler.current)) { | ||
evt.stop(); | ||
} | ||
}); | ||
this._focusCycler.chain(focusable.focusCycler); | ||
} | ||
@@ -432,0 +419,0 @@ }); |
@@ -59,3 +59,4 @@ /** | ||
], | ||
dir: this.locale.uiLanguageDirection | ||
dir: this.locale.uiLanguageDirection, | ||
role: 'application' | ||
}, | ||
@@ -62,0 +63,0 @@ children: this |
@@ -8,3 +8,3 @@ /** | ||
*/ | ||
import { type ArrayOrItem, type FocusTracker, type KeystrokeHandler } from '@ckeditor/ckeditor5-utils'; | ||
import { type ArrayOrItem, type FocusTracker, type KeystrokeHandler, type KeystrokeHandlerOptions } from '@ckeditor/ckeditor5-utils'; | ||
import type View from './view.js'; | ||
@@ -109,2 +109,3 @@ import type ViewCollection from './viewcollection.js'; | ||
keystrokeHandler?: KeystrokeHandler; | ||
keystrokeHandlerOptions?: KeystrokeHandlerOptions; | ||
actions?: FocusCyclerActions; | ||
@@ -170,2 +171,50 @@ }); | ||
/** | ||
* Allows for creating continuous focus cycling across multiple focus cyclers and their collections of {@link #focusables}. | ||
* | ||
* It starts listening to the {@link module:ui/focuscycler~FocusCyclerForwardCycleEvent} and | ||
* {@link module:ui/focuscycler~FocusCyclerBackwardCycleEvent} events of the chained focus cycler and engages, | ||
* whenever the user reaches the last (forwards navigation) or first (backwards navigation) focusable view | ||
* and would normally start over. Instead, the navigation continues on the higher level (flattens). | ||
* | ||
* For instance, for the following nested focus navigation structure, the focus would get stuck the moment | ||
* the AB gets focused and its focus cycler starts managing it: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├───┐ │ │ │ | ||
* │ ├───► │ └─────┘ └─────┘ └─────┘ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ └──────────────────────────────┘ │ │ │ | ||
* │ │ │ │ │ │ | ||
* └────────────┘ └──────────────────────────────────┘ └────────────┘ | ||
* | ||
* Chaining a focus tracker that manages AA, AB, and AC with the focus tracker that manages ABA, ABB, and ABC | ||
* creates a seamless navigation experience instead: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├──┐ │ │ │ | ||
* ┌──► ├───┼─┘ └─────┘ └─────┘ └─────┘ └──┼───► ├──┐ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ └────────────┘ └──────────────────────────────────┘ └────────────┘ │ | ||
* │ │ | ||
* │ │ | ||
* └──────────────────────────────────────────────────────────────────────────┘ | ||
* | ||
* See {@link #unchain} to reverse the chaining. | ||
*/ | ||
chain(chainedFocusCycler: FocusCycler): void; | ||
/** | ||
* Reverses a chaining made by {@link #chain}. | ||
*/ | ||
unchain(otherFocusCycler: FocusCycler): void; | ||
/** | ||
* Focuses the given view if it exists. | ||
@@ -210,8 +259,5 @@ * | ||
}; | ||
export interface FocusCyclerActions { | ||
focusFirst?: ArrayOrItem<string>; | ||
focusLast?: ArrayOrItem<string>; | ||
focusNext?: ArrayOrItem<string>; | ||
focusPrevious?: ArrayOrItem<string>; | ||
} | ||
export type FocusCyclerActions = { | ||
[key in 'focusFirst' | 'focusLast' | 'focusPrevious' | 'focusNext']?: ArrayOrItem<string>; | ||
}; | ||
/** | ||
@@ -218,0 +264,0 @@ * Fired when the focus cycler is about to move the focus from the last focusable item |
@@ -83,3 +83,3 @@ /** | ||
cancel(); | ||
}); | ||
}, options.keystrokeHandlerOptions); | ||
} | ||
@@ -203,2 +203,80 @@ } | ||
/** | ||
* Allows for creating continuous focus cycling across multiple focus cyclers and their collections of {@link #focusables}. | ||
* | ||
* It starts listening to the {@link module:ui/focuscycler~FocusCyclerForwardCycleEvent} and | ||
* {@link module:ui/focuscycler~FocusCyclerBackwardCycleEvent} events of the chained focus cycler and engages, | ||
* whenever the user reaches the last (forwards navigation) or first (backwards navigation) focusable view | ||
* and would normally start over. Instead, the navigation continues on the higher level (flattens). | ||
* | ||
* For instance, for the following nested focus navigation structure, the focus would get stuck the moment | ||
* the AB gets focused and its focus cycler starts managing it: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├───┐ │ │ │ | ||
* │ ├───► │ └─────┘ └─────┘ └─────┘ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ └──────────────────────────────┘ │ │ │ | ||
* │ │ │ │ │ │ | ||
* └────────────┘ └──────────────────────────────────┘ └────────────┘ | ||
* | ||
* Chaining a focus tracker that manages AA, AB, and AC with the focus tracker that manages ABA, ABB, and ABC | ||
* creates a seamless navigation experience instead: | ||
* | ||
* ┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ | ||
* │ AA │ │ AB │ │ AC │ | ||
* │ │ │ │ │ │ | ||
* │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ | ||
* │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├──┐ │ │ │ | ||
* ┌──► ├───┼─┘ └─────┘ └─────┘ └─────┘ └──┼───► ├──┐ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ │ │ │ │ │ │ │ | ||
* │ └────────────┘ └──────────────────────────────────┘ └────────────┘ │ | ||
* │ │ | ||
* │ │ | ||
* └──────────────────────────────────────────────────────────────────────────┘ | ||
* | ||
* See {@link #unchain} to reverse the chaining. | ||
*/ | ||
chain(chainedFocusCycler) { | ||
const getCurrentFocusedView = () => { | ||
// This may happen when one focus cycler does not include focusables of the other (horizontal case). | ||
if (this.current === null) { | ||
return null; | ||
} | ||
return this.focusables.get(this.current); | ||
}; | ||
this.listenTo(chainedFocusCycler, 'forwardCycle', evt => { | ||
const oldCurrent = getCurrentFocusedView(); | ||
this.focusNext(); | ||
// Stop the event propagation only if an attempt at focusing the view actually moved the focus. | ||
// If not, let the otherFocusCycler handle the event. | ||
if (oldCurrent !== getCurrentFocusedView()) { | ||
evt.stop(); | ||
} | ||
// The priority is critical for cycling across multiple chain levels when there's a single view at some of them only. | ||
}, { priority: 'low' }); | ||
this.listenTo(chainedFocusCycler, 'backwardCycle', evt => { | ||
const oldCurrent = getCurrentFocusedView(); | ||
this.focusPrevious(); | ||
// Stop the event propagation only if an attempt at focusing the view actually moved the focus. | ||
// If not, let the otherFocusCycler handle the event. | ||
if (oldCurrent !== getCurrentFocusedView()) { | ||
evt.stop(); | ||
} | ||
// The priority is critical for cycling across multiple chain levels when there's a single view at some of them only. | ||
}, { priority: 'low' }); | ||
} | ||
/** | ||
* Reverses a chaining made by {@link #chain}. | ||
*/ | ||
unchain(otherFocusCycler) { | ||
this.stopListening(otherFocusCycler); | ||
} | ||
/** | ||
* Focuses the given view if it exists. | ||
@@ -205,0 +283,0 @@ * |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
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
6336723
61509
+ Added@ckeditor/ckeditor5-core@0.0.0-nightly-20240731.0(transitive)
+ Added@ckeditor/ckeditor5-engine@0.0.0-nightly-20240731.0(transitive)
+ Added@ckeditor/ckeditor5-utils@0.0.0-nightly-20240731.0(transitive)
+ Added@ckeditor/ckeditor5-watchdog@0.0.0-nightly-20240731.0(transitive)
- Removed@ckeditor/ckeditor5-core@0.0.0-nightly-20240730.0(transitive)
- Removed@ckeditor/ckeditor5-engine@0.0.0-nightly-20240730.0(transitive)
- Removed@ckeditor/ckeditor5-utils@0.0.0-nightly-20240730.0(transitive)
- Removed@ckeditor/ckeditor5-watchdog@0.0.0-nightly-20240730.0(transitive)