@ckeditor/ckeditor5-ui 44.3.0 → 45.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE.md +1 -1
  2. package/ckeditor5-metadata.json +1 -1
  3. package/dist/index-editor.css +28 -0
  4. package/dist/index.css +33 -0
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.js +196 -74
  7. package/dist/index.js.map +1 -1
  8. package/dist/translations/be.d.ts +8 -0
  9. package/dist/translations/be.js +5 -0
  10. package/dist/translations/be.umd.js +11 -0
  11. package/lang/translations/be.po +208 -0
  12. package/package.json +12 -6
  13. package/src/arialiveannouncer.js +24 -0
  14. package/src/autocomplete/autocompleteview.js +29 -25
  15. package/src/badge/badge.js +23 -15
  16. package/src/bindings/draggableviewmixin.js +12 -12
  17. package/src/button/buttonview.js +35 -5
  18. package/src/button/filedialogbuttonview.js +11 -1
  19. package/src/button/listitembuttonview.js +14 -10
  20. package/src/button/switchbuttonview.js +4 -0
  21. package/src/collapsible/collapsibleview.d.ts +1 -4
  22. package/src/collapsible/collapsibleview.js +13 -2
  23. package/src/colorgrid/colorgridview.js +18 -2
  24. package/src/colorgrid/colortileview.d.ts +1 -4
  25. package/src/colorgrid/colortileview.js +3 -3
  26. package/src/colorpicker/colorpickerview.js +28 -1
  27. package/src/colorselector/colorgridsfragmentview.js +80 -4
  28. package/src/colorselector/colorpickerfragmentview.js +44 -3
  29. package/src/colorselector/colorselectorview.js +36 -0
  30. package/src/componentfactory.js +8 -4
  31. package/src/dialog/dialog.js +18 -0
  32. package/src/dialog/dialogactionsview.js +20 -0
  33. package/src/dialog/dialogcontentview.js +4 -0
  34. package/src/dialog/dialogview.d.ts +1 -1
  35. package/src/dialog/dialogview.js +56 -11
  36. package/src/dropdown/button/dropdownbuttonview.d.ts +0 -3
  37. package/src/dropdown/button/dropdownbuttonview.js +6 -2
  38. package/src/dropdown/button/splitbuttonview.d.ts +1 -4
  39. package/src/dropdown/button/splitbuttonview.js +27 -3
  40. package/src/dropdown/dropdownpanelview.js +8 -0
  41. package/src/dropdown/dropdownview.js +235 -184
  42. package/src/dropdown/menu/dropdownmenubuttonview.d.ts +0 -3
  43. package/src/dropdown/menu/dropdownmenubuttonview.js +6 -2
  44. package/src/dropdown/menu/dropdownmenulistitembuttonview.js +1 -0
  45. package/src/dropdown/menu/dropdownmenulistitemview.js +4 -0
  46. package/src/dropdown/menu/dropdownmenunestedmenuview.js +31 -8
  47. package/src/dropdown/menu/dropdownmenurootlistview.js +16 -8
  48. package/src/editableui/editableuiview.js +22 -4
  49. package/src/editableui/inline/inlineeditableuiview.js +4 -0
  50. package/src/editorui/accessibilityhelp/accessibilityhelp.js +8 -11
  51. package/src/editorui/bodycollection.js +13 -0
  52. package/src/editorui/boxed/boxededitoruiview.js +14 -0
  53. package/src/editorui/editorui.d.ts +1 -1
  54. package/src/editorui/editorui.js +56 -25
  55. package/src/editorui/editoruiview.d.ts +15 -1
  56. package/src/editorui/editoruiview.js +22 -0
  57. package/src/editorui/evaluationbadge.js +5 -5
  58. package/src/editorui/poweredby.d.ts +1 -4
  59. package/src/editorui/poweredby.js +5 -2
  60. package/src/focuscycler.js +31 -0
  61. package/src/formheader/formheaderview.js +8 -0
  62. package/src/formrow/formrowview.d.ts +57 -0
  63. package/src/formrow/formrowview.js +56 -0
  64. package/src/highlightedtext/highlightedtextview.js +1 -1
  65. package/src/highlightedtext/labelwithhighlightview.js +4 -0
  66. package/src/icon/iconview.js +25 -16
  67. package/src/index.d.ts +1 -0
  68. package/src/index.js +1 -0
  69. package/src/input/inputbase.js +5 -0
  70. package/src/label/labelview.js +5 -0
  71. package/src/labeledfield/labeledfieldview.js +20 -0
  72. package/src/labeledinput/labeledinputview.js +13 -0
  73. package/src/list/listitemgroupview.js +15 -0
  74. package/src/list/listitemview.js +4 -0
  75. package/src/list/listview.js +27 -5
  76. package/src/menubar/menubarmenubuttonview.d.ts +0 -3
  77. package/src/menubar/menubarmenubuttonview.js +6 -2
  78. package/src/menubar/menubarmenupanelview.js +4 -0
  79. package/src/menubar/menubarmenuview.js +23 -6
  80. package/src/menubar/menubarview.d.ts +8 -0
  81. package/src/menubar/menubarview.js +27 -7
  82. package/src/menubar/utils.d.ts +6 -0
  83. package/src/menubar/utils.js +16 -3
  84. package/src/model.js +1 -1
  85. package/src/panel/balloon/balloonpanelview.js +464 -449
  86. package/src/panel/balloon/contextualballoon.js +60 -24
  87. package/src/panel/sticky/stickypanelview.js +14 -0
  88. package/src/search/searchresultsview.js +18 -0
  89. package/src/search/text/searchtextqueryview.d.ts +0 -3
  90. package/src/search/text/searchtextqueryview.js +15 -3
  91. package/src/search/text/searchtextview.js +43 -3
  92. package/src/template.js +69 -1
  93. package/src/textarea/textareaview.js +12 -5
  94. package/src/toolbar/balloon/balloontoolbar.d.ts +1 -1
  95. package/src/toolbar/balloon/balloontoolbar.js +38 -11
  96. package/src/toolbar/block/blocktoolbar.js +24 -8
  97. package/src/toolbar/toolbarview.d.ts +15 -2
  98. package/src/toolbar/toolbarview.js +206 -58
  99. package/src/tooltipmanager.js +50 -32
  100. package/src/view.js +76 -0
  101. package/src/viewcollection.js +4 -0
  102. package/theme/components/form/form.css +87 -0
  103. package/theme/components/formrow/formrow.css +32 -0
  104. package/theme/icons/accessibility.svg +0 -1
  105. package/theme/icons/color-tile-check.svg +0 -1
  106. package/theme/icons/dropdown-arrow.svg +0 -1
  107. package/theme/icons/project-logo.svg +0 -1
@@ -13,24 +13,77 @@ import preventDefault from '../bindings/preventdefault.js';
13
13
  import { createDropdown, addToolbarToDropdown } from '../dropdown/utils.js';
14
14
  import normalizeToolbarConfig from './normalizetoolbarconfig.js';
15
15
  import { FocusTracker, KeystrokeHandler, Rect, ResizeObserver, global, isVisible, logWarning } from '@ckeditor/ckeditor5-utils';
16
- import { icons } from '@ckeditor/ckeditor5-core';
17
- import { isObject } from 'lodash-es';
16
+ import { IconAlignLeft, IconBold, IconImportExport, IconParagraph, IconPlus, IconText, IconThreeVerticalDots, IconPilcrow, IconDragIndicator } from '@ckeditor/ckeditor5-icons';
17
+ import { isObject } from 'es-toolkit/compat';
18
18
  import '../../theme/components/toolbar/toolbar.css';
19
19
  export const NESTED_TOOLBAR_ICONS = /* #__PURE__ */ (() => ({
20
- alignLeft: icons.alignLeft,
21
- bold: icons.bold,
22
- importExport: icons.importExport,
23
- paragraph: icons.paragraph,
24
- plus: icons.plus,
25
- text: icons.text,
26
- threeVerticalDots: icons.threeVerticalDots,
27
- pilcrow: icons.pilcrow,
28
- dragIndicator: icons.dragIndicator
20
+ alignLeft: IconAlignLeft,
21
+ bold: IconBold,
22
+ importExport: IconImportExport,
23
+ paragraph: IconParagraph,
24
+ plus: IconPlus,
25
+ text: IconText,
26
+ threeVerticalDots: IconThreeVerticalDots,
27
+ pilcrow: IconPilcrow,
28
+ dragIndicator: IconDragIndicator
29
29
  }))();
30
30
  /**
31
31
  * The toolbar view class.
32
32
  */
33
33
  export default class ToolbarView extends View {
34
+ /**
35
+ * A reference to the options object passed to the constructor.
36
+ */
37
+ options;
38
+ /**
39
+ * A collection of toolbar items (buttons, dropdowns, etc.).
40
+ */
41
+ items;
42
+ /**
43
+ * Tracks information about the DOM focus in the toolbar.
44
+ */
45
+ focusTracker;
46
+ /**
47
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}
48
+ * to handle keyboard navigation in the toolbar.
49
+ */
50
+ keystrokes;
51
+ /**
52
+ * A (child) view containing {@link #items toolbar items}.
53
+ */
54
+ itemsView;
55
+ /**
56
+ * A top–level collection aggregating building blocks of the toolbar.
57
+ *
58
+ * ┌───────────────── ToolbarView ─────────────────┐
59
+ * | ┌──────────────── #children ────────────────┐ |
60
+ * | | ┌──────────── #itemsView ───────────┐ | |
61
+ * | | | [ item1 ] [ item2 ] ... [ itemN ] | | |
62
+ * | | └──────────────────────────────────-┘ | |
63
+ * | └───────────────────────────────────────────┘ |
64
+ * └───────────────────────────────────────────────┘
65
+ *
66
+ * By default, it contains the {@link #itemsView} but it can be extended with additional
67
+ * UI elements when necessary.
68
+ */
69
+ children;
70
+ /**
71
+ * A collection of {@link #items} that take part in the focus cycling
72
+ * (i.e. navigation using the keyboard). Usually, it contains a subset of {@link #items} with
73
+ * some optional UI elements that also belong to the toolbar and should be focusable
74
+ * by the user.
75
+ */
76
+ focusables;
77
+ /**
78
+ * Helps cycling over {@link #focusables focusable items} in the toolbar.
79
+ */
80
+ _focusCycler;
81
+ /**
82
+ * An instance of the active toolbar behavior that shapes its look and functionality.
83
+ *
84
+ * See {@link module:ui/toolbar/toolbarview~ToolbarBehavior} to learn more.
85
+ */
86
+ _behavior;
34
87
  /**
35
88
  * Creates an instance of the {@link module:ui/toolbar/toolbarview~ToolbarView} class.
36
89
  *
@@ -47,11 +100,14 @@ export default class ToolbarView extends View {
47
100
  this.set('ariaLabel', t('Editor toolbar'));
48
101
  this.set('maxWidth', 'auto');
49
102
  this.set('role', 'toolbar');
103
+ this.set('isGrouping', !!this.options.shouldGroupWhenFull);
50
104
  this.items = this.createCollection();
51
105
  this.focusTracker = new FocusTracker();
52
106
  this.keystrokes = new KeystrokeHandler();
53
107
  this.set('class', undefined);
54
108
  this.set('isCompact', false);
109
+ // Static toolbar can be vertical when needed.
110
+ this.set('isVertical', false);
55
111
  this.itemsView = new ItemsView(locale);
56
112
  this.children = this.createCollection();
57
113
  this.children.add(this.itemsView);
@@ -72,7 +128,11 @@ export default class ToolbarView extends View {
72
128
  'ck',
73
129
  'ck-toolbar',
74
130
  bind.to('class'),
75
- bind.if('isCompact', 'ck-toolbar_compact')
131
+ bind.if('isCompact', 'ck-toolbar_compact'),
132
+ // To group items dynamically, the toolbar needs a dedicated CSS class. Only used for dynamic grouping.
133
+ bind.if('isGrouping', 'ck-toolbar_grouping'),
134
+ // When vertical, the toolbar has an additional CSS class. Only used for static layout.
135
+ bind.if('isVertical', 'ck-toolbar_vertical')
76
136
  ];
77
137
  if (this.options.shouldGroupWhenFull && this.options.isFloating) {
78
138
  classes.push('ck-toolbar_floating');
@@ -149,6 +209,25 @@ export default class ToolbarView extends View {
149
209
  fillFromConfig(itemsOrConfig, factory, removeItems) {
150
210
  this.items.addMany(this._buildItemsFromConfig(itemsOrConfig, factory, removeItems));
151
211
  }
212
+ /**
213
+ * Changes the behavior of toolbar if it does not fit into the available space.
214
+ */
215
+ switchBehavior(newBehaviorType) {
216
+ if (this._behavior.type !== newBehaviorType) {
217
+ this._behavior.destroy();
218
+ this.itemsView.children.clear();
219
+ this.focusables.clear();
220
+ if (newBehaviorType === 'dynamic') {
221
+ this._behavior = new DynamicGrouping(this);
222
+ this._behavior.render(this);
223
+ this._behavior.refreshItems();
224
+ }
225
+ else {
226
+ this._behavior = new StaticLayout(this);
227
+ this._behavior.render(this);
228
+ }
229
+ }
230
+ }
152
231
  /**
153
232
  * A utility that expands the plain toolbar configuration into a list of view items using a given component factory.
154
233
  *
@@ -336,7 +415,7 @@ export default class ToolbarView extends View {
336
415
  // Allow disabling icon by passing false.
337
416
  if (icon !== false) {
338
417
  // A pre-defined icon picked by name, SVG string, a fallback (default) icon.
339
- dropdownView.buttonView.icon = NESTED_TOOLBAR_ICONS[icon] || icon || icons.threeVerticalDots;
418
+ dropdownView.buttonView.icon = NESTED_TOOLBAR_ICONS[icon] || icon || IconThreeVerticalDots;
340
419
  }
341
420
  // If the icon is disabled, display the label automatically.
342
421
  else {
@@ -351,6 +430,10 @@ export default class ToolbarView extends View {
351
430
  * {@link module:ui/toolbar/toolbarview~ToolbarView#items}.
352
431
  */
353
432
  class ItemsView extends View {
433
+ /**
434
+ * A collection of items (buttons, dropdowns, etc.).
435
+ */
436
+ children;
354
437
  /**
355
438
  * @inheritDoc
356
439
  */
@@ -375,6 +458,10 @@ class ItemsView extends View {
375
458
  * using the {@link module:ui/toolbar/toolbarview~ToolbarView#isVertical} property.
376
459
  */
377
460
  class StaticLayout {
461
+ /**
462
+ * Toolbar behavior type.
463
+ */
464
+ type = 'static';
378
465
  /**
379
466
  * Creates an instance of the {@link module:ui/toolbar/toolbarview~StaticLayout} toolbar
380
467
  * behavior.
@@ -382,21 +469,11 @@ class StaticLayout {
382
469
  * @param view An instance of the toolbar that this behavior is added to.
383
470
  */
384
471
  constructor(view) {
385
- const bind = view.bindTemplate;
386
- // Static toolbar can be vertical when needed.
387
- view.set('isVertical', false);
472
+ view.isGrouping = false;
388
473
  // 1:1 pass–through binding, all ToolbarView#items are visible.
389
474
  view.itemsView.children.bindTo(view.items).using(item => item);
390
475
  // 1:1 pass–through binding, all ToolbarView#items are focusable.
391
476
  view.focusables.bindTo(view.items).using(item => isFocusable(item) ? item : null);
392
- view.extendTemplate({
393
- attributes: {
394
- class: [
395
- // When vertical, the toolbar has an additional CSS class.
396
- bind.if('isVertical', 'ck-toolbar_vertical')
397
- ]
398
- }
399
- });
400
477
  }
401
478
  /**
402
479
  * @inheritDoc
@@ -426,6 +503,91 @@ class StaticLayout {
426
503
  * ```
427
504
  */
428
505
  class DynamicGrouping {
506
+ /**
507
+ * Toolbar behavior type.
508
+ */
509
+ type = 'dynamic';
510
+ /**
511
+ * A toolbar view this behavior belongs to.
512
+ */
513
+ view;
514
+ /**
515
+ * A collection of toolbar children.
516
+ */
517
+ viewChildren;
518
+ /**
519
+ * A collection of focusable toolbar elements.
520
+ */
521
+ viewFocusables;
522
+ /**
523
+ * A view containing toolbar items.
524
+ */
525
+ viewItemsView;
526
+ /**
527
+ * Toolbar focus tracker.
528
+ */
529
+ viewFocusTracker;
530
+ /**
531
+ * Toolbar locale.
532
+ */
533
+ viewLocale;
534
+ /**
535
+ * A subset of toolbar {@link module:ui/toolbar/toolbarview~ToolbarView#items}.
536
+ * Aggregates items that fit into a single row of the toolbar and were not {@link #groupedItems grouped}
537
+ * into a {@link #groupedItemsDropdown dropdown}. Items of this collection are displayed in the
538
+ * {@link module:ui/toolbar/toolbarview~ToolbarView#itemsView}.
539
+ *
540
+ * When none of the {@link module:ui/toolbar/toolbarview~ToolbarView#items} were grouped, it
541
+ * matches the {@link module:ui/toolbar/toolbarview~ToolbarView#items} collection in size and order.
542
+ */
543
+ ungroupedItems;
544
+ /**
545
+ * A subset of toolbar {@link module:ui/toolbar/toolbarview~ToolbarView#items}.
546
+ * A collection of the toolbar items that do not fit into a single row of the toolbar.
547
+ * Grouped items are displayed in a dedicated {@link #groupedItemsDropdown dropdown}.
548
+ *
549
+ * When none of the {@link module:ui/toolbar/toolbarview~ToolbarView#items} were grouped,
550
+ * this collection is empty.
551
+ */
552
+ groupedItems;
553
+ /**
554
+ * The dropdown that aggregates {@link #groupedItems grouped items} that do not fit into a single
555
+ * row of the toolbar. It is displayed on demand as the last of
556
+ * {@link module:ui/toolbar/toolbarview~ToolbarView#children toolbar children} and offers another
557
+ * (nested) toolbar which displays items that would normally overflow.
558
+ */
559
+ groupedItemsDropdown;
560
+ /**
561
+ * An instance of the resize observer that helps dynamically determine the geometry of the toolbar
562
+ * and manage items that do not fit into a single row.
563
+ *
564
+ * **Note:** Created in {@link #_enableGroupingOnResize}.
565
+ *
566
+ * @readonly
567
+ */
568
+ resizeObserver = null;
569
+ /**
570
+ * A cached value of the horizontal padding style used by {@link #_updateGrouping}
571
+ * to manage the {@link module:ui/toolbar/toolbarview~ToolbarView#items} that do not fit into
572
+ * a single toolbar line. This value can be reused between updates because it is unlikely that
573
+ * the padding will change and re–using `Window.getComputedStyle()` is expensive.
574
+ *
575
+ * @readonly
576
+ */
577
+ cachedPadding = null;
578
+ /**
579
+ * A flag indicating that an items grouping update has been queued (e.g. due to the toolbar being visible)
580
+ * and should be executed immediately the next time the toolbar shows up.
581
+ *
582
+ * @readonly
583
+ */
584
+ shouldUpdateGroupingOnNextResize = false;
585
+ /**
586
+ * Toolbar element.
587
+ *
588
+ * @readonly
589
+ */
590
+ viewElement;
429
591
  /**
430
592
  * Creates an instance of the {@link module:ui/toolbar/toolbarview~DynamicGrouping} toolbar
431
593
  * behavior.
@@ -433,37 +595,13 @@ class DynamicGrouping {
433
595
  * @param view An instance of the toolbar that this behavior is added to.
434
596
  */
435
597
  constructor(view) {
436
- /**
437
- * An instance of the resize observer that helps dynamically determine the geometry of the toolbar
438
- * and manage items that do not fit into a single row.
439
- *
440
- * **Note:** Created in {@link #_enableGroupingOnResize}.
441
- *
442
- * @readonly
443
- */
444
- this.resizeObserver = null;
445
- /**
446
- * A cached value of the horizontal padding style used by {@link #_updateGrouping}
447
- * to manage the {@link module:ui/toolbar/toolbarview~ToolbarView#items} that do not fit into
448
- * a single toolbar line. This value can be reused between updates because it is unlikely that
449
- * the padding will change and re–using `Window.getComputedStyle()` is expensive.
450
- *
451
- * @readonly
452
- */
453
- this.cachedPadding = null;
454
- /**
455
- * A flag indicating that an items grouping update has been queued (e.g. due to the toolbar being visible)
456
- * and should be executed immediately the next time the toolbar shows up.
457
- *
458
- * @readonly
459
- */
460
- this.shouldUpdateGroupingOnNextResize = false;
461
598
  this.view = view;
462
599
  this.viewChildren = view.children;
463
600
  this.viewFocusables = view.focusables;
464
601
  this.viewItemsView = view.itemsView;
465
602
  this.viewFocusTracker = view.focusTracker;
466
603
  this.viewLocale = view.locale;
604
+ this.view.isGrouping = true;
467
605
  this.ungroupedItems = view.createCollection();
468
606
  this.groupedItems = view.createCollection();
469
607
  this.groupedItemsDropdown = this._createGroupedItemsDropdown();
@@ -505,14 +643,6 @@ class DynamicGrouping {
505
643
  // some new space is available and we could do some ungrouping.
506
644
  this._updateGrouping();
507
645
  });
508
- view.extendTemplate({
509
- attributes: {
510
- class: [
511
- // To group items dynamically, the toolbar needs a dedicated CSS class.
512
- 'ck-toolbar_grouping'
513
- ]
514
- }
515
- });
516
646
  }
517
647
  /**
518
648
  * Enables dynamic items grouping based on the dimensions of the toolbar.
@@ -531,8 +661,26 @@ class DynamicGrouping {
531
661
  // The dropdown may not be in ToolbarView#children at the moment of toolbar destruction
532
662
  // so let's make sure it's actually destroyed along with the toolbar.
533
663
  this.groupedItemsDropdown.destroy();
664
+ // Do not try to remove the same elements if they are already removed.
665
+ if (this.viewChildren.length > 1) {
666
+ this.viewChildren.remove(this.groupedItemsDropdown);
667
+ this.viewChildren.remove(this.viewChildren.last);
668
+ }
534
669
  this.resizeObserver.destroy();
535
670
  }
671
+ /**
672
+ * Re-adds all items to the toolbar. Use when the toolbar is re-rendered and the items grouping is lost.
673
+ */
674
+ refreshItems() {
675
+ const view = this.view;
676
+ if (view.items.length) {
677
+ for (let currentIndex = 0; currentIndex < view.items.length; currentIndex++) {
678
+ const item = [...view.items][currentIndex];
679
+ this.ungroupedItems.add(item, currentIndex);
680
+ }
681
+ this._updateGrouping();
682
+ }
683
+ }
536
684
  /**
537
685
  * When called, it will check if any of the {@link #ungroupedItems} do not fit into a single row of the toolbar,
538
686
  * and it will move them to the {@link #groupedItems} when it happens.
@@ -694,7 +842,7 @@ class DynamicGrouping {
694
842
  label: t('Show more items'),
695
843
  tooltip: true,
696
844
  tooltipPosition: locale.uiLanguageDirection === 'rtl' ? 'se' : 'sw',
697
- icon: icons.threeVerticalDots
845
+ icon: IconThreeVerticalDots
698
846
  });
699
847
  return dropdown;
700
848
  }
@@ -8,7 +8,7 @@
8
8
  import View from './view.js';
9
9
  import BalloonPanelView from './panel/balloon/balloonpanelview.js';
10
10
  import { DomEmitterMixin, first, global, isVisible } from '@ckeditor/ckeditor5-utils';
11
- import { isElement, debounce } from 'lodash-es';
11
+ import { isElement, debounce } from 'es-toolkit/compat';
12
12
  import '../theme/components/tooltip/tooltip.css';
13
13
  const BALLOON_CLASS = 'ck-tooltip';
14
14
  /**
@@ -74,24 +74,60 @@ const BALLOON_CLASS = 'ck-tooltip';
74
74
  * {@link module:ui/editorui/editorui~EditorUI} of the first editor.
75
75
  */
76
76
  class TooltipManager extends /* #__PURE__ */ DomEmitterMixin() {
77
+ /**
78
+ * The view rendering text of the tooltip.
79
+ */
80
+ tooltipTextView;
81
+ /**
82
+ * The instance of the balloon panel that renders and positions the tooltip.
83
+ */
84
+ balloonPanelView;
85
+ /**
86
+ * A set of default {@link module:utils/dom/position~PositioningFunction positioning functions} used by the `TooltipManager`
87
+ * to pin tooltips in different positions.
88
+ */
89
+ static defaultBalloonPositions = /* #__PURE__ */ BalloonPanelView.generatePositions({
90
+ heightOffset: 5,
91
+ sideOffset: 13
92
+ });
93
+ /**
94
+ * Stores the reference to the DOM element the tooltip is attached to. `null` when there's no tooltip
95
+ * in the UI.
96
+ */
97
+ _currentElementWithTooltip = null;
98
+ /**
99
+ * Stores the current tooltip position. `null` when there's no tooltip in the UI.
100
+ */
101
+ _currentTooltipPosition = null;
102
+ /**
103
+ * An instance of the mutation observer that keeps track on target element attributes changes.
104
+ */
105
+ _mutationObserver = null;
106
+ /**
107
+ * A debounced version of {@link #_pinTooltip}. Tooltips show with a delay to avoid flashing and
108
+ * to improve the UX.
109
+ */
110
+ _pinTooltipDebounced;
111
+ /**
112
+ * A debounced version of {@link #_unpinTooltip}. Tooltips hide with a delay to allow hovering of their titles.
113
+ */
114
+ _unpinTooltipDebounced;
115
+ _watchdogExcluded;
116
+ /**
117
+ * A set of editors the single tooltip manager instance must listen to.
118
+ * This is mostly to handle `EditorUI#update` listeners from individual editors.
119
+ */
120
+ static _editors = new Set();
121
+ /**
122
+ * A reference to the `TooltipManager` instance. The class is a singleton and as such,
123
+ * successive attempts at creating instances should return this instance.
124
+ */
125
+ static _instance = null;
77
126
  /**
78
127
  * Creates an instance of the tooltip manager.
79
128
  */
80
129
  constructor(editor) {
81
130
  super();
82
- /**
83
- * Stores the reference to the DOM element the tooltip is attached to. `null` when there's no tooltip
84
- * in the UI.
85
- */
86
- this._currentElementWithTooltip = null;
87
- /**
88
- * Stores the current tooltip position. `null` when there's no tooltip in the UI.
89
- */
90
- this._currentTooltipPosition = null;
91
- /**
92
- * An instance of the mutation observer that keeps track on target element attributes changes.
93
- */
94
- this._mutationObserver = null;
95
131
  TooltipManager._editors.add(editor);
96
132
  // TooltipManager must be a singleton. Multiple instances would mean multiple tooltips attached
97
133
  // to the same DOM element with data-cke-tooltip-* attributes.
@@ -383,24 +419,6 @@ class TooltipManager extends /* #__PURE__ */ DomEmitterMixin() {
383
419
  });
384
420
  }
385
421
  }
386
- /**
387
- * A set of default {@link module:utils/dom/position~PositioningFunction positioning functions} used by the `TooltipManager`
388
- * to pin tooltips in different positions.
389
- */
390
- TooltipManager.defaultBalloonPositions = BalloonPanelView.generatePositions({
391
- heightOffset: 5,
392
- sideOffset: 13
393
- });
394
- /**
395
- * A set of editors the single tooltip manager instance must listen to.
396
- * This is mostly to handle `EditorUI#update` listeners from individual editors.
397
- */
398
- TooltipManager._editors = new Set();
399
- /**
400
- * A reference to the `TooltipManager` instance. The class is a singleton and as such,
401
- * successive attempts at creating instances should return this instance.
402
- */
403
- TooltipManager._instance = null;
404
422
  export default TooltipManager;
405
423
  function getDescendantWithTooltip(element) {
406
424
  if (!isElement(element)) {
package/src/view.js CHANGED
@@ -76,6 +76,82 @@ import '../theme/globals/globals.css';
76
76
  * ```
77
77
  */
78
78
  export default class View extends /* #__PURE__ */ DomEmitterMixin(/* #__PURE__ */ ObservableMixin()) {
79
+ /**
80
+ * An HTML element of the view. `null` until {@link #render rendered}
81
+ * from the {@link #template}.
82
+ *
83
+ * ```ts
84
+ * class SampleView extends View {
85
+ * constructor() {
86
+ * super();
87
+ *
88
+ * // A template instance the #element will be created from.
89
+ * this.setTemplate( {
90
+ * tag: 'p'
91
+ *
92
+ * // ...
93
+ * } );
94
+ * }
95
+ * }
96
+ *
97
+ * const view = new SampleView();
98
+ *
99
+ * // Renders the #template.
100
+ * view.render();
101
+ *
102
+ * // Append the HTML element of the view to <body>.
103
+ * document.body.appendChild( view.element );
104
+ * ```
105
+ *
106
+ * **Note**: The element of the view can also be assigned directly:
107
+ *
108
+ * ```ts
109
+ * view.element = document.querySelector( '#my-container' );
110
+ * ```
111
+ */
112
+ element;
113
+ /**
114
+ * Set `true` when the view has already been {@link module:ui/view~View#render rendered}.
115
+ *
116
+ * @readonly
117
+ */
118
+ isRendered;
119
+ /**
120
+ * A set of tools to localize the user interface.
121
+ *
122
+ * Also see {@link module:core/editor/editor~Editor#locale}.
123
+ *
124
+ * @readonly
125
+ */
126
+ locale;
127
+ /**
128
+ * Shorthand for {@link module:utils/locale~Locale#t}.
129
+ *
130
+ * Note: If {@link #locale} instance hasn't been passed to the view this method may not
131
+ * be available.
132
+ *
133
+ * @see module:utils/locale~Locale#t
134
+ */
135
+ t;
136
+ /**
137
+ * Template of this view. It provides the {@link #element} representing
138
+ * the view in DOM, which is {@link #render rendered}.
139
+ */
140
+ template;
141
+ /**
142
+ * Collections registered with {@link #createCollection}.
143
+ */
144
+ _viewCollections;
145
+ /**
146
+ * A collection of view instances, which have been added directly
147
+ * into the {@link module:ui/template~Template#children}.
148
+ */
149
+ _unboundChildren;
150
+ /**
151
+ * Cached {@link module:ui/template~BindChain bind chain} object created by the
152
+ * {@link #template}. See {@link #bindTemplate}.
153
+ */
154
+ _bindTemplate;
79
155
  /**
80
156
  * Creates an instance of the {@link module:ui/view~View} class.
81
157
  *
@@ -47,6 +47,10 @@ import { CKEditorError, Collection } from '@ckeditor/ckeditor5-utils';
47
47
  * of a {@link module:ui/template~Template template}.
48
48
  */
49
49
  export default class ViewCollection extends Collection {
50
+ /**
51
+ * A parent element within which child views are rendered and managed in DOM.
52
+ */
53
+ _parentElement;
50
54
  /**
51
55
  * Creates a new instance of the {@link module:ui/viewcollection~ViewCollection}.
52
56
  *
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
+ */
5
+
6
+ @import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";
7
+ @import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";
8
+
9
+ :root {
10
+ --ck-form-default-width: 340px;
11
+ }
12
+
13
+ .ck.ck-form {
14
+ padding: 0 0 var(--ck-spacing-large);
15
+
16
+ &.ck-form_default-width {
17
+ width: var(--ck-form-default-width);
18
+ }
19
+
20
+ &:focus {
21
+ outline: none;
22
+ }
23
+
24
+ & .ck.ck-input-text,
25
+ & .ck.ck-input-number {
26
+ min-width: 100%;
27
+ width: 0;
28
+ }
29
+
30
+ & .ck.ck-dropdown {
31
+ min-width: 100%;
32
+
33
+ & .ck-dropdown__button {
34
+ &:not(:focus) {
35
+ border: 1px solid var(--ck-color-base-border);
36
+ }
37
+
38
+ & .ck-button__label {
39
+ width: 100%;
40
+ }
41
+ }
42
+ }
43
+
44
+ /* Default `ck-responsive-form` customization when it lies next to `ck-form` class */
45
+ &.ck-responsive-form {
46
+ & .ck.ck-form__row {
47
+ &.ck-form__row_with-submit {
48
+ @mixin ck-media-phone {
49
+ flex-direction: column;
50
+ align-items: stretch;
51
+ padding: 0;
52
+ }
53
+
54
+ > .ck {
55
+ @mixin ck-media-phone {
56
+ margin: var(--ck-spacing-large) var(--ck-spacing-large) 0;
57
+ }
58
+ }
59
+
60
+ .ck-button_with-text {
61
+ @mixin ck-media-phone {
62
+ justify-content: center;
63
+ }
64
+ }
65
+ }
66
+
67
+ &.ck-form__row_large-bottom-padding {
68
+ @mixin ck-media-phone {
69
+ padding-bottom: var(--ck-spacing-large);
70
+ }
71
+ }
72
+ }
73
+
74
+ @mixin ck-dir ltr {
75
+ & > :not(:first-child) {
76
+ margin-left: 0;
77
+ }
78
+ }
79
+
80
+ @mixin ck-dir rtl {
81
+ & > :not(:last-child) {
82
+ margin-left: 0;
83
+ }
84
+ }
85
+ }
86
+ /* End of `ck-responsive-form` customization */
87
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
+ */
5
+
6
+ .ck.ck-form__row {
7
+ display: flex;
8
+ flex-direction: row;
9
+ justify-content: space-between;
10
+ align-items: flex-start;
11
+ padding: var(--ck-spacing-standard) var(--ck-spacing-large) 0;
12
+
13
+ &.ck-form__row_large-top-padding {
14
+ padding-top: var(--ck-spacing-large);
15
+ }
16
+
17
+ &.ck-form__row_large-bottom-padding {
18
+ padding-bottom: var(--ck-spacing-large);
19
+ }
20
+
21
+ &.ck-form__row_with-submit {
22
+ flex-wrap: nowrap;
23
+
24
+ & > *:not(:first-child) {
25
+ margin-inline-start: var(--ck-spacing-standard);
26
+ }
27
+ }
28
+
29
+ & > .ck.ck-form__row {
30
+ padding: 0;
31
+ }
32
+ }