@ckeditor/ckeditor5-table 0.0.0-nightly-next-20260108.0 → 0.0.0-nightly-20260109.0

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 (274) hide show
  1. package/build/table.js +5 -0
  2. package/build/translations/af.js +1 -0
  3. package/build/translations/ar.js +1 -0
  4. package/build/translations/ast.js +1 -0
  5. package/build/translations/az.js +1 -0
  6. package/build/translations/be.js +1 -0
  7. package/build/translations/bg.js +1 -0
  8. package/build/translations/bn.js +1 -0
  9. package/build/translations/bs.js +1 -0
  10. package/build/translations/ca.js +1 -0
  11. package/build/translations/cs.js +1 -0
  12. package/build/translations/da.js +1 -0
  13. package/build/translations/de-ch.js +1 -0
  14. package/build/translations/de.js +1 -0
  15. package/build/translations/el.js +1 -0
  16. package/build/translations/en-au.js +1 -0
  17. package/build/translations/en-gb.js +1 -0
  18. package/build/translations/eo.js +1 -0
  19. package/build/translations/es-co.js +1 -0
  20. package/build/translations/es.js +1 -0
  21. package/build/translations/et.js +1 -0
  22. package/build/translations/eu.js +1 -0
  23. package/build/translations/fa.js +1 -0
  24. package/build/translations/fi.js +1 -0
  25. package/build/translations/fr.js +1 -0
  26. package/build/translations/gl.js +1 -0
  27. package/build/translations/gu.js +1 -0
  28. package/build/translations/he.js +1 -0
  29. package/build/translations/hi.js +1 -0
  30. package/build/translations/hr.js +1 -0
  31. package/build/translations/hu.js +1 -0
  32. package/build/translations/hy.js +1 -0
  33. package/build/translations/id.js +1 -0
  34. package/build/translations/it.js +1 -0
  35. package/build/translations/ja.js +1 -0
  36. package/build/translations/jv.js +1 -0
  37. package/build/translations/kk.js +1 -0
  38. package/build/translations/km.js +1 -0
  39. package/build/translations/kn.js +1 -0
  40. package/build/translations/ko.js +1 -0
  41. package/build/translations/ku.js +1 -0
  42. package/build/translations/lt.js +1 -0
  43. package/build/translations/lv.js +1 -0
  44. package/build/translations/ms.js +1 -0
  45. package/build/translations/nb.js +1 -0
  46. package/build/translations/ne.js +1 -0
  47. package/build/translations/nl.js +1 -0
  48. package/build/translations/no.js +1 -0
  49. package/build/translations/oc.js +1 -0
  50. package/build/translations/pl.js +1 -0
  51. package/build/translations/pt-br.js +1 -0
  52. package/build/translations/pt.js +1 -0
  53. package/build/translations/ro.js +1 -0
  54. package/build/translations/ru.js +1 -0
  55. package/build/translations/si.js +1 -0
  56. package/build/translations/sk.js +1 -0
  57. package/build/translations/sl.js +1 -0
  58. package/build/translations/sq.js +1 -0
  59. package/build/translations/sr-latn.js +1 -0
  60. package/build/translations/sr.js +1 -0
  61. package/build/translations/sv.js +1 -0
  62. package/build/translations/th.js +1 -0
  63. package/build/translations/ti.js +1 -0
  64. package/build/translations/tk.js +1 -0
  65. package/build/translations/tr.js +1 -0
  66. package/build/translations/tt.js +1 -0
  67. package/build/translations/ug.js +1 -0
  68. package/build/translations/uk.js +1 -0
  69. package/build/translations/ur.js +1 -0
  70. package/build/translations/uz.js +1 -0
  71. package/build/translations/vi.js +1 -0
  72. package/build/translations/zh-cn.js +1 -0
  73. package/build/translations/zh.js +1 -0
  74. package/ckeditor5-metadata.json +7 -16
  75. package/dist/index-content.css +30 -30
  76. package/dist/index-editor.css +170 -104
  77. package/dist/index.css +237 -147
  78. package/dist/index.css.map +1 -1
  79. package/dist/index.js +2433 -448
  80. package/dist/index.js.map +1 -1
  81. package/lang/contexts.json +4 -2
  82. package/package.json +35 -25
  83. package/{dist → src}/augmentation.d.ts +15 -4
  84. package/src/augmentation.js +5 -0
  85. package/{dist → src}/commands/insertcolumncommand.d.ts +1 -5
  86. package/src/commands/insertcolumncommand.js +71 -0
  87. package/{dist → src}/commands/insertrowcommand.d.ts +1 -5
  88. package/src/commands/insertrowcommand.js +70 -0
  89. package/{dist → src}/commands/inserttablecommand.d.ts +1 -5
  90. package/src/commands/inserttablecommand.js +69 -0
  91. package/{dist → src}/commands/inserttablelayoutcommand.d.ts +1 -5
  92. package/src/commands/inserttablelayoutcommand.js +65 -0
  93. package/{dist → src}/commands/mergecellcommand.d.ts +3 -7
  94. package/src/commands/mergecellcommand.js +206 -0
  95. package/{dist → src}/commands/mergecellscommand.d.ts +1 -5
  96. package/src/commands/mergecellscommand.js +94 -0
  97. package/{dist → src}/commands/removecolumncommand.d.ts +1 -5
  98. package/src/commands/removecolumncommand.js +109 -0
  99. package/{dist → src}/commands/removerowcommand.d.ts +1 -5
  100. package/src/commands/removerowcommand.js +82 -0
  101. package/{dist → src}/commands/selectcolumncommand.d.ts +1 -5
  102. package/src/commands/selectcolumncommand.js +60 -0
  103. package/{dist → src}/commands/selectrowcommand.d.ts +1 -5
  104. package/src/commands/selectrowcommand.js +56 -0
  105. package/{dist → src}/commands/setheadercolumncommand.d.ts +1 -5
  106. package/src/commands/setheadercolumncommand.js +76 -0
  107. package/{dist → src}/commands/setheaderrowcommand.d.ts +1 -5
  108. package/src/commands/setheaderrowcommand.js +83 -0
  109. package/{dist → src}/commands/splitcellcommand.d.ts +1 -5
  110. package/src/commands/splitcellcommand.js +58 -0
  111. package/{dist → src}/converters/downcast.d.ts +2 -6
  112. package/src/converters/downcast.js +298 -0
  113. package/{dist → src}/converters/table-caption-post-fixer.d.ts +1 -5
  114. package/src/converters/table-caption-post-fixer.js +55 -0
  115. package/{dist → src}/converters/table-cell-paragraph-post-fixer.d.ts +1 -5
  116. package/src/converters/table-cell-paragraph-post-fixer.js +109 -0
  117. package/{dist → src}/converters/table-cell-refresh-handler.d.ts +1 -5
  118. package/src/converters/table-cell-refresh-handler.js +47 -0
  119. package/{dist → src}/converters/table-headings-refresh-handler.d.ts +1 -5
  120. package/src/converters/table-headings-refresh-handler.js +51 -0
  121. package/{dist → src}/converters/table-layout-post-fixer.d.ts +1 -5
  122. package/src/converters/table-layout-post-fixer.js +369 -0
  123. package/{dist → src}/converters/tableproperties.d.ts +2 -6
  124. package/src/converters/tableproperties.js +444 -0
  125. package/{dist → src}/converters/upcasttable.d.ts +1 -5
  126. package/src/converters/upcasttable.js +385 -0
  127. package/{dist → src}/index.d.ts +5 -6
  128. package/src/index.js +98 -0
  129. package/{dist → src}/plaintableoutput.d.ts +1 -5
  130. package/src/plaintableoutput.js +49 -0
  131. package/{dist → src}/table.d.ts +2 -6
  132. package/src/table.js +50 -0
  133. package/{dist → src}/tablecaption/tablecaptionediting.d.ts +2 -6
  134. package/src/tablecaption/tablecaptionediting.js +136 -0
  135. package/{dist → src}/tablecaption/tablecaptionui.d.ts +1 -5
  136. package/src/tablecaption/tablecaptionui.js +64 -0
  137. package/{dist → src}/tablecaption/toggletablecaptioncommand.d.ts +1 -5
  138. package/src/tablecaption/toggletablecaptioncommand.js +105 -0
  139. package/{dist → src}/tablecaption/utils.d.ts +1 -5
  140. package/src/tablecaption/utils.js +61 -0
  141. package/{dist → src}/tablecaption.d.ts +1 -5
  142. package/src/tablecaption.js +34 -0
  143. package/{dist → src}/tablecellproperties/commands/tablecellbackgroundcolorcommand.d.ts +1 -5
  144. package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +30 -0
  145. package/{dist → src}/tablecellproperties/commands/tablecellbordercolorcommand.d.ts +2 -6
  146. package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +44 -0
  147. package/{dist → src}/tablecellproperties/commands/tablecellborderstylecommand.d.ts +2 -6
  148. package/src/tablecellproperties/commands/tablecellborderstylecommand.js +44 -0
  149. package/{dist → src}/tablecellproperties/commands/tablecellborderwidthcommand.d.ts +2 -6
  150. package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +64 -0
  151. package/{dist → src}/tablecellproperties/commands/tablecellheightcommand.d.ts +1 -5
  152. package/src/tablecellproperties/commands/tablecellheightcommand.js +51 -0
  153. package/{dist → src}/tablecellproperties/commands/tablecellhorizontalalignmentcommand.d.ts +1 -5
  154. package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +30 -0
  155. package/{dist → src}/tablecellproperties/commands/tablecellpaddingcommand.d.ts +2 -6
  156. package/src/tablecellproperties/commands/tablecellpaddingcommand.js +64 -0
  157. package/{dist → src}/tablecellproperties/commands/tablecellpropertycommand.d.ts +2 -6
  158. package/src/tablecellproperties/commands/tablecellpropertycommand.js +138 -0
  159. package/{dist → src}/tablecellproperties/commands/tablecelltypecommand.d.ts +6 -6
  160. package/src/tablecellproperties/commands/tablecelltypecommand.js +167 -0
  161. package/{dist → src}/tablecellproperties/commands/tablecellverticalalignmentcommand.d.ts +1 -5
  162. package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +38 -0
  163. package/{dist → src}/tablecellproperties/tablecellpropertiesediting.d.ts +1 -5
  164. package/src/tablecellproperties/tablecellpropertiesediting.js +412 -0
  165. package/{dist → src}/tablecellproperties/tablecellpropertiesui.d.ts +2 -6
  166. package/src/tablecellproperties/tablecellpropertiesui.js +385 -0
  167. package/src/tablecellproperties/tablecellpropertiesuiexperimental.d.ts +128 -0
  168. package/src/tablecellproperties/tablecellpropertiesuiexperimental.js +408 -0
  169. package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +229 -0
  170. package/src/tablecellproperties/ui/tablecellpropertiesview.js +612 -0
  171. package/{dist/tablecellproperties/ui/tablecellpropertiesview.d.ts → src/tablecellproperties/ui/tablecellpropertiesviewexperimental.d.ts} +12 -15
  172. package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.js +744 -0
  173. package/{dist → src}/tablecellproperties.d.ts +1 -5
  174. package/src/tablecellproperties.js +40 -0
  175. package/{dist → src}/tablecellwidth/commands/tablecellwidthcommand.d.ts +1 -5
  176. package/src/tablecellwidth/commands/tablecellwidthcommand.js +51 -0
  177. package/{dist → src}/tablecellwidth/tablecellwidthediting.d.ts +1 -5
  178. package/src/tablecellwidth/tablecellwidthediting.js +53 -0
  179. package/{dist → src}/tableclipboard.d.ts +3 -7
  180. package/src/tableclipboard.js +500 -0
  181. package/{dist → src}/tablecolumnresize/constants.d.ts +0 -4
  182. package/src/tablecolumnresize/constants.js +33 -0
  183. package/{dist → src}/tablecolumnresize/converters.d.ts +1 -5
  184. package/src/tablecolumnresize/converters.js +62 -0
  185. package/{dist → src}/tablecolumnresize/tablecolumnresizeediting.d.ts +2 -6
  186. package/src/tablecolumnresize/tablecolumnresizeediting.js +729 -0
  187. package/{dist → src}/tablecolumnresize/tablewidthscommand.d.ts +2 -6
  188. package/src/tablecolumnresize/tablewidthscommand.js +61 -0
  189. package/{dist → src}/tablecolumnresize/utils.d.ts +2 -6
  190. package/src/tablecolumnresize/utils.js +370 -0
  191. package/{dist → src}/tablecolumnresize.d.ts +1 -5
  192. package/src/tablecolumnresize.js +36 -0
  193. package/{dist → src}/tableconfig.d.ts +6 -30
  194. package/src/tableconfig.js +5 -0
  195. package/{dist → src}/tableediting.d.ts +2 -6
  196. package/src/tableediting.js +246 -0
  197. package/{dist → src}/tablekeyboard.d.ts +3 -7
  198. package/src/tablekeyboard.js +273 -0
  199. package/{dist → src}/tablelayout/commands/tabletypecommand.d.ts +1 -5
  200. package/src/tablelayout/commands/tabletypecommand.js +68 -0
  201. package/{dist → src}/tablelayout/tablelayoutediting.d.ts +1 -5
  202. package/src/tablelayout/tablelayoutediting.js +295 -0
  203. package/{dist → src}/tablelayout/tablelayoutui.d.ts +1 -5
  204. package/src/tablelayout/tablelayoutui.js +196 -0
  205. package/{dist → src}/tablelayout.d.ts +1 -5
  206. package/src/tablelayout.js +37 -0
  207. package/{dist → src}/tablemouse/mouseeventsobserver.d.ts +1 -5
  208. package/src/tablemouse/mouseeventsobserver.js +34 -0
  209. package/{dist → src}/tablemouse.d.ts +1 -5
  210. package/src/tablemouse.js +178 -0
  211. package/{dist → src}/tableproperties/commands/tablealignmentcommand.d.ts +1 -5
  212. package/src/tableproperties/commands/tablealignmentcommand.js +30 -0
  213. package/{dist → src}/tableproperties/commands/tablebackgroundcolorcommand.d.ts +1 -5
  214. package/src/tableproperties/commands/tablebackgroundcolorcommand.js +30 -0
  215. package/{dist → src}/tableproperties/commands/tablebordercolorcommand.d.ts +2 -6
  216. package/src/tableproperties/commands/tablebordercolorcommand.js +44 -0
  217. package/{dist → src}/tableproperties/commands/tableborderstylecommand.d.ts +2 -6
  218. package/src/tableproperties/commands/tableborderstylecommand.js +44 -0
  219. package/{dist → src}/tableproperties/commands/tableborderwidthcommand.d.ts +2 -6
  220. package/src/tableproperties/commands/tableborderwidthcommand.js +64 -0
  221. package/{dist → src}/tableproperties/commands/tableheightcommand.d.ts +1 -5
  222. package/src/tableproperties/commands/tableheightcommand.js +54 -0
  223. package/{dist → src}/tableproperties/commands/tablepropertycommand.d.ts +2 -6
  224. package/src/tableproperties/commands/tablepropertycommand.js +103 -0
  225. package/{dist → src}/tableproperties/commands/tablewidthcommand.d.ts +1 -5
  226. package/src/tableproperties/commands/tablewidthcommand.js +54 -0
  227. package/{dist → src}/tableproperties/tablepropertiesediting.d.ts +1 -5
  228. package/src/tableproperties/tablepropertiesediting.js +546 -0
  229. package/{dist → src}/tableproperties/tablepropertiesui.d.ts +2 -6
  230. package/src/tableproperties/tablepropertiesui.js +374 -0
  231. package/src/tableproperties/tablepropertiesuiexperimental.d.ts +136 -0
  232. package/src/tableproperties/tablepropertiesuiexperimental.js +375 -0
  233. package/{dist → src}/tableproperties/ui/tablepropertiesview.d.ts +2 -14
  234. package/src/tableproperties/ui/tablepropertiesview.js +520 -0
  235. package/src/tableproperties/ui/tablepropertiesviewexperimental.d.ts +216 -0
  236. package/src/tableproperties/ui/tablepropertiesviewexperimental.js +544 -0
  237. package/{dist → src}/tableproperties.d.ts +1 -5
  238. package/src/tableproperties.js +40 -0
  239. package/{dist → src}/tableselection.d.ts +2 -6
  240. package/src/tableselection.js +323 -0
  241. package/{dist → src}/tabletoolbar.d.ts +2 -6
  242. package/src/tabletoolbar.js +63 -0
  243. package/{dist → src}/tableui.d.ts +1 -5
  244. package/src/tableui.js +335 -0
  245. package/{dist → src}/tableutils.d.ts +2 -6
  246. package/src/tableutils.js +1282 -0
  247. package/{dist → src}/tablewalker.d.ts +1 -5
  248. package/src/tablewalker.js +489 -0
  249. package/{dist → src}/ui/colorinputview.d.ts +2 -6
  250. package/src/ui/colorinputview.js +305 -0
  251. package/{dist → src}/ui/inserttableview.d.ts +2 -6
  252. package/src/ui/inserttableview.js +192 -0
  253. package/{dist → src}/utils/common.d.ts +2 -6
  254. package/src/utils/common.js +118 -0
  255. package/{dist → src}/utils/structure.d.ts +1 -5
  256. package/src/utils/structure.js +452 -0
  257. package/{dist → src}/utils/table-properties.d.ts +1 -5
  258. package/src/utils/table-properties.js +121 -0
  259. package/{dist → src}/utils/ui/contextualballoon.d.ts +2 -6
  260. package/src/utils/ui/contextualballoon.js +111 -0
  261. package/{dist → src}/utils/ui/table-properties.d.ts +2 -6
  262. package/src/utils/ui/table-properties.js +390 -0
  263. package/src/utils/ui/table-propertiesexperimental.d.ts +215 -0
  264. package/src/utils/ui/table-propertiesexperimental.js +391 -0
  265. package/{dist → src}/utils/ui/widget.d.ts +1 -5
  266. package/src/utils/ui/widget.js +56 -0
  267. package/theme/formrow-experimental.css +15 -0
  268. package/theme/formrow.css +0 -2
  269. package/theme/tablecellproperties-experimental.css +4 -0
  270. package/theme/tableform-experimental.css +61 -0
  271. package/theme/tableform.css +5 -1
  272. package/theme/tableproperties-experimental.css +78 -0
  273. package/theme/tableproperties.css +0 -60
  274. package/dist/tablecellproperties/tablecellpropertiesutils.d.ts +0 -22
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command, Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
6
6
  import { toWidgetEditable, toWidget, Widget, isWidget, WidgetToolbarRepository } from '@ckeditor/ckeditor5-widget/dist/index.js';
7
7
  import { first, global, CKEditorError, KeystrokeHandler, FocusTracker, Collection, getLocalizedArrowKeyCodeDirection, Rect, priorities, DomEmitterMixin, toUnit } from '@ckeditor/ckeditor5-utils/dist/index.js';
8
8
  import { isObject, debounce, isEqual, throttle } from 'es-toolkit/compat';
9
- import { IconTable, IconTableColumn, IconTableRow, IconTableMergeCell, IconPreviousArrow, IconAlignBottom, IconAlignMiddle, IconAlignTop, IconAlignJustify, IconAlignRight, IconAlignCenter, IconAlignLeft, IconTableCellProperties, IconTableLayout, IconTableProperties, IconObjectRight, IconObjectLeft, IconObjectInlineRight, IconObjectCenter, IconObjectInlineLeft, IconCaption } from '@ckeditor/ckeditor5-icons/dist/index.js';
9
+ import { IconTable, IconTableColumn, IconTableRow, IconTableMergeCell, IconCheck, IconCancel, IconAlignBottom, IconAlignMiddle, IconAlignTop, IconAlignJustify, IconAlignRight, IconAlignCenter, IconAlignLeft, IconTableCellProperties, IconTableLayout, IconTableProperties, IconObjectInlineRight, IconObjectCenter, IconObjectInlineLeft, IconCaption, IconPreviousArrow, IconObjectRight, IconObjectLeft } from '@ckeditor/ckeditor5-icons/dist/index.js';
10
10
  import { View, addKeyboardHandlingForGrid, ButtonView, createDropdown, MenuBarMenuView, SwitchButtonView, SplitButtonView, addListToDropdown, UIModel, ViewCollection, FocusCycler, InputTextView, ColorSelectorView, FormHeaderView, FormRowView, submitHandler, LabelView, LabeledFieldView, createLabeledDropdown, createLabeledInputText, ToolbarView, BalloonPanelView, ContextualBalloon, normalizeColorOptions, getLocalizedColorOptions, clickOutsideHandler, DropdownButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
11
11
  import { ClipboardMarkersUtils, ClipboardPipeline } from '@ckeditor/ckeditor5-clipboard/dist/index.js';
12
12
  import { DomEventObserver, isColorStyleValue, isLengthStyleValue, isPercentageStyleValue, addBorderStylesRules, addPaddingStylesRules, addBackgroundStylesRules, addMarginStylesRules, enableViewPlaceholder, ModelElement } from '@ckeditor/ckeditor5-engine/dist/index.js';
@@ -941,22 +941,6 @@ const downcastTableAlignmentConfig = {
941
941
  // @if CK_DEBUG // } );
942
942
  // @if CK_DEBUG // }
943
943
 
944
- /**
945
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
946
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
947
- */ /**
948
- * @module table/tablecellproperties/tablecellpropertiesutils
949
- */ /**
950
- * Type of the table cell.
951
- */ /**
952
- * Checks if the given cell type represents a header cell.
953
- *
954
- * @param cellType The type of the table cell.
955
- * @returns `true` if the cell type represents a header cell, `false` otherwise.
956
- */ function isTableHeaderCellType(cellType) {
957
- return cellType === 'header' || cellType === 'header-row' || cellType === 'header-column';
958
- }
959
-
960
944
  /**
961
945
  * A common method to update the numeric value. If a value is the default one, it will be unset.
962
946
  *
@@ -1058,7 +1042,7 @@ const downcastTableAlignmentConfig = {
1058
1042
  });
1059
1043
  for (const { cell } of tableWalker){
1060
1044
  const cellType = cell.getAttribute('tableCellType');
1061
- if (!isTableHeaderCellType(cellType)) {
1045
+ if (cellType !== 'header') {
1062
1046
  return false;
1063
1047
  }
1064
1048
  }
@@ -1069,8 +1053,8 @@ const downcastTableAlignmentConfig = {
1069
1053
  *
1070
1054
  * @internal
1071
1055
  */ function isTableCellTypeEnabled(editor) {
1072
- const { model } = editor;
1073
- return model.schema.checkAttribute('tableCell', 'tableCellType');
1056
+ const { model, config } = editor;
1057
+ return model.schema.checkAttribute('tableCell', 'tableCellType') && config.get('experimentalFlags.tableCellTypeSupport') === true;
1074
1058
  }
1075
1059
 
1076
1060
  /**
@@ -2085,8 +2069,7 @@ const downcastTableAlignmentConfig = {
2085
2069
  return (tableCell, { writer })=>{
2086
2070
  // If the table cell type feature is enabled, then we can simply check the cell type attribute.
2087
2071
  if (options.cellTypeEnabled?.()) {
2088
- const tableCellType = tableCell.getAttribute('tableCellType');
2089
- const cellElementName = isTableHeaderCellType(tableCellType) ? 'th' : 'td';
2072
+ const cellElementName = tableCell.getAttribute('tableCellType') === 'header' ? 'th' : 'td';
2090
2073
  return createCellElement(writer, cellElementName);
2091
2074
  }
2092
2075
  // If the table cell type feature is not enabled, we should iterate through the table structure
@@ -2192,7 +2175,10 @@ const downcastTableAlignmentConfig = {
2192
2175
  * Downcasts a plain table (also used in the clipboard pipeline).
2193
2176
  */ function convertPlainTable(editor) {
2194
2177
  return (table, conversionApi)=>{
2195
- if (!conversionApi.options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2178
+ const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
2179
+ const isClipboardPipeline = conversionApi.options.isClipboardPipeline;
2180
+ const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
2181
+ if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
2196
2182
  return null;
2197
2183
  }
2198
2184
  return downcastPlainTable(table, conversionApi, editor);
@@ -2202,7 +2188,10 @@ const downcastTableAlignmentConfig = {
2202
2188
  * Downcasts a plain table caption (also used in the clipboard pipeline).
2203
2189
  */ function convertPlainTableCaption(editor) {
2204
2190
  return (modelElement, { writer, options })=>{
2205
- if (!options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2191
+ const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
2192
+ const isClipboardPipeline = options.isClipboardPipeline;
2193
+ const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
2194
+ if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
2206
2195
  return null;
2207
2196
  }
2208
2197
  if (modelElement.parent.name === 'table') {
@@ -2290,7 +2279,10 @@ const downcastTableAlignmentConfig = {
2290
2279
  return dispatcher.on(`attribute:${modelAttribute}:table`, (evt, data, conversionApi)=>{
2291
2280
  const { item, attributeNewValue } = data;
2292
2281
  const { mapper, writer } = conversionApi;
2293
- if (!conversionApi.options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2282
+ const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
2283
+ const isClipboardPipeline = conversionApi.options.isClipboardPipeline;
2284
+ const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
2285
+ if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
2294
2286
  return;
2295
2287
  }
2296
2288
  if (!conversionApi.consumable.consume(item, evt.name)) {
@@ -3518,7 +3510,6 @@ const downcastTableAlignmentConfig = {
3518
3510
  const isCopyStructure = options.copyStructureFromAbove !== undefined;
3519
3511
  const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt;
3520
3512
  const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
3521
- const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
3522
3513
  const rows = this.getRows(table);
3523
3514
  const columns = this.getColumns(table);
3524
3515
  if (insertAt > rows) {
@@ -3532,6 +3523,7 @@ const downcastTableAlignmentConfig = {
3532
3523
  }
3533
3524
  model.change((writer)=>{
3534
3525
  let headingRows = table.getAttribute('headingRows') || 0;
3526
+ const headingColumns = table.getAttribute('headingColumns') || 0;
3535
3527
  // Inserting rows inside heading section requires to update `headingRows` attribute as the heading section will grow.
3536
3528
  if (headingRows > insertAt) {
3537
3529
  headingRows += rowsToInsert;
@@ -3546,14 +3538,10 @@ const downcastTableAlignmentConfig = {
3546
3538
  for(let rowOffset = 0; rowOffset < rows.length; rowOffset++){
3547
3539
  const row = rows[rowOffset];
3548
3540
  for(let columnIndex = 0; columnIndex < columns; columnIndex++){
3549
- updateTableCellType({
3550
- table,
3551
- writer,
3552
- cell: row[columnIndex],
3553
- row: insertAt + rowOffset,
3554
- column: columnIndex,
3555
- scopedHeaders
3556
- });
3541
+ const cell = row[columnIndex];
3542
+ if (insertAt + rowOffset < headingRows || columnIndex < headingColumns) {
3543
+ writer.setAttribute('tableCellType', 'header', cell);
3544
+ }
3557
3545
  }
3558
3546
  }
3559
3547
  }
@@ -3588,18 +3576,12 @@ const downcastTableAlignmentConfig = {
3588
3576
  const insertPosition = writer.createPositionAt(tableRow, 'end');
3589
3577
  // Insert the empty cell only if this slot is not row-spanned from any other cell.
3590
3578
  if (colspan > 0) {
3591
- const insertedCell = createEmptyTableCell(writer, insertPosition, colspan > 1 ? {
3579
+ const insertedCells = createEmptyTableCell(writer, insertPosition, colspan > 1 ? {
3592
3580
  colspan
3593
3581
  } : undefined);
3594
- if (cellTypeEnabled) {
3595
- updateTableCellType({
3596
- table,
3597
- writer,
3598
- cell: insertedCell,
3599
- row: insertAt + rowIndex,
3600
- column: cellIndex,
3601
- scopedHeaders
3602
- });
3582
+ // If we insert row in heading section, set proper cell type.
3583
+ if (cellTypeEnabled && (insertAt + rowIndex < headingRows || cellIndex < headingColumns)) {
3584
+ writer.setAttribute('tableCellType', 'header', insertedCells);
3603
3585
  }
3604
3586
  }
3605
3587
  // Skip the col-spanned slots, there won't be any cells.
@@ -3639,8 +3621,8 @@ const downcastTableAlignmentConfig = {
3639
3621
  const insertAt = options.at || 0;
3640
3622
  const columnsToInsert = options.columns || 1;
3641
3623
  const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
3642
- const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
3643
3624
  model.change((writer)=>{
3625
+ const headingRows = table.getAttribute('headingRows') || 0;
3644
3626
  let headingColumns = table.getAttribute('headingColumns');
3645
3627
  // Inserting columns inside heading section requires to update `headingColumns` attribute as the heading section will grow.
3646
3628
  if (insertAt < headingColumns) {
@@ -3662,14 +3644,9 @@ const downcastTableAlignmentConfig = {
3662
3644
  if (cellTypeEnabled) {
3663
3645
  // If we insert column in heading section, set proper cell type.
3664
3646
  for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
3665
- updateTableCellType({
3666
- table,
3667
- writer,
3668
- cell: insertedCells[columnOffset],
3669
- row: rowIndex,
3670
- column: insertAt + columnOffset,
3671
- scopedHeaders
3672
- });
3647
+ if (insertAt + columnOffset < headingColumns || rowIndex < headingRows) {
3648
+ writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
3649
+ }
3673
3650
  }
3674
3651
  }
3675
3652
  rowIndex++;
@@ -3702,14 +3679,9 @@ const downcastTableAlignmentConfig = {
3702
3679
  // If we insert column in heading section, set proper cell type.
3703
3680
  if (cellTypeEnabled) {
3704
3681
  for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
3705
- updateTableCellType({
3706
- table,
3707
- writer,
3708
- cell: insertedCells[columnOffset],
3709
- row,
3710
- column: insertAt + columnOffset,
3711
- scopedHeaders
3712
- });
3682
+ if (insertAt + columnOffset < headingColumns || row < headingRows) {
3683
+ writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
3684
+ }
3713
3685
  }
3714
3686
  }
3715
3687
  }
@@ -4220,7 +4192,6 @@ const downcastTableAlignmentConfig = {
4220
4192
  * Default is `true`.
4221
4193
  */ setHeadingRowsCount(writer, table, headingRows, options = {}) {
4222
4194
  const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
4223
- const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
4224
4195
  const oldHeadingRows = table.getAttribute('headingRows') || 0;
4225
4196
  if (headingRows === oldHeadingRows) {
4226
4197
  return;
@@ -4238,8 +4209,7 @@ const downcastTableAlignmentConfig = {
4238
4209
  writer,
4239
4210
  cell,
4240
4211
  row,
4241
- column,
4242
- scopedHeaders
4212
+ column
4243
4213
  });
4244
4214
  }
4245
4215
  // If heading rows were reduced, set body type to all cells in rows that are no longer in heading section.
@@ -4261,8 +4231,7 @@ const downcastTableAlignmentConfig = {
4261
4231
  writer,
4262
4232
  cell,
4263
4233
  row: cellRow,
4264
- column,
4265
- scopedHeaders
4234
+ column
4266
4235
  });
4267
4236
  }
4268
4237
  }
@@ -4295,7 +4264,6 @@ const downcastTableAlignmentConfig = {
4295
4264
  */ setHeadingColumnsCount(writer, table, headingColumns, options = {}) {
4296
4265
  const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
4297
4266
  const oldHeadingColumns = table.getAttribute('headingColumns') || 0;
4298
- const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
4299
4267
  if (headingColumns === oldHeadingColumns) {
4300
4268
  return;
4301
4269
  }
@@ -4312,8 +4280,7 @@ const downcastTableAlignmentConfig = {
4312
4280
  writer,
4313
4281
  cell,
4314
4282
  row,
4315
- column,
4316
- scopedHeaders
4283
+ column
4317
4284
  });
4318
4285
  }
4319
4286
  // If heading columns were reduced, set body type to all cells in columns that are no longer in heading section.
@@ -4335,8 +4302,7 @@ const downcastTableAlignmentConfig = {
4335
4302
  writer,
4336
4303
  cell,
4337
4304
  row,
4338
- column: cellColumn,
4339
- scopedHeaders
4305
+ column: cellColumn
4340
4306
  });
4341
4307
  }
4342
4308
  }
@@ -4703,23 +4669,14 @@ function compareRangeOrder(rangeA, rangeB) {
4703
4669
  /**
4704
4670
  * Updates the `tableCellType` attribute of a table cell based on its position in the table
4705
4671
  * and the table's `headingRows` and `headingColumns` attributes.
4706
- */ function updateTableCellType({ writer, table, row, column, cell, scopedHeaders }) {
4672
+ */ function updateTableCellType({ writer, table, row, column, cell }) {
4707
4673
  const headingRows = table.getAttribute('headingRows') || 0;
4708
4674
  const headingColumns = table.getAttribute('headingColumns') || 0;
4709
4675
  if (row >= headingRows && column >= headingColumns) {
4710
4676
  writer.removeAttribute('tableCellType', cell);
4711
- return;
4712
- }
4713
- let headerCellType = 'header';
4714
- // If scoped headers are enabled, we prefer to set 'row' or 'column' header types depending on the position.
4715
- if (scopedHeaders) {
4716
- if (row < headingRows) {
4717
- headerCellType = 'header-column';
4718
- } else {
4719
- headerCellType = 'header-row';
4720
- }
4677
+ } else {
4678
+ writer.setAttribute('tableCellType', 'header', cell);
4721
4679
  }
4722
- writer.setAttribute('tableCellType', headerCellType, cell);
4723
4680
  }
4724
4681
 
4725
4682
  /**
@@ -7958,7 +7915,7 @@ const isEmpty = (val)=>val === '';
7958
7915
  *
7959
7916
  * @internal
7960
7917
  * @param t The "t" function provided by the editor that is used to localize strings.
7961
- */ function getBorderStyleLabels(t) {
7918
+ */ function getBorderStyleLabels$1(t) {
7962
7919
  return {
7963
7920
  none: t('None'),
7964
7921
  solid: t('Solid'),
@@ -8028,9 +7985,9 @@ const isEmpty = (val)=>val === '';
8028
7985
  *
8029
7986
  * @internal
8030
7987
  * @param defaultStyle The default border.
8031
- */ function getBorderStyleDefinitions(view, defaultStyle) {
7988
+ */ function getBorderStyleDefinitions$1(view, defaultStyle) {
8032
7989
  const itemDefinitions = new Collection();
8033
- const styleLabels = getBorderStyleLabels(view.t);
7990
+ const styleLabels = getBorderStyleLabels$1(view.t);
8034
7991
  for(const style in styleLabels){
8035
7992
  const definition = {
8036
7993
  type: 'button',
@@ -8073,7 +8030,7 @@ const isEmpty = (val)=>val === '';
8073
8030
  * @param options.propertyName The name of the observable property in the view.
8074
8031
  * @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
8075
8032
  * @param options.defaultValue Default value for the property.
8076
- */ function fillToolbar(options) {
8033
+ */ function fillToolbar$1(options) {
8077
8034
  const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
8078
8035
  for(const name in labels){
8079
8036
  const button = new ButtonView(view.locale);
@@ -8277,10 +8234,10 @@ const isEmpty = (val)=>val === '';
8277
8234
  * @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
8278
8235
  * the "Restore default" button. Instead of clearing the input field, the default color value will be set.
8279
8236
  * @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
8280
- */ function getLabeledColorInputCreator(options) {
8237
+ */ function getLabeledColorInputCreator$1(options) {
8281
8238
  return (labeledFieldView, viewUid, statusUid)=>{
8282
8239
  const colorInputView = new ColorInputView(labeledFieldView.locale, {
8283
- colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
8240
+ colorDefinitions: colorConfigToColorGridDefinitions$1(options.colorConfig),
8284
8241
  columns: options.columns,
8285
8242
  defaultColorValue: options.defaultColorValue,
8286
8243
  colorPickerConfig: options.colorPickerConfig
@@ -8307,7 +8264,7 @@ const isEmpty = (val)=>val === '';
8307
8264
  const parsedValue = parseFloat(value);
8308
8265
  return !Number.isNaN(parsedValue) && value === String(parsedValue);
8309
8266
  }
8310
- function colorConfigToColorGridDefinitions(colorConfig) {
8267
+ function colorConfigToColorGridDefinitions$1(colorConfig) {
8311
8268
  return colorConfig.map((item)=>({
8312
8269
  color: item.model,
8313
8270
  label: item.label,
@@ -8345,9 +8302,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8345
8302
  /**
8346
8303
  * An input that allows specifying the table cell background color.
8347
8304
  */ backgroundInput;
8348
- /**
8349
- * A dropdown that allows selecting the type of the table cell (data or header).
8350
- */ cellTypeDropdown;
8351
8305
  /**
8352
8306
  * An input that allows specifying the table cell padding.
8353
8307
  */ paddingInput;
@@ -8369,9 +8323,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8369
8323
  /**
8370
8324
  * The "Cancel" button view.
8371
8325
  */ cancelButtonView;
8372
- /**
8373
- * The "Back" button view.
8374
- */ backButtonView;
8375
8326
  /**
8376
8327
  * A collection of views that can be focused in the form.
8377
8328
  */ _focusables;
@@ -8397,13 +8348,11 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8397
8348
  width: '',
8398
8349
  height: '',
8399
8350
  horizontalAlignment: '',
8400
- verticalAlignment: '',
8401
- cellType: ''
8351
+ verticalAlignment: ''
8402
8352
  });
8403
8353
  this.options = options;
8404
8354
  const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
8405
8355
  const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
8406
- const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
8407
8356
  const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
8408
8357
  const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
8409
8358
  this.focusTracker = new FocusTracker();
@@ -8413,7 +8362,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8413
8362
  this.borderWidthInput = borderWidthInput;
8414
8363
  this.borderColorInput = borderColorInput;
8415
8364
  this.backgroundInput = backgroundInput;
8416
- this.cellTypeDropdown = cellTypeDropdown;
8417
8365
  this.paddingInput = this._createPaddingField();
8418
8366
  this.widthInput = widthInput;
8419
8367
  this.heightInput = heightInput;
@@ -8425,7 +8373,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8425
8373
  const { saveButtonView, cancelButtonView } = this._createActionButtons();
8426
8374
  this.saveButtonView = saveButtonView;
8427
8375
  this.cancelButtonView = cancelButtonView;
8428
- this.backButtonView = this._createBackButton();
8429
8376
  this._focusables = new ViewCollection();
8430
8377
  this._focusCycler = new FocusCycler({
8431
8378
  focusables: this._focusables,
@@ -8439,42 +8386,28 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8439
8386
  }
8440
8387
  });
8441
8388
  // Form header.
8442
- const header = new FormHeaderView(locale, {
8389
+ this.children.add(new FormHeaderView(locale, {
8443
8390
  label: this.t('Cell properties')
8444
- });
8445
- header.children.add(this.backButtonView, 0);
8446
- this.children.add(header);
8391
+ }));
8447
8392
  // Border row.
8448
8393
  this.children.add(new FormRowView(locale, {
8449
8394
  labelView: borderRowLabel,
8450
8395
  children: [
8451
8396
  borderRowLabel,
8452
8397
  borderStyleDropdown,
8453
- borderWidthInput,
8454
- borderColorInput
8398
+ borderColorInput,
8399
+ borderWidthInput
8455
8400
  ],
8456
8401
  class: 'ck-table-form__border-row'
8457
8402
  }));
8458
- // Background and cell type.
8403
+ // Background.
8459
8404
  this.children.add(new FormRowView(locale, {
8405
+ labelView: backgroundRowLabel,
8460
8406
  children: [
8461
- new FormRowView(locale, {
8462
- labelView: cellTypeRowLabel,
8463
- children: [
8464
- cellTypeRowLabel,
8465
- cellTypeDropdown
8466
- ],
8467
- class: 'ck-table-form__cell-type-row'
8468
- }),
8469
- new FormRowView(locale, {
8470
- labelView: backgroundRowLabel,
8471
- children: [
8472
- backgroundRowLabel,
8473
- backgroundInput
8474
- ],
8475
- class: 'ck-table-form__background-row'
8476
- })
8477
- ]
8407
+ backgroundRowLabel,
8408
+ backgroundInput
8409
+ ],
8410
+ class: 'ck-table-form__background-row'
8478
8411
  }));
8479
8412
  // Dimensions row and padding.
8480
8413
  this.children.add(new FormRowView(locale, {
@@ -8512,8 +8445,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8512
8445
  // Action row.
8513
8446
  this.children.add(new FormRowView(locale, {
8514
8447
  children: [
8515
- this.cancelButtonView,
8516
- this.saveButtonView
8448
+ this.saveButtonView,
8449
+ this.cancelButtonView
8517
8450
  ],
8518
8451
  class: 'ck-table-form__action-row'
8519
8452
  }));
@@ -8552,16 +8485,14 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8552
8485
  this.borderStyleDropdown,
8553
8486
  this.borderColorInput,
8554
8487
  this.borderWidthInput,
8555
- this.cellTypeDropdown,
8556
8488
  this.backgroundInput,
8557
8489
  this.widthInput,
8558
8490
  this.heightInput,
8559
8491
  this.paddingInput,
8560
8492
  this.horizontalAlignmentToolbar,
8561
8493
  this.verticalAlignmentToolbar,
8562
- this.cancelButtonView,
8563
8494
  this.saveButtonView,
8564
- this.backButtonView
8495
+ this.cancelButtonView
8565
8496
  ].forEach((view)=>{
8566
8497
  // Register the view as focusable.
8567
8498
  this._focusables.add(view);
@@ -8596,7 +8527,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8596
8527
  width: defaultTableCellProperties.borderWidth,
8597
8528
  color: defaultTableCellProperties.borderColor
8598
8529
  };
8599
- const colorInputCreator = getLabeledColorInputCreator({
8530
+ const colorInputCreator = getLabeledColorInputCreator$1({
8600
8531
  colorConfig: this.options.borderColors,
8601
8532
  columns: 5,
8602
8533
  defaultColorValue: defaultBorder.color,
@@ -8609,7 +8540,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8609
8540
  const borderRowLabel = new LabelView(locale);
8610
8541
  borderRowLabel.text = t('Border');
8611
8542
  // -- Style ---------------------------------------------------
8612
- const styleLabels = getBorderStyleLabels(t);
8543
+ const styleLabels = getBorderStyleLabels$1(t);
8613
8544
  const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
8614
8545
  borderStyleDropdown.set({
8615
8546
  label: accessibleLabel,
@@ -8629,7 +8560,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8629
8560
  this.borderStyle = evt.source._borderStyleValue;
8630
8561
  });
8631
8562
  borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
8632
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
8563
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
8633
8564
  role: 'menu',
8634
8565
  ariaLabel: accessibleLabel
8635
8566
  });
@@ -8640,7 +8571,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8640
8571
  class: 'ck-table-form__border-width'
8641
8572
  });
8642
8573
  borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
8643
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
8574
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
8644
8575
  borderWidthInput.fieldView.on('input', ()=>{
8645
8576
  this.borderWidth = borderWidthInput.fieldView.element.value;
8646
8577
  });
@@ -8651,7 +8582,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8651
8582
  class: 'ck-table-form__border-color'
8652
8583
  });
8653
8584
  borderColorInput.fieldView.bind('value').to(this, 'borderColor');
8654
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
8585
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
8655
8586
  borderColorInput.fieldView.on('input', ()=>{
8656
8587
  this.borderColor = borderColorInput.fieldView.value;
8657
8588
  });
@@ -8659,12 +8590,12 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8659
8590
  this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
8660
8591
  // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
8661
8592
  // See: https://github.com/ckeditor/ckeditor5/issues/6227.
8662
- if (!isBorderStyleSet$1(newValue)) {
8593
+ if (!isBorderStyleSet$3(newValue)) {
8663
8594
  this.borderColor = '';
8664
8595
  this.borderWidth = '';
8665
8596
  }
8666
8597
  // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
8667
- if (!isBorderStyleSet$1(oldValue)) {
8598
+ if (!isBorderStyleSet$3(oldValue)) {
8668
8599
  this.borderColor = defaultBorder.color;
8669
8600
  this.borderWidth = defaultBorder.width;
8670
8601
  }
@@ -8687,7 +8618,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8687
8618
  const backgroundRowLabel = new LabelView(locale);
8688
8619
  backgroundRowLabel.text = t('Background');
8689
8620
  // -- Background color input -----------------------------------
8690
- const colorInputCreator = getLabeledColorInputCreator({
8621
+ const colorInputCreator = getLabeledColorInputCreator$1({
8691
8622
  colorConfig: this.options.backgroundColors,
8692
8623
  columns: 5,
8693
8624
  defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
@@ -8707,46 +8638,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8707
8638
  backgroundInput
8708
8639
  };
8709
8640
  }
8710
- /**
8711
- * Create cell type field.
8712
- *
8713
- * * {@link #cellTypeDropdown}.
8714
- *
8715
- * @internal
8716
- */ _createCellTypeField() {
8717
- const locale = this.locale;
8718
- const t = this.t;
8719
- const cellTypeRowLabel = new LabelView(locale);
8720
- cellTypeRowLabel.text = t('Cell type');
8721
- const cellTypeLabels = this._cellTypeLabels;
8722
- const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
8723
- cellTypeDropdown.set({
8724
- label: t('Cell type'),
8725
- class: 'ck-table-cell-properties-form__cell-type'
8726
- });
8727
- cellTypeDropdown.fieldView.buttonView.set({
8728
- ariaLabel: t('Cell type'),
8729
- ariaLabelledBy: undefined,
8730
- isOn: false,
8731
- withText: true,
8732
- tooltip: t('Cell type')
8733
- });
8734
- cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
8735
- return cellTypeLabels[value || 'data'];
8736
- });
8737
- cellTypeDropdown.fieldView.on('execute', (evt)=>{
8738
- this.cellType = evt.source._cellTypeValue;
8739
- });
8740
- cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
8741
- addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
8742
- role: 'menu',
8743
- ariaLabel: t('Cell type')
8744
- });
8745
- return {
8746
- cellTypeRowLabel,
8747
- cellTypeDropdown
8748
- };
8749
- }
8750
8641
  /**
8751
8642
  * Creates the following form fields:
8752
8643
  *
@@ -8843,10 +8734,9 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8843
8734
  horizontalAlignmentToolbar.set({
8844
8735
  isCompact: true,
8845
8736
  role: 'radiogroup',
8846
- ariaLabel: t('Horizontal text alignment toolbar'),
8847
- class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
8737
+ ariaLabel: t('Horizontal text alignment toolbar')
8848
8738
  });
8849
- fillToolbar({
8739
+ fillToolbar$1({
8850
8740
  view: this,
8851
8741
  icons: ALIGNMENT_ICONS,
8852
8742
  toolbar: horizontalAlignmentToolbar,
@@ -8870,10 +8760,9 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8870
8760
  verticalAlignmentToolbar.set({
8871
8761
  isCompact: true,
8872
8762
  role: 'radiogroup',
8873
- ariaLabel: t('Vertical text alignment toolbar'),
8874
- class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
8763
+ ariaLabel: t('Vertical text alignment toolbar')
8875
8764
  });
8876
- fillToolbar({
8765
+ fillToolbar$1({
8877
8766
  view: this,
8878
8767
  icons: ALIGNMENT_ICONS,
8879
8768
  toolbar: verticalAlignmentToolbar,
@@ -8905,7 +8794,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8905
8794
  ];
8906
8795
  saveButtonView.set({
8907
8796
  label: t('Save'),
8908
- class: 'ck-button-action',
8797
+ icon: IconCheck,
8798
+ class: 'ck-button-save',
8909
8799
  type: 'submit',
8910
8800
  withText: true
8911
8801
  });
@@ -8914,6 +8804,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8914
8804
  });
8915
8805
  cancelButtonView.set({
8916
8806
  label: t('Cancel'),
8807
+ icon: IconCancel,
8808
+ class: 'ck-button-cancel',
8917
8809
  withText: true
8918
8810
  });
8919
8811
  cancelButtonView.delegate('execute').to(this, 'cancel');
@@ -8922,47 +8814,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8922
8814
  cancelButtonView
8923
8815
  };
8924
8816
  }
8925
- /**
8926
- * Creates a back button view that cancels the form.
8927
- */ _createBackButton() {
8928
- const t = this.locale.t;
8929
- const backButton = new ButtonView(this.locale);
8930
- backButton.set({
8931
- class: 'ck-button-back',
8932
- label: t('Back'),
8933
- icon: IconPreviousArrow,
8934
- tooltip: true
8935
- });
8936
- backButton.delegate('execute').to(this, 'cancel');
8937
- return backButton;
8938
- }
8939
- /**
8940
- * Creates the cell type dropdown definitions.
8941
- */ _getCellTypeDefinitions() {
8942
- const itemDefinitions = new Collection();
8943
- const labels = this._cellTypeLabels;
8944
- const types = [
8945
- 'data',
8946
- 'header'
8947
- ];
8948
- if (this.options.showScopedHeaderOptions) {
8949
- types.push('header-column', 'header-row');
8950
- }
8951
- for (const type of types){
8952
- const definition = {
8953
- type: 'button',
8954
- model: new UIModel({
8955
- _cellTypeValue: type,
8956
- label: labels[type],
8957
- role: 'menuitemradio',
8958
- withText: true
8959
- })
8960
- };
8961
- definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
8962
- itemDefinitions.add(definition);
8963
- }
8964
- return itemDefinitions;
8965
- }
8966
8817
  /**
8967
8818
  * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
8968
8819
  */ get _horizontalAlignmentLabels() {
@@ -8999,19 +8850,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
8999
8850
  bottom: t('Align cell text to the bottom')
9000
8851
  };
9001
8852
  }
9002
- /**
9003
- * Provides localized labels for {@link #cellTypeDropdown}.
9004
- */ get _cellTypeLabels() {
9005
- const t = this.t;
9006
- return {
9007
- data: t('Data cell'),
9008
- header: t('Header cell'),
9009
- 'header-column': t('Column header'),
9010
- 'header-row': t('Row header')
9011
- };
9012
- }
9013
8853
  }
9014
- function isBorderStyleSet$1(value) {
8854
+ function isBorderStyleSet$3(value) {
9015
8855
  return value !== 'none';
9016
8856
  }
9017
8857
 
@@ -9110,9 +8950,9 @@ const BALLOON_POSITIONS = /* #__PURE__ */ (()=>[
9110
8950
  return Rect.getBoundingRect(rects);
9111
8951
  }
9112
8952
 
9113
- const ERROR_TEXT_TIMEOUT$1 = 500;
8953
+ const ERROR_TEXT_TIMEOUT$3 = 500;
9114
8954
  // Map of view properties and related commands.
9115
- const propertyToCommandMap$1 = {
8955
+ const propertyToCommandMap$3 = {
9116
8956
  borderStyle: 'tableCellBorderStyle',
9117
8957
  borderColor: 'tableCellBorderColor',
9118
8958
  borderWidth: 'tableCellBorderWidth',
@@ -9121,8 +8961,7 @@ const propertyToCommandMap$1 = {
9121
8961
  padding: 'tableCellPadding',
9122
8962
  backgroundColor: 'tableCellBackgroundColor',
9123
8963
  horizontalAlignment: 'tableCellHorizontalAlignment',
9124
- verticalAlignment: 'tableCellVerticalAlignment',
9125
- cellType: 'tableCellType'
8964
+ verticalAlignment: 'tableCellVerticalAlignment'
9126
8965
  };
9127
8966
  /**
9128
8967
  * The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
@@ -9209,7 +9048,7 @@ const propertyToCommandMap$1 = {
9209
9048
  tooltip: true
9210
9049
  });
9211
9050
  this.listenTo(view, 'execute', ()=>this._showView());
9212
- const commands = Object.values(propertyToCommandMap$1).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
9051
+ const commands = Object.values(propertyToCommandMap$3).map((commandName)=>editor.commands.get(commandName));
9213
9052
  view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
9214
9053
  return view;
9215
9054
  });
@@ -9231,7 +9070,6 @@ const propertyToCommandMap$1 = {
9231
9070
  */ _createPropertiesView(defaultTableCellProperties) {
9232
9071
  const editor = this.editor;
9233
9072
  const config = editor.config.get('table.tableCellProperties');
9234
- const scopedHeaders = !!editor.config.get('table.tableCellProperties.scopedHeaders');
9235
9073
  const borderColorsConfig = normalizeColorOptions(config.borderColors);
9236
9074
  const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
9237
9075
  const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
@@ -9241,8 +9079,7 @@ const propertyToCommandMap$1 = {
9241
9079
  borderColors: localizedBorderColors,
9242
9080
  backgroundColors: localizedBackgroundColors,
9243
9081
  defaultTableCellProperties,
9244
- colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false,
9245
- showScopedHeaderOptions: scopedHeaders
9082
+ colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
9246
9083
  });
9247
9084
  const t = editor.t;
9248
9085
  // Render the view so its #element is available for the clickOutsideHandler.
@@ -9317,11 +9154,6 @@ const propertyToCommandMap$1 = {
9317
9154
  }));
9318
9155
  view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
9319
9156
  view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
9320
- const cellTypeCommand = editor.commands.get('tableCellType');
9321
- if (cellTypeCommand) {
9322
- view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
9323
- view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
9324
- }
9325
9157
  return view;
9326
9158
  }
9327
9159
  /**
@@ -9334,24 +9166,12 @@ const propertyToCommandMap$1 = {
9334
9166
  */ _fillViewFormFromCommandValues() {
9335
9167
  const commands = this.editor.commands;
9336
9168
  const borderStyleCommand = commands.get('tableCellBorderStyle');
9337
- Object.entries(propertyToCommandMap$1).flatMap(([property, commandName])=>{
9338
- const command = commands.get(commandName);
9339
- if (!command) {
9340
- return [];
9341
- }
9169
+ Object.entries(propertyToCommandMap$3).map(([property, commandName])=>{
9342
9170
  const propertyKey = property;
9343
- let defaultValue;
9344
- if (propertyKey === 'cellType') {
9345
- defaultValue = '';
9346
- } else {
9347
- defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
9348
- }
9349
- const entry = [
9350
- property,
9351
- command.value || defaultValue
9352
- ];
9171
+ const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
9353
9172
  return [
9354
- entry
9173
+ property,
9174
+ commands.get(commandName).value || defaultValue
9355
9175
  ];
9356
9176
  }).forEach(([property, value])=>{
9357
9177
  // Do not set the `border-color` and `border-width` fields if `border-style:none`.
@@ -9452,7 +9272,7 @@ const propertyToCommandMap$1 = {
9452
9272
  const { commandName, viewField, validator, errorText } = options;
9453
9273
  const setErrorTextDebounced = debounce(()=>{
9454
9274
  viewField.errorText = errorText;
9455
- }, ERROR_TEXT_TIMEOUT$1);
9275
+ }, ERROR_TEXT_TIMEOUT$3);
9456
9276
  return (evt, propertyName, newValue)=>{
9457
9277
  setErrorTextDebounced.cancel();
9458
9278
  // Do not execute the command on initial call (opening the table properties view).
@@ -10112,7 +9932,7 @@ const propertyToCommandMap$1 = {
10112
9932
  // Check each cell in the current row/column.
10113
9933
  for (const { cell, row, column } of walker){
10114
9934
  // If we find a non-header cell, this row/column can't be part of the heading section.
10115
- if (!isTableHeaderCellType(cell.getAttribute('tableCellType'))) {
9935
+ if (cell.getAttribute('tableCellType') !== 'header') {
10116
9936
  allCellsAreHeaders = false;
10117
9937
  break;
10118
9938
  }
@@ -10238,8 +10058,10 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10238
10058
  editor.commands.add('tableCellHorizontalAlignment', new TableCellHorizontalAlignmentCommand(editor, defaultTableCellProperties.horizontalAlignment));
10239
10059
  enableVerticalAlignmentProperty(schema, conversion, defaultTableCellProperties.verticalAlignment);
10240
10060
  editor.commands.add('tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand(editor, defaultTableCellProperties.verticalAlignment));
10241
- enableCellTypeProperty(editor);
10242
- editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
10061
+ if (editor.config.get('experimentalFlags.tableCellTypeSupport')) {
10062
+ enableCellTypeProperty(editor);
10063
+ editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
10064
+ }
10243
10065
  }
10244
10066
  }
10245
10067
  /**
@@ -10429,9 +10251,8 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10429
10251
  /**
10430
10252
  * Enables the `tableCellType` attribute for table cells.
10431
10253
  */ function enableCellTypeProperty(editor) {
10432
- const { model, conversion, editing, config } = editor;
10254
+ const { model, conversion, editing } = editor;
10433
10255
  const { schema } = model;
10434
- const scopedHeaders = !!config.get('table.tableCellProperties.scopedHeaders');
10435
10256
  const tableUtils = editor.plugins.get(TableUtils);
10436
10257
  schema.extend('tableCell', {
10437
10258
  allowAttributes: [
@@ -10454,7 +10275,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10454
10275
  const { writer } = conversionApi;
10455
10276
  const { modelRange } = data;
10456
10277
  const modelElement = modelRange?.start.nodeAfter;
10457
- if (modelElement?.is('element', 'tableCell') && !modelElement.hasAttribute('tableCellType')) {
10278
+ if (modelElement?.is('element', 'tableCell')) {
10458
10279
  writer.setAttribute('tableCellType', 'header', modelElement);
10459
10280
  }
10460
10281
  });
@@ -10466,8 +10287,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10466
10287
  const modelElement = modelRange?.start.nodeAfter;
10467
10288
  if (modelElement?.is('element', 'table') && modelElement.getAttribute('tableType') === 'layout') {
10468
10289
  for (const { cell } of new TableWalker(modelElement)){
10469
- const tableCellType = cell.getAttribute('tableCellType');
10470
- if (isTableHeaderCellType(tableCellType)) {
10290
+ if (cell.getAttribute('tableCellType') === 'header') {
10471
10291
  writer.setAttribute('tableType', 'content', modelElement);
10472
10292
  break;
10473
10293
  }
@@ -10477,55 +10297,6 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10477
10297
  priority: priorities.low - 1
10478
10298
  });
10479
10299
  });
10480
- // If scoped headers are enabled, add conversion for the `scope` attribute.
10481
- if (scopedHeaders) {
10482
- conversion.for('downcast').attributeToAttribute({
10483
- model: {
10484
- name: 'tableCell',
10485
- key: 'tableCellType'
10486
- },
10487
- view: (modelAttributeValue)=>{
10488
- switch(modelAttributeValue){
10489
- case 'header-row':
10490
- return {
10491
- key: 'scope',
10492
- value: 'row'
10493
- };
10494
- case 'header-column':
10495
- return {
10496
- key: 'scope',
10497
- value: 'col'
10498
- };
10499
- }
10500
- }
10501
- });
10502
- // Attribute to attribute conversion tend to not override existing `tableCellType` set by other converters.
10503
- // However, in this scenario if the previous converter set `tableCellType` to `header`, we can adjust it
10504
- // based on the `scope` attribute.
10505
- conversion.for('upcast').add((dispatcher)=>{
10506
- dispatcher.on('element:th', (_, data, conversionApi)=>{
10507
- const { writer, consumable } = conversionApi;
10508
- const { viewItem, modelRange } = data;
10509
- const modelElement = modelRange.start.nodeAfter;
10510
- const previousTableCellType = modelElement?.getAttribute('tableCellType');
10511
- if (previousTableCellType === 'header' && consumable.consume(viewItem, {
10512
- attributes: [
10513
- 'scope'
10514
- ]
10515
- })) {
10516
- const scope = viewItem.getAttribute('scope');
10517
- switch(scope){
10518
- case 'row':
10519
- writer.setAttribute('tableCellType', 'header-row', modelElement);
10520
- break;
10521
- case 'col':
10522
- writer.setAttribute('tableCellType', 'header-column', modelElement);
10523
- break;
10524
- }
10525
- }
10526
- });
10527
- });
10528
- }
10529
10300
  // Registers a post-fixer that ensures the `headingRows` and `headingColumns` attributes
10530
10301
  // are consistent with the `tableCellType` attribute of the cells. `tableCellType` has priority
10531
10302
  // over `headingRows` and `headingColumns` and we use it to adjust the heading sections of the table.
@@ -10583,7 +10354,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10583
10354
  for (const tableCell of cellsToReconvert){
10584
10355
  const viewElement = editing.mapper.toViewElement(tableCell);
10585
10356
  const cellType = tableCell.getAttribute('tableCellType');
10586
- const expectedElementName = isTableHeaderCellType(cellType) ? 'th' : 'td';
10357
+ const expectedElementName = cellType === 'header' ? 'th' : 'td';
10587
10358
  if (viewElement?.name !== expectedElementName) {
10588
10359
  editing.reconvertItem(tableCell);
10589
10360
  }
@@ -10714,10 +10485,14 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10714
10485
  */ afterInit() {
10715
10486
  const { editor } = this;
10716
10487
  const { ui, plugins } = editor;
10717
- if (!editor.plugins.has('TablePropertiesUI')) {
10488
+ let tablePropertiesUI;
10489
+ if (plugins.has('TablePropertiesUIExperimental')) {
10490
+ tablePropertiesUI = plugins.get('TablePropertiesUIExperimental');
10491
+ } else if (plugins.has('TablePropertiesUI')) {
10492
+ tablePropertiesUI = plugins.get('TablePropertiesUI');
10493
+ } else {
10718
10494
  return;
10719
10495
  }
10720
- const tablePropertiesUI = plugins.get('TablePropertiesUI');
10721
10496
  // Override the default table properties button to include the table type dropdown.
10722
10497
  // It needs to be done in `afterInit()` to make sure that `tableProperties` button is
10723
10498
  // registered after the initialization of the `TablePropertiesUI`. Otherwise, the
@@ -12483,7 +12258,7 @@ const TABLE_TYPES = [
12483
12258
  const defaultTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
12484
12259
  includeAlignmentProperty: true
12485
12260
  });
12486
- const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles') === true;
12261
+ const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles') !== false;
12487
12262
  editor.data.addStyleProcessorRules(addMarginStylesRules);
12488
12263
  editor.data.addStyleProcessorRules(addBorderStylesRules);
12489
12264
  enableBorderProperties(editor, {
@@ -12494,7 +12269,11 @@ const TABLE_TYPES = [
12494
12269
  editor.commands.add('tableBorderColor', new TableBorderColorCommand(editor, defaultTableProperties.borderColor));
12495
12270
  editor.commands.add('tableBorderStyle', new TableBorderStyleCommand(editor, defaultTableProperties.borderStyle));
12496
12271
  editor.commands.add('tableBorderWidth', new TableBorderWidthCommand(editor, defaultTableProperties.borderWidth));
12497
- enableAlignmentProperty(schema, conversion, defaultTableProperties.alignment, useInlineStyles);
12272
+ if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
12273
+ enableExtendedAlignmentProperty(schema, conversion, defaultTableProperties.alignment, useInlineStyles);
12274
+ } else {
12275
+ enableAlignmentProperty(schema, conversion, defaultTableProperties.alignment);
12276
+ }
12498
12277
  editor.commands.add('tableAlignment', new TableAlignmentCommand(editor, defaultTableProperties.alignment));
12499
12278
  enableTableToFigureProperty(schema, conversion, {
12500
12279
  modelAttribute: 'tableWidth',
@@ -12521,18 +12300,20 @@ const TABLE_TYPES = [
12521
12300
  defaultValue: defaultTableProperties.backgroundColor
12522
12301
  });
12523
12302
  editor.commands.add('tableBackgroundColor', new TableBackgroundColorCommand(editor, defaultTableProperties.backgroundColor));
12524
- const viewDoc = editor.editing.view.document;
12525
- // Adjust clipboard output to wrap tables in divs if needed (for alignment).
12526
- this.listenTo(viewDoc, 'clipboardOutput', (evt, data)=>{
12527
- editor.editing.view.change((writer)=>{
12528
- for (const { item } of writer.createRangeIn(data.content)){
12529
- wrapInDivIfNeeded(item, writer);
12530
- }
12531
- data.dataTransfer.setData('text/html', this.editor.data.htmlProcessor.toData(data.content));
12303
+ if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
12304
+ const viewDoc = editor.editing.view.document;
12305
+ // Adjust clipboard output to wrap tables in divs if needed (for alignment).
12306
+ this.listenTo(viewDoc, 'clipboardOutput', (evt, data)=>{
12307
+ editor.editing.view.change((writer)=>{
12308
+ for (const { item } of writer.createRangeIn(data.content)){
12309
+ wrapInDivIfNeeded(item, writer);
12310
+ }
12311
+ data.dataTransfer.setData('text/html', this.editor.data.htmlProcessor.toData(data.content));
12312
+ });
12313
+ }, {
12314
+ priority: 'lowest'
12532
12315
  });
12533
- }, {
12534
- priority: 'lowest'
12535
- });
12316
+ }
12536
12317
  }
12537
12318
  }
12538
12319
  /**
@@ -12602,10 +12383,10 @@ function insertWrapperWithAlignment(writer, align, table) {
12602
12383
  });
12603
12384
  }
12604
12385
  /**
12605
- * Enables the `'alignment'` attribute for table.
12386
+ * Enables the extended block`'alignment'` attribute for table.
12606
12387
  *
12607
12388
  * @param defaultValue The default alignment value.
12608
- */ function enableAlignmentProperty(schema, conversion, defaultValue, useInlineStyles) {
12389
+ */ function enableExtendedAlignmentProperty(schema, conversion, defaultValue, useInlineStyles) {
12609
12390
  schema.extend('table', {
12610
12391
  allowAttributes: [
12611
12392
  'tableAlignment'
@@ -12705,33 +12486,171 @@ function insertWrapperWithAlignment(writer, align, table) {
12705
12486
  conversion.for('upcast').add(upcastTableAlignedDiv(defaultValue));
12706
12487
  }
12707
12488
  /**
12708
- * Returns a function that converts the table view representation:
12709
- *
12710
- * ```html
12711
- * <div align="right"><table>...</table></div>
12712
- * <!-- or -->
12713
- * <div align="center"><table>...</table></div>
12714
- * <!-- or -->
12715
- * <div align="left"><table>...</table></div>
12716
- * ```
12717
- *
12718
- * to the model representation:
12719
- *
12720
- * ```xml
12721
- * <table tableAlignment="right|center|left"></table>
12722
- * ```
12489
+ * Enables the `'alignment'` attribute for table.
12723
12490
  *
12724
- * @internal
12725
- */ function upcastTableAlignedDiv(defaultValue) {
12726
- return (dispatcher)=>{
12727
- dispatcher.on('element:div', (evt, data, conversionApi)=>{
12728
- // Do not convert if this is not a "table wrapped in div with align attribute".
12729
- if (!conversionApi.consumable.test(data.viewItem, {
12730
- name: true,
12731
- attributes: 'align'
12732
- })) {
12733
- return;
12734
- }
12491
+ * @param defaultValue The default alignment value.
12492
+ */ function enableAlignmentProperty(schema, conversion, defaultValue) {
12493
+ const ALIGN_VALUES_REG_EXP = /^(left|center|right)$/;
12494
+ const FLOAT_VALUES_REG_EXP = /^(left|none|right)$/;
12495
+ schema.extend('table', {
12496
+ allowAttributes: [
12497
+ 'tableAlignment'
12498
+ ]
12499
+ });
12500
+ schema.setAttributeProperties('tableAlignment', {
12501
+ isFormatting: true
12502
+ });
12503
+ conversion.for('downcast').attributeToAttribute({
12504
+ model: {
12505
+ name: 'table',
12506
+ key: 'tableAlignment',
12507
+ values: [
12508
+ 'left',
12509
+ 'center',
12510
+ 'right'
12511
+ ]
12512
+ },
12513
+ view: {
12514
+ left: {
12515
+ key: 'style',
12516
+ value: {
12517
+ float: 'left'
12518
+ }
12519
+ },
12520
+ right: {
12521
+ key: 'style',
12522
+ value: {
12523
+ float: 'right'
12524
+ }
12525
+ },
12526
+ center: (alignment, conversionApi, data)=>{
12527
+ const value = data.item.getAttribute('tableType') !== 'layout' ? {
12528
+ // Model: `alignment:center` => CSS: `float:none`.
12529
+ float: 'none'
12530
+ } : {
12531
+ 'margin-left': 'auto',
12532
+ 'margin-right': 'auto'
12533
+ };
12534
+ return {
12535
+ key: 'style',
12536
+ value
12537
+ };
12538
+ }
12539
+ },
12540
+ converterPriority: 'high'
12541
+ });
12542
+ conversion.for('upcast')// Support for the `float:*;` CSS definition for the table alignment.
12543
+ .attributeToAttribute({
12544
+ view: {
12545
+ name: /^(table|figure)$/,
12546
+ styles: {
12547
+ float: FLOAT_VALUES_REG_EXP
12548
+ }
12549
+ },
12550
+ model: {
12551
+ key: 'tableAlignment',
12552
+ value: (viewElement, conversionApi, data)=>{
12553
+ // Ignore other figure elements.
12554
+ if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
12555
+ return;
12556
+ }
12557
+ const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12558
+ let align = viewElement.getStyle('float');
12559
+ // CSS: `float:none` => Model: `alignment:center`.
12560
+ if (align === 'none') {
12561
+ align = 'center';
12562
+ }
12563
+ if (align !== localDefaultValue) {
12564
+ return align;
12565
+ }
12566
+ // Consume the style even if not applied to the element so it won't be processed by other converters.
12567
+ conversionApi.consumable.consume(viewElement, {
12568
+ styles: 'float'
12569
+ });
12570
+ }
12571
+ }
12572
+ })// Support for the `margin-left:auto; margin-right:auto;` CSS definition for the table alignment.
12573
+ .attributeToAttribute({
12574
+ view: {
12575
+ name: /^(table|figure)$/,
12576
+ styles: {
12577
+ 'margin-left': 'auto',
12578
+ 'margin-right': 'auto'
12579
+ }
12580
+ },
12581
+ model: {
12582
+ key: 'tableAlignment',
12583
+ value: (viewElement, conversionApi, data)=>{
12584
+ // Ignore other figure elements.
12585
+ if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
12586
+ return;
12587
+ }
12588
+ const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12589
+ const align = 'center';
12590
+ if (align !== localDefaultValue) {
12591
+ return align;
12592
+ }
12593
+ // Consume the styles even if not applied to the element so it won't be processed by other converters.
12594
+ conversionApi.consumable.consume(viewElement, {
12595
+ styles: [
12596
+ 'margin-left',
12597
+ 'margin-right'
12598
+ ]
12599
+ });
12600
+ }
12601
+ }
12602
+ })// Support for the `align` attribute as the backward compatibility while pasting from other sources.
12603
+ .attributeToAttribute({
12604
+ view: {
12605
+ name: 'table',
12606
+ attributes: {
12607
+ align: ALIGN_VALUES_REG_EXP
12608
+ }
12609
+ },
12610
+ model: {
12611
+ key: 'tableAlignment',
12612
+ value: (viewElement, conversionApi, data)=>{
12613
+ const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12614
+ const align = viewElement.getAttribute('align');
12615
+ if (align !== localDefaultValue) {
12616
+ return align;
12617
+ }
12618
+ // Consume the attribute even if not applied to the element so it won't be processed by other converters.
12619
+ conversionApi.consumable.consume(viewElement, {
12620
+ attributes: 'align'
12621
+ });
12622
+ }
12623
+ }
12624
+ });
12625
+ }
12626
+ /**
12627
+ * Returns a function that converts the table view representation:
12628
+ *
12629
+ * ```html
12630
+ * <div align="right"><table>...</table></div>
12631
+ * <!-- or -->
12632
+ * <div align="center"><table>...</table></div>
12633
+ * <!-- or -->
12634
+ * <div align="left"><table>...</table></div>
12635
+ * ```
12636
+ *
12637
+ * to the model representation:
12638
+ *
12639
+ * ```xml
12640
+ * <table tableAlignment="right|center|left"></table>
12641
+ * ```
12642
+ *
12643
+ * @internal
12644
+ */ function upcastTableAlignedDiv(defaultValue) {
12645
+ return (dispatcher)=>{
12646
+ dispatcher.on('element:div', (evt, data, conversionApi)=>{
12647
+ // Do not convert if this is not a "table wrapped in div with align attribute".
12648
+ if (!conversionApi.consumable.test(data.viewItem, {
12649
+ name: true,
12650
+ attributes: 'align'
12651
+ })) {
12652
+ return;
12653
+ }
12735
12654
  // Find a table element inside the div element.
12736
12655
  const viewTable = getViewTableFromWrapper(data.viewItem);
12737
12656
  // Do not convert if table element is absent or was already converted.
@@ -12894,9 +12813,6 @@ function insertWrapperWithAlignment(writer, align, table) {
12894
12813
  /**
12895
12814
  * The "Cancel" button view.
12896
12815
  */ cancelButtonView;
12897
- /**
12898
- * The Back button view displayed in the header.
12899
- */ backButtonView;
12900
12816
  /**
12901
12817
  * A collection of views that can be focused in the form.
12902
12818
  */ _focusables;
@@ -12938,7 +12854,6 @@ function insertWrapperWithAlignment(writer, align, table) {
12938
12854
  const { saveButtonView, cancelButtonView } = this._createActionButtons();
12939
12855
  this.saveButtonView = saveButtonView;
12940
12856
  this.cancelButtonView = cancelButtonView;
12941
- this.backButtonView = this._createBackButton();
12942
12857
  this._focusables = new ViewCollection();
12943
12858
  this._focusCycler = new FocusCycler({
12944
12859
  focusables: this._focusables,
@@ -12952,22 +12867,29 @@ function insertWrapperWithAlignment(writer, align, table) {
12952
12867
  }
12953
12868
  });
12954
12869
  // Form header.
12955
- const headerView = new FormHeaderView(locale, {
12870
+ this.children.add(new FormHeaderView(locale, {
12956
12871
  label: this.t('Table properties')
12957
- });
12958
- headerView.children.add(this.backButtonView, 0);
12959
- this.children.add(headerView);
12872
+ }));
12960
12873
  // Border row.
12961
12874
  this.children.add(new FormRowView(locale, {
12962
12875
  labelView: borderRowLabel,
12963
12876
  children: [
12964
12877
  borderRowLabel,
12965
12878
  borderStyleDropdown,
12966
- borderWidthInput,
12967
- borderColorInput
12879
+ borderColorInput,
12880
+ borderWidthInput
12968
12881
  ],
12969
12882
  class: 'ck-table-form__border-row'
12970
12883
  }));
12884
+ // Background row.
12885
+ this.children.add(new FormRowView(locale, {
12886
+ labelView: backgroundRowLabel,
12887
+ children: [
12888
+ backgroundRowLabel,
12889
+ backgroundInput
12890
+ ],
12891
+ class: 'ck-table-form__background-row'
12892
+ }));
12971
12893
  this.children.add(new FormRowView(locale, {
12972
12894
  children: [
12973
12895
  // Dimensions row.
@@ -12981,31 +12903,22 @@ function insertWrapperWithAlignment(writer, align, table) {
12981
12903
  ],
12982
12904
  class: 'ck-table-form__dimensions-row'
12983
12905
  }),
12984
- // Background row.
12906
+ // Alignment row.
12985
12907
  new FormRowView(locale, {
12986
- labelView: backgroundRowLabel,
12908
+ labelView: alignmentLabel,
12987
12909
  children: [
12988
- backgroundRowLabel,
12989
- backgroundInput
12910
+ alignmentLabel,
12911
+ alignmentToolbar
12990
12912
  ],
12991
- class: 'ck-table-form__background-row'
12913
+ class: 'ck-table-properties-form__alignment-row'
12992
12914
  })
12993
12915
  ]
12994
12916
  }));
12995
- // Alignment row.
12996
- this.children.add(new FormRowView(locale, {
12997
- labelView: alignmentLabel,
12998
- children: [
12999
- alignmentLabel,
13000
- alignmentToolbar
13001
- ],
13002
- class: 'ck-table-properties-form__alignment-row'
13003
- }));
13004
12917
  // Action row.
13005
12918
  this.children.add(new FormRowView(locale, {
13006
12919
  children: [
13007
- this.cancelButtonView,
13008
- this.saveButtonView
12920
+ this.saveButtonView,
12921
+ this.cancelButtonView
13009
12922
  ],
13010
12923
  class: 'ck-table-form__action-row'
13011
12924
  }));
@@ -13042,15 +12955,14 @@ function insertWrapperWithAlignment(writer, align, table) {
13042
12955
  });
13043
12956
  [
13044
12957
  this.borderStyleDropdown,
13045
- this.borderWidthInput,
13046
12958
  this.borderColorInput,
12959
+ this.borderWidthInput,
12960
+ this.backgroundInput,
13047
12961
  this.widthInput,
13048
12962
  this.heightInput,
13049
- this.backgroundInput,
13050
12963
  this.alignmentToolbar,
13051
- this.cancelButtonView,
13052
12964
  this.saveButtonView,
13053
- this.backButtonView
12965
+ this.cancelButtonView
13054
12966
  ].forEach((view)=>{
13055
12967
  // Register the view as focusable.
13056
12968
  this._focusables.add(view);
@@ -13085,7 +12997,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13085
12997
  width: defaultTableProperties.borderWidth,
13086
12998
  color: defaultTableProperties.borderColor
13087
12999
  };
13088
- const colorInputCreator = getLabeledColorInputCreator({
13000
+ const colorInputCreator = getLabeledColorInputCreator$1({
13089
13001
  colorConfig: this.options.borderColors,
13090
13002
  columns: 5,
13091
13003
  defaultColorValue: defaultBorder.color,
@@ -13098,7 +13010,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13098
13010
  const borderRowLabel = new LabelView(locale);
13099
13011
  borderRowLabel.text = t('Border');
13100
13012
  // -- Style ---------------------------------------------------
13101
- const styleLabels = getBorderStyleLabels(t);
13013
+ const styleLabels = getBorderStyleLabels$1(t);
13102
13014
  const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
13103
13015
  borderStyleDropdown.set({
13104
13016
  label: accessibleLabel,
@@ -13118,7 +13030,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13118
13030
  this.borderStyle = evt.source._borderStyleValue;
13119
13031
  });
13120
13032
  borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
13121
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
13033
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
13122
13034
  role: 'menu',
13123
13035
  ariaLabel: accessibleLabel
13124
13036
  });
@@ -13129,7 +13041,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13129
13041
  class: 'ck-table-form__border-width'
13130
13042
  });
13131
13043
  borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
13132
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
13044
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
13133
13045
  borderWidthInput.fieldView.on('input', ()=>{
13134
13046
  this.borderWidth = borderWidthInput.fieldView.element.value;
13135
13047
  });
@@ -13140,7 +13052,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13140
13052
  class: 'ck-table-form__border-color'
13141
13053
  });
13142
13054
  borderColorInput.fieldView.bind('value').to(this, 'borderColor');
13143
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
13055
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
13144
13056
  borderColorInput.fieldView.on('input', ()=>{
13145
13057
  this.borderColor = borderColorInput.fieldView.value;
13146
13058
  });
@@ -13148,12 +13060,12 @@ function insertWrapperWithAlignment(writer, align, table) {
13148
13060
  this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
13149
13061
  // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
13150
13062
  // See: https://github.com/ckeditor/ckeditor5/issues/6227.
13151
- if (!isBorderStyleSet(newValue)) {
13063
+ if (!isBorderStyleSet$2(newValue)) {
13152
13064
  this.borderColor = '';
13153
13065
  this.borderWidth = '';
13154
13066
  }
13155
13067
  // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
13156
- if (!isBorderStyleSet(oldValue)) {
13068
+ if (!isBorderStyleSet$2(oldValue)) {
13157
13069
  this.borderColor = defaultBorder.color;
13158
13070
  this.borderWidth = defaultBorder.width;
13159
13071
  }
@@ -13176,7 +13088,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13176
13088
  const backgroundRowLabel = new LabelView(locale);
13177
13089
  backgroundRowLabel.text = t('Background');
13178
13090
  // -- Background color input -----------------------------------
13179
- const backgroundInputCreator = getLabeledColorInputCreator({
13091
+ const backgroundInputCreator = getLabeledColorInputCreator$1({
13180
13092
  colorConfig: this.options.backgroundColors,
13181
13093
  columns: 5,
13182
13094
  defaultColorValue: this.options.defaultTableProperties.backgroundColor,
@@ -13258,7 +13170,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13258
13170
  const t = this.t;
13259
13171
  // -- Label ---------------------------------------------------
13260
13172
  const alignmentLabel = new LabelView(locale);
13261
- alignmentLabel.text = t('Table Alignment');
13173
+ alignmentLabel.text = t('Alignment');
13262
13174
  // -- Toolbar ---------------------------------------------------
13263
13175
  const alignmentToolbar = new ToolbarView(locale);
13264
13176
  alignmentToolbar.set({
@@ -13266,14 +13178,12 @@ function insertWrapperWithAlignment(writer, align, table) {
13266
13178
  isCompact: true,
13267
13179
  ariaLabel: t('Table alignment toolbar')
13268
13180
  });
13269
- fillToolbar({
13181
+ fillToolbar$1({
13270
13182
  view: this,
13271
13183
  icons: {
13272
13184
  left: IconObjectInlineLeft,
13273
13185
  center: IconObjectCenter,
13274
- right: IconObjectInlineRight,
13275
- blockLeft: IconObjectLeft,
13276
- blockRight: IconObjectRight
13186
+ right: IconObjectInlineRight
13277
13187
  },
13278
13188
  toolbar: alignmentToolbar,
13279
13189
  labels: this._alignmentLabels,
@@ -13304,7 +13214,8 @@ function insertWrapperWithAlignment(writer, align, table) {
13304
13214
  ];
13305
13215
  saveButtonView.set({
13306
13216
  label: t('Save'),
13307
- class: 'ck-button-action',
13217
+ icon: IconCheck,
13218
+ class: 'ck-button-save',
13308
13219
  type: 'submit',
13309
13220
  withText: true
13310
13221
  });
@@ -13313,6 +13224,8 @@ function insertWrapperWithAlignment(writer, align, table) {
13313
13224
  });
13314
13225
  cancelButtonView.set({
13315
13226
  label: t('Cancel'),
13227
+ icon: IconCancel,
13228
+ class: 'ck-button-cancel',
13316
13229
  withText: true
13317
13230
  });
13318
13231
  cancelButtonView.delegate('execute').to(this, 'cancel');
@@ -13321,56 +13234,37 @@ function insertWrapperWithAlignment(writer, align, table) {
13321
13234
  cancelButtonView
13322
13235
  };
13323
13236
  }
13324
- /**
13325
- * Creates a back button view that cancels the form.
13326
- */ _createBackButton() {
13327
- const t = this.locale.t;
13328
- const backButton = new ButtonView(this.locale);
13329
- backButton.set({
13330
- class: 'ck-button-back',
13331
- label: t('Back'),
13332
- icon: IconPreviousArrow,
13333
- tooltip: true
13334
- });
13335
- backButton.delegate('execute').to(this, 'cancel');
13336
- return backButton;
13337
- }
13338
13237
  /**
13339
13238
  * Provides localized labels for {@link #alignmentToolbar} buttons.
13340
13239
  */ get _alignmentLabels() {
13341
13240
  const locale = this.locale;
13342
13241
  const t = this.t;
13343
- const blockLeft = t('Align table to the left with no text wrapping');
13344
- const blockRight = t('Align table to the right with no text wrapping');
13345
- const left = t('Align table to the left with text wrapping');
13346
- const center = t('Center table with no text wrapping');
13347
- const right = t('Align table to the right with text wrapping');
13242
+ const left = t('Align table to the left');
13243
+ const center = t('Center table');
13244
+ const right = t('Align table to the right');
13348
13245
  // Returns object with a proper order of labels.
13349
13246
  if (locale.uiLanguageDirection === 'rtl') {
13350
13247
  return {
13351
13248
  right,
13249
+ center,
13250
+ left
13251
+ };
13252
+ } else {
13253
+ return {
13352
13254
  left,
13353
- blockRight,
13354
13255
  center,
13355
- blockLeft
13256
+ right
13356
13257
  };
13357
13258
  }
13358
- return {
13359
- blockLeft,
13360
- center,
13361
- blockRight,
13362
- left,
13363
- right
13364
- };
13365
13259
  }
13366
13260
  }
13367
- function isBorderStyleSet(value) {
13261
+ function isBorderStyleSet$2(value) {
13368
13262
  return value !== 'none';
13369
13263
  }
13370
13264
 
13371
- const ERROR_TEXT_TIMEOUT = 500;
13265
+ const ERROR_TEXT_TIMEOUT$2 = 500;
13372
13266
  // Map of view properties and related commands.
13373
- const propertyToCommandMap = {
13267
+ const propertyToCommandMap$2 = {
13374
13268
  borderStyle: 'tableBorderStyle',
13375
13269
  borderColor: 'tableBorderColor',
13376
13270
  borderWidth: 'tableBorderWidth',
@@ -13462,7 +13356,7 @@ const propertyToCommandMap = {
13462
13356
  tooltip: true
13463
13357
  });
13464
13358
  this.listenTo(view, 'execute', ()=>this._showView());
13465
- const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName));
13359
+ const commands = Object.values(propertyToCommandMap$2).map((commandName)=>editor.commands.get(commandName));
13466
13360
  view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
13467
13361
  return view;
13468
13362
  }
@@ -13572,7 +13466,7 @@ const propertyToCommandMap = {
13572
13466
  */ _fillViewFormFromCommandValues() {
13573
13467
  const commands = this.editor.commands;
13574
13468
  const borderStyleCommand = commands.get('tableBorderStyle');
13575
- Object.entries(propertyToCommandMap).map(([property, commandName])=>{
13469
+ Object.entries(propertyToCommandMap$2).map(([property, commandName])=>{
13576
13470
  const propertyKey = property;
13577
13471
  const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
13578
13472
  return [
@@ -13681,7 +13575,7 @@ const propertyToCommandMap = {
13681
13575
  const { commandName, viewField, validator, errorText } = options;
13682
13576
  const setErrorTextDebounced = debounce(()=>{
13683
13577
  viewField.errorText = errorText;
13684
- }, ERROR_TEXT_TIMEOUT);
13578
+ }, ERROR_TEXT_TIMEOUT$2);
13685
13579
  return (evt, propertyName, newValue)=>{
13686
13580
  setErrorTextDebounced.cancel();
13687
13581
  // Do not execute the command on initial call (opening the table properties view).
@@ -14122,5 +14016,2096 @@ const propertyToCommandMap = {
14122
14016
  }
14123
14017
  }
14124
14018
 
14125
- export { InsertColumnCommand, InsertRowCommand, InsertTableCommand, InsertTableLayoutCommand, MergeCellCommand, MergeCellsCommand, PlainTableOutput, RemoveColumnCommand, RemoveRowCommand, SelectColumnCommand, SelectRowCommand, SetHeaderColumnCommand, SetHeaderRowCommand, SplitCellCommand, Table, TableAlignmentCommand, TableBackgroundColorCommand, TableBorderColorCommand, TableBorderStyleCommand, TableBorderWidthCommand, TableCaption, TableCaptionEditing, TableCaptionUI, TableCellBackgroundColorCommand, TableCellBorderColorCommand, TableCellBorderStyleCommand, TableCellBorderWidthCommand, TableCellHeightCommand, TableCellHorizontalAlignmentCommand, TableCellPaddingCommand, TableCellProperties, TableCellPropertiesEditing, TableCellPropertiesUI, TableCellPropertiesView, TableCellPropertyCommand, TableCellTypeCommand, TableCellVerticalAlignmentCommand, TableCellWidthCommand, TableCellWidthEditing, TableClipboard, TableColumnResize, TableColumnResizeEditing, TableEditing, TableHeightCommand, TableKeyboard, TableLayout, TableLayoutEditing, TableLayoutUI, TableMouse, TableProperties, TablePropertiesEditing, TablePropertiesUI, TablePropertiesView, TablePropertyCommand, TableSelection, TableToolbar, TableTypeCommand, TableUI, TableUtils, TableWalker, TableWidthCommand, TableWidthsCommand, ToggleTableCaptionCommand, InsertTableView as _InsertTableView, COLUMN_MIN_WIDTH_AS_PERCENTAGE as _TABLE_COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS as _TABLE_COLUMN_MIN_WIDTH_IN_PIXELS, COLUMN_RESIZE_DISTANCE_THRESHOLD as _TABLE_COLUMN_RESIZE_DISTANCE_THRESHOLD, COLUMN_WIDTH_PRECISION as _TABLE_COLUMN_WIDTH_PRECISION, defaultColors as _TABLE_DEFAULT_COLORS, ColorInputView as _TableColorInputView, MouseEventsObserver as _TableMouseEventsObserver, addDefaultUnitToNumericValue as _addDefaultUnitToNumericValue, adjustLastColumnIndex as _adjustLastTableColumnIndex, adjustLastRowIndex as _adjustLastTableRowIndex, clamp as _clamp, colorFieldValidator as _colorTableFieldValidator, convertParagraphInTableCell as _convertParagraphInTableCell, createEmptyTableCell as _createEmptyTableCell, createFilledArray as _createFilledArray, cropTableToDimensions as _cropTableToDimensions, downcastTable as _downcastTable, downcastTableAttribute as _downcastTableAttribute, downcastAttributeToStyle as _downcastTableAttributeToStyle, downcastCell as _downcastTableCell, downcastTableResizedClass as _downcastTableResizedClass, downcastRow as _downcastTableRow, enableProperty$1 as _enableTableCellProperty, ensureParagraphInTableCell as _ensureParagraphInTableCell, fillToolbar as _fillTableOrCellToolbar, getBalloonCellPositionData as _getBalloonTableCellPositionData, getBalloonTablePositionData as _getBalloonTablePositionData, getBorderStyleLabels as _getBorderTableStyleLabels, getChangedResizedTables as _getChangedResizedTables, getDefaultValueAdjusted as _getDefaultTableValueAdjusted, getDomCellOuterWidth as _getDomTableCellOuterWidth, getElementWidthInPixels as _getElementWidthInPixels, getHorizontallyOverlappingCells as _getHorizontallyOverlappingTableCells, getLabeledColorInputCreator as _getLabeledTableColorInputCreator, getLocalizedColorErrorText as _getLocalizedTableColorErrorText, getLocalizedLengthErrorText as _getLocalizedTableLengthErrorText, getNormalizedDefaultProperties as _getNormalizedDefaultTableBaseProperties, getNormalizedDefaultCellProperties as _getNormalizedDefaultTableCellProperties, getNormalizedDefaultTableProperties as _getNormalizedDefaultTableProperties, getSelectedTableWidget as _getSelectedTableWidget, getSelectionAffectedTable as _getSelectionAffectedTable, getSelectionAffectedTableWidget as _getSelectionAffectedTableWidget, getSingleValue as _getTableBorderBoxSingleValue, getCaptionFromTableModelElement as _getTableCaptionFromModelElement, getCaptionFromModelSelection as _getTableCaptionFromModelSelection, getColumnEdgesIndexes as _getTableColumnEdgesIndexes, getTableColumnElements as _getTableColumnElements, getColumnGroupElement as _getTableColumnGroupElement, getColumnMinWidthAsPercentage as _getTableColumnMinWidthAsPercentage, getTableColumnsWidths as _getTableColumnsWidths, getBorderStyleDefinitions as _getTableOrCellBorderStyleDefinitions, getTableWidgetAncestor as _getTableWidgetAncestor, getTableWidthInPixels as _getTableWidthInPixels, getVerticallyOverlappingCells as _getVerticallyOverlappingTableCells, injectTableCaptionPostFixer as _injectTableCaptionPostFixer, injectTableCellParagraphPostFixer as _injectTableCellParagraphPostFixer, injectTableLayoutPostFixer as _injectTableLayoutPostFixer, isSingleParagraphWithoutAttributes as _isSingleTableParagraphWithoutAttributes, isHeadingColumnCell as _isTableHeadingColumnCell, isTable as _isTableModelElement, lengthFieldValidator as _lengthTableFieldValidator, lineWidthFieldValidator as _lineWidthTableFieldValidator, matchTableCaptionViewElement as _matchTableCaptionViewElement, normalizeColumnWidths as _normalizeTableColumnWidths, removeEmptyColumns as _removeEmptyTableColumns, removeEmptyRows as _removeEmptyTableRows, removeEmptyRowsColumns as _removeEmptyTableRowsColumns, repositionContextualBalloon as _repositionTableContextualBalloon, skipEmptyTableRow as _skipEmptyTableRow, splitHorizontally as _splitTableCellHorizontally, splitVertically as _splitTableCellVertically, sumArray as _sumArray, tableCellRefreshHandler as _tableCellRefreshHandler, tableHeadingsRefreshHandler as _tableHeadingsRefreshHandler, toPrecision as _toPrecision, translateColSpanAttribute as _translateTableColspanAttribute, trimTableCellIfNeeded as _trimTableCellIfNeeded, upcastStyleToAttribute as _upcastNormalizedTableStyleToAttribute, upcastTable as _upcastTable, upcastBorderStyles as _upcastTableBorderStyles, upcastColgroupElement as _upcastTableColgroupElement, upcastTableFigure as _upcastTableFigure, updateColumnElements as _updateTableColumnElements, updateNumericAttribute as _updateTableNumericAttribute, isTableHeaderCellType };
14019
+ /**
14020
+ * Returns an object containing pairs of CSS border style values and their localized UI
14021
+ * labels. Used by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
14022
+ * and {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView}.
14023
+ *
14024
+ * @internal
14025
+ * @param t The "t" function provided by the editor that is used to localize strings.
14026
+ */ function getBorderStyleLabels(t) {
14027
+ return {
14028
+ none: t('None'),
14029
+ solid: t('Solid'),
14030
+ dotted: t('Dotted'),
14031
+ dashed: t('Dashed'),
14032
+ double: t('Double'),
14033
+ groove: t('Groove'),
14034
+ ridge: t('Ridge'),
14035
+ inset: t('Inset'),
14036
+ outset: t('Outset')
14037
+ };
14038
+ }
14039
+ /**
14040
+ * Generates item definitions for a UI dropdown that allows changing the border style of a table or a table cell.
14041
+ *
14042
+ * @internal
14043
+ * @param defaultStyle The default border.
14044
+ */ function getBorderStyleDefinitions(view, defaultStyle) {
14045
+ const itemDefinitions = new Collection();
14046
+ const styleLabels = getBorderStyleLabels(view.t);
14047
+ for(const style in styleLabels){
14048
+ const definition = {
14049
+ type: 'button',
14050
+ model: new UIModel({
14051
+ _borderStyleValue: style,
14052
+ label: styleLabels[style],
14053
+ role: 'menuitemradio',
14054
+ withText: true
14055
+ })
14056
+ };
14057
+ if (style === 'none') {
14058
+ definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
14059
+ if (defaultStyle === 'none') {
14060
+ return !value;
14061
+ }
14062
+ return value === style;
14063
+ });
14064
+ } else {
14065
+ definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
14066
+ return value === style;
14067
+ });
14068
+ }
14069
+ itemDefinitions.add(definition);
14070
+ }
14071
+ return itemDefinitions;
14072
+ }
14073
+ /**
14074
+ * A helper that fills a toolbar with buttons that:
14075
+ *
14076
+ * * have some labels,
14077
+ * * have some icons,
14078
+ * * set a certain UI view property value upon execution.
14079
+ *
14080
+ * @internal
14081
+ * @param options Configuration options
14082
+ * @param options.view The view that has the observable property.
14083
+ * @param options.icons Object with button icons.
14084
+ * @param options.toolbar The toolbar to fill with buttons.
14085
+ * @param options.labels Object with button labels.
14086
+ * @param options.propertyName The name of the observable property in the view.
14087
+ * @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
14088
+ * @param options.defaultValue Default value for the property.
14089
+ */ function fillToolbar(options) {
14090
+ const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
14091
+ for(const name in labels){
14092
+ const button = new ButtonView(view.locale);
14093
+ button.set({
14094
+ role: 'radio',
14095
+ isToggleable: true,
14096
+ label: labels[name],
14097
+ icon: icons[name],
14098
+ tooltip: labels[name]
14099
+ });
14100
+ // If specified the `nameToValue()` callback, map the value based on the option's name.
14101
+ const buttonValue = nameToValue ? nameToValue(name) : name;
14102
+ button.bind('isOn').to(view, propertyName, (value)=>{
14103
+ // `value` comes from `view[ propertyName ]`.
14104
+ let valueToCompare = value;
14105
+ // If it's empty, and the `defaultValue` is specified, use it instead.
14106
+ if (value === '' && defaultValue) {
14107
+ valueToCompare = defaultValue;
14108
+ }
14109
+ return buttonValue === valueToCompare;
14110
+ });
14111
+ button.on('execute', ()=>{
14112
+ // Allow toggling alignment if there is no default value specified (especially for layout tables).
14113
+ if (!defaultValue && buttonValue && view[propertyName] === buttonValue) {
14114
+ view[propertyName] = undefined;
14115
+ } else {
14116
+ view[propertyName] = buttonValue;
14117
+ }
14118
+ });
14119
+ toolbar.items.add(button);
14120
+ }
14121
+ }
14122
+ /**
14123
+ * Returns a creator for a color input with a label.
14124
+ *
14125
+ * For given options, it returns a function that creates an instance of a
14126
+ * {@link module:table/ui/colorinputview~ColorInputView color input} logically related to
14127
+ * a {@link module:ui/labeledfield/labeledfieldview~LabeledFieldView labeled view} in the DOM.
14128
+ *
14129
+ * The helper does the following:
14130
+ *
14131
+ * * It sets the color input `id` and `ariaDescribedById` attributes.
14132
+ * * It binds the color input `isReadOnly` to the labeled view.
14133
+ * * It binds the color input `hasError` to the labeled view.
14134
+ * * It enables a logic that cleans up the error when the user starts typing in the color input.
14135
+ *
14136
+ * Usage:
14137
+ *
14138
+ * ```ts
14139
+ * const colorInputCreator = getLabeledColorInputCreator( {
14140
+ * colorConfig: [ ... ],
14141
+ * columns: 3,
14142
+ * } );
14143
+ *
14144
+ * const labeledInputView = new LabeledFieldView( locale, colorInputCreator );
14145
+ * console.log( labeledInputView.view ); // A color input instance.
14146
+ * ```
14147
+ *
14148
+ * @internal
14149
+ * @param options Color input options.
14150
+ * @param options.colorConfig The configuration of the color palette displayed in the input's dropdown.
14151
+ * @param options.columns The configuration of the number of columns the color palette consists of in the input's dropdown.
14152
+ * @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
14153
+ * the "Restore default" button. Instead of clearing the input field, the default color value will be set.
14154
+ * @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
14155
+ */ function getLabeledColorInputCreator(options) {
14156
+ return (labeledFieldView, viewUid, statusUid)=>{
14157
+ const colorInputView = new ColorInputView(labeledFieldView.locale, {
14158
+ colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
14159
+ columns: options.columns,
14160
+ defaultColorValue: options.defaultColorValue,
14161
+ colorPickerConfig: options.colorPickerConfig
14162
+ });
14163
+ colorInputView.inputView.set({
14164
+ id: viewUid,
14165
+ ariaDescribedById: statusUid
14166
+ });
14167
+ colorInputView.bind('isReadOnly').to(labeledFieldView, 'isEnabled', (value)=>!value);
14168
+ colorInputView.bind('hasError').to(labeledFieldView, 'errorText', (value)=>!!value);
14169
+ colorInputView.on('input', ()=>{
14170
+ // UX: Make the error text disappear and disable the error indicator as the user
14171
+ // starts fixing the errors.
14172
+ labeledFieldView.errorText = null;
14173
+ });
14174
+ labeledFieldView.bind('isEmpty', 'isFocused').to(colorInputView);
14175
+ return colorInputView;
14176
+ };
14177
+ }
14178
+ function colorConfigToColorGridDefinitions(colorConfig) {
14179
+ return colorConfig.map((item)=>({
14180
+ color: item.model,
14181
+ label: item.label,
14182
+ options: {
14183
+ hasBorder: item.hasBorder
14184
+ }
14185
+ }));
14186
+ }
14187
+
14188
+ /**
14189
+ * The class representing a table properties form, allowing users to customize
14190
+ * certain style aspects of a table, for instance, border, background color, alignment, etc..
14191
+ */ class TablePropertiesViewExperimental extends View {
14192
+ /**
14193
+ * Options passed to the view. See {@link #constructor} to learn more.
14194
+ */ options;
14195
+ /**
14196
+ * Tracks information about the DOM focus in the form.
14197
+ */ focusTracker;
14198
+ /**
14199
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
14200
+ */ keystrokes;
14201
+ /**
14202
+ * A collection of child views in the form.
14203
+ */ children;
14204
+ /**
14205
+ * A dropdown that allows selecting the style of the table border.
14206
+ */ borderStyleDropdown;
14207
+ /**
14208
+ * An input that allows specifying the width of the table border.
14209
+ */ borderWidthInput;
14210
+ /**
14211
+ * An input that allows specifying the color of the table border.
14212
+ */ borderColorInput;
14213
+ /**
14214
+ * An input that allows specifying the table background color.
14215
+ */ backgroundInput;
14216
+ /**
14217
+ * An input that allows specifying the table width.
14218
+ */ widthInput;
14219
+ /**
14220
+ * An input that allows specifying the table height.
14221
+ */ heightInput;
14222
+ /**
14223
+ * A toolbar with buttons that allow changing the alignment of an entire table.
14224
+ */ alignmentToolbar;
14225
+ /**
14226
+ * The "Save" button view.
14227
+ */ saveButtonView;
14228
+ /**
14229
+ * The "Cancel" button view.
14230
+ */ cancelButtonView;
14231
+ /**
14232
+ * The Back button view displayed in the header.
14233
+ */ backButtonView;
14234
+ /**
14235
+ * A collection of views that can be focused in the form.
14236
+ */ _focusables;
14237
+ /**
14238
+ * Helps cycling over {@link #_focusables} in the form.
14239
+ */ _focusCycler;
14240
+ /**
14241
+ * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
14242
+ * @param options Additional configuration of the view.
14243
+ */ constructor(locale, options){
14244
+ super(locale);
14245
+ this.set({
14246
+ borderStyle: '',
14247
+ borderWidth: '',
14248
+ borderColor: '',
14249
+ backgroundColor: '',
14250
+ width: '',
14251
+ height: '',
14252
+ alignment: ''
14253
+ });
14254
+ this.options = options;
14255
+ const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
14256
+ const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
14257
+ const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
14258
+ const { alignmentToolbar, alignmentLabel } = this._createAlignmentFields();
14259
+ this.focusTracker = new FocusTracker();
14260
+ this.keystrokes = new KeystrokeHandler();
14261
+ this.children = this.createCollection();
14262
+ this.borderStyleDropdown = borderStyleDropdown;
14263
+ this.borderWidthInput = borderWidthInput;
14264
+ this.borderColorInput = borderColorInput;
14265
+ this.backgroundInput = backgroundInput;
14266
+ this.widthInput = widthInput;
14267
+ this.heightInput = heightInput;
14268
+ this.alignmentToolbar = alignmentToolbar;
14269
+ // Defer creating to make sure other fields are present and the Save button can
14270
+ // bind its #isEnabled to their error messages so there's no way to save unless all
14271
+ // fields are valid.
14272
+ const { saveButtonView, cancelButtonView } = this._createActionButtons();
14273
+ this.saveButtonView = saveButtonView;
14274
+ this.cancelButtonView = cancelButtonView;
14275
+ this.backButtonView = this._createBackButton();
14276
+ this._focusables = new ViewCollection();
14277
+ this._focusCycler = new FocusCycler({
14278
+ focusables: this._focusables,
14279
+ focusTracker: this.focusTracker,
14280
+ keystrokeHandler: this.keystrokes,
14281
+ actions: {
14282
+ // Navigate form fields backwards using the Shift + Tab keystroke.
14283
+ focusPrevious: 'shift + tab',
14284
+ // Navigate form fields forwards using the Tab key.
14285
+ focusNext: 'tab'
14286
+ }
14287
+ });
14288
+ // Form header.
14289
+ const headerView = new FormHeaderView(locale, {
14290
+ label: this.t('Table properties')
14291
+ });
14292
+ headerView.children.add(this.backButtonView, 0);
14293
+ this.children.add(headerView);
14294
+ // Border row.
14295
+ this.children.add(new FormRowView(locale, {
14296
+ labelView: borderRowLabel,
14297
+ children: [
14298
+ borderRowLabel,
14299
+ borderStyleDropdown,
14300
+ borderWidthInput,
14301
+ borderColorInput
14302
+ ],
14303
+ class: 'ck-table-form__border-row'
14304
+ }));
14305
+ this.children.add(new FormRowView(locale, {
14306
+ children: [
14307
+ // Dimensions row.
14308
+ new FormRowView(locale, {
14309
+ labelView: dimensionsLabel,
14310
+ children: [
14311
+ dimensionsLabel,
14312
+ widthInput,
14313
+ operatorLabel,
14314
+ heightInput
14315
+ ],
14316
+ class: 'ck-table-form__dimensions-row'
14317
+ }),
14318
+ // Background row.
14319
+ new FormRowView(locale, {
14320
+ labelView: backgroundRowLabel,
14321
+ children: [
14322
+ backgroundRowLabel,
14323
+ backgroundInput
14324
+ ],
14325
+ class: 'ck-table-form__background-row'
14326
+ })
14327
+ ]
14328
+ }));
14329
+ // Alignment row.
14330
+ this.children.add(new FormRowView(locale, {
14331
+ labelView: alignmentLabel,
14332
+ children: [
14333
+ alignmentLabel,
14334
+ alignmentToolbar
14335
+ ],
14336
+ class: 'ck-table-properties-form__alignment-row'
14337
+ }));
14338
+ // Action row.
14339
+ this.children.add(new FormRowView(locale, {
14340
+ children: [
14341
+ this.cancelButtonView,
14342
+ this.saveButtonView
14343
+ ],
14344
+ class: 'ck-table-form__action-row'
14345
+ }));
14346
+ this.setTemplate({
14347
+ tag: 'form',
14348
+ attributes: {
14349
+ class: [
14350
+ 'ck',
14351
+ 'ck-form',
14352
+ 'ck-table-form',
14353
+ 'ck-table-properties-form',
14354
+ 'ck-table-properties-form_experimental'
14355
+ ],
14356
+ // https://github.com/ckeditor/ckeditor5-link/issues/90
14357
+ tabindex: '-1'
14358
+ },
14359
+ children: this.children
14360
+ });
14361
+ }
14362
+ /**
14363
+ * @inheritDoc
14364
+ */ render() {
14365
+ super.render();
14366
+ // Enable the "submit" event for this view. It can be triggered by the #saveButtonView
14367
+ // which is of the "submit" DOM "type".
14368
+ submitHandler({
14369
+ view: this
14370
+ });
14371
+ // Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
14372
+ [
14373
+ this.borderColorInput,
14374
+ this.backgroundInput
14375
+ ].forEach((view)=>{
14376
+ this._focusCycler.chain(view.fieldView.focusCycler);
14377
+ });
14378
+ [
14379
+ this.borderStyleDropdown,
14380
+ this.borderWidthInput,
14381
+ this.borderColorInput,
14382
+ this.widthInput,
14383
+ this.heightInput,
14384
+ this.backgroundInput,
14385
+ this.alignmentToolbar,
14386
+ this.cancelButtonView,
14387
+ this.saveButtonView,
14388
+ this.backButtonView
14389
+ ].forEach((view)=>{
14390
+ // Register the view as focusable.
14391
+ this._focusables.add(view);
14392
+ // Register the view in the focus tracker.
14393
+ this.focusTracker.add(view.element);
14394
+ });
14395
+ // Mainly for closing using "Esc" and navigation using "Tab".
14396
+ this.keystrokes.listenTo(this.element);
14397
+ }
14398
+ /**
14399
+ * @inheritDoc
14400
+ */ destroy() {
14401
+ super.destroy();
14402
+ this.focusTracker.destroy();
14403
+ this.keystrokes.destroy();
14404
+ }
14405
+ /**
14406
+ * Focuses the fist focusable field in the form.
14407
+ */ focus() {
14408
+ this._focusCycler.focusFirst();
14409
+ }
14410
+ /**
14411
+ * Creates the following form fields:
14412
+ *
14413
+ * * {@link #borderStyleDropdown},
14414
+ * * {@link #borderWidthInput},
14415
+ * * {@link #borderColorInput}.
14416
+ */ _createBorderFields() {
14417
+ const defaultTableProperties = this.options.defaultTableProperties;
14418
+ const defaultBorder = {
14419
+ style: defaultTableProperties.borderStyle,
14420
+ width: defaultTableProperties.borderWidth,
14421
+ color: defaultTableProperties.borderColor
14422
+ };
14423
+ const colorInputCreator = getLabeledColorInputCreator({
14424
+ colorConfig: this.options.borderColors,
14425
+ columns: 5,
14426
+ defaultColorValue: defaultBorder.color,
14427
+ colorPickerConfig: this.options.colorPickerConfig
14428
+ });
14429
+ const locale = this.locale;
14430
+ const t = this.t;
14431
+ const accessibleLabel = t('Style');
14432
+ // -- Group label ---------------------------------------------
14433
+ const borderRowLabel = new LabelView(locale);
14434
+ borderRowLabel.text = t('Border');
14435
+ // -- Style ---------------------------------------------------
14436
+ const styleLabels = getBorderStyleLabels(t);
14437
+ const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
14438
+ borderStyleDropdown.set({
14439
+ label: accessibleLabel,
14440
+ class: 'ck-table-form__border-style'
14441
+ });
14442
+ borderStyleDropdown.fieldView.buttonView.set({
14443
+ ariaLabel: accessibleLabel,
14444
+ ariaLabelledBy: undefined,
14445
+ isOn: false,
14446
+ withText: true,
14447
+ tooltip: accessibleLabel
14448
+ });
14449
+ borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
14450
+ return styleLabels[value ? value : 'none'];
14451
+ });
14452
+ borderStyleDropdown.fieldView.on('execute', (evt)=>{
14453
+ this.borderStyle = evt.source._borderStyleValue;
14454
+ });
14455
+ borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
14456
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
14457
+ role: 'menu',
14458
+ ariaLabel: accessibleLabel
14459
+ });
14460
+ // -- Width ---------------------------------------------------
14461
+ const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
14462
+ borderWidthInput.set({
14463
+ label: t('Width'),
14464
+ class: 'ck-table-form__border-width'
14465
+ });
14466
+ borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
14467
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
14468
+ borderWidthInput.fieldView.on('input', ()=>{
14469
+ this.borderWidth = borderWidthInput.fieldView.element.value;
14470
+ });
14471
+ // -- Color ---------------------------------------------------
14472
+ const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
14473
+ borderColorInput.set({
14474
+ label: t('Color'),
14475
+ class: 'ck-table-form__border-color'
14476
+ });
14477
+ borderColorInput.fieldView.bind('value').to(this, 'borderColor');
14478
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
14479
+ borderColorInput.fieldView.on('input', ()=>{
14480
+ this.borderColor = borderColorInput.fieldView.value;
14481
+ });
14482
+ // Reset the border color and width fields depending on the `border-style` value.
14483
+ this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
14484
+ // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
14485
+ // See: https://github.com/ckeditor/ckeditor5/issues/6227.
14486
+ if (!isBorderStyleSet$1(newValue)) {
14487
+ this.borderColor = '';
14488
+ this.borderWidth = '';
14489
+ }
14490
+ // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
14491
+ if (!isBorderStyleSet$1(oldValue)) {
14492
+ this.borderColor = defaultBorder.color;
14493
+ this.borderWidth = defaultBorder.width;
14494
+ }
14495
+ });
14496
+ return {
14497
+ borderRowLabel,
14498
+ borderStyleDropdown,
14499
+ borderColorInput,
14500
+ borderWidthInput
14501
+ };
14502
+ }
14503
+ /**
14504
+ * Creates the following form fields:
14505
+ *
14506
+ * * {@link #backgroundInput}.
14507
+ */ _createBackgroundFields() {
14508
+ const locale = this.locale;
14509
+ const t = this.t;
14510
+ // -- Group label ---------------------------------------------
14511
+ const backgroundRowLabel = new LabelView(locale);
14512
+ backgroundRowLabel.text = t('Background');
14513
+ // -- Background color input -----------------------------------
14514
+ const backgroundInputCreator = getLabeledColorInputCreator({
14515
+ colorConfig: this.options.backgroundColors,
14516
+ columns: 5,
14517
+ defaultColorValue: this.options.defaultTableProperties.backgroundColor,
14518
+ colorPickerConfig: this.options.colorPickerConfig
14519
+ });
14520
+ const backgroundInput = new LabeledFieldView(locale, backgroundInputCreator);
14521
+ backgroundInput.set({
14522
+ label: t('Color'),
14523
+ class: 'ck-table-properties-form__background'
14524
+ });
14525
+ backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
14526
+ backgroundInput.fieldView.on('input', ()=>{
14527
+ this.backgroundColor = backgroundInput.fieldView.value;
14528
+ });
14529
+ return {
14530
+ backgroundRowLabel,
14531
+ backgroundInput
14532
+ };
14533
+ }
14534
+ /**
14535
+ * Creates the following form fields:
14536
+ *
14537
+ * * {@link #widthInput},
14538
+ * * {@link #heightInput}.
14539
+ */ _createDimensionFields() {
14540
+ const locale = this.locale;
14541
+ const t = this.t;
14542
+ // -- Label ---------------------------------------------------
14543
+ const dimensionsLabel = new LabelView(locale);
14544
+ dimensionsLabel.text = t('Dimensions');
14545
+ // -- Width ---------------------------------------------------
14546
+ const widthInput = new LabeledFieldView(locale, createLabeledInputText);
14547
+ widthInput.set({
14548
+ label: t('Width'),
14549
+ class: 'ck-table-form__dimensions-row__width'
14550
+ });
14551
+ widthInput.fieldView.bind('value').to(this, 'width');
14552
+ widthInput.fieldView.on('input', ()=>{
14553
+ this.width = widthInput.fieldView.element.value;
14554
+ });
14555
+ // -- Operator ---------------------------------------------------
14556
+ const operatorLabel = new View(locale);
14557
+ operatorLabel.setTemplate({
14558
+ tag: 'span',
14559
+ attributes: {
14560
+ class: [
14561
+ 'ck-table-form__dimension-operator'
14562
+ ]
14563
+ },
14564
+ children: [
14565
+ {
14566
+ text: '×'
14567
+ }
14568
+ ]
14569
+ });
14570
+ // -- Height ---------------------------------------------------
14571
+ const heightInput = new LabeledFieldView(locale, createLabeledInputText);
14572
+ heightInput.set({
14573
+ label: t('Height'),
14574
+ class: 'ck-table-form__dimensions-row__height'
14575
+ });
14576
+ heightInput.fieldView.bind('value').to(this, 'height');
14577
+ heightInput.fieldView.on('input', ()=>{
14578
+ this.height = heightInput.fieldView.element.value;
14579
+ });
14580
+ return {
14581
+ dimensionsLabel,
14582
+ widthInput,
14583
+ operatorLabel,
14584
+ heightInput
14585
+ };
14586
+ }
14587
+ /**
14588
+ * Creates the following form fields:
14589
+ *
14590
+ * * {@link #alignmentToolbar}.
14591
+ */ _createAlignmentFields() {
14592
+ const locale = this.locale;
14593
+ const t = this.t;
14594
+ // -- Label ---------------------------------------------------
14595
+ const alignmentLabel = new LabelView(locale);
14596
+ alignmentLabel.text = t('Table Alignment');
14597
+ // -- Toolbar ---------------------------------------------------
14598
+ const alignmentToolbar = new ToolbarView(locale);
14599
+ alignmentToolbar.set({
14600
+ role: 'radiogroup',
14601
+ isCompact: true,
14602
+ ariaLabel: t('Table alignment toolbar')
14603
+ });
14604
+ fillToolbar({
14605
+ view: this,
14606
+ icons: {
14607
+ left: IconObjectInlineLeft,
14608
+ center: IconObjectCenter,
14609
+ right: IconObjectInlineRight,
14610
+ blockLeft: IconObjectLeft,
14611
+ blockRight: IconObjectRight
14612
+ },
14613
+ toolbar: alignmentToolbar,
14614
+ labels: this._alignmentLabels,
14615
+ propertyName: 'alignment',
14616
+ defaultValue: this.options.defaultTableProperties.alignment
14617
+ });
14618
+ return {
14619
+ alignmentLabel,
14620
+ alignmentToolbar
14621
+ };
14622
+ }
14623
+ /**
14624
+ * Creates the following form controls:
14625
+ *
14626
+ * * {@link #saveButtonView},
14627
+ * * {@link #cancelButtonView}.
14628
+ */ _createActionButtons() {
14629
+ const locale = this.locale;
14630
+ const t = this.t;
14631
+ const saveButtonView = new ButtonView(locale);
14632
+ const cancelButtonView = new ButtonView(locale);
14633
+ const fieldsThatShouldValidateToSave = [
14634
+ this.borderWidthInput,
14635
+ this.borderColorInput,
14636
+ this.backgroundInput,
14637
+ this.widthInput,
14638
+ this.heightInput
14639
+ ];
14640
+ saveButtonView.set({
14641
+ label: t('Save'),
14642
+ class: 'ck-button-action',
14643
+ type: 'submit',
14644
+ withText: true
14645
+ });
14646
+ saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
14647
+ return errorTexts.every((errorText)=>!errorText);
14648
+ });
14649
+ cancelButtonView.set({
14650
+ label: t('Cancel'),
14651
+ withText: true
14652
+ });
14653
+ cancelButtonView.delegate('execute').to(this, 'cancel');
14654
+ return {
14655
+ saveButtonView,
14656
+ cancelButtonView
14657
+ };
14658
+ }
14659
+ /**
14660
+ * Creates a back button view that cancels the form.
14661
+ */ _createBackButton() {
14662
+ const t = this.locale.t;
14663
+ const backButton = new ButtonView(this.locale);
14664
+ backButton.set({
14665
+ class: 'ck-button-back',
14666
+ label: t('Back'),
14667
+ icon: IconPreviousArrow,
14668
+ tooltip: true
14669
+ });
14670
+ backButton.delegate('execute').to(this, 'cancel');
14671
+ return backButton;
14672
+ }
14673
+ /**
14674
+ * Provides localized labels for {@link #alignmentToolbar} buttons.
14675
+ */ get _alignmentLabels() {
14676
+ const locale = this.locale;
14677
+ const t = this.t;
14678
+ const blockLeft = t('Align table to the left with no text wrapping');
14679
+ const blockRight = t('Align table to the right with no text wrapping');
14680
+ const left = t('Align table to the left with text wrapping');
14681
+ const center = t('Center table with no text wrapping');
14682
+ const right = t('Align table to the right with text wrapping');
14683
+ // Returns object with a proper order of labels.
14684
+ if (locale.uiLanguageDirection === 'rtl') {
14685
+ return {
14686
+ right,
14687
+ left,
14688
+ blockRight,
14689
+ center,
14690
+ blockLeft
14691
+ };
14692
+ }
14693
+ return {
14694
+ blockLeft,
14695
+ center,
14696
+ blockRight,
14697
+ left,
14698
+ right
14699
+ };
14700
+ }
14701
+ }
14702
+ function isBorderStyleSet$1(value) {
14703
+ return value !== 'none';
14704
+ }
14705
+
14706
+ const ERROR_TEXT_TIMEOUT$1 = 500;
14707
+ // Map of view properties and related commands.
14708
+ const propertyToCommandMap$1 = {
14709
+ borderStyle: 'tableBorderStyle',
14710
+ borderColor: 'tableBorderColor',
14711
+ borderWidth: 'tableBorderWidth',
14712
+ backgroundColor: 'tableBackgroundColor',
14713
+ width: 'tableWidth',
14714
+ height: 'tableHeight',
14715
+ alignment: 'tableAlignment'
14716
+ };
14717
+ /**
14718
+ * The table properties UI plugin. It introduces the `'tableProperties'` button
14719
+ * that opens a form allowing to specify visual styling of an entire table.
14720
+ *
14721
+ * It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
14722
+ */ class TablePropertiesUIExperimental extends Plugin {
14723
+ /**
14724
+ * The default table properties.
14725
+ */ _defaultContentTableProperties;
14726
+ /**
14727
+ * The default layout table properties.
14728
+ */ _defaultLayoutTableProperties;
14729
+ /**
14730
+ * The contextual balloon plugin instance.
14731
+ */ _balloon;
14732
+ /**
14733
+ * The properties form view displayed inside the balloon.
14734
+ */ view = null;
14735
+ /**
14736
+ * The properties form view displayed inside the balloon (content table).
14737
+ */ _viewWithContentTableDefaults = null;
14738
+ /**
14739
+ * The properties form view displayed inside the balloon (layout table).
14740
+ */ _viewWithLayoutTableDefaults = null;
14741
+ /**
14742
+ * The batch used to undo all changes made by the form (which are live, as the user types)
14743
+ * when "Cancel" was pressed. Each time the view is shown, a new batch is created.
14744
+ */ _undoStepBatch;
14745
+ /**
14746
+ * Flag used to indicate whether view is ready to execute update commands
14747
+ * (it finished loading initial data).
14748
+ */ _isReady;
14749
+ /**
14750
+ * @inheritDoc
14751
+ */ static get requires() {
14752
+ return [
14753
+ ContextualBalloon
14754
+ ];
14755
+ }
14756
+ /**
14757
+ * @inheritDoc
14758
+ */ static get pluginName() {
14759
+ return 'TablePropertiesUIExperimental';
14760
+ }
14761
+ /**
14762
+ * @inheritDoc
14763
+ */ static get isOfficialPlugin() {
14764
+ return true;
14765
+ }
14766
+ /**
14767
+ * @inheritDoc
14768
+ */ constructor(editor){
14769
+ super(editor);
14770
+ editor.config.define('table.tableProperties', {
14771
+ borderColors: defaultColors,
14772
+ backgroundColors: defaultColors
14773
+ });
14774
+ }
14775
+ /**
14776
+ * @inheritDoc
14777
+ */ init() {
14778
+ const editor = this.editor;
14779
+ this._defaultContentTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
14780
+ includeAlignmentProperty: true
14781
+ });
14782
+ this._defaultLayoutTableProperties = getNormalizedDefaultProperties();
14783
+ this._balloon = editor.plugins.get(ContextualBalloon);
14784
+ editor.ui.componentFactory.add('tableProperties', ()=>this._createTablePropertiesButton());
14785
+ }
14786
+ /**
14787
+ * Creates the table properties button.
14788
+ *
14789
+ * @internal
14790
+ */ _createTablePropertiesButton() {
14791
+ const editor = this.editor;
14792
+ const t = editor.t;
14793
+ const view = new ButtonView(editor.locale);
14794
+ view.set({
14795
+ label: t('Table properties'),
14796
+ icon: IconTableProperties,
14797
+ tooltip: true
14798
+ });
14799
+ this.listenTo(view, 'execute', ()=>this._showView());
14800
+ const commands = Object.values(propertyToCommandMap$1).map((commandName)=>editor.commands.get(commandName));
14801
+ view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
14802
+ return view;
14803
+ }
14804
+ /**
14805
+ * @inheritDoc
14806
+ */ destroy() {
14807
+ super.destroy();
14808
+ // Destroy created UI components as they are not automatically destroyed.
14809
+ // See https://github.com/ckeditor/ckeditor5/issues/1341.
14810
+ if (this.view) {
14811
+ this.view.destroy();
14812
+ }
14813
+ }
14814
+ /**
14815
+ * Creates the {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView} instance.
14816
+ *
14817
+ * @returns The table properties form view instance.
14818
+ */ _createPropertiesView(defaultTableProperties) {
14819
+ const editor = this.editor;
14820
+ const config = editor.config.get('table.tableProperties');
14821
+ const borderColorsConfig = normalizeColorOptions(config.borderColors);
14822
+ const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
14823
+ const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
14824
+ const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
14825
+ const hasColorPicker = config.colorPicker !== false;
14826
+ const view = new TablePropertiesViewExperimental(editor.locale, {
14827
+ borderColors: localizedBorderColors,
14828
+ backgroundColors: localizedBackgroundColors,
14829
+ defaultTableProperties,
14830
+ colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
14831
+ });
14832
+ const t = editor.t;
14833
+ // Render the view so its #element is available for the clickOutsideHandler.
14834
+ view.render();
14835
+ this.listenTo(view, 'submit', ()=>{
14836
+ this._hideView();
14837
+ });
14838
+ this.listenTo(view, 'cancel', ()=>{
14839
+ // https://github.com/ckeditor/ckeditor5/issues/6180
14840
+ if (this._undoStepBatch.operations.length) {
14841
+ editor.execute('undo', this._undoStepBatch);
14842
+ }
14843
+ this._hideView();
14844
+ });
14845
+ // Close the balloon on Esc key press.
14846
+ view.keystrokes.set('Esc', (data, cancel)=>{
14847
+ this._hideView();
14848
+ cancel();
14849
+ });
14850
+ // Close on click outside of balloon panel element.
14851
+ clickOutsideHandler({
14852
+ emitter: view,
14853
+ activator: ()=>this._isViewInBalloon,
14854
+ contextElements: [
14855
+ this._balloon.view.element
14856
+ ],
14857
+ callback: ()=>this._hideView()
14858
+ });
14859
+ const colorErrorText = getLocalizedColorErrorText(t);
14860
+ const lengthErrorText = getLocalizedLengthErrorText(t);
14861
+ // Create the "UI -> editor data" binding.
14862
+ // These listeners update the editor data (via table commands) when any observable
14863
+ // property of the view has changed. They also validate the value and display errors in the UI
14864
+ // when necessary. This makes the view live, which means the changes are
14865
+ // visible in the editing as soon as the user types or changes fields' values.
14866
+ view.on('change:borderStyle', this._getPropertyChangeCallback('tableBorderStyle'));
14867
+ view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
14868
+ viewField: view.borderColorInput,
14869
+ commandName: 'tableBorderColor',
14870
+ errorText: colorErrorText,
14871
+ validator: colorFieldValidator
14872
+ }));
14873
+ view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
14874
+ viewField: view.borderWidthInput,
14875
+ commandName: 'tableBorderWidth',
14876
+ errorText: lengthErrorText,
14877
+ validator: lineWidthFieldValidator
14878
+ }));
14879
+ view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
14880
+ viewField: view.backgroundInput,
14881
+ commandName: 'tableBackgroundColor',
14882
+ errorText: colorErrorText,
14883
+ validator: colorFieldValidator
14884
+ }));
14885
+ view.on('change:width', this._getValidatedPropertyChangeCallback({
14886
+ viewField: view.widthInput,
14887
+ commandName: 'tableWidth',
14888
+ errorText: lengthErrorText,
14889
+ validator: lengthFieldValidator
14890
+ }));
14891
+ view.on('change:height', this._getValidatedPropertyChangeCallback({
14892
+ viewField: view.heightInput,
14893
+ commandName: 'tableHeight',
14894
+ errorText: lengthErrorText,
14895
+ validator: lengthFieldValidator
14896
+ }));
14897
+ view.on('change:alignment', this._getPropertyChangeCallback('tableAlignment'));
14898
+ return view;
14899
+ }
14900
+ /**
14901
+ * In this method the "editor data -> UI" binding is happening.
14902
+ *
14903
+ * When executed, this method obtains selected table property values from various table commands
14904
+ * and passes them to the {@link #view}.
14905
+ *
14906
+ * This way, the UI stays up–to–date with the editor data.
14907
+ */ _fillViewFormFromCommandValues() {
14908
+ const commands = this.editor.commands;
14909
+ const borderStyleCommand = commands.get('tableBorderStyle');
14910
+ Object.entries(propertyToCommandMap$1).map(([property, commandName])=>{
14911
+ const propertyKey = property;
14912
+ const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
14913
+ return [
14914
+ propertyKey,
14915
+ commands.get(commandName).value || defaultValue
14916
+ ];
14917
+ }).forEach(([property, value])=>{
14918
+ // Do not set the `border-color` and `border-width` fields if `border-style:none`.
14919
+ if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
14920
+ return;
14921
+ }
14922
+ this.view.set(property, value);
14923
+ });
14924
+ this._isReady = true;
14925
+ }
14926
+ /**
14927
+ * Shows the {@link #view} in the {@link #_balloon}.
14928
+ *
14929
+ * **Note**: Each time a view is shown, the new {@link #_undoStepBatch} is created that contains
14930
+ * all changes made to the document when the view is visible, allowing a single undo step
14931
+ * for all of them.
14932
+ */ _showView() {
14933
+ const editor = this.editor;
14934
+ const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
14935
+ const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
14936
+ const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
14937
+ if (useDefaults && !this._viewWithContentTableDefaults) {
14938
+ this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableProperties);
14939
+ } else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
14940
+ this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableProperties);
14941
+ }
14942
+ this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
14943
+ this.listenTo(editor.ui, 'update', ()=>{
14944
+ this._updateView();
14945
+ });
14946
+ // Update the view with the model values.
14947
+ this._fillViewFormFromCommandValues();
14948
+ this._balloon.add({
14949
+ view: this.view,
14950
+ position: getBalloonTablePositionData(editor)
14951
+ });
14952
+ // Create a new batch. Clicking "Cancel" will undo this batch.
14953
+ this._undoStepBatch = editor.model.createBatch();
14954
+ // Basic a11y.
14955
+ this.view.focus();
14956
+ }
14957
+ /**
14958
+ * Removes the {@link #view} from the {@link #_balloon}.
14959
+ */ _hideView() {
14960
+ const editor = this.editor;
14961
+ this.stopListening(editor.ui, 'update');
14962
+ this._isReady = false;
14963
+ // Blur any input element before removing it from DOM to prevent issues in some browsers.
14964
+ // See https://github.com/ckeditor/ckeditor5/issues/1501.
14965
+ this.view.saveButtonView.focus();
14966
+ this._balloon.remove(this.view);
14967
+ // Make sure the focus is not lost in the process by putting it directly
14968
+ // into the editing view.
14969
+ this.editor.editing.view.focus();
14970
+ }
14971
+ /**
14972
+ * Repositions the {@link #_balloon} or hides the {@link #view} if a table is no longer selected.
14973
+ */ _updateView() {
14974
+ const editor = this.editor;
14975
+ const viewDocument = editor.editing.view.document;
14976
+ if (!getSelectionAffectedTableWidget(viewDocument.selection)) {
14977
+ this._hideView();
14978
+ } else if (this._isViewVisible) {
14979
+ repositionContextualBalloon(editor, 'table');
14980
+ }
14981
+ }
14982
+ /**
14983
+ * Returns `true` when the {@link #view} is the visible in the {@link #_balloon}.
14984
+ */ get _isViewVisible() {
14985
+ return !!this.view && this._balloon.visibleView === this.view;
14986
+ }
14987
+ /**
14988
+ * Returns `true` when the {@link #view} is in the {@link #_balloon}.
14989
+ */ get _isViewInBalloon() {
14990
+ return !!this.view && this._balloon.hasView(this.view);
14991
+ }
14992
+ /**
14993
+ * Creates a callback that when executed upon {@link #view view's} property change
14994
+ * executes a related editor command with the new property value.
14995
+ *
14996
+ * If new value will be set to the default value, the command will not be executed.
14997
+ *
14998
+ * @param commandName The command that will be executed.
14999
+ */ _getPropertyChangeCallback(commandName) {
15000
+ return (evt, propertyName, newValue)=>{
15001
+ // Do not execute the command on initial call (opening the table properties view).
15002
+ if (!this._isReady) {
15003
+ return;
15004
+ }
15005
+ this.editor.execute(commandName, {
15006
+ value: newValue,
15007
+ batch: this._undoStepBatch
15008
+ });
15009
+ };
15010
+ }
15011
+ /**
15012
+ * Creates a callback that when executed upon {@link #view view's} property change:
15013
+ * * executes a related editor command with the new property value if the value is valid,
15014
+ * * or sets the error text next to the invalid field, if the value did not pass the validation.
15015
+ */ _getValidatedPropertyChangeCallback(options) {
15016
+ const { commandName, viewField, validator, errorText } = options;
15017
+ const setErrorTextDebounced = debounce(()=>{
15018
+ viewField.errorText = errorText;
15019
+ }, ERROR_TEXT_TIMEOUT$1);
15020
+ return (evt, propertyName, newValue)=>{
15021
+ setErrorTextDebounced.cancel();
15022
+ // Do not execute the command on initial call (opening the table properties view).
15023
+ if (!this._isReady) {
15024
+ return;
15025
+ }
15026
+ if (validator(newValue)) {
15027
+ this.editor.execute(commandName, {
15028
+ value: newValue,
15029
+ batch: this._undoStepBatch
15030
+ });
15031
+ viewField.errorText = null;
15032
+ } else {
15033
+ setErrorTextDebounced();
15034
+ }
15035
+ };
15036
+ }
15037
+ }
15038
+
15039
+ /**
15040
+ * The class representing a table cell properties form, allowing users to customize
15041
+ * certain style aspects of a table cell, for instance, border, padding, text alignment, etc..
15042
+ */ class TableCellPropertiesViewExperimental extends View {
15043
+ /**
15044
+ * Options passed to the view. See {@link #constructor} to learn more.
15045
+ */ options;
15046
+ /**
15047
+ * Tracks information about the DOM focus in the form.
15048
+ */ focusTracker;
15049
+ /**
15050
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
15051
+ */ keystrokes;
15052
+ /**
15053
+ * A collection of child views in the form.
15054
+ */ children;
15055
+ /**
15056
+ * A dropdown that allows selecting the style of the table cell border.
15057
+ */ borderStyleDropdown;
15058
+ /**
15059
+ * An input that allows specifying the width of the table cell border.
15060
+ */ borderWidthInput;
15061
+ /**
15062
+ * An input that allows specifying the color of the table cell border.
15063
+ */ borderColorInput;
15064
+ /**
15065
+ * An input that allows specifying the table cell background color.
15066
+ */ backgroundInput;
15067
+ /**
15068
+ * A dropdown that allows selecting the type of the table cell (data or header).
15069
+ */ cellTypeDropdown;
15070
+ /**
15071
+ * An input that allows specifying the table cell padding.
15072
+ */ paddingInput;
15073
+ /**
15074
+ * An input that allows specifying the table cell width.
15075
+ */ widthInput;
15076
+ /**
15077
+ * An input that allows specifying the table cell height.
15078
+ */ heightInput;
15079
+ /**
15080
+ * A toolbar with buttons that allow changing the horizontal text alignment in a table cell.
15081
+ */ horizontalAlignmentToolbar;
15082
+ /**
15083
+ * A toolbar with buttons that allow changing the vertical text alignment in a table cell.
15084
+ */ verticalAlignmentToolbar;
15085
+ /**
15086
+ * The "Save" button view.
15087
+ */ saveButtonView;
15088
+ /**
15089
+ * The "Cancel" button view.
15090
+ */ cancelButtonView;
15091
+ /**
15092
+ * The "Back" button view.
15093
+ */ backButtonView;
15094
+ /**
15095
+ * A collection of views that can be focused in the form.
15096
+ */ _focusables;
15097
+ /**
15098
+ * Helps cycling over {@link #_focusables} in the form.
15099
+ */ _focusCycler;
15100
+ /**
15101
+ * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
15102
+ * @param options Additional configuration of the view.
15103
+ * @param options.borderColors A configuration of the border color palette used by the
15104
+ * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#borderColorInput}.
15105
+ * @param options.backgroundColors A configuration of the background color palette used by the
15106
+ * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#backgroundInput}.
15107
+ * @param options.defaultTableCellProperties The default table cell properties.
15108
+ * @param options.isTableCellTypeSupported A flag indicating whether the table cell type is supported.
15109
+ */ constructor(locale, options){
15110
+ super(locale);
15111
+ this.set({
15112
+ borderStyle: '',
15113
+ borderWidth: '',
15114
+ borderColor: '',
15115
+ padding: '',
15116
+ backgroundColor: '',
15117
+ width: '',
15118
+ height: '',
15119
+ horizontalAlignment: '',
15120
+ verticalAlignment: '',
15121
+ cellType: ''
15122
+ });
15123
+ this.options = options;
15124
+ const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
15125
+ const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
15126
+ const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
15127
+ const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
15128
+ const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
15129
+ this.focusTracker = new FocusTracker();
15130
+ this.keystrokes = new KeystrokeHandler();
15131
+ this.children = this.createCollection();
15132
+ this.borderStyleDropdown = borderStyleDropdown;
15133
+ this.borderWidthInput = borderWidthInput;
15134
+ this.borderColorInput = borderColorInput;
15135
+ this.backgroundInput = backgroundInput;
15136
+ this.cellTypeDropdown = cellTypeDropdown;
15137
+ this.paddingInput = this._createPaddingField();
15138
+ this.widthInput = widthInput;
15139
+ this.heightInput = heightInput;
15140
+ this.horizontalAlignmentToolbar = horizontalAlignmentToolbar;
15141
+ this.verticalAlignmentToolbar = verticalAlignmentToolbar;
15142
+ // Defer creating to make sure other fields are present and the Save button can
15143
+ // bind its #isEnabled to their error messages so there's no way to save unless all
15144
+ // fields are valid.
15145
+ const { saveButtonView, cancelButtonView } = this._createActionButtons();
15146
+ this.saveButtonView = saveButtonView;
15147
+ this.cancelButtonView = cancelButtonView;
15148
+ this.backButtonView = this._createBackButton();
15149
+ this._focusables = new ViewCollection();
15150
+ this._focusCycler = new FocusCycler({
15151
+ focusables: this._focusables,
15152
+ focusTracker: this.focusTracker,
15153
+ keystrokeHandler: this.keystrokes,
15154
+ actions: {
15155
+ // Navigate form fields backwards using the Shift + Tab keystroke.
15156
+ focusPrevious: 'shift + tab',
15157
+ // Navigate form fields forwards using the Tab key.
15158
+ focusNext: 'tab'
15159
+ }
15160
+ });
15161
+ // Form header.
15162
+ const header = new FormHeaderView(locale, {
15163
+ label: this.t('Cell properties')
15164
+ });
15165
+ header.children.add(this.backButtonView, 0);
15166
+ this.children.add(header);
15167
+ // Border row.
15168
+ this.children.add(new FormRowView(locale, {
15169
+ labelView: borderRowLabel,
15170
+ children: this.options.isTableCellTypeSupported ? [
15171
+ borderRowLabel,
15172
+ borderStyleDropdown,
15173
+ borderWidthInput,
15174
+ borderColorInput
15175
+ ] : [
15176
+ borderRowLabel,
15177
+ borderStyleDropdown,
15178
+ borderColorInput,
15179
+ borderWidthInput
15180
+ ],
15181
+ class: `ck-table-form__border-row${this.options.isTableCellTypeSupported ? ' ck-table-form__border-row_experimental' : ''}`
15182
+ }));
15183
+ // Background and cell type.
15184
+ this.children.add(new FormRowView(locale, {
15185
+ children: this.options.isTableCellTypeSupported ? [
15186
+ new FormRowView(locale, {
15187
+ labelView: cellTypeRowLabel,
15188
+ children: [
15189
+ cellTypeRowLabel,
15190
+ cellTypeDropdown
15191
+ ],
15192
+ class: 'ck-table-form__cell-type-row'
15193
+ }),
15194
+ new FormRowView(locale, {
15195
+ labelView: backgroundRowLabel,
15196
+ children: [
15197
+ backgroundRowLabel,
15198
+ backgroundInput
15199
+ ],
15200
+ class: 'ck-table-form__background-row'
15201
+ })
15202
+ ] : [
15203
+ new FormRowView(locale, {
15204
+ labelView: backgroundRowLabel,
15205
+ children: [
15206
+ backgroundRowLabel,
15207
+ backgroundInput
15208
+ ],
15209
+ class: 'ck-table-form__background-row'
15210
+ })
15211
+ ]
15212
+ }));
15213
+ // Dimensions row and padding.
15214
+ this.children.add(new FormRowView(locale, {
15215
+ children: [
15216
+ // Dimensions row.
15217
+ new FormRowView(locale, {
15218
+ labelView: dimensionsLabel,
15219
+ children: [
15220
+ dimensionsLabel,
15221
+ widthInput,
15222
+ operatorLabel,
15223
+ heightInput
15224
+ ],
15225
+ class: 'ck-table-form__dimensions-row'
15226
+ }),
15227
+ // Padding row.
15228
+ new FormRowView(locale, {
15229
+ children: [
15230
+ this.paddingInput
15231
+ ],
15232
+ class: 'ck-table-cell-properties-form__padding-row'
15233
+ })
15234
+ ]
15235
+ }));
15236
+ // Text alignment row.
15237
+ this.children.add(new FormRowView(locale, {
15238
+ labelView: alignmentLabel,
15239
+ children: [
15240
+ alignmentLabel,
15241
+ horizontalAlignmentToolbar,
15242
+ verticalAlignmentToolbar
15243
+ ],
15244
+ class: 'ck-table-cell-properties-form__alignment-row'
15245
+ }));
15246
+ // Action row.
15247
+ this.children.add(new FormRowView(locale, {
15248
+ children: [
15249
+ this.cancelButtonView,
15250
+ this.saveButtonView
15251
+ ],
15252
+ class: 'ck-table-form__action-row'
15253
+ }));
15254
+ this.setTemplate({
15255
+ tag: 'form',
15256
+ attributes: {
15257
+ class: [
15258
+ 'ck',
15259
+ 'ck-form',
15260
+ 'ck-table-form',
15261
+ 'ck-table-cell-properties-form',
15262
+ 'ck-table-cell-properties-form_experimental',
15263
+ this.options.isTableCellTypeSupported ? 'ck-table-cell-properties-form_experimental-no-cell-type' : ''
15264
+ ],
15265
+ // https://github.com/ckeditor/ckeditor5-link/issues/90
15266
+ tabindex: '-1'
15267
+ },
15268
+ children: this.children
15269
+ });
15270
+ }
15271
+ /**
15272
+ * @inheritDoc
15273
+ */ render() {
15274
+ super.render();
15275
+ // Enable the "submit" event for this view. It can be triggered by the #saveButtonView
15276
+ // which is of the "submit" DOM "type".
15277
+ submitHandler({
15278
+ view: this
15279
+ });
15280
+ // Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
15281
+ [
15282
+ this.borderColorInput,
15283
+ this.backgroundInput
15284
+ ].forEach((view)=>{
15285
+ this._focusCycler.chain(view.fieldView.focusCycler);
15286
+ });
15287
+ [
15288
+ this.borderStyleDropdown,
15289
+ this.borderColorInput,
15290
+ this.borderWidthInput,
15291
+ this.cellTypeDropdown,
15292
+ this.backgroundInput,
15293
+ this.widthInput,
15294
+ this.heightInput,
15295
+ this.paddingInput,
15296
+ this.horizontalAlignmentToolbar,
15297
+ this.verticalAlignmentToolbar,
15298
+ this.cancelButtonView,
15299
+ this.saveButtonView,
15300
+ this.backButtonView
15301
+ ].forEach((view)=>{
15302
+ // Register the view as focusable.
15303
+ this._focusables.add(view);
15304
+ // Register the view in the focus tracker.
15305
+ this.focusTracker.add(view.element);
15306
+ });
15307
+ // Mainly for closing using "Esc" and navigation using "Tab".
15308
+ this.keystrokes.listenTo(this.element);
15309
+ }
15310
+ /**
15311
+ * @inheritDoc
15312
+ */ destroy() {
15313
+ super.destroy();
15314
+ this.focusTracker.destroy();
15315
+ this.keystrokes.destroy();
15316
+ }
15317
+ /**
15318
+ * Focuses the fist focusable field in the form.
15319
+ */ focus() {
15320
+ this._focusCycler.focusFirst();
15321
+ }
15322
+ /**
15323
+ * Creates the following form fields:
15324
+ *
15325
+ * * {@link #borderStyleDropdown},
15326
+ * * {@link #borderWidthInput},
15327
+ * * {@link #borderColorInput}.
15328
+ */ _createBorderFields() {
15329
+ const defaultTableCellProperties = this.options.defaultTableCellProperties;
15330
+ const defaultBorder = {
15331
+ style: defaultTableCellProperties.borderStyle,
15332
+ width: defaultTableCellProperties.borderWidth,
15333
+ color: defaultTableCellProperties.borderColor
15334
+ };
15335
+ const colorInputCreator = getLabeledColorInputCreator({
15336
+ colorConfig: this.options.borderColors,
15337
+ columns: 5,
15338
+ defaultColorValue: defaultBorder.color,
15339
+ colorPickerConfig: this.options.colorPickerConfig
15340
+ });
15341
+ const locale = this.locale;
15342
+ const t = this.t;
15343
+ const accessibleLabel = t('Style');
15344
+ // -- Group label ---------------------------------------------
15345
+ const borderRowLabel = new LabelView(locale);
15346
+ borderRowLabel.text = t('Border');
15347
+ // -- Style ---------------------------------------------------
15348
+ const styleLabels = getBorderStyleLabels(t);
15349
+ const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
15350
+ borderStyleDropdown.set({
15351
+ label: accessibleLabel,
15352
+ class: 'ck-table-form__border-style'
15353
+ });
15354
+ borderStyleDropdown.fieldView.buttonView.set({
15355
+ ariaLabel: accessibleLabel,
15356
+ ariaLabelledBy: undefined,
15357
+ isOn: false,
15358
+ withText: true,
15359
+ tooltip: accessibleLabel
15360
+ });
15361
+ borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
15362
+ return styleLabels[value ? value : 'none'];
15363
+ });
15364
+ borderStyleDropdown.fieldView.on('execute', (evt)=>{
15365
+ this.borderStyle = evt.source._borderStyleValue;
15366
+ });
15367
+ borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
15368
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
15369
+ role: 'menu',
15370
+ ariaLabel: accessibleLabel
15371
+ });
15372
+ // -- Width ---------------------------------------------------
15373
+ const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
15374
+ borderWidthInput.set({
15375
+ label: t('Width'),
15376
+ class: 'ck-table-form__border-width'
15377
+ });
15378
+ borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
15379
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
15380
+ borderWidthInput.fieldView.on('input', ()=>{
15381
+ this.borderWidth = borderWidthInput.fieldView.element.value;
15382
+ });
15383
+ // -- Color ---------------------------------------------------
15384
+ const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
15385
+ borderColorInput.set({
15386
+ label: t('Color'),
15387
+ class: 'ck-table-form__border-color'
15388
+ });
15389
+ borderColorInput.fieldView.bind('value').to(this, 'borderColor');
15390
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
15391
+ borderColorInput.fieldView.on('input', ()=>{
15392
+ this.borderColor = borderColorInput.fieldView.value;
15393
+ });
15394
+ // Reset the border color and width fields depending on the `border-style` value.
15395
+ this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
15396
+ // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
15397
+ // See: https://github.com/ckeditor/ckeditor5/issues/6227.
15398
+ if (!isBorderStyleSet(newValue)) {
15399
+ this.borderColor = '';
15400
+ this.borderWidth = '';
15401
+ }
15402
+ // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
15403
+ if (!isBorderStyleSet(oldValue)) {
15404
+ this.borderColor = defaultBorder.color;
15405
+ this.borderWidth = defaultBorder.width;
15406
+ }
15407
+ });
15408
+ return {
15409
+ borderRowLabel,
15410
+ borderStyleDropdown,
15411
+ borderColorInput,
15412
+ borderWidthInput
15413
+ };
15414
+ }
15415
+ /**
15416
+ * Creates the following form fields:
15417
+ *
15418
+ * * {@link #backgroundInput}.
15419
+ */ _createBackgroundFields() {
15420
+ const locale = this.locale;
15421
+ const t = this.t;
15422
+ // -- Group label ---------------------------------------------
15423
+ const backgroundRowLabel = new LabelView(locale);
15424
+ backgroundRowLabel.text = t('Background');
15425
+ // -- Background color input -----------------------------------
15426
+ const colorInputCreator = getLabeledColorInputCreator({
15427
+ colorConfig: this.options.backgroundColors,
15428
+ columns: 5,
15429
+ defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
15430
+ colorPickerConfig: this.options.colorPickerConfig
15431
+ });
15432
+ const backgroundInput = new LabeledFieldView(locale, colorInputCreator);
15433
+ backgroundInput.set({
15434
+ label: t('Color'),
15435
+ class: 'ck-table-cell-properties-form__background'
15436
+ });
15437
+ backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
15438
+ backgroundInput.fieldView.on('input', ()=>{
15439
+ this.backgroundColor = backgroundInput.fieldView.value;
15440
+ });
15441
+ return {
15442
+ backgroundRowLabel,
15443
+ backgroundInput
15444
+ };
15445
+ }
15446
+ /**
15447
+ * Create cell type field.
15448
+ *
15449
+ * * {@link #cellTypeDropdown}.
15450
+ *
15451
+ * @internal
15452
+ */ _createCellTypeField() {
15453
+ const locale = this.locale;
15454
+ const t = this.t;
15455
+ const cellTypeRowLabel = new LabelView(locale);
15456
+ cellTypeRowLabel.text = t('Cell type');
15457
+ const cellTypeLabels = this._cellTypeLabels;
15458
+ const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
15459
+ cellTypeDropdown.set({
15460
+ label: t('Cell type'),
15461
+ class: 'ck-table-cell-properties-form__cell-type'
15462
+ });
15463
+ cellTypeDropdown.fieldView.buttonView.set({
15464
+ ariaLabel: t('Cell type'),
15465
+ ariaLabelledBy: undefined,
15466
+ isOn: false,
15467
+ withText: true,
15468
+ tooltip: t('Cell type')
15469
+ });
15470
+ cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
15471
+ return cellTypeLabels[value || 'data'];
15472
+ });
15473
+ cellTypeDropdown.fieldView.on('execute', (evt)=>{
15474
+ this.cellType = evt.source._cellTypeValue;
15475
+ });
15476
+ cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
15477
+ addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
15478
+ role: 'menu',
15479
+ ariaLabel: t('Cell type')
15480
+ });
15481
+ return {
15482
+ cellTypeRowLabel,
15483
+ cellTypeDropdown
15484
+ };
15485
+ }
15486
+ /**
15487
+ * Creates the following form fields:
15488
+ *
15489
+ * * {@link #widthInput}.
15490
+ * * {@link #heightInput}.
15491
+ */ _createDimensionFields() {
15492
+ const locale = this.locale;
15493
+ const t = this.t;
15494
+ // -- Label ---------------------------------------------------
15495
+ const dimensionsLabel = new LabelView(locale);
15496
+ dimensionsLabel.text = t('Dimensions');
15497
+ // -- Width ---------------------------------------------------
15498
+ const widthInput = new LabeledFieldView(locale, createLabeledInputText);
15499
+ widthInput.set({
15500
+ label: t('Width'),
15501
+ class: 'ck-table-form__dimensions-row__width'
15502
+ });
15503
+ widthInput.fieldView.bind('value').to(this, 'width');
15504
+ widthInput.fieldView.on('input', ()=>{
15505
+ this.width = widthInput.fieldView.element.value;
15506
+ });
15507
+ // -- Operator ---------------------------------------------------
15508
+ const operatorLabel = new View(locale);
15509
+ operatorLabel.setTemplate({
15510
+ tag: 'span',
15511
+ attributes: {
15512
+ class: [
15513
+ 'ck-table-form__dimension-operator'
15514
+ ]
15515
+ },
15516
+ children: [
15517
+ {
15518
+ text: '×'
15519
+ }
15520
+ ]
15521
+ });
15522
+ // -- Height ---------------------------------------------------
15523
+ const heightInput = new LabeledFieldView(locale, createLabeledInputText);
15524
+ heightInput.set({
15525
+ label: t('Height'),
15526
+ class: 'ck-table-form__dimensions-row__height'
15527
+ });
15528
+ heightInput.fieldView.bind('value').to(this, 'height');
15529
+ heightInput.fieldView.on('input', ()=>{
15530
+ this.height = heightInput.fieldView.element.value;
15531
+ });
15532
+ return {
15533
+ dimensionsLabel,
15534
+ widthInput,
15535
+ operatorLabel,
15536
+ heightInput
15537
+ };
15538
+ }
15539
+ /**
15540
+ * Creates the following form fields:
15541
+ *
15542
+ * * {@link #paddingInput}.
15543
+ */ _createPaddingField() {
15544
+ const locale = this.locale;
15545
+ const t = this.t;
15546
+ const paddingInput = new LabeledFieldView(locale, createLabeledInputText);
15547
+ paddingInput.set({
15548
+ label: t('Padding'),
15549
+ class: 'ck-table-cell-properties-form__padding'
15550
+ });
15551
+ paddingInput.fieldView.bind('value').to(this, 'padding');
15552
+ paddingInput.fieldView.on('input', ()=>{
15553
+ this.padding = paddingInput.fieldView.element.value;
15554
+ });
15555
+ return paddingInput;
15556
+ }
15557
+ /**
15558
+ * Creates the following form fields:
15559
+ *
15560
+ * * {@link #horizontalAlignmentToolbar},
15561
+ * * {@link #verticalAlignmentToolbar}.
15562
+ */ _createAlignmentFields() {
15563
+ const locale = this.locale;
15564
+ const t = this.t;
15565
+ const alignmentLabel = new LabelView(locale);
15566
+ const ALIGNMENT_ICONS = {
15567
+ left: IconAlignLeft,
15568
+ center: IconAlignCenter,
15569
+ right: IconAlignRight,
15570
+ justify: IconAlignJustify,
15571
+ top: IconAlignTop,
15572
+ middle: IconAlignMiddle,
15573
+ bottom: IconAlignBottom
15574
+ };
15575
+ alignmentLabel.text = t('Table cell text alignment');
15576
+ // -- Horizontal ---------------------------------------------------
15577
+ const horizontalAlignmentToolbar = new ToolbarView(locale);
15578
+ const isContentRTL = locale.contentLanguageDirection === 'rtl';
15579
+ horizontalAlignmentToolbar.set({
15580
+ isCompact: true,
15581
+ role: 'radiogroup',
15582
+ ariaLabel: t('Horizontal text alignment toolbar'),
15583
+ class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
15584
+ });
15585
+ fillToolbar({
15586
+ view: this,
15587
+ icons: ALIGNMENT_ICONS,
15588
+ toolbar: horizontalAlignmentToolbar,
15589
+ labels: this._horizontalAlignmentLabels,
15590
+ propertyName: 'horizontalAlignment',
15591
+ nameToValue: (name)=>{
15592
+ // For the RTL content, we want to swap the buttons "align to the left" and "align to the right".
15593
+ if (isContentRTL) {
15594
+ if (name === 'left') {
15595
+ return 'right';
15596
+ } else if (name === 'right') {
15597
+ return 'left';
15598
+ }
15599
+ }
15600
+ return name;
15601
+ },
15602
+ defaultValue: this.options.defaultTableCellProperties.horizontalAlignment
15603
+ });
15604
+ // -- Vertical -----------------------------------------------------
15605
+ const verticalAlignmentToolbar = new ToolbarView(locale);
15606
+ verticalAlignmentToolbar.set({
15607
+ isCompact: true,
15608
+ role: 'radiogroup',
15609
+ ariaLabel: t('Vertical text alignment toolbar'),
15610
+ class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
15611
+ });
15612
+ fillToolbar({
15613
+ view: this,
15614
+ icons: ALIGNMENT_ICONS,
15615
+ toolbar: verticalAlignmentToolbar,
15616
+ labels: this._verticalAlignmentLabels,
15617
+ propertyName: 'verticalAlignment',
15618
+ defaultValue: this.options.defaultTableCellProperties.verticalAlignment
15619
+ });
15620
+ return {
15621
+ horizontalAlignmentToolbar,
15622
+ verticalAlignmentToolbar,
15623
+ alignmentLabel
15624
+ };
15625
+ }
15626
+ /**
15627
+ * Creates the following form controls:
15628
+ *
15629
+ * * {@link #saveButtonView},
15630
+ * * {@link #cancelButtonView}.
15631
+ */ _createActionButtons() {
15632
+ const locale = this.locale;
15633
+ const t = this.t;
15634
+ const saveButtonView = new ButtonView(locale);
15635
+ const cancelButtonView = new ButtonView(locale);
15636
+ const fieldsThatShouldValidateToSave = [
15637
+ this.borderWidthInput,
15638
+ this.borderColorInput,
15639
+ this.backgroundInput,
15640
+ this.paddingInput
15641
+ ];
15642
+ saveButtonView.set({
15643
+ label: t('Save'),
15644
+ class: 'ck-button-action',
15645
+ type: 'submit',
15646
+ withText: true
15647
+ });
15648
+ saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
15649
+ return errorTexts.every((errorText)=>!errorText);
15650
+ });
15651
+ cancelButtonView.set({
15652
+ label: t('Cancel'),
15653
+ withText: true
15654
+ });
15655
+ cancelButtonView.delegate('execute').to(this, 'cancel');
15656
+ return {
15657
+ saveButtonView,
15658
+ cancelButtonView
15659
+ };
15660
+ }
15661
+ /**
15662
+ * Creates a back button view that cancels the form.
15663
+ */ _createBackButton() {
15664
+ const t = this.locale.t;
15665
+ const backButton = new ButtonView(this.locale);
15666
+ backButton.set({
15667
+ class: 'ck-button-back',
15668
+ label: t('Back'),
15669
+ icon: IconPreviousArrow,
15670
+ tooltip: true
15671
+ });
15672
+ backButton.delegate('execute').to(this, 'cancel');
15673
+ return backButton;
15674
+ }
15675
+ /**
15676
+ * Creates the cell type dropdown definitions.
15677
+ */ _getCellTypeDefinitions() {
15678
+ const itemDefinitions = new Collection();
15679
+ const cellTypeLabels = this._cellTypeLabels;
15680
+ for (const type of [
15681
+ 'data',
15682
+ 'header'
15683
+ ]){
15684
+ const definition = {
15685
+ type: 'button',
15686
+ model: new UIModel({
15687
+ _cellTypeValue: type,
15688
+ label: cellTypeLabels[type],
15689
+ role: 'menuitemradio',
15690
+ withText: true
15691
+ })
15692
+ };
15693
+ definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
15694
+ itemDefinitions.add(definition);
15695
+ }
15696
+ return itemDefinitions;
15697
+ }
15698
+ /**
15699
+ * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
15700
+ */ get _horizontalAlignmentLabels() {
15701
+ const locale = this.locale;
15702
+ const t = this.t;
15703
+ const left = t('Align cell text to the left');
15704
+ const center = t('Align cell text to the center');
15705
+ const right = t('Align cell text to the right');
15706
+ const justify = t('Justify cell text');
15707
+ // Returns object with a proper order of labels.
15708
+ if (locale.uiLanguageDirection === 'rtl') {
15709
+ return {
15710
+ right,
15711
+ center,
15712
+ left,
15713
+ justify
15714
+ };
15715
+ } else {
15716
+ return {
15717
+ left,
15718
+ center,
15719
+ right,
15720
+ justify
15721
+ };
15722
+ }
15723
+ }
15724
+ /**
15725
+ * Provides localized labels for {@link #verticalAlignmentToolbar} buttons.
15726
+ */ get _verticalAlignmentLabels() {
15727
+ const t = this.t;
15728
+ return {
15729
+ top: t('Align cell text to the top'),
15730
+ middle: t('Align cell text to the middle'),
15731
+ bottom: t('Align cell text to the bottom')
15732
+ };
15733
+ }
15734
+ /**
15735
+ * Provides localized labels for {@link #cellTypeDropdown}.
15736
+ */ get _cellTypeLabels() {
15737
+ const t = this.t;
15738
+ return {
15739
+ data: t('Data cell'),
15740
+ header: t('Header cell')
15741
+ };
15742
+ }
15743
+ }
15744
+ function isBorderStyleSet(value) {
15745
+ return value !== 'none';
15746
+ }
15747
+
15748
+ const ERROR_TEXT_TIMEOUT = 500;
15749
+ // Map of view properties and related commands.
15750
+ const propertyToCommandMap = {
15751
+ borderStyle: 'tableCellBorderStyle',
15752
+ borderColor: 'tableCellBorderColor',
15753
+ borderWidth: 'tableCellBorderWidth',
15754
+ height: 'tableCellHeight',
15755
+ width: 'tableCellWidth',
15756
+ padding: 'tableCellPadding',
15757
+ backgroundColor: 'tableCellBackgroundColor',
15758
+ horizontalAlignment: 'tableCellHorizontalAlignment',
15759
+ verticalAlignment: 'tableCellVerticalAlignment',
15760
+ cellType: 'tableCellType'
15761
+ };
15762
+ /**
15763
+ * The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
15764
+ * that opens a form allowing to specify the visual styling of a table cell.
15765
+ *
15766
+ * It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
15767
+ */ class TableCellPropertiesUIExperimental extends Plugin {
15768
+ /**
15769
+ * The default table cell properties.
15770
+ */ _defaultContentTableCellProperties;
15771
+ /**
15772
+ * The default layout table cell properties.
15773
+ */ _defaultLayoutTableCellProperties;
15774
+ /**
15775
+ * The contextual balloon plugin instance.
15776
+ */ _balloon;
15777
+ /**
15778
+ * The cell properties form view displayed inside the balloon.
15779
+ */ view;
15780
+ /**
15781
+ * The cell properties form view displayed inside the balloon (content table).
15782
+ */ _viewWithContentTableDefaults;
15783
+ /**
15784
+ * The cell properties form view displayed inside the balloon (layout table).
15785
+ */ _viewWithLayoutTableDefaults;
15786
+ /**
15787
+ * The batch used to undo all changes made by the form (which are live, as the user types)
15788
+ * when "Cancel" was pressed. Each time the view is shown, a new batch is created.
15789
+ */ _undoStepBatch;
15790
+ /**
15791
+ * Flag used to indicate whether view is ready to execute update commands
15792
+ * (it finished loading initial data).
15793
+ */ _isReady;
15794
+ /**
15795
+ * @inheritDoc
15796
+ */ static get requires() {
15797
+ return [
15798
+ ContextualBalloon
15799
+ ];
15800
+ }
15801
+ /**
15802
+ * @inheritDoc
15803
+ */ static get pluginName() {
15804
+ return 'TableCellPropertiesUIExperimental';
15805
+ }
15806
+ /**
15807
+ * @inheritDoc
15808
+ */ static get isOfficialPlugin() {
15809
+ return true;
15810
+ }
15811
+ /**
15812
+ * @inheritDoc
15813
+ */ constructor(editor){
15814
+ super(editor);
15815
+ editor.config.define('table.tableCellProperties', {
15816
+ borderColors: defaultColors,
15817
+ backgroundColors: defaultColors
15818
+ });
15819
+ }
15820
+ /**
15821
+ * @inheritDoc
15822
+ */ init() {
15823
+ const editor = this.editor;
15824
+ const t = editor.t;
15825
+ this._defaultContentTableCellProperties = getNormalizedDefaultCellProperties(editor.config.get('table.tableCellProperties.defaultProperties'), {
15826
+ includeVerticalAlignmentProperty: true,
15827
+ includeHorizontalAlignmentProperty: true,
15828
+ includePaddingProperty: true,
15829
+ isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
15830
+ });
15831
+ this._defaultLayoutTableCellProperties = getNormalizedDefaultProperties(undefined, {
15832
+ includeVerticalAlignmentProperty: true,
15833
+ includeHorizontalAlignmentProperty: true,
15834
+ isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
15835
+ });
15836
+ this._balloon = editor.plugins.get(ContextualBalloon);
15837
+ this.view = null;
15838
+ this._isReady = false;
15839
+ editor.ui.componentFactory.add('tableCellProperties', (locale)=>{
15840
+ const view = new ButtonView(locale);
15841
+ view.set({
15842
+ label: t('Cell properties'),
15843
+ icon: IconTableCellProperties,
15844
+ tooltip: true
15845
+ });
15846
+ this.listenTo(view, 'execute', ()=>this._showView());
15847
+ const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
15848
+ view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
15849
+ return view;
15850
+ });
15851
+ }
15852
+ /**
15853
+ * @inheritDoc
15854
+ */ destroy() {
15855
+ super.destroy();
15856
+ // Destroy created UI components as they are not automatically destroyed.
15857
+ // See https://github.com/ckeditor/ckeditor5/issues/1341.
15858
+ if (this.view) {
15859
+ this.view.destroy();
15860
+ }
15861
+ }
15862
+ /**
15863
+ * Creates the {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView} instance.
15864
+ *
15865
+ * @returns The cell properties form view instance.
15866
+ */ _createPropertiesView(defaultTableCellProperties) {
15867
+ const editor = this.editor;
15868
+ const config = editor.config.get('table.tableCellProperties');
15869
+ const borderColorsConfig = normalizeColorOptions(config.borderColors);
15870
+ const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
15871
+ const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
15872
+ const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
15873
+ const hasColorPicker = config.colorPicker !== false;
15874
+ const isTableCellTypeSupported = !!editor.config.get('experimentalFlags.tableCellTypeSupport');
15875
+ const view = new TableCellPropertiesViewExperimental(editor.locale, {
15876
+ borderColors: localizedBorderColors,
15877
+ backgroundColors: localizedBackgroundColors,
15878
+ defaultTableCellProperties,
15879
+ colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false,
15880
+ isTableCellTypeSupported
15881
+ });
15882
+ const t = editor.t;
15883
+ // Render the view so its #element is available for the clickOutsideHandler.
15884
+ view.render();
15885
+ this.listenTo(view, 'submit', ()=>{
15886
+ this._hideView();
15887
+ });
15888
+ this.listenTo(view, 'cancel', ()=>{
15889
+ // https://github.com/ckeditor/ckeditor5/issues/6180
15890
+ if (this._undoStepBatch.operations.length) {
15891
+ editor.execute('undo', this._undoStepBatch);
15892
+ }
15893
+ this._hideView();
15894
+ });
15895
+ // Close the balloon on Esc key press.
15896
+ view.keystrokes.set('Esc', (data, cancel)=>{
15897
+ this._hideView();
15898
+ cancel();
15899
+ });
15900
+ // Close on click outside of balloon panel element.
15901
+ clickOutsideHandler({
15902
+ emitter: view,
15903
+ activator: ()=>this._isViewInBalloon,
15904
+ contextElements: [
15905
+ this._balloon.view.element
15906
+ ],
15907
+ callback: ()=>this._hideView()
15908
+ });
15909
+ const colorErrorText = getLocalizedColorErrorText(t);
15910
+ const lengthErrorText = getLocalizedLengthErrorText(t);
15911
+ // Create the "UI -> editor data" binding.
15912
+ // These listeners update the editor data (via table commands) when any observable
15913
+ // property of the view has changed. They also validate the value and display errors in the UI
15914
+ // when necessary. This makes the view live, which means the changes are
15915
+ // visible in the editing as soon as the user types or changes fields' values.
15916
+ view.on('change:borderStyle', this._getPropertyChangeCallback('tableCellBorderStyle'));
15917
+ view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
15918
+ viewField: view.borderColorInput,
15919
+ commandName: 'tableCellBorderColor',
15920
+ errorText: colorErrorText,
15921
+ validator: colorFieldValidator
15922
+ }));
15923
+ view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
15924
+ viewField: view.borderWidthInput,
15925
+ commandName: 'tableCellBorderWidth',
15926
+ errorText: lengthErrorText,
15927
+ validator: lineWidthFieldValidator
15928
+ }));
15929
+ view.on('change:padding', this._getValidatedPropertyChangeCallback({
15930
+ viewField: view.paddingInput,
15931
+ commandName: 'tableCellPadding',
15932
+ errorText: lengthErrorText,
15933
+ validator: lengthFieldValidator
15934
+ }));
15935
+ view.on('change:width', this._getValidatedPropertyChangeCallback({
15936
+ viewField: view.widthInput,
15937
+ commandName: 'tableCellWidth',
15938
+ errorText: lengthErrorText,
15939
+ validator: lengthFieldValidator
15940
+ }));
15941
+ view.on('change:height', this._getValidatedPropertyChangeCallback({
15942
+ viewField: view.heightInput,
15943
+ commandName: 'tableCellHeight',
15944
+ errorText: lengthErrorText,
15945
+ validator: lengthFieldValidator
15946
+ }));
15947
+ view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
15948
+ viewField: view.backgroundInput,
15949
+ commandName: 'tableCellBackgroundColor',
15950
+ errorText: colorErrorText,
15951
+ validator: colorFieldValidator
15952
+ }));
15953
+ view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
15954
+ view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
15955
+ const cellTypeCommand = editor.commands.get('tableCellType');
15956
+ if (cellTypeCommand) {
15957
+ view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
15958
+ view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
15959
+ }
15960
+ return view;
15961
+ }
15962
+ /**
15963
+ * In this method the "editor data -> UI" binding is happening.
15964
+ *
15965
+ * When executed, this method obtains selected cell property values from various table commands
15966
+ * and passes them to the {@link #view}.
15967
+ *
15968
+ * This way, the UI stays up–to–date with the editor data.
15969
+ */ _fillViewFormFromCommandValues() {
15970
+ const commands = this.editor.commands;
15971
+ const borderStyleCommand = commands.get('tableCellBorderStyle');
15972
+ Object.entries(propertyToCommandMap).flatMap(([property, commandName])=>{
15973
+ const command = commands.get(commandName);
15974
+ if (!command) {
15975
+ return [];
15976
+ }
15977
+ const propertyKey = property;
15978
+ let defaultValue;
15979
+ if (propertyKey === 'cellType') {
15980
+ defaultValue = '';
15981
+ } else {
15982
+ defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
15983
+ }
15984
+ const entry = [
15985
+ property,
15986
+ command.value || defaultValue
15987
+ ];
15988
+ return [
15989
+ entry
15990
+ ];
15991
+ }).forEach(([property, value])=>{
15992
+ // Do not set the `border-color` and `border-width` fields if `border-style:none`.
15993
+ if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
15994
+ return;
15995
+ }
15996
+ this.view.set(property, value);
15997
+ });
15998
+ this._isReady = true;
15999
+ }
16000
+ /**
16001
+ * Shows the {@link #view} in the {@link #_balloon}.
16002
+ *
16003
+ * **Note**: Each time a view is shown, a new {@link #_undoStepBatch} is created. It contains
16004
+ * all changes made to the document when the view is visible, allowing a single undo step
16005
+ * for all of them.
16006
+ */ _showView() {
16007
+ const editor = this.editor;
16008
+ const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
16009
+ const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
16010
+ const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
16011
+ if (useDefaults && !this._viewWithContentTableDefaults) {
16012
+ this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableCellProperties);
16013
+ } else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
16014
+ this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableCellProperties);
16015
+ }
16016
+ this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
16017
+ this.listenTo(editor.ui, 'update', ()=>{
16018
+ this._updateView();
16019
+ });
16020
+ // Update the view with the model values.
16021
+ this._fillViewFormFromCommandValues();
16022
+ this._balloon.add({
16023
+ view: this.view,
16024
+ position: getBalloonCellPositionData(editor)
16025
+ });
16026
+ // Create a new batch. Clicking "Cancel" will undo this batch.
16027
+ this._undoStepBatch = editor.model.createBatch();
16028
+ // Basic a11y.
16029
+ this.view.focus();
16030
+ }
16031
+ /**
16032
+ * Removes the {@link #view} from the {@link #_balloon}.
16033
+ */ _hideView() {
16034
+ const editor = this.editor;
16035
+ this.stopListening(editor.ui, 'update');
16036
+ this._isReady = false;
16037
+ // Blur any input element before removing it from DOM to prevent issues in some browsers.
16038
+ // See https://github.com/ckeditor/ckeditor5/issues/1501.
16039
+ this.view.saveButtonView.focus();
16040
+ this._balloon.remove(this.view);
16041
+ // Make sure the focus is not lost in the process by putting it directly
16042
+ // into the editing view.
16043
+ this.editor.editing.view.focus();
16044
+ }
16045
+ /**
16046
+ * Repositions the {@link #_balloon} or hides the {@link #view} if a table cell is no longer selected.
16047
+ */ _updateView() {
16048
+ const editor = this.editor;
16049
+ const viewDocument = editor.editing.view.document;
16050
+ if (!getTableWidgetAncestor(viewDocument.selection)) {
16051
+ this._hideView();
16052
+ } else if (this._isViewVisible) {
16053
+ repositionContextualBalloon(editor, 'cell');
16054
+ }
16055
+ }
16056
+ /**
16057
+ * Returns `true` when the {@link #view} is visible in the {@link #_balloon}.
16058
+ */ get _isViewVisible() {
16059
+ return !!this.view && this._balloon.visibleView === this.view;
16060
+ }
16061
+ /**
16062
+ * Returns `true` when the {@link #view} is in the {@link #_balloon}.
16063
+ */ get _isViewInBalloon() {
16064
+ return !!this.view && this._balloon.hasView(this.view);
16065
+ }
16066
+ /**
16067
+ * Creates a callback that when executed upon the {@link #view view's} property change
16068
+ * executes a related editor command with the new property value.
16069
+ *
16070
+ * @param commandName The default value of the command.
16071
+ */ _getPropertyChangeCallback(commandName) {
16072
+ return (evt, propertyName, newValue)=>{
16073
+ if (!this._isReady) {
16074
+ return;
16075
+ }
16076
+ this.editor.execute(commandName, {
16077
+ value: newValue,
16078
+ batch: this._undoStepBatch
16079
+ });
16080
+ };
16081
+ }
16082
+ /**
16083
+ * Creates a callback that when executed upon the {@link #view view's} property change:
16084
+ * * Executes a related editor command with the new property value if the value is valid,
16085
+ * * Or sets the error text next to the invalid field, if the value did not pass the validation.
16086
+ */ _getValidatedPropertyChangeCallback(options) {
16087
+ const { commandName, viewField, validator, errorText } = options;
16088
+ const setErrorTextDebounced = debounce(()=>{
16089
+ viewField.errorText = errorText;
16090
+ }, ERROR_TEXT_TIMEOUT);
16091
+ return (evt, propertyName, newValue)=>{
16092
+ setErrorTextDebounced.cancel();
16093
+ // Do not execute the command on initial call (opening the table properties view).
16094
+ if (!this._isReady) {
16095
+ return;
16096
+ }
16097
+ if (validator(newValue)) {
16098
+ this.editor.execute(commandName, {
16099
+ value: newValue,
16100
+ batch: this._undoStepBatch
16101
+ });
16102
+ viewField.errorText = null;
16103
+ } else {
16104
+ setErrorTextDebounced();
16105
+ }
16106
+ };
16107
+ }
16108
+ }
16109
+
16110
+ export { InsertColumnCommand, InsertRowCommand, InsertTableCommand, InsertTableLayoutCommand, MergeCellCommand, MergeCellsCommand, PlainTableOutput, RemoveColumnCommand, RemoveRowCommand, SelectColumnCommand, SelectRowCommand, SetHeaderColumnCommand, SetHeaderRowCommand, SplitCellCommand, Table, TableAlignmentCommand, TableBackgroundColorCommand, TableBorderColorCommand, TableBorderStyleCommand, TableBorderWidthCommand, TableCaption, TableCaptionEditing, TableCaptionUI, TableCellBackgroundColorCommand, TableCellBorderColorCommand, TableCellBorderStyleCommand, TableCellBorderWidthCommand, TableCellHeightCommand, TableCellHorizontalAlignmentCommand, TableCellPaddingCommand, TableCellProperties, TableCellPropertiesEditing, TableCellPropertiesUI, TableCellPropertiesUIExperimental, TableCellPropertiesView, TableCellPropertiesViewExperimental, TableCellPropertyCommand, TableCellTypeCommand, TableCellVerticalAlignmentCommand, TableCellWidthCommand, TableCellWidthEditing, TableClipboard, TableColumnResize, TableColumnResizeEditing, TableEditing, TableHeightCommand, TableKeyboard, TableLayout, TableLayoutEditing, TableLayoutUI, TableMouse, TableProperties, TablePropertiesEditing, TablePropertiesUI, TablePropertiesUIExperimental, TablePropertiesView, TablePropertiesViewExperimental, TablePropertyCommand, TableSelection, TableToolbar, TableTypeCommand, TableUI, TableUtils, TableWalker, TableWidthCommand, TableWidthsCommand, ToggleTableCaptionCommand, InsertTableView as _InsertTableView, COLUMN_MIN_WIDTH_AS_PERCENTAGE as _TABLE_COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS as _TABLE_COLUMN_MIN_WIDTH_IN_PIXELS, COLUMN_RESIZE_DISTANCE_THRESHOLD as _TABLE_COLUMN_RESIZE_DISTANCE_THRESHOLD, COLUMN_WIDTH_PRECISION as _TABLE_COLUMN_WIDTH_PRECISION, defaultColors as _TABLE_DEFAULT_COLORS, ColorInputView as _TableColorInputView, MouseEventsObserver as _TableMouseEventsObserver, addDefaultUnitToNumericValue as _addDefaultUnitToNumericValue, adjustLastColumnIndex as _adjustLastTableColumnIndex, adjustLastRowIndex as _adjustLastTableRowIndex, clamp as _clamp, colorFieldValidator as _colorTableFieldValidator, convertParagraphInTableCell as _convertParagraphInTableCell, createEmptyTableCell as _createEmptyTableCell, createFilledArray as _createFilledArray, cropTableToDimensions as _cropTableToDimensions, downcastTable as _downcastTable, downcastTableAttribute as _downcastTableAttribute, downcastAttributeToStyle as _downcastTableAttributeToStyle, downcastCell as _downcastTableCell, downcastTableResizedClass as _downcastTableResizedClass, downcastRow as _downcastTableRow, enableProperty$1 as _enableTableCellProperty, ensureParagraphInTableCell as _ensureParagraphInTableCell, fillToolbar$1 as _fillTableOrCellToolbar, getBalloonCellPositionData as _getBalloonTableCellPositionData, getBalloonTablePositionData as _getBalloonTablePositionData, getBorderStyleLabels$1 as _getBorderTableStyleLabels, getChangedResizedTables as _getChangedResizedTables, getDefaultValueAdjusted as _getDefaultTableValueAdjusted, getDomCellOuterWidth as _getDomTableCellOuterWidth, getElementWidthInPixels as _getElementWidthInPixels, getHorizontallyOverlappingCells as _getHorizontallyOverlappingTableCells, getLabeledColorInputCreator$1 as _getLabeledTableColorInputCreator, getLocalizedColorErrorText as _getLocalizedTableColorErrorText, getLocalizedLengthErrorText as _getLocalizedTableLengthErrorText, getNormalizedDefaultProperties as _getNormalizedDefaultTableBaseProperties, getNormalizedDefaultCellProperties as _getNormalizedDefaultTableCellProperties, getNormalizedDefaultTableProperties as _getNormalizedDefaultTableProperties, getSelectedTableWidget as _getSelectedTableWidget, getSelectionAffectedTable as _getSelectionAffectedTable, getSelectionAffectedTableWidget as _getSelectionAffectedTableWidget, getSingleValue as _getTableBorderBoxSingleValue, getCaptionFromTableModelElement as _getTableCaptionFromModelElement, getCaptionFromModelSelection as _getTableCaptionFromModelSelection, getColumnEdgesIndexes as _getTableColumnEdgesIndexes, getTableColumnElements as _getTableColumnElements, getColumnGroupElement as _getTableColumnGroupElement, getColumnMinWidthAsPercentage as _getTableColumnMinWidthAsPercentage, getTableColumnsWidths as _getTableColumnsWidths, getBorderStyleDefinitions$1 as _getTableOrCellBorderStyleDefinitions, getTableWidgetAncestor as _getTableWidgetAncestor, getTableWidthInPixels as _getTableWidthInPixels, getVerticallyOverlappingCells as _getVerticallyOverlappingTableCells, injectTableCaptionPostFixer as _injectTableCaptionPostFixer, injectTableCellParagraphPostFixer as _injectTableCellParagraphPostFixer, injectTableLayoutPostFixer as _injectTableLayoutPostFixer, isSingleParagraphWithoutAttributes as _isSingleTableParagraphWithoutAttributes, isHeadingColumnCell as _isTableHeadingColumnCell, isTable as _isTableModelElement, lengthFieldValidator as _lengthTableFieldValidator, lineWidthFieldValidator as _lineWidthTableFieldValidator, matchTableCaptionViewElement as _matchTableCaptionViewElement, normalizeColumnWidths as _normalizeTableColumnWidths, removeEmptyColumns as _removeEmptyTableColumns, removeEmptyRows as _removeEmptyTableRows, removeEmptyRowsColumns as _removeEmptyTableRowsColumns, repositionContextualBalloon as _repositionTableContextualBalloon, skipEmptyTableRow as _skipEmptyTableRow, splitHorizontally as _splitTableCellHorizontally, splitVertically as _splitTableCellVertically, sumArray as _sumArray, tableCellRefreshHandler as _tableCellRefreshHandler, tableHeadingsRefreshHandler as _tableHeadingsRefreshHandler, toPrecision as _toPrecision, translateColSpanAttribute as _translateTableColspanAttribute, trimTableCellIfNeeded as _trimTableCellIfNeeded, upcastStyleToAttribute as _upcastNormalizedTableStyleToAttribute, upcastTable as _upcastTable, upcastBorderStyles as _upcastTableBorderStyles, upcastColgroupElement as _upcastTableColgroupElement, upcastTableFigure as _upcastTableFigure, updateColumnElements as _updateTableColumnElements, updateNumericAttribute as _updateTableNumericAttribute };
14126
16111
  //# sourceMappingURL=index.js.map