@ckeditor/ckeditor5-table 47.3.0-alpha.7 → 47.4.0-alpha.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 (574) hide show
  1. package/LICENSE.md +1 -1
  2. package/build/table.js +3 -3
  3. package/build/translations/af.js +1 -1
  4. package/build/translations/ar.js +1 -1
  5. package/build/translations/ast.js +1 -1
  6. package/build/translations/az.js +1 -1
  7. package/build/translations/be.js +1 -1
  8. package/build/translations/bg.js +1 -1
  9. package/build/translations/bn.js +1 -1
  10. package/build/translations/bs.js +1 -1
  11. package/build/translations/ca.js +1 -1
  12. package/build/translations/cs.js +1 -1
  13. package/build/translations/da.js +1 -1
  14. package/build/translations/de-ch.js +1 -1
  15. package/build/translations/de.js +1 -1
  16. package/build/translations/el.js +1 -1
  17. package/build/translations/en-au.js +1 -1
  18. package/build/translations/en-gb.js +1 -1
  19. package/build/translations/eo.js +1 -1
  20. package/build/translations/es-co.js +1 -1
  21. package/build/translations/es.js +1 -1
  22. package/build/translations/et.js +1 -1
  23. package/build/translations/eu.js +1 -1
  24. package/build/translations/fa.js +1 -1
  25. package/build/translations/fi.js +1 -1
  26. package/build/translations/fr.js +1 -1
  27. package/build/translations/gl.js +1 -1
  28. package/build/translations/gu.js +1 -1
  29. package/build/translations/he.js +1 -1
  30. package/build/translations/hi.js +1 -1
  31. package/build/translations/hr.js +1 -1
  32. package/build/translations/hu.js +1 -1
  33. package/build/translations/hy.js +1 -1
  34. package/build/translations/id.js +1 -1
  35. package/build/translations/it.js +1 -1
  36. package/build/translations/ja.js +1 -1
  37. package/build/translations/jv.js +1 -1
  38. package/build/translations/kk.js +1 -1
  39. package/build/translations/km.js +1 -1
  40. package/build/translations/kn.js +1 -1
  41. package/build/translations/ko.js +1 -1
  42. package/build/translations/ku.js +1 -1
  43. package/build/translations/lt.js +1 -1
  44. package/build/translations/lv.js +1 -1
  45. package/build/translations/ms.js +1 -1
  46. package/build/translations/nb.js +1 -1
  47. package/build/translations/ne.js +1 -1
  48. package/build/translations/nl.js +1 -1
  49. package/build/translations/no.js +1 -1
  50. package/build/translations/oc.js +1 -1
  51. package/build/translations/pl.js +1 -1
  52. package/build/translations/pt-br.js +1 -1
  53. package/build/translations/pt.js +1 -1
  54. package/build/translations/ro.js +1 -1
  55. package/build/translations/ru.js +1 -1
  56. package/build/translations/si.js +1 -1
  57. package/build/translations/sk.js +1 -1
  58. package/build/translations/sl.js +1 -1
  59. package/build/translations/sq.js +1 -1
  60. package/build/translations/sr-latn.js +1 -1
  61. package/build/translations/sr.js +1 -1
  62. package/build/translations/sv.js +1 -1
  63. package/build/translations/th.js +1 -1
  64. package/build/translations/ti.js +1 -1
  65. package/build/translations/tk.js +1 -1
  66. package/build/translations/tr.js +1 -1
  67. package/build/translations/tt.js +1 -1
  68. package/build/translations/ug.js +1 -1
  69. package/build/translations/uk.js +1 -1
  70. package/build/translations/ur.js +1 -1
  71. package/build/translations/uz.js +1 -1
  72. package/build/translations/vi.js +1 -1
  73. package/build/translations/zh-cn.js +1 -1
  74. package/build/translations/zh.js +1 -1
  75. package/dist/index-content.css +5 -1
  76. package/dist/index-editor.css +77 -86
  77. package/dist/index.css +124 -127
  78. package/dist/index.css.map +1 -1
  79. package/dist/index.js +863 -138
  80. package/dist/index.js.map +1 -1
  81. package/dist/translations/af.d.ts +1 -1
  82. package/dist/translations/af.js +2 -2
  83. package/dist/translations/af.umd.js +2 -2
  84. package/dist/translations/ar.d.ts +1 -1
  85. package/dist/translations/ar.js +2 -2
  86. package/dist/translations/ar.umd.js +2 -2
  87. package/dist/translations/ast.d.ts +1 -1
  88. package/dist/translations/ast.js +2 -2
  89. package/dist/translations/ast.umd.js +2 -2
  90. package/dist/translations/az.d.ts +1 -1
  91. package/dist/translations/az.js +2 -2
  92. package/dist/translations/az.umd.js +2 -2
  93. package/dist/translations/be.d.ts +1 -1
  94. package/dist/translations/be.js +2 -2
  95. package/dist/translations/be.umd.js +2 -2
  96. package/dist/translations/bg.d.ts +1 -1
  97. package/dist/translations/bg.js +2 -2
  98. package/dist/translations/bg.umd.js +2 -2
  99. package/dist/translations/bn.d.ts +1 -1
  100. package/dist/translations/bn.js +2 -2
  101. package/dist/translations/bn.umd.js +2 -2
  102. package/dist/translations/bs.d.ts +1 -1
  103. package/dist/translations/bs.js +2 -2
  104. package/dist/translations/bs.umd.js +2 -2
  105. package/dist/translations/ca.d.ts +1 -1
  106. package/dist/translations/ca.js +2 -2
  107. package/dist/translations/ca.umd.js +2 -2
  108. package/dist/translations/cs.d.ts +1 -1
  109. package/dist/translations/cs.js +2 -2
  110. package/dist/translations/cs.umd.js +2 -2
  111. package/dist/translations/da.d.ts +1 -1
  112. package/dist/translations/da.js +2 -2
  113. package/dist/translations/da.umd.js +2 -2
  114. package/dist/translations/de-ch.d.ts +1 -1
  115. package/dist/translations/de-ch.js +2 -2
  116. package/dist/translations/de-ch.umd.js +2 -2
  117. package/dist/translations/de.d.ts +1 -1
  118. package/dist/translations/de.js +2 -2
  119. package/dist/translations/de.umd.js +2 -2
  120. package/dist/translations/el.d.ts +1 -1
  121. package/dist/translations/el.js +2 -2
  122. package/dist/translations/el.umd.js +2 -2
  123. package/dist/translations/en-au.d.ts +1 -1
  124. package/dist/translations/en-au.js +2 -2
  125. package/dist/translations/en-au.umd.js +2 -2
  126. package/dist/translations/en-gb.d.ts +1 -1
  127. package/dist/translations/en-gb.js +2 -2
  128. package/dist/translations/en-gb.umd.js +2 -2
  129. package/dist/translations/en.d.ts +1 -1
  130. package/dist/translations/en.js +2 -2
  131. package/dist/translations/en.umd.js +2 -2
  132. package/dist/translations/eo.d.ts +1 -1
  133. package/dist/translations/eo.js +2 -2
  134. package/dist/translations/eo.umd.js +2 -2
  135. package/dist/translations/es-co.d.ts +1 -1
  136. package/dist/translations/es-co.js +2 -2
  137. package/dist/translations/es-co.umd.js +2 -2
  138. package/dist/translations/es.d.ts +1 -1
  139. package/dist/translations/es.js +2 -2
  140. package/dist/translations/es.umd.js +2 -2
  141. package/dist/translations/et.d.ts +1 -1
  142. package/dist/translations/et.js +2 -2
  143. package/dist/translations/et.umd.js +2 -2
  144. package/dist/translations/eu.d.ts +1 -1
  145. package/dist/translations/eu.js +2 -2
  146. package/dist/translations/eu.umd.js +2 -2
  147. package/dist/translations/fa.d.ts +1 -1
  148. package/dist/translations/fa.js +2 -2
  149. package/dist/translations/fa.umd.js +2 -2
  150. package/dist/translations/fi.d.ts +1 -1
  151. package/dist/translations/fi.js +2 -2
  152. package/dist/translations/fi.umd.js +2 -2
  153. package/dist/translations/fr.d.ts +1 -1
  154. package/dist/translations/fr.js +2 -2
  155. package/dist/translations/fr.umd.js +2 -2
  156. package/dist/translations/gl.d.ts +1 -1
  157. package/dist/translations/gl.js +2 -2
  158. package/dist/translations/gl.umd.js +2 -2
  159. package/dist/translations/gu.d.ts +1 -1
  160. package/dist/translations/gu.js +2 -2
  161. package/dist/translations/gu.umd.js +2 -2
  162. package/dist/translations/he.d.ts +1 -1
  163. package/dist/translations/he.js +2 -2
  164. package/dist/translations/he.umd.js +2 -2
  165. package/dist/translations/hi.d.ts +1 -1
  166. package/dist/translations/hi.js +2 -2
  167. package/dist/translations/hi.umd.js +2 -2
  168. package/dist/translations/hr.d.ts +1 -1
  169. package/dist/translations/hr.js +2 -2
  170. package/dist/translations/hr.umd.js +2 -2
  171. package/dist/translations/hu.d.ts +1 -1
  172. package/dist/translations/hu.js +2 -2
  173. package/dist/translations/hu.umd.js +2 -2
  174. package/dist/translations/hy.d.ts +1 -1
  175. package/dist/translations/hy.js +2 -2
  176. package/dist/translations/hy.umd.js +2 -2
  177. package/dist/translations/id.d.ts +1 -1
  178. package/dist/translations/id.js +2 -2
  179. package/dist/translations/id.umd.js +2 -2
  180. package/dist/translations/it.d.ts +1 -1
  181. package/dist/translations/it.js +2 -2
  182. package/dist/translations/it.umd.js +2 -2
  183. package/dist/translations/ja.d.ts +1 -1
  184. package/dist/translations/ja.js +2 -2
  185. package/dist/translations/ja.umd.js +2 -2
  186. package/dist/translations/jv.d.ts +1 -1
  187. package/dist/translations/jv.js +2 -2
  188. package/dist/translations/jv.umd.js +2 -2
  189. package/dist/translations/kk.d.ts +1 -1
  190. package/dist/translations/kk.js +2 -2
  191. package/dist/translations/kk.umd.js +2 -2
  192. package/dist/translations/km.d.ts +1 -1
  193. package/dist/translations/km.js +2 -2
  194. package/dist/translations/km.umd.js +2 -2
  195. package/dist/translations/kn.d.ts +1 -1
  196. package/dist/translations/kn.js +2 -2
  197. package/dist/translations/kn.umd.js +2 -2
  198. package/dist/translations/ko.d.ts +1 -1
  199. package/dist/translations/ko.js +2 -2
  200. package/dist/translations/ko.umd.js +2 -2
  201. package/dist/translations/ku.d.ts +1 -1
  202. package/dist/translations/ku.js +2 -2
  203. package/dist/translations/ku.umd.js +2 -2
  204. package/dist/translations/lt.d.ts +1 -1
  205. package/dist/translations/lt.js +2 -2
  206. package/dist/translations/lt.umd.js +2 -2
  207. package/dist/translations/lv.d.ts +1 -1
  208. package/dist/translations/lv.js +2 -2
  209. package/dist/translations/lv.umd.js +2 -2
  210. package/dist/translations/ms.d.ts +1 -1
  211. package/dist/translations/ms.js +2 -2
  212. package/dist/translations/ms.umd.js +2 -2
  213. package/dist/translations/nb.d.ts +1 -1
  214. package/dist/translations/nb.js +2 -2
  215. package/dist/translations/nb.umd.js +2 -2
  216. package/dist/translations/ne.d.ts +1 -1
  217. package/dist/translations/ne.js +2 -2
  218. package/dist/translations/ne.umd.js +2 -2
  219. package/dist/translations/nl.d.ts +1 -1
  220. package/dist/translations/nl.js +2 -2
  221. package/dist/translations/nl.umd.js +2 -2
  222. package/dist/translations/no.d.ts +1 -1
  223. package/dist/translations/no.js +2 -2
  224. package/dist/translations/no.umd.js +2 -2
  225. package/dist/translations/oc.d.ts +1 -1
  226. package/dist/translations/oc.js +2 -2
  227. package/dist/translations/oc.umd.js +2 -2
  228. package/dist/translations/pl.d.ts +1 -1
  229. package/dist/translations/pl.js +2 -2
  230. package/dist/translations/pl.umd.js +2 -2
  231. package/dist/translations/pt-br.d.ts +1 -1
  232. package/dist/translations/pt-br.js +2 -2
  233. package/dist/translations/pt-br.umd.js +2 -2
  234. package/dist/translations/pt.d.ts +1 -1
  235. package/dist/translations/pt.js +2 -2
  236. package/dist/translations/pt.umd.js +2 -2
  237. package/dist/translations/ro.d.ts +1 -1
  238. package/dist/translations/ro.js +2 -2
  239. package/dist/translations/ro.umd.js +2 -2
  240. package/dist/translations/ru.d.ts +1 -1
  241. package/dist/translations/ru.js +2 -2
  242. package/dist/translations/ru.umd.js +2 -2
  243. package/dist/translations/si.d.ts +1 -1
  244. package/dist/translations/si.js +2 -2
  245. package/dist/translations/si.umd.js +2 -2
  246. package/dist/translations/sk.d.ts +1 -1
  247. package/dist/translations/sk.js +2 -2
  248. package/dist/translations/sk.umd.js +2 -2
  249. package/dist/translations/sl.d.ts +1 -1
  250. package/dist/translations/sl.js +2 -2
  251. package/dist/translations/sl.umd.js +2 -2
  252. package/dist/translations/sq.d.ts +1 -1
  253. package/dist/translations/sq.js +2 -2
  254. package/dist/translations/sq.umd.js +2 -2
  255. package/dist/translations/sr-latn.d.ts +1 -1
  256. package/dist/translations/sr-latn.js +2 -2
  257. package/dist/translations/sr-latn.umd.js +2 -2
  258. package/dist/translations/sr.d.ts +1 -1
  259. package/dist/translations/sr.js +2 -2
  260. package/dist/translations/sr.umd.js +2 -2
  261. package/dist/translations/sv.d.ts +1 -1
  262. package/dist/translations/sv.js +2 -2
  263. package/dist/translations/sv.umd.js +2 -2
  264. package/dist/translations/th.d.ts +1 -1
  265. package/dist/translations/th.js +2 -2
  266. package/dist/translations/th.umd.js +2 -2
  267. package/dist/translations/ti.d.ts +1 -1
  268. package/dist/translations/ti.js +2 -2
  269. package/dist/translations/ti.umd.js +2 -2
  270. package/dist/translations/tk.d.ts +1 -1
  271. package/dist/translations/tk.js +2 -2
  272. package/dist/translations/tk.umd.js +2 -2
  273. package/dist/translations/tr.d.ts +1 -1
  274. package/dist/translations/tr.js +2 -2
  275. package/dist/translations/tr.umd.js +2 -2
  276. package/dist/translations/tt.d.ts +1 -1
  277. package/dist/translations/tt.js +2 -2
  278. package/dist/translations/tt.umd.js +2 -2
  279. package/dist/translations/ug.d.ts +1 -1
  280. package/dist/translations/ug.js +2 -2
  281. package/dist/translations/ug.umd.js +2 -2
  282. package/dist/translations/uk.d.ts +1 -1
  283. package/dist/translations/uk.js +2 -2
  284. package/dist/translations/uk.umd.js +2 -2
  285. package/dist/translations/ur.d.ts +1 -1
  286. package/dist/translations/ur.js +2 -2
  287. package/dist/translations/ur.umd.js +2 -2
  288. package/dist/translations/uz.d.ts +1 -1
  289. package/dist/translations/uz.js +2 -2
  290. package/dist/translations/uz.umd.js +2 -2
  291. package/dist/translations/vi.d.ts +1 -1
  292. package/dist/translations/vi.js +2 -2
  293. package/dist/translations/vi.umd.js +2 -2
  294. package/dist/translations/zh-cn.d.ts +1 -1
  295. package/dist/translations/zh-cn.js +2 -2
  296. package/dist/translations/zh-cn.umd.js +2 -2
  297. package/dist/translations/zh.d.ts +1 -1
  298. package/dist/translations/zh.js +2 -2
  299. package/dist/translations/zh.umd.js +2 -2
  300. package/lang/contexts.json +3 -0
  301. package/lang/translations/af.po +13 -1
  302. package/lang/translations/ar.po +13 -1
  303. package/lang/translations/ast.po +13 -1
  304. package/lang/translations/az.po +13 -1
  305. package/lang/translations/be.po +13 -1
  306. package/lang/translations/bg.po +13 -1
  307. package/lang/translations/bn.po +13 -1
  308. package/lang/translations/bs.po +13 -1
  309. package/lang/translations/ca.po +13 -1
  310. package/lang/translations/cs.po +13 -1
  311. package/lang/translations/da.po +13 -1
  312. package/lang/translations/de-ch.po +13 -1
  313. package/lang/translations/de.po +13 -1
  314. package/lang/translations/el.po +13 -1
  315. package/lang/translations/en-au.po +13 -1
  316. package/lang/translations/en-gb.po +13 -1
  317. package/lang/translations/en.po +13 -1
  318. package/lang/translations/eo.po +13 -1
  319. package/lang/translations/es-co.po +13 -1
  320. package/lang/translations/es.po +13 -1
  321. package/lang/translations/et.po +13 -1
  322. package/lang/translations/eu.po +13 -1
  323. package/lang/translations/fa.po +13 -1
  324. package/lang/translations/fi.po +13 -1
  325. package/lang/translations/fr.po +13 -1
  326. package/lang/translations/gl.po +13 -1
  327. package/lang/translations/gu.po +13 -1
  328. package/lang/translations/he.po +13 -1
  329. package/lang/translations/hi.po +13 -1
  330. package/lang/translations/hr.po +13 -1
  331. package/lang/translations/hu.po +13 -1
  332. package/lang/translations/hy.po +13 -1
  333. package/lang/translations/id.po +13 -1
  334. package/lang/translations/it.po +13 -1
  335. package/lang/translations/ja.po +13 -1
  336. package/lang/translations/jv.po +13 -1
  337. package/lang/translations/kk.po +13 -1
  338. package/lang/translations/km.po +13 -1
  339. package/lang/translations/kn.po +13 -1
  340. package/lang/translations/ko.po +13 -1
  341. package/lang/translations/ku.po +13 -1
  342. package/lang/translations/lt.po +13 -1
  343. package/lang/translations/lv.po +13 -1
  344. package/lang/translations/ms.po +13 -1
  345. package/lang/translations/nb.po +13 -1
  346. package/lang/translations/ne.po +13 -1
  347. package/lang/translations/nl.po +13 -1
  348. package/lang/translations/no.po +13 -1
  349. package/lang/translations/oc.po +13 -1
  350. package/lang/translations/pl.po +13 -1
  351. package/lang/translations/pt-br.po +13 -1
  352. package/lang/translations/pt.po +13 -1
  353. package/lang/translations/ro.po +13 -1
  354. package/lang/translations/ru.po +13 -1
  355. package/lang/translations/si.po +13 -1
  356. package/lang/translations/sk.po +13 -1
  357. package/lang/translations/sl.po +13 -1
  358. package/lang/translations/sq.po +13 -1
  359. package/lang/translations/sr-latn.po +13 -1
  360. package/lang/translations/sr.po +13 -1
  361. package/lang/translations/sv.po +13 -1
  362. package/lang/translations/th.po +13 -1
  363. package/lang/translations/ti.po +13 -1
  364. package/lang/translations/tk.po +13 -1
  365. package/lang/translations/tr.po +13 -1
  366. package/lang/translations/tt.po +13 -1
  367. package/lang/translations/ug.po +13 -1
  368. package/lang/translations/uk.po +13 -1
  369. package/lang/translations/ur.po +13 -1
  370. package/lang/translations/uz.po +13 -1
  371. package/lang/translations/vi.po +13 -1
  372. package/lang/translations/zh-cn.po +13 -1
  373. package/lang/translations/zh.po +13 -1
  374. package/package.json +10 -10
  375. package/src/augmentation.d.ts +11 -2
  376. package/src/augmentation.js +1 -1
  377. package/src/commands/insertcolumncommand.d.ts +1 -1
  378. package/src/commands/insertcolumncommand.js +1 -1
  379. package/src/commands/insertrowcommand.d.ts +1 -1
  380. package/src/commands/insertrowcommand.js +1 -1
  381. package/src/commands/inserttablecommand.d.ts +1 -1
  382. package/src/commands/inserttablecommand.js +1 -1
  383. package/src/commands/inserttablelayoutcommand.d.ts +1 -1
  384. package/src/commands/inserttablelayoutcommand.js +1 -1
  385. package/src/commands/mergecellcommand.d.ts +1 -1
  386. package/src/commands/mergecellcommand.js +1 -1
  387. package/src/commands/mergecellscommand.d.ts +1 -1
  388. package/src/commands/mergecellscommand.js +1 -1
  389. package/src/commands/removecolumncommand.d.ts +1 -1
  390. package/src/commands/removecolumncommand.js +1 -1
  391. package/src/commands/removerowcommand.d.ts +1 -1
  392. package/src/commands/removerowcommand.js +1 -1
  393. package/src/commands/selectcolumncommand.d.ts +1 -1
  394. package/src/commands/selectcolumncommand.js +1 -1
  395. package/src/commands/selectrowcommand.d.ts +1 -1
  396. package/src/commands/selectrowcommand.js +1 -1
  397. package/src/commands/setheadercolumncommand.d.ts +1 -1
  398. package/src/commands/setheadercolumncommand.js +3 -3
  399. package/src/commands/setheaderrowcommand.d.ts +1 -1
  400. package/src/commands/setheaderrowcommand.js +2 -3
  401. package/src/commands/splitcellcommand.d.ts +1 -1
  402. package/src/commands/splitcellcommand.js +1 -1
  403. package/src/converters/downcast.d.ts +5 -3
  404. package/src/converters/downcast.js +21 -9
  405. package/src/converters/table-caption-post-fixer.d.ts +1 -1
  406. package/src/converters/table-caption-post-fixer.js +1 -1
  407. package/src/converters/table-cell-paragraph-post-fixer.d.ts +1 -1
  408. package/src/converters/table-cell-paragraph-post-fixer.js +1 -1
  409. package/src/converters/table-cell-refresh-handler.d.ts +1 -1
  410. package/src/converters/table-cell-refresh-handler.js +1 -1
  411. package/src/converters/table-headings-refresh-handler.d.ts +1 -1
  412. package/src/converters/table-headings-refresh-handler.js +1 -1
  413. package/src/converters/table-layout-post-fixer.d.ts +1 -1
  414. package/src/converters/table-layout-post-fixer.js +1 -1
  415. package/src/converters/tableproperties.d.ts +1 -1
  416. package/src/converters/tableproperties.js +1 -1
  417. package/src/converters/upcasttable.d.ts +1 -1
  418. package/src/converters/upcasttable.js +13 -6
  419. package/src/index.d.ts +3 -2
  420. package/src/index.js +3 -2
  421. package/src/plaintableoutput.d.ts +1 -1
  422. package/src/plaintableoutput.js +1 -1
  423. package/src/table.d.ts +1 -1
  424. package/src/table.js +1 -1
  425. package/src/tablecaption/tablecaptionediting.d.ts +1 -1
  426. package/src/tablecaption/tablecaptionediting.js +1 -1
  427. package/src/tablecaption/tablecaptionui.d.ts +1 -1
  428. package/src/tablecaption/tablecaptionui.js +1 -1
  429. package/src/tablecaption/toggletablecaptioncommand.d.ts +1 -1
  430. package/src/tablecaption/toggletablecaptioncommand.js +1 -1
  431. package/src/tablecaption/utils.d.ts +1 -1
  432. package/src/tablecaption/utils.js +1 -1
  433. package/src/tablecaption.d.ts +1 -1
  434. package/src/tablecaption.js +1 -1
  435. package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.d.ts +1 -1
  436. package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +1 -1
  437. package/src/tablecellproperties/commands/tablecellbordercolorcommand.d.ts +1 -1
  438. package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +1 -1
  439. package/src/tablecellproperties/commands/tablecellborderstylecommand.d.ts +1 -1
  440. package/src/tablecellproperties/commands/tablecellborderstylecommand.js +1 -1
  441. package/src/tablecellproperties/commands/tablecellborderwidthcommand.d.ts +1 -1
  442. package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +1 -1
  443. package/src/tablecellproperties/commands/tablecellheightcommand.d.ts +1 -1
  444. package/src/tablecellproperties/commands/tablecellheightcommand.js +1 -1
  445. package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.d.ts +1 -1
  446. package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +1 -1
  447. package/src/tablecellproperties/commands/tablecellpaddingcommand.d.ts +1 -1
  448. package/src/tablecellproperties/commands/tablecellpaddingcommand.js +1 -1
  449. package/src/tablecellproperties/commands/tablecellpropertycommand.d.ts +20 -2
  450. package/src/tablecellproperties/commands/tablecellpropertycommand.js +9 -1
  451. package/src/tablecellproperties/commands/tablecelltypecommand.d.ts +53 -0
  452. package/src/tablecellproperties/commands/tablecelltypecommand.js +167 -0
  453. package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.d.ts +1 -1
  454. package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +1 -1
  455. package/src/tablecellproperties/tablecellpropertiesediting.d.ts +1 -4
  456. package/src/tablecellproperties/tablecellpropertiesediting.js +121 -1
  457. package/src/tablecellproperties/tablecellpropertiesui.d.ts +1 -1
  458. package/src/tablecellproperties/tablecellpropertiesui.js +1 -1
  459. package/src/tablecellproperties/tablecellpropertiesuiexperimental.d.ts +1 -1
  460. package/src/tablecellproperties/tablecellpropertiesuiexperimental.js +34 -12
  461. package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +1 -1
  462. package/src/tablecellproperties/ui/tablecellpropertiesview.js +1 -1
  463. package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.d.ts +33 -4
  464. package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.js +130 -19
  465. package/src/tablecellproperties.d.ts +1 -1
  466. package/src/tablecellproperties.js +1 -1
  467. package/src/tablecellwidth/commands/tablecellwidthcommand.d.ts +1 -1
  468. package/src/tablecellwidth/commands/tablecellwidthcommand.js +1 -1
  469. package/src/tablecellwidth/tablecellwidthediting.d.ts +1 -1
  470. package/src/tablecellwidth/tablecellwidthediting.js +1 -1
  471. package/src/tableclipboard.d.ts +1 -1
  472. package/src/tableclipboard.js +1 -1
  473. package/src/tablecolumnresize/constants.d.ts +1 -1
  474. package/src/tablecolumnresize/constants.js +1 -1
  475. package/src/tablecolumnresize/converters.d.ts +1 -1
  476. package/src/tablecolumnresize/converters.js +1 -1
  477. package/src/tablecolumnresize/tablecolumnresizeediting.d.ts +1 -1
  478. package/src/tablecolumnresize/tablecolumnresizeediting.js +1 -1
  479. package/src/tablecolumnresize/tablewidthscommand.d.ts +1 -1
  480. package/src/tablecolumnresize/tablewidthscommand.js +1 -1
  481. package/src/tablecolumnresize/utils.d.ts +1 -1
  482. package/src/tablecolumnresize/utils.js +1 -1
  483. package/src/tablecolumnresize.d.ts +1 -1
  484. package/src/tablecolumnresize.js +1 -1
  485. package/src/tableconfig.d.ts +19 -1
  486. package/src/tableconfig.js +1 -1
  487. package/src/tableediting.d.ts +1 -1
  488. package/src/tableediting.js +24 -6
  489. package/src/tablekeyboard.d.ts +1 -1
  490. package/src/tablekeyboard.js +1 -1
  491. package/src/tablelayout/commands/tabletypecommand.d.ts +1 -1
  492. package/src/tablelayout/commands/tabletypecommand.js +1 -1
  493. package/src/tablelayout/tablelayoutediting.d.ts +1 -1
  494. package/src/tablelayout/tablelayoutediting.js +1 -1
  495. package/src/tablelayout/tablelayoutui.d.ts +1 -1
  496. package/src/tablelayout/tablelayoutui.js +12 -5
  497. package/src/tablelayout.d.ts +1 -1
  498. package/src/tablelayout.js +1 -1
  499. package/src/tablemouse/mouseeventsobserver.d.ts +1 -1
  500. package/src/tablemouse/mouseeventsobserver.js +1 -1
  501. package/src/tablemouse.d.ts +1 -1
  502. package/src/tablemouse.js +1 -1
  503. package/src/tableproperties/commands/tablealignmentcommand.d.ts +1 -1
  504. package/src/tableproperties/commands/tablealignmentcommand.js +1 -1
  505. package/src/tableproperties/commands/tablebackgroundcolorcommand.d.ts +1 -1
  506. package/src/tableproperties/commands/tablebackgroundcolorcommand.js +1 -1
  507. package/src/tableproperties/commands/tablebordercolorcommand.d.ts +1 -1
  508. package/src/tableproperties/commands/tablebordercolorcommand.js +1 -1
  509. package/src/tableproperties/commands/tableborderstylecommand.d.ts +1 -1
  510. package/src/tableproperties/commands/tableborderstylecommand.js +1 -1
  511. package/src/tableproperties/commands/tableborderwidthcommand.d.ts +1 -1
  512. package/src/tableproperties/commands/tableborderwidthcommand.js +1 -1
  513. package/src/tableproperties/commands/tableheightcommand.d.ts +1 -1
  514. package/src/tableproperties/commands/tableheightcommand.js +1 -1
  515. package/src/tableproperties/commands/tablepropertycommand.d.ts +1 -1
  516. package/src/tableproperties/commands/tablepropertycommand.js +1 -1
  517. package/src/tableproperties/commands/tablewidthcommand.d.ts +1 -1
  518. package/src/tableproperties/commands/tablewidthcommand.js +1 -1
  519. package/src/tableproperties/tablepropertiesediting.d.ts +1 -1
  520. package/src/tableproperties/tablepropertiesediting.js +1 -1
  521. package/src/tableproperties/tablepropertiesui.d.ts +1 -1
  522. package/src/tableproperties/tablepropertiesui.js +1 -1
  523. package/src/tableproperties/tablepropertiesuiexperimental.d.ts +1 -1
  524. package/src/tableproperties/tablepropertiesuiexperimental.js +1 -1
  525. package/src/tableproperties/ui/tablepropertiesview.d.ts +1 -1
  526. package/src/tableproperties/ui/tablepropertiesview.js +1 -1
  527. package/src/tableproperties/ui/tablepropertiesviewexperimental.d.ts +1 -1
  528. package/src/tableproperties/ui/tablepropertiesviewexperimental.js +1 -1
  529. package/src/tableproperties.d.ts +1 -1
  530. package/src/tableproperties.js +1 -1
  531. package/src/tableselection.d.ts +1 -1
  532. package/src/tableselection.js +1 -1
  533. package/src/tabletoolbar.d.ts +1 -1
  534. package/src/tabletoolbar.js +1 -1
  535. package/src/tableui.d.ts +1 -1
  536. package/src/tableui.js +1 -1
  537. package/src/tableutils.d.ts +39 -1
  538. package/src/tableutils.js +220 -14
  539. package/src/tablewalker.d.ts +1 -1
  540. package/src/tablewalker.js +1 -1
  541. package/src/ui/colorinputview.d.ts +1 -1
  542. package/src/ui/colorinputview.js +1 -1
  543. package/src/ui/inserttableview.d.ts +1 -1
  544. package/src/ui/inserttableview.js +1 -1
  545. package/src/utils/common.d.ts +24 -1
  546. package/src/utils/common.js +43 -1
  547. package/src/utils/structure.d.ts +1 -1
  548. package/src/utils/structure.js +1 -1
  549. package/src/utils/table-properties.d.ts +1 -1
  550. package/src/utils/table-properties.js +1 -1
  551. package/src/utils/ui/contextualballoon.d.ts +1 -1
  552. package/src/utils/ui/contextualballoon.js +1 -1
  553. package/src/utils/ui/table-properties.d.ts +1 -1
  554. package/src/utils/ui/table-properties.js +1 -1
  555. package/src/utils/ui/table-propertiesexperimental.d.ts +1 -1
  556. package/src/utils/ui/table-propertiesexperimental.js +1 -1
  557. package/src/utils/ui/widget.d.ts +1 -1
  558. package/src/utils/ui/widget.js +1 -1
  559. package/theme/colorinput.css +1 -1
  560. package/theme/formrow-experimental.css +1 -1
  561. package/theme/formrow.css +1 -1
  562. package/theme/inserttable.css +1 -1
  563. package/theme/table.css +7 -2
  564. package/theme/tablecaption.css +1 -1
  565. package/theme/tablecellproperties-experimental.css +4 -0
  566. package/theme/tablecellproperties.css +1 -1
  567. package/theme/tablecolumnresize.css +1 -1
  568. package/theme/tableediting.css +1 -1
  569. package/theme/tableform-experimental.css +1 -13
  570. package/theme/tableform.css +6 -7
  571. package/theme/tablelayout.css +1 -1
  572. package/theme/tableproperties-experimental.css +1 -1
  573. package/theme/tableproperties.css +1 -1
  574. package/theme/tableselection.css +1 -1
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
4
  */
5
5
  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
- import { first, global, CKEditorError, KeystrokeHandler, FocusTracker, Collection, getLocalizedArrowKeyCodeDirection, Rect, DomEmitterMixin, toUnit } from '@ckeditor/ckeditor5-utils/dist/index.js';
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
9
  import { IconTable, IconTableColumn, IconTableRow, IconTableMergeCell, IconCheck, IconCancel, IconAlignBottom, IconAlignMiddle, IconAlignTop, IconAlignJustify, IconAlignRight, IconAlignCenter, IconAlignLeft, IconTableCellProperties, IconTableLayout, IconTableProperties, IconObjectInlineRight, IconObjectCenter, IconObjectInlineLeft, IconCaption, IconPreviousArrow, IconObjectRight, IconObjectLeft } from '@ckeditor/ckeditor5-icons/dist/index.js';
10
10
  import { View, addKeyboardHandlingForGrid, ButtonView, createDropdown, MenuBarMenuView, SwitchButtonView, SplitButtonView, addListToDropdown, UIModel, ViewCollection, FocusCycler, InputTextView, ColorSelectorView, FormHeaderView, FormRowView, submitHandler, LabelView, LabeledFieldView, createLabeledDropdown, createLabeledInputText, ToolbarView, BalloonPanelView, ContextualBalloon, normalizeColorOptions, getLocalizedColorOptions, clickOutsideHandler, DropdownButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
@@ -504,83 +504,7 @@ const downcastTableAlignmentConfig = {
504
504
  };
505
505
 
506
506
  /**
507
- * A common method to update the numeric value. If a value is the default one, it will be unset.
508
- *
509
- * @internal
510
- * @param key An attribute key.
511
- * @param value The new attribute value.
512
- * @param item A model item on which the attribute will be set.
513
- * @param defaultValue The default attribute value. If a value is lower or equal, it will be unset.
514
- */ function updateNumericAttribute(key, value, item, writer, defaultValue = 1) {
515
- if (value !== undefined && value !== null && defaultValue !== undefined && defaultValue !== null && value > defaultValue) {
516
- writer.setAttribute(key, value, item);
517
- } else {
518
- writer.removeAttribute(key, item);
519
- }
520
- }
521
- /**
522
- * A common method to create an empty table cell. It creates a proper model structure as a table cell must have at least one block inside.
523
- *
524
- * @internal
525
- * @param writer The model writer.
526
- * @param insertPosition The position at which the table cell should be inserted.
527
- * @param attributes The element attributes.
528
- * @returns Created table cell.
529
- */ function createEmptyTableCell(writer, insertPosition, attributes = {}) {
530
- const tableCell = writer.createElement('tableCell', attributes);
531
- writer.insertElement('paragraph', tableCell);
532
- writer.insert(tableCell, insertPosition);
533
- return tableCell;
534
- }
535
- /**
536
- * Checks if a table cell belongs to the heading column section.
537
- *
538
- * @internal
539
- */ function isHeadingColumnCell(tableUtils, tableCell) {
540
- const table = tableCell.parent.parent;
541
- const headingColumns = parseInt(table.getAttribute('headingColumns') || '0');
542
- const { column } = tableUtils.getCellLocation(tableCell);
543
- return !!headingColumns && column < headingColumns;
544
- }
545
- /**
546
- * Enables conversion for an attribute for simple view-model mappings.
547
- *
548
- * @internal
549
- * @param options.defaultValue The default value for the specified `modelAttribute`.
550
- */ function enableProperty$1(schema, conversion, options) {
551
- const { modelAttribute } = options;
552
- schema.extend('tableCell', {
553
- allowAttributes: [
554
- modelAttribute
555
- ]
556
- });
557
- schema.setAttributeProperties(modelAttribute, {
558
- isFormatting: true
559
- });
560
- upcastStyleToAttribute(conversion, {
561
- viewElement: /^(td|th)$/,
562
- ...options
563
- });
564
- downcastAttributeToStyle(conversion, {
565
- modelElement: 'tableCell',
566
- ...options
567
- });
568
- }
569
- /**
570
- * Depending on the position of the selection we either return the table under cursor or look for the table higher in the hierarchy.
571
- *
572
- * @internal
573
- */ function getSelectionAffectedTable(selection) {
574
- const selectedElement = selection.getSelectedElement();
575
- // Is the command triggered from the `tableToolbar`?
576
- if (selectedElement && selectedElement.is('element', 'table')) {
577
- return selectedElement;
578
- }
579
- return selection.getFirstPosition().findAncestor('table');
580
- }
581
-
582
- /**
583
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
507
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
584
508
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
585
509
  */ /**
586
510
  * @module table/tablewalker
@@ -1017,6 +941,122 @@ const downcastTableAlignmentConfig = {
1017
941
  // @if CK_DEBUG // } );
1018
942
  // @if CK_DEBUG // }
1019
943
 
944
+ /**
945
+ * A common method to update the numeric value. If a value is the default one, it will be unset.
946
+ *
947
+ * @internal
948
+ * @param key An attribute key.
949
+ * @param value The new attribute value.
950
+ * @param item A model item on which the attribute will be set.
951
+ * @param defaultValue The default attribute value. If a value is lower or equal, it will be unset.
952
+ */ function updateNumericAttribute(key, value, item, writer, defaultValue = 1) {
953
+ if (value !== undefined && value !== null && defaultValue !== undefined && defaultValue !== null && value > defaultValue) {
954
+ writer.setAttribute(key, value, item);
955
+ } else {
956
+ writer.removeAttribute(key, item);
957
+ }
958
+ }
959
+ /**
960
+ * A common method to create an empty table cell. It creates a proper model structure as a table cell must have at least one block inside.
961
+ *
962
+ * @internal
963
+ * @param writer The model writer.
964
+ * @param insertPosition The position at which the table cell should be inserted.
965
+ * @param attributes The element attributes.
966
+ * @returns Created table cell.
967
+ */ function createEmptyTableCell(writer, insertPosition, attributes = {}) {
968
+ const tableCell = writer.createElement('tableCell', attributes);
969
+ writer.insertElement('paragraph', tableCell);
970
+ writer.insert(tableCell, insertPosition);
971
+ return tableCell;
972
+ }
973
+ /**
974
+ * Checks if a table cell belongs to the heading column section.
975
+ *
976
+ * @internal
977
+ */ function isHeadingColumnCell(tableUtils, tableCell) {
978
+ const table = tableCell.parent.parent;
979
+ const headingColumns = parseInt(table.getAttribute('headingColumns') || '0');
980
+ const { column } = tableUtils.getCellLocation(tableCell);
981
+ return !!headingColumns && column < headingColumns;
982
+ }
983
+ /**
984
+ * Enables conversion for an attribute for simple view-model mappings.
985
+ *
986
+ * @internal
987
+ * @param options.defaultValue The default value for the specified `modelAttribute`.
988
+ */ function enableProperty$1(schema, conversion, options) {
989
+ const { modelAttribute } = options;
990
+ schema.extend('tableCell', {
991
+ allowAttributes: [
992
+ modelAttribute
993
+ ]
994
+ });
995
+ schema.setAttributeProperties(modelAttribute, {
996
+ isFormatting: true
997
+ });
998
+ upcastStyleToAttribute(conversion, {
999
+ viewElement: /^(td|th)$/,
1000
+ ...options
1001
+ });
1002
+ downcastAttributeToStyle(conversion, {
1003
+ modelElement: 'tableCell',
1004
+ ...options
1005
+ });
1006
+ }
1007
+ /**
1008
+ * Depending on the position of the selection we either return the table under cursor or look for the table higher in the hierarchy.
1009
+ *
1010
+ * @internal
1011
+ */ function getSelectionAffectedTable(selection) {
1012
+ const selectedElement = selection.getSelectedElement();
1013
+ // Is the command triggered from the `tableToolbar`?
1014
+ if (selectedElement && selectedElement.is('element', 'table')) {
1015
+ return selectedElement;
1016
+ }
1017
+ return selection.getFirstPosition().findAncestor('table');
1018
+ }
1019
+ /**
1020
+ * Groups table cells by their parent table.
1021
+ *
1022
+ * @internal
1023
+ */ function groupCellsByTable(tableCells) {
1024
+ const tableMap = new Map();
1025
+ for (const tableCell of tableCells){
1026
+ const table = tableCell.findAncestor('table');
1027
+ if (!tableMap.has(table)) {
1028
+ tableMap.set(table, []);
1029
+ }
1030
+ tableMap.get(table).push(tableCell);
1031
+ }
1032
+ return tableMap;
1033
+ }
1034
+ /**
1035
+ * Checks if all cells in a given row or column are header cells.
1036
+ *
1037
+ * @internal
1038
+ */ function isEntireCellsLineHeader({ table, row, column }) {
1039
+ const tableWalker = new TableWalker(table, {
1040
+ row,
1041
+ column
1042
+ });
1043
+ for (const { cell } of tableWalker){
1044
+ const cellType = cell.getAttribute('tableCellType');
1045
+ if (cellType !== 'header') {
1046
+ return false;
1047
+ }
1048
+ }
1049
+ return true;
1050
+ }
1051
+ /**
1052
+ * Checks whether the `tableCellType` attribute is enabled in the editor schema and the experimental flag is set.
1053
+ *
1054
+ * @internal
1055
+ */ function isTableCellTypeEnabled(editor) {
1056
+ const { model, config } = editor;
1057
+ return model.schema.checkAttribute('tableCell', 'tableCellType') && config.get('experimentalFlags.tableCellTypeSupport') === true;
1058
+ }
1059
+
1020
1060
  /**
1021
1061
  * Returns a cropped table according to given dimensions.
1022
1062
 
@@ -1642,9 +1682,12 @@ const downcastTableAlignmentConfig = {
1642
1682
  * headingRows - The number of rows that go as table headers.
1643
1683
  * headingColumns - The maximum number of row headings.
1644
1684
  * rows - Sorted `<tr>` elements as they should go into the model - ie. if `<thead>` is inserted after `<tbody>` in the view.
1685
+ *
1686
+ * @param viewTable The view table element.
1687
+ * @returns The table metadata.
1645
1688
  */ function scanTable(viewTable) {
1646
- let headingRows = 0;
1647
1689
  let headingColumns = undefined;
1690
+ let shouldAccumulateHeadingRows = true;
1648
1691
  // The `<tbody>` and `<thead>` sections in the DOM do not have to be in order `<thead>` -> `<tbody>` and there might be more than one
1649
1692
  // of them.
1650
1693
  // As the model does not have these sections, rows from different sections must be sorted.
@@ -1670,6 +1713,7 @@ const downcastTableAlignmentConfig = {
1670
1713
  }
1671
1714
  // Save the first `<thead>` in the table as table header - all other ones will be converted to table body rows.
1672
1715
  if (tableChild.name === 'thead' && !firstTheadElement) {
1716
+ shouldAccumulateHeadingRows = true;
1673
1717
  firstTheadElement = tableChild;
1674
1718
  }
1675
1719
  // There might be some extra empty text nodes between the `<tr>`s.
@@ -1684,11 +1728,13 @@ const downcastTableAlignmentConfig = {
1684
1728
  // This case is problematic because it's not clear if this row should be a heading row or not, as it may be result
1685
1729
  // of the cell span from the previous row.
1686
1730
  // Issue: https://github.com/ckeditor/ckeditor5/issues/17556
1687
- (maxPrevColumns === null || trColumns.length === maxPrevColumns) && trColumns.every((e)=>e.is('element', 'th'))) {
1688
- headingRows++;
1731
+ (maxPrevColumns === null || trColumns.length === maxPrevColumns) && trColumns.every((e)=>e.is('element', 'th')) && // If there is at least one "normal" table row between heading rows, then stop accumulating heading rows.
1732
+ shouldAccumulateHeadingRows) {
1689
1733
  headRows.push(tr);
1734
+ shouldAccumulateHeadingRows = true;
1690
1735
  } else {
1691
1736
  bodyRows.push(tr);
1737
+ shouldAccumulateHeadingRows = false;
1692
1738
  }
1693
1739
  // We use the maximum number of columns to avoid false positives when detecting
1694
1740
  // multiple rows with single column within `rowspan`. Without it the last row of `rowspan=3`
@@ -1708,12 +1754,12 @@ const downcastTableAlignmentConfig = {
1708
1754
  index += 1;
1709
1755
  }
1710
1756
  // Update headingColumns.
1711
- if (!headingColumns || index < headingColumns) {
1757
+ if (headingColumns === undefined || index < headingColumns) {
1712
1758
  headingColumns = index;
1713
1759
  }
1714
1760
  }
1715
1761
  return {
1716
- headingRows,
1762
+ headingRows: headRows.length,
1717
1763
  headingColumns: headingColumns || 0,
1718
1764
  rows: [
1719
1765
  ...headRows,
@@ -2017,9 +2063,17 @@ const downcastTableAlignmentConfig = {
2017
2063
  *
2018
2064
  * @internal
2019
2065
  * @param options.asWidget If set to `true`, the downcast conversion will produce a widget.
2066
+ * @param options.cellTypeEnabled If returns `true`, the downcast conversion will use the `tableCellType` attribute to determine cell type.
2020
2067
  * @returns Element creator.
2021
- */ function downcastCell(options = {}) {
2068
+ */ function downcastCell(options) {
2022
2069
  return (tableCell, { writer })=>{
2070
+ // If the table cell type feature is enabled, then we can simply check the cell type attribute.
2071
+ if (options.cellTypeEnabled?.()) {
2072
+ const cellElementName = tableCell.getAttribute('tableCellType') === 'header' ? 'th' : 'td';
2073
+ return createCellElement(writer, cellElementName);
2074
+ }
2075
+ // If the table cell type feature is not enabled, we should iterate through the table structure
2076
+ // to determine whether the cell is in the heading section.
2023
2077
  const tableRow = tableCell.parent;
2024
2078
  const table = tableRow.parent;
2025
2079
  const rowIndex = table.getChildIndex(tableRow);
@@ -2033,15 +2087,17 @@ const downcastTableAlignmentConfig = {
2033
2087
  for (const tableSlot of tableWalker){
2034
2088
  if (tableSlot.cell == tableCell) {
2035
2089
  const isHeading = tableSlot.row < headingRows || tableSlot.column < headingColumns;
2036
- const cellElementName = isHeading ? 'th' : 'td';
2037
- result = options.asWidget ? toWidgetEditable(writer.createEditableElement(cellElementName), writer, {
2038
- withAriaRole: false
2039
- }) : writer.createContainerElement(cellElementName);
2090
+ result = createCellElement(writer, isHeading ? 'th' : 'td');
2040
2091
  break;
2041
2092
  }
2042
2093
  }
2043
2094
  return result;
2044
2095
  };
2096
+ function createCellElement(writer, name) {
2097
+ return options.asWidget ? toWidgetEditable(writer.createEditableElement(name), writer, {
2098
+ withAriaRole: false
2099
+ }) : writer.createContainerElement(name);
2100
+ }
2045
2101
  }
2046
2102
  /**
2047
2103
  * Overrides paragraph inside table cell conversion.
@@ -2149,7 +2205,7 @@ const downcastTableAlignmentConfig = {
2149
2205
  *
2150
2206
  * @param table Table model element.
2151
2207
  * @param conversionApi The conversion API object.
2152
- * @param defaultTableProperties Normalized default table properties.
2208
+ * @param editor The editor instance.
2153
2209
  * @returns Created element.
2154
2210
  */ function downcastPlainTable(table, conversionApi, editor) {
2155
2211
  const writer = conversionApi.writer;
@@ -2175,7 +2231,7 @@ const downcastTableAlignmentConfig = {
2175
2231
  const tableAttributes = {
2176
2232
  class: 'table'
2177
2233
  };
2178
- if (editor.plugins.has('TableProperties') && conversionApi.options.isClipboardPipeline) {
2234
+ if (editor.plugins.has('TablePropertiesEditing') && conversionApi.options.isClipboardPipeline) {
2179
2235
  const defaultTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
2180
2236
  includeAlignmentProperty: true
2181
2237
  });
@@ -2885,7 +2941,7 @@ const downcastTableAlignmentConfig = {
2885
2941
  splitHorizontally(cell, headingRowsToSet, writer);
2886
2942
  }
2887
2943
  }
2888
- updateNumericAttribute('headingRows', headingRowsToSet, table, writer, 0);
2944
+ tableUtils.setHeadingRowsCount(writer, table, headingRowsToSet);
2889
2945
  });
2890
2946
  }
2891
2947
  /**
@@ -2955,13 +3011,13 @@ const downcastTableAlignmentConfig = {
2955
3011
  splitVertically(cell, column, headingColumnsToSet, writer);
2956
3012
  }
2957
3013
  }
2958
- updateNumericAttribute('headingColumns', headingColumnsToSet, table, writer, 0);
3014
+ tableUtils.setHeadingColumnsCount(writer, table, headingColumnsToSet);
2959
3015
  });
2960
3016
  }
2961
3017
  }
2962
3018
 
2963
3019
  /**
2964
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3020
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
2965
3021
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
2966
3022
  */ /**
2967
3023
  * @module table/tablecolumnresize/constants
@@ -3413,10 +3469,10 @@ const downcastTableAlignmentConfig = {
3413
3469
  const columns = options.columns || 2;
3414
3470
  createEmptyRows(writer, table, 0, rows, columns);
3415
3471
  if (options.headingRows) {
3416
- updateNumericAttribute('headingRows', Math.min(options.headingRows, rows), table, writer, 0);
3472
+ this.setHeadingRowsCount(writer, table, Math.min(options.headingRows, rows));
3417
3473
  }
3418
3474
  if (options.headingColumns) {
3419
- updateNumericAttribute('headingColumns', Math.min(options.headingColumns, columns), table, writer, 0);
3475
+ this.setHeadingColumnsCount(writer, table, Math.min(options.headingColumns, columns));
3420
3476
  }
3421
3477
  return table;
3422
3478
  }
@@ -3453,6 +3509,7 @@ const downcastTableAlignmentConfig = {
3453
3509
  const rowsToInsert = options.rows || 1;
3454
3510
  const isCopyStructure = options.copyStructureFromAbove !== undefined;
3455
3511
  const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt;
3512
+ const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
3456
3513
  const rows = this.getRows(table);
3457
3514
  const columns = this.getColumns(table);
3458
3515
  if (insertAt > rows) {
@@ -3465,14 +3522,29 @@ const downcastTableAlignmentConfig = {
3465
3522
  });
3466
3523
  }
3467
3524
  model.change((writer)=>{
3468
- const headingRows = table.getAttribute('headingRows') || 0;
3525
+ let headingRows = table.getAttribute('headingRows') || 0;
3526
+ const headingColumns = table.getAttribute('headingColumns') || 0;
3469
3527
  // Inserting rows inside heading section requires to update `headingRows` attribute as the heading section will grow.
3470
3528
  if (headingRows > insertAt) {
3471
- updateNumericAttribute('headingRows', headingRows + rowsToInsert, table, writer, 0);
3529
+ headingRows += rowsToInsert;
3530
+ this.setHeadingRowsCount(writer, table, headingRows, {
3531
+ shallow: true
3532
+ });
3472
3533
  }
3473
3534
  // Inserting at the end or at the beginning of a table doesn't require to calculate anything special.
3474
3535
  if (!isCopyStructure && (insertAt === 0 || insertAt === rows)) {
3475
- createEmptyRows(writer, table, insertAt, rowsToInsert, columns);
3536
+ const rows = createEmptyRows(writer, table, insertAt, rowsToInsert, columns);
3537
+ if (cellTypeEnabled) {
3538
+ for(let rowOffset = 0; rowOffset < rows.length; rowOffset++){
3539
+ const row = rows[rowOffset];
3540
+ for(let columnIndex = 0; columnIndex < columns; columnIndex++){
3541
+ const cell = row[columnIndex];
3542
+ if (insertAt + rowOffset < headingRows || columnIndex < headingColumns) {
3543
+ writer.setAttribute('tableCellType', 'header', cell);
3544
+ }
3545
+ }
3546
+ }
3547
+ }
3476
3548
  return;
3477
3549
  }
3478
3550
  // Iterate over all the rows above the inserted rows in order to check for the row-spanned cells.
@@ -3504,9 +3576,13 @@ const downcastTableAlignmentConfig = {
3504
3576
  const insertPosition = writer.createPositionAt(tableRow, 'end');
3505
3577
  // Insert the empty cell only if this slot is not row-spanned from any other cell.
3506
3578
  if (colspan > 0) {
3507
- createEmptyTableCell(writer, insertPosition, colspan > 1 ? {
3579
+ const insertedCells = createEmptyTableCell(writer, insertPosition, colspan > 1 ? {
3508
3580
  colspan
3509
3581
  } : undefined);
3582
+ // If we insert row in heading section, set proper cell type.
3583
+ if (cellTypeEnabled && (insertAt + rowIndex < headingRows || cellIndex < headingColumns)) {
3584
+ writer.setAttribute('tableCellType', 'header', insertedCells);
3585
+ }
3510
3586
  }
3511
3587
  // Skip the col-spanned slots, there won't be any cells.
3512
3588
  cellIndex += Math.abs(colspan) - 1;
@@ -3544,21 +3620,36 @@ const downcastTableAlignmentConfig = {
3544
3620
  const model = this.editor.model;
3545
3621
  const insertAt = options.at || 0;
3546
3622
  const columnsToInsert = options.columns || 1;
3623
+ const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
3547
3624
  model.change((writer)=>{
3548
- const headingColumns = table.getAttribute('headingColumns');
3625
+ const headingRows = table.getAttribute('headingRows') || 0;
3626
+ let headingColumns = table.getAttribute('headingColumns');
3549
3627
  // Inserting columns inside heading section requires to update `headingColumns` attribute as the heading section will grow.
3550
3628
  if (insertAt < headingColumns) {
3551
- writer.setAttribute('headingColumns', headingColumns + columnsToInsert, table);
3629
+ headingColumns += columnsToInsert;
3630
+ this.setHeadingColumnsCount(writer, table, headingColumns, {
3631
+ shallow: true
3632
+ });
3552
3633
  }
3553
3634
  const tableColumns = this.getColumns(table);
3554
3635
  // Inserting at the end and at the beginning of a table doesn't require to calculate anything special.
3555
3636
  if (insertAt === 0 || tableColumns === insertAt) {
3637
+ let rowIndex = 0;
3556
3638
  for (const tableRow of table.getChildren()){
3557
3639
  // Ignore non-row elements inside the table (e.g. caption).
3558
3640
  if (!tableRow.is('element', 'tableRow')) {
3559
3641
  continue;
3560
3642
  }
3561
- createCells(columnsToInsert, writer, writer.createPositionAt(tableRow, insertAt ? 'end' : 0));
3643
+ const insertedCells = createCells(columnsToInsert, writer, writer.createPositionAt(tableRow, insertAt ? 'end' : 0));
3644
+ if (cellTypeEnabled) {
3645
+ // If we insert column in heading section, set proper cell type.
3646
+ for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
3647
+ if (insertAt + columnOffset < headingColumns || rowIndex < headingRows) {
3648
+ writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
3649
+ }
3650
+ }
3651
+ }
3652
+ rowIndex++;
3562
3653
  }
3563
3654
  return;
3564
3655
  }
@@ -3584,7 +3675,15 @@ const downcastTableAlignmentConfig = {
3584
3675
  } else {
3585
3676
  // It's either cell at this column index or spanned cell by a row-spanned cell from row above.
3586
3677
  // In table above it's cell "e" and a spanned position from row below (empty cell between cells "g" and "h")
3587
- createCells(columnsToInsert, writer, tableSlot.getPositionBefore());
3678
+ const insertedCells = createCells(columnsToInsert, writer, tableSlot.getPositionBefore());
3679
+ // If we insert column in heading section, set proper cell type.
3680
+ if (cellTypeEnabled) {
3681
+ for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
3682
+ if (insertAt + columnOffset < headingColumns || row < headingRows) {
3683
+ writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
3684
+ }
3685
+ }
3686
+ }
3588
3687
  }
3589
3688
  }
3590
3689
  });
@@ -3664,6 +3763,20 @@ const downcastTableAlignmentConfig = {
3664
3763
  // because of cleaning empty rows and we only removed one of them.
3665
3764
  removeEmptyRows(table, this);
3666
3765
  }
3766
+ // 3. If next rows are entirely header, adjust heading rows count.
3767
+ if (isTableCellTypeEnabled(this.editor)) {
3768
+ let headingRows = table.getAttribute('headingRows') || 0;
3769
+ const totalRows = this.getRows(table);
3770
+ while(headingRows < totalRows && isEntireCellsLineHeader({
3771
+ table,
3772
+ row: headingRows
3773
+ })){
3774
+ headingRows++;
3775
+ }
3776
+ this.setHeadingRowsCount(writer, table, headingRows, {
3777
+ shallow: true
3778
+ });
3779
+ }
3667
3780
  });
3668
3781
  }
3669
3782
  /**
@@ -3736,6 +3849,20 @@ const downcastTableAlignmentConfig = {
3736
3849
  // because of cleaning empty columns and we only removed one of them.
3737
3850
  removeEmptyColumns(table, this);
3738
3851
  }
3852
+ // If next columns are entirely header, adjust heading columns count.
3853
+ if (isTableCellTypeEnabled(this.editor)) {
3854
+ let headingColumns = table.getAttribute('headingColumns') || 0;
3855
+ const totalColumns = this.getColumns(table);
3856
+ while(headingColumns < totalColumns && isEntireCellsLineHeader({
3857
+ table,
3858
+ column: headingColumns
3859
+ })){
3860
+ headingColumns++;
3861
+ }
3862
+ this.setHeadingColumnsCount(writer, table, headingColumns, {
3863
+ shallow: true
3864
+ });
3865
+ }
3739
3866
  });
3740
3867
  }
3741
3868
  /**
@@ -4050,6 +4177,148 @@ const downcastTableAlignmentConfig = {
4050
4177
  }
4051
4178
  return cells;
4052
4179
  }
4180
+ /**
4181
+ * Sets the number of heading rows for the given `table`.
4182
+ *
4183
+ * @param writer The model writer.
4184
+ * @param table The table model element.
4185
+ * @param headingRows The number of heading rows to set.
4186
+ * @param options Additional options.
4187
+ * @param options.shallow If set to `true` it will only update the `headingRows` attribute
4188
+ * without updating the cell types in the table. Default is `false`.
4189
+ * @param options.resetFormerHeadingCells If set to `true`, it will check if the rows that are no longer in the heading section
4190
+ * should be updated to body cells. Default is `true`.
4191
+ * @param options.autoExpand If set to `true`, it will check if the following rows look like a header and expand the heading section.
4192
+ * Default is `true`.
4193
+ */ setHeadingRowsCount(writer, table, headingRows, options = {}) {
4194
+ const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
4195
+ const oldHeadingRows = table.getAttribute('headingRows') || 0;
4196
+ if (headingRows === oldHeadingRows) {
4197
+ return;
4198
+ }
4199
+ updateNumericAttribute('headingRows', headingRows, table, writer, 0);
4200
+ if (shallow || !isTableCellTypeEnabled(this.editor)) {
4201
+ return;
4202
+ }
4203
+ // Set header type to all cells in new heading rows.
4204
+ for (const { cell, row, column } of new TableWalker(table, {
4205
+ endRow: headingRows - 1
4206
+ })){
4207
+ updateTableCellType({
4208
+ table,
4209
+ writer,
4210
+ cell,
4211
+ row,
4212
+ column
4213
+ });
4214
+ }
4215
+ // If heading rows were reduced, set body type to all cells in rows that are no longer in heading section.
4216
+ if (resetFormerHeadingCells && headingRows < oldHeadingRows) {
4217
+ for(let row = headingRows; row < oldHeadingRows; row++){
4218
+ // Handle edge case when some cells were already changed to body type manually,
4219
+ // before changing heading rows count.
4220
+ if (!isEntireCellsLineHeader({
4221
+ table,
4222
+ row
4223
+ })) {
4224
+ break;
4225
+ }
4226
+ for (const { cell, row: cellRow, column } of new TableWalker(table, {
4227
+ row
4228
+ })){
4229
+ updateTableCellType({
4230
+ table,
4231
+ writer,
4232
+ cell,
4233
+ row: cellRow,
4234
+ column
4235
+ });
4236
+ }
4237
+ }
4238
+ }
4239
+ // If following rows looks like header, expand heading rows to cover them.
4240
+ if (autoExpand && headingRows > oldHeadingRows) {
4241
+ const totalRows = this.getRows(table);
4242
+ while(headingRows < totalRows && isEntireCellsLineHeader({
4243
+ table,
4244
+ row: headingRows
4245
+ })){
4246
+ headingRows++;
4247
+ }
4248
+ updateNumericAttribute('headingRows', headingRows, table, writer, 0);
4249
+ }
4250
+ }
4251
+ /**
4252
+ * Sets the number of heading columns for the given `table`.
4253
+ *
4254
+ * @param writer The model writer to use.
4255
+ * @param table The table model element.
4256
+ * @param headingColumns The number of heading columns to set.
4257
+ * @param options Additional options.
4258
+ * @param options.shallow If set to `true` it will only update the `headingColumns` attribute
4259
+ * without updating the cell types in the table. Default is `false`.
4260
+ * @param options.resetFormerHeadingCells If set to `true`, it will check if the columns that are no longer in the heading section
4261
+ * should be updated to body cells. Default is `true`.
4262
+ * @param options.autoExpand If set to `true`, it will check if the following columns look like a header and expand the heading section.
4263
+ * Default is `true`.
4264
+ */ setHeadingColumnsCount(writer, table, headingColumns, options = {}) {
4265
+ const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
4266
+ const oldHeadingColumns = table.getAttribute('headingColumns') || 0;
4267
+ if (headingColumns === oldHeadingColumns) {
4268
+ return;
4269
+ }
4270
+ updateNumericAttribute('headingColumns', headingColumns, table, writer, 0);
4271
+ if (shallow || !isTableCellTypeEnabled(this.editor)) {
4272
+ return;
4273
+ }
4274
+ // Set header type to all cells in new heading columns.
4275
+ for (const { cell, row, column } of new TableWalker(table, {
4276
+ endColumn: headingColumns - 1
4277
+ })){
4278
+ updateTableCellType({
4279
+ table,
4280
+ writer,
4281
+ cell,
4282
+ row,
4283
+ column
4284
+ });
4285
+ }
4286
+ // If heading columns were reduced, set body type to all cells in columns that are no longer in heading section.
4287
+ if (resetFormerHeadingCells && headingColumns < oldHeadingColumns) {
4288
+ for(let column = headingColumns; column < oldHeadingColumns; column++){
4289
+ // Handle edge case when some cells were already changed to body type manually,
4290
+ // before changing heading columns count.
4291
+ if (!isEntireCellsLineHeader({
4292
+ table,
4293
+ column
4294
+ })) {
4295
+ break;
4296
+ }
4297
+ for (const { cell, row, column: cellColumn } of new TableWalker(table, {
4298
+ column
4299
+ })){
4300
+ updateTableCellType({
4301
+ table,
4302
+ writer,
4303
+ cell,
4304
+ row,
4305
+ column: cellColumn
4306
+ });
4307
+ }
4308
+ }
4309
+ }
4310
+ // If following columns looks like header, expand heading columns to cover them.
4311
+ if (autoExpand && headingColumns > oldHeadingColumns) {
4312
+ const totalColumns = this.getColumns(table);
4313
+ while(headingColumns < totalColumns && isEntireCellsLineHeader({
4314
+ table,
4315
+ column: headingColumns
4316
+ })){
4317
+ headingColumns++;
4318
+ }
4319
+ updateNumericAttribute('headingColumns', headingColumns, table, writer, 0);
4320
+ }
4321
+ }
4053
4322
  /**
4054
4323
  * Returns all model table cells that the provided model selection's ranges
4055
4324
  * {@link module:engine/model/range~ModelRange#start} inside.
@@ -4228,20 +4497,27 @@ const downcastTableAlignmentConfig = {
4228
4497
  * @param rows The number of rows to create.
4229
4498
  * @param tableCellToInsert The number of cells to insert in each row.
4230
4499
  */ function createEmptyRows(writer, table, insertAt, rows, tableCellToInsert, attributes = {}) {
4500
+ const insertedRows = [];
4231
4501
  for(let i = 0; i < rows; i++){
4232
4502
  const tableRow = writer.createElement('tableRow');
4233
4503
  writer.insert(tableRow, table, insertAt);
4234
- createCells(tableCellToInsert, writer, writer.createPositionAt(tableRow, 'end'), attributes);
4504
+ insertedRows.push(createCells(tableCellToInsert, writer, writer.createPositionAt(tableRow, 'end'), attributes));
4235
4505
  }
4506
+ return insertedRows;
4236
4507
  }
4237
4508
  /**
4238
4509
  * Creates cells at a given position.
4239
4510
  *
4240
4511
  * @param cells The number of cells to create
4241
4512
  */ function createCells(cells, writer, insertPosition, attributes = {}) {
4513
+ const createdCells = [];
4514
+ let currentPosition = insertPosition;
4242
4515
  for(let i = 0; i < cells; i++){
4243
- createEmptyTableCell(writer, insertPosition, attributes);
4516
+ const cell = createEmptyTableCell(writer, currentPosition, attributes);
4517
+ createdCells.push(cell);
4518
+ currentPosition = writer.createPositionAfter(cell);
4244
4519
  }
4520
+ return createdCells;
4245
4521
  }
4246
4522
  /**
4247
4523
  * Evenly distributes the span of a cell to a number of provided cells.
@@ -4390,6 +4666,18 @@ function compareRangeOrder(rangeA, rangeB) {
4390
4666
  const firstColumn = Math.min(...columnIndexes);
4391
4667
  return (lastRow - firstRow + 1) * (lastColumn - firstColumn + 1);
4392
4668
  }
4669
+ /**
4670
+ * Updates the `tableCellType` attribute of a table cell based on its position in the table
4671
+ * and the table's `headingRows` and `headingColumns` attributes.
4672
+ */ function updateTableCellType({ writer, table, row, column, cell }) {
4673
+ const headingRows = table.getAttribute('headingRows') || 0;
4674
+ const headingColumns = table.getAttribute('headingColumns') || 0;
4675
+ if (row >= headingRows && column >= headingColumns) {
4676
+ writer.removeAttribute('tableCellType', cell);
4677
+ } else {
4678
+ writer.setAttribute('tableCellType', 'header', cell);
4679
+ }
4680
+ }
4393
4681
 
4394
4682
  /**
4395
4683
  * The merge cells command.
@@ -4934,7 +5222,7 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
4934
5222
  }
4935
5223
 
4936
5224
  /**
4937
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
5225
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
4938
5226
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4939
5227
  */ /**
4940
5228
  * @module table/converters/table-cell-paragraph-post-fixer
@@ -5232,12 +5520,15 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
5232
5520
  conversion.for('editingDowncast').elementToElement({
5233
5521
  model: 'tableCell',
5234
5522
  view: downcastCell({
5235
- asWidget: true
5523
+ asWidget: true,
5524
+ cellTypeEnabled: ()=>isTableCellTypeEnabled(this.editor)
5236
5525
  })
5237
5526
  });
5238
5527
  conversion.for('dataDowncast').elementToElement({
5239
5528
  model: 'tableCell',
5240
- view: downcastCell()
5529
+ view: downcastCell({
5530
+ cellTypeEnabled: ()=>isTableCellTypeEnabled(this.editor)
5531
+ })
5241
5532
  });
5242
5533
  // Duplicates code - needed to properly refresh paragraph inside a table cell.
5243
5534
  conversion.for('editingDowncast').elementToElement({
@@ -5280,6 +5571,14 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
5280
5571
  // Define the config.
5281
5572
  editor.config.define('table.defaultHeadings.rows', 0);
5282
5573
  editor.config.define('table.defaultHeadings.columns', 0);
5574
+ editor.config.define('table.showHiddenBorders', true);
5575
+ if (editor.config.get('table.showHiddenBorders')) {
5576
+ editor.editing.view.change((writer)=>{
5577
+ for (const root of editor.editing.view.document.roots){
5578
+ writer.addClass('ck-table-show-hidden-borders', root);
5579
+ }
5580
+ });
5581
+ }
5283
5582
  // Define all the commands.
5284
5583
  editor.commands.add('insertTable', new InsertTableCommand(editor));
5285
5584
  editor.commands.add('insertTableRowAbove', new InsertRowCommand(editor, {
@@ -5322,7 +5621,11 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
5322
5621
  injectTableLayoutPostFixer(model);
5323
5622
  injectTableCellParagraphPostFixer(model);
5324
5623
  this.listenTo(model.document, 'change:data', ()=>{
5325
- tableHeadingsRefreshHandler(model, editor.editing);
5624
+ // It's no longer needed to refresh table headings on every data change if table cell type feature is enabled.
5625
+ // It's because headings rows / columns are updated based on cell types which triggers their own refresh handler.
5626
+ if (!isTableCellTypeEnabled(editor)) {
5627
+ tableHeadingsRefreshHandler(model, editor.editing);
5628
+ }
5326
5629
  tableCellRefreshHandler(model, editor.editing);
5327
5630
  });
5328
5631
  }
@@ -5343,7 +5646,7 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
5343
5646
  converterPriority: 'high'
5344
5647
  });
5345
5648
  // Make sure table <caption> is downcasted into <caption> in the data pipeline when necessary.
5346
- if (editor.plugins.has('TableCaption')) {
5649
+ if (editor.plugins.has('TableCaptionEditing')) {
5347
5650
  editor.conversion.for('dataDowncast').elementToElement({
5348
5651
  model: 'caption',
5349
5652
  view: convertPlainTableCaption(editor),
@@ -5351,7 +5654,7 @@ function getMaxOffset(tableCell, start, currentMaxOffset, which) {
5351
5654
  });
5352
5655
  }
5353
5656
  // Handle border-style, border-color, border-width and background-color table attributes.
5354
- if (editor.plugins.has('TableProperties')) {
5657
+ if (editor.plugins.has('TablePropertiesEditing')) {
5355
5658
  downcastTableBorderAndBackgroundAttributes(editor);
5356
5659
  }
5357
5660
  }
@@ -9020,6 +9323,9 @@ const propertyToCommandMap$3 = {
9020
9323
  this._defaultContentTableValue = defaultValue;
9021
9324
  // Hardcoded defaults for layout table.
9022
9325
  switch(attributeName){
9326
+ case 'tableCellType':
9327
+ this._defaultLayoutTableValue = 'data';
9328
+ break;
9023
9329
  case 'tableCellBorderStyle':
9024
9330
  this._defaultLayoutTableValue = 'none';
9025
9331
  break;
@@ -9065,6 +9371,11 @@ const propertyToCommandMap$3 = {
9065
9371
  } else {
9066
9372
  tableCells.forEach((tableCell)=>writer.removeAttribute(this.attributeName, tableCell));
9067
9373
  }
9374
+ this.fire('afterExecute', {
9375
+ writer,
9376
+ tableCells,
9377
+ valueToSet
9378
+ });
9068
9379
  });
9069
9380
  }
9070
9381
  /**
@@ -9484,6 +9795,168 @@ const propertyToCommandMap$3 = {
9484
9795
  }
9485
9796
  }
9486
9797
 
9798
+ /**
9799
+ * The table cell type command.
9800
+ *
9801
+ * The command is registered by the {@link module:table/tablecellproperties/tablecellpropertiesediting~TableCellPropertiesEditing} as
9802
+ * the `'tableCellType'` editor command.
9803
+ *
9804
+ * To change the type of selected cells, execute the command:
9805
+ *
9806
+ * ```ts
9807
+ * editor.execute( 'tableCellType', {
9808
+ * value: 'header'
9809
+ * } );
9810
+ * ```
9811
+ *
9812
+ * The `value` can be either `'header'` or `'data'`.
9813
+ * It'll return `undefined` if multiple types are selected.
9814
+ */ class TableCellTypeCommand extends TableCellPropertyCommand {
9815
+ /**
9816
+ * Creates a new `TableCellTypeCommand` instance.
9817
+ *
9818
+ * @param editor An editor in which this command will be used.
9819
+ */ constructor(editor){
9820
+ super(editor, 'tableCellType', 'data');
9821
+ this.on('afterExecute', (_, data)=>{
9822
+ const { writer, tableCells } = data;
9823
+ const tableUtils = this.editor.plugins.get(TableUtils);
9824
+ const tablesMap = groupCellsByTable(tableCells);
9825
+ updateTablesHeadingAttributes(tableUtils, writer, tablesMap.keys());
9826
+ });
9827
+ }
9828
+ /**
9829
+ * @inheritDoc
9830
+ */ refresh() {
9831
+ super.refresh();
9832
+ const table = getSelectionAffectedTable(this.editor.model.document.selection);
9833
+ if (this.isEnabled && table && table.getAttribute('tableType') === 'layout') {
9834
+ this.isEnabled = false;
9835
+ }
9836
+ }
9837
+ /**
9838
+ * Returns the attribute value for a table cell.
9839
+ */ _getAttribute(tableCell) {
9840
+ return tableCell?.getAttribute(this.attributeName) || 'data';
9841
+ }
9842
+ }
9843
+ /**
9844
+ * Updates the `headingRows` and `headingColumns` attributes of the given tables
9845
+ * based on the `tableCellType` of their cells.
9846
+ */ function updateTablesHeadingAttributes(tableUtils, writer, tables) {
9847
+ let changed = false;
9848
+ for (const table of tables){
9849
+ let headingRows = table.getAttribute('headingRows') || 0;
9850
+ let headingColumns = table.getAttribute('headingColumns') || 0;
9851
+ // Prioritize the dimension that is already larger to prevent the other dimension from
9852
+ // aggressively consuming "orphaned" header cells. In other words, if table has three
9853
+ // heading columns (which fills entire table), we should not count all rows as heading rows.
9854
+ // User might later add column to the right which should not be heading.
9855
+ //
9856
+ // The other example, in a 2x2 table where all cells are headers (e.g. due to concurrent edits),
9857
+ // if headingColumns=0 and headingRows=0 (but all cells are headers):
9858
+ // - Processing rows first would expand headingRows to 2 (covering all cells), leaving headingColumns at 0.
9859
+ // - Processing columns first expands headingColumns to 2, leaving headingRows at 0.
9860
+ //
9861
+ // It should be good enough to resolve conflicts in most cases.
9862
+ const processColumnsFirst = headingColumns > headingRows;
9863
+ if (processColumnsFirst) {
9864
+ const newHeadingColumns = getAdjustedHeadingSectionSize(tableUtils, table, 'column', headingColumns, headingRows);
9865
+ if (newHeadingColumns !== headingColumns) {
9866
+ tableUtils.setHeadingColumnsCount(writer, table, newHeadingColumns, {
9867
+ shallow: true
9868
+ });
9869
+ headingColumns = newHeadingColumns;
9870
+ changed = true;
9871
+ }
9872
+ }
9873
+ const newHeadingRows = getAdjustedHeadingSectionSize(tableUtils, table, 'row', headingRows, headingColumns);
9874
+ if (newHeadingRows !== headingRows) {
9875
+ tableUtils.setHeadingRowsCount(writer, table, newHeadingRows, {
9876
+ shallow: true
9877
+ });
9878
+ headingRows = newHeadingRows;
9879
+ changed = true;
9880
+ }
9881
+ if (!processColumnsFirst) {
9882
+ const newHeadingColumns = getAdjustedHeadingSectionSize(tableUtils, table, 'column', headingColumns, headingRows);
9883
+ if (newHeadingColumns !== headingColumns) {
9884
+ tableUtils.setHeadingColumnsCount(writer, table, newHeadingColumns, {
9885
+ shallow: true
9886
+ });
9887
+ changed = true;
9888
+ }
9889
+ }
9890
+ }
9891
+ return changed;
9892
+ }
9893
+ /**
9894
+ * Calculates the adjusted size of a heading section (rows or columns).
9895
+ *
9896
+ * The algorithm iterates through rows (or columns) to determine if they should be part of the heading section.
9897
+ * A row/column is included if:
9898
+ * 1. All its cells are of type 'header'.
9899
+ * 2. AND it contains at least one header cell that is NOT already covered by the perpendicular heading section.
9900
+ *
9901
+ * This check prevents the algorithm from aggressively expanding the heading section when cells are already
9902
+ * headers due to the other dimension.
9903
+ *
9904
+ * Consider a 2x2 table where all cells are headers:
9905
+ *
9906
+ * ```
9907
+ * C0 C1
9908
+ * +---+---+
9909
+ * R0| H | H |
9910
+ * +---+---+
9911
+ * R1| H | H |
9912
+ * +---+---+
9913
+ * ```
9914
+ *
9915
+ * If `headingColumns=2`, both C0 and C1 are heading columns.
9916
+ * If we want `headingRows=1` (only R0), the algorithm must NOT include R1, even though R1 consists of header cells.
9917
+ * R1's cells are headers because of C0 and C1.
9918
+ *
9919
+ * Without this check, the algorithm would see that R1 is all headers and force `headingRows` to 2.
9920
+ * This would prevent the user from reducing `headingRows` from 2 to 1 without converting R1 cells to 'data'
9921
+ * (which would incorrectly break C0 and C1).
9922
+ */ function getAdjustedHeadingSectionSize(tableUtils, table, mode, currentSize, perpendicularHeadingSize) {
9923
+ const totalRowsOrColumns = mode === 'row' ? tableUtils.getRows(table) : tableUtils.getColumns(table);
9924
+ let size = currentSize;
9925
+ // Iterate through each row/column to check if all cells are headers.
9926
+ for(let currentIndex = 0; currentIndex < totalRowsOrColumns; currentIndex++){
9927
+ const walker = new TableWalker(table, {
9928
+ [mode]: currentIndex
9929
+ });
9930
+ let allCellsAreHeaders = true;
9931
+ let hasHeaderOutsidePerpendicularSection = false;
9932
+ // Check each cell in the current row/column.
9933
+ for (const { cell, row, column } of walker){
9934
+ // If we find a non-header cell, this row/column can't be part of the heading section.
9935
+ if (cell.getAttribute('tableCellType') !== 'header') {
9936
+ allCellsAreHeaders = false;
9937
+ break;
9938
+ }
9939
+ // Check if this header cell extends beyond the perpendicular heading section.
9940
+ // E.g., when checking rows, see if the cell extends beyond headingColumns.
9941
+ const perpendicularIndex = mode === 'row' ? column : row;
9942
+ if (perpendicularIndex >= perpendicularHeadingSize) {
9943
+ hasHeaderOutsidePerpendicularSection = true;
9944
+ }
9945
+ }
9946
+ // If not all cells are headers, we can't extend the heading section any further.
9947
+ if (!allCellsAreHeaders) {
9948
+ // The section cannot extend beyond the last valid header row/column.
9949
+ return Math.min(size, currentIndex);
9950
+ }
9951
+ // If there's a header extending beyond the perpendicular section,
9952
+ // we must include this row/column in the heading section.
9953
+ if (hasHeaderOutsidePerpendicularSection) {
9954
+ size = Math.max(size, currentIndex + 1);
9955
+ }
9956
+ }
9957
+ return Math.min(size, totalRowsOrColumns);
9958
+ }
9959
+
9487
9960
  const VALIGN_VALUES_REG_EXP = /^(top|middle|bottom)$/;
9488
9961
  const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
9489
9962
  /**
@@ -9585,6 +10058,10 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
9585
10058
  editor.commands.add('tableCellHorizontalAlignment', new TableCellHorizontalAlignmentCommand(editor, defaultTableCellProperties.horizontalAlignment));
9586
10059
  enableVerticalAlignmentProperty(schema, conversion, defaultTableCellProperties.verticalAlignment);
9587
10060
  editor.commands.add('tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand(editor, defaultTableCellProperties.verticalAlignment));
10061
+ if (editor.config.get('experimentalFlags.tableCellTypeSupport')) {
10062
+ enableCellTypeProperty(editor);
10063
+ editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
10064
+ }
9588
10065
  }
9589
10066
  }
9590
10067
  /**
@@ -9771,6 +10248,119 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
9771
10248
  }
9772
10249
  });
9773
10250
  }
10251
+ /**
10252
+ * Enables the `tableCellType` attribute for table cells.
10253
+ */ function enableCellTypeProperty(editor) {
10254
+ const { model, conversion, editing } = editor;
10255
+ const { schema } = model;
10256
+ const tableUtils = editor.plugins.get(TableUtils);
10257
+ schema.extend('tableCell', {
10258
+ allowAttributes: [
10259
+ 'tableCellType'
10260
+ ]
10261
+ });
10262
+ schema.setAttributeProperties('tableCellType', {
10263
+ isFormatting: true
10264
+ });
10265
+ // Do not allow setting `tableCellType` in layout tables.
10266
+ schema.addAttributeCheck((context)=>{
10267
+ const nearestTable = Array.from(context).reverse().find((item)=>item.name === 'table');
10268
+ if (nearestTable?.getAttribute('tableType') === 'layout') {
10269
+ return false;
10270
+ }
10271
+ }, 'tableCellType');
10272
+ // Upcast conversion for td/th elements.
10273
+ conversion.for('upcast').add((dispatcher)=>{
10274
+ dispatcher.on('element:th', (evt, data, conversionApi)=>{
10275
+ const { writer } = conversionApi;
10276
+ const { modelRange } = data;
10277
+ const modelElement = modelRange?.start.nodeAfter;
10278
+ if (modelElement?.is('element', 'tableCell')) {
10279
+ writer.setAttribute('tableCellType', 'header', modelElement);
10280
+ }
10281
+ });
10282
+ // Table type is examined after all other cell converters, on low priority, so
10283
+ // we double check if there is any `th` left in the table. If so, the table is converted to a content table.
10284
+ dispatcher.on('element:table', (evt, data, conversionApi)=>{
10285
+ const { writer } = conversionApi;
10286
+ const { modelRange } = data;
10287
+ const modelElement = modelRange?.start.nodeAfter;
10288
+ if (modelElement?.is('element', 'table') && modelElement.getAttribute('tableType') === 'layout') {
10289
+ for (const { cell } of new TableWalker(modelElement)){
10290
+ if (cell.getAttribute('tableCellType') === 'header') {
10291
+ writer.setAttribute('tableType', 'content', modelElement);
10292
+ break;
10293
+ }
10294
+ }
10295
+ }
10296
+ }, {
10297
+ priority: priorities.low - 1
10298
+ });
10299
+ });
10300
+ // Registers a post-fixer that ensures the `headingRows` and `headingColumns` attributes
10301
+ // are consistent with the `tableCellType` attribute of the cells. `tableCellType` has priority
10302
+ // over `headingRows` and `headingColumns` and we use it to adjust the heading sections of the table.
10303
+ model.document.registerPostFixer((writer)=>{
10304
+ // 1. Collect all tables that need to be checked.
10305
+ const changes = model.document.differ.getChanges();
10306
+ const tablesToCheck = new Set();
10307
+ for (const change of changes){
10308
+ // Check if headingRows or headingColumns changed.
10309
+ if (change.type === 'attribute' && (change.attributeKey === 'headingRows' || change.attributeKey === 'headingColumns')) {
10310
+ const table = change.range.start.nodeAfter;
10311
+ if (table?.is('element', 'table') && table.root.rootName !== '$graveyard') {
10312
+ tablesToCheck.add(table);
10313
+ }
10314
+ }
10315
+ // Check if tableCellType changed.
10316
+ if (change.type === 'attribute' && change.attributeKey === 'tableCellType') {
10317
+ const cell = change.range.start.nodeAfter;
10318
+ if (cell?.is('element', 'tableCell') && cell.root.rootName !== '$graveyard') {
10319
+ const table = cell.findAncestor('table');
10320
+ if (table) {
10321
+ tablesToCheck.add(table);
10322
+ }
10323
+ }
10324
+ }
10325
+ // Check if new headers were inserted.
10326
+ if (change.type === 'insert' && change.position.nodeAfter) {
10327
+ for (const { item } of model.createRangeOn(change.position.nodeAfter)){
10328
+ if (item.is('element', 'tableCell') && item.getAttribute('tableCellType') && item.root.rootName !== '$graveyard') {
10329
+ const table = item.findAncestor('table');
10330
+ if (table) {
10331
+ tablesToCheck.add(table);
10332
+ }
10333
+ }
10334
+ }
10335
+ }
10336
+ }
10337
+ // 2. Update the attributes of the collected tables.
10338
+ return updateTablesHeadingAttributes(tableUtils, writer, tablesToCheck);
10339
+ });
10340
+ // Refresh the table cells in the editing view when their `tableCellType` attribute changes.
10341
+ model.document.on('change:data', ()=>{
10342
+ const { differ } = model.document;
10343
+ const cellsToReconvert = new Set();
10344
+ for (const change of differ.getChanges()){
10345
+ // If the `tableCellType` attribute changed, the entire cell needs to be re-rendered.
10346
+ if (change.type === 'attribute' && change.attributeKey === 'tableCellType') {
10347
+ const tableCell = change.range.start.nodeAfter;
10348
+ if (tableCell.is('element', 'tableCell')) {
10349
+ cellsToReconvert.add(tableCell);
10350
+ }
10351
+ }
10352
+ }
10353
+ // Reconvert table cells that had their `tableCellType` attribute changed.
10354
+ for (const tableCell of cellsToReconvert){
10355
+ const viewElement = editing.mapper.toViewElement(tableCell);
10356
+ const cellType = tableCell.getAttribute('tableCellType');
10357
+ const expectedElementName = cellType === 'header' ? 'th' : 'td';
10358
+ if (viewElement?.name !== expectedElementName) {
10359
+ editing.reconvertItem(tableCell);
10360
+ }
10361
+ }
10362
+ });
10363
+ }
9774
10364
 
9775
10365
  /**
9776
10366
  * The table cell properties feature. Enables support for setting properties of table cells (size, border, background, etc.).
@@ -9893,17 +10483,22 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
9893
10483
  /**
9894
10484
  * @inheritDoc
9895
10485
  */ afterInit() {
9896
- const editor = this.editor;
9897
- if (!editor.plugins.has('TablePropertiesUI')) {
10486
+ const { editor } = this;
10487
+ const { ui, plugins } = editor;
10488
+ let tablePropertiesUI;
10489
+ if (plugins.has('TablePropertiesUIExperimental')) {
10490
+ tablePropertiesUI = plugins.get('TablePropertiesUIExperimental');
10491
+ } else if (plugins.has('TablePropertiesUI')) {
10492
+ tablePropertiesUI = plugins.get('TablePropertiesUI');
10493
+ } else {
9898
10494
  return;
9899
10495
  }
9900
- const tablePropertiesUI = editor.plugins.get('TablePropertiesUI');
9901
10496
  // Override the default table properties button to include the table type dropdown.
9902
10497
  // It needs to be done in `afterInit()` to make sure that `tableProperties` button is
9903
10498
  // registered after the initialization of the `TablePropertiesUI`. Otherwise, the
9904
10499
  // button will be overridden by the default one if the `TablePropertiesUI` is
9905
10500
  // initialized after the `TableLayoutUI`.
9906
- editor.ui.componentFactory.add('tableProperties', (locale)=>{
10501
+ ui.componentFactory.add('tableProperties', (locale)=>{
9907
10502
  const baseButton = tablePropertiesUI._createTablePropertiesButton();
9908
10503
  const splitButtonView = new SplitButtonView(locale, baseButton);
9909
10504
  return createTableTypeDropdown(editor, splitButtonView);
@@ -13031,7 +13626,7 @@ const propertyToCommandMap$2 = {
13031
13626
  }
13032
13627
 
13033
13628
  /**
13034
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
13629
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
13035
13630
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
13036
13631
  */ /**
13037
13632
  * @module table/converters/table-caption-post-fixer
@@ -14469,6 +15064,9 @@ const propertyToCommandMap$1 = {
14469
15064
  /**
14470
15065
  * An input that allows specifying the table cell background color.
14471
15066
  */ backgroundInput;
15067
+ /**
15068
+ * A dropdown that allows selecting the type of the table cell (data or header).
15069
+ */ cellTypeDropdown;
14472
15070
  /**
14473
15071
  * An input that allows specifying the table cell padding.
14474
15072
  */ paddingInput;
@@ -14507,6 +15105,7 @@ const propertyToCommandMap$1 = {
14507
15105
  * @param options.backgroundColors A configuration of the background color palette used by the
14508
15106
  * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#backgroundInput}.
14509
15107
  * @param options.defaultTableCellProperties The default table cell properties.
15108
+ * @param options.isTableCellTypeSupported A flag indicating whether the table cell type is supported.
14510
15109
  */ constructor(locale, options){
14511
15110
  super(locale);
14512
15111
  this.set({
@@ -14518,11 +15117,13 @@ const propertyToCommandMap$1 = {
14518
15117
  width: '',
14519
15118
  height: '',
14520
15119
  horizontalAlignment: '',
14521
- verticalAlignment: ''
15120
+ verticalAlignment: '',
15121
+ cellType: ''
14522
15122
  });
14523
15123
  this.options = options;
14524
15124
  const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
14525
15125
  const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
15126
+ const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
14526
15127
  const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
14527
15128
  const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
14528
15129
  this.focusTracker = new FocusTracker();
@@ -14532,6 +15133,7 @@ const propertyToCommandMap$1 = {
14532
15133
  this.borderWidthInput = borderWidthInput;
14533
15134
  this.borderColorInput = borderColorInput;
14534
15135
  this.backgroundInput = backgroundInput;
15136
+ this.cellTypeDropdown = cellTypeDropdown;
14535
15137
  this.paddingInput = this._createPaddingField();
14536
15138
  this.widthInput = widthInput;
14537
15139
  this.heightInput = heightInput;
@@ -14565,22 +15167,48 @@ const propertyToCommandMap$1 = {
14565
15167
  // Border row.
14566
15168
  this.children.add(new FormRowView(locale, {
14567
15169
  labelView: borderRowLabel,
14568
- children: [
15170
+ children: this.options.isTableCellTypeSupported ? [
15171
+ borderRowLabel,
15172
+ borderStyleDropdown,
15173
+ borderWidthInput,
15174
+ borderColorInput
15175
+ ] : [
14569
15176
  borderRowLabel,
14570
15177
  borderStyleDropdown,
14571
15178
  borderColorInput,
14572
15179
  borderWidthInput
14573
15180
  ],
14574
- class: 'ck-table-form__border-row'
15181
+ class: `ck-table-form__border-row${this.options.isTableCellTypeSupported ? ' ck-table-form__border-row_experimental' : ''}`
14575
15182
  }));
14576
- // Background.
15183
+ // Background and cell type.
14577
15184
  this.children.add(new FormRowView(locale, {
14578
- labelView: backgroundRowLabel,
14579
- children: [
14580
- backgroundRowLabel,
14581
- backgroundInput
14582
- ],
14583
- class: 'ck-table-form__background-row'
15185
+ children: this.options.isTableCellTypeSupported ? [
15186
+ new FormRowView(locale, {
15187
+ labelView: cellTypeRowLabel,
15188
+ children: [
15189
+ cellTypeRowLabel,
15190
+ cellTypeDropdown
15191
+ ],
15192
+ class: 'ck-table-form__cell-type-row'
15193
+ }),
15194
+ new FormRowView(locale, {
15195
+ labelView: backgroundRowLabel,
15196
+ children: [
15197
+ backgroundRowLabel,
15198
+ backgroundInput
15199
+ ],
15200
+ class: 'ck-table-form__background-row'
15201
+ })
15202
+ ] : [
15203
+ new FormRowView(locale, {
15204
+ labelView: backgroundRowLabel,
15205
+ children: [
15206
+ backgroundRowLabel,
15207
+ backgroundInput
15208
+ ],
15209
+ class: 'ck-table-form__background-row'
15210
+ })
15211
+ ]
14584
15212
  }));
14585
15213
  // Dimensions row and padding.
14586
15214
  this.children.add(new FormRowView(locale, {
@@ -14630,7 +15258,9 @@ const propertyToCommandMap$1 = {
14630
15258
  'ck',
14631
15259
  'ck-form',
14632
15260
  'ck-table-form',
14633
- 'ck-table-cell-properties-form'
15261
+ 'ck-table-cell-properties-form',
15262
+ 'ck-table-cell-properties-form_experimental',
15263
+ this.options.isTableCellTypeSupported ? 'ck-table-cell-properties-form_experimental-no-cell-type' : ''
14634
15264
  ],
14635
15265
  // https://github.com/ckeditor/ckeditor5-link/issues/90
14636
15266
  tabindex: '-1'
@@ -14658,6 +15288,7 @@ const propertyToCommandMap$1 = {
14658
15288
  this.borderStyleDropdown,
14659
15289
  this.borderColorInput,
14660
15290
  this.borderWidthInput,
15291
+ this.cellTypeDropdown,
14661
15292
  this.backgroundInput,
14662
15293
  this.widthInput,
14663
15294
  this.heightInput,
@@ -14812,6 +15443,46 @@ const propertyToCommandMap$1 = {
14812
15443
  backgroundInput
14813
15444
  };
14814
15445
  }
15446
+ /**
15447
+ * Create cell type field.
15448
+ *
15449
+ * * {@link #cellTypeDropdown}.
15450
+ *
15451
+ * @internal
15452
+ */ _createCellTypeField() {
15453
+ const locale = this.locale;
15454
+ const t = this.t;
15455
+ const cellTypeRowLabel = new LabelView(locale);
15456
+ cellTypeRowLabel.text = t('Cell type');
15457
+ const cellTypeLabels = this._cellTypeLabels;
15458
+ const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
15459
+ cellTypeDropdown.set({
15460
+ label: t('Cell type'),
15461
+ class: 'ck-table-cell-properties-form__cell-type'
15462
+ });
15463
+ cellTypeDropdown.fieldView.buttonView.set({
15464
+ ariaLabel: t('Cell type'),
15465
+ ariaLabelledBy: undefined,
15466
+ isOn: false,
15467
+ withText: true,
15468
+ tooltip: t('Cell type')
15469
+ });
15470
+ cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
15471
+ return cellTypeLabels[value || 'data'];
15472
+ });
15473
+ cellTypeDropdown.fieldView.on('execute', (evt)=>{
15474
+ this.cellType = evt.source._cellTypeValue;
15475
+ });
15476
+ cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
15477
+ addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
15478
+ role: 'menu',
15479
+ ariaLabel: t('Cell type')
15480
+ });
15481
+ return {
15482
+ cellTypeRowLabel,
15483
+ cellTypeDropdown
15484
+ };
15485
+ }
14815
15486
  /**
14816
15487
  * Creates the following form fields:
14817
15488
  *
@@ -14908,7 +15579,8 @@ const propertyToCommandMap$1 = {
14908
15579
  horizontalAlignmentToolbar.set({
14909
15580
  isCompact: true,
14910
15581
  role: 'radiogroup',
14911
- ariaLabel: t('Horizontal text alignment toolbar')
15582
+ ariaLabel: t('Horizontal text alignment toolbar'),
15583
+ class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
14912
15584
  });
14913
15585
  fillToolbar({
14914
15586
  view: this,
@@ -14934,7 +15606,8 @@ const propertyToCommandMap$1 = {
14934
15606
  verticalAlignmentToolbar.set({
14935
15607
  isCompact: true,
14936
15608
  role: 'radiogroup',
14937
- ariaLabel: t('Vertical text alignment toolbar')
15609
+ ariaLabel: t('Vertical text alignment toolbar'),
15610
+ class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
14938
15611
  });
14939
15612
  fillToolbar({
14940
15613
  view: this,
@@ -14999,6 +15672,29 @@ const propertyToCommandMap$1 = {
14999
15672
  backButton.delegate('execute').to(this, 'cancel');
15000
15673
  return backButton;
15001
15674
  }
15675
+ /**
15676
+ * Creates the cell type dropdown definitions.
15677
+ */ _getCellTypeDefinitions() {
15678
+ const itemDefinitions = new Collection();
15679
+ const cellTypeLabels = this._cellTypeLabels;
15680
+ for (const type of [
15681
+ 'data',
15682
+ 'header'
15683
+ ]){
15684
+ const definition = {
15685
+ type: 'button',
15686
+ model: new UIModel({
15687
+ _cellTypeValue: type,
15688
+ label: cellTypeLabels[type],
15689
+ role: 'menuitemradio',
15690
+ withText: true
15691
+ })
15692
+ };
15693
+ definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
15694
+ itemDefinitions.add(definition);
15695
+ }
15696
+ return itemDefinitions;
15697
+ }
15002
15698
  /**
15003
15699
  * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
15004
15700
  */ get _horizontalAlignmentLabels() {
@@ -15035,6 +15731,15 @@ const propertyToCommandMap$1 = {
15035
15731
  bottom: t('Align cell text to the bottom')
15036
15732
  };
15037
15733
  }
15734
+ /**
15735
+ * Provides localized labels for {@link #cellTypeDropdown}.
15736
+ */ get _cellTypeLabels() {
15737
+ const t = this.t;
15738
+ return {
15739
+ data: t('Data cell'),
15740
+ header: t('Header cell')
15741
+ };
15742
+ }
15038
15743
  }
15039
15744
  function isBorderStyleSet(value) {
15040
15745
  return value !== 'none';
@@ -15051,7 +15756,8 @@ const propertyToCommandMap = {
15051
15756
  padding: 'tableCellPadding',
15052
15757
  backgroundColor: 'tableCellBackgroundColor',
15053
15758
  horizontalAlignment: 'tableCellHorizontalAlignment',
15054
- verticalAlignment: 'tableCellVerticalAlignment'
15759
+ verticalAlignment: 'tableCellVerticalAlignment',
15760
+ cellType: 'tableCellType'
15055
15761
  };
15056
15762
  /**
15057
15763
  * The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
@@ -15138,7 +15844,7 @@ const propertyToCommandMap = {
15138
15844
  tooltip: true
15139
15845
  });
15140
15846
  this.listenTo(view, 'execute', ()=>this._showView());
15141
- const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName));
15847
+ const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
15142
15848
  view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
15143
15849
  return view;
15144
15850
  });
@@ -15165,11 +15871,13 @@ const propertyToCommandMap = {
15165
15871
  const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
15166
15872
  const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
15167
15873
  const hasColorPicker = config.colorPicker !== false;
15874
+ const isTableCellTypeSupported = !!editor.config.get('experimentalFlags.tableCellTypeSupport');
15168
15875
  const view = new TableCellPropertiesViewExperimental(editor.locale, {
15169
15876
  borderColors: localizedBorderColors,
15170
15877
  backgroundColors: localizedBackgroundColors,
15171
15878
  defaultTableCellProperties,
15172
- colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
15879
+ colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false,
15880
+ isTableCellTypeSupported
15173
15881
  });
15174
15882
  const t = editor.t;
15175
15883
  // Render the view so its #element is available for the clickOutsideHandler.
@@ -15244,6 +15952,11 @@ const propertyToCommandMap = {
15244
15952
  }));
15245
15953
  view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
15246
15954
  view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
15955
+ const cellTypeCommand = editor.commands.get('tableCellType');
15956
+ if (cellTypeCommand) {
15957
+ view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
15958
+ view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
15959
+ }
15247
15960
  return view;
15248
15961
  }
15249
15962
  /**
@@ -15256,12 +15969,24 @@ const propertyToCommandMap = {
15256
15969
  */ _fillViewFormFromCommandValues() {
15257
15970
  const commands = this.editor.commands;
15258
15971
  const borderStyleCommand = commands.get('tableCellBorderStyle');
15259
- Object.entries(propertyToCommandMap).map(([property, commandName])=>{
15972
+ Object.entries(propertyToCommandMap).flatMap(([property, commandName])=>{
15973
+ const command = commands.get(commandName);
15974
+ if (!command) {
15975
+ return [];
15976
+ }
15260
15977
  const propertyKey = property;
15261
- const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
15262
- return [
15978
+ let defaultValue;
15979
+ if (propertyKey === 'cellType') {
15980
+ defaultValue = '';
15981
+ } else {
15982
+ defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
15983
+ }
15984
+ const entry = [
15263
15985
  property,
15264
- commands.get(commandName).value || defaultValue
15986
+ command.value || defaultValue
15987
+ ];
15988
+ return [
15989
+ entry
15265
15990
  ];
15266
15991
  }).forEach(([property, value])=>{
15267
15992
  // Do not set the `border-color` and `border-width` fields if `border-style:none`.
@@ -15382,5 +16107,5 @@ const propertyToCommandMap = {
15382
16107
  }
15383
16108
  }
15384
16109
 
15385
- 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, 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 };
16110
+ export { InsertColumnCommand, InsertRowCommand, InsertTableCommand, InsertTableLayoutCommand, MergeCellCommand, MergeCellsCommand, PlainTableOutput, RemoveColumnCommand, RemoveRowCommand, SelectColumnCommand, SelectRowCommand, SetHeaderColumnCommand, SetHeaderRowCommand, SplitCellCommand, Table, TableAlignmentCommand, TableBackgroundColorCommand, TableBorderColorCommand, TableBorderStyleCommand, TableBorderWidthCommand, TableCaption, TableCaptionEditing, TableCaptionUI, TableCellBackgroundColorCommand, TableCellBorderColorCommand, TableCellBorderStyleCommand, TableCellBorderWidthCommand, TableCellHeightCommand, TableCellHorizontalAlignmentCommand, TableCellPaddingCommand, TableCellProperties, TableCellPropertiesEditing, TableCellPropertiesUI, TableCellPropertiesUIExperimental, TableCellPropertiesView, TableCellPropertiesViewExperimental, TableCellPropertyCommand, TableCellTypeCommand, TableCellVerticalAlignmentCommand, TableCellWidthCommand, TableCellWidthEditing, TableClipboard, TableColumnResize, TableColumnResizeEditing, TableEditing, TableHeightCommand, TableKeyboard, TableLayout, TableLayoutEditing, TableLayoutUI, TableMouse, TableProperties, TablePropertiesEditing, TablePropertiesUI, TablePropertiesUIExperimental, TablePropertiesView, TablePropertiesViewExperimental, TablePropertyCommand, TableSelection, TableToolbar, TableTypeCommand, TableUI, TableUtils, TableWalker, TableWidthCommand, TableWidthsCommand, ToggleTableCaptionCommand, InsertTableView as _InsertTableView, COLUMN_MIN_WIDTH_AS_PERCENTAGE as _TABLE_COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS as _TABLE_COLUMN_MIN_WIDTH_IN_PIXELS, COLUMN_RESIZE_DISTANCE_THRESHOLD as _TABLE_COLUMN_RESIZE_DISTANCE_THRESHOLD, COLUMN_WIDTH_PRECISION as _TABLE_COLUMN_WIDTH_PRECISION, defaultColors as _TABLE_DEFAULT_COLORS, ColorInputView as _TableColorInputView, MouseEventsObserver as _TableMouseEventsObserver, addDefaultUnitToNumericValue as _addDefaultUnitToNumericValue, adjustLastColumnIndex as _adjustLastTableColumnIndex, adjustLastRowIndex as _adjustLastTableRowIndex, clamp as _clamp, colorFieldValidator as _colorTableFieldValidator, convertParagraphInTableCell as _convertParagraphInTableCell, createEmptyTableCell as _createEmptyTableCell, createFilledArray as _createFilledArray, cropTableToDimensions as _cropTableToDimensions, downcastTable as _downcastTable, downcastTableAttribute as _downcastTableAttribute, downcastAttributeToStyle as _downcastTableAttributeToStyle, downcastCell as _downcastTableCell, downcastTableResizedClass as _downcastTableResizedClass, downcastRow as _downcastTableRow, enableProperty$1 as _enableTableCellProperty, ensureParagraphInTableCell as _ensureParagraphInTableCell, fillToolbar$1 as _fillTableOrCellToolbar, getBalloonCellPositionData as _getBalloonTableCellPositionData, getBalloonTablePositionData as _getBalloonTablePositionData, getBorderStyleLabels$1 as _getBorderTableStyleLabels, getChangedResizedTables as _getChangedResizedTables, getDefaultValueAdjusted as _getDefaultTableValueAdjusted, getDomCellOuterWidth as _getDomTableCellOuterWidth, getElementWidthInPixels as _getElementWidthInPixels, getHorizontallyOverlappingCells as _getHorizontallyOverlappingTableCells, getLabeledColorInputCreator$1 as _getLabeledTableColorInputCreator, getLocalizedColorErrorText as _getLocalizedTableColorErrorText, getLocalizedLengthErrorText as _getLocalizedTableLengthErrorText, getNormalizedDefaultProperties as _getNormalizedDefaultTableBaseProperties, getNormalizedDefaultCellProperties as _getNormalizedDefaultTableCellProperties, getNormalizedDefaultTableProperties as _getNormalizedDefaultTableProperties, getSelectedTableWidget as _getSelectedTableWidget, getSelectionAffectedTable as _getSelectionAffectedTable, getSelectionAffectedTableWidget as _getSelectionAffectedTableWidget, getSingleValue as _getTableBorderBoxSingleValue, getCaptionFromTableModelElement as _getTableCaptionFromModelElement, getCaptionFromModelSelection as _getTableCaptionFromModelSelection, getColumnEdgesIndexes as _getTableColumnEdgesIndexes, getTableColumnElements as _getTableColumnElements, getColumnGroupElement as _getTableColumnGroupElement, getColumnMinWidthAsPercentage as _getTableColumnMinWidthAsPercentage, getTableColumnsWidths as _getTableColumnsWidths, getBorderStyleDefinitions$1 as _getTableOrCellBorderStyleDefinitions, getTableWidgetAncestor as _getTableWidgetAncestor, getTableWidthInPixels as _getTableWidthInPixels, getVerticallyOverlappingCells as _getVerticallyOverlappingTableCells, injectTableCaptionPostFixer as _injectTableCaptionPostFixer, injectTableCellParagraphPostFixer as _injectTableCellParagraphPostFixer, injectTableLayoutPostFixer as _injectTableLayoutPostFixer, isSingleParagraphWithoutAttributes as _isSingleTableParagraphWithoutAttributes, isHeadingColumnCell as _isTableHeadingColumnCell, isTable as _isTableModelElement, lengthFieldValidator as _lengthTableFieldValidator, lineWidthFieldValidator as _lineWidthTableFieldValidator, matchTableCaptionViewElement as _matchTableCaptionViewElement, normalizeColumnWidths as _normalizeTableColumnWidths, removeEmptyColumns as _removeEmptyTableColumns, removeEmptyRows as _removeEmptyTableRows, removeEmptyRowsColumns as _removeEmptyTableRowsColumns, repositionContextualBalloon as _repositionTableContextualBalloon, skipEmptyTableRow as _skipEmptyTableRow, splitHorizontally as _splitTableCellHorizontally, splitVertically as _splitTableCellVertically, sumArray as _sumArray, tableCellRefreshHandler as _tableCellRefreshHandler, tableHeadingsRefreshHandler as _tableHeadingsRefreshHandler, toPrecision as _toPrecision, translateColSpanAttribute as _translateTableColspanAttribute, trimTableCellIfNeeded as _trimTableCellIfNeeded, upcastStyleToAttribute as _upcastNormalizedTableStyleToAttribute, upcastTable as _upcastTable, upcastBorderStyles as _upcastTableBorderStyles, upcastColgroupElement as _upcastTableColgroupElement, upcastTableFigure as _upcastTableFigure, updateColumnElements as _updateTableColumnElements, updateNumericAttribute as _updateTableNumericAttribute };
15386
16111
  //# sourceMappingURL=index.js.map