@ckeditor/ckeditor5-table 0.0.0-nightly-20251218.0 → 0.0.0-nightly-next-20251218.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 (112) hide show
  1. package/build/table.js +2 -2
  2. package/build/translations/af.js +1 -1
  3. package/build/translations/ar.js +1 -1
  4. package/build/translations/ast.js +1 -1
  5. package/build/translations/az.js +1 -1
  6. package/build/translations/be.js +1 -1
  7. package/build/translations/bg.js +1 -1
  8. package/build/translations/bn.js +1 -1
  9. package/build/translations/bs.js +1 -1
  10. package/build/translations/ca.js +1 -1
  11. package/build/translations/cs.js +1 -1
  12. package/build/translations/da.js +1 -1
  13. package/build/translations/de-ch.js +1 -1
  14. package/build/translations/de.js +1 -1
  15. package/build/translations/el.js +1 -1
  16. package/build/translations/en-au.js +1 -1
  17. package/build/translations/en-gb.js +1 -1
  18. package/build/translations/eo.js +1 -1
  19. package/build/translations/es-co.js +1 -1
  20. package/build/translations/es.js +1 -1
  21. package/build/translations/et.js +1 -1
  22. package/build/translations/eu.js +1 -1
  23. package/build/translations/fa.js +1 -1
  24. package/build/translations/fi.js +1 -1
  25. package/build/translations/fr.js +1 -1
  26. package/build/translations/gl.js +1 -1
  27. package/build/translations/gu.js +1 -1
  28. package/build/translations/he.js +1 -1
  29. package/build/translations/hi.js +1 -1
  30. package/build/translations/hr.js +1 -1
  31. package/build/translations/hu.js +1 -1
  32. package/build/translations/hy.js +1 -1
  33. package/build/translations/id.js +1 -1
  34. package/build/translations/it.js +1 -1
  35. package/build/translations/ja.js +1 -1
  36. package/build/translations/jv.js +1 -1
  37. package/build/translations/kk.js +1 -1
  38. package/build/translations/km.js +1 -1
  39. package/build/translations/kn.js +1 -1
  40. package/build/translations/ko.js +1 -1
  41. package/build/translations/ku.js +1 -1
  42. package/build/translations/lt.js +1 -1
  43. package/build/translations/lv.js +1 -1
  44. package/build/translations/ms.js +1 -1
  45. package/build/translations/nb.js +1 -1
  46. package/build/translations/ne.js +1 -1
  47. package/build/translations/nl.js +1 -1
  48. package/build/translations/no.js +1 -1
  49. package/build/translations/oc.js +1 -1
  50. package/build/translations/pl.js +1 -1
  51. package/build/translations/pt-br.js +1 -1
  52. package/build/translations/pt.js +1 -1
  53. package/build/translations/ro.js +1 -1
  54. package/build/translations/ru.js +1 -1
  55. package/build/translations/si.js +1 -1
  56. package/build/translations/sk.js +1 -1
  57. package/build/translations/sl.js +1 -1
  58. package/build/translations/sq.js +1 -1
  59. package/build/translations/sr-latn.js +1 -1
  60. package/build/translations/sr.js +1 -1
  61. package/build/translations/sv.js +1 -1
  62. package/build/translations/th.js +1 -1
  63. package/build/translations/ti.js +1 -1
  64. package/build/translations/tk.js +1 -1
  65. package/build/translations/tr.js +1 -1
  66. package/build/translations/tt.js +1 -1
  67. package/build/translations/ug.js +1 -1
  68. package/build/translations/uk.js +1 -1
  69. package/build/translations/ur.js +1 -1
  70. package/build/translations/uz.js +1 -1
  71. package/build/translations/vi.js +1 -1
  72. package/build/translations/zh-cn.js +1 -1
  73. package/build/translations/zh.js +1 -1
  74. package/ckeditor5-metadata.json +11 -2
  75. package/dist/index-content.css +30 -30
  76. package/dist/index-editor.css +104 -170
  77. package/dist/index.css +147 -237
  78. package/dist/index.css.map +1 -1
  79. package/dist/index.js +303 -2395
  80. package/dist/index.js.map +1 -1
  81. package/lang/contexts.json +0 -4
  82. package/package.json +9 -9
  83. package/src/augmentation.d.ts +0 -15
  84. package/src/converters/downcast.js +3 -12
  85. package/src/index.d.ts +0 -4
  86. package/src/index.js +0 -5
  87. package/src/tablecellproperties/tablecellpropertiesediting.js +2 -4
  88. package/src/tablecellproperties/tablecellpropertiesui.js +30 -10
  89. package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +35 -0
  90. package/src/tablecellproperties/ui/tablecellpropertiesview.js +137 -23
  91. package/src/tableconfig.d.ts +4 -4
  92. package/src/tableproperties/tablepropertiesediting.js +14 -147
  93. package/src/tableproperties/ui/tablepropertiesview.d.ts +8 -0
  94. package/src/tableproperties/ui/tablepropertiesview.js +59 -37
  95. package/src/utils/common.js +2 -3
  96. package/theme/formrow.css +2 -0
  97. package/theme/tableform.css +1 -5
  98. package/theme/tableproperties.css +60 -0
  99. package/src/tablecellproperties/tablecellpropertiesuiexperimental.d.ts +0 -128
  100. package/src/tablecellproperties/tablecellpropertiesuiexperimental.js +0 -408
  101. package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.d.ts +0 -266
  102. package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.js +0 -744
  103. package/src/tableproperties/tablepropertiesuiexperimental.d.ts +0 -136
  104. package/src/tableproperties/tablepropertiesuiexperimental.js +0 -375
  105. package/src/tableproperties/ui/tablepropertiesviewexperimental.d.ts +0 -216
  106. package/src/tableproperties/ui/tablepropertiesviewexperimental.js +0 -544
  107. package/src/utils/ui/table-propertiesexperimental.d.ts +0 -215
  108. package/src/utils/ui/table-propertiesexperimental.js +0 -391
  109. package/theme/formrow-experimental.css +0 -15
  110. package/theme/tablecellproperties-experimental.css +0 -4
  111. package/theme/tableform-experimental.css +0 -61
  112. package/theme/tableproperties-experimental.css +0 -78
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, 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';
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';
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';
@@ -1053,8 +1053,8 @@ const downcastTableAlignmentConfig = {
1053
1053
  *
1054
1054
  * @internal
1055
1055
  */ function isTableCellTypeEnabled(editor) {
1056
- const { model, config } = editor;
1057
- return model.schema.checkAttribute('tableCell', 'tableCellType') && config.get('experimentalFlags.tableCellTypeSupport') === true;
1056
+ const { model } = editor;
1057
+ return model.schema.checkAttribute('tableCell', 'tableCellType');
1058
1058
  }
1059
1059
 
1060
1060
  /**
@@ -2175,10 +2175,7 @@ const downcastTableAlignmentConfig = {
2175
2175
  * Downcasts a plain table (also used in the clipboard pipeline).
2176
2176
  */ function convertPlainTable(editor) {
2177
2177
  return (table, conversionApi)=>{
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)) {
2178
+ if (!conversionApi.options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2182
2179
  return null;
2183
2180
  }
2184
2181
  return downcastPlainTable(table, conversionApi, editor);
@@ -2188,10 +2185,7 @@ const downcastTableAlignmentConfig = {
2188
2185
  * Downcasts a plain table caption (also used in the clipboard pipeline).
2189
2186
  */ function convertPlainTableCaption(editor) {
2190
2187
  return (modelElement, { writer, options })=>{
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)) {
2188
+ if (!options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2195
2189
  return null;
2196
2190
  }
2197
2191
  if (modelElement.parent.name === 'table') {
@@ -2279,10 +2273,7 @@ const downcastTableAlignmentConfig = {
2279
2273
  return dispatcher.on(`attribute:${modelAttribute}:table`, (evt, data, conversionApi)=>{
2280
2274
  const { item, attributeNewValue } = data;
2281
2275
  const { mapper, writer } = conversionApi;
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)) {
2276
+ if (!conversionApi.options.isClipboardPipeline && !editor.plugins.has('PlainTableOutput')) {
2286
2277
  return;
2287
2278
  }
2288
2279
  if (!conversionApi.consumable.consume(item, evt.name)) {
@@ -7907,7 +7898,7 @@ const isEmpty = (val)=>val === '';
7907
7898
  *
7908
7899
  * @internal
7909
7900
  * @param t The "t" function provided by the editor that is used to localize strings.
7910
- */ function getBorderStyleLabels$1(t) {
7901
+ */ function getBorderStyleLabels(t) {
7911
7902
  return {
7912
7903
  none: t('None'),
7913
7904
  solid: t('Solid'),
@@ -7977,9 +7968,9 @@ const isEmpty = (val)=>val === '';
7977
7968
  *
7978
7969
  * @internal
7979
7970
  * @param defaultStyle The default border.
7980
- */ function getBorderStyleDefinitions$1(view, defaultStyle) {
7971
+ */ function getBorderStyleDefinitions(view, defaultStyle) {
7981
7972
  const itemDefinitions = new Collection();
7982
- const styleLabels = getBorderStyleLabels$1(view.t);
7973
+ const styleLabels = getBorderStyleLabels(view.t);
7983
7974
  for(const style in styleLabels){
7984
7975
  const definition = {
7985
7976
  type: 'button',
@@ -8022,7 +8013,7 @@ const isEmpty = (val)=>val === '';
8022
8013
  * @param options.propertyName The name of the observable property in the view.
8023
8014
  * @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
8024
8015
  * @param options.defaultValue Default value for the property.
8025
- */ function fillToolbar$1(options) {
8016
+ */ function fillToolbar(options) {
8026
8017
  const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
8027
8018
  for(const name in labels){
8028
8019
  const button = new ButtonView(view.locale);
@@ -8226,10 +8217,10 @@ const isEmpty = (val)=>val === '';
8226
8217
  * @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
8227
8218
  * the "Restore default" button. Instead of clearing the input field, the default color value will be set.
8228
8219
  * @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
8229
- */ function getLabeledColorInputCreator$1(options) {
8220
+ */ function getLabeledColorInputCreator(options) {
8230
8221
  return (labeledFieldView, viewUid, statusUid)=>{
8231
8222
  const colorInputView = new ColorInputView(labeledFieldView.locale, {
8232
- colorDefinitions: colorConfigToColorGridDefinitions$1(options.colorConfig),
8223
+ colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
8233
8224
  columns: options.columns,
8234
8225
  defaultColorValue: options.defaultColorValue,
8235
8226
  colorPickerConfig: options.colorPickerConfig
@@ -8256,7 +8247,7 @@ const isEmpty = (val)=>val === '';
8256
8247
  const parsedValue = parseFloat(value);
8257
8248
  return !Number.isNaN(parsedValue) && value === String(parsedValue);
8258
8249
  }
8259
- function colorConfigToColorGridDefinitions$1(colorConfig) {
8250
+ function colorConfigToColorGridDefinitions(colorConfig) {
8260
8251
  return colorConfig.map((item)=>({
8261
8252
  color: item.model,
8262
8253
  label: item.label,
@@ -8294,6 +8285,9 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8294
8285
  /**
8295
8286
  * An input that allows specifying the table cell background color.
8296
8287
  */ backgroundInput;
8288
+ /**
8289
+ * A dropdown that allows selecting the type of the table cell (data or header).
8290
+ */ cellTypeDropdown;
8297
8291
  /**
8298
8292
  * An input that allows specifying the table cell padding.
8299
8293
  */ paddingInput;
@@ -8315,6 +8309,9 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8315
8309
  /**
8316
8310
  * The "Cancel" button view.
8317
8311
  */ cancelButtonView;
8312
+ /**
8313
+ * The "Back" button view.
8314
+ */ backButtonView;
8318
8315
  /**
8319
8316
  * A collection of views that can be focused in the form.
8320
8317
  */ _focusables;
@@ -8340,11 +8337,13 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8340
8337
  width: '',
8341
8338
  height: '',
8342
8339
  horizontalAlignment: '',
8343
- verticalAlignment: ''
8340
+ verticalAlignment: '',
8341
+ cellType: ''
8344
8342
  });
8345
8343
  this.options = options;
8346
8344
  const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
8347
8345
  const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
8346
+ const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
8348
8347
  const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
8349
8348
  const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
8350
8349
  this.focusTracker = new FocusTracker();
@@ -8354,6 +8353,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8354
8353
  this.borderWidthInput = borderWidthInput;
8355
8354
  this.borderColorInput = borderColorInput;
8356
8355
  this.backgroundInput = backgroundInput;
8356
+ this.cellTypeDropdown = cellTypeDropdown;
8357
8357
  this.paddingInput = this._createPaddingField();
8358
8358
  this.widthInput = widthInput;
8359
8359
  this.heightInput = heightInput;
@@ -8365,6 +8365,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8365
8365
  const { saveButtonView, cancelButtonView } = this._createActionButtons();
8366
8366
  this.saveButtonView = saveButtonView;
8367
8367
  this.cancelButtonView = cancelButtonView;
8368
+ this.backButtonView = this._createBackButton();
8368
8369
  this._focusables = new ViewCollection();
8369
8370
  this._focusCycler = new FocusCycler({
8370
8371
  focusables: this._focusables,
@@ -8378,28 +8379,42 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8378
8379
  }
8379
8380
  });
8380
8381
  // Form header.
8381
- this.children.add(new FormHeaderView(locale, {
8382
+ const header = new FormHeaderView(locale, {
8382
8383
  label: this.t('Cell properties')
8383
- }));
8384
+ });
8385
+ header.children.add(this.backButtonView, 0);
8386
+ this.children.add(header);
8384
8387
  // Border row.
8385
8388
  this.children.add(new FormRowView(locale, {
8386
8389
  labelView: borderRowLabel,
8387
8390
  children: [
8388
8391
  borderRowLabel,
8389
8392
  borderStyleDropdown,
8390
- borderColorInput,
8391
- borderWidthInput
8393
+ borderWidthInput,
8394
+ borderColorInput
8392
8395
  ],
8393
8396
  class: 'ck-table-form__border-row'
8394
8397
  }));
8395
- // Background.
8398
+ // Background and cell type.
8396
8399
  this.children.add(new FormRowView(locale, {
8397
- labelView: backgroundRowLabel,
8398
8400
  children: [
8399
- backgroundRowLabel,
8400
- backgroundInput
8401
- ],
8402
- class: 'ck-table-form__background-row'
8401
+ new FormRowView(locale, {
8402
+ labelView: cellTypeRowLabel,
8403
+ children: [
8404
+ cellTypeRowLabel,
8405
+ cellTypeDropdown
8406
+ ],
8407
+ class: 'ck-table-form__cell-type-row'
8408
+ }),
8409
+ new FormRowView(locale, {
8410
+ labelView: backgroundRowLabel,
8411
+ children: [
8412
+ backgroundRowLabel,
8413
+ backgroundInput
8414
+ ],
8415
+ class: 'ck-table-form__background-row'
8416
+ })
8417
+ ]
8403
8418
  }));
8404
8419
  // Dimensions row and padding.
8405
8420
  this.children.add(new FormRowView(locale, {
@@ -8437,8 +8452,8 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8437
8452
  // Action row.
8438
8453
  this.children.add(new FormRowView(locale, {
8439
8454
  children: [
8440
- this.saveButtonView,
8441
- this.cancelButtonView
8455
+ this.cancelButtonView,
8456
+ this.saveButtonView
8442
8457
  ],
8443
8458
  class: 'ck-table-form__action-row'
8444
8459
  }));
@@ -8477,14 +8492,16 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8477
8492
  this.borderStyleDropdown,
8478
8493
  this.borderColorInput,
8479
8494
  this.borderWidthInput,
8495
+ this.cellTypeDropdown,
8480
8496
  this.backgroundInput,
8481
8497
  this.widthInput,
8482
8498
  this.heightInput,
8483
8499
  this.paddingInput,
8484
8500
  this.horizontalAlignmentToolbar,
8485
8501
  this.verticalAlignmentToolbar,
8502
+ this.cancelButtonView,
8486
8503
  this.saveButtonView,
8487
- this.cancelButtonView
8504
+ this.backButtonView
8488
8505
  ].forEach((view)=>{
8489
8506
  // Register the view as focusable.
8490
8507
  this._focusables.add(view);
@@ -8519,7 +8536,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8519
8536
  width: defaultTableCellProperties.borderWidth,
8520
8537
  color: defaultTableCellProperties.borderColor
8521
8538
  };
8522
- const colorInputCreator = getLabeledColorInputCreator$1({
8539
+ const colorInputCreator = getLabeledColorInputCreator({
8523
8540
  colorConfig: this.options.borderColors,
8524
8541
  columns: 5,
8525
8542
  defaultColorValue: defaultBorder.color,
@@ -8532,7 +8549,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8532
8549
  const borderRowLabel = new LabelView(locale);
8533
8550
  borderRowLabel.text = t('Border');
8534
8551
  // -- Style ---------------------------------------------------
8535
- const styleLabels = getBorderStyleLabels$1(t);
8552
+ const styleLabels = getBorderStyleLabels(t);
8536
8553
  const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
8537
8554
  borderStyleDropdown.set({
8538
8555
  label: accessibleLabel,
@@ -8552,7 +8569,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8552
8569
  this.borderStyle = evt.source._borderStyleValue;
8553
8570
  });
8554
8571
  borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
8555
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
8572
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
8556
8573
  role: 'menu',
8557
8574
  ariaLabel: accessibleLabel
8558
8575
  });
@@ -8563,7 +8580,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8563
8580
  class: 'ck-table-form__border-width'
8564
8581
  });
8565
8582
  borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
8566
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
8583
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
8567
8584
  borderWidthInput.fieldView.on('input', ()=>{
8568
8585
  this.borderWidth = borderWidthInput.fieldView.element.value;
8569
8586
  });
@@ -8574,7 +8591,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8574
8591
  class: 'ck-table-form__border-color'
8575
8592
  });
8576
8593
  borderColorInput.fieldView.bind('value').to(this, 'borderColor');
8577
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
8594
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
8578
8595
  borderColorInput.fieldView.on('input', ()=>{
8579
8596
  this.borderColor = borderColorInput.fieldView.value;
8580
8597
  });
@@ -8582,12 +8599,12 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8582
8599
  this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
8583
8600
  // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
8584
8601
  // See: https://github.com/ckeditor/ckeditor5/issues/6227.
8585
- if (!isBorderStyleSet$3(newValue)) {
8602
+ if (!isBorderStyleSet$1(newValue)) {
8586
8603
  this.borderColor = '';
8587
8604
  this.borderWidth = '';
8588
8605
  }
8589
8606
  // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
8590
- if (!isBorderStyleSet$3(oldValue)) {
8607
+ if (!isBorderStyleSet$1(oldValue)) {
8591
8608
  this.borderColor = defaultBorder.color;
8592
8609
  this.borderWidth = defaultBorder.width;
8593
8610
  }
@@ -8610,7 +8627,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8610
8627
  const backgroundRowLabel = new LabelView(locale);
8611
8628
  backgroundRowLabel.text = t('Background');
8612
8629
  // -- Background color input -----------------------------------
8613
- const colorInputCreator = getLabeledColorInputCreator$1({
8630
+ const colorInputCreator = getLabeledColorInputCreator({
8614
8631
  colorConfig: this.options.backgroundColors,
8615
8632
  columns: 5,
8616
8633
  defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
@@ -8630,6 +8647,46 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8630
8647
  backgroundInput
8631
8648
  };
8632
8649
  }
8650
+ /**
8651
+ * Create cell type field.
8652
+ *
8653
+ * * {@link #cellTypeDropdown}.
8654
+ *
8655
+ * @internal
8656
+ */ _createCellTypeField() {
8657
+ const locale = this.locale;
8658
+ const t = this.t;
8659
+ const cellTypeRowLabel = new LabelView(locale);
8660
+ cellTypeRowLabel.text = t('Cell type');
8661
+ const cellTypeLabels = this._cellTypeLabels;
8662
+ const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
8663
+ cellTypeDropdown.set({
8664
+ label: t('Cell type'),
8665
+ class: 'ck-table-cell-properties-form__cell-type'
8666
+ });
8667
+ cellTypeDropdown.fieldView.buttonView.set({
8668
+ ariaLabel: t('Cell type'),
8669
+ ariaLabelledBy: undefined,
8670
+ isOn: false,
8671
+ withText: true,
8672
+ tooltip: t('Cell type')
8673
+ });
8674
+ cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
8675
+ return cellTypeLabels[value || 'data'];
8676
+ });
8677
+ cellTypeDropdown.fieldView.on('execute', (evt)=>{
8678
+ this.cellType = evt.source._cellTypeValue;
8679
+ });
8680
+ cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
8681
+ addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
8682
+ role: 'menu',
8683
+ ariaLabel: t('Cell type')
8684
+ });
8685
+ return {
8686
+ cellTypeRowLabel,
8687
+ cellTypeDropdown
8688
+ };
8689
+ }
8633
8690
  /**
8634
8691
  * Creates the following form fields:
8635
8692
  *
@@ -8726,9 +8783,10 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8726
8783
  horizontalAlignmentToolbar.set({
8727
8784
  isCompact: true,
8728
8785
  role: 'radiogroup',
8729
- ariaLabel: t('Horizontal text alignment toolbar')
8786
+ ariaLabel: t('Horizontal text alignment toolbar'),
8787
+ class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
8730
8788
  });
8731
- fillToolbar$1({
8789
+ fillToolbar({
8732
8790
  view: this,
8733
8791
  icons: ALIGNMENT_ICONS,
8734
8792
  toolbar: horizontalAlignmentToolbar,
@@ -8752,9 +8810,10 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8752
8810
  verticalAlignmentToolbar.set({
8753
8811
  isCompact: true,
8754
8812
  role: 'radiogroup',
8755
- ariaLabel: t('Vertical text alignment toolbar')
8813
+ ariaLabel: t('Vertical text alignment toolbar'),
8814
+ class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
8756
8815
  });
8757
- fillToolbar$1({
8816
+ fillToolbar({
8758
8817
  view: this,
8759
8818
  icons: ALIGNMENT_ICONS,
8760
8819
  toolbar: verticalAlignmentToolbar,
@@ -8786,8 +8845,7 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8786
8845
  ];
8787
8846
  saveButtonView.set({
8788
8847
  label: t('Save'),
8789
- icon: IconCheck,
8790
- class: 'ck-button-save',
8848
+ class: 'ck-button-action',
8791
8849
  type: 'submit',
8792
8850
  withText: true
8793
8851
  });
@@ -8796,8 +8854,6 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8796
8854
  });
8797
8855
  cancelButtonView.set({
8798
8856
  label: t('Cancel'),
8799
- icon: IconCancel,
8800
- class: 'ck-button-cancel',
8801
8857
  withText: true
8802
8858
  });
8803
8859
  cancelButtonView.delegate('execute').to(this, 'cancel');
@@ -8806,6 +8862,43 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8806
8862
  cancelButtonView
8807
8863
  };
8808
8864
  }
8865
+ /**
8866
+ * Creates a back button view that cancels the form.
8867
+ */ _createBackButton() {
8868
+ const t = this.locale.t;
8869
+ const backButton = new ButtonView(this.locale);
8870
+ backButton.set({
8871
+ class: 'ck-button-back',
8872
+ label: t('Back'),
8873
+ icon: IconPreviousArrow,
8874
+ tooltip: true
8875
+ });
8876
+ backButton.delegate('execute').to(this, 'cancel');
8877
+ return backButton;
8878
+ }
8879
+ /**
8880
+ * Creates the cell type dropdown definitions.
8881
+ */ _getCellTypeDefinitions() {
8882
+ const itemDefinitions = new Collection();
8883
+ const cellTypeLabels = this._cellTypeLabels;
8884
+ for (const type of [
8885
+ 'data',
8886
+ 'header'
8887
+ ]){
8888
+ const definition = {
8889
+ type: 'button',
8890
+ model: new UIModel({
8891
+ _cellTypeValue: type,
8892
+ label: cellTypeLabels[type],
8893
+ role: 'menuitemradio',
8894
+ withText: true
8895
+ })
8896
+ };
8897
+ definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
8898
+ itemDefinitions.add(definition);
8899
+ }
8900
+ return itemDefinitions;
8901
+ }
8809
8902
  /**
8810
8903
  * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
8811
8904
  */ get _horizontalAlignmentLabels() {
@@ -8842,8 +8935,17 @@ function colorConfigToColorGridDefinitions$1(colorConfig) {
8842
8935
  bottom: t('Align cell text to the bottom')
8843
8936
  };
8844
8937
  }
8938
+ /**
8939
+ * Provides localized labels for {@link #cellTypeDropdown}.
8940
+ */ get _cellTypeLabels() {
8941
+ const t = this.t;
8942
+ return {
8943
+ data: t('Data cell'),
8944
+ header: t('Header cell')
8945
+ };
8946
+ }
8845
8947
  }
8846
- function isBorderStyleSet$3(value) {
8948
+ function isBorderStyleSet$1(value) {
8847
8949
  return value !== 'none';
8848
8950
  }
8849
8951
 
@@ -8942,9 +9044,9 @@ const BALLOON_POSITIONS = /* #__PURE__ */ (()=>[
8942
9044
  return Rect.getBoundingRect(rects);
8943
9045
  }
8944
9046
 
8945
- const ERROR_TEXT_TIMEOUT$3 = 500;
9047
+ const ERROR_TEXT_TIMEOUT$1 = 500;
8946
9048
  // Map of view properties and related commands.
8947
- const propertyToCommandMap$3 = {
9049
+ const propertyToCommandMap$1 = {
8948
9050
  borderStyle: 'tableCellBorderStyle',
8949
9051
  borderColor: 'tableCellBorderColor',
8950
9052
  borderWidth: 'tableCellBorderWidth',
@@ -8953,7 +9055,8 @@ const propertyToCommandMap$3 = {
8953
9055
  padding: 'tableCellPadding',
8954
9056
  backgroundColor: 'tableCellBackgroundColor',
8955
9057
  horizontalAlignment: 'tableCellHorizontalAlignment',
8956
- verticalAlignment: 'tableCellVerticalAlignment'
9058
+ verticalAlignment: 'tableCellVerticalAlignment',
9059
+ cellType: 'tableCellType'
8957
9060
  };
8958
9061
  /**
8959
9062
  * The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
@@ -9040,7 +9143,7 @@ const propertyToCommandMap$3 = {
9040
9143
  tooltip: true
9041
9144
  });
9042
9145
  this.listenTo(view, 'execute', ()=>this._showView());
9043
- const commands = Object.values(propertyToCommandMap$3).map((commandName)=>editor.commands.get(commandName));
9146
+ const commands = Object.values(propertyToCommandMap$1).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
9044
9147
  view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
9045
9148
  return view;
9046
9149
  });
@@ -9146,6 +9249,11 @@ const propertyToCommandMap$3 = {
9146
9249
  }));
9147
9250
  view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
9148
9251
  view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
9252
+ const cellTypeCommand = editor.commands.get('tableCellType');
9253
+ if (cellTypeCommand) {
9254
+ view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
9255
+ view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
9256
+ }
9149
9257
  return view;
9150
9258
  }
9151
9259
  /**
@@ -9158,12 +9266,24 @@ const propertyToCommandMap$3 = {
9158
9266
  */ _fillViewFormFromCommandValues() {
9159
9267
  const commands = this.editor.commands;
9160
9268
  const borderStyleCommand = commands.get('tableCellBorderStyle');
9161
- Object.entries(propertyToCommandMap$3).map(([property, commandName])=>{
9269
+ Object.entries(propertyToCommandMap$1).flatMap(([property, commandName])=>{
9270
+ const command = commands.get(commandName);
9271
+ if (!command) {
9272
+ return [];
9273
+ }
9162
9274
  const propertyKey = property;
9163
- const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
9164
- return [
9275
+ let defaultValue;
9276
+ if (propertyKey === 'cellType') {
9277
+ defaultValue = '';
9278
+ } else {
9279
+ defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
9280
+ }
9281
+ const entry = [
9165
9282
  property,
9166
- commands.get(commandName).value || defaultValue
9283
+ command.value || defaultValue
9284
+ ];
9285
+ return [
9286
+ entry
9167
9287
  ];
9168
9288
  }).forEach(([property, value])=>{
9169
9289
  // Do not set the `border-color` and `border-width` fields if `border-style:none`.
@@ -9264,7 +9384,7 @@ const propertyToCommandMap$3 = {
9264
9384
  const { commandName, viewField, validator, errorText } = options;
9265
9385
  const setErrorTextDebounced = debounce(()=>{
9266
9386
  viewField.errorText = errorText;
9267
- }, ERROR_TEXT_TIMEOUT$3);
9387
+ }, ERROR_TEXT_TIMEOUT$1);
9268
9388
  return (evt, propertyName, newValue)=>{
9269
9389
  setErrorTextDebounced.cancel();
9270
9390
  // Do not execute the command on initial call (opening the table properties view).
@@ -10050,10 +10170,8 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
10050
10170
  editor.commands.add('tableCellHorizontalAlignment', new TableCellHorizontalAlignmentCommand(editor, defaultTableCellProperties.horizontalAlignment));
10051
10171
  enableVerticalAlignmentProperty(schema, conversion, defaultTableCellProperties.verticalAlignment);
10052
10172
  editor.commands.add('tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand(editor, defaultTableCellProperties.verticalAlignment));
10053
- if (editor.config.get('experimentalFlags.tableCellTypeSupport')) {
10054
- enableCellTypeProperty(editor);
10055
- editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
10056
- }
10173
+ enableCellTypeProperty(editor);
10174
+ editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
10057
10175
  }
10058
10176
  }
10059
10177
  /**
@@ -12238,7 +12356,7 @@ const TABLE_TYPES = [
12238
12356
  const defaultTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
12239
12357
  includeAlignmentProperty: true
12240
12358
  });
12241
- const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles') !== false;
12359
+ const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles') === true;
12242
12360
  editor.data.addStyleProcessorRules(addMarginStylesRules);
12243
12361
  editor.data.addStyleProcessorRules(addBorderStylesRules);
12244
12362
  enableBorderProperties(editor, {
@@ -12249,11 +12367,7 @@ const TABLE_TYPES = [
12249
12367
  editor.commands.add('tableBorderColor', new TableBorderColorCommand(editor, defaultTableProperties.borderColor));
12250
12368
  editor.commands.add('tableBorderStyle', new TableBorderStyleCommand(editor, defaultTableProperties.borderStyle));
12251
12369
  editor.commands.add('tableBorderWidth', new TableBorderWidthCommand(editor, defaultTableProperties.borderWidth));
12252
- if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
12253
- enableExtendedAlignmentProperty(schema, conversion, defaultTableProperties.alignment, useInlineStyles);
12254
- } else {
12255
- enableAlignmentProperty(schema, conversion, defaultTableProperties.alignment);
12256
- }
12370
+ enableAlignmentProperty(schema, conversion, defaultTableProperties.alignment, useInlineStyles);
12257
12371
  editor.commands.add('tableAlignment', new TableAlignmentCommand(editor, defaultTableProperties.alignment));
12258
12372
  enableTableToFigureProperty(schema, conversion, {
12259
12373
  modelAttribute: 'tableWidth',
@@ -12280,20 +12394,18 @@ const TABLE_TYPES = [
12280
12394
  defaultValue: defaultTableProperties.backgroundColor
12281
12395
  });
12282
12396
  editor.commands.add('tableBackgroundColor', new TableBackgroundColorCommand(editor, defaultTableProperties.backgroundColor));
12283
- if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
12284
- const viewDoc = editor.editing.view.document;
12285
- // Adjust clipboard output to wrap tables in divs if needed (for alignment).
12286
- this.listenTo(viewDoc, 'clipboardOutput', (evt, data)=>{
12287
- editor.editing.view.change((writer)=>{
12288
- for (const { item } of writer.createRangeIn(data.content)){
12289
- wrapInDivIfNeeded(item, writer);
12290
- }
12291
- data.dataTransfer.setData('text/html', this.editor.data.htmlProcessor.toData(data.content));
12292
- });
12293
- }, {
12294
- priority: 'lowest'
12397
+ const viewDoc = editor.editing.view.document;
12398
+ // Adjust clipboard output to wrap tables in divs if needed (for alignment).
12399
+ this.listenTo(viewDoc, 'clipboardOutput', (evt, data)=>{
12400
+ editor.editing.view.change((writer)=>{
12401
+ for (const { item } of writer.createRangeIn(data.content)){
12402
+ wrapInDivIfNeeded(item, writer);
12403
+ }
12404
+ data.dataTransfer.setData('text/html', this.editor.data.htmlProcessor.toData(data.content));
12295
12405
  });
12296
- }
12406
+ }, {
12407
+ priority: 'lowest'
12408
+ });
12297
12409
  }
12298
12410
  }
12299
12411
  /**
@@ -12363,10 +12475,10 @@ function insertWrapperWithAlignment(writer, align, table) {
12363
12475
  });
12364
12476
  }
12365
12477
  /**
12366
- * Enables the extended block`'alignment'` attribute for table.
12478
+ * Enables the `'alignment'` attribute for table.
12367
12479
  *
12368
12480
  * @param defaultValue The default alignment value.
12369
- */ function enableExtendedAlignmentProperty(schema, conversion, defaultValue, useInlineStyles) {
12481
+ */ function enableAlignmentProperty(schema, conversion, defaultValue, useInlineStyles) {
12370
12482
  schema.extend('table', {
12371
12483
  allowAttributes: [
12372
12484
  'tableAlignment'
@@ -12466,170 +12578,32 @@ function insertWrapperWithAlignment(writer, align, table) {
12466
12578
  conversion.for('upcast').add(upcastTableAlignedDiv(defaultValue));
12467
12579
  }
12468
12580
  /**
12469
- * Enables the `'alignment'` attribute for table.
12581
+ * Returns a function that converts the table view representation:
12470
12582
  *
12471
- * @param defaultValue The default alignment value.
12472
- */ function enableAlignmentProperty(schema, conversion, defaultValue) {
12473
- const ALIGN_VALUES_REG_EXP = /^(left|center|right)$/;
12474
- const FLOAT_VALUES_REG_EXP = /^(left|none|right)$/;
12475
- schema.extend('table', {
12476
- allowAttributes: [
12477
- 'tableAlignment'
12478
- ]
12479
- });
12480
- schema.setAttributeProperties('tableAlignment', {
12481
- isFormatting: true
12482
- });
12483
- conversion.for('downcast').attributeToAttribute({
12484
- model: {
12485
- name: 'table',
12486
- key: 'tableAlignment',
12487
- values: [
12488
- 'left',
12489
- 'center',
12490
- 'right'
12491
- ]
12492
- },
12493
- view: {
12494
- left: {
12495
- key: 'style',
12496
- value: {
12497
- float: 'left'
12498
- }
12499
- },
12500
- right: {
12501
- key: 'style',
12502
- value: {
12503
- float: 'right'
12504
- }
12505
- },
12506
- center: (alignment, conversionApi, data)=>{
12507
- const value = data.item.getAttribute('tableType') !== 'layout' ? {
12508
- // Model: `alignment:center` => CSS: `float:none`.
12509
- float: 'none'
12510
- } : {
12511
- 'margin-left': 'auto',
12512
- 'margin-right': 'auto'
12513
- };
12514
- return {
12515
- key: 'style',
12516
- value
12517
- };
12518
- }
12519
- },
12520
- converterPriority: 'high'
12521
- });
12522
- conversion.for('upcast')// Support for the `float:*;` CSS definition for the table alignment.
12523
- .attributeToAttribute({
12524
- view: {
12525
- name: /^(table|figure)$/,
12526
- styles: {
12527
- float: FLOAT_VALUES_REG_EXP
12528
- }
12529
- },
12530
- model: {
12531
- key: 'tableAlignment',
12532
- value: (viewElement, conversionApi, data)=>{
12533
- // Ignore other figure elements.
12534
- if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
12535
- return;
12536
- }
12537
- const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12538
- let align = viewElement.getStyle('float');
12539
- // CSS: `float:none` => Model: `alignment:center`.
12540
- if (align === 'none') {
12541
- align = 'center';
12542
- }
12543
- if (align !== localDefaultValue) {
12544
- return align;
12545
- }
12546
- // Consume the style even if not applied to the element so it won't be processed by other converters.
12547
- conversionApi.consumable.consume(viewElement, {
12548
- styles: 'float'
12549
- });
12550
- }
12551
- }
12552
- })// Support for the `margin-left:auto; margin-right:auto;` CSS definition for the table alignment.
12553
- .attributeToAttribute({
12554
- view: {
12555
- name: /^(table|figure)$/,
12556
- styles: {
12557
- 'margin-left': 'auto',
12558
- 'margin-right': 'auto'
12559
- }
12560
- },
12561
- model: {
12562
- key: 'tableAlignment',
12563
- value: (viewElement, conversionApi, data)=>{
12564
- // Ignore other figure elements.
12565
- if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
12566
- return;
12567
- }
12568
- const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12569
- const align = 'center';
12570
- if (align !== localDefaultValue) {
12571
- return align;
12572
- }
12573
- // Consume the styles even if not applied to the element so it won't be processed by other converters.
12574
- conversionApi.consumable.consume(viewElement, {
12575
- styles: [
12576
- 'margin-left',
12577
- 'margin-right'
12578
- ]
12579
- });
12580
- }
12581
- }
12582
- })// Support for the `align` attribute as the backward compatibility while pasting from other sources.
12583
- .attributeToAttribute({
12584
- view: {
12585
- name: 'table',
12586
- attributes: {
12587
- align: ALIGN_VALUES_REG_EXP
12588
- }
12589
- },
12590
- model: {
12591
- key: 'tableAlignment',
12592
- value: (viewElement, conversionApi, data)=>{
12593
- const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
12594
- const align = viewElement.getAttribute('align');
12595
- if (align !== localDefaultValue) {
12596
- return align;
12597
- }
12598
- // Consume the attribute even if not applied to the element so it won't be processed by other converters.
12599
- conversionApi.consumable.consume(viewElement, {
12600
- attributes: 'align'
12601
- });
12602
- }
12603
- }
12604
- });
12605
- }
12606
- /**
12607
- * Returns a function that converts the table view representation:
12608
- *
12609
- * ```html
12610
- * <div align="right"><table>...</table></div>
12611
- * <!-- or -->
12612
- * <div align="center"><table>...</table></div>
12613
- * <!-- or -->
12614
- * <div align="left"><table>...</table></div>
12615
- * ```
12616
- *
12617
- * to the model representation:
12618
- *
12619
- * ```xml
12620
- * <table tableAlignment="right|center|left"></table>
12621
- * ```
12622
- *
12623
- * @internal
12624
- */ function upcastTableAlignedDiv(defaultValue) {
12625
- return (dispatcher)=>{
12626
- dispatcher.on('element:div', (evt, data, conversionApi)=>{
12627
- // Do not convert if this is not a "table wrapped in div with align attribute".
12628
- if (!conversionApi.consumable.test(data.viewItem, {
12629
- name: true,
12630
- attributes: 'align'
12631
- })) {
12632
- return;
12583
+ * ```html
12584
+ * <div align="right"><table>...</table></div>
12585
+ * <!-- or -->
12586
+ * <div align="center"><table>...</table></div>
12587
+ * <!-- or -->
12588
+ * <div align="left"><table>...</table></div>
12589
+ * ```
12590
+ *
12591
+ * to the model representation:
12592
+ *
12593
+ * ```xml
12594
+ * <table tableAlignment="right|center|left"></table>
12595
+ * ```
12596
+ *
12597
+ * @internal
12598
+ */ function upcastTableAlignedDiv(defaultValue) {
12599
+ return (dispatcher)=>{
12600
+ dispatcher.on('element:div', (evt, data, conversionApi)=>{
12601
+ // Do not convert if this is not a "table wrapped in div with align attribute".
12602
+ if (!conversionApi.consumable.test(data.viewItem, {
12603
+ name: true,
12604
+ attributes: 'align'
12605
+ })) {
12606
+ return;
12633
12607
  }
12634
12608
  // Find a table element inside the div element.
12635
12609
  const viewTable = getViewTableFromWrapper(data.viewItem);
@@ -12793,6 +12767,9 @@ function insertWrapperWithAlignment(writer, align, table) {
12793
12767
  /**
12794
12768
  * The "Cancel" button view.
12795
12769
  */ cancelButtonView;
12770
+ /**
12771
+ * The Back button view displayed in the header.
12772
+ */ backButtonView;
12796
12773
  /**
12797
12774
  * A collection of views that can be focused in the form.
12798
12775
  */ _focusables;
@@ -12834,6 +12811,7 @@ function insertWrapperWithAlignment(writer, align, table) {
12834
12811
  const { saveButtonView, cancelButtonView } = this._createActionButtons();
12835
12812
  this.saveButtonView = saveButtonView;
12836
12813
  this.cancelButtonView = cancelButtonView;
12814
+ this.backButtonView = this._createBackButton();
12837
12815
  this._focusables = new ViewCollection();
12838
12816
  this._focusCycler = new FocusCycler({
12839
12817
  focusables: this._focusables,
@@ -12847,29 +12825,22 @@ function insertWrapperWithAlignment(writer, align, table) {
12847
12825
  }
12848
12826
  });
12849
12827
  // Form header.
12850
- this.children.add(new FormHeaderView(locale, {
12828
+ const headerView = new FormHeaderView(locale, {
12851
12829
  label: this.t('Table properties')
12852
- }));
12830
+ });
12831
+ headerView.children.add(this.backButtonView, 0);
12832
+ this.children.add(headerView);
12853
12833
  // Border row.
12854
12834
  this.children.add(new FormRowView(locale, {
12855
12835
  labelView: borderRowLabel,
12856
12836
  children: [
12857
12837
  borderRowLabel,
12858
12838
  borderStyleDropdown,
12859
- borderColorInput,
12860
- borderWidthInput
12839
+ borderWidthInput,
12840
+ borderColorInput
12861
12841
  ],
12862
12842
  class: 'ck-table-form__border-row'
12863
12843
  }));
12864
- // Background row.
12865
- this.children.add(new FormRowView(locale, {
12866
- labelView: backgroundRowLabel,
12867
- children: [
12868
- backgroundRowLabel,
12869
- backgroundInput
12870
- ],
12871
- class: 'ck-table-form__background-row'
12872
- }));
12873
12844
  this.children.add(new FormRowView(locale, {
12874
12845
  children: [
12875
12846
  // Dimensions row.
@@ -12883,22 +12854,31 @@ function insertWrapperWithAlignment(writer, align, table) {
12883
12854
  ],
12884
12855
  class: 'ck-table-form__dimensions-row'
12885
12856
  }),
12886
- // Alignment row.
12857
+ // Background row.
12887
12858
  new FormRowView(locale, {
12888
- labelView: alignmentLabel,
12859
+ labelView: backgroundRowLabel,
12889
12860
  children: [
12890
- alignmentLabel,
12891
- alignmentToolbar
12861
+ backgroundRowLabel,
12862
+ backgroundInput
12892
12863
  ],
12893
- class: 'ck-table-properties-form__alignment-row'
12864
+ class: 'ck-table-form__background-row'
12894
12865
  })
12895
12866
  ]
12896
12867
  }));
12868
+ // Alignment row.
12869
+ this.children.add(new FormRowView(locale, {
12870
+ labelView: alignmentLabel,
12871
+ children: [
12872
+ alignmentLabel,
12873
+ alignmentToolbar
12874
+ ],
12875
+ class: 'ck-table-properties-form__alignment-row'
12876
+ }));
12897
12877
  // Action row.
12898
12878
  this.children.add(new FormRowView(locale, {
12899
12879
  children: [
12900
- this.saveButtonView,
12901
- this.cancelButtonView
12880
+ this.cancelButtonView,
12881
+ this.saveButtonView
12902
12882
  ],
12903
12883
  class: 'ck-table-form__action-row'
12904
12884
  }));
@@ -12935,14 +12915,15 @@ function insertWrapperWithAlignment(writer, align, table) {
12935
12915
  });
12936
12916
  [
12937
12917
  this.borderStyleDropdown,
12938
- this.borderColorInput,
12939
12918
  this.borderWidthInput,
12940
- this.backgroundInput,
12919
+ this.borderColorInput,
12941
12920
  this.widthInput,
12942
12921
  this.heightInput,
12922
+ this.backgroundInput,
12943
12923
  this.alignmentToolbar,
12924
+ this.cancelButtonView,
12944
12925
  this.saveButtonView,
12945
- this.cancelButtonView
12926
+ this.backButtonView
12946
12927
  ].forEach((view)=>{
12947
12928
  // Register the view as focusable.
12948
12929
  this._focusables.add(view);
@@ -12977,7 +12958,7 @@ function insertWrapperWithAlignment(writer, align, table) {
12977
12958
  width: defaultTableProperties.borderWidth,
12978
12959
  color: defaultTableProperties.borderColor
12979
12960
  };
12980
- const colorInputCreator = getLabeledColorInputCreator$1({
12961
+ const colorInputCreator = getLabeledColorInputCreator({
12981
12962
  colorConfig: this.options.borderColors,
12982
12963
  columns: 5,
12983
12964
  defaultColorValue: defaultBorder.color,
@@ -12990,7 +12971,7 @@ function insertWrapperWithAlignment(writer, align, table) {
12990
12971
  const borderRowLabel = new LabelView(locale);
12991
12972
  borderRowLabel.text = t('Border');
12992
12973
  // -- Style ---------------------------------------------------
12993
- const styleLabels = getBorderStyleLabels$1(t);
12974
+ const styleLabels = getBorderStyleLabels(t);
12994
12975
  const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
12995
12976
  borderStyleDropdown.set({
12996
12977
  label: accessibleLabel,
@@ -13010,7 +12991,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13010
12991
  this.borderStyle = evt.source._borderStyleValue;
13011
12992
  });
13012
12993
  borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
13013
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
12994
+ addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
13014
12995
  role: 'menu',
13015
12996
  ariaLabel: accessibleLabel
13016
12997
  });
@@ -13021,7 +13002,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13021
13002
  class: 'ck-table-form__border-width'
13022
13003
  });
13023
13004
  borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
13024
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
13005
+ borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
13025
13006
  borderWidthInput.fieldView.on('input', ()=>{
13026
13007
  this.borderWidth = borderWidthInput.fieldView.element.value;
13027
13008
  });
@@ -13032,7 +13013,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13032
13013
  class: 'ck-table-form__border-color'
13033
13014
  });
13034
13015
  borderColorInput.fieldView.bind('value').to(this, 'borderColor');
13035
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
13016
+ borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
13036
13017
  borderColorInput.fieldView.on('input', ()=>{
13037
13018
  this.borderColor = borderColorInput.fieldView.value;
13038
13019
  });
@@ -13040,12 +13021,12 @@ function insertWrapperWithAlignment(writer, align, table) {
13040
13021
  this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
13041
13022
  // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
13042
13023
  // See: https://github.com/ckeditor/ckeditor5/issues/6227.
13043
- if (!isBorderStyleSet$2(newValue)) {
13024
+ if (!isBorderStyleSet(newValue)) {
13044
13025
  this.borderColor = '';
13045
13026
  this.borderWidth = '';
13046
13027
  }
13047
13028
  // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
13048
- if (!isBorderStyleSet$2(oldValue)) {
13029
+ if (!isBorderStyleSet(oldValue)) {
13049
13030
  this.borderColor = defaultBorder.color;
13050
13031
  this.borderWidth = defaultBorder.width;
13051
13032
  }
@@ -13068,7 +13049,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13068
13049
  const backgroundRowLabel = new LabelView(locale);
13069
13050
  backgroundRowLabel.text = t('Background');
13070
13051
  // -- Background color input -----------------------------------
13071
- const backgroundInputCreator = getLabeledColorInputCreator$1({
13052
+ const backgroundInputCreator = getLabeledColorInputCreator({
13072
13053
  colorConfig: this.options.backgroundColors,
13073
13054
  columns: 5,
13074
13055
  defaultColorValue: this.options.defaultTableProperties.backgroundColor,
@@ -13150,7 +13131,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13150
13131
  const t = this.t;
13151
13132
  // -- Label ---------------------------------------------------
13152
13133
  const alignmentLabel = new LabelView(locale);
13153
- alignmentLabel.text = t('Alignment');
13134
+ alignmentLabel.text = t('Table Alignment');
13154
13135
  // -- Toolbar ---------------------------------------------------
13155
13136
  const alignmentToolbar = new ToolbarView(locale);
13156
13137
  alignmentToolbar.set({
@@ -13158,12 +13139,14 @@ function insertWrapperWithAlignment(writer, align, table) {
13158
13139
  isCompact: true,
13159
13140
  ariaLabel: t('Table alignment toolbar')
13160
13141
  });
13161
- fillToolbar$1({
13142
+ fillToolbar({
13162
13143
  view: this,
13163
13144
  icons: {
13164
13145
  left: IconObjectInlineLeft,
13165
13146
  center: IconObjectCenter,
13166
- right: IconObjectInlineRight
13147
+ right: IconObjectInlineRight,
13148
+ blockLeft: IconObjectLeft,
13149
+ blockRight: IconObjectRight
13167
13150
  },
13168
13151
  toolbar: alignmentToolbar,
13169
13152
  labels: this._alignmentLabels,
@@ -13194,8 +13177,7 @@ function insertWrapperWithAlignment(writer, align, table) {
13194
13177
  ];
13195
13178
  saveButtonView.set({
13196
13179
  label: t('Save'),
13197
- icon: IconCheck,
13198
- class: 'ck-button-save',
13180
+ class: 'ck-button-action',
13199
13181
  type: 'submit',
13200
13182
  withText: true
13201
13183
  });
@@ -13204,8 +13186,6 @@ function insertWrapperWithAlignment(writer, align, table) {
13204
13186
  });
13205
13187
  cancelButtonView.set({
13206
13188
  label: t('Cancel'),
13207
- icon: IconCancel,
13208
- class: 'ck-button-cancel',
13209
13189
  withText: true
13210
13190
  });
13211
13191
  cancelButtonView.delegate('execute').to(this, 'cancel');
@@ -13214,37 +13194,56 @@ function insertWrapperWithAlignment(writer, align, table) {
13214
13194
  cancelButtonView
13215
13195
  };
13216
13196
  }
13197
+ /**
13198
+ * Creates a back button view that cancels the form.
13199
+ */ _createBackButton() {
13200
+ const t = this.locale.t;
13201
+ const backButton = new ButtonView(this.locale);
13202
+ backButton.set({
13203
+ class: 'ck-button-back',
13204
+ label: t('Back'),
13205
+ icon: IconPreviousArrow,
13206
+ tooltip: true
13207
+ });
13208
+ backButton.delegate('execute').to(this, 'cancel');
13209
+ return backButton;
13210
+ }
13217
13211
  /**
13218
13212
  * Provides localized labels for {@link #alignmentToolbar} buttons.
13219
13213
  */ get _alignmentLabels() {
13220
13214
  const locale = this.locale;
13221
13215
  const t = this.t;
13222
- const left = t('Align table to the left');
13223
- const center = t('Center table');
13224
- const right = t('Align table to the right');
13216
+ const blockLeft = t('Align table to the left with no text wrapping');
13217
+ const blockRight = t('Align table to the right with no text wrapping');
13218
+ const left = t('Align table to the left with text wrapping');
13219
+ const center = t('Center table with no text wrapping');
13220
+ const right = t('Align table to the right with text wrapping');
13225
13221
  // Returns object with a proper order of labels.
13226
13222
  if (locale.uiLanguageDirection === 'rtl') {
13227
13223
  return {
13228
13224
  right,
13229
- center,
13230
- left
13231
- };
13232
- } else {
13233
- return {
13234
13225
  left,
13226
+ blockRight,
13235
13227
  center,
13236
- right
13228
+ blockLeft
13237
13229
  };
13238
13230
  }
13231
+ return {
13232
+ blockLeft,
13233
+ center,
13234
+ blockRight,
13235
+ left,
13236
+ right
13237
+ };
13239
13238
  }
13240
13239
  }
13241
- function isBorderStyleSet$2(value) {
13240
+ function isBorderStyleSet(value) {
13242
13241
  return value !== 'none';
13243
13242
  }
13244
13243
 
13245
- const ERROR_TEXT_TIMEOUT$2 = 500;
13244
+ const ERROR_TEXT_TIMEOUT = 500;
13246
13245
  // Map of view properties and related commands.
13247
- const propertyToCommandMap$2 = {
13246
+ const propertyToCommandMap = {
13248
13247
  borderStyle: 'tableBorderStyle',
13249
13248
  borderColor: 'tableBorderColor',
13250
13249
  borderWidth: 'tableBorderWidth',
@@ -13336,7 +13335,7 @@ const propertyToCommandMap$2 = {
13336
13335
  tooltip: true
13337
13336
  });
13338
13337
  this.listenTo(view, 'execute', ()=>this._showView());
13339
- const commands = Object.values(propertyToCommandMap$2).map((commandName)=>editor.commands.get(commandName));
13338
+ const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName));
13340
13339
  view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
13341
13340
  return view;
13342
13341
  }
@@ -13446,7 +13445,7 @@ const propertyToCommandMap$2 = {
13446
13445
  */ _fillViewFormFromCommandValues() {
13447
13446
  const commands = this.editor.commands;
13448
13447
  const borderStyleCommand = commands.get('tableBorderStyle');
13449
- Object.entries(propertyToCommandMap$2).map(([property, commandName])=>{
13448
+ Object.entries(propertyToCommandMap).map(([property, commandName])=>{
13450
13449
  const propertyKey = property;
13451
13450
  const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
13452
13451
  return [
@@ -13555,7 +13554,7 @@ const propertyToCommandMap$2 = {
13555
13554
  const { commandName, viewField, validator, errorText } = options;
13556
13555
  const setErrorTextDebounced = debounce(()=>{
13557
13556
  viewField.errorText = errorText;
13558
- }, ERROR_TEXT_TIMEOUT$2);
13557
+ }, ERROR_TEXT_TIMEOUT);
13559
13558
  return (evt, propertyName, newValue)=>{
13560
13559
  setErrorTextDebounced.cancel();
13561
13560
  // Do not execute the command on initial call (opening the table properties view).
@@ -13996,2096 +13995,5 @@ const propertyToCommandMap$2 = {
13996
13995
  }
13997
13996
  }
13998
13997
 
13999
- /**
14000
- * Returns an object containing pairs of CSS border style values and their localized UI
14001
- * labels. Used by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
14002
- * and {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView}.
14003
- *
14004
- * @internal
14005
- * @param t The "t" function provided by the editor that is used to localize strings.
14006
- */ function getBorderStyleLabels(t) {
14007
- return {
14008
- none: t('None'),
14009
- solid: t('Solid'),
14010
- dotted: t('Dotted'),
14011
- dashed: t('Dashed'),
14012
- double: t('Double'),
14013
- groove: t('Groove'),
14014
- ridge: t('Ridge'),
14015
- inset: t('Inset'),
14016
- outset: t('Outset')
14017
- };
14018
- }
14019
- /**
14020
- * Generates item definitions for a UI dropdown that allows changing the border style of a table or a table cell.
14021
- *
14022
- * @internal
14023
- * @param defaultStyle The default border.
14024
- */ function getBorderStyleDefinitions(view, defaultStyle) {
14025
- const itemDefinitions = new Collection();
14026
- const styleLabels = getBorderStyleLabels(view.t);
14027
- for(const style in styleLabels){
14028
- const definition = {
14029
- type: 'button',
14030
- model: new UIModel({
14031
- _borderStyleValue: style,
14032
- label: styleLabels[style],
14033
- role: 'menuitemradio',
14034
- withText: true
14035
- })
14036
- };
14037
- if (style === 'none') {
14038
- definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
14039
- if (defaultStyle === 'none') {
14040
- return !value;
14041
- }
14042
- return value === style;
14043
- });
14044
- } else {
14045
- definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
14046
- return value === style;
14047
- });
14048
- }
14049
- itemDefinitions.add(definition);
14050
- }
14051
- return itemDefinitions;
14052
- }
14053
- /**
14054
- * A helper that fills a toolbar with buttons that:
14055
- *
14056
- * * have some labels,
14057
- * * have some icons,
14058
- * * set a certain UI view property value upon execution.
14059
- *
14060
- * @internal
14061
- * @param options Configuration options
14062
- * @param options.view The view that has the observable property.
14063
- * @param options.icons Object with button icons.
14064
- * @param options.toolbar The toolbar to fill with buttons.
14065
- * @param options.labels Object with button labels.
14066
- * @param options.propertyName The name of the observable property in the view.
14067
- * @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
14068
- * @param options.defaultValue Default value for the property.
14069
- */ function fillToolbar(options) {
14070
- const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
14071
- for(const name in labels){
14072
- const button = new ButtonView(view.locale);
14073
- button.set({
14074
- role: 'radio',
14075
- isToggleable: true,
14076
- label: labels[name],
14077
- icon: icons[name],
14078
- tooltip: labels[name]
14079
- });
14080
- // If specified the `nameToValue()` callback, map the value based on the option's name.
14081
- const buttonValue = nameToValue ? nameToValue(name) : name;
14082
- button.bind('isOn').to(view, propertyName, (value)=>{
14083
- // `value` comes from `view[ propertyName ]`.
14084
- let valueToCompare = value;
14085
- // If it's empty, and the `defaultValue` is specified, use it instead.
14086
- if (value === '' && defaultValue) {
14087
- valueToCompare = defaultValue;
14088
- }
14089
- return buttonValue === valueToCompare;
14090
- });
14091
- button.on('execute', ()=>{
14092
- // Allow toggling alignment if there is no default value specified (especially for layout tables).
14093
- if (!defaultValue && buttonValue && view[propertyName] === buttonValue) {
14094
- view[propertyName] = undefined;
14095
- } else {
14096
- view[propertyName] = buttonValue;
14097
- }
14098
- });
14099
- toolbar.items.add(button);
14100
- }
14101
- }
14102
- /**
14103
- * Returns a creator for a color input with a label.
14104
- *
14105
- * For given options, it returns a function that creates an instance of a
14106
- * {@link module:table/ui/colorinputview~ColorInputView color input} logically related to
14107
- * a {@link module:ui/labeledfield/labeledfieldview~LabeledFieldView labeled view} in the DOM.
14108
- *
14109
- * The helper does the following:
14110
- *
14111
- * * It sets the color input `id` and `ariaDescribedById` attributes.
14112
- * * It binds the color input `isReadOnly` to the labeled view.
14113
- * * It binds the color input `hasError` to the labeled view.
14114
- * * It enables a logic that cleans up the error when the user starts typing in the color input.
14115
- *
14116
- * Usage:
14117
- *
14118
- * ```ts
14119
- * const colorInputCreator = getLabeledColorInputCreator( {
14120
- * colorConfig: [ ... ],
14121
- * columns: 3,
14122
- * } );
14123
- *
14124
- * const labeledInputView = new LabeledFieldView( locale, colorInputCreator );
14125
- * console.log( labeledInputView.view ); // A color input instance.
14126
- * ```
14127
- *
14128
- * @internal
14129
- * @param options Color input options.
14130
- * @param options.colorConfig The configuration of the color palette displayed in the input's dropdown.
14131
- * @param options.columns The configuration of the number of columns the color palette consists of in the input's dropdown.
14132
- * @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
14133
- * the "Restore default" button. Instead of clearing the input field, the default color value will be set.
14134
- * @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
14135
- */ function getLabeledColorInputCreator(options) {
14136
- return (labeledFieldView, viewUid, statusUid)=>{
14137
- const colorInputView = new ColorInputView(labeledFieldView.locale, {
14138
- colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
14139
- columns: options.columns,
14140
- defaultColorValue: options.defaultColorValue,
14141
- colorPickerConfig: options.colorPickerConfig
14142
- });
14143
- colorInputView.inputView.set({
14144
- id: viewUid,
14145
- ariaDescribedById: statusUid
14146
- });
14147
- colorInputView.bind('isReadOnly').to(labeledFieldView, 'isEnabled', (value)=>!value);
14148
- colorInputView.bind('hasError').to(labeledFieldView, 'errorText', (value)=>!!value);
14149
- colorInputView.on('input', ()=>{
14150
- // UX: Make the error text disappear and disable the error indicator as the user
14151
- // starts fixing the errors.
14152
- labeledFieldView.errorText = null;
14153
- });
14154
- labeledFieldView.bind('isEmpty', 'isFocused').to(colorInputView);
14155
- return colorInputView;
14156
- };
14157
- }
14158
- function colorConfigToColorGridDefinitions(colorConfig) {
14159
- return colorConfig.map((item)=>({
14160
- color: item.model,
14161
- label: item.label,
14162
- options: {
14163
- hasBorder: item.hasBorder
14164
- }
14165
- }));
14166
- }
14167
-
14168
- /**
14169
- * The class representing a table properties form, allowing users to customize
14170
- * certain style aspects of a table, for instance, border, background color, alignment, etc..
14171
- */ class TablePropertiesViewExperimental extends View {
14172
- /**
14173
- * Options passed to the view. See {@link #constructor} to learn more.
14174
- */ options;
14175
- /**
14176
- * Tracks information about the DOM focus in the form.
14177
- */ focusTracker;
14178
- /**
14179
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
14180
- */ keystrokes;
14181
- /**
14182
- * A collection of child views in the form.
14183
- */ children;
14184
- /**
14185
- * A dropdown that allows selecting the style of the table border.
14186
- */ borderStyleDropdown;
14187
- /**
14188
- * An input that allows specifying the width of the table border.
14189
- */ borderWidthInput;
14190
- /**
14191
- * An input that allows specifying the color of the table border.
14192
- */ borderColorInput;
14193
- /**
14194
- * An input that allows specifying the table background color.
14195
- */ backgroundInput;
14196
- /**
14197
- * An input that allows specifying the table width.
14198
- */ widthInput;
14199
- /**
14200
- * An input that allows specifying the table height.
14201
- */ heightInput;
14202
- /**
14203
- * A toolbar with buttons that allow changing the alignment of an entire table.
14204
- */ alignmentToolbar;
14205
- /**
14206
- * The "Save" button view.
14207
- */ saveButtonView;
14208
- /**
14209
- * The "Cancel" button view.
14210
- */ cancelButtonView;
14211
- /**
14212
- * The Back button view displayed in the header.
14213
- */ backButtonView;
14214
- /**
14215
- * A collection of views that can be focused in the form.
14216
- */ _focusables;
14217
- /**
14218
- * Helps cycling over {@link #_focusables} in the form.
14219
- */ _focusCycler;
14220
- /**
14221
- * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
14222
- * @param options Additional configuration of the view.
14223
- */ constructor(locale, options){
14224
- super(locale);
14225
- this.set({
14226
- borderStyle: '',
14227
- borderWidth: '',
14228
- borderColor: '',
14229
- backgroundColor: '',
14230
- width: '',
14231
- height: '',
14232
- alignment: ''
14233
- });
14234
- this.options = options;
14235
- const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
14236
- const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
14237
- const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
14238
- const { alignmentToolbar, alignmentLabel } = this._createAlignmentFields();
14239
- this.focusTracker = new FocusTracker();
14240
- this.keystrokes = new KeystrokeHandler();
14241
- this.children = this.createCollection();
14242
- this.borderStyleDropdown = borderStyleDropdown;
14243
- this.borderWidthInput = borderWidthInput;
14244
- this.borderColorInput = borderColorInput;
14245
- this.backgroundInput = backgroundInput;
14246
- this.widthInput = widthInput;
14247
- this.heightInput = heightInput;
14248
- this.alignmentToolbar = alignmentToolbar;
14249
- // Defer creating to make sure other fields are present and the Save button can
14250
- // bind its #isEnabled to their error messages so there's no way to save unless all
14251
- // fields are valid.
14252
- const { saveButtonView, cancelButtonView } = this._createActionButtons();
14253
- this.saveButtonView = saveButtonView;
14254
- this.cancelButtonView = cancelButtonView;
14255
- this.backButtonView = this._createBackButton();
14256
- this._focusables = new ViewCollection();
14257
- this._focusCycler = new FocusCycler({
14258
- focusables: this._focusables,
14259
- focusTracker: this.focusTracker,
14260
- keystrokeHandler: this.keystrokes,
14261
- actions: {
14262
- // Navigate form fields backwards using the Shift + Tab keystroke.
14263
- focusPrevious: 'shift + tab',
14264
- // Navigate form fields forwards using the Tab key.
14265
- focusNext: 'tab'
14266
- }
14267
- });
14268
- // Form header.
14269
- const headerView = new FormHeaderView(locale, {
14270
- label: this.t('Table properties')
14271
- });
14272
- headerView.children.add(this.backButtonView, 0);
14273
- this.children.add(headerView);
14274
- // Border row.
14275
- this.children.add(new FormRowView(locale, {
14276
- labelView: borderRowLabel,
14277
- children: [
14278
- borderRowLabel,
14279
- borderStyleDropdown,
14280
- borderWidthInput,
14281
- borderColorInput
14282
- ],
14283
- class: 'ck-table-form__border-row'
14284
- }));
14285
- this.children.add(new FormRowView(locale, {
14286
- children: [
14287
- // Dimensions row.
14288
- new FormRowView(locale, {
14289
- labelView: dimensionsLabel,
14290
- children: [
14291
- dimensionsLabel,
14292
- widthInput,
14293
- operatorLabel,
14294
- heightInput
14295
- ],
14296
- class: 'ck-table-form__dimensions-row'
14297
- }),
14298
- // Background row.
14299
- new FormRowView(locale, {
14300
- labelView: backgroundRowLabel,
14301
- children: [
14302
- backgroundRowLabel,
14303
- backgroundInput
14304
- ],
14305
- class: 'ck-table-form__background-row'
14306
- })
14307
- ]
14308
- }));
14309
- // Alignment row.
14310
- this.children.add(new FormRowView(locale, {
14311
- labelView: alignmentLabel,
14312
- children: [
14313
- alignmentLabel,
14314
- alignmentToolbar
14315
- ],
14316
- class: 'ck-table-properties-form__alignment-row'
14317
- }));
14318
- // Action row.
14319
- this.children.add(new FormRowView(locale, {
14320
- children: [
14321
- this.cancelButtonView,
14322
- this.saveButtonView
14323
- ],
14324
- class: 'ck-table-form__action-row'
14325
- }));
14326
- this.setTemplate({
14327
- tag: 'form',
14328
- attributes: {
14329
- class: [
14330
- 'ck',
14331
- 'ck-form',
14332
- 'ck-table-form',
14333
- 'ck-table-properties-form',
14334
- 'ck-table-properties-form_experimental'
14335
- ],
14336
- // https://github.com/ckeditor/ckeditor5-link/issues/90
14337
- tabindex: '-1'
14338
- },
14339
- children: this.children
14340
- });
14341
- }
14342
- /**
14343
- * @inheritDoc
14344
- */ render() {
14345
- super.render();
14346
- // Enable the "submit" event for this view. It can be triggered by the #saveButtonView
14347
- // which is of the "submit" DOM "type".
14348
- submitHandler({
14349
- view: this
14350
- });
14351
- // Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
14352
- [
14353
- this.borderColorInput,
14354
- this.backgroundInput
14355
- ].forEach((view)=>{
14356
- this._focusCycler.chain(view.fieldView.focusCycler);
14357
- });
14358
- [
14359
- this.borderStyleDropdown,
14360
- this.borderWidthInput,
14361
- this.borderColorInput,
14362
- this.widthInput,
14363
- this.heightInput,
14364
- this.backgroundInput,
14365
- this.alignmentToolbar,
14366
- this.cancelButtonView,
14367
- this.saveButtonView,
14368
- this.backButtonView
14369
- ].forEach((view)=>{
14370
- // Register the view as focusable.
14371
- this._focusables.add(view);
14372
- // Register the view in the focus tracker.
14373
- this.focusTracker.add(view.element);
14374
- });
14375
- // Mainly for closing using "Esc" and navigation using "Tab".
14376
- this.keystrokes.listenTo(this.element);
14377
- }
14378
- /**
14379
- * @inheritDoc
14380
- */ destroy() {
14381
- super.destroy();
14382
- this.focusTracker.destroy();
14383
- this.keystrokes.destroy();
14384
- }
14385
- /**
14386
- * Focuses the fist focusable field in the form.
14387
- */ focus() {
14388
- this._focusCycler.focusFirst();
14389
- }
14390
- /**
14391
- * Creates the following form fields:
14392
- *
14393
- * * {@link #borderStyleDropdown},
14394
- * * {@link #borderWidthInput},
14395
- * * {@link #borderColorInput}.
14396
- */ _createBorderFields() {
14397
- const defaultTableProperties = this.options.defaultTableProperties;
14398
- const defaultBorder = {
14399
- style: defaultTableProperties.borderStyle,
14400
- width: defaultTableProperties.borderWidth,
14401
- color: defaultTableProperties.borderColor
14402
- };
14403
- const colorInputCreator = getLabeledColorInputCreator({
14404
- colorConfig: this.options.borderColors,
14405
- columns: 5,
14406
- defaultColorValue: defaultBorder.color,
14407
- colorPickerConfig: this.options.colorPickerConfig
14408
- });
14409
- const locale = this.locale;
14410
- const t = this.t;
14411
- const accessibleLabel = t('Style');
14412
- // -- Group label ---------------------------------------------
14413
- const borderRowLabel = new LabelView(locale);
14414
- borderRowLabel.text = t('Border');
14415
- // -- Style ---------------------------------------------------
14416
- const styleLabels = getBorderStyleLabels(t);
14417
- const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
14418
- borderStyleDropdown.set({
14419
- label: accessibleLabel,
14420
- class: 'ck-table-form__border-style'
14421
- });
14422
- borderStyleDropdown.fieldView.buttonView.set({
14423
- ariaLabel: accessibleLabel,
14424
- ariaLabelledBy: undefined,
14425
- isOn: false,
14426
- withText: true,
14427
- tooltip: accessibleLabel
14428
- });
14429
- borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
14430
- return styleLabels[value ? value : 'none'];
14431
- });
14432
- borderStyleDropdown.fieldView.on('execute', (evt)=>{
14433
- this.borderStyle = evt.source._borderStyleValue;
14434
- });
14435
- borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
14436
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
14437
- role: 'menu',
14438
- ariaLabel: accessibleLabel
14439
- });
14440
- // -- Width ---------------------------------------------------
14441
- const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
14442
- borderWidthInput.set({
14443
- label: t('Width'),
14444
- class: 'ck-table-form__border-width'
14445
- });
14446
- borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
14447
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
14448
- borderWidthInput.fieldView.on('input', ()=>{
14449
- this.borderWidth = borderWidthInput.fieldView.element.value;
14450
- });
14451
- // -- Color ---------------------------------------------------
14452
- const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
14453
- borderColorInput.set({
14454
- label: t('Color'),
14455
- class: 'ck-table-form__border-color'
14456
- });
14457
- borderColorInput.fieldView.bind('value').to(this, 'borderColor');
14458
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
14459
- borderColorInput.fieldView.on('input', ()=>{
14460
- this.borderColor = borderColorInput.fieldView.value;
14461
- });
14462
- // Reset the border color and width fields depending on the `border-style` value.
14463
- this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
14464
- // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
14465
- // See: https://github.com/ckeditor/ckeditor5/issues/6227.
14466
- if (!isBorderStyleSet$1(newValue)) {
14467
- this.borderColor = '';
14468
- this.borderWidth = '';
14469
- }
14470
- // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
14471
- if (!isBorderStyleSet$1(oldValue)) {
14472
- this.borderColor = defaultBorder.color;
14473
- this.borderWidth = defaultBorder.width;
14474
- }
14475
- });
14476
- return {
14477
- borderRowLabel,
14478
- borderStyleDropdown,
14479
- borderColorInput,
14480
- borderWidthInput
14481
- };
14482
- }
14483
- /**
14484
- * Creates the following form fields:
14485
- *
14486
- * * {@link #backgroundInput}.
14487
- */ _createBackgroundFields() {
14488
- const locale = this.locale;
14489
- const t = this.t;
14490
- // -- Group label ---------------------------------------------
14491
- const backgroundRowLabel = new LabelView(locale);
14492
- backgroundRowLabel.text = t('Background');
14493
- // -- Background color input -----------------------------------
14494
- const backgroundInputCreator = getLabeledColorInputCreator({
14495
- colorConfig: this.options.backgroundColors,
14496
- columns: 5,
14497
- defaultColorValue: this.options.defaultTableProperties.backgroundColor,
14498
- colorPickerConfig: this.options.colorPickerConfig
14499
- });
14500
- const backgroundInput = new LabeledFieldView(locale, backgroundInputCreator);
14501
- backgroundInput.set({
14502
- label: t('Color'),
14503
- class: 'ck-table-properties-form__background'
14504
- });
14505
- backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
14506
- backgroundInput.fieldView.on('input', ()=>{
14507
- this.backgroundColor = backgroundInput.fieldView.value;
14508
- });
14509
- return {
14510
- backgroundRowLabel,
14511
- backgroundInput
14512
- };
14513
- }
14514
- /**
14515
- * Creates the following form fields:
14516
- *
14517
- * * {@link #widthInput},
14518
- * * {@link #heightInput}.
14519
- */ _createDimensionFields() {
14520
- const locale = this.locale;
14521
- const t = this.t;
14522
- // -- Label ---------------------------------------------------
14523
- const dimensionsLabel = new LabelView(locale);
14524
- dimensionsLabel.text = t('Dimensions');
14525
- // -- Width ---------------------------------------------------
14526
- const widthInput = new LabeledFieldView(locale, createLabeledInputText);
14527
- widthInput.set({
14528
- label: t('Width'),
14529
- class: 'ck-table-form__dimensions-row__width'
14530
- });
14531
- widthInput.fieldView.bind('value').to(this, 'width');
14532
- widthInput.fieldView.on('input', ()=>{
14533
- this.width = widthInput.fieldView.element.value;
14534
- });
14535
- // -- Operator ---------------------------------------------------
14536
- const operatorLabel = new View(locale);
14537
- operatorLabel.setTemplate({
14538
- tag: 'span',
14539
- attributes: {
14540
- class: [
14541
- 'ck-table-form__dimension-operator'
14542
- ]
14543
- },
14544
- children: [
14545
- {
14546
- text: '×'
14547
- }
14548
- ]
14549
- });
14550
- // -- Height ---------------------------------------------------
14551
- const heightInput = new LabeledFieldView(locale, createLabeledInputText);
14552
- heightInput.set({
14553
- label: t('Height'),
14554
- class: 'ck-table-form__dimensions-row__height'
14555
- });
14556
- heightInput.fieldView.bind('value').to(this, 'height');
14557
- heightInput.fieldView.on('input', ()=>{
14558
- this.height = heightInput.fieldView.element.value;
14559
- });
14560
- return {
14561
- dimensionsLabel,
14562
- widthInput,
14563
- operatorLabel,
14564
- heightInput
14565
- };
14566
- }
14567
- /**
14568
- * Creates the following form fields:
14569
- *
14570
- * * {@link #alignmentToolbar}.
14571
- */ _createAlignmentFields() {
14572
- const locale = this.locale;
14573
- const t = this.t;
14574
- // -- Label ---------------------------------------------------
14575
- const alignmentLabel = new LabelView(locale);
14576
- alignmentLabel.text = t('Table Alignment');
14577
- // -- Toolbar ---------------------------------------------------
14578
- const alignmentToolbar = new ToolbarView(locale);
14579
- alignmentToolbar.set({
14580
- role: 'radiogroup',
14581
- isCompact: true,
14582
- ariaLabel: t('Table alignment toolbar')
14583
- });
14584
- fillToolbar({
14585
- view: this,
14586
- icons: {
14587
- left: IconObjectInlineLeft,
14588
- center: IconObjectCenter,
14589
- right: IconObjectInlineRight,
14590
- blockLeft: IconObjectLeft,
14591
- blockRight: IconObjectRight
14592
- },
14593
- toolbar: alignmentToolbar,
14594
- labels: this._alignmentLabels,
14595
- propertyName: 'alignment',
14596
- defaultValue: this.options.defaultTableProperties.alignment
14597
- });
14598
- return {
14599
- alignmentLabel,
14600
- alignmentToolbar
14601
- };
14602
- }
14603
- /**
14604
- * Creates the following form controls:
14605
- *
14606
- * * {@link #saveButtonView},
14607
- * * {@link #cancelButtonView}.
14608
- */ _createActionButtons() {
14609
- const locale = this.locale;
14610
- const t = this.t;
14611
- const saveButtonView = new ButtonView(locale);
14612
- const cancelButtonView = new ButtonView(locale);
14613
- const fieldsThatShouldValidateToSave = [
14614
- this.borderWidthInput,
14615
- this.borderColorInput,
14616
- this.backgroundInput,
14617
- this.widthInput,
14618
- this.heightInput
14619
- ];
14620
- saveButtonView.set({
14621
- label: t('Save'),
14622
- class: 'ck-button-action',
14623
- type: 'submit',
14624
- withText: true
14625
- });
14626
- saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
14627
- return errorTexts.every((errorText)=>!errorText);
14628
- });
14629
- cancelButtonView.set({
14630
- label: t('Cancel'),
14631
- withText: true
14632
- });
14633
- cancelButtonView.delegate('execute').to(this, 'cancel');
14634
- return {
14635
- saveButtonView,
14636
- cancelButtonView
14637
- };
14638
- }
14639
- /**
14640
- * Creates a back button view that cancels the form.
14641
- */ _createBackButton() {
14642
- const t = this.locale.t;
14643
- const backButton = new ButtonView(this.locale);
14644
- backButton.set({
14645
- class: 'ck-button-back',
14646
- label: t('Back'),
14647
- icon: IconPreviousArrow,
14648
- tooltip: true
14649
- });
14650
- backButton.delegate('execute').to(this, 'cancel');
14651
- return backButton;
14652
- }
14653
- /**
14654
- * Provides localized labels for {@link #alignmentToolbar} buttons.
14655
- */ get _alignmentLabels() {
14656
- const locale = this.locale;
14657
- const t = this.t;
14658
- const blockLeft = t('Align table to the left with no text wrapping');
14659
- const blockRight = t('Align table to the right with no text wrapping');
14660
- const left = t('Align table to the left with text wrapping');
14661
- const center = t('Center table with no text wrapping');
14662
- const right = t('Align table to the right with text wrapping');
14663
- // Returns object with a proper order of labels.
14664
- if (locale.uiLanguageDirection === 'rtl') {
14665
- return {
14666
- right,
14667
- left,
14668
- blockRight,
14669
- center,
14670
- blockLeft
14671
- };
14672
- }
14673
- return {
14674
- blockLeft,
14675
- center,
14676
- blockRight,
14677
- left,
14678
- right
14679
- };
14680
- }
14681
- }
14682
- function isBorderStyleSet$1(value) {
14683
- return value !== 'none';
14684
- }
14685
-
14686
- const ERROR_TEXT_TIMEOUT$1 = 500;
14687
- // Map of view properties and related commands.
14688
- const propertyToCommandMap$1 = {
14689
- borderStyle: 'tableBorderStyle',
14690
- borderColor: 'tableBorderColor',
14691
- borderWidth: 'tableBorderWidth',
14692
- backgroundColor: 'tableBackgroundColor',
14693
- width: 'tableWidth',
14694
- height: 'tableHeight',
14695
- alignment: 'tableAlignment'
14696
- };
14697
- /**
14698
- * The table properties UI plugin. It introduces the `'tableProperties'` button
14699
- * that opens a form allowing to specify visual styling of an entire table.
14700
- *
14701
- * It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
14702
- */ class TablePropertiesUIExperimental extends Plugin {
14703
- /**
14704
- * The default table properties.
14705
- */ _defaultContentTableProperties;
14706
- /**
14707
- * The default layout table properties.
14708
- */ _defaultLayoutTableProperties;
14709
- /**
14710
- * The contextual balloon plugin instance.
14711
- */ _balloon;
14712
- /**
14713
- * The properties form view displayed inside the balloon.
14714
- */ view = null;
14715
- /**
14716
- * The properties form view displayed inside the balloon (content table).
14717
- */ _viewWithContentTableDefaults = null;
14718
- /**
14719
- * The properties form view displayed inside the balloon (layout table).
14720
- */ _viewWithLayoutTableDefaults = null;
14721
- /**
14722
- * The batch used to undo all changes made by the form (which are live, as the user types)
14723
- * when "Cancel" was pressed. Each time the view is shown, a new batch is created.
14724
- */ _undoStepBatch;
14725
- /**
14726
- * Flag used to indicate whether view is ready to execute update commands
14727
- * (it finished loading initial data).
14728
- */ _isReady;
14729
- /**
14730
- * @inheritDoc
14731
- */ static get requires() {
14732
- return [
14733
- ContextualBalloon
14734
- ];
14735
- }
14736
- /**
14737
- * @inheritDoc
14738
- */ static get pluginName() {
14739
- return 'TablePropertiesUIExperimental';
14740
- }
14741
- /**
14742
- * @inheritDoc
14743
- */ static get isOfficialPlugin() {
14744
- return true;
14745
- }
14746
- /**
14747
- * @inheritDoc
14748
- */ constructor(editor){
14749
- super(editor);
14750
- editor.config.define('table.tableProperties', {
14751
- borderColors: defaultColors,
14752
- backgroundColors: defaultColors
14753
- });
14754
- }
14755
- /**
14756
- * @inheritDoc
14757
- */ init() {
14758
- const editor = this.editor;
14759
- this._defaultContentTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
14760
- includeAlignmentProperty: true
14761
- });
14762
- this._defaultLayoutTableProperties = getNormalizedDefaultProperties();
14763
- this._balloon = editor.plugins.get(ContextualBalloon);
14764
- editor.ui.componentFactory.add('tableProperties', ()=>this._createTablePropertiesButton());
14765
- }
14766
- /**
14767
- * Creates the table properties button.
14768
- *
14769
- * @internal
14770
- */ _createTablePropertiesButton() {
14771
- const editor = this.editor;
14772
- const t = editor.t;
14773
- const view = new ButtonView(editor.locale);
14774
- view.set({
14775
- label: t('Table properties'),
14776
- icon: IconTableProperties,
14777
- tooltip: true
14778
- });
14779
- this.listenTo(view, 'execute', ()=>this._showView());
14780
- const commands = Object.values(propertyToCommandMap$1).map((commandName)=>editor.commands.get(commandName));
14781
- view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
14782
- return view;
14783
- }
14784
- /**
14785
- * @inheritDoc
14786
- */ destroy() {
14787
- super.destroy();
14788
- // Destroy created UI components as they are not automatically destroyed.
14789
- // See https://github.com/ckeditor/ckeditor5/issues/1341.
14790
- if (this.view) {
14791
- this.view.destroy();
14792
- }
14793
- }
14794
- /**
14795
- * Creates the {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView} instance.
14796
- *
14797
- * @returns The table properties form view instance.
14798
- */ _createPropertiesView(defaultTableProperties) {
14799
- const editor = this.editor;
14800
- const config = editor.config.get('table.tableProperties');
14801
- const borderColorsConfig = normalizeColorOptions(config.borderColors);
14802
- const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
14803
- const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
14804
- const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
14805
- const hasColorPicker = config.colorPicker !== false;
14806
- const view = new TablePropertiesViewExperimental(editor.locale, {
14807
- borderColors: localizedBorderColors,
14808
- backgroundColors: localizedBackgroundColors,
14809
- defaultTableProperties,
14810
- colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
14811
- });
14812
- const t = editor.t;
14813
- // Render the view so its #element is available for the clickOutsideHandler.
14814
- view.render();
14815
- this.listenTo(view, 'submit', ()=>{
14816
- this._hideView();
14817
- });
14818
- this.listenTo(view, 'cancel', ()=>{
14819
- // https://github.com/ckeditor/ckeditor5/issues/6180
14820
- if (this._undoStepBatch.operations.length) {
14821
- editor.execute('undo', this._undoStepBatch);
14822
- }
14823
- this._hideView();
14824
- });
14825
- // Close the balloon on Esc key press.
14826
- view.keystrokes.set('Esc', (data, cancel)=>{
14827
- this._hideView();
14828
- cancel();
14829
- });
14830
- // Close on click outside of balloon panel element.
14831
- clickOutsideHandler({
14832
- emitter: view,
14833
- activator: ()=>this._isViewInBalloon,
14834
- contextElements: [
14835
- this._balloon.view.element
14836
- ],
14837
- callback: ()=>this._hideView()
14838
- });
14839
- const colorErrorText = getLocalizedColorErrorText(t);
14840
- const lengthErrorText = getLocalizedLengthErrorText(t);
14841
- // Create the "UI -> editor data" binding.
14842
- // These listeners update the editor data (via table commands) when any observable
14843
- // property of the view has changed. They also validate the value and display errors in the UI
14844
- // when necessary. This makes the view live, which means the changes are
14845
- // visible in the editing as soon as the user types or changes fields' values.
14846
- view.on('change:borderStyle', this._getPropertyChangeCallback('tableBorderStyle'));
14847
- view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
14848
- viewField: view.borderColorInput,
14849
- commandName: 'tableBorderColor',
14850
- errorText: colorErrorText,
14851
- validator: colorFieldValidator
14852
- }));
14853
- view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
14854
- viewField: view.borderWidthInput,
14855
- commandName: 'tableBorderWidth',
14856
- errorText: lengthErrorText,
14857
- validator: lineWidthFieldValidator
14858
- }));
14859
- view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
14860
- viewField: view.backgroundInput,
14861
- commandName: 'tableBackgroundColor',
14862
- errorText: colorErrorText,
14863
- validator: colorFieldValidator
14864
- }));
14865
- view.on('change:width', this._getValidatedPropertyChangeCallback({
14866
- viewField: view.widthInput,
14867
- commandName: 'tableWidth',
14868
- errorText: lengthErrorText,
14869
- validator: lengthFieldValidator
14870
- }));
14871
- view.on('change:height', this._getValidatedPropertyChangeCallback({
14872
- viewField: view.heightInput,
14873
- commandName: 'tableHeight',
14874
- errorText: lengthErrorText,
14875
- validator: lengthFieldValidator
14876
- }));
14877
- view.on('change:alignment', this._getPropertyChangeCallback('tableAlignment'));
14878
- return view;
14879
- }
14880
- /**
14881
- * In this method the "editor data -> UI" binding is happening.
14882
- *
14883
- * When executed, this method obtains selected table property values from various table commands
14884
- * and passes them to the {@link #view}.
14885
- *
14886
- * This way, the UI stays up–to–date with the editor data.
14887
- */ _fillViewFormFromCommandValues() {
14888
- const commands = this.editor.commands;
14889
- const borderStyleCommand = commands.get('tableBorderStyle');
14890
- Object.entries(propertyToCommandMap$1).map(([property, commandName])=>{
14891
- const propertyKey = property;
14892
- const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
14893
- return [
14894
- propertyKey,
14895
- commands.get(commandName).value || defaultValue
14896
- ];
14897
- }).forEach(([property, value])=>{
14898
- // Do not set the `border-color` and `border-width` fields if `border-style:none`.
14899
- if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
14900
- return;
14901
- }
14902
- this.view.set(property, value);
14903
- });
14904
- this._isReady = true;
14905
- }
14906
- /**
14907
- * Shows the {@link #view} in the {@link #_balloon}.
14908
- *
14909
- * **Note**: Each time a view is shown, the new {@link #_undoStepBatch} is created that contains
14910
- * all changes made to the document when the view is visible, allowing a single undo step
14911
- * for all of them.
14912
- */ _showView() {
14913
- const editor = this.editor;
14914
- const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
14915
- const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
14916
- const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
14917
- if (useDefaults && !this._viewWithContentTableDefaults) {
14918
- this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableProperties);
14919
- } else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
14920
- this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableProperties);
14921
- }
14922
- this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
14923
- this.listenTo(editor.ui, 'update', ()=>{
14924
- this._updateView();
14925
- });
14926
- // Update the view with the model values.
14927
- this._fillViewFormFromCommandValues();
14928
- this._balloon.add({
14929
- view: this.view,
14930
- position: getBalloonTablePositionData(editor)
14931
- });
14932
- // Create a new batch. Clicking "Cancel" will undo this batch.
14933
- this._undoStepBatch = editor.model.createBatch();
14934
- // Basic a11y.
14935
- this.view.focus();
14936
- }
14937
- /**
14938
- * Removes the {@link #view} from the {@link #_balloon}.
14939
- */ _hideView() {
14940
- const editor = this.editor;
14941
- this.stopListening(editor.ui, 'update');
14942
- this._isReady = false;
14943
- // Blur any input element before removing it from DOM to prevent issues in some browsers.
14944
- // See https://github.com/ckeditor/ckeditor5/issues/1501.
14945
- this.view.saveButtonView.focus();
14946
- this._balloon.remove(this.view);
14947
- // Make sure the focus is not lost in the process by putting it directly
14948
- // into the editing view.
14949
- this.editor.editing.view.focus();
14950
- }
14951
- /**
14952
- * Repositions the {@link #_balloon} or hides the {@link #view} if a table is no longer selected.
14953
- */ _updateView() {
14954
- const editor = this.editor;
14955
- const viewDocument = editor.editing.view.document;
14956
- if (!getSelectionAffectedTableWidget(viewDocument.selection)) {
14957
- this._hideView();
14958
- } else if (this._isViewVisible) {
14959
- repositionContextualBalloon(editor, 'table');
14960
- }
14961
- }
14962
- /**
14963
- * Returns `true` when the {@link #view} is the visible in the {@link #_balloon}.
14964
- */ get _isViewVisible() {
14965
- return !!this.view && this._balloon.visibleView === this.view;
14966
- }
14967
- /**
14968
- * Returns `true` when the {@link #view} is in the {@link #_balloon}.
14969
- */ get _isViewInBalloon() {
14970
- return !!this.view && this._balloon.hasView(this.view);
14971
- }
14972
- /**
14973
- * Creates a callback that when executed upon {@link #view view's} property change
14974
- * executes a related editor command with the new property value.
14975
- *
14976
- * If new value will be set to the default value, the command will not be executed.
14977
- *
14978
- * @param commandName The command that will be executed.
14979
- */ _getPropertyChangeCallback(commandName) {
14980
- return (evt, propertyName, newValue)=>{
14981
- // Do not execute the command on initial call (opening the table properties view).
14982
- if (!this._isReady) {
14983
- return;
14984
- }
14985
- this.editor.execute(commandName, {
14986
- value: newValue,
14987
- batch: this._undoStepBatch
14988
- });
14989
- };
14990
- }
14991
- /**
14992
- * Creates a callback that when executed upon {@link #view view's} property change:
14993
- * * executes a related editor command with the new property value if the value is valid,
14994
- * * or sets the error text next to the invalid field, if the value did not pass the validation.
14995
- */ _getValidatedPropertyChangeCallback(options) {
14996
- const { commandName, viewField, validator, errorText } = options;
14997
- const setErrorTextDebounced = debounce(()=>{
14998
- viewField.errorText = errorText;
14999
- }, ERROR_TEXT_TIMEOUT$1);
15000
- return (evt, propertyName, newValue)=>{
15001
- setErrorTextDebounced.cancel();
15002
- // Do not execute the command on initial call (opening the table properties view).
15003
- if (!this._isReady) {
15004
- return;
15005
- }
15006
- if (validator(newValue)) {
15007
- this.editor.execute(commandName, {
15008
- value: newValue,
15009
- batch: this._undoStepBatch
15010
- });
15011
- viewField.errorText = null;
15012
- } else {
15013
- setErrorTextDebounced();
15014
- }
15015
- };
15016
- }
15017
- }
15018
-
15019
- /**
15020
- * The class representing a table cell properties form, allowing users to customize
15021
- * certain style aspects of a table cell, for instance, border, padding, text alignment, etc..
15022
- */ class TableCellPropertiesViewExperimental extends View {
15023
- /**
15024
- * Options passed to the view. See {@link #constructor} to learn more.
15025
- */ options;
15026
- /**
15027
- * Tracks information about the DOM focus in the form.
15028
- */ focusTracker;
15029
- /**
15030
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
15031
- */ keystrokes;
15032
- /**
15033
- * A collection of child views in the form.
15034
- */ children;
15035
- /**
15036
- * A dropdown that allows selecting the style of the table cell border.
15037
- */ borderStyleDropdown;
15038
- /**
15039
- * An input that allows specifying the width of the table cell border.
15040
- */ borderWidthInput;
15041
- /**
15042
- * An input that allows specifying the color of the table cell border.
15043
- */ borderColorInput;
15044
- /**
15045
- * An input that allows specifying the table cell background color.
15046
- */ backgroundInput;
15047
- /**
15048
- * A dropdown that allows selecting the type of the table cell (data or header).
15049
- */ cellTypeDropdown;
15050
- /**
15051
- * An input that allows specifying the table cell padding.
15052
- */ paddingInput;
15053
- /**
15054
- * An input that allows specifying the table cell width.
15055
- */ widthInput;
15056
- /**
15057
- * An input that allows specifying the table cell height.
15058
- */ heightInput;
15059
- /**
15060
- * A toolbar with buttons that allow changing the horizontal text alignment in a table cell.
15061
- */ horizontalAlignmentToolbar;
15062
- /**
15063
- * A toolbar with buttons that allow changing the vertical text alignment in a table cell.
15064
- */ verticalAlignmentToolbar;
15065
- /**
15066
- * The "Save" button view.
15067
- */ saveButtonView;
15068
- /**
15069
- * The "Cancel" button view.
15070
- */ cancelButtonView;
15071
- /**
15072
- * The "Back" button view.
15073
- */ backButtonView;
15074
- /**
15075
- * A collection of views that can be focused in the form.
15076
- */ _focusables;
15077
- /**
15078
- * Helps cycling over {@link #_focusables} in the form.
15079
- */ _focusCycler;
15080
- /**
15081
- * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
15082
- * @param options Additional configuration of the view.
15083
- * @param options.borderColors A configuration of the border color palette used by the
15084
- * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#borderColorInput}.
15085
- * @param options.backgroundColors A configuration of the background color palette used by the
15086
- * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#backgroundInput}.
15087
- * @param options.defaultTableCellProperties The default table cell properties.
15088
- * @param options.isTableCellTypeSupported A flag indicating whether the table cell type is supported.
15089
- */ constructor(locale, options){
15090
- super(locale);
15091
- this.set({
15092
- borderStyle: '',
15093
- borderWidth: '',
15094
- borderColor: '',
15095
- padding: '',
15096
- backgroundColor: '',
15097
- width: '',
15098
- height: '',
15099
- horizontalAlignment: '',
15100
- verticalAlignment: '',
15101
- cellType: ''
15102
- });
15103
- this.options = options;
15104
- const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
15105
- const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
15106
- const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
15107
- const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
15108
- const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
15109
- this.focusTracker = new FocusTracker();
15110
- this.keystrokes = new KeystrokeHandler();
15111
- this.children = this.createCollection();
15112
- this.borderStyleDropdown = borderStyleDropdown;
15113
- this.borderWidthInput = borderWidthInput;
15114
- this.borderColorInput = borderColorInput;
15115
- this.backgroundInput = backgroundInput;
15116
- this.cellTypeDropdown = cellTypeDropdown;
15117
- this.paddingInput = this._createPaddingField();
15118
- this.widthInput = widthInput;
15119
- this.heightInput = heightInput;
15120
- this.horizontalAlignmentToolbar = horizontalAlignmentToolbar;
15121
- this.verticalAlignmentToolbar = verticalAlignmentToolbar;
15122
- // Defer creating to make sure other fields are present and the Save button can
15123
- // bind its #isEnabled to their error messages so there's no way to save unless all
15124
- // fields are valid.
15125
- const { saveButtonView, cancelButtonView } = this._createActionButtons();
15126
- this.saveButtonView = saveButtonView;
15127
- this.cancelButtonView = cancelButtonView;
15128
- this.backButtonView = this._createBackButton();
15129
- this._focusables = new ViewCollection();
15130
- this._focusCycler = new FocusCycler({
15131
- focusables: this._focusables,
15132
- focusTracker: this.focusTracker,
15133
- keystrokeHandler: this.keystrokes,
15134
- actions: {
15135
- // Navigate form fields backwards using the Shift + Tab keystroke.
15136
- focusPrevious: 'shift + tab',
15137
- // Navigate form fields forwards using the Tab key.
15138
- focusNext: 'tab'
15139
- }
15140
- });
15141
- // Form header.
15142
- const header = new FormHeaderView(locale, {
15143
- label: this.t('Cell properties')
15144
- });
15145
- header.children.add(this.backButtonView, 0);
15146
- this.children.add(header);
15147
- // Border row.
15148
- this.children.add(new FormRowView(locale, {
15149
- labelView: borderRowLabel,
15150
- children: this.options.isTableCellTypeSupported ? [
15151
- borderRowLabel,
15152
- borderStyleDropdown,
15153
- borderWidthInput,
15154
- borderColorInput
15155
- ] : [
15156
- borderRowLabel,
15157
- borderStyleDropdown,
15158
- borderColorInput,
15159
- borderWidthInput
15160
- ],
15161
- class: `ck-table-form__border-row${this.options.isTableCellTypeSupported ? ' ck-table-form__border-row_experimental' : ''}`
15162
- }));
15163
- // Background and cell type.
15164
- this.children.add(new FormRowView(locale, {
15165
- children: this.options.isTableCellTypeSupported ? [
15166
- new FormRowView(locale, {
15167
- labelView: cellTypeRowLabel,
15168
- children: [
15169
- cellTypeRowLabel,
15170
- cellTypeDropdown
15171
- ],
15172
- class: 'ck-table-form__cell-type-row'
15173
- }),
15174
- new FormRowView(locale, {
15175
- labelView: backgroundRowLabel,
15176
- children: [
15177
- backgroundRowLabel,
15178
- backgroundInput
15179
- ],
15180
- class: 'ck-table-form__background-row'
15181
- })
15182
- ] : [
15183
- new FormRowView(locale, {
15184
- labelView: backgroundRowLabel,
15185
- children: [
15186
- backgroundRowLabel,
15187
- backgroundInput
15188
- ],
15189
- class: 'ck-table-form__background-row'
15190
- })
15191
- ]
15192
- }));
15193
- // Dimensions row and padding.
15194
- this.children.add(new FormRowView(locale, {
15195
- children: [
15196
- // Dimensions row.
15197
- new FormRowView(locale, {
15198
- labelView: dimensionsLabel,
15199
- children: [
15200
- dimensionsLabel,
15201
- widthInput,
15202
- operatorLabel,
15203
- heightInput
15204
- ],
15205
- class: 'ck-table-form__dimensions-row'
15206
- }),
15207
- // Padding row.
15208
- new FormRowView(locale, {
15209
- children: [
15210
- this.paddingInput
15211
- ],
15212
- class: 'ck-table-cell-properties-form__padding-row'
15213
- })
15214
- ]
15215
- }));
15216
- // Text alignment row.
15217
- this.children.add(new FormRowView(locale, {
15218
- labelView: alignmentLabel,
15219
- children: [
15220
- alignmentLabel,
15221
- horizontalAlignmentToolbar,
15222
- verticalAlignmentToolbar
15223
- ],
15224
- class: 'ck-table-cell-properties-form__alignment-row'
15225
- }));
15226
- // Action row.
15227
- this.children.add(new FormRowView(locale, {
15228
- children: [
15229
- this.cancelButtonView,
15230
- this.saveButtonView
15231
- ],
15232
- class: 'ck-table-form__action-row'
15233
- }));
15234
- this.setTemplate({
15235
- tag: 'form',
15236
- attributes: {
15237
- class: [
15238
- 'ck',
15239
- 'ck-form',
15240
- 'ck-table-form',
15241
- 'ck-table-cell-properties-form',
15242
- 'ck-table-cell-properties-form_experimental',
15243
- this.options.isTableCellTypeSupported ? 'ck-table-cell-properties-form_experimental-no-cell-type' : ''
15244
- ],
15245
- // https://github.com/ckeditor/ckeditor5-link/issues/90
15246
- tabindex: '-1'
15247
- },
15248
- children: this.children
15249
- });
15250
- }
15251
- /**
15252
- * @inheritDoc
15253
- */ render() {
15254
- super.render();
15255
- // Enable the "submit" event for this view. It can be triggered by the #saveButtonView
15256
- // which is of the "submit" DOM "type".
15257
- submitHandler({
15258
- view: this
15259
- });
15260
- // Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
15261
- [
15262
- this.borderColorInput,
15263
- this.backgroundInput
15264
- ].forEach((view)=>{
15265
- this._focusCycler.chain(view.fieldView.focusCycler);
15266
- });
15267
- [
15268
- this.borderStyleDropdown,
15269
- this.borderColorInput,
15270
- this.borderWidthInput,
15271
- this.cellTypeDropdown,
15272
- this.backgroundInput,
15273
- this.widthInput,
15274
- this.heightInput,
15275
- this.paddingInput,
15276
- this.horizontalAlignmentToolbar,
15277
- this.verticalAlignmentToolbar,
15278
- this.cancelButtonView,
15279
- this.saveButtonView,
15280
- this.backButtonView
15281
- ].forEach((view)=>{
15282
- // Register the view as focusable.
15283
- this._focusables.add(view);
15284
- // Register the view in the focus tracker.
15285
- this.focusTracker.add(view.element);
15286
- });
15287
- // Mainly for closing using "Esc" and navigation using "Tab".
15288
- this.keystrokes.listenTo(this.element);
15289
- }
15290
- /**
15291
- * @inheritDoc
15292
- */ destroy() {
15293
- super.destroy();
15294
- this.focusTracker.destroy();
15295
- this.keystrokes.destroy();
15296
- }
15297
- /**
15298
- * Focuses the fist focusable field in the form.
15299
- */ focus() {
15300
- this._focusCycler.focusFirst();
15301
- }
15302
- /**
15303
- * Creates the following form fields:
15304
- *
15305
- * * {@link #borderStyleDropdown},
15306
- * * {@link #borderWidthInput},
15307
- * * {@link #borderColorInput}.
15308
- */ _createBorderFields() {
15309
- const defaultTableCellProperties = this.options.defaultTableCellProperties;
15310
- const defaultBorder = {
15311
- style: defaultTableCellProperties.borderStyle,
15312
- width: defaultTableCellProperties.borderWidth,
15313
- color: defaultTableCellProperties.borderColor
15314
- };
15315
- const colorInputCreator = getLabeledColorInputCreator({
15316
- colorConfig: this.options.borderColors,
15317
- columns: 5,
15318
- defaultColorValue: defaultBorder.color,
15319
- colorPickerConfig: this.options.colorPickerConfig
15320
- });
15321
- const locale = this.locale;
15322
- const t = this.t;
15323
- const accessibleLabel = t('Style');
15324
- // -- Group label ---------------------------------------------
15325
- const borderRowLabel = new LabelView(locale);
15326
- borderRowLabel.text = t('Border');
15327
- // -- Style ---------------------------------------------------
15328
- const styleLabels = getBorderStyleLabels(t);
15329
- const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
15330
- borderStyleDropdown.set({
15331
- label: accessibleLabel,
15332
- class: 'ck-table-form__border-style'
15333
- });
15334
- borderStyleDropdown.fieldView.buttonView.set({
15335
- ariaLabel: accessibleLabel,
15336
- ariaLabelledBy: undefined,
15337
- isOn: false,
15338
- withText: true,
15339
- tooltip: accessibleLabel
15340
- });
15341
- borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
15342
- return styleLabels[value ? value : 'none'];
15343
- });
15344
- borderStyleDropdown.fieldView.on('execute', (evt)=>{
15345
- this.borderStyle = evt.source._borderStyleValue;
15346
- });
15347
- borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
15348
- addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
15349
- role: 'menu',
15350
- ariaLabel: accessibleLabel
15351
- });
15352
- // -- Width ---------------------------------------------------
15353
- const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
15354
- borderWidthInput.set({
15355
- label: t('Width'),
15356
- class: 'ck-table-form__border-width'
15357
- });
15358
- borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
15359
- borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
15360
- borderWidthInput.fieldView.on('input', ()=>{
15361
- this.borderWidth = borderWidthInput.fieldView.element.value;
15362
- });
15363
- // -- Color ---------------------------------------------------
15364
- const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
15365
- borderColorInput.set({
15366
- label: t('Color'),
15367
- class: 'ck-table-form__border-color'
15368
- });
15369
- borderColorInput.fieldView.bind('value').to(this, 'borderColor');
15370
- borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
15371
- borderColorInput.fieldView.on('input', ()=>{
15372
- this.borderColor = borderColorInput.fieldView.value;
15373
- });
15374
- // Reset the border color and width fields depending on the `border-style` value.
15375
- this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
15376
- // When removing the border (`border-style:none`), clear the remaining `border-*` properties.
15377
- // See: https://github.com/ckeditor/ckeditor5/issues/6227.
15378
- if (!isBorderStyleSet(newValue)) {
15379
- this.borderColor = '';
15380
- this.borderWidth = '';
15381
- }
15382
- // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
15383
- if (!isBorderStyleSet(oldValue)) {
15384
- this.borderColor = defaultBorder.color;
15385
- this.borderWidth = defaultBorder.width;
15386
- }
15387
- });
15388
- return {
15389
- borderRowLabel,
15390
- borderStyleDropdown,
15391
- borderColorInput,
15392
- borderWidthInput
15393
- };
15394
- }
15395
- /**
15396
- * Creates the following form fields:
15397
- *
15398
- * * {@link #backgroundInput}.
15399
- */ _createBackgroundFields() {
15400
- const locale = this.locale;
15401
- const t = this.t;
15402
- // -- Group label ---------------------------------------------
15403
- const backgroundRowLabel = new LabelView(locale);
15404
- backgroundRowLabel.text = t('Background');
15405
- // -- Background color input -----------------------------------
15406
- const colorInputCreator = getLabeledColorInputCreator({
15407
- colorConfig: this.options.backgroundColors,
15408
- columns: 5,
15409
- defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
15410
- colorPickerConfig: this.options.colorPickerConfig
15411
- });
15412
- const backgroundInput = new LabeledFieldView(locale, colorInputCreator);
15413
- backgroundInput.set({
15414
- label: t('Color'),
15415
- class: 'ck-table-cell-properties-form__background'
15416
- });
15417
- backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
15418
- backgroundInput.fieldView.on('input', ()=>{
15419
- this.backgroundColor = backgroundInput.fieldView.value;
15420
- });
15421
- return {
15422
- backgroundRowLabel,
15423
- backgroundInput
15424
- };
15425
- }
15426
- /**
15427
- * Create cell type field.
15428
- *
15429
- * * {@link #cellTypeDropdown}.
15430
- *
15431
- * @internal
15432
- */ _createCellTypeField() {
15433
- const locale = this.locale;
15434
- const t = this.t;
15435
- const cellTypeRowLabel = new LabelView(locale);
15436
- cellTypeRowLabel.text = t('Cell type');
15437
- const cellTypeLabels = this._cellTypeLabels;
15438
- const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
15439
- cellTypeDropdown.set({
15440
- label: t('Cell type'),
15441
- class: 'ck-table-cell-properties-form__cell-type'
15442
- });
15443
- cellTypeDropdown.fieldView.buttonView.set({
15444
- ariaLabel: t('Cell type'),
15445
- ariaLabelledBy: undefined,
15446
- isOn: false,
15447
- withText: true,
15448
- tooltip: t('Cell type')
15449
- });
15450
- cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
15451
- return cellTypeLabels[value || 'data'];
15452
- });
15453
- cellTypeDropdown.fieldView.on('execute', (evt)=>{
15454
- this.cellType = evt.source._cellTypeValue;
15455
- });
15456
- cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
15457
- addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
15458
- role: 'menu',
15459
- ariaLabel: t('Cell type')
15460
- });
15461
- return {
15462
- cellTypeRowLabel,
15463
- cellTypeDropdown
15464
- };
15465
- }
15466
- /**
15467
- * Creates the following form fields:
15468
- *
15469
- * * {@link #widthInput}.
15470
- * * {@link #heightInput}.
15471
- */ _createDimensionFields() {
15472
- const locale = this.locale;
15473
- const t = this.t;
15474
- // -- Label ---------------------------------------------------
15475
- const dimensionsLabel = new LabelView(locale);
15476
- dimensionsLabel.text = t('Dimensions');
15477
- // -- Width ---------------------------------------------------
15478
- const widthInput = new LabeledFieldView(locale, createLabeledInputText);
15479
- widthInput.set({
15480
- label: t('Width'),
15481
- class: 'ck-table-form__dimensions-row__width'
15482
- });
15483
- widthInput.fieldView.bind('value').to(this, 'width');
15484
- widthInput.fieldView.on('input', ()=>{
15485
- this.width = widthInput.fieldView.element.value;
15486
- });
15487
- // -- Operator ---------------------------------------------------
15488
- const operatorLabel = new View(locale);
15489
- operatorLabel.setTemplate({
15490
- tag: 'span',
15491
- attributes: {
15492
- class: [
15493
- 'ck-table-form__dimension-operator'
15494
- ]
15495
- },
15496
- children: [
15497
- {
15498
- text: '×'
15499
- }
15500
- ]
15501
- });
15502
- // -- Height ---------------------------------------------------
15503
- const heightInput = new LabeledFieldView(locale, createLabeledInputText);
15504
- heightInput.set({
15505
- label: t('Height'),
15506
- class: 'ck-table-form__dimensions-row__height'
15507
- });
15508
- heightInput.fieldView.bind('value').to(this, 'height');
15509
- heightInput.fieldView.on('input', ()=>{
15510
- this.height = heightInput.fieldView.element.value;
15511
- });
15512
- return {
15513
- dimensionsLabel,
15514
- widthInput,
15515
- operatorLabel,
15516
- heightInput
15517
- };
15518
- }
15519
- /**
15520
- * Creates the following form fields:
15521
- *
15522
- * * {@link #paddingInput}.
15523
- */ _createPaddingField() {
15524
- const locale = this.locale;
15525
- const t = this.t;
15526
- const paddingInput = new LabeledFieldView(locale, createLabeledInputText);
15527
- paddingInput.set({
15528
- label: t('Padding'),
15529
- class: 'ck-table-cell-properties-form__padding'
15530
- });
15531
- paddingInput.fieldView.bind('value').to(this, 'padding');
15532
- paddingInput.fieldView.on('input', ()=>{
15533
- this.padding = paddingInput.fieldView.element.value;
15534
- });
15535
- return paddingInput;
15536
- }
15537
- /**
15538
- * Creates the following form fields:
15539
- *
15540
- * * {@link #horizontalAlignmentToolbar},
15541
- * * {@link #verticalAlignmentToolbar}.
15542
- */ _createAlignmentFields() {
15543
- const locale = this.locale;
15544
- const t = this.t;
15545
- const alignmentLabel = new LabelView(locale);
15546
- const ALIGNMENT_ICONS = {
15547
- left: IconAlignLeft,
15548
- center: IconAlignCenter,
15549
- right: IconAlignRight,
15550
- justify: IconAlignJustify,
15551
- top: IconAlignTop,
15552
- middle: IconAlignMiddle,
15553
- bottom: IconAlignBottom
15554
- };
15555
- alignmentLabel.text = t('Table cell text alignment');
15556
- // -- Horizontal ---------------------------------------------------
15557
- const horizontalAlignmentToolbar = new ToolbarView(locale);
15558
- const isContentRTL = locale.contentLanguageDirection === 'rtl';
15559
- horizontalAlignmentToolbar.set({
15560
- isCompact: true,
15561
- role: 'radiogroup',
15562
- ariaLabel: t('Horizontal text alignment toolbar'),
15563
- class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
15564
- });
15565
- fillToolbar({
15566
- view: this,
15567
- icons: ALIGNMENT_ICONS,
15568
- toolbar: horizontalAlignmentToolbar,
15569
- labels: this._horizontalAlignmentLabels,
15570
- propertyName: 'horizontalAlignment',
15571
- nameToValue: (name)=>{
15572
- // For the RTL content, we want to swap the buttons "align to the left" and "align to the right".
15573
- if (isContentRTL) {
15574
- if (name === 'left') {
15575
- return 'right';
15576
- } else if (name === 'right') {
15577
- return 'left';
15578
- }
15579
- }
15580
- return name;
15581
- },
15582
- defaultValue: this.options.defaultTableCellProperties.horizontalAlignment
15583
- });
15584
- // -- Vertical -----------------------------------------------------
15585
- const verticalAlignmentToolbar = new ToolbarView(locale);
15586
- verticalAlignmentToolbar.set({
15587
- isCompact: true,
15588
- role: 'radiogroup',
15589
- ariaLabel: t('Vertical text alignment toolbar'),
15590
- class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
15591
- });
15592
- fillToolbar({
15593
- view: this,
15594
- icons: ALIGNMENT_ICONS,
15595
- toolbar: verticalAlignmentToolbar,
15596
- labels: this._verticalAlignmentLabels,
15597
- propertyName: 'verticalAlignment',
15598
- defaultValue: this.options.defaultTableCellProperties.verticalAlignment
15599
- });
15600
- return {
15601
- horizontalAlignmentToolbar,
15602
- verticalAlignmentToolbar,
15603
- alignmentLabel
15604
- };
15605
- }
15606
- /**
15607
- * Creates the following form controls:
15608
- *
15609
- * * {@link #saveButtonView},
15610
- * * {@link #cancelButtonView}.
15611
- */ _createActionButtons() {
15612
- const locale = this.locale;
15613
- const t = this.t;
15614
- const saveButtonView = new ButtonView(locale);
15615
- const cancelButtonView = new ButtonView(locale);
15616
- const fieldsThatShouldValidateToSave = [
15617
- this.borderWidthInput,
15618
- this.borderColorInput,
15619
- this.backgroundInput,
15620
- this.paddingInput
15621
- ];
15622
- saveButtonView.set({
15623
- label: t('Save'),
15624
- class: 'ck-button-action',
15625
- type: 'submit',
15626
- withText: true
15627
- });
15628
- saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
15629
- return errorTexts.every((errorText)=>!errorText);
15630
- });
15631
- cancelButtonView.set({
15632
- label: t('Cancel'),
15633
- withText: true
15634
- });
15635
- cancelButtonView.delegate('execute').to(this, 'cancel');
15636
- return {
15637
- saveButtonView,
15638
- cancelButtonView
15639
- };
15640
- }
15641
- /**
15642
- * Creates a back button view that cancels the form.
15643
- */ _createBackButton() {
15644
- const t = this.locale.t;
15645
- const backButton = new ButtonView(this.locale);
15646
- backButton.set({
15647
- class: 'ck-button-back',
15648
- label: t('Back'),
15649
- icon: IconPreviousArrow,
15650
- tooltip: true
15651
- });
15652
- backButton.delegate('execute').to(this, 'cancel');
15653
- return backButton;
15654
- }
15655
- /**
15656
- * Creates the cell type dropdown definitions.
15657
- */ _getCellTypeDefinitions() {
15658
- const itemDefinitions = new Collection();
15659
- const cellTypeLabels = this._cellTypeLabels;
15660
- for (const type of [
15661
- 'data',
15662
- 'header'
15663
- ]){
15664
- const definition = {
15665
- type: 'button',
15666
- model: new UIModel({
15667
- _cellTypeValue: type,
15668
- label: cellTypeLabels[type],
15669
- role: 'menuitemradio',
15670
- withText: true
15671
- })
15672
- };
15673
- definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
15674
- itemDefinitions.add(definition);
15675
- }
15676
- return itemDefinitions;
15677
- }
15678
- /**
15679
- * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
15680
- */ get _horizontalAlignmentLabels() {
15681
- const locale = this.locale;
15682
- const t = this.t;
15683
- const left = t('Align cell text to the left');
15684
- const center = t('Align cell text to the center');
15685
- const right = t('Align cell text to the right');
15686
- const justify = t('Justify cell text');
15687
- // Returns object with a proper order of labels.
15688
- if (locale.uiLanguageDirection === 'rtl') {
15689
- return {
15690
- right,
15691
- center,
15692
- left,
15693
- justify
15694
- };
15695
- } else {
15696
- return {
15697
- left,
15698
- center,
15699
- right,
15700
- justify
15701
- };
15702
- }
15703
- }
15704
- /**
15705
- * Provides localized labels for {@link #verticalAlignmentToolbar} buttons.
15706
- */ get _verticalAlignmentLabels() {
15707
- const t = this.t;
15708
- return {
15709
- top: t('Align cell text to the top'),
15710
- middle: t('Align cell text to the middle'),
15711
- bottom: t('Align cell text to the bottom')
15712
- };
15713
- }
15714
- /**
15715
- * Provides localized labels for {@link #cellTypeDropdown}.
15716
- */ get _cellTypeLabels() {
15717
- const t = this.t;
15718
- return {
15719
- data: t('Data cell'),
15720
- header: t('Header cell')
15721
- };
15722
- }
15723
- }
15724
- function isBorderStyleSet(value) {
15725
- return value !== 'none';
15726
- }
15727
-
15728
- const ERROR_TEXT_TIMEOUT = 500;
15729
- // Map of view properties and related commands.
15730
- const propertyToCommandMap = {
15731
- borderStyle: 'tableCellBorderStyle',
15732
- borderColor: 'tableCellBorderColor',
15733
- borderWidth: 'tableCellBorderWidth',
15734
- height: 'tableCellHeight',
15735
- width: 'tableCellWidth',
15736
- padding: 'tableCellPadding',
15737
- backgroundColor: 'tableCellBackgroundColor',
15738
- horizontalAlignment: 'tableCellHorizontalAlignment',
15739
- verticalAlignment: 'tableCellVerticalAlignment',
15740
- cellType: 'tableCellType'
15741
- };
15742
- /**
15743
- * The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
15744
- * that opens a form allowing to specify the visual styling of a table cell.
15745
- *
15746
- * It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
15747
- */ class TableCellPropertiesUIExperimental extends Plugin {
15748
- /**
15749
- * The default table cell properties.
15750
- */ _defaultContentTableCellProperties;
15751
- /**
15752
- * The default layout table cell properties.
15753
- */ _defaultLayoutTableCellProperties;
15754
- /**
15755
- * The contextual balloon plugin instance.
15756
- */ _balloon;
15757
- /**
15758
- * The cell properties form view displayed inside the balloon.
15759
- */ view;
15760
- /**
15761
- * The cell properties form view displayed inside the balloon (content table).
15762
- */ _viewWithContentTableDefaults;
15763
- /**
15764
- * The cell properties form view displayed inside the balloon (layout table).
15765
- */ _viewWithLayoutTableDefaults;
15766
- /**
15767
- * The batch used to undo all changes made by the form (which are live, as the user types)
15768
- * when "Cancel" was pressed. Each time the view is shown, a new batch is created.
15769
- */ _undoStepBatch;
15770
- /**
15771
- * Flag used to indicate whether view is ready to execute update commands
15772
- * (it finished loading initial data).
15773
- */ _isReady;
15774
- /**
15775
- * @inheritDoc
15776
- */ static get requires() {
15777
- return [
15778
- ContextualBalloon
15779
- ];
15780
- }
15781
- /**
15782
- * @inheritDoc
15783
- */ static get pluginName() {
15784
- return 'TableCellPropertiesUIExperimental';
15785
- }
15786
- /**
15787
- * @inheritDoc
15788
- */ static get isOfficialPlugin() {
15789
- return true;
15790
- }
15791
- /**
15792
- * @inheritDoc
15793
- */ constructor(editor){
15794
- super(editor);
15795
- editor.config.define('table.tableCellProperties', {
15796
- borderColors: defaultColors,
15797
- backgroundColors: defaultColors
15798
- });
15799
- }
15800
- /**
15801
- * @inheritDoc
15802
- */ init() {
15803
- const editor = this.editor;
15804
- const t = editor.t;
15805
- this._defaultContentTableCellProperties = getNormalizedDefaultCellProperties(editor.config.get('table.tableCellProperties.defaultProperties'), {
15806
- includeVerticalAlignmentProperty: true,
15807
- includeHorizontalAlignmentProperty: true,
15808
- includePaddingProperty: true,
15809
- isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
15810
- });
15811
- this._defaultLayoutTableCellProperties = getNormalizedDefaultProperties(undefined, {
15812
- includeVerticalAlignmentProperty: true,
15813
- includeHorizontalAlignmentProperty: true,
15814
- isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
15815
- });
15816
- this._balloon = editor.plugins.get(ContextualBalloon);
15817
- this.view = null;
15818
- this._isReady = false;
15819
- editor.ui.componentFactory.add('tableCellProperties', (locale)=>{
15820
- const view = new ButtonView(locale);
15821
- view.set({
15822
- label: t('Cell properties'),
15823
- icon: IconTableCellProperties,
15824
- tooltip: true
15825
- });
15826
- this.listenTo(view, 'execute', ()=>this._showView());
15827
- const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
15828
- view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
15829
- return view;
15830
- });
15831
- }
15832
- /**
15833
- * @inheritDoc
15834
- */ destroy() {
15835
- super.destroy();
15836
- // Destroy created UI components as they are not automatically destroyed.
15837
- // See https://github.com/ckeditor/ckeditor5/issues/1341.
15838
- if (this.view) {
15839
- this.view.destroy();
15840
- }
15841
- }
15842
- /**
15843
- * Creates the {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView} instance.
15844
- *
15845
- * @returns The cell properties form view instance.
15846
- */ _createPropertiesView(defaultTableCellProperties) {
15847
- const editor = this.editor;
15848
- const config = editor.config.get('table.tableCellProperties');
15849
- const borderColorsConfig = normalizeColorOptions(config.borderColors);
15850
- const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
15851
- const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
15852
- const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
15853
- const hasColorPicker = config.colorPicker !== false;
15854
- const isTableCellTypeSupported = !!editor.config.get('experimentalFlags.tableCellTypeSupport');
15855
- const view = new TableCellPropertiesViewExperimental(editor.locale, {
15856
- borderColors: localizedBorderColors,
15857
- backgroundColors: localizedBackgroundColors,
15858
- defaultTableCellProperties,
15859
- colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false,
15860
- isTableCellTypeSupported
15861
- });
15862
- const t = editor.t;
15863
- // Render the view so its #element is available for the clickOutsideHandler.
15864
- view.render();
15865
- this.listenTo(view, 'submit', ()=>{
15866
- this._hideView();
15867
- });
15868
- this.listenTo(view, 'cancel', ()=>{
15869
- // https://github.com/ckeditor/ckeditor5/issues/6180
15870
- if (this._undoStepBatch.operations.length) {
15871
- editor.execute('undo', this._undoStepBatch);
15872
- }
15873
- this._hideView();
15874
- });
15875
- // Close the balloon on Esc key press.
15876
- view.keystrokes.set('Esc', (data, cancel)=>{
15877
- this._hideView();
15878
- cancel();
15879
- });
15880
- // Close on click outside of balloon panel element.
15881
- clickOutsideHandler({
15882
- emitter: view,
15883
- activator: ()=>this._isViewInBalloon,
15884
- contextElements: [
15885
- this._balloon.view.element
15886
- ],
15887
- callback: ()=>this._hideView()
15888
- });
15889
- const colorErrorText = getLocalizedColorErrorText(t);
15890
- const lengthErrorText = getLocalizedLengthErrorText(t);
15891
- // Create the "UI -> editor data" binding.
15892
- // These listeners update the editor data (via table commands) when any observable
15893
- // property of the view has changed. They also validate the value and display errors in the UI
15894
- // when necessary. This makes the view live, which means the changes are
15895
- // visible in the editing as soon as the user types or changes fields' values.
15896
- view.on('change:borderStyle', this._getPropertyChangeCallback('tableCellBorderStyle'));
15897
- view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
15898
- viewField: view.borderColorInput,
15899
- commandName: 'tableCellBorderColor',
15900
- errorText: colorErrorText,
15901
- validator: colorFieldValidator
15902
- }));
15903
- view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
15904
- viewField: view.borderWidthInput,
15905
- commandName: 'tableCellBorderWidth',
15906
- errorText: lengthErrorText,
15907
- validator: lineWidthFieldValidator
15908
- }));
15909
- view.on('change:padding', this._getValidatedPropertyChangeCallback({
15910
- viewField: view.paddingInput,
15911
- commandName: 'tableCellPadding',
15912
- errorText: lengthErrorText,
15913
- validator: lengthFieldValidator
15914
- }));
15915
- view.on('change:width', this._getValidatedPropertyChangeCallback({
15916
- viewField: view.widthInput,
15917
- commandName: 'tableCellWidth',
15918
- errorText: lengthErrorText,
15919
- validator: lengthFieldValidator
15920
- }));
15921
- view.on('change:height', this._getValidatedPropertyChangeCallback({
15922
- viewField: view.heightInput,
15923
- commandName: 'tableCellHeight',
15924
- errorText: lengthErrorText,
15925
- validator: lengthFieldValidator
15926
- }));
15927
- view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
15928
- viewField: view.backgroundInput,
15929
- commandName: 'tableCellBackgroundColor',
15930
- errorText: colorErrorText,
15931
- validator: colorFieldValidator
15932
- }));
15933
- view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
15934
- view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
15935
- const cellTypeCommand = editor.commands.get('tableCellType');
15936
- if (cellTypeCommand) {
15937
- view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
15938
- view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
15939
- }
15940
- return view;
15941
- }
15942
- /**
15943
- * In this method the "editor data -> UI" binding is happening.
15944
- *
15945
- * When executed, this method obtains selected cell property values from various table commands
15946
- * and passes them to the {@link #view}.
15947
- *
15948
- * This way, the UI stays up–to–date with the editor data.
15949
- */ _fillViewFormFromCommandValues() {
15950
- const commands = this.editor.commands;
15951
- const borderStyleCommand = commands.get('tableCellBorderStyle');
15952
- Object.entries(propertyToCommandMap).flatMap(([property, commandName])=>{
15953
- const command = commands.get(commandName);
15954
- if (!command) {
15955
- return [];
15956
- }
15957
- const propertyKey = property;
15958
- let defaultValue;
15959
- if (propertyKey === 'cellType') {
15960
- defaultValue = '';
15961
- } else {
15962
- defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
15963
- }
15964
- const entry = [
15965
- property,
15966
- command.value || defaultValue
15967
- ];
15968
- return [
15969
- entry
15970
- ];
15971
- }).forEach(([property, value])=>{
15972
- // Do not set the `border-color` and `border-width` fields if `border-style:none`.
15973
- if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
15974
- return;
15975
- }
15976
- this.view.set(property, value);
15977
- });
15978
- this._isReady = true;
15979
- }
15980
- /**
15981
- * Shows the {@link #view} in the {@link #_balloon}.
15982
- *
15983
- * **Note**: Each time a view is shown, a new {@link #_undoStepBatch} is created. It contains
15984
- * all changes made to the document when the view is visible, allowing a single undo step
15985
- * for all of them.
15986
- */ _showView() {
15987
- const editor = this.editor;
15988
- const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
15989
- const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
15990
- const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
15991
- if (useDefaults && !this._viewWithContentTableDefaults) {
15992
- this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableCellProperties);
15993
- } else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
15994
- this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableCellProperties);
15995
- }
15996
- this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
15997
- this.listenTo(editor.ui, 'update', ()=>{
15998
- this._updateView();
15999
- });
16000
- // Update the view with the model values.
16001
- this._fillViewFormFromCommandValues();
16002
- this._balloon.add({
16003
- view: this.view,
16004
- position: getBalloonCellPositionData(editor)
16005
- });
16006
- // Create a new batch. Clicking "Cancel" will undo this batch.
16007
- this._undoStepBatch = editor.model.createBatch();
16008
- // Basic a11y.
16009
- this.view.focus();
16010
- }
16011
- /**
16012
- * Removes the {@link #view} from the {@link #_balloon}.
16013
- */ _hideView() {
16014
- const editor = this.editor;
16015
- this.stopListening(editor.ui, 'update');
16016
- this._isReady = false;
16017
- // Blur any input element before removing it from DOM to prevent issues in some browsers.
16018
- // See https://github.com/ckeditor/ckeditor5/issues/1501.
16019
- this.view.saveButtonView.focus();
16020
- this._balloon.remove(this.view);
16021
- // Make sure the focus is not lost in the process by putting it directly
16022
- // into the editing view.
16023
- this.editor.editing.view.focus();
16024
- }
16025
- /**
16026
- * Repositions the {@link #_balloon} or hides the {@link #view} if a table cell is no longer selected.
16027
- */ _updateView() {
16028
- const editor = this.editor;
16029
- const viewDocument = editor.editing.view.document;
16030
- if (!getTableWidgetAncestor(viewDocument.selection)) {
16031
- this._hideView();
16032
- } else if (this._isViewVisible) {
16033
- repositionContextualBalloon(editor, 'cell');
16034
- }
16035
- }
16036
- /**
16037
- * Returns `true` when the {@link #view} is visible in the {@link #_balloon}.
16038
- */ get _isViewVisible() {
16039
- return !!this.view && this._balloon.visibleView === this.view;
16040
- }
16041
- /**
16042
- * Returns `true` when the {@link #view} is in the {@link #_balloon}.
16043
- */ get _isViewInBalloon() {
16044
- return !!this.view && this._balloon.hasView(this.view);
16045
- }
16046
- /**
16047
- * Creates a callback that when executed upon the {@link #view view's} property change
16048
- * executes a related editor command with the new property value.
16049
- *
16050
- * @param commandName The default value of the command.
16051
- */ _getPropertyChangeCallback(commandName) {
16052
- return (evt, propertyName, newValue)=>{
16053
- if (!this._isReady) {
16054
- return;
16055
- }
16056
- this.editor.execute(commandName, {
16057
- value: newValue,
16058
- batch: this._undoStepBatch
16059
- });
16060
- };
16061
- }
16062
- /**
16063
- * Creates a callback that when executed upon the {@link #view view's} property change:
16064
- * * Executes a related editor command with the new property value if the value is valid,
16065
- * * Or sets the error text next to the invalid field, if the value did not pass the validation.
16066
- */ _getValidatedPropertyChangeCallback(options) {
16067
- const { commandName, viewField, validator, errorText } = options;
16068
- const setErrorTextDebounced = debounce(()=>{
16069
- viewField.errorText = errorText;
16070
- }, ERROR_TEXT_TIMEOUT);
16071
- return (evt, propertyName, newValue)=>{
16072
- setErrorTextDebounced.cancel();
16073
- // Do not execute the command on initial call (opening the table properties view).
16074
- if (!this._isReady) {
16075
- return;
16076
- }
16077
- if (validator(newValue)) {
16078
- this.editor.execute(commandName, {
16079
- value: newValue,
16080
- batch: this._undoStepBatch
16081
- });
16082
- viewField.errorText = null;
16083
- } else {
16084
- setErrorTextDebounced();
16085
- }
16086
- };
16087
- }
16088
- }
16089
-
16090
- 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 };
13998
+ 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 };
16091
13999
  //# sourceMappingURL=index.js.map