Socket
Socket
Sign inDemoInstall

@ckeditor/ckeditor5-ui

Package Overview
Dependencies
Maintainers
1
Versions
611
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-ui - npm Package Compare versions

Comparing version 42.0.2 to 43.0.0-alpha.0

dist/button/listitembuttonview.d.ts

540

CHANGELOG.md
Changelog
=========
All changes in the package are documented in the main repository. See: https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.
Changes for the past releases are available below.
## [19.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v18.0.0...v19.0.0) (April 29, 2020)
### MAJOR BREAKING CHANGES
* `ViewCollection` no longer has the `locale` property.
* The `ViewCollection#constructor()` no longer accepts the `locale` parameter.
* `LabeledView` component was renamed to `LabeledFieldView`. Also, its instance of a labeled component's view is available through `LabeledFieldView#fieldView`. It replaced the `LabeledView#view`.
### MINOR BREAKING CHANGES
* The `DropdownView#focusTracker` property has been removed as it served no purpose.
### Features
* Allowed defining initial items of `ViewCollection` and `BodyCollection` in the constructor. See [ckeditor/ckeditor5#6319](https://github.com/ckeditor/ckeditor5/issues/6319). ([6cd15de](https://github.com/ckeditor/ckeditor5-ui/commit/6cd15de))
The `View#createCollection()` method now also accepts an iterator of views.
* Introduce `FormHeaderView` UI component. Closes [ckeditor/ckeditor5#6109](https://github.com/ckeditor/ckeditor5/issues/6109). ([eb1ce18](https://github.com/ckeditor/ckeditor5-ui/commit/eb1ce18))
* The `BlockToolbar` should group items when there is no place to show them all. Closes [ckeditor/ckeditor5#6449](https://github.com/ckeditor/ckeditor5/issues/6449). Closes [ckeditor/ckeditor5#6575](https://github.com/ckeditor/ckeditor5/issues/6575). Closes [ckeditor/ckeditor5#6570](https://github.com/ckeditor/ckeditor5/issues/6570). ([fcd9c4e](https://github.com/ckeditor/ckeditor5-ui/commit/fcd9c4e))
Improved `ToolbarView#maxWidth` and items grouping when the toolbar is invisible.
### Bug fixes
* Call `ResizeObserver.destroy()` when destroying block toolbar. ([59449d2](https://github.com/ckeditor/ckeditor5-ui/commit/59449d2))
### Other changes
* Removed the obsolete `DropdownView#focusTracker`. Closes [ckeditor/ckeditor5#6548](https://github.com/ckeditor/ckeditor5/issues/6548). ([ac750c7](https://github.com/ckeditor/ckeditor5-ui/commit/ac750c7))
* Rename `LabeledView` component to `LabeledFieldView`. See [ckeditor/ckeditor5#6110](https://github.com/ckeditor/ckeditor5/issues/6110). ([5a7aca7](https://github.com/ckeditor/ckeditor5-ui/commit/5a7aca7))
* Updated translations. ([2a391d6](https://github.com/ckeditor/ckeditor5-ui/commit/2a391d6))
## [18.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v17.0.0...v18.0.0) (March 19, 2020)
### MAJOR BREAKING CHANGES
* The `BalloonToolbar` plugin now groups the overflowing items by default. This can be disabled by setting [`config.balloonToolbar.shouldNotGroupWhenFull`](https://ckeditor.com/docs/ckeditor5/latest/api/module_ui_toolbar_toolbarview-ToolbarOptions.html#member-shouldGroupWhenFull) configuration to `true`.
### Features
* The `BalloonToolbar` plugin should group items when its width is close to related editable element's width. Closes [ckeditor/ckeditor5#5597](https://github.com/ckeditor/ckeditor5/issues/5597). Closes [ckeditor/ckeditor5#5501](https://github.com/ckeditor/ckeditor5/issues/5501). ([d36fd23](https://github.com/ckeditor/ckeditor5-ui/commit/d36fd23))
[`BalloonPanelView.defaultPositions`](https://ckeditor.com/docs/ckeditor5/latest/api/module_ui_panel_balloon_balloonpanelview-BalloonPanelView.html#static-member-defaultPositions) has been extended with additional positions. Refer to the documentation to learn more.
### Other changes
* Updated translations. ([ace38eb](https://github.com/ckeditor/ckeditor5-ui/commit/ace38eb))
## [17.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v16.0.0...v17.0.0) (February 19, 2020)
### Features
* Created the `LabeledView` class (see https://github.com/ckeditor/ckeditor5-table/pull/227). ([ec39406](https://github.com/ckeditor/ckeditor5-ui/commit/ec39406))
Also added `id` properties to the `DropdownView` and `LabelView` for compatibility with the `LabeledView`.
* Implemented the `Toolbar#isCompact` property to turn regular toolbars into compact ones (with less spacing) (see [ckeditor/ckeditor5#6112](https://github.com/ckeditor/ckeditor5/issues/6112)). ([a6b9c09](https://github.com/ckeditor/ckeditor5-ui/commit/a6b9c09))
* Reintroduced the concept of body collections with a focus on better management of multiple editors and support for context plugins (plugins which leave outside an editor instance). Closes [ckeditor/ckeditor5#5888](https://github.com/ckeditor/ckeditor5/issues/5888). ([23d12e9](https://github.com/ckeditor/ckeditor5-ui/commit/23d12e9))
### Bug fixes
* Make `BlockToolbar` work with an empty configuration. Closes [ckeditor/ckeditor5#5980](https://github.com/ckeditor/ckeditor5/issues/5980). ([1e05098](https://github.com/ckeditor/ckeditor5-ui/commit/1e05098))
### Other changes
* Replaced the `getResizeObserver()` helper with new `ResizeObserver` class in `ToolbarView`. ([be98aa4](https://github.com/ckeditor/ckeditor5-ui/commit/be98aa4))
Follow-up on: https://github.com/ckeditor/ckeditor5-utils/pull/320
* Updated translations. ([b8bd38e](https://github.com/ckeditor/ckeditor5-ui/commit/b8bd38e))
## [16.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v15.0.0...v16.0.0) (December 4, 2019)
### Features
* Enabled keystroke preview in `ButtonView`. Implemented the `ButtonView#withKeystroke` property. Closes [ckeditor/ckeditor5#5782](https://github.com/ckeditor/ckeditor5/issues/5782). ([dac8ce0](https://github.com/ckeditor/ckeditor5-ui/commit/dac8ce0))
### Bug fixes
* Use relative positioning for dropdowns to prevent ugly blurring in Chrome. Closes [ckeditor/ckeditor5#1053](https://github.com/ckeditor/ckeditor5/issues/1053). ([95404e3](https://github.com/ckeditor/ckeditor5-ui/commit/95404e3))
### Other changes
* Updated translations. ([16ee253](https://github.com/ckeditor/ckeditor5-ui/commit/16ee253))
## [15.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v14.0.0...v15.0.0) (October 23, 2019)
### MAJOR BREAKING CHANGES
* The internal structure of the toolbar component has changed. Toolbar items are no longer direct descendants of the toolbar in the DOM, which may affect some integrations (mainly CSS selectors if adjustments were made to the styles).
### Features
* The editor toolbar is now responsive. Closes [ckeditor/ckeditor5#416](https://github.com/ckeditor/ckeditor5/issues/416). ([46911bf](https://github.com/ckeditor/ckeditor5-ui/commit/46911bf))
### Other changes
* Updated translations. ([c233bb7](https://github.com/ckeditor/ckeditor5-ui/commit/c233bb7)) ([f8f07b2](https://github.com/ckeditor/ckeditor5-ui/commit/f8f07b2))
## [14.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v13.0.2...v14.0.0) (August 26, 2019)
### Features
* Brought support for right–to–left (RTL) languages to various UI components. See [ckeditor/ckeditor5#1151](https://github.com/ckeditor/ckeditor5/issues/1151). ([d6c7f55](https://github.com/ckeditor/ckeditor5-ui/commit/d6c7f55))
### Bug fixes
* `ColorGrid` should set the `#isOn` property value of new `ColorTiles`. See [ckeditor/ckeditor5-font#51](https://github.com/ckeditor/ckeditor5-font/issues/51). ([e89ad60](https://github.com/ckeditor/ckeditor5-ui/commit/e89ad60))
* All editor toolbars should come with the `role` and `aria-label` attributes. Closes [ckeditor/ckeditor5#1404](https://github.com/ckeditor/ckeditor5/issues/1404). ([bdede90](https://github.com/ckeditor/ckeditor5-ui/commit/bdede90))
* Screen reader will now properly prompt errors for text inputs. Closes [ckeditor/ckeditor5#1406](https://github.com/ckeditor/ckeditor5/issues/1406). ([3a164b7](https://github.com/ckeditor/ckeditor5-ui/commit/3a164b7))
### Other changes
* The issue tracker for this package was moved to https://github.com/ckeditor/ckeditor5/issues. See [ckeditor/ckeditor5#1988](https://github.com/ckeditor/ckeditor5/issues/1988). ([451df7b](https://github.com/ckeditor/ckeditor5-ui/commit/451df7b))
* Updated translations. ([eca9fe6](https://github.com/ckeditor/ckeditor5-ui/commit/eca9fe6))
### BREAKING CHANGES
* The `ToolbarView` class requires the [editor locale](https://ckeditor.com/docs/ckeditor5/latest/api/module_utils_locale-Locale.html) to be passed into the constructor.
## [13.0.2](https://github.com/ckeditor/ckeditor5-ui/compare/v13.0.1...v13.0.2) (July 10, 2019)
### Other changes
* Updated translations. ([ad189b6](https://github.com/ckeditor/ckeditor5-ui/commit/ad189b6))
## [13.0.1](https://github.com/ckeditor/ckeditor5-ui/compare/v13.0.0...v13.0.1) (July 4, 2019)
### Other changes
* Updated translations. ([1964cc0](https://github.com/ckeditor/ckeditor5-ui/commit/1964cc0)) ([11cfd41](https://github.com/ckeditor/ckeditor5-ui/commit/11cfd41))
## [13.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v12.1.0...v13.0.0) (June 6, 2019)
### Features
* Implemented the single view mode for the `ContextualBalloon` plugin. See https://github.com/ckeditor/ckeditor5-mention/issues/74. ([c000c93](https://github.com/ckeditor/ckeditor5-ui/commit/c000c93))
* Introduced rotatable panels for `ContextualBalloon`. Closes https://github.com/ckeditor/ckeditor5-ui/issues/491. ([581d8f7](https://github.com/ckeditor/ckeditor5-ui/commit/581d8f7))
### Other changes
* Renamed a misspelled `InputTextViewariaDesribedById` property to `InputTextView#ariaDescribedById`. Closes [#483](https://github.com/ckeditor/ckeditor5-ui/issues/483). ([2288bf3](https://github.com/ckeditor/ckeditor5-ui/commit/2288bf3))
* The `_rwd.css` mixin was moved to this package from `@ckeditor/ckeditor5-theme-lark`. See [ckeditor/ckeditor5#1662](https://github.com/ckeditor/ckeditor5/issues/1662). ([96e3a3c](https://github.com/ckeditor/ckeditor5-ui/commit/96e3a3c))
* The `ContextualBalloon#add()` method should accept the `withArrow` option. Closes [#487](https://github.com/ckeditor/ckeditor5-ui/issues/487). ([0e7f670](https://github.com/ckeditor/ckeditor5-ui/commit/0e7f670))
* Updated translations. ([4699d8b](https://github.com/ckeditor/ckeditor5-ui/commit/4699d8b)) ([d4c5714](https://github.com/ckeditor/ckeditor5-ui/commit/d4c5714))
### BREAKING CHANGES
* The (misspelled) `InputTextView#ariaDesribedById` property is no longer available. Use `ariaDescribedById` instead.
## [12.1.0](https://github.com/ckeditor/ckeditor5-ui/compare/v12.0.0...v12.1.0) (April 4, 2019)
### Features
* Implemented `ColorGridView` and `ColorTileView` components. See [ckeditor/ckeditor5#1457](https://github.com/ckeditor/ckeditor5/issues/1457). ([6be52b4](https://github.com/ckeditor/ckeditor5-ui/commit/6be52b4))
### Bug fixes
* Fixed `View#render` collision when moving focus from a one editable to the other in multi-root editor. Closes https://github.com/ckeditor/ckeditor5/issues/1676. ([17e86f9](https://github.com/ckeditor/ckeditor5-ui/commit/17e86f9))
### Other changes
* Optimized icons. ([5325ea8](https://github.com/ckeditor/ckeditor5-ui/commit/5325ea8))
* Updated translations. ([dcdca2e](https://github.com/ckeditor/ckeditor5-ui/commit/dcdca2e))
## [12.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v11.2.0...v12.0.0) (February 28, 2019)
### Bug fixes
* Prevented from changing the view document during the render phase. Closes https://github.com/ckeditor/ckeditor5/issues/1530. ([7cf835e](https://github.com/ckeditor/ckeditor5-ui/commit/7cf835e))
* Fixed memory leaks during editor initialization and destruction (see [ckeditor/ckeditor5#1341](https://github.com/ckeditor/ckeditor5/issues/1341)). ([fd18fb9](https://github.com/ckeditor/ckeditor5-ui/commit/fd18fb9))
### Other changes
* The `class` property should control the DOM class attribute in all UI components. Closes [#450](https://github.com/ckeditor/ckeditor5-ui/issues/450). ([b9b68c6](https://github.com/ckeditor/ckeditor5-ui/commit/b9b68c6))
* Updated translations. ([b9caee9](https://github.com/ckeditor/ckeditor5-ui/commit/b9caee9)) ([a3afaaa](https://github.com/ckeditor/ckeditor5-ui/commit/a3afaaa)) ([909e676](https://github.com/ckeditor/ckeditor5-ui/commit/909e676))
### BREAKING CHANGES
* Upgraded minimal versions of Node to `8.0.0` and npm to `5.7.1`. See: [ckeditor/ckeditor5#1507](https://github.com/ckeditor/ckeditor5/issues/1507). ([612ea3c](https://github.com/ckeditor/ckeditor5-cloud-services/commit/612ea3c))
* The `BallonPanelView#className` property was renamed to `#class`.
* The `ToolbarView#className` property was renamed to `#class`.
* The `EditableUIView#externalElement` property (which held the element on which the editor was created if it was explicitly passed) was removed.
* The `EditorUIView#editableElement` property was made private. Use `editor.ui.getEditableElement()` method instead.
## [11.2.0](https://github.com/ckeditor/ckeditor5-ui/compare/v11.1.0...v11.2.0) (December 5, 2018)
### Features
* Added the `.ck-read-only` CSS class to the `EditableUIView` when `#isReadOnly` is `true`. ([4119822](https://github.com/ckeditor/ckeditor5-ui/commit/4119822))
* Added the optional `DropdownView#class` property to set a custom CSS class on the main element in DOM. Closes [#447](https://github.com/ckeditor/ckeditor5-ui/issues/447). ([9cdcd4a](https://github.com/ckeditor/ckeditor5-ui/commit/9cdcd4a))
Thanks to [@lucasreppewelander](https://github.com/lucasreppewelander)!
* Implemented `LabeledInputView#infoText` to display useful hints next to the input (see [ckeditor/ckeditor5-media-embed#35](https://github.com/ckeditor/ckeditor5-media-embed/issues/35)). ([6ac03ea](https://github.com/ckeditor/ckeditor5-ui/commit/6ac03ea))
* Implemented configurable, smart `DropdownView` panel positioning. Closes [#123](https://github.com/ckeditor/ckeditor5-ui/issues/123). ([8094f19](https://github.com/ckeditor/ckeditor5-ui/commit/8094f19))
### Other changes
* Improved SVG icons size. See [ckeditor/ckeditor5-theme-lark#206](https://github.com/ckeditor/ckeditor5-theme-lark/issues/206). ([ed88305](https://github.com/ckeditor/ckeditor5-ui/commit/ed88305))
* Updated translations. ([2e409a9](https://github.com/ckeditor/ckeditor5-ui/commit/2e409a9)) ([611bd04](https://github.com/ckeditor/ckeditor5-ui/commit/611bd04)) ([c6689e4](https://github.com/ckeditor/ckeditor5-ui/commit/c6689e4)) ([07c4fdb](https://github.com/ckeditor/ckeditor5-ui/commit/07c4fdb))
## [11.1.0](https://github.com/ckeditor/ckeditor5-ui/compare/v11.0.0...v11.1.0) (October 8, 2018)
### Features
* Allowed displaying an error message next to the `LabeledInputVIew` (see [ckeditor/ckeditor5-media-embed#1](https://github.com/ckeditor/ckeditor5-media-embed/issues/1)). ([81aaea4](https://github.com/ckeditor/ckeditor5-ui/commit/81aaea4))
### Bug fixes
* Made the `Edit block` string translatable. Closes [#445](https://github.com/ckeditor/ckeditor5-ui/issues/445). ([1fa84e9](https://github.com/ckeditor/ckeditor5-ui/commit/1fa84e9))
### Other changes
* Updated translations. ([baff3c9](https://github.com/ckeditor/ckeditor5-ui/commit/baff3c9))
* Updated translations. ([e58bcbb](https://github.com/ckeditor/ckeditor5-ui/commit/e58bcbb))
## [11.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v10.1.0...v11.0.0) (July 18, 2018)
### Features
* Implemented the `SwitchButtonView`. Closes [#402](https://github.com/ckeditor/ckeditor5-ui/issues/402). Closes [#403](https://github.com/ckeditor/ckeditor5-ui/issues/403). ([105fbea](https://github.com/ckeditor/ckeditor5-ui/commit/105fbea))
Also:
* Simplified the `ListItemView` class, which is now just a container for `ButtonView` (and others),
* Moved `ListItemView#style` and `#class` to the `ButtonView` (as `#class` and `#labelStyle`),
* Enhanced the `addListToDropdown` utility with a better configuration (`ListDropdownItemDefinition`) and the support for buttons, switch buttons, and separators,
* `.ck-button` and `.ck-list` became `flex` containers; the first one to allow complex inner structures (like the toggle) and the later to take control of complex list items (like `.ck-switchbutton`).
### Bug fixes
* The `BalloonToolbar` should hide when the editable is blurred. Closes [#418](https://github.com/ckeditor/ckeditor5-ui/issues/418). ([f6a02d4](https://github.com/ckeditor/ckeditor5-ui/commit/f6a02d4))
* The `BlockToolbar` should add elements to the `FocusTracker` only after `uiReady` is fired to avoid errors. Closes [#424](https://github.com/ckeditor/ckeditor5-ui/issues/424). ([ae9fa09](https://github.com/ckeditor/ckeditor5-ui/commit/ae9fa09))
* The `BlockToolbar` should hide when the editor is blurred. Closes [#408](https://github.com/ckeditor/ckeditor5-ui/issues/408). ([e3bbccf](https://github.com/ckeditor/ckeditor5-ui/commit/e3bbccf))
### Other changes
* Allowed list item's buttons to have an outer, visible box-shadow. Ensured the balloon panel's arrow does not cover panel's children. Closes [#394](https://github.com/ckeditor/ckeditor5-ui/issues/394). ([8a64ee2](https://github.com/ckeditor/ckeditor5-ui/commit/8a64ee2))
* Updated translations. ([949585d](https://github.com/ckeditor/ckeditor5-ui/commit/949585d))
### BREAKING CHANGES
* Most of the `ListItemView` functionality is now handled by the `ButtonView`,
* The API of the `addListToDropdown` has changed; see `ListDropdownItemDefinition` to learn more,
* The `.ck-button` and `.ck-list` classes are using `flex` which may have an impact on rendering.
## [10.1.0](https://github.com/ckeditor/ckeditor5-ui/compare/v10.0.0...v10.1.0) (June 21, 2018)
### Features
* Implemented list component separators (see [ckeditor/ckeditor5-table#24](https://github.com/ckeditor/ckeditor5-table/issues/24)). ([0808a8c](https://github.com/ckeditor/ckeditor5-ui/commit/0808a8c))
* Introduced the `BlockToolbar` plugin. Closes [#391](https://github.com/ckeditor/ckeditor5-ui/issues/391). ([5868516](https://github.com/ckeditor/ckeditor5-ui/commit/5868516))
### Bug fixes
* The action should be executed upon the first click of a tooltip-enabled UI in iOS. Closes [ckeditor/ckeditor5#920](https://github.com/ckeditor/ckeditor5/issues/920). ([6508ba2](https://github.com/ckeditor/ckeditor5-ui/commit/6508ba2))
* The balloon toolbar should be attached correctly in case of a multi-range selection. Closes [#385](https://github.com/ckeditor/ckeditor5-ui/issues/385). ([714ef21](https://github.com/ckeditor/ckeditor5-ui/commit/714ef21))
* The buttons in the editor should provide basic accessibility. Closes [ckeditor/ckeditor5#1013](https://github.com/ckeditor/ckeditor5/issues/1013). ([9e17d13](https://github.com/ckeditor/ckeditor5-ui/commit/9e17d13))
### Other changes
* Disabling a `ListItemView` should be possible using the `isEnabled` property. Closes [#389](https://github.com/ckeditor/ckeditor5-ui/issues/389). ([76a4d47](https://github.com/ckeditor/ckeditor5-ui/commit/76a4d47))
* Made the `ContextualBalloon` always use the position of the topmost view in the stack (see: [ckeditor/ckeditor5-table#28](https://github.com/ckeditor/ckeditor5-table/issues/28)). Closes [ckeditor/ckeditor5#900](https://github.com/ckeditor/ckeditor5/issues/900). ([a2ef073](https://github.com/ckeditor/ckeditor5-ui/commit/a2ef073))
* Updated translations. ([084e8c6](https://github.com/ckeditor/ckeditor5-ui/commit/084e8c6))
## [10.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v1.0.0-beta.4...v10.0.0) (April 25, 2018)
### Other changes
* Changed the license to GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991). ([f1e5fbf](https://github.com/ckeditor/ckeditor5-ui/commit/f1e5fbf))
### BREAKING CHANGES
* The license under which CKEditor 5 is released has been changed from a triple GPL, LGPL and MPL license to a GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991) for more information.
## [1.0.0-beta.4](https://github.com/ckeditor/ckeditor5-ui/compare/v1.0.0-beta.2...v1.0.0-beta.4) (April 19, 2018)
Internal changes only (updated dependencies, documentation, etc.).
## [1.0.0-beta.2](https://github.com/ckeditor/ckeditor5-ui/compare/v1.0.0-beta.1...v1.0.0-beta.2) (April 10, 2018)
### Other changes
* Renamed plural method names to singular. See [ckeditor/ckeditor5#742](https://github.com/ckeditor/ckeditor5/issues/742). ([48cd53d](https://github.com/ckeditor/ckeditor5-ui/commit/48cd53d))
### BREAKING CHANGES
* `View#registerChildren()` and `View#deregisterChildren()` have been renamed to `View#registerChild()` and `View#deregisterChild()`.
## [1.0.0-beta.1](https://github.com/ckeditor/ckeditor5-ui/compare/v1.0.0-alpha.2...v1.0.0-beta.1) (March 15, 2018)
### Features
* Implemented the `IconView#fillColor` observable which fills child `.ck-icon__fill` paths with the color (see [ckeditor/ckeditor5-theme-lark#148](https://github.com/ckeditor/ckeditor5-theme-lark/issues/148)). ([728a691](https://github.com/ckeditor/ckeditor5-ui/commit/728a691))
* Initial implementation of the `ButtonDropdownView`. Closes [#333](https://github.com/ckeditor/ckeditor5-ui/issues/333). ([6e9c6e4](https://github.com/ckeditor/ckeditor5-ui/commit/6e9c6e4))
Also:
* Allowed vertical layout of the `ToolbarView` thanks to the `#isVertical` attribute.
* Implemented `ToolbarView#className` attribute.
* Implemented `DropdownView#isEnabled` attribute along with the CSS class binding.
* Updated UI components to bring the support for the refreshed Lark theme (see [ckeditor/ckeditor5#645](https://github.com/ckeditor/ckeditor5/issues/645)). ([623d536](https://github.com/ckeditor/ckeditor5-ui/commit/623d536))
### Bug fixes
* Button icon styles should not touch the dropdown's arrow. Closes [ckeditor/ckeditor5#831](https://github.com/ckeditor/ckeditor5/issues/831). ([507549f](https://github.com/ckeditor/ckeditor5-ui/commit/507549f))
### Other changes
* Added a CSS class to the SplitButtonView when the arrow is on (see [ckeditor/ckeditor5-theme-lark#134](https://github.com/ckeditor/ckeditor5-theme-lark/issues/134)). ([d490d61](https://github.com/ckeditor/ckeditor5-ui/commit/d490d61))
* Added the `.ck-content` CSS class to the `EditableUIView` to simplify styling the editor content. Closes [#176](https://github.com/ckeditor/ckeditor5-ui/issues/176). ([f38ae70](https://github.com/ckeditor/ckeditor5-ui/commit/f38ae70))
* Align feature class naming to a new scheme. ([1c500f6](https://github.com/ckeditor/ckeditor5-ui/commit/1c500f6))
* Aligned code to changes (`config.lang` to `config.languages`). Part of the Translation Service v2 ([ckeditor/ckeditor5#624](https://github.com/ckeditor/ckeditor5/issues/624)). ([876f681](https://github.com/ckeditor/ckeditor5-ui/commit/876f681))
* ComponentFactory.names() will return original component names (instead of normalized names). Closes [#376](https://github.com/ckeditor/ckeditor5-ui/issues/376). ([b6b39d7](https://github.com/ckeditor/ckeditor5-ui/commit/b6b39d7))
* CSS classes should be prefixed with `ck-` instead of `cke-`. Closes [#112](https://github.com/ckeditor/ckeditor5-ui/issues/112). ([7973f83](https://github.com/ckeditor/ckeditor5-ui/commit/7973f83))
* Introduced `SplitButtonView` and new dropdown creation helpers (`createDropdown()`, `addListToDropdown()` and `addToolbarToDropdown()`) Closes [#344](https://github.com/ckeditor/ckeditor5-ui/issues/344). Closes [#356](https://github.com/ckeditor/ckeditor5-ui/issues/356). ([0f26ca8](https://github.com/ckeditor/ckeditor5-ui/commit/0f26ca8))
* Migrated the package styles from SASS to PostCSS to bring theme support and avoid duplicates in some editor builds. Closes [#144](https://github.com/ckeditor/ckeditor5-ui/issues/144). Closes [ckeditor/ckeditor5#420](https://github.com/ckeditor/ckeditor5/issues/420). ([f152dfc](https://github.com/ckeditor/ckeditor5-ui/commit/f152dfc))
* Moved ck-button-icon mixin from ckeditor5-theme-lark. ([8757d27](https://github.com/ckeditor/ckeditor5-ui/commit/8757d27))
* Removed the `.ck-editor-toolbar` and `.ck-editor-toolbar-container` classes (see [ckeditor/ckeditor5-theme-lark#135](https://github.com/ckeditor/ckeditor5-theme-lark/issues/135)). ([352d056](https://github.com/ckeditor/ckeditor5-ui/commit/352d056))
* Rename `ContextualToolbar` to `BalloonToolbar`. Closes [ckeditor/ckeditor5#550](https://github.com/ckeditor/ckeditor5/issues/550). ([28f59df](https://github.com/ckeditor/ckeditor5-ui/commit/28f59df))
* The `closeDropdownOnBlur()` helper should use `clickOutsideHandler()`. Decorated the `View#render()` method. Closes [#311](https://github.com/ckeditor/ckeditor5-ui/issues/311). ([269e97b](https://github.com/ckeditor/ckeditor5-ui/commit/269e97b))
* Updated translations. ([f657be2](https://github.com/ckeditor/ckeditor5-ui/commit/f657be2))
### BREAKING CHANGES
* Renamed `contextual/contextualtoolbar~ContextualToolbar` to `balloon/balloontoolbar~BalloonToolbar`.
* Renamed `contextualToolbar` configuration option to `balloonToolbar`.
* Removed `DropdownModel` interface – you can use dropdown properties directly now. See [#356](https://github.com/ckeditor/ckeditor5-ui/issues/356).
* Removed `createButtonDropdown()` and `ButtonDropdownView`. See [#356](https://github.com/ckeditor/ckeditor5-ui/issues/356).
* Removed `createListDropdown()` and `ListDropdownView`. See [#356](https://github.com/ckeditor/ckeditor5-ui/issues/356).
* The DOM structure of the dropdown component has changed. Please refer to the documentation to find out more.
* Basic properties of the balloon panel component (the location of the arrow, the default positions) have changed, which may have an impact on existing integrations.
* The styles are no longer developed in SASS which means the `.scss` files became unavailable. Please refer to the [Theme Customization](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/ui/theme-customization.html) guide to learn more about migration to PostCSS.
## [1.0.0-alpha.2](https://github.com/ckeditor/ckeditor5-ui/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (November 14, 2017)
### Bug fixes
* `Template#getViews()` generator should not traverse native HTML elements. Closes [#337](https://github.com/ckeditor/ckeditor5-ui/issues/337). Closes [ckeditor/ckeditor5#657](https://github.com/ckeditor/ckeditor5/issues/657). ([894bad0](https://github.com/ckeditor/ckeditor5-ui/commit/894bad0))
* Improved binding of the `value` attribute in `InputTextView`. Closes [#335](https://github.com/ckeditor/ckeditor5-ui/issues/335). ([823120b](https://github.com/ckeditor/ckeditor5-ui/commit/823120b))
### Other changes
* Implemented `View#render()` method which replaces rendering the `#element` upon the first access and incorporates the `#init()` method functionality. Closes [#262](https://github.com/ckeditor/ckeditor5-ui/issues/262). Closes [#302](https://github.com/ckeditor/ckeditor5-ui/issues/302). ([bf90ad5](https://github.com/ckeditor/ckeditor5-ui/commit/bf90ad5))
In other words – the `View#render()` method needs to be called to render a view and it sets the `View#element` itself. It can be called only once and it is done automatically if a view is added to some other view (as its child). If you need to add any additional logic to your component's initialization, then override the `render()` method (and remember to call `super.render()`).
Additionally, from now on `View#setTemplate()` and `View#extendTemplate()` methods are recommended as a shorthand for `view.template = new Template( { ... } )` and `Template.extend( view.template )`.
Please refer to the updated [documentation](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/architecture/intro.html#ui-library) to learn more.
* Removed legacy `width` and `height` attributes from the `BoxedEditorUIView`. Closes [#25](https://github.com/ckeditor/ckeditor5-ui/issues/25). ([ffa419a](https://github.com/ckeditor/ckeditor5-ui/commit/ffa419a))
* The `ComponentFactory` should be case-insensitive. Closes [#324](https://github.com/ckeditor/ckeditor5-ui/issues/324). ([94417e9](https://github.com/ckeditor/ckeditor5-ui/commit/94417e9))
* Updated translations. ([186f365](https://github.com/ckeditor/ckeditor5-ui/commit/186f365))
### BREAKING CHANGES
* The `View#init()` method in UI components has been renamed to `render()`. Please refer to the [documentation](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/architecture/intro.html#UI-library) to learn more.
* The `View#element` is no longer a getter which renders an element when first referenced. Use the `View#render()` method instead.
* `Template#children` property became an `Array` (previously `ViewCollection`).
* `View#addChildren()` and `View#removeChildren()` methods became `#registerChildren()` and `#deregisterChildren()`.
* The DOM structure of the `StickyPanelView` has changed along with the class names. Please refer to the component documentation to learn more.
## [1.0.0-alpha.1](https://github.com/ckeditor/ckeditor5-ui/compare/v0.10.0...v1.0.0-alpha.1) (October 3, 2017)
### Bug fixes
* `ContextualBalloon` should remember position passed to `#updatePosition()`. Closes [#305](https://github.com/ckeditor/ckeditor5-ui/issues/305). Closes [ckeditor/ckeditor5-image#141](https://github.com/ckeditor/ckeditor5-image/issues/141). ([c787c0d](https://github.com/ckeditor/ckeditor5-ui/commit/c787c0d))
* `ContextualToolbar` should not be positioned to a zero–width DOM rect when invoked for a multi-line forward selection. Closes [#308](https://github.com/ckeditor/ckeditor5-ui/issues/308). ([00b701b](https://github.com/ckeditor/ckeditor5-ui/commit/00b701b))
* `ContextualToolbar` will accept the object format of `config.contextualToolbar`. Closes [#316](https://github.com/ckeditor/ckeditor5-ui/issues/316). ([d71cad8](https://github.com/ckeditor/ckeditor5-ui/commit/d71cad8))
* Fixed sticky panel's `z-index` so it is correctly rendered above images (or other relatively positioned elements). Closes [#315](https://github.com/ckeditor/ckeditor5-ui/issues/315). ([00f2add](https://github.com/ckeditor/ckeditor5-ui/commit/00f2add))
* The content of the `BalloonPanelView` should be selectable. Closes [#294](https://github.com/ckeditor/ckeditor5-ui/issues/294). Closes https://github.com/ckeditor/ckeditor5/issues/498. ([e5315df](https://github.com/ckeditor/ckeditor5-ui/commit/e5315df))
### Features
* Implemented `View#removeChildren()`, the opposite of `View#addChildren()`. Closes [#303](https://github.com/ckeditor/ckeditor5-ui/issues/303). ([0f1ea5a](https://github.com/ckeditor/ckeditor5-ui/commit/0f1ea5a))
* Replaced `StickyToolbarView` with a generic `StickyPanelView`. Closes [#297](https://github.com/ckeditor/ckeditor5-ui/issues/297). ([b10b43c](https://github.com/ckeditor/ckeditor5-ui/commit/b10b43c))
### Other changes
* `ToolbarView#fillFromConfig()` will warn when the factory does not provide a component. Closes [#291](https://github.com/ckeditor/ckeditor5-ui/issues/291). Closes [ckeditor/ckeditor5#526](https://github.com/ckeditor/ckeditor5/issues/526). ([2e63e70](https://github.com/ckeditor/ckeditor5-ui/commit/2e63e70))
* The `escPressHandler` function should be replaced by the `KeystrokeHandler`. Closes [#150](https://github.com/ckeditor/ckeditor5-ui/issues/150). ([b322744](https://github.com/ckeditor/ckeditor5-ui/commit/b322744))
### BREAKING CHANGES
* `Toolbar#fillFromConfig()` cannot be now called with an `undefined`. Make sure to use `normalizeToolbarConfig()` to get a reliable object.
* The `escPressHandler` is no longer available. Please
refer to the `KeystrokeHandler` helper to learn more.
* The `StickyToolbarView` and corresponding CSS `.ck-sticky-panel` classes are no longer available. `StickyPanelView` + `ToolbarView` combo should be used instead.
## [0.10.0](https://github.com/ckeditor/ckeditor5-ui/compare/v0.9.0...v0.10.0) (September 3, 2017)
### Bug fixes
* `ContextualToolbar` should have proper editor toolbar styling. Closes [#230](https://github.com/ckeditor/ckeditor5-ui/issues/230). ([4e2ee36](https://github.com/ckeditor/ckeditor5-ui/commit/4e2ee36))
* BalloonPanelView should prevent native #selectstart event. Closes [#243](https://github.com/ckeditor/ckeditor5-ui/issues/243). ([cba3fb1](https://github.com/ckeditor/ckeditor5-ui/commit/cba3fb1))
* Button tooltip should not look blurry on low-DPI screens. Closes [#142](https://github.com/ckeditor/ckeditor5-ui/issues/142). Closes [#133](https://github.com/ckeditor/ckeditor5-ui/issues/133). ([a497aff](https://github.com/ckeditor/ckeditor5-ui/commit/a497aff))
* Clicking and dragging in a dropdown panel should not break the selection. Closes [#228](https://github.com/ckeditor/ckeditor5-ui/issues/228). ([6066a09](https://github.com/ckeditor/ckeditor5-ui/commit/6066a09))
* Contextual toolbar should re–position correctly on window scroll. Closes [#227](https://github.com/ckeditor/ckeditor5-ui/issues/227). ([e5ea25f](https://github.com/ckeditor/ckeditor5-ui/commit/e5ea25f))
* `DropdownView` should open upon arrow down key press. Closes [#249](https://github.com/ckeditor/ckeditor5-ui/issues/249). ([c1e6afc](https://github.com/ckeditor/ckeditor5-ui/commit/c1e6afc))
* List items should handle Enter and Space key press when focused. Closes [#153](https://github.com/ckeditor/ckeditor5-ui/issues/153). ([403b64a](https://github.com/ckeditor/ckeditor5-ui/commit/403b64a))
* The `clickOutsideHandler` helper should use `mousedown` instead of `mouseup` event. Closes [#281](https://github.com/ckeditor/ckeditor5-ui/issues/281). ([6b980b6](https://github.com/ckeditor/ckeditor5-ui/commit/6b980b6))
* The `Template` class should not throw an error when a child view in the definition has an `id` attribute set without a value. Closes [#289](https://github.com/ckeditor/ckeditor5-ui/issues/289). ([d7072ba](https://github.com/ckeditor/ckeditor5-ui/commit/d7072ba))
* The `TooltipView` should hide when the `TooltipView#text` is empty. The `ButtonView's` ability to get a tooltip should not be restricted after `View` initialization. Closes [#283](https://github.com/ckeditor/ckeditor5-ui/issues/283). ([1588c82](https://github.com/ckeditor/ckeditor5-ui/commit/1588c82))
* The dropdown menu should not open using the keyboard when disabled. Closes [#238](https://github.com/ckeditor/ckeditor5-ui/issues/238). ([fc524b8](https://github.com/ckeditor/ckeditor5-ui/commit/fc524b8))
### Features
* `StickyToolbarView` now supports a configurable vertical offset from the top of the page. Closes [#277](https://github.com/ckeditor/ckeditor5-ui/issues/277). ([245f0fa](https://github.com/ckeditor/ckeditor5-ui/commit/245f0fa))
Also implemented the `normalizeToolbarConfig()` utility.
* Added `TextInputView#isReadOnly` and `LabeledInputView#isReadOnly` states. Closes [#266](https://github.com/ckeditor/ckeditor5-ui/issues/266). Closes [#268](https://github.com/ckeditor/ckeditor5-ui/issues/268). ([111a728](https://github.com/ckeditor/ckeditor5-ui/commit/111a728))
* Added optional notification title. Closes [#241](https://github.com/ckeditor/ckeditor5-ui/issues/241). ([abbb68f](https://github.com/ckeditor/ckeditor5-ui/commit/abbb68f))
* Allowed `BalloonPanelView` position limiter defined as a function. Made `ContextualBalloon` position limiter configurable via `#positionLimiter` property. Closes [#260](https://github.com/ckeditor/ckeditor5-ui/issues/260). ([322563e](https://github.com/ckeditor/ckeditor5-ui/commit/322563e))
* Implemented placeholder in `InputTextView`. Closes [#220](https://github.com/ckeditor/ckeditor5-ui/issues/220). ([5d91d18](https://github.com/ckeditor/ckeditor5-ui/commit/5d91d18))
* Introduced `CommandFactory#names()`. Closes [#287](https://github.com/ckeditor/ckeditor5-ui/issues/287). ([4038da2](https://github.com/ckeditor/ckeditor5-ui/commit/4038da2))
### Other changes
* Add support for multiple context elements in the `clickOutsideHandler` helper. Closes [#261](https://github.com/ckeditor/ckeditor5-ui/issues/261). ([9da5bf7](https://github.com/ckeditor/ckeditor5-ui/commit/9da5bf7))
* Added the `beforeShow` event to the `ContextualToolbar` plugin. Closes [#222](https://github.com/ckeditor/ckeditor5-ui/issues/222). ([835d0ac](https://github.com/ckeditor/ckeditor5-ui/commit/835d0ac))
* Implemented public `show()` and `hide()` methods in the `ContextualToolbar` plugin. Closes [#263](https://github.com/ckeditor/ckeditor5-ui/issues/263). ([eb4caab](https://github.com/ckeditor/ckeditor5-ui/commit/eb4caab))
* Improvements in the `BalloonPanelView`–based components for the balloon toolbar editor. Closes [#236](https://github.com/ckeditor/ckeditor5-ui/issues/236). Closes [#234](https://github.com/ckeditor/ckeditor5-ui/issues/234). Closes [#224](https://github.com/ckeditor/ckeditor5-ui/issues/224). ([737b55f](https://github.com/ckeditor/ckeditor5-ui/commit/737b55f))
* Made the UI component initialization and destruction processes synchronous. Closes [#225](https://github.com/ckeditor/ckeditor5-ui/issues/225). ([07e1502](https://github.com/ckeditor/ckeditor5-ui/commit/07e1502))
* Made the UI destruction a fail–safe, repeatable process. Closes [#248](https://github.com/ckeditor/ckeditor5-ui/issues/248). ([6f5ec0d](https://github.com/ckeditor/ckeditor5-ui/commit/6f5ec0d))
* The `ContextualToolbar` should not show up when all child items are disabled. The `ContextualToolbar#beforeShow` event has been replaced by `ContextualToolbar#show`. Closes [#269](https://github.com/ckeditor/ckeditor5-ui/issues/269). Closes [#232](https://github.com/ckeditor/ckeditor5-ui/issues/232). ([d83d07d](https://github.com/ckeditor/ckeditor5-ui/commit/d83d07d))
### BREAKING CHANGES
* `StickyToolbarView#limiterOffset` has been renamed to `StickyToolbarView#limiterBottomOffset`.
* `ContextualToolbar#beforeShow` is no longer available. Please refer to `ContextualToolbar#show` instead.
* The `clickOutsideHandler` helper's `contextElement` configuration option is now an `Array` named `contextElements`.
* `View#init()`, `View#destroy()` (also `ViewCollection#init()`, `ViewCollection#destroy()` and `ViewCollection#add()`) no longer return `Promise`. It may require updates in UI components which inherit from `View` and rely on the value returned by these methods.
* Various UI components switched to synchronous `init()` and `destroy()` (no longer returning `Promise`), which means that features using these components may need some updates to work properly.
* The position names in `BalloonPanelView.defaultPositions` and their results have changed. Please refer to the latest API documentation to learn more.
## [0.9.0](https://github.com/ckeditor/ckeditor5-ui/compare/v0.8.0...v0.9.0) (May 7, 2017)
### Bug fixes
* `BalloonPanelView` should not be focusable. Closes [#206](https://github.com/ckeditor/ckeditor5-ui/issues/206). ([f9e3bb7](https://github.com/ckeditor/ckeditor5-ui/commit/f9e3bb7))
T/206a: BalloonPanelView should not be focusable
* ContextualBalloon plugin should use BalloonPanelView#pin instead of #attachTo. Closes [#192](https://github.com/ckeditor/ckeditor5-ui/issues/192). ([28dd457](https://github.com/ckeditor/ckeditor5-ui/commit/28dd457))
* ContextualBalloon.view#element should be registered in editor's focus tracker. Closes [#193](https://github.com/ckeditor/ckeditor5-ui/issues/193). ([cfbe329](https://github.com/ckeditor/ckeditor5-ui/commit/cfbe329))
* FocusCycler should ignore invisible views. Closes [#209](https://github.com/ckeditor/ckeditor5-ui/issues/209). ([b8fbaf1](https://github.com/ckeditor/ckeditor5-ui/commit/b8fbaf1))
T/209: FocusCycler should not consider invisible views.
* ViewCollection#destroy should wait for all ViewCollection#add promises to resolve to avoid errors. Closes [#203](https://github.com/ckeditor/ckeditor5-ui/issues/203). ([a7e7c94](https://github.com/ckeditor/ckeditor5-ui/commit/a7e7c94))
### Features
* Added keepAttachedTo() method to the BalloonPanelView. Closes [#170](https://github.com/ckeditor/ckeditor5-ui/issues/170). ([101b465](https://github.com/ckeditor/ckeditor5-ui/commit/101b465))
* Introduced `ContextualToolbar` plugin. Closes [#182](https://github.com/ckeditor/ckeditor5-ui/issues/182). Closes [#187](https://github.com/ckeditor/ckeditor5-ui/issues/187). ([66a30b1](https://github.com/ckeditor/ckeditor5-ui/commit/66a30b1))
Introduced several new positions in `BalloonPanelView#defaultPositions`. Added `className` attribute to the `BalloonPanelView` interface.
BREAKING CHANGE: Default positions of the `BalloonPanelView` have been renamed.
BREAKING CHANGE: Class names controlling the arrow of the panel have been renamed.
* Introduced ContextualBalloon plugin for managing contextual balloons. Closes [#134](https://github.com/ckeditor/ckeditor5-ui/issues/134). ([3ceb6a6](https://github.com/ckeditor/ckeditor5-ui/commit/3ceb6a6))
* Introduced notification plugin. Closes [#189](https://github.com/ckeditor/ckeditor5-ui/issues/189). ([f2dd63f](https://github.com/ckeditor/ckeditor5-ui/commit/f2dd63f))
### Other changes
* Improved ContextualBalloon so it supports asynchronous Views. Closes [#200](https://github.com/ckeditor/ckeditor5-ui/issues/200). ([09067aa](https://github.com/ckeditor/ckeditor5-ui/commit/09067aa))
* Merged `FloatingPanelView` into `BalloonPanelView`. Closes [#191](https://github.com/ckeditor/ckeditor5-ui/issues/191). ([4b90faa](https://github.com/ckeditor/ckeditor5-ui/commit/4b90faa))
BREAKING CHANGE: `FloatingPanelView` is no longer available.
BREAKING CHANGE: `BalloonPanelView#keepAttachedTo()` has been replaced by `pin()`.
BREAKING CHANGE: Default position names in `BalloonPanelView.defaultPositions` have changed. Now prefixed with `arrow_`.
* Updated translations. ([3455fe7](https://github.com/ckeditor/ckeditor5-ui/commit/3455fe7))
### BREAKING CHANGES
* Default positions of the `BalloonPanelView` have been renamed.
* Class names controlling the arrow of the panel have been renamed.
* `FloatingPanelView` is no longer available.
* `BalloonPanelView#keepAttachedTo()` has been replaced by `pin()`.
* Default position names in `BalloonPanelView.defaultPositions` have changed. Now prefixed with `arrow_`.
## [0.8.0](https://github.com/ckeditor/ckeditor5-ui/compare/v0.7.1...v0.8.0) (April 5, 2017)
### Features
* Allowed marking ListItemView active using the #isActive attribute. Closes [#166](https://github.com/ckeditor/ckeditor5-ui/issues/166). ([a19d6c4](https://github.com/ckeditor/ckeditor5-ui/commit/a19d6c4))
* Enabled styling via "class" attribute in ListItemView. Closes [#162](https://github.com/ckeditor/ckeditor5-ui/issues/162). ([672bf82](https://github.com/ckeditor/ckeditor5-ui/commit/672bf82))
* Implemented features necessary for creating inline editors UI: `FloatingPanelView` class, `Template.revert()` method, and `enableToolbarKeyboardFocus()` utility. Closes [#152](https://github.com/ckeditor/ckeditor5-ui/issues/152). ([cb606d7](https://github.com/ckeditor/ckeditor5-ui/commit/cb606d7))
### Other changes
* `ComponentFactory` will throw an error when attempting to create a non-existent component. Closes [#174](https://github.com/ckeditor/ckeditor5-ui/issues/174). ([ef0a7f8](https://github.com/ckeditor/ckeditor5-ui/commit/ef0a7f8))
* Imported "ck-hidden" CSS class from ckeditor5-theme-lark. Closes [#164](https://github.com/ckeditor/ckeditor5-ui/issues/164). ([486bb22](https://github.com/ckeditor/ckeditor5-ui/commit/486bb22))
* Moved `ViewCollection#bindTo` method to `Collection` class in `ckeditor5-utils`. Closes [#168](https://github.com/ckeditor/ckeditor5-ui/issues/168). ([5b55987](https://github.com/ckeditor/ckeditor5-ui/commit/5b55987))
* Updated translations. ([3b27e51](https://github.com/ckeditor/ckeditor5-ui/commit/3b27e51))
### BREAKING CHANGES
* `ViewCollection#bindTo.as` is renamed to `Collection#bindTo.using` when mapping function is a parameter. See the `Collection#bindTo` documentation.
* The `ui/balloonpanel/balloonpanelview` module was renamed to `ui/panel/balloon/balloonpanelview`. See [#152](https://github.com/ckeditor/ckeditor5-ui/issues/152).
## [0.7.1](https://github.com/ckeditor/ckeditor5-ui/compare/v0.7.0...v0.8.0) (March 6, 2017)
### Bug fixes
* Removed title from the editable element. Fixes [#121](https://github.com/ckeditor/ckeditor5/issues/121). ([71fb3eb](https://github.com/ckeditor/ckeditor5-ui/commit/71fb3eb))
### Features
* Added support for toolbar item separators. Closes [#154](https://github.com/ckeditor/ckeditor5/issues/154). ([f3cb75d](https://github.com/ckeditor/ckeditor5-ui/commit/f3cb75d))
### Other changes
* Uploaded translations. ([67ba32b](https://github.com/ckeditor/ckeditor5-ui/commit/67ba32b))
All changes in the package are documented in https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.

@@ -146,8 +146,2 @@ /**

/**
* (Optional) The ARIA property reflected by the `aria-checked` DOM attribute used by assistive technologies.
*
* @observable
*/
ariaChecked?: boolean | undefined;
/**
* (Optional) The ARIA property reflected by the `aria-label` DOM attribute used by assistive technologies.

@@ -154,0 +148,0 @@ *

@@ -127,6 +127,2 @@ /**

*/
ariaChecked: boolean | undefined;
/**
* @inheritDoc
*/
ariaLabel?: string | undefined;

@@ -138,2 +134,18 @@ /**

/**
* Aria-pressed attribute of element. It is calculated based on {@link #isToggleable isToggleable} and {@link #role}.
* It's set to true if the button is on and the role is not checkable.
*
* @readonly
* @internal
*/
_ariaPressed: string | false;
/**
* Aria-checked attribute of element. It is calculated based on {@link #isToggleable isToggleable} and {@link #role}.
* It's set to true if the button is on and the role is checkable.
*
* @readonly
* @internal
*/
_ariaChecked: string | false;
/**
* Tooltip of the button bound to the template.

@@ -140,0 +152,0 @@ *

@@ -9,4 +9,10 @@ /**

*/
/**
* @module ui/button/filedialogbuttonview
*/
import View from '../view.js';
import ButtonView from './buttonview.js';
import type { Locale } from '@ckeditor/ckeditor5-utils';
import type { Mixed } from '@ckeditor/ckeditor5-utils';
import ListItemButtonView from './listitembuttonview.js';
declare const FileDialogButtonView_base: Mixed<typeof ButtonView, FileDialogButtonViewBase>;
/**

@@ -36,3 +42,35 @@ * The file dialog button view.

*/
export default class FileDialogButtonView extends ButtonView {
export default class FileDialogButtonView extends /* #__PURE__ */ FileDialogButtonView_base {
}
declare const FileDialogListItemButtonView_base: Mixed<typeof ListItemButtonView, FileDialogButtonViewBase>;
/**
* The file dialog button view used in a lists.
*
* This component provides a button that opens the native file selection dialog.
* It can be used to implement the UI of a file upload feature.
*
* ```ts
* const view = new FileDialogListItemButtonView( locale );
*
* view.set( {
* acceptedType: 'image/*',
* allowMultipleFiles: true
* label: t( 'Insert image' ),
* icon: imageIcon,
* tooltip: true
* } );
*
* view.on( 'done', ( evt, files ) => {
* for ( const file of Array.from( files ) ) {
* console.log( 'Selected file', file );
* }
* } );
* ```
*/
export declare class FileDialogListItemButtonView extends /* #__PURE__ */ FileDialogListItemButtonView_base {
}
/**
* Represents the base view for a file dialog button component.
*/
type FileDialogButtonViewBase = View & {
/**

@@ -45,6 +83,2 @@ * The button view of the component.

/**
* A hidden `<input>` view used to execute file dialog.
*/
private _fileInputView;
/**
* Accepted file types. Can be provided in form of file extensions, media type or one of:

@@ -64,11 +98,3 @@ * * `audio/*`,

allowMultipleFiles: boolean;
/**
* @inheritDoc
*/
constructor(locale?: Locale);
/**
* @inheritDoc
*/
render(): void;
}
};
/**

@@ -89,1 +115,2 @@ * Fired when file dialog is closed with file selected.

};
export {};

@@ -54,3 +54,3 @@ /**

*/
private _showDialog;
private _toggleDialog;
}

@@ -20,2 +20,3 @@ /**

import type { Editor } from '@ckeditor/ckeditor5-core';
import type { default as MenuBarView, MenuBarConfigAddedGroup, MenuBarConfigAddedItem, MenuBarConfigAddedMenu } from '../menubar/menubarview.js';
declare const EditorUI_base: {

@@ -109,2 +110,10 @@ new (): import("@ckeditor/ckeditor5-utils").Observable;

/**
* All additional menu bar items, groups or menus that have their default location defined.
*/
private _extraMenuBarElements;
/**
* The last focused element to which focus should return on `Esc` press.
*/
private _lastFocusedForeignElement;
/**
* Creates an instance of the editor UI class.

@@ -175,2 +184,42 @@ *

/**
* Registers an extra menu bar element, which could be a single item, a group of items, or a menu containing groups.
*
* ```ts
* // Register a new menu bar item.
* editor.ui.extendMenuBar( {
* item: 'menuBar:customFunctionButton',
* position: 'after:menuBar:bold'
* } );
*
* // Register a new menu bar group.
* editor.ui.extendMenuBar( {
* group: {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* },
* position: 'start:help'
* } );
*
* // Register a new menu bar menu.
* editor.ui.extendMenuBar( {
* menu: {
* menuId: 'customMenu',
* label: 'customMenu',
* groups: [
* {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* }
* ]
* },
* position: 'after:help'
* } );
* ```
*/
extendMenuBar(config: MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu): void;
/**
* Stores all editable elements used by the editor instance.

@@ -182,2 +231,6 @@ *

/**
* Initializes menu bar.
*/
protected _initMenuBar(menuBarView: MenuBarView): void;
/**
* Returns viewport offsets object:

@@ -204,2 +257,6 @@ *

/**
* Saves last focused element that doen not belong to editing view to restore focus on `Esc`.
*/
private _saveLastFocusedForeignElement;
/**
* Returns definitions of toolbars that could potentially be focused, sorted by their importance for the user.

@@ -206,0 +263,0 @@ *

@@ -17,2 +17,3 @@ /**

import '../../theme/components/editorui/editorui.css';
import type MenuBarView from '../menubar/menubarview.js';
/**

@@ -31,2 +32,6 @@ * The editor UI view class. Base class for the editor main views.

/**
* Menu bar view instance. May not be initialized in some editor types.
*/
menuBarView?: MenuBarView;
/**
* Creates an instance of the editor UI view class.

@@ -33,0 +38,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

@@ -25,4 +25,3 @@ /**

* It is used i.a.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
* and {@link module:special-characters/ui/specialcharactersnavigationview~SpecialCharactersNavigationView}.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}.
*

@@ -29,0 +28,0 @@ * The latter is an example, where the component has been extended by {@link module:ui/dropdown/dropdownview~DropdownView} view.

@@ -25,3 +25,4 @@ /**

export { default as SwitchButtonView } from './button/switchbuttonview.js';
export { default as FileDialogButtonView } from './button/filedialogbuttonview.js';
export { default as ListItemButtonView } from './button/listitembuttonview.js';
export { default as FileDialogButtonView, FileDialogListItemButtonView } from './button/filedialogbuttonview.js';
export { default as CollapsibleView } from './collapsible/collapsibleview.js';

@@ -61,2 +62,3 @@ export * from './colorgrid/utils.js';

export { default as ListView } from './list/listview.js';
export { default as filterGroupAndItemNames } from './search/filtergroupanditemnames.js';
export { default as Notification } from './notification/notification.js';

@@ -72,2 +74,4 @@ export { default as ViewModel } from './model.js';

export { default as HighlightedTextView } from './highlightedtext/highlightedtextview.js';
export { default as ButtonLabelWithHighlightView } from './highlightedtext/buttonlabelwithhighlightview.js';
export { default as LabelWithHighlightView } from './highlightedtext/labelwithhighlightview.js';
export { default as TooltipManager } from './tooltipmanager.js';

@@ -89,3 +93,3 @@ export { default as Template, type TemplateDefinition } from './template.js';

export { default as MenuBarMenuListItemFileDialogButtonView } from './menubar/menubarmenulistitemfiledialogbuttonview.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems, _initMenuBar } from './menubar/utils.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems } from './menubar/utils.js';
import './augmentation.js';

@@ -13,3 +13,3 @@ /**

import IconView from '../icon/iconview.js';
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import type { Locale } from '@ckeditor/ckeditor5-utils';

@@ -21,3 +21,3 @@ import '../../theme/components/menubar/menubarmenubutton.css';

*/
export default class MenuBarMenuButtonView extends ButtonView {
export default class MenuBarMenuButtonView extends ListItemButtonView {
/**

@@ -24,0 +24,0 @@ * An icon that displays an arrow to indicate a direction of the menu.

@@ -13,3 +13,3 @@ /**

import type { Locale } from '@ckeditor/ckeditor5-utils';
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -19,3 +19,3 @@ /**

*/
export default class MenuBarMenuListItemButtonView extends ButtonView {
export default class MenuBarMenuListItemButtonView extends ListItemButtonView {
/**

@@ -22,0 +22,0 @@ * Creates an instance of the menu bar list button view.

@@ -13,3 +13,3 @@ /**

import type { Locale } from '@ckeditor/ckeditor5-utils';
import FileDialogButtonView from '../button/filedialogbuttonview.js';
import { FileDialogListItemButtonView } from '../button/filedialogbuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -21,3 +21,3 @@ /**

*/
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogButtonView {
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogListItemButtonView {
/**

@@ -24,0 +24,0 @@ * Creates an instance of the menu bar list button view.

@@ -28,2 +28,7 @@ /**

constructor(locale: Locale);
/**
* This method adds empty space if there is any toggleable item in the list.
* It makes the list properly aligned.
*/
private _setItemsCheckSpace;
}

@@ -36,2 +36,11 @@ /**

/**
* Indicates whether the menu bar has been interacted with using the keyboard.
*
* It is useful for showing focus outlines while hovering over the menu bar when
* interaction with the keyboard was detected.
*
* @observable
*/
isFocusBorderEnabled: boolean;
/**
* A list of {@link module:ui/menubar/menubarmenuview~MenuBarMenuView} instances registered in the menu bar.

@@ -55,3 +64,3 @@ *

*/
fillFromConfig(config: NormalizedMenuBarConfigObject, componentFactory: ComponentFactory): void;
fillFromConfig(config: NormalizedMenuBarConfigObject, componentFactory: ComponentFactory, extraItems?: Array<MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu>): void;
/**

@@ -58,0 +67,0 @@ * @inheritDoc

@@ -10,5 +10,4 @@ /**

import type MenuBarMenuView from './menubarmenuview.js';
import type { default as MenuBarView, MenuBarConfig, MenuBarConfigObject, NormalizedMenuBarConfigObject } from './menubarview.js';
import type { default as MenuBarView, MenuBarConfig, MenuBarConfigObject, MenuBarConfigAddedGroup, MenuBarConfigAddedMenu, NormalizedMenuBarConfigObject, MenuBarConfigAddedItem } from './menubarview.js';
import type ComponentFactory from '../componentfactory.js';
import type { Editor } from '@ckeditor/ckeditor5-core';
import { type Locale, type PositioningFunction } from '@ckeditor/ckeditor5-utils';

@@ -52,2 +51,7 @@ type DeepReadonly<T> = Readonly<{

closeOnClickOutside(menuBarView: MenuBarView): void;
/**
* Tracks the keyboard focus interaction on the menu bar view. It is used to determine if the nested items
* of the menu bar should render focus rings after first interaction with the keyboard.
*/
enableFocusHighlightOnInteraction(menuBarView: MenuBarView): void;
};

@@ -242,2 +246,8 @@ /**

* {
* groupId: 'previewMergeFields',
* items: [
* 'menuBar:previewMergeFields'
* ]
* },
* {
* groupId: 'restrictedEditingException',

@@ -267,3 +277,4 @@ * items: [

* 'menuBar:link',
* 'menuBar:comment'
* 'menuBar:comment',
* 'menuBar:insertMergeField'
* ]

@@ -438,13 +449,8 @@ * },

*/
export declare function processMenuBarConfig({ normalizedConfig, locale, componentFactory }: {
export declare function processMenuBarConfig({ normalizedConfig, locale, componentFactory, extraItems }: {
normalizedConfig: NormalizedMenuBarConfigObject;
locale: Locale;
componentFactory: ComponentFactory;
extraItems: Array<MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu>;
}): NormalizedMenuBarConfigObject;
/**
* Initializes menu bar for given editor.
*
* @internal
*/
export declare function _initMenuBar(editor: Editor, menuBarView: MenuBarView): void;
export {};

@@ -118,2 +118,6 @@ /**

/**
* An instance of resize observer used to detect if target element is still visible.
*/
private _resizeObserver;
/**
* @inheritDoc

@@ -123,2 +127,6 @@ */

/**
* @inheritDoc
*/
destroy(): void;
/**
* Shows the panel.

@@ -166,4 +174,6 @@ *

* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/
attachTo(options: Partial<PositionOptions>): void;
attachTo(options: Partial<PositionOptions>): boolean;
/**

@@ -212,2 +222,4 @@ * Works the same way as the {@link #attachTo} method except that the position of the panel is

* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/

@@ -214,0 +226,0 @@ private _startPinning;

@@ -141,2 +141,6 @@ /**

/**
* Repositions the button on scroll.
*/
private _repositionButtonOnScroll;
/**
* Attaches the {@link #buttonView} to the target block of content.

@@ -148,2 +152,12 @@ *

/**
* Clips the button element to the viewport of the editable element.
*
* * If the button overflows the editable viewport, it is clipped to make it look like it's cut off by the editable scrollable region.
* * If the button is fully hidden by the top of the editable, it is not clickable but still visible in the DOM.
*
* @param buttonView The button view to clip.
* @param editableElement The editable element whose viewport is used for clipping.
*/
private _clipButtonToViewport;
/**
* Creates a resize observer that observes selected editable and resizes the toolbar panel accordingly.

@@ -150,0 +164,0 @@ */

@@ -101,9 +101,2 @@ /**

/**
* An instance of the resize observer that keeps track on target element visibility,
* when it hides the tooltip should also disappear.
*
* {@link module:core/editor/editorconfig~EditorConfig#balloonToolbar configuration}.
*/
private _resizeObserver;
/**
* An instance of the mutation observer that keeps track on target element attributes changes.

@@ -110,0 +103,0 @@ */

@@ -5,2 +5,2 @@ /**

*/
export default {"sr-latn":{"dictionary":{"Rich Text Editor":"Prošireni uređivač teksta","Editor editing area: %0":"Oblast za uređivanje urednika: %0","Edit block":"Blok uređivač","Click to edit block":"Kliknite da biste uredili blok","Drag to move":"Prevucite da biste premestili","Next":"Sledeći","Previous":"Prethodni","Editor toolbar":"Uređivač traka sa alatkama","Dropdown toolbar":"Padajuća traka sa alatkama","Black":"Crna","Dim grey":"Bledo siva","Grey":"Siva","Light grey":"Svetlo siva","White":"Bela","Red":"Crvena","Orange":"Narandžasta","Yellow":"Žuta","Light green":"Svetlo zelena","Green":"Zelena","Aquamarine":"Zelenkastoplava","Turquoise":"Tirkizna","Light blue":"Svetloplava","Blue":"Plava","Purple":"Ljubičasta","Editor block content toolbar":"Traka sa alatkama za blokiranje sadržaja uređivača","Editor contextual toolbar":"Kontekstualna traka sa alatkama Editor","HEX":"HEX","No results found":"Nije pronađen nijedan rezultat","No searchable items":"Nema stavki koje se mogu pretražiti","Editor dialog":"","Close":"","Help Contents. To close this dialog press ESC.":"","Below, you can find a list of keyboard shortcuts that can be used in the editor.":"","(may require <kbd>Fn</kbd>)":"","Accessibility":"","Accessibility help":"","Press %0 for help.":"","Move focus in and out of an active dialog window":"","MENU_BAR_MENU_FILE":"","MENU_BAR_MENU_EDIT":"Uredi","MENU_BAR_MENU_VIEW":"","MENU_BAR_MENU_INSERT":"Ubaci","MENU_BAR_MENU_FORMAT":"","MENU_BAR_MENU_TOOLS":"","MENU_BAR_MENU_HELP":"","MENU_BAR_MENU_TEXT":"Tekst","MENU_BAR_MENU_FONT":"","Editor menu bar":"","Please enter a valid color (e.g. \"ff0000\").":""},getPluralForm(n){return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);}}}
export default {"sr-latn":{"dictionary":{"Rich Text Editor":"Prošireni uređivač teksta","Editor editing area: %0":"Oblast za uređivanje urednika: %0","Edit block":"Blok uređivač","Click to edit block":"Kliknite da biste uredili blok","Drag to move":"Prevucite da biste premestili","Next":"Sledeći","Previous":"Prethodni","Editor toolbar":"Uređivač traka sa alatkama","Dropdown toolbar":"Padajuća traka sa alatkama","Black":"Crna","Dim grey":"Bledo siva","Grey":"Siva","Light grey":"Svetlo siva","White":"Bela","Red":"Crvena","Orange":"Narandžasta","Yellow":"Žuta","Light green":"Svetlo zelena","Green":"Zelena","Aquamarine":"Zelenkastoplava","Turquoise":"Tirkizna","Light blue":"Svetloplava","Blue":"Plava","Purple":"Ljubičasta","Editor block content toolbar":"Traka sa alatkama za blokiranje sadržaja uređivača","Editor contextual toolbar":"Kontekstualna traka sa alatkama Editor","HEX":"HEX","No results found":"Nije pronađen nijedan rezultat","No searchable items":"Nema stavki koje se mogu pretražiti","Editor dialog":"Editor dijalog","Close":"Blizu","Help Contents. To close this dialog press ESC.":"Sadržaj pomoći. Da biste zatvorili ovaj dijalog, pritisnite ESC.","Below, you can find a list of keyboard shortcuts that can be used in the editor.":"Ispod možete pronaći listu prečica na tastaturi koje se mogu koristiti u uređivaču.","(may require <kbd>Fn</kbd>)":"(možda zahteva Fn)","Accessibility":"Pristupačnost","Accessibility help":"Pomoć za pristupačnost","Press %0 for help.":"Pritisnite %0 za pomoć.","Move focus in and out of an active dialog window":"Pomeranje fokusa u i van aktivnog prozora dijaloga","MENU_BAR_MENU_FILE":"File","MENU_BAR_MENU_EDIT":"Uredi","MENU_BAR_MENU_VIEW":"View","MENU_BAR_MENU_INSERT":"Ubaci","MENU_BAR_MENU_FORMAT":"Format","MENU_BAR_MENU_TOOLS":"Alati","MENU_BAR_MENU_HELP":"Pomoć","MENU_BAR_MENU_TEXT":"Tekst","MENU_BAR_MENU_FONT":"Font","Editor menu bar":"Traka menija uređivača","Please enter a valid color (e.g. \"ff0000\").":"Unesite važeću boju (npr. „ff0000“)."},getPluralForm(n){return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);}}}

@@ -7,3 +7,3 @@ /**

( e => {
const { [ 'sr-latn' ]: { dictionary, getPluralForm } } = {"sr-latn":{"dictionary":{"Rich Text Editor":"Prošireni uređivač teksta","Editor editing area: %0":"Oblast za uređivanje urednika: %0","Edit block":"Blok uređivač","Click to edit block":"Kliknite da biste uredili blok","Drag to move":"Prevucite da biste premestili","Next":"Sledeći","Previous":"Prethodni","Editor toolbar":"Uređivač traka sa alatkama","Dropdown toolbar":"Padajuća traka sa alatkama","Black":"Crna","Dim grey":"Bledo siva","Grey":"Siva","Light grey":"Svetlo siva","White":"Bela","Red":"Crvena","Orange":"Narandžasta","Yellow":"Žuta","Light green":"Svetlo zelena","Green":"Zelena","Aquamarine":"Zelenkastoplava","Turquoise":"Tirkizna","Light blue":"Svetloplava","Blue":"Plava","Purple":"Ljubičasta","Editor block content toolbar":"Traka sa alatkama za blokiranje sadržaja uređivača","Editor contextual toolbar":"Kontekstualna traka sa alatkama Editor","HEX":"HEX","No results found":"Nije pronađen nijedan rezultat","No searchable items":"Nema stavki koje se mogu pretražiti","Editor dialog":"","Close":"","Help Contents. To close this dialog press ESC.":"","Below, you can find a list of keyboard shortcuts that can be used in the editor.":"","(may require <kbd>Fn</kbd>)":"","Accessibility":"","Accessibility help":"","Press %0 for help.":"","Move focus in and out of an active dialog window":"","MENU_BAR_MENU_FILE":"","MENU_BAR_MENU_EDIT":"Uredi","MENU_BAR_MENU_VIEW":"","MENU_BAR_MENU_INSERT":"Ubaci","MENU_BAR_MENU_FORMAT":"","MENU_BAR_MENU_TOOLS":"","MENU_BAR_MENU_HELP":"","MENU_BAR_MENU_TEXT":"Tekst","MENU_BAR_MENU_FONT":"","Editor menu bar":"","Please enter a valid color (e.g. \"ff0000\").":""},getPluralForm(n){return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);}}};
const { [ 'sr-latn' ]: { dictionary, getPluralForm } } = {"sr-latn":{"dictionary":{"Rich Text Editor":"Prošireni uređivač teksta","Editor editing area: %0":"Oblast za uređivanje urednika: %0","Edit block":"Blok uređivač","Click to edit block":"Kliknite da biste uredili blok","Drag to move":"Prevucite da biste premestili","Next":"Sledeći","Previous":"Prethodni","Editor toolbar":"Uređivač traka sa alatkama","Dropdown toolbar":"Padajuća traka sa alatkama","Black":"Crna","Dim grey":"Bledo siva","Grey":"Siva","Light grey":"Svetlo siva","White":"Bela","Red":"Crvena","Orange":"Narandžasta","Yellow":"Žuta","Light green":"Svetlo zelena","Green":"Zelena","Aquamarine":"Zelenkastoplava","Turquoise":"Tirkizna","Light blue":"Svetloplava","Blue":"Plava","Purple":"Ljubičasta","Editor block content toolbar":"Traka sa alatkama za blokiranje sadržaja uređivača","Editor contextual toolbar":"Kontekstualna traka sa alatkama Editor","HEX":"HEX","No results found":"Nije pronađen nijedan rezultat","No searchable items":"Nema stavki koje se mogu pretražiti","Editor dialog":"Editor dijalog","Close":"Blizu","Help Contents. To close this dialog press ESC.":"Sadržaj pomoći. Da biste zatvorili ovaj dijalog, pritisnite ESC.","Below, you can find a list of keyboard shortcuts that can be used in the editor.":"Ispod možete pronaći listu prečica na tastaturi koje se mogu koristiti u uređivaču.","(may require <kbd>Fn</kbd>)":"(možda zahteva Fn)","Accessibility":"Pristupačnost","Accessibility help":"Pomoć za pristupačnost","Press %0 for help.":"Pritisnite %0 za pomoć.","Move focus in and out of an active dialog window":"Pomeranje fokusa u i van aktivnog prozora dijaloga","MENU_BAR_MENU_FILE":"File","MENU_BAR_MENU_EDIT":"Uredi","MENU_BAR_MENU_VIEW":"View","MENU_BAR_MENU_INSERT":"Ubaci","MENU_BAR_MENU_FORMAT":"Format","MENU_BAR_MENU_TOOLS":"Alati","MENU_BAR_MENU_HELP":"Pomoć","MENU_BAR_MENU_TEXT":"Tekst","MENU_BAR_MENU_FONT":"Font","Editor menu bar":"Traka menija uređivača","Please enter a valid color (e.g. \"ff0000\").":"Unesite važeću boju (npr. „ff0000“)."},getPluralForm(n){return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);}}};
e[ 'sr-latn' ] ||= { dictionary: {}, getPluralForm: null };

@@ -10,0 +10,0 @@ e[ 'sr-latn' ].dictionary = Object.assign( e[ 'sr-latn' ].dictionary, dictionary );

{
"name": "@ckeditor/ckeditor5-ui",
"version": "42.0.2",
"version": "43.0.0-alpha.0",
"description": "The UI framework and standard UI library of CKEditor 5.",

@@ -15,4 +15,4 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-core": "42.0.2",
"@ckeditor/ckeditor5-utils": "42.0.2",
"@ckeditor/ckeditor5-core": "43.0.0-alpha.0",
"@ckeditor/ckeditor5-utils": "43.0.0-alpha.0",
"color-convert": "2.0.1",

@@ -19,0 +19,0 @@ "color-parse": "1.4.2",

@@ -114,3 +114,2 @@ /**

attributes: {
role: 'region',
'aria-live': politeness,

@@ -117,0 +116,0 @@ 'aria-relevant': 'additions'

@@ -27,3 +27,3 @@ /**

/**
* @inheritdoc
* @inheritDoc
*/

@@ -30,0 +30,0 @@ constructor(...args) {

@@ -142,8 +142,2 @@ /**

/**
* (Optional) The ARIA property reflected by the `aria-checked` DOM attribute used by assistive technologies.
*
* @observable
*/
ariaChecked?: boolean | undefined;
/**
* (Optional) The ARIA property reflected by the `aria-label` DOM attribute used by assistive technologies.

@@ -150,0 +144,0 @@ *

@@ -123,6 +123,2 @@ /**

*/
ariaChecked: boolean | undefined;
/**
* @inheritDoc
*/
ariaLabel?: string | undefined;

@@ -134,2 +130,18 @@ /**

/**
* Aria-pressed attribute of element. It is calculated based on {@link #isToggleable isToggleable} and {@link #role}.
* It's set to true if the button is on and the role is not checkable.
*
* @readonly
* @internal
*/
_ariaPressed: string | false;
/**
* Aria-checked attribute of element. It is calculated based on {@link #isToggleable isToggleable} and {@link #role}.
* It's set to true if the button is on and the role is checkable.
*
* @readonly
* @internal
*/
_ariaChecked: string | false;
/**
* Tooltip of the button bound to the template.

@@ -136,0 +148,0 @@ *

@@ -48,2 +48,4 @@ /**

// Implement the Button interface.
this.set('_ariaPressed', false);
this.set('_ariaChecked', false);
this.set('ariaLabel', undefined);

@@ -93,7 +95,7 @@ this.set('ariaLabelledBy', `ck-editor__aria-label_${ariaLabelUid}`);

tabindex: bind.to('tabindex'),
'aria-checked': bind.to('ariaChecked'),
'aria-checked': bind.to('_ariaChecked'),
'aria-pressed': bind.to('_ariaPressed'),
'aria-label': bind.to('ariaLabel'),
'aria-labelledby': bind.to('ariaLabelledBy'),
'aria-disabled': bind.if('isEnabled', true, value => !value),
'aria-pressed': bind.to('isOn', value => this.isToggleable ? String(!!value) : false),
'data-cke-tooltip-text': bind.to('_tooltipString'),

@@ -118,2 +120,14 @@ 'data-cke-tooltip-position': bind.to('tooltipPosition')

};
this.bind('_ariaPressed').to(this, 'isOn', this, 'isToggleable', this, 'role', (isOn, isToggleable, role) => {
if (!isToggleable || isCheckableRole(role)) {
return false;
}
return String(!!isOn);
});
this.bind('_ariaChecked').to(this, 'isOn', this, 'isToggleable', this, 'role', (isOn, isToggleable, role) => {
if (!isToggleable || !isCheckableRole(role)) {
return false;
}
return String(!!isOn);
});
// On Safari we have to force the focus on a button on click as it's the only browser

@@ -222,1 +236,17 @@ // that doesn't do that automatically. See #12115.

}
/**
* Checks if `aria-checkbox` can be used with specified role.
*/
function isCheckableRole(role) {
switch (role) {
case 'radio':
case 'checkbox':
case 'option':
case 'switch':
case 'menuitemcheckbox':
case 'menuitemradio':
return true;
default:
return false;
}
}

@@ -5,4 +5,10 @@ /**

*/
/**
* @module ui/button/filedialogbuttonview
*/
import View from '../view.js';
import ButtonView from './buttonview.js';
import type { Locale } from '@ckeditor/ckeditor5-utils';
import type { Mixed } from '@ckeditor/ckeditor5-utils';
import ListItemButtonView from './listitembuttonview.js';
declare const FileDialogButtonView_base: Mixed<typeof ButtonView, FileDialogButtonViewBase>;
/**

@@ -32,3 +38,35 @@ * The file dialog button view.

*/
export default class FileDialogButtonView extends ButtonView {
export default class FileDialogButtonView extends /* #__PURE__ */ FileDialogButtonView_base {
}
declare const FileDialogListItemButtonView_base: Mixed<typeof ListItemButtonView, FileDialogButtonViewBase>;
/**
* The file dialog button view used in a lists.
*
* This component provides a button that opens the native file selection dialog.
* It can be used to implement the UI of a file upload feature.
*
* ```ts
* const view = new FileDialogListItemButtonView( locale );
*
* view.set( {
* acceptedType: 'image/*',
* allowMultipleFiles: true
* label: t( 'Insert image' ),
* icon: imageIcon,
* tooltip: true
* } );
*
* view.on( 'done', ( evt, files ) => {
* for ( const file of Array.from( files ) ) {
* console.log( 'Selected file', file );
* }
* } );
* ```
*/
export declare class FileDialogListItemButtonView extends /* #__PURE__ */ FileDialogListItemButtonView_base {
}
/**
* Represents the base view for a file dialog button component.
*/
type FileDialogButtonViewBase = View & {
/**

@@ -41,6 +79,2 @@ * The button view of the component.

/**
* A hidden `<input>` view used to execute file dialog.
*/
private _fileInputView;
/**
* Accepted file types. Can be provided in form of file extensions, media type or one of:

@@ -60,11 +94,3 @@ * * `audio/*`,

allowMultipleFiles: boolean;
/**
* @inheritDoc
*/
constructor(locale?: Locale);
/**
* @inheritDoc
*/
render(): void;
}
};
/**

@@ -85,1 +111,2 @@ * Fired when file dialog is closed with file selected.

};
export {};

@@ -10,2 +10,3 @@ /**

import ButtonView from './buttonview.js';
import ListItemButtonView from './listitembuttonview.js';
/**

@@ -35,30 +36,71 @@ * The file dialog button view.

*/
export default class FileDialogButtonView extends ButtonView {
/**
* @inheritDoc
*/
constructor(locale) {
super(locale);
// For backward compatibility.
this.buttonView = this;
this._fileInputView = new FileInputView(locale);
this._fileInputView.bind('acceptedType').to(this);
this._fileInputView.bind('allowMultipleFiles').to(this);
this._fileInputView.delegate('done').to(this);
this.on('execute', () => {
this._fileInputView.open();
});
this.extendTemplate({
attributes: {
class: 'ck-file-dialog-button'
}
});
export default class FileDialogButtonView extends /* #__PURE__ */ FileDialogViewMixin(ButtonView) {
}
/**
* The file dialog button view used in a lists.
*
* This component provides a button that opens the native file selection dialog.
* It can be used to implement the UI of a file upload feature.
*
* ```ts
* const view = new FileDialogListItemButtonView( locale );
*
* view.set( {
* acceptedType: 'image/*',
* allowMultipleFiles: true
* label: t( 'Insert image' ),
* icon: imageIcon,
* tooltip: true
* } );
*
* view.on( 'done', ( evt, files ) => {
* for ( const file of Array.from( files ) ) {
* console.log( 'Selected file', file );
* }
* } );
* ```
*/
export class FileDialogListItemButtonView extends /* #__PURE__ */ FileDialogViewMixin(ListItemButtonView) {
}
/**
* Mixin function that enhances a base button view class with file dialog functionality. It is used
* to create a button view class that opens the native select file dialog when clicked.
*
* The enhanced view includes a button and a hidden file input. When the button is clicked, the file dialog is opened.
* The mixin adds properties and methods to the base class to handle the file selection.
*
* @param view The base class to be enhanced with file dialog functionality.
* @returns A new class that extends the base class and includes the file dialog functionality.
*/
function FileDialogViewMixin(view) {
class FileDialogView extends view {
/**
* @inheritDoc
*/
constructor(...args) {
super(...args);
// For backward compatibility.
this.buttonView = this;
this._fileInputView = new FileInputView(this.locale);
this._fileInputView.bind('acceptedType').to(this);
this._fileInputView.bind('allowMultipleFiles').to(this);
this._fileInputView.delegate('done').to(this);
this.on('execute', () => {
this._fileInputView.open();
});
this.extendTemplate({
attributes: {
class: 'ck-file-dialog-button'
}
});
}
/**
* @inheritDoc
*/
render() {
super.render();
this.children.add(this._fileInputView);
}
}
/**
* @inheritDoc
*/
render() {
super.render();
this.children.add(this._fileInputView);
}
return FileDialogView;
}

@@ -65,0 +107,0 @@ /**

@@ -197,2 +197,7 @@ /**

const { t } = this.locale;
// If the input is hidden, it's always valid, because there is no way to select
// invalid color value using diagram color picker.
if (this._config.hideInput) {
return true;
}
this.resetValidationStatus();

@@ -199,0 +204,0 @@ // One error per field is enough.

@@ -12,3 +12,2 @@ /**

import ColorTileView from '../colorgrid/colortileview.js';
import LabelView from '../label/labelview.js';
import Template from '../template.js';

@@ -119,5 +118,5 @@ import DocumentColorCollection from './documentcolorcollection.js';

const bind = Template.bind(this.documentColors, this.documentColors);
const label = new LabelView(this.locale);
label.text = this._documentColorsLabel;
label.extendTemplate({
const label = new View(this.locale);
label.setTemplate({
tag: 'span',
attributes: {

@@ -129,3 +128,8 @@ class: [

]
}
},
children: [
{
text: this._documentColorsLabel
}
]
});

@@ -132,0 +136,0 @@ this.items.add(label);

@@ -26,3 +26,6 @@ /**

this._initMultiRootIntegration();
this.set('id', null);
this.set({
id: null,
isOpen: false
});
// Add the information about the keystroke to the accessibility database.

@@ -29,0 +32,0 @@ editor.accessibility.addKeystrokeInfos({

@@ -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 @@ });

@@ -15,3 +15,2 @@ /**

import ListSeparatorView from '../list/listseparatorview.js';
import ButtonView from '../button/buttonview.js';
import SplitButtonView from './button/splitbuttonview.js';

@@ -25,2 +24,3 @@ import SwitchButtonView from '../button/switchbuttonview.js';

import ListItemGroupView from '../list/listitemgroupview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
/**

@@ -432,2 +432,19 @@ * A helper for creating dropdowns. It creates an instance of a {@link module:ui/dropdown/dropdownview~DropdownView dropdown},

function bindViewCollectionItemsToDefinitions(dropdownView, listItems, definitions, locale) {
// List item checkboxes have a reserved space for the check icon, so we need to know if there are any checkboxes in the list
// to adjust the layout accordingly. It'd look weird if the items on the list were not aligned horizontally.
//
// Possible theoretical performance problem if many items are added one by one, as this will be called for each item.
listItems.on('change', () => {
// Filter-map. Check all items, leave only these that have buttons and return the buttons.
const listItemButtons = [...listItems].reduce((acc, item) => {
if (item instanceof ListItemView && item.children.first instanceof ListItemButtonView) {
acc.push(item.children.first);
}
return acc;
}, []);
const hasAnyCheckboxOnList = listItemButtons.some(button => button.isToggleable);
listItemButtons.forEach(item => {
item.hasCheckSpace = hasAnyCheckboxOnList;
});
});
listItems.bindTo(definitions).using(def => {

@@ -445,7 +462,10 @@ if (def.type === 'separator') {

else if (def.type === 'button' || def.type === 'switchbutton') {
const isToggleable = def.model.role === 'menuitemcheckbox' || def.model.role === 'menuitemradio';
const listItemView = new ListItemView(locale);
let buttonView;
if (def.type === 'button') {
buttonView = new ButtonView(locale);
buttonView.bind('ariaChecked').to(buttonView, 'isOn');
buttonView = new ListItemButtonView(locale);
buttonView.set({
isToggleable
});
}

@@ -452,0 +472,0 @@ else {

@@ -50,3 +50,3 @@ /**

*/
private _showDialog;
private _toggleDialog;
}

@@ -66,3 +66,3 @@ /**

editor.keystrokes.set('Alt+0', (evt, cancel) => {
this._showDialog();
this._toggleDialog();
cancel();

@@ -77,2 +77,3 @@ });

const editor = this.editor;
const dialog = editor.plugins.get('Dialog');
const locale = editor.locale;

@@ -82,5 +83,7 @@ const view = new ButtonClass(locale);

keystroke: 'Alt+0',
icon: accessibilityIcon
icon: accessibilityIcon,
isToggleable: true
});
view.on('execute', () => this._showDialog());
view.on('execute', () => this._toggleDialog());
view.bind('isOn').to(dialog, 'id', id => id === 'accessibilityHelp');
return view;

@@ -116,3 +119,3 @@ }

*/
_showDialog() {
_toggleDialog() {
const editor = this.editor;

@@ -124,11 +127,16 @@ const dialog = editor.plugins.get('Dialog');

}
dialog.show({
id: 'accessibilityHelp',
className: 'ck-accessibility-help-dialog',
title: t('Accessibility help'),
icon: accessibilityIcon,
hasCloseButton: true,
content: this.contentView
});
if (dialog.id === 'accessibilityHelp') {
dialog.hide();
}
else {
dialog.show({
id: 'accessibilityHelp',
className: 'ck-accessibility-help-dialog',
title: t('Accessibility help'),
icon: accessibilityIcon,
hasCloseButton: true,
content: this.contentView
});
}
}
}

@@ -59,3 +59,4 @@ /**

],
dir: this.locale.uiLanguageDirection
dir: this.locale.uiLanguageDirection,
role: 'application'
},

@@ -62,0 +63,0 @@ children: this

@@ -16,2 +16,3 @@ /**

import type { Editor } from '@ckeditor/ckeditor5-core';
import type { default as MenuBarView, MenuBarConfigAddedGroup, MenuBarConfigAddedItem, MenuBarConfigAddedMenu } from '../menubar/menubarview.js';
declare const EditorUI_base: {

@@ -105,2 +106,10 @@ new (): import("@ckeditor/ckeditor5-utils").Observable;

/**
* All additional menu bar items, groups or menus that have their default location defined.
*/
private _extraMenuBarElements;
/**
* The last focused element to which focus should return on `Esc` press.
*/
private _lastFocusedForeignElement;
/**
* Creates an instance of the editor UI class.

@@ -171,2 +180,42 @@ *

/**
* Registers an extra menu bar element, which could be a single item, a group of items, or a menu containing groups.
*
* ```ts
* // Register a new menu bar item.
* editor.ui.extendMenuBar( {
* item: 'menuBar:customFunctionButton',
* position: 'after:menuBar:bold'
* } );
*
* // Register a new menu bar group.
* editor.ui.extendMenuBar( {
* group: {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* },
* position: 'start:help'
* } );
*
* // Register a new menu bar menu.
* editor.ui.extendMenuBar( {
* menu: {
* menuId: 'customMenu',
* label: 'customMenu',
* groups: [
* {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* }
* ]
* },
* position: 'after:help'
* } );
* ```
*/
extendMenuBar(config: MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu): void;
/**
* Stores all editable elements used by the editor instance.

@@ -178,2 +227,6 @@ *

/**
* Initializes menu bar.
*/
protected _initMenuBar(menuBarView: MenuBarView): void;
/**
* Returns viewport offsets object:

@@ -200,2 +253,6 @@ *

/**
* Saves last focused element that doen not belong to editing view to restore focus on `Esc`.
*/
private _saveLastFocusedForeignElement;
/**
* Returns definitions of toolbars that could potentially be focused, sorted by their importance for the user.

@@ -202,0 +259,0 @@ *

@@ -14,2 +14,3 @@ /**

import { ObservableMixin, isVisible, FocusTracker } from '@ckeditor/ckeditor5-utils';
import { normalizeMenuBarConfig } from '../menubar/utils.js';
/**

@@ -41,2 +42,10 @@ * A class providing the minimal interface that is required to successfully bootstrap any editor UI.

this._focusableToolbarDefinitions = [];
/**
* All additional menu bar items, groups or menus that have their default location defined.
*/
this._extraMenuBarElements = [];
/**
* The last focused element to which focus should return on `Esc` press.
*/
this._lastFocusedForeignElement = null;
const editingView = editor.editing.view;

@@ -186,2 +195,44 @@ this.editor = editor;

/**
* Registers an extra menu bar element, which could be a single item, a group of items, or a menu containing groups.
*
* ```ts
* // Register a new menu bar item.
* editor.ui.extendMenuBar( {
* item: 'menuBar:customFunctionButton',
* position: 'after:menuBar:bold'
* } );
*
* // Register a new menu bar group.
* editor.ui.extendMenuBar( {
* group: {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* },
* position: 'start:help'
* } );
*
* // Register a new menu bar menu.
* editor.ui.extendMenuBar( {
* menu: {
* menuId: 'customMenu',
* label: 'customMenu',
* groups: [
* {
* groupId: 'customGroup',
* items: [
* 'menuBar:customFunctionButton'
* ]
* }
* ]
* },
* position: 'after:help'
* } );
* ```
*/
extendMenuBar(config) {
this._extraMenuBarElements.push(config);
}
/**
* Stores all editable elements used by the editor instance.

@@ -206,2 +257,38 @@ *

/**
* Initializes menu bar.
*/
_initMenuBar(menuBarView) {
const menuBarViewElement = menuBarView.element;
this.focusTracker.add(menuBarViewElement);
this.editor.keystrokes.listenTo(menuBarViewElement);
const normalizedMenuBarConfig = normalizeMenuBarConfig(this.editor.config.get('menuBar') || {});
menuBarView.fillFromConfig(normalizedMenuBarConfig, this.componentFactory, this._extraMenuBarElements);
this.editor.keystrokes.set('Esc', (data, cancel) => {
if (!menuBarViewElement.contains(this.editor.ui.focusTracker.focusedElement)) {
return;
}
// Bring focus back to where it came from before focusing the toolbar:
// If it came from outside the engine view (e.g. source editing), move it there.
if (this._lastFocusedForeignElement) {
this._lastFocusedForeignElement.focus();
this._lastFocusedForeignElement = null;
}
// Else just focus the view editing.
else {
this.editor.editing.view.focus();
}
cancel();
});
this.editor.keystrokes.set('Alt+F9', (data, cancel) => {
// If menu bar is already focused do nothing.
if (menuBarViewElement.contains(this.editor.ui.focusTracker.focusedElement)) {
return;
}
this._saveLastFocusedForeignElement();
menuBarView.isFocusBorderEnabled = true;
menuBarView.focus();
cancel();
});
}
/**
* Returns viewport offsets object:

@@ -253,14 +340,6 @@ *

const editingView = editor.editing.view;
let lastFocusedForeignElement;
let candidateDefinitions;
// Focus the next focusable toolbar on <kbd>Alt</kbd> + <kbd>F10</kbd>.
editor.keystrokes.set('Alt+F10', (data, cancel) => {
const focusedElement = this.focusTracker.focusedElement;
// Focus moved out of a DOM element that
// * is not a toolbar,
// * does not belong to the editing view (e.g. source editing).
if (Array.from(this._editableElementsMap.values()).includes(focusedElement) &&
!Array.from(editingView.domRoots.values()).includes(focusedElement)) {
lastFocusedForeignElement = focusedElement;
}
this._saveLastFocusedForeignElement();
const currentFocusedToolbarDefinition = this._getCurrentFocusedToolbarDefinition();

@@ -303,5 +382,5 @@ // * When focusing a toolbar for the first time, set the array of definitions for successive presses of Alt+F10.

// 1. If it came from outside the engine view (e.g. source editing), move it there.
if (lastFocusedForeignElement) {
lastFocusedForeignElement.focus();
lastFocusedForeignElement = null;
if (this._lastFocusedForeignElement) {
this._lastFocusedForeignElement.focus();
this._lastFocusedForeignElement = null;
}

@@ -323,2 +402,15 @@ // 2. There are two possibilities left:

/**
* Saves last focused element that doen not belong to editing view to restore focus on `Esc`.
*/
_saveLastFocusedForeignElement() {
const focusedElement = this.focusTracker.focusedElement;
// Focus moved out of a DOM element that
// * is not a toolbar,
// * does not belong to the editing view (e.g. source editing).
if (Array.from(this._editableElementsMap.values()).includes(focusedElement) &&
!Array.from(this.editor.editing.view.domRoots.values()).includes(focusedElement)) {
this._lastFocusedForeignElement = focusedElement;
}
}
/**
* Returns definitions of toolbars that could potentially be focused, sorted by their importance for the user.

@@ -325,0 +417,0 @@ *

@@ -13,2 +13,3 @@ /**

import '../../theme/components/editorui/editorui.css';
import type MenuBarView from '../menubar/menubarview.js';
/**

@@ -27,2 +28,6 @@ * The editor UI view class. Base class for the editor main views.

/**
* Menu bar view instance. May not be initialized in some editor types.
*/
menuBarView?: MenuBarView;
/**
* Creates an instance of the editor UI view class.

@@ -29,0 +34,0 @@ *

@@ -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 @@ *

@@ -21,4 +21,3 @@ /**

* It is used i.a.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
* and {@link module:special-characters/ui/specialcharactersnavigationview~SpecialCharactersNavigationView}.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}.
*

@@ -25,0 +24,0 @@ * The latter is an example, where the component has been extended by {@link module:ui/dropdown/dropdownview~DropdownView} view.

@@ -19,4 +19,3 @@ /**

* It is used i.a.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
* and {@link module:special-characters/ui/specialcharactersnavigationview~SpecialCharactersNavigationView}.
* by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}.
*

@@ -23,0 +22,0 @@ * The latter is an example, where the component has been extended by {@link module:ui/dropdown/dropdownview~DropdownView} view.

@@ -21,3 +21,4 @@ /**

export { default as SwitchButtonView } from './button/switchbuttonview.js';
export { default as FileDialogButtonView } from './button/filedialogbuttonview.js';
export { default as ListItemButtonView } from './button/listitembuttonview.js';
export { default as FileDialogButtonView, FileDialogListItemButtonView } from './button/filedialogbuttonview.js';
export { default as CollapsibleView } from './collapsible/collapsibleview.js';

@@ -57,2 +58,3 @@ export * from './colorgrid/utils.js';

export { default as ListView } from './list/listview.js';
export { default as filterGroupAndItemNames } from './search/filtergroupanditemnames.js';
export { default as Notification } from './notification/notification.js';

@@ -68,2 +70,4 @@ export { default as ViewModel } from './model.js';

export { default as HighlightedTextView } from './highlightedtext/highlightedtextview.js';
export { default as ButtonLabelWithHighlightView } from './highlightedtext/buttonlabelwithhighlightview.js';
export { default as LabelWithHighlightView } from './highlightedtext/labelwithhighlightview.js';
export { default as TooltipManager } from './tooltipmanager.js';

@@ -85,3 +89,3 @@ export { default as Template, type TemplateDefinition } from './template.js';

export { default as MenuBarMenuListItemFileDialogButtonView } from './menubar/menubarmenulistitemfiledialogbuttonview.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems, _initMenuBar } from './menubar/utils.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems } from './menubar/utils.js';
import './augmentation.js';

@@ -20,3 +20,4 @@ /**

export { default as SwitchButtonView } from './button/switchbuttonview.js';
export { default as FileDialogButtonView } from './button/filedialogbuttonview.js';
export { default as ListItemButtonView } from './button/listitembuttonview.js';
export { default as FileDialogButtonView, FileDialogListItemButtonView } from './button/filedialogbuttonview.js';
export { default as CollapsibleView } from './collapsible/collapsibleview.js';

@@ -55,2 +56,3 @@ export * from './colorgrid/utils.js';

export { default as ListView } from './list/listview.js';
export { default as filterGroupAndItemNames } from './search/filtergroupanditemnames.js';
export { default as Notification } from './notification/notification.js';

@@ -65,2 +67,4 @@ export { default as ViewModel } from './model.js';

export { default as HighlightedTextView } from './highlightedtext/highlightedtextview.js';
export { default as ButtonLabelWithHighlightView } from './highlightedtext/buttonlabelwithhighlightview.js';
export { default as LabelWithHighlightView } from './highlightedtext/labelwithhighlightview.js';
export { default as TooltipManager } from './tooltipmanager.js';

@@ -82,3 +86,3 @@ export { default as Template } from './template.js';

export { default as MenuBarMenuListItemFileDialogButtonView } from './menubar/menubarmenulistitemfiledialogbuttonview.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems, _initMenuBar } from './menubar/utils.js';
export { normalizeMenuBarConfig, DefaultMenuBarItems } from './menubar/utils.js';
import './augmentation.js';

@@ -9,3 +9,3 @@ /**

import IconView from '../icon/iconview.js';
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import type { Locale } from '@ckeditor/ckeditor5-utils';

@@ -17,3 +17,3 @@ import '../../theme/components/menubar/menubarmenubutton.css';

*/
export default class MenuBarMenuButtonView extends ButtonView {
export default class MenuBarMenuButtonView extends ListItemButtonView {
/**

@@ -20,0 +20,0 @@ * An icon that displays an arrow to indicate a direction of the menu.

@@ -9,3 +9,3 @@ /**

import IconView from '../icon/iconview.js';
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import dropdownArrowIcon from '../../theme/icons/dropdown-arrow.svg';

@@ -17,3 +17,3 @@ import '../../theme/components/menubar/menubarmenubutton.css';

*/
export default class MenuBarMenuButtonView extends ButtonView {
export default class MenuBarMenuButtonView extends ListItemButtonView {
/**

@@ -20,0 +20,0 @@ * Creates an instance of the menu bar button view.

@@ -9,3 +9,3 @@ /**

import type { Locale } from '@ckeditor/ckeditor5-utils';
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -15,3 +15,3 @@ /**

*/
export default class MenuBarMenuListItemButtonView extends ButtonView {
export default class MenuBarMenuListItemButtonView extends ListItemButtonView {
/**

@@ -18,0 +18,0 @@ * Creates an instance of the menu bar list button view.

@@ -5,3 +5,3 @@ /**

*/
import ButtonView from '../button/buttonview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -11,3 +11,3 @@ /**

*/
export default class MenuBarMenuListItemButtonView extends ButtonView {
export default class MenuBarMenuListItemButtonView extends ListItemButtonView {
/**

@@ -14,0 +14,0 @@ * Creates an instance of the menu bar list button view.

@@ -9,3 +9,3 @@ /**

import type { Locale } from '@ckeditor/ckeditor5-utils';
import FileDialogButtonView from '../button/filedialogbuttonview.js';
import { FileDialogListItemButtonView } from '../button/filedialogbuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -17,3 +17,3 @@ /**

*/
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogButtonView {
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogListItemButtonView {
/**

@@ -20,0 +20,0 @@ * Creates an instance of the menu bar list button view.

@@ -5,3 +5,3 @@ /**

*/
import FileDialogButtonView from '../button/filedialogbuttonview.js';
import { FileDialogListItemButtonView } from '../button/filedialogbuttonview.js';
import '../../theme/components/menubar/menubarmenulistitembutton.css';

@@ -13,3 +13,3 @@ /**

*/
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogButtonView {
export default class MenuBarMenuListItemFileDialogButtonView extends FileDialogListItemButtonView {
/**

@@ -16,0 +16,0 @@ * Creates an instance of the menu bar list button view.

@@ -24,2 +24,7 @@ /**

constructor(locale: Locale);
/**
* This method adds empty space if there is any toggleable item in the list.
* It makes the list properly aligned.
*/
private _setItemsCheckSpace;
}

@@ -5,3 +5,6 @@ /**

*/
import ListItemView from '../list/listitemview.js';
import ListView from '../list/listview.js';
import ListItemButtonView from '../button/listitembuttonview.js';
import ButtonView from '../button/buttonview.js';
/**

@@ -23,3 +26,49 @@ * A list of menu bar items, a child of {@link module:ui/menubar/menubarmenuview~MenuBarMenuView#panelView}.

this.role = 'menu';
this.items.on('change', this._setItemsCheckSpace.bind(this));
}
/**
* This method adds empty space if there is any toggleable item in the list.
* It makes the list properly aligned.
*/
_setItemsCheckSpace() {
const hasAnyToggleableItem = (Array
.from(this.items)
.some(item => {
const listButtonView = pickListButtonMenuViewIfPresent(item);
return listButtonView && listButtonView.isToggleable;
}));
this.items.forEach(item => {
const listButtonView = pickListButtonMenuViewIfPresent(item);
if (listButtonView) {
listButtonView.hasCheckSpace = hasAnyToggleableItem;
}
});
}
}
/**
* Picks the first button menu view from the given item if present.
*
* @param item The item to check for a button menu view.
* @returns The first button menu view found in the item, or `null` if not found.
*/
function pickListButtonMenuViewIfPresent(item) {
if (!(item instanceof ListItemView)) {
return null;
}
return item
.children
.map(child => isNestedMenuLikeView(child) ? child.buttonView : child)
.find(item => item instanceof ListItemButtonView);
}
/**
* Checks if the given item is a nested menu-like view. `MenuBarMenuView` imports this file
* so to avoid circular dependencies, this function is defined in more generic way.
*
* @param item The item to check.
* @returns `true` if the item is a nested menu-like view, `false` otherwise.
*/
function isNestedMenuLikeView(item) {
return (typeof item === 'object' &&
'buttonView' in item &&
item.buttonView instanceof ButtonView);
}

@@ -32,2 +32,11 @@ /**

/**
* Indicates whether the menu bar has been interacted with using the keyboard.
*
* It is useful for showing focus outlines while hovering over the menu bar when
* interaction with the keyboard was detected.
*
* @observable
*/
isFocusBorderEnabled: boolean;
/**
* A list of {@link module:ui/menubar/menubarmenuview~MenuBarMenuView} instances registered in the menu bar.

@@ -51,3 +60,3 @@ *

*/
fillFromConfig(config: NormalizedMenuBarConfigObject, componentFactory: ComponentFactory): void;
fillFromConfig(config: NormalizedMenuBarConfigObject, componentFactory: ComponentFactory, extraItems?: Array<MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu>): void;
/**

@@ -54,0 +63,0 @@ * @inheritDoc

@@ -40,3 +40,7 @@ /**

const t = locale.t;
this.set('isOpen', false);
const bind = this.bindTemplate;
this.set({
isOpen: false,
isFocusBorderEnabled: false
});
this._setupIsOpenUpdater();

@@ -53,3 +57,4 @@ this.children = this.createCollection();

'ck',
'ck-menu-bar'
'ck-menu-bar',
bind.if('isFocusBorderEnabled', 'ck-menu-bar_focus-border-enabled')
],

@@ -69,3 +74,3 @@ 'aria-label': t('Editor menu bar'),

*/
fillFromConfig(config, componentFactory) {
fillFromConfig(config, componentFactory, extraItems = []) {
const locale = this.locale;

@@ -75,3 +80,4 @@ const processedConfig = processMenuBarConfig({

locale,
componentFactory
componentFactory,
extraItems
});

@@ -94,2 +100,3 @@ const topLevelCategoryMenuViews = processedConfig.items.map(menuDefinition => this._createMenu({

MenuBarBehaviors.closeOnClickOutside(this);
MenuBarBehaviors.enableFocusHighlightOnInteraction(this);
}

@@ -96,0 +103,0 @@ /**

@@ -6,5 +6,4 @@ /**

import type MenuBarMenuView from './menubarmenuview.js';
import type { default as MenuBarView, MenuBarConfig, MenuBarConfigObject, NormalizedMenuBarConfigObject } from './menubarview.js';
import type { default as MenuBarView, MenuBarConfig, MenuBarConfigObject, MenuBarConfigAddedGroup, MenuBarConfigAddedMenu, NormalizedMenuBarConfigObject, MenuBarConfigAddedItem } from './menubarview.js';
import type ComponentFactory from '../componentfactory.js';
import type { Editor } from '@ckeditor/ckeditor5-core';
import { type Locale, type PositioningFunction } from '@ckeditor/ckeditor5-utils';

@@ -48,2 +47,7 @@ type DeepReadonly<T> = Readonly<{

closeOnClickOutside(menuBarView: MenuBarView): void;
/**
* Tracks the keyboard focus interaction on the menu bar view. It is used to determine if the nested items
* of the menu bar should render focus rings after first interaction with the keyboard.
*/
enableFocusHighlightOnInteraction(menuBarView: MenuBarView): void;
};

@@ -238,2 +242,8 @@ /**

* {
* groupId: 'previewMergeFields',
* items: [
* 'menuBar:previewMergeFields'
* ]
* },
* {
* groupId: 'restrictedEditingException',

@@ -263,3 +273,4 @@ * items: [

* 'menuBar:link',
* 'menuBar:comment'
* 'menuBar:comment',
* 'menuBar:insertMergeField'
* ]

@@ -434,13 +445,8 @@ * },

*/
export declare function processMenuBarConfig({ normalizedConfig, locale, componentFactory }: {
export declare function processMenuBarConfig({ normalizedConfig, locale, componentFactory, extraItems }: {
normalizedConfig: NormalizedMenuBarConfigObject;
locale: Locale;
componentFactory: ComponentFactory;
extraItems: Array<MenuBarConfigAddedItem | MenuBarConfigAddedGroup | MenuBarConfigAddedMenu>;
}): NormalizedMenuBarConfigObject;
/**
* Initializes menu bar for given editor.
*
* @internal
*/
export declare function _initMenuBar(editor: Editor, menuBarView: MenuBarView): void;
export {};

@@ -24,16 +24,20 @@ /**

menuBarView.on('menu:mouseenter', evt => {
// This works only when the menu bar has already been open and the user hover over the menu bar.
if (!menuBarView.isOpen) {
// This behavior should be activated when one of condition is present:
// 1. The user opened any submenu of menubar and hover over items in the menu bar.
// 2. The user focused whole menubar using keyboard interaction and enabled focus borders and hover over items in the menu bar.
if (!menuBarView.isFocusBorderEnabled && !menuBarView.isOpen) {
return;
}
for (const menuView of menuBarView.menus) {
// @if CK_DEBUG_MENU_BAR // const wasOpen = menuView.isOpen;
const pathLeaf = evt.path[0];
const isListItemContainingMenu = pathLeaf instanceof MenuBarMenuListItemView && pathLeaf.children.first === menuView;
menuView.isOpen = (evt.path.includes(menuView) || isListItemContainingMenu) && menuView.isEnabled;
// @if CK_DEBUG_MENU_BAR // if ( wasOpen !== menuView.isOpen ) {
// @if CK_DEBUG_MENU_BAR // console.log( '[BEHAVIOR] toggleMenusAndFocusItemsOnHover(): Toggle',
// @if CK_DEBUG_MENU_BAR // logMenu( menuView ), 'isOpen', menuView.isOpen
// @if CK_DEBUG_MENU_BAR // );
// @if CK_DEBUG_MENU_BAR // }
if (menuBarView.isOpen) {
for (const menuView of menuBarView.menus) {
// @if CK_DEBUG_MENU_BAR // const wasOpen = menuView.isOpen;
const pathLeaf = evt.path[0];
const isListItemContainingMenu = pathLeaf instanceof MenuBarMenuListItemView && pathLeaf.children.first === menuView;
menuView.isOpen = (evt.path.includes(menuView) || isListItemContainingMenu) && menuView.isEnabled;
// @if CK_DEBUG_MENU_BAR // if ( wasOpen !== menuView.isOpen ) {
// @if CK_DEBUG_MENU_BAR // console.log( '[BEHAVIOR] toggleMenusAndFocusItemsOnHover(): Toggle',
// @if CK_DEBUG_MENU_BAR // logMenu( menuView ), 'isOpen', menuView.isOpen
// @if CK_DEBUG_MENU_BAR // );
// @if CK_DEBUG_MENU_BAR // }
}
}

@@ -115,2 +119,36 @@ evt.source.focus();

});
},
/**
* Tracks the keyboard focus interaction on the menu bar view. It is used to determine if the nested items
* of the menu bar should render focus rings after first interaction with the keyboard.
*/
enableFocusHighlightOnInteraction(menuBarView) {
let isKeyPressed = false;
menuBarView.on('change:isOpen', (_, evt, isOpen) => {
if (!isOpen) {
menuBarView.isFocusBorderEnabled = false;
// Reset the flag when the menu bar is closed, menu items tend to intercept `keyup` event
// and sometimes, after pressing `enter` on focused item, `isKeyPressed` stuck in `true` state.
isKeyPressed = false;
}
});
// After clicking menu bar list item the focus is moved to the newly opened submenu.
// We need to enable focus border for the submenu items because after pressing arrow down it will
// focus second item instead of first which is not super intuitive.
menuBarView.listenTo(menuBarView.element, 'click', () => {
if (menuBarView.isOpen && menuBarView.element.matches(':focus-within')) {
menuBarView.isFocusBorderEnabled = true;
}
}, { useCapture: true });
menuBarView.listenTo(menuBarView.element, 'keydown', () => {
isKeyPressed = true;
}, { useCapture: true });
menuBarView.listenTo(menuBarView.element, 'keyup', () => {
isKeyPressed = false;
}, { useCapture: true });
menuBarView.listenTo(menuBarView.element, 'focus', () => {
if (isKeyPressed) {
menuBarView.isFocusBorderEnabled = true;
}
}, { useCapture: true });
}

@@ -161,3 +199,5 @@ };

menuView.isOpen = true;
menuView.panelView.focus();
if (menuView.parentMenuView) {
menuView.panelView.focus();
}
});

@@ -171,5 +211,2 @@ },

menuView.isOpen = !menuView.isOpen;
if (menuView.isOpen) {
menuView.panelView.focus();
}
});

@@ -427,2 +464,8 @@ },

* {
* groupId: 'previewMergeFields',
* items: [
* 'menuBar:previewMergeFields'
* ]
* },
* {
* groupId: 'restrictedEditingException',

@@ -452,3 +495,4 @@ * items: [

* 'menuBar:link',
* 'menuBar:comment'
* 'menuBar:comment',
* 'menuBar:insertMergeField'
* ]

@@ -679,6 +723,12 @@ * },

{
groupId: 'restrictedEditingException',
groupId: 'previewMergeFields',
items: [
'menuBar:restrictedEditingException'
'menuBar:previewMergeFields'
]
},
{
groupId: 'restrictedEditing',
items: [
'menuBar:restrictedEditing'
]
}

@@ -704,3 +754,4 @@ ]

'menuBar:link',
'menuBar:comment'
'menuBar:comment',
'menuBar:insertMergeField'
]

@@ -713,2 +764,3 @@ },

'menuBar:insertTemplate',
'menuBar:specialCharacters',
'menuBar:blockQuote',

@@ -728,5 +780,5 @@ 'menuBar:codeBlock',

{
groupId: 'restrictedEditing',
groupId: 'restrictedEditingException',
items: [
'menuBar:restrictedEditing'
'menuBar:restrictedEditingException'
]

@@ -898,6 +950,7 @@ }

*/
export function processMenuBarConfig({ normalizedConfig, locale, componentFactory }) {
export function processMenuBarConfig({ normalizedConfig, locale, componentFactory, extraItems }) {
const configClone = cloneDeep(normalizedConfig);
handleAdditions(normalizedConfig, configClone, extraItems);
handleRemovals(normalizedConfig, configClone);
handleAdditions(normalizedConfig, configClone);
handleAdditions(normalizedConfig, configClone, configClone.addItems);
purgeUnavailableComponents(normalizedConfig, configClone, componentFactory);

@@ -967,9 +1020,11 @@ purgeEmptyMenus(normalizedConfig, configClone);

/**
* Handles the `config.menuBar.addItems` configuration. It allows for adding menus, groups, and items at arbitrary
* Adds provided items to config. It allows for adding menus, groups, and items at arbitrary
* positions in the menu bar. If the position does not exist, a warning is logged.
*/
function handleAdditions(originalConfig, config) {
const itemsToBeAdded = config.addItems;
function handleAdditions(originalConfig, config, items) {
const successFullyAddedItems = [];
for (const itemToAdd of itemsToBeAdded) {
if (items.length == 0) {
return;
}
for (const itemToAdd of items) {
const relation = getRelationFromPosition(itemToAdd.position);

@@ -1053,3 +1108,3 @@ const relativeId = getRelativeIdFromPosition(itemToAdd.position);

}
for (const addedItemConfig of itemsToBeAdded) {
for (const addedItemConfig of items) {
if (!successFullyAddedItems.includes(addedItemConfig)) {

@@ -1338,25 +1393,1 @@ /**

}
/**
* Initializes menu bar for given editor.
*
* @internal
*/
export function _initMenuBar(editor, menuBarView) {
const menuBarViewElement = menuBarView.element;
editor.ui.focusTracker.add(menuBarViewElement);
editor.keystrokes.listenTo(menuBarViewElement);
const normalizedMenuBarConfig = normalizeMenuBarConfig(editor.config.get('menuBar') || {});
menuBarView.fillFromConfig(normalizedMenuBarConfig, editor.ui.componentFactory);
editor.keystrokes.set('Esc', (data, cancel) => {
if (menuBarViewElement.contains(editor.ui.focusTracker.focusedElement)) {
editor.editing.view.focus();
cancel();
}
});
editor.keystrokes.set('Alt+F9', (data, cancel) => {
if (!menuBarViewElement.contains(editor.ui.focusTracker.focusedElement)) {
menuBarView.focus();
cancel();
}
});
}

@@ -114,2 +114,6 @@ /**

/**
* An instance of resize observer used to detect if target element is still visible.
*/
private _resizeObserver;
/**
* @inheritDoc

@@ -119,2 +123,6 @@ */

/**
* @inheritDoc
*/
destroy(): void;
/**
* Shows the panel.

@@ -162,4 +170,6 @@ *

* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/
attachTo(options: Partial<PositionOptions>): void;
attachTo(options: Partial<PositionOptions>): boolean;
/**

@@ -208,2 +218,4 @@ * Works the same way as the {@link #attachTo} method except that the position of the panel is

* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/

@@ -210,0 +222,0 @@ private _startPinning;

@@ -9,3 +9,3 @@ /**

import View from '../../view.js';
import { getOptimalPosition, global, isRange, toUnit } from '@ckeditor/ckeditor5-utils';
import { getOptimalPosition, global, isRange, toUnit, isVisible, ResizeObserver } from '@ckeditor/ckeditor5-utils';
import { isElement } from 'lodash-es';

@@ -83,2 +83,3 @@ import '../../../theme/components/panel/balloonpanel.css';

this._pinWhenIsVisibleCallback = null;
this._resizeObserver = null;
this.content = this.createCollection();

@@ -105,2 +106,9 @@ this.setTemplate({

/**
* @inheritDoc
*/
destroy() {
this.hide();
super.destroy();
}
/**
* Shows the panel.

@@ -152,4 +160,10 @@ *

* Default `positions` array is {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/
attachTo(options) {
const target = getDomElement(options.target);
if (target && !isVisible(target)) {
return false;
}
this.show();

@@ -187,2 +201,3 @@ const defaultPositions = BalloonPanelView.defaultPositions;

this.withArrow = withArrow;
return true;
}

@@ -225,2 +240,5 @@ /**

this.unpin();
if (!this._startPinning(options)) {
return;
}
this._pinWhenIsVisibleCallback = () => {

@@ -234,3 +252,2 @@ if (this.isVisible) {

};
this._startPinning(options);
// Control the state of the listeners depending on whether the panel is visible

@@ -259,5 +276,9 @@ // or not.

* @param options Positioning options compatible with {@link module:utils/dom/position~getOptimalPosition}.
* @returns Whether the balloon was shown and successfully attached or not. Attaching can fail if the target
* provided in the options is invisible (e.g. element detached from DOM).
*/
_startPinning(options) {
this.attachTo(options);
if (!this.attachTo(options)) {
return false;
}
const targetElement = getDomElement(options.target);

@@ -282,2 +303,15 @@ const limiterElement = options.limiter ? getDomElement(options.limiter) : global.document.body;

});
// Hide the panel if the target element is no longer visible.
if (targetElement && !this._resizeObserver) {
const checkVisibility = () => {
// If the target element is no longer visible, hide the panel.
if (!isVisible(targetElement)) {
this.unpin();
}
};
// Element is being resized to 0x0 after it's parent became hidden,
// so we need to check size in order to determine if it's visible or not.
this._resizeObserver = new ResizeObserver(targetElement, checkVisibility);
}
return true;
}

@@ -290,2 +324,6 @@ /**

this.stopListening(global.window, 'resize');
if (this._resizeObserver) {
this._resizeObserver.destroy();
this._resizeObserver = null;
}
}

@@ -292,0 +330,0 @@ /**

@@ -130,2 +130,3 @@ /**

this.search('');
this.filteredView.element.scrollTo(0, 0);
}

@@ -132,0 +133,0 @@ /**

@@ -165,3 +165,3 @@ /**

}
// Don not show the toolbar when all components inside are disabled
// Do not show the toolbar when all components inside are disabled
// see https://github.com/ckeditor/ckeditor5-ui/issues/269.

@@ -168,0 +168,0 @@ if (Array.from(this.toolbarView.items).every((item) => item.isEnabled !== undefined && !item.isEnabled)) {

@@ -137,2 +137,6 @@ /**

/**
* Repositions the button on scroll.
*/
private _repositionButtonOnScroll;
/**
* Attaches the {@link #buttonView} to the target block of content.

@@ -144,2 +148,12 @@ *

/**
* Clips the button element to the viewport of the editable element.
*
* * If the button overflows the editable viewport, it is clipped to make it look like it's cut off by the editable scrollable region.
* * If the button is fully hidden by the top of the editable, it is not clickable but still visible in the DOM.
*
* @param buttonView The button view to clip.
* @param editableElement The editable element whose viewport is used for clipping.
*/
private _clipButtonToViewport;
/**
* Creates a resize observer that observes selected editable and resizes the toolbar panel accordingly.

@@ -146,0 +160,0 @@ */

@@ -10,3 +10,3 @@ /**

import { Plugin } from '@ckeditor/ckeditor5-core';
import { Rect, ResizeObserver, toUnit } from '@ckeditor/ckeditor5-utils';
import { global, Rect, ResizeObserver, toUnit } from '@ckeditor/ckeditor5-utils';
import BlockButtonView from './blockbuttonview.js';

@@ -135,2 +135,4 @@ import BalloonPanelView from '../../panel/balloon/balloonpanelview.js';

});
// Reposition button on scroll.
this._repositionButtonOnScroll();
// Register the toolbar so it becomes available for Alt+F10 and Esc navigation.

@@ -334,2 +336,33 @@ editor.ui.addToolbar(this.toolbarView, {

/**
* Repositions the button on scroll.
*/
_repositionButtonOnScroll() {
const { buttonView } = this;
let pendingAnimationFrame = false;
// Reposition the button on scroll, but do it only once per animation frame to avoid performance issues.
const repositionOnScroll = () => {
if (pendingAnimationFrame) {
return;
}
pendingAnimationFrame = true;
global.window.requestAnimationFrame(() => {
this._updateButton();
pendingAnimationFrame = false;
});
};
// Watch scroll event only when the button is visible, it prevents attaching the scroll event listener
// to the document when the button is not visible.
buttonView.on('change:isVisible', (evt, name, isVisible) => {
if (isVisible) {
buttonView.listenTo(global.document, 'scroll', repositionOnScroll, {
useCapture: true,
usePassive: true
});
}
else {
buttonView.stopListening(global.document, 'scroll', repositionOnScroll);
}
});
}
/**
* Attaches the {@link #buttonView} to the target block of content.

@@ -340,4 +373,6 @@ *

_attachButtonToElement(targetElement) {
const buttonElement = this.buttonView.element;
const editableElement = this._getSelectedEditableElement();
const contentStyles = window.getComputedStyle(targetElement);
const editableRect = new Rect(this._getSelectedEditableElement());
const editableRect = new Rect(editableElement);
const contentPaddingTop = parseInt(contentStyles.paddingTop, 10);

@@ -347,3 +382,3 @@ // When line height is not an integer then treat it as "normal".

const contentLineHeight = parseInt(contentStyles.lineHeight, 10) || parseInt(contentStyles.fontSize, 10) * 1.2;
const buttonRect = new Rect(this.buttonView.element);
const buttonRect = new Rect(buttonElement);
const contentRect = new Rect(targetElement);

@@ -362,4 +397,49 @@ let positionLeft;

this.buttonView.left = absoluteButtonRect.left;
this._clipButtonToViewport(this.buttonView, editableElement);
}
/**
* Clips the button element to the viewport of the editable element.
*
* * If the button overflows the editable viewport, it is clipped to make it look like it's cut off by the editable scrollable region.
* * If the button is fully hidden by the top of the editable, it is not clickable but still visible in the DOM.
*
* @param buttonView The button view to clip.
* @param editableElement The editable element whose viewport is used for clipping.
*/
_clipButtonToViewport(buttonView, editableElement) {
const absoluteButtonRect = new Rect(buttonView.element);
const scrollViewportRect = new Rect(editableElement).getVisible();
// Sets polygon clip path for the button element, if there is no argument provided, the clip path is removed.
const setButtonClipping = (...paths) => {
buttonView.element.style.clipPath = paths.length ? `polygon(${paths.join(',')})` : '';
};
// Hide the button if it's fully hidden by the top of the editable.
// Note that the button is still visible in the DOM, but it's not clickable. It's because we don't
// want to hide the button completely, as there are plenty of `isVisible` watchers which toggles
// the button scroll listeners.
const markAsHidden = (isHidden) => {
buttonView.isEnabled = !isHidden;
buttonView.element.style.pointerEvents = isHidden ? 'none' : '';
};
if (scrollViewportRect && scrollViewportRect.bottom < absoluteButtonRect.bottom) {
// Calculate the delta between the button bottom and the editable bottom, and clip the button
// to make it look like it's cut off by the editable scrollable region.
const delta = Math.min(absoluteButtonRect.height, absoluteButtonRect.bottom - scrollViewportRect.bottom);
markAsHidden(delta >= absoluteButtonRect.height);
setButtonClipping('0 0', '100% 0', `100% calc(100% - ${toPx(delta)})`, `0 calc(100% - ${toPx(delta)}`);
}
else if (scrollViewportRect && scrollViewportRect.top > absoluteButtonRect.top) {
// Calculate the delta between the button top and the editable top, and clip the button
// to make it look like it's cut off by the editable scrollable region.
const delta = Math.min(absoluteButtonRect.height, scrollViewportRect.top - absoluteButtonRect.top);
markAsHidden(delta >= absoluteButtonRect.height);
setButtonClipping(`0 ${toPx(delta)}`, `100% ${toPx(delta)}`, '100% 100%', '0 100%');
}
else {
// Reset the clip path if button is fully visible.
markAsHidden(false);
setButtonClipping();
}
}
/**
* Creates a resize observer that observes selected editable and resizes the toolbar panel accordingly.

@@ -366,0 +446,0 @@ */

@@ -97,9 +97,2 @@ /**

/**
* An instance of the resize observer that keeps track on target element visibility,
* when it hides the tooltip should also disappear.
*
* {@link module:core/editor/editorconfig~EditorConfig#balloonToolbar configuration}.
*/
private _resizeObserver;
/**
* An instance of the mutation observer that keeps track on target element attributes changes.

@@ -106,0 +99,0 @@ */

@@ -10,3 +10,3 @@ /**

import BalloonPanelView from './panel/balloon/balloonpanelview.js';
import { DomEmitterMixin, ResizeObserver, first, global, isVisible } from '@ckeditor/ckeditor5-utils';
import { DomEmitterMixin, first, global, isVisible } from '@ckeditor/ckeditor5-utils';
import { isElement, debounce } from 'lodash-es';

@@ -85,9 +85,2 @@ import '../theme/components/tooltip/tooltip.css';

/**
* An instance of the resize observer that keeps track on target element visibility,
* when it hides the tooltip should also disappear.
*
* {@link module:core/editor/editorconfig~EditorConfig#balloonToolbar configuration}.
*/
this._resizeObserver = null;
/**
* An instance of the mutation observer that keeps track on target element attributes changes.

@@ -324,9 +317,2 @@ */

});
this._resizeObserver = new ResizeObserver(targetDomElement, () => {
// The ResizeObserver will call its callback when the target element hides and the tooltip
// should also disappear (https://github.com/ckeditor/ckeditor5/issues/12492).
if (!isVisible(targetDomElement)) {
this._unpinTooltip();
}
});
this._mutationObserver.attach(targetDomElement);

@@ -355,5 +341,2 @@ // Start responding to changes in editor UI or content layout. For instance, when collaborators change content

this.tooltipTextView.text = '';
if (this._resizeObserver) {
this._resizeObserver.destroy();
}
this._mutationObserver.detach();

@@ -360,0 +343,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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 not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc