-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,939 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
packages/ckeditor5-ui/src/button/buttonlabelwithhighlightview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module ui/button/buttonlabelwithhighlightview | ||
*/ | ||
|
||
import type ButtonLabel from './buttonlabel.js'; | ||
import HighlightedTextView from '../highlightedtext/highlightedtextview.js'; | ||
|
||
/** | ||
* A button label view that can highlight a text fragment. | ||
*/ | ||
export default class ButtonLabelWithHighlightView extends HighlightedTextView implements ButtonLabel { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
declare public style: string | undefined; | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
declare public text: string | undefined; | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
declare public id: string | undefined; | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
constructor() { | ||
super(); | ||
|
||
this.set( { | ||
style: undefined, | ||
text: undefined, | ||
id: undefined | ||
} ); | ||
|
||
const bind = this.bindTemplate; | ||
|
||
this.extendTemplate( { | ||
attributes: { | ||
class: [ | ||
'ck-button__label' | ||
], | ||
style: bind.to( 'style' ), | ||
id: bind.to( 'id' ) | ||
} | ||
} ); | ||
} | ||
} |
136 changes: 136 additions & 0 deletions
136
packages/ckeditor5-ui/src/dropdown/menu/filterview/dropdownmenulistfilteredview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module ui/dropdown/menu/filterview/dropdownmenulistfilteredview | ||
*/ | ||
|
||
import type { Editor } from '@ckeditor/ckeditor5-core'; | ||
import type { DropdownMenuDefinition } from '../definition/dropdownmenudefinitiontypings.js'; | ||
import type FilteredView from '../../../search/filteredview.js'; | ||
|
||
import { filterDropdownMenuTreeByRegExp, type DropdownMenuSearchResult } from '../tree/dropdownmenutreefilterutils.js'; | ||
|
||
import View from '../../../view.js'; | ||
import DropdownMenuListFoundItemsView from './dropdownmenulistfounditemsview.js'; | ||
import DropdownMenuRootListView, { type DropdownMenuRootListViewAttributes } from '../dropdownmenurootlistview.js'; | ||
|
||
/** | ||
* Represents a filtered view for a dropdown menu list. | ||
* This class extends the `View` class and implements the `FilteredView` interface. | ||
*/ | ||
export default class DropdownMenuListFilteredView extends View implements FilteredView { | ||
/** | ||
* The root list view of the dropdown menu. | ||
*/ | ||
protected _menuView: DropdownMenuRootListView; | ||
|
||
/** | ||
* The found list view of the dropdown menu. | ||
*/ | ||
protected _foundListView: DropdownMenuListFoundItemsView | null = null; | ||
|
||
/** | ||
* Represents a filtered view for the dropdown menu list. | ||
*/ | ||
constructor( | ||
editor: Editor, | ||
definitions: Array<DropdownMenuDefinition>, | ||
menuAttributes?: DropdownMenuRootListViewAttributes | ||
) { | ||
super( editor.locale ); | ||
|
||
this._menuView = new DropdownMenuRootListView( editor, definitions, menuAttributes ); | ||
this.setTemplate( { | ||
tag: 'div', | ||
|
||
attributes: { | ||
class: [ | ||
'ck', | ||
'ck-dropdown-menu-filter' | ||
], | ||
tabindex: -1 | ||
}, | ||
|
||
children: [ | ||
this._menuView | ||
] | ||
} ); | ||
} | ||
|
||
/** | ||
* The root list view of the dropdown menu. | ||
*/ | ||
public get menuView(): DropdownMenuRootListView { | ||
return this._menuView; | ||
} | ||
|
||
/** | ||
* Gets the found list view of the dropdown menu. | ||
*/ | ||
public get foundListView(): DropdownMenuListFoundItemsView | null { | ||
return this._foundListView; | ||
} | ||
|
||
/** | ||
* Filters the dropdown menu list based on the provided regular expression. | ||
* | ||
* @param regExp The regular expression to filter the list. | ||
* @returns An object containing the number of filtered results and the total number of items in the list. | ||
*/ | ||
public filter( regExp: RegExp | null ): DropdownMenuSearchResult { | ||
const { element } = this; | ||
|
||
if ( regExp ) { | ||
// Preload all menus to ensure that all items are available for filtering. | ||
this._menuView.preloadAllMenus(); | ||
} | ||
|
||
const { filteredTree, resultsCount, totalItemsCount } = filterDropdownMenuTreeByRegExp( | ||
regExp, | ||
this._menuView.tree | ||
); | ||
|
||
element!.innerHTML = ''; | ||
|
||
if ( this._foundListView ) { | ||
this._foundListView.destroy(); | ||
this._foundListView = null; | ||
} | ||
|
||
if ( resultsCount !== totalItemsCount ) { | ||
this._foundListView = new DropdownMenuListFoundItemsView( this.locale!, filteredTree, { | ||
highlightRegex: regExp, | ||
limitFoundItemsCount: 25 | ||
} ); | ||
|
||
this._menuView.close(); | ||
this._foundListView.render(); | ||
|
||
element!.appendChild( this._foundListView.element! ); | ||
} else { | ||
element!.appendChild( this._menuView.element! ); | ||
} | ||
|
||
return { | ||
filteredTree, | ||
resultsCount, | ||
totalItemsCount | ||
}; | ||
} | ||
|
||
/** | ||
* Sets the focus on the dropdown menu list. | ||
*/ | ||
public focus(): void { | ||
const { _menuView, _foundListView } = this; | ||
|
||
if ( _foundListView ) { | ||
_foundListView.focus(); | ||
} else { | ||
_menuView.focus(); | ||
} | ||
} | ||
} |
139 changes: 139 additions & 0 deletions
139
packages/ckeditor5-ui/src/dropdown/menu/filterview/dropdownmenulistfounditemsview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module ui/dropdown/menu/filterview/dropdownmenulistfounditemsview | ||
*/ | ||
|
||
import type { Locale } from '@ckeditor/ckeditor5-utils'; | ||
import { | ||
groupDropdownTreeByFirstFoundParent, | ||
type DropdownMenusViewsFilteredFlatItem, | ||
type DropdownMenusViewsFilteredTreeNode | ||
} from '../tree/dropdownmenutreefilterutils.js'; | ||
|
||
import ButtonLabelWithHighlightView from '../../../button/buttonlabelwithhighlightview.js'; | ||
import ButtonView from '../../../button/buttonview.js'; | ||
import LabelWithHighlightView from '../../../label/labelwithhighlightview.js'; | ||
import ListItemGroupView from '../../../list/listitemgroupview.js'; | ||
import ListItemView from '../../../list/listitemview.js'; | ||
import ListView from '../../../list/listview.js'; | ||
|
||
/** | ||
* Represents a view for the found list in the dropdown menu list. | ||
*/ | ||
export default class DropdownMenuListFoundItemsView extends ListView { | ||
/** | ||
* The maximum number of found items to display. It prevents slow rendering when there are too many items. | ||
*/ | ||
private readonly config: FoundItemsViewRenderConfig; | ||
|
||
/** | ||
* Creates a new instance of the DropdownMenuListFoundItemsView class. | ||
* | ||
* @param locale The locale object. | ||
* @param tree The filtered tree node. | ||
* @param config The configuration object. | ||
*/ | ||
constructor( | ||
locale: Locale, | ||
tree: DropdownMenusViewsFilteredTreeNode, | ||
config: FoundItemsViewRenderConfig | ||
) { | ||
super( locale ); | ||
|
||
this.config = config; | ||
this.role = 'listbox'; | ||
|
||
const items = this._createFilteredTreeListBox( tree ); | ||
|
||
if ( items.length ) { | ||
this.items.addMany( items ); | ||
} | ||
} | ||
|
||
/** | ||
* Creates a filtered tree list box based on the provided highlight regex and tree data. | ||
* | ||
* @param highlightRegex The regular expression used for highlighting the filtered items. | ||
* @param tree The tree data used to create the filtered tree list box. | ||
* @returns An array of ListItemGroupView or ListItemView objects representing the filtered tree list box. | ||
*/ | ||
private _createFilteredTreeListBox( | ||
tree: DropdownMenusViewsFilteredTreeNode | ||
): Array<ListItemGroupView | ListItemView> { | ||
const { locale, config } = this; | ||
const { highlightRegex, limitFoundItemsCount } = config; | ||
|
||
const groupedFlatEntries = groupDropdownTreeByFirstFoundParent( tree ); | ||
|
||
// Map each flat child node to a ListItemView | ||
const mapFlatChildNodeToView = ( entry: DropdownMenusViewsFilteredFlatItem ): ListItemView => { | ||
const listItemView = new ListItemView( locale ); | ||
const labelView = new ButtonLabelWithHighlightView(); | ||
const button = new ButtonView( locale, labelView ); | ||
|
||
button.set( { | ||
label: entry.search.raw, | ||
withText: true, | ||
role: 'option' | ||
} ); | ||
|
||
listItemView.children.add( button ); | ||
labelView.highlightText( highlightRegex ); | ||
|
||
button.delegate( 'execute' ).to( entry.item ); | ||
button.bind( 'isEnabled' ).to( entry.item, 'isEnabled' ); | ||
|
||
return listItemView; | ||
}; | ||
|
||
// The total number of items rendered in the dropdown menu list. | ||
let totalRenderedItems = 0; | ||
|
||
// Create the filtered tree list box | ||
return groupedFlatEntries.flatMap<ListItemGroupView | ListItemView>( ( { parent, children } ) => { | ||
const listItems = children | ||
.slice( 0, limitFoundItemsCount - totalRenderedItems ) | ||
.map( mapFlatChildNodeToView ); | ||
|
||
if ( !listItems.length ) { | ||
return []; | ||
} | ||
|
||
totalRenderedItems += listItems.length; | ||
|
||
if ( parent.type === 'Root' ) { | ||
return listItems; | ||
} | ||
|
||
const labelView = new LabelWithHighlightView(); | ||
const groupView = new ListItemGroupView( locale, labelView ); | ||
|
||
groupView.label = parent.search.raw; | ||
groupView.items.addMany( listItems ); | ||
|
||
labelView.highlightText( highlightRegex ); | ||
|
||
return [ groupView ]; | ||
} ); | ||
} | ||
} | ||
|
||
/** | ||
* Configuration options for rendering the FoundItemsView in the DropdownMenuList. | ||
*/ | ||
type FoundItemsViewRenderConfig = { | ||
|
||
/** | ||
* A regular expression used to highlight matching items in the view. If set to `null`, highlighting will be disabled. | ||
*/ | ||
highlightRegex: RegExp | null; | ||
|
||
/** | ||
* The maximum number of found items to display in the view. | ||
*/ | ||
limitFoundItemsCount: number; | ||
}; |
Oops, something went wrong.