@wordpress/block-editor 12.13.0 → 12.15.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 (528) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/build/components/block-heading-level-dropdown/index.js +1 -1
  4. package/build/components/block-heading-level-dropdown/index.js.map +1 -1
  5. package/build/components/block-list/block.native.js +2 -0
  6. package/build/components/block-list/block.native.js.map +1 -1
  7. package/build/components/block-list/index.js +2 -9
  8. package/build/components/block-list/index.js.map +1 -1
  9. package/build/components/block-list-appender/index.js +16 -3
  10. package/build/components/block-list-appender/index.js.map +1 -1
  11. package/build/components/block-parent-selector/index.js +1 -1
  12. package/build/components/block-parent-selector/index.js.map +1 -1
  13. package/build/components/block-pattern-setup/index.js +25 -16
  14. package/build/components/block-pattern-setup/index.js.map +1 -1
  15. package/build/components/block-pattern-setup/setup-toolbar.js +4 -2
  16. package/build/components/block-pattern-setup/setup-toolbar.js.map +1 -1
  17. package/build/components/block-patterns-list/index.js +36 -19
  18. package/build/components/block-patterns-list/index.js.map +1 -1
  19. package/build/components/block-quick-navigation/index.js +6 -4
  20. package/build/components/block-quick-navigation/index.js.map +1 -1
  21. package/build/components/block-rename/index.js +28 -0
  22. package/build/components/block-rename/index.js.map +1 -0
  23. package/build/components/block-rename/is-empty-string.js +10 -0
  24. package/build/components/block-rename/is-empty-string.js.map +1 -0
  25. package/build/components/block-rename/modal.js +87 -0
  26. package/build/components/block-rename/modal.js.map +1 -0
  27. package/build/components/block-rename/rename-control.js +74 -0
  28. package/build/components/block-rename/rename-control.js.map +1 -0
  29. package/build/components/block-rename/use-block-rename.js +17 -0
  30. package/build/components/block-rename/use-block-rename.js.map +1 -0
  31. package/build/components/block-settings-menu/block-settings-dropdown.js +33 -20
  32. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  33. package/build/components/block-settings-menu-controls/index.js +7 -0
  34. package/build/components/block-settings-menu-controls/index.js.map +1 -1
  35. package/build/components/block-styles/index.js +0 -8
  36. package/build/components/block-styles/index.js.map +1 -1
  37. package/build/components/block-switcher/pattern-transformations-menu.js +18 -14
  38. package/build/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  39. package/build/components/block-toolbar/block-toolbar-menu.native.js +1 -1
  40. package/build/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  41. package/build/components/block-tools/back-compat.js +2 -2
  42. package/build/components/block-tools/back-compat.js.map +1 -1
  43. package/build/components/block-tools/block-contextual-toolbar.js +11 -81
  44. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  45. package/build/components/block-tools/empty-block-inserter.js +56 -0
  46. package/build/components/block-tools/empty-block-inserter.js.map +1 -0
  47. package/build/components/block-tools/index.js +48 -9
  48. package/build/components/block-tools/index.js.map +1 -1
  49. package/build/components/block-tools/selected-block-tools.js +113 -0
  50. package/build/components/block-tools/selected-block-tools.js.map +1 -0
  51. package/build/components/block-tools/use-selected-block-tool-props.js +56 -0
  52. package/build/components/block-tools/use-selected-block-tool-props.js.map +1 -0
  53. package/build/components/block-types-list/index.js +6 -2
  54. package/build/components/block-types-list/index.js.map +1 -1
  55. package/build/components/date-format-picker/index.js +8 -1
  56. package/build/components/date-format-picker/index.js.map +1 -1
  57. package/build/components/editable-text/index.js +1 -2
  58. package/build/components/editable-text/index.js.map +1 -1
  59. package/build/components/global-styles/advanced-panel.js +1 -1
  60. package/build/components/global-styles/advanced-panel.js.map +1 -1
  61. package/build/components/iframe/index.js +4 -3
  62. package/build/components/iframe/index.js.map +1 -1
  63. package/build/components/image-size-control/index.js +0 -5
  64. package/build/components/image-size-control/index.js.map +1 -1
  65. package/build/components/inner-blocks/index.js +3 -1
  66. package/build/components/inner-blocks/index.js.map +1 -1
  67. package/build/components/inner-blocks/warning-max-depth-exceeded.native.js +29 -31
  68. package/build/components/inner-blocks/warning-max-depth-exceeded.native.js.map +1 -1
  69. package/build/components/inserter/block-patterns-explorer/{explorer.js → index.js} +7 -7
  70. package/build/components/inserter/block-patterns-explorer/index.js.map +1 -0
  71. package/build/components/inserter/block-patterns-explorer/{sidebar.js → pattern-explorer-sidebar.js} +1 -1
  72. package/build/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js.map +1 -0
  73. package/build/components/inserter/block-patterns-explorer/{patterns-list.js → pattern-list.js} +4 -4
  74. package/build/components/inserter/block-patterns-explorer/pattern-list.js.map +1 -0
  75. package/build/components/inserter/block-patterns-tab/index.js +75 -0
  76. package/build/components/inserter/block-patterns-tab/index.js.map +1 -0
  77. package/build/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +48 -0
  78. package/build/components/inserter/block-patterns-tab/pattern-category-preview-panel.js.map +1 -0
  79. package/build/components/inserter/block-patterns-tab/pattern-category-previews.js +108 -0
  80. package/build/components/inserter/block-patterns-tab/pattern-category-previews.js.map +1 -0
  81. package/build/components/inserter/{block-patterns-filter.js → block-patterns-tab/patterns-filter.js} +18 -34
  82. package/build/components/inserter/block-patterns-tab/patterns-filter.js.map +1 -0
  83. package/build/components/inserter/block-patterns-tab/use-pattern-categories.js +55 -0
  84. package/build/components/inserter/block-patterns-tab/use-pattern-categories.js.map +1 -0
  85. package/build/components/inserter/block-patterns-tab/utils.js +69 -0
  86. package/build/components/inserter/block-patterns-tab/utils.js.map +1 -0
  87. package/build/components/inserter/hooks/use-patterns-state.js +2 -1
  88. package/build/components/inserter/hooks/use-patterns-state.js.map +1 -1
  89. package/build/components/inserter/media-tab/media-list.js +9 -5
  90. package/build/components/inserter/media-tab/media-list.js.map +1 -1
  91. package/build/components/inserter/media-tab/media-preview.js +15 -12
  92. package/build/components/inserter/media-tab/media-preview.js.map +1 -1
  93. package/build/components/inserter/menu.js +3 -4
  94. package/build/components/inserter/menu.js.map +1 -1
  95. package/build/components/inserter-listbox/index.js +11 -6
  96. package/build/components/inserter-listbox/index.js.map +1 -1
  97. package/build/components/inserter-listbox/item.js +24 -23
  98. package/build/components/inserter-listbox/item.js.map +1 -1
  99. package/build/components/inserter-listbox/row.js +5 -5
  100. package/build/components/inserter-listbox/row.js.map +1 -1
  101. package/build/components/link-control/index.js +6 -5
  102. package/build/components/link-control/index.js.map +1 -1
  103. package/build/components/list-view/block-select-button.js +39 -0
  104. package/build/components/list-view/block-select-button.js.map +1 -1
  105. package/build/components/list-view/block.js +16 -3
  106. package/build/components/list-view/block.js.map +1 -1
  107. package/build/components/list-view/index.js +3 -2
  108. package/build/components/list-view/index.js.map +1 -1
  109. package/build/components/list-view/use-list-view-expand-selected-item.js +2 -3
  110. package/build/components/list-view/use-list-view-expand-selected-item.js.map +1 -1
  111. package/build/components/navigable-toolbar/index.js +69 -18
  112. package/build/components/navigable-toolbar/index.js.map +1 -1
  113. package/build/components/preview-options/index.js +4 -2
  114. package/build/components/preview-options/index.js.map +1 -1
  115. package/build/components/provider/use-block-sync.js +1 -14
  116. package/build/components/provider/use-block-sync.js.map +1 -1
  117. package/build/components/rich-text/index.js +0 -1
  118. package/build/components/rich-text/index.js.map +1 -1
  119. package/build/components/rich-text/index.native.js +4 -2
  120. package/build/components/rich-text/index.native.js.map +1 -1
  121. package/build/components/rich-text/native/format-edit.js +45 -0
  122. package/build/components/rich-text/native/format-edit.js.map +1 -0
  123. package/build/components/rich-text/native/get-format-colors.native.js +41 -0
  124. package/build/components/rich-text/native/get-format-colors.native.js.map +1 -0
  125. package/build/components/rich-text/native/index.js +9 -0
  126. package/build/components/rich-text/native/index.js.map +1 -0
  127. package/build/components/rich-text/native/index.native.js +1189 -0
  128. package/build/components/rich-text/native/index.native.js.map +1 -0
  129. package/build/components/rich-text/native/toolbar-button-with-options.native.js +58 -0
  130. package/build/components/rich-text/native/toolbar-button-with-options.native.js.map +1 -0
  131. package/build/components/rich-text/native/use-format-types.js +111 -0
  132. package/build/components/rich-text/native/use-format-types.js.map +1 -0
  133. package/build/components/rich-text/use-input-rules.js +30 -1
  134. package/build/components/rich-text/use-input-rules.js.map +1 -1
  135. package/build/components/rich-text/use-paste-handler.js +2 -5
  136. package/build/components/rich-text/use-paste-handler.js.map +1 -1
  137. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  138. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  139. package/build/components/url-popover/image-url-input-ui.js +2 -1
  140. package/build/components/url-popover/image-url-input-ui.js.map +1 -1
  141. package/build/components/use-block-drop-zone/index.js +4 -1
  142. package/build/components/use-block-drop-zone/index.js.map +1 -1
  143. package/build/components/use-moving-animation/index.js +2 -1
  144. package/build/components/use-moving-animation/index.js.map +1 -1
  145. package/build/components/use-settings/index.js +2 -2
  146. package/build/components/use-settings/index.js.map +1 -1
  147. package/build/components/writing-flow/use-tab-nav.js +7 -3
  148. package/build/components/writing-flow/use-tab-nav.js.map +1 -1
  149. package/build/hooks/align.js +10 -10
  150. package/build/hooks/align.js.map +1 -1
  151. package/build/hooks/align.native.js +2 -2
  152. package/build/hooks/align.native.js.map +1 -1
  153. package/build/hooks/anchor.js +7 -6
  154. package/build/hooks/anchor.js.map +1 -1
  155. package/build/hooks/background.js +16 -4
  156. package/build/hooks/background.js.map +1 -1
  157. package/build/hooks/block-hooks.js +7 -8
  158. package/build/hooks/block-hooks.js.map +1 -1
  159. package/build/hooks/block-renaming.js +42 -0
  160. package/build/hooks/block-renaming.js.map +1 -1
  161. package/build/hooks/content-lock-ui.js +5 -5
  162. package/build/hooks/content-lock-ui.js.map +1 -1
  163. package/build/hooks/custom-class-name.js +8 -7
  164. package/build/hooks/custom-class-name.js.map +1 -1
  165. package/build/hooks/custom-fields.js +57 -52
  166. package/build/hooks/custom-fields.js.map +1 -1
  167. package/build/hooks/duotone.js +9 -20
  168. package/build/hooks/duotone.js.map +1 -1
  169. package/build/hooks/index.js +0 -1
  170. package/build/hooks/index.js.map +1 -1
  171. package/build/hooks/layout.js +103 -93
  172. package/build/hooks/layout.js.map +1 -1
  173. package/build/hooks/position.js +10 -9
  174. package/build/hooks/position.js.map +1 -1
  175. package/build/hooks/style.js +10 -13
  176. package/build/hooks/style.js.map +1 -1
  177. package/build/hooks/utils.js +30 -0
  178. package/build/hooks/utils.js.map +1 -1
  179. package/build/layouts/constrained.js +4 -3
  180. package/build/layouts/constrained.js.map +1 -1
  181. package/build/private-apis.js +3 -0
  182. package/build/private-apis.js.map +1 -1
  183. package/build/store/actions.js +30 -37
  184. package/build/store/actions.js.map +1 -1
  185. package/build/store/reducer.js +18 -0
  186. package/build/store/reducer.js.map +1 -1
  187. package/build/store/selectors.js +18 -13
  188. package/build/store/selectors.js.map +1 -1
  189. package/build/utils/transform-styles/index.js +26 -6
  190. package/build/utils/transform-styles/index.js.map +1 -1
  191. package/build-module/components/block-heading-level-dropdown/index.js +1 -1
  192. package/build-module/components/block-heading-level-dropdown/index.js.map +1 -1
  193. package/build-module/components/block-list/block.native.js +2 -0
  194. package/build-module/components/block-list/block.native.js.map +1 -1
  195. package/build-module/components/block-list/index.js +3 -10
  196. package/build-module/components/block-list/index.js.map +1 -1
  197. package/build-module/components/block-list-appender/index.js +16 -3
  198. package/build-module/components/block-list-appender/index.js.map +1 -1
  199. package/build-module/components/block-parent-selector/index.js +1 -1
  200. package/build-module/components/block-parent-selector/index.js.map +1 -1
  201. package/build-module/components/block-pattern-setup/index.js +24 -15
  202. package/build-module/components/block-pattern-setup/index.js.map +1 -1
  203. package/build-module/components/block-pattern-setup/setup-toolbar.js +4 -2
  204. package/build-module/components/block-pattern-setup/setup-toolbar.js.map +1 -1
  205. package/build-module/components/block-patterns-list/index.js +36 -19
  206. package/build-module/components/block-patterns-list/index.js.map +1 -1
  207. package/build-module/components/block-quick-navigation/index.js +7 -5
  208. package/build-module/components/block-quick-navigation/index.js.map +1 -1
  209. package/build-module/components/block-rename/index.js +4 -0
  210. package/build-module/components/block-rename/index.js.map +1 -0
  211. package/build-module/components/block-rename/is-empty-string.js +4 -0
  212. package/build-module/components/block-rename/is-empty-string.js.map +1 -0
  213. package/build-module/components/block-rename/modal.js +79 -0
  214. package/build-module/components/block-rename/modal.js.map +1 -0
  215. package/build-module/components/block-rename/rename-control.js +66 -0
  216. package/build-module/components/block-rename/rename-control.js.map +1 -0
  217. package/build-module/components/block-rename/use-block-rename.js +10 -0
  218. package/build-module/components/block-rename/use-block-rename.js.map +1 -0
  219. package/build-module/components/block-settings-menu/block-settings-dropdown.js +34 -21
  220. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  221. package/build-module/components/block-settings-menu-controls/index.js +7 -0
  222. package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
  223. package/build-module/components/block-styles/index.js +0 -8
  224. package/build-module/components/block-styles/index.js.map +1 -1
  225. package/build-module/components/block-switcher/pattern-transformations-menu.js +17 -13
  226. package/build-module/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  227. package/build-module/components/block-toolbar/block-toolbar-menu.native.js +1 -1
  228. package/build-module/components/block-toolbar/block-toolbar-menu.native.js.map +1 -1
  229. package/build-module/components/block-tools/back-compat.js +1 -1
  230. package/build-module/components/block-tools/back-compat.js.map +1 -1
  231. package/build-module/components/block-tools/block-contextual-toolbar.js +11 -80
  232. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  233. package/build-module/components/block-tools/empty-block-inserter.js +48 -0
  234. package/build-module/components/block-tools/empty-block-inserter.js.map +1 -0
  235. package/build-module/components/block-tools/index.js +48 -9
  236. package/build-module/components/block-tools/index.js.map +1 -1
  237. package/build-module/components/block-tools/selected-block-tools.js +105 -0
  238. package/build-module/components/block-tools/selected-block-tools.js.map +1 -0
  239. package/build-module/components/block-tools/use-selected-block-tool-props.js +50 -0
  240. package/build-module/components/block-tools/use-selected-block-tool-props.js.map +1 -0
  241. package/build-module/components/block-types-list/index.js +6 -2
  242. package/build-module/components/block-types-list/index.js.map +1 -1
  243. package/build-module/components/date-format-picker/index.js +8 -1
  244. package/build-module/components/date-format-picker/index.js.map +1 -1
  245. package/build-module/components/editable-text/index.js +1 -2
  246. package/build-module/components/editable-text/index.js.map +1 -1
  247. package/build-module/components/global-styles/advanced-panel.js +1 -1
  248. package/build-module/components/global-styles/advanced-panel.js.map +1 -1
  249. package/build-module/components/iframe/index.js +4 -3
  250. package/build-module/components/iframe/index.js.map +1 -1
  251. package/build-module/components/image-size-control/index.js +0 -5
  252. package/build-module/components/image-size-control/index.js.map +1 -1
  253. package/build-module/components/inner-blocks/index.js +3 -1
  254. package/build-module/components/inner-blocks/index.js.map +1 -1
  255. package/build-module/components/inner-blocks/warning-max-depth-exceeded.native.js +30 -32
  256. package/build-module/components/inner-blocks/warning-max-depth-exceeded.native.js.map +1 -1
  257. package/build-module/components/inserter/block-patterns-explorer/{explorer.js → index.js} +5 -5
  258. package/build-module/components/inserter/block-patterns-explorer/index.js.map +1 -0
  259. package/build-module/components/inserter/block-patterns-explorer/{sidebar.js → pattern-explorer-sidebar.js} +1 -1
  260. package/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js.map +1 -0
  261. package/build-module/components/inserter/block-patterns-explorer/{patterns-list.js → pattern-list.js} +3 -3
  262. package/build-module/components/inserter/block-patterns-explorer/pattern-list.js.map +1 -0
  263. package/build-module/components/inserter/block-patterns-tab/index.js +66 -0
  264. package/build-module/components/inserter/block-patterns-tab/index.js.map +1 -0
  265. package/build-module/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +42 -0
  266. package/build-module/components/inserter/block-patterns-tab/pattern-category-preview-panel.js.map +1 -0
  267. package/build-module/components/inserter/block-patterns-tab/pattern-category-previews.js +100 -0
  268. package/build-module/components/inserter/block-patterns-tab/pattern-category-previews.js.map +1 -0
  269. package/build-module/components/inserter/{block-patterns-filter.js → block-patterns-tab/patterns-filter.js} +7 -20
  270. package/build-module/components/inserter/block-patterns-tab/patterns-filter.js.map +1 -0
  271. package/build-module/components/inserter/block-patterns-tab/use-pattern-categories.js +47 -0
  272. package/build-module/components/inserter/block-patterns-tab/use-pattern-categories.js.map +1 -0
  273. package/build-module/components/inserter/block-patterns-tab/utils.js +57 -0
  274. package/build-module/components/inserter/block-patterns-tab/utils.js.map +1 -0
  275. package/build-module/components/inserter/hooks/use-patterns-state.js +2 -1
  276. package/build-module/components/inserter/hooks/use-patterns-state.js.map +1 -1
  277. package/build-module/components/inserter/media-tab/media-list.js +9 -5
  278. package/build-module/components/inserter/media-tab/media-list.js.map +1 -1
  279. package/build-module/components/inserter/media-tab/media-preview.js +15 -12
  280. package/build-module/components/inserter/media-tab/media-preview.js.map +1 -1
  281. package/build-module/components/inserter/menu.js +4 -3
  282. package/build-module/components/inserter/menu.js.map +1 -1
  283. package/build-module/components/inserter-listbox/index.js +13 -8
  284. package/build-module/components/inserter-listbox/index.js.map +1 -1
  285. package/build-module/components/inserter-listbox/item.js +25 -23
  286. package/build-module/components/inserter-listbox/item.js.map +1 -1
  287. package/build-module/components/inserter-listbox/row.js +6 -5
  288. package/build-module/components/inserter-listbox/row.js.map +1 -1
  289. package/build-module/components/link-control/index.js +7 -6
  290. package/build-module/components/link-control/index.js.map +1 -1
  291. package/build-module/components/list-view/block-select-button.js +39 -0
  292. package/build-module/components/list-view/block-select-button.js.map +1 -1
  293. package/build-module/components/list-view/block.js +16 -3
  294. package/build-module/components/list-view/block.js.map +1 -1
  295. package/build-module/components/list-view/index.js +3 -2
  296. package/build-module/components/list-view/index.js.map +1 -1
  297. package/build-module/components/list-view/use-list-view-expand-selected-item.js +2 -3
  298. package/build-module/components/list-view/use-list-view-expand-selected-item.js.map +1 -1
  299. package/build-module/components/navigable-toolbar/index.js +69 -17
  300. package/build-module/components/navigable-toolbar/index.js.map +1 -1
  301. package/build-module/components/preview-options/index.js +4 -2
  302. package/build-module/components/preview-options/index.js.map +1 -1
  303. package/build-module/components/provider/use-block-sync.js +1 -14
  304. package/build-module/components/provider/use-block-sync.js.map +1 -1
  305. package/build-module/components/rich-text/index.js +0 -1
  306. package/build-module/components/rich-text/index.js.map +1 -1
  307. package/build-module/components/rich-text/index.native.js +4 -2
  308. package/build-module/components/rich-text/index.native.js.map +1 -1
  309. package/build-module/components/rich-text/native/format-edit.js +38 -0
  310. package/build-module/components/rich-text/native/format-edit.js.map +1 -0
  311. package/build-module/components/rich-text/native/get-format-colors.native.js +34 -0
  312. package/build-module/components/rich-text/native/get-format-colors.native.js.map +1 -0
  313. package/build-module/components/rich-text/native/index.js +2 -0
  314. package/build-module/components/rich-text/native/index.js.map +1 -0
  315. package/build-module/components/rich-text/native/index.native.js +1179 -0
  316. package/build-module/components/rich-text/native/index.native.js.map +1 -0
  317. package/build-module/components/rich-text/native/toolbar-button-with-options.native.js +51 -0
  318. package/build-module/components/rich-text/native/toolbar-button-with-options.native.js.map +1 -0
  319. package/build-module/components/rich-text/native/use-format-types.js +104 -0
  320. package/build-module/components/rich-text/native/use-format-types.js.map +1 -0
  321. package/build-module/components/rich-text/use-input-rules.js +31 -2
  322. package/build-module/components/rich-text/use-input-rules.js.map +1 -1
  323. package/build-module/components/rich-text/use-paste-handler.js +2 -5
  324. package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
  325. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  326. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  327. package/build-module/components/url-popover/image-url-input-ui.js +2 -1
  328. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  329. package/build-module/components/use-block-drop-zone/index.js +4 -1
  330. package/build-module/components/use-block-drop-zone/index.js.map +1 -1
  331. package/build-module/components/use-moving-animation/index.js +2 -1
  332. package/build-module/components/use-moving-animation/index.js.map +1 -1
  333. package/build-module/components/use-settings/index.js +2 -2
  334. package/build-module/components/use-settings/index.js.map +1 -1
  335. package/build-module/components/writing-flow/use-tab-nav.js +7 -3
  336. package/build-module/components/writing-flow/use-tab-nav.js.map +1 -1
  337. package/build-module/hooks/align.js +8 -8
  338. package/build-module/hooks/align.js.map +1 -1
  339. package/build-module/hooks/align.native.js +2 -2
  340. package/build-module/hooks/align.native.js.map +1 -1
  341. package/build-module/hooks/anchor.js +5 -4
  342. package/build-module/hooks/anchor.js.map +1 -1
  343. package/build-module/hooks/background.js +17 -5
  344. package/build-module/hooks/background.js.map +1 -1
  345. package/build-module/hooks/block-hooks.js +5 -6
  346. package/build-module/hooks/block-hooks.js.map +1 -1
  347. package/build-module/hooks/block-renaming.js +40 -0
  348. package/build-module/hooks/block-renaming.js.map +1 -1
  349. package/build-module/hooks/content-lock-ui.js +3 -3
  350. package/build-module/hooks/content-lock-ui.js.map +1 -1
  351. package/build-module/hooks/custom-class-name.js +6 -5
  352. package/build-module/hooks/custom-class-name.js.map +1 -1
  353. package/build-module/hooks/custom-fields.js +57 -52
  354. package/build-module/hooks/custom-fields.js.map +1 -1
  355. package/build-module/hooks/duotone.js +10 -21
  356. package/build-module/hooks/duotone.js.map +1 -1
  357. package/build-module/hooks/index.js +0 -1
  358. package/build-module/hooks/index.js.map +1 -1
  359. package/build-module/hooks/layout.js +103 -93
  360. package/build-module/hooks/layout.js.map +1 -1
  361. package/build-module/hooks/position.js +11 -10
  362. package/build-module/hooks/position.js.map +1 -1
  363. package/build-module/hooks/style.js +10 -13
  364. package/build-module/hooks/style.js.map +1 -1
  365. package/build-module/hooks/utils.js +30 -1
  366. package/build-module/hooks/utils.js.map +1 -1
  367. package/build-module/layouts/constrained.js +4 -3
  368. package/build-module/layouts/constrained.js.map +1 -1
  369. package/build-module/private-apis.js +4 -1
  370. package/build-module/private-apis.js.map +1 -1
  371. package/build-module/store/actions.js +29 -37
  372. package/build-module/store/actions.js.map +1 -1
  373. package/build-module/store/reducer.js +17 -0
  374. package/build-module/store/reducer.js.map +1 -1
  375. package/build-module/store/selectors.js +17 -13
  376. package/build-module/store/selectors.js.map +1 -1
  377. package/build-module/utils/transform-styles/index.js +24 -7
  378. package/build-module/utils/transform-styles/index.js.map +1 -1
  379. package/build-style/content-rtl.css +6 -6
  380. package/build-style/content.css +6 -6
  381. package/build-style/style-rtl.css +26 -20
  382. package/build-style/style.css +26 -20
  383. package/package.json +31 -31
  384. package/src/components/block-heading-level-dropdown/index.js +1 -1
  385. package/src/components/block-list/block.native.js +2 -0
  386. package/src/components/block-list/index.js +4 -18
  387. package/src/components/block-list-appender/index.js +20 -4
  388. package/src/components/block-parent-selector/index.js +1 -1
  389. package/src/components/block-pattern-setup/index.js +38 -22
  390. package/src/components/block-pattern-setup/setup-toolbar.js +2 -0
  391. package/src/components/block-pattern-setup/style.scss +4 -1
  392. package/src/components/block-patterns-list/README.md +4 -4
  393. package/src/components/block-patterns-list/index.js +60 -34
  394. package/src/components/block-patterns-list/style.scss +7 -0
  395. package/src/components/block-quick-navigation/index.js +11 -5
  396. package/src/components/block-rename/index.js +3 -0
  397. package/src/components/block-rename/is-empty-string.js +3 -0
  398. package/src/components/block-rename/modal.js +115 -0
  399. package/src/components/block-rename/rename-control.js +80 -0
  400. package/src/components/block-rename/use-block-rename.js +10 -0
  401. package/src/components/block-settings-menu/block-settings-dropdown.js +38 -34
  402. package/src/components/block-settings-menu-controls/index.js +9 -0
  403. package/src/components/block-styles/index.js +0 -10
  404. package/src/components/block-switcher/pattern-transformations-menu.js +20 -14
  405. package/src/components/block-toolbar/block-toolbar-menu.native.js +1 -4
  406. package/src/components/block-toolbar/style.scss +8 -0
  407. package/src/components/block-tools/back-compat.js +1 -1
  408. package/src/components/block-tools/block-contextual-toolbar.js +11 -134
  409. package/src/components/block-tools/empty-block-inserter.js +56 -0
  410. package/src/components/block-tools/index.js +72 -16
  411. package/src/components/block-tools/selected-block-tools.js +127 -0
  412. package/src/components/block-tools/style.scss +0 -10
  413. package/src/components/block-tools/use-selected-block-tool-props.js +66 -0
  414. package/src/components/block-types-list/index.js +5 -4
  415. package/src/components/button-block-appender/content.scss +2 -2
  416. package/src/components/date-format-picker/index.js +7 -0
  417. package/src/components/editable-text/README.md +0 -36
  418. package/src/components/editable-text/index.js +1 -8
  419. package/src/components/global-styles/advanced-panel.js +1 -1
  420. package/src/components/iframe/index.js +4 -3
  421. package/src/components/image-size-control/index.js +0 -6
  422. package/src/components/inner-blocks/index.js +6 -2
  423. package/src/components/inner-blocks/warning-max-depth-exceeded.native.js +57 -33
  424. package/src/components/inserter/block-patterns-explorer/{explorer.js → index.js} +4 -4
  425. package/src/components/inserter/block-patterns-explorer/{patterns-list.js → pattern-list.js} +9 -2
  426. package/src/components/inserter/block-patterns-tab/index.js +118 -0
  427. package/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +48 -0
  428. package/src/components/inserter/block-patterns-tab/pattern-category-previews.js +179 -0
  429. package/src/components/inserter/{block-patterns-filter.js → block-patterns-tab/patterns-filter.js} +15 -21
  430. package/src/components/inserter/block-patterns-tab/use-pattern-categories.js +101 -0
  431. package/src/components/inserter/block-patterns-tab/utils.js +78 -0
  432. package/src/components/inserter/hooks/use-patterns-state.js +3 -1
  433. package/src/components/inserter/media-tab/media-list.js +7 -7
  434. package/src/components/inserter/media-tab/media-preview.js +27 -22
  435. package/src/components/inserter/menu.js +4 -5
  436. package/src/components/inserter-listbox/index.js +11 -7
  437. package/src/components/inserter-listbox/item.js +11 -12
  438. package/src/components/inserter-listbox/row.js +6 -12
  439. package/src/components/link-control/README.md +2 -2
  440. package/src/components/link-control/index.js +15 -6
  441. package/src/components/link-control/style.scss +8 -5
  442. package/src/components/list-view/block-select-button.js +44 -1
  443. package/src/components/list-view/block.js +11 -11
  444. package/src/components/list-view/index.js +2 -0
  445. package/src/components/list-view/use-list-view-expand-selected-item.js +7 -8
  446. package/src/components/media-replace-flow/style.scss +2 -2
  447. package/src/components/navigable-toolbar/index.js +71 -25
  448. package/src/components/plain-text/README.md +2 -30
  449. package/src/components/preview-options/index.js +2 -0
  450. package/src/components/provider/use-block-sync.js +2 -21
  451. package/src/components/rich-text/README.md +6 -63
  452. package/src/components/rich-text/index.js +0 -1
  453. package/src/components/rich-text/index.native.js +4 -2
  454. package/src/components/rich-text/native/format-edit.js +44 -0
  455. package/src/components/rich-text/native/get-format-colors.native.js +54 -0
  456. package/src/components/rich-text/native/index.js +1 -0
  457. package/src/components/rich-text/native/index.native.js +1406 -0
  458. package/src/components/rich-text/native/style.native.scss +28 -0
  459. package/src/components/rich-text/native/test/__snapshots__/index.native.js.snap +79 -0
  460. package/src/components/rich-text/native/test/index.native.js +278 -0
  461. package/src/components/rich-text/native/test/performance/rich-text.native.js +44 -0
  462. package/src/components/rich-text/native/toolbar-button-with-options.native.js +61 -0
  463. package/src/components/rich-text/native/use-format-types.js +146 -0
  464. package/src/components/rich-text/use-input-rules.js +30 -2
  465. package/src/components/rich-text/use-paste-handler.js +1 -6
  466. package/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +1 -1
  467. package/src/components/url-input/README.md +1 -74
  468. package/src/components/url-popover/image-url-input-ui.js +1 -0
  469. package/src/components/use-block-drop-zone/index.js +4 -1
  470. package/src/components/use-moving-animation/index.js +1 -1
  471. package/src/components/use-settings/index.js +2 -2
  472. package/src/components/use-settings/test/index.js +1 -1
  473. package/src/components/writing-flow/use-tab-nav.js +8 -3
  474. package/src/hooks/align.js +8 -8
  475. package/src/hooks/align.native.js +2 -2
  476. package/src/hooks/anchor.js +21 -23
  477. package/src/hooks/background.js +28 -6
  478. package/src/hooks/block-hooks.js +20 -16
  479. package/src/hooks/block-renaming.js +47 -0
  480. package/src/hooks/content-lock-ui.js +3 -3
  481. package/src/hooks/custom-class-name.js +7 -6
  482. package/src/hooks/custom-fields.js +73 -70
  483. package/src/hooks/duotone.js +23 -33
  484. package/src/hooks/index.js +0 -1
  485. package/src/hooks/layout.js +126 -113
  486. package/src/hooks/position.js +8 -21
  487. package/src/hooks/style.js +17 -31
  488. package/src/hooks/test/__snapshots__/align.native.js.snap +5 -5
  489. package/src/hooks/test/align.js +4 -4
  490. package/src/hooks/utils.js +33 -1
  491. package/src/layouts/constrained.js +57 -50
  492. package/src/private-apis.js +4 -1
  493. package/src/store/actions.js +26 -72
  494. package/src/store/reducer.js +19 -0
  495. package/src/store/selectors.js +15 -19
  496. package/src/style.scss +1 -1
  497. package/src/utils/test/transform-styles.js +49 -0
  498. package/src/utils/transform-styles/index.js +39 -13
  499. package/build/components/block-tools/selected-block-popover.js +0 -221
  500. package/build/components/block-tools/selected-block-popover.js.map +0 -1
  501. package/build/components/inserter/block-patterns-explorer/explorer.js.map +0 -1
  502. package/build/components/inserter/block-patterns-explorer/patterns-list.js.map +0 -1
  503. package/build/components/inserter/block-patterns-explorer/sidebar.js.map +0 -1
  504. package/build/components/inserter/block-patterns-filter.js.map +0 -1
  505. package/build/components/inserter/block-patterns-tab.js +0 -270
  506. package/build/components/inserter/block-patterns-tab.js.map +0 -1
  507. package/build/hooks/block-rename-ui.js +0 -165
  508. package/build/hooks/block-rename-ui.js.map +0 -1
  509. package/build/store/utils.js +0 -22
  510. package/build/store/utils.js.map +0 -1
  511. package/build-module/components/block-tools/selected-block-popover.js +0 -213
  512. package/build-module/components/block-tools/selected-block-popover.js.map +0 -1
  513. package/build-module/components/inserter/block-patterns-explorer/explorer.js.map +0 -1
  514. package/build-module/components/inserter/block-patterns-explorer/patterns-list.js.map +0 -1
  515. package/build-module/components/inserter/block-patterns-explorer/sidebar.js.map +0 -1
  516. package/build-module/components/inserter/block-patterns-filter.js.map +0 -1
  517. package/build-module/components/inserter/block-patterns-tab.js +0 -254
  518. package/build-module/components/inserter/block-patterns-tab.js.map +0 -1
  519. package/build-module/hooks/block-rename-ui.js +0 -157
  520. package/build-module/hooks/block-rename-ui.js.map +0 -1
  521. package/build-module/store/utils.js +0 -16
  522. package/build-module/store/utils.js.map +0 -1
  523. package/src/components/block-tools/selected-block-popover.js +0 -265
  524. package/src/components/inserter/block-patterns-tab.js +0 -448
  525. package/src/hooks/block-rename-ui.js +0 -226
  526. package/src/store/utils.js +0 -12
  527. /package/src/{hooks/block-rename-ui.scss → components/block-rename/style.scss} +0 -0
  528. /package/src/components/inserter/block-patterns-explorer/{sidebar.js → pattern-explorer-sidebar.js} +0 -0
@@ -0,0 +1,1189 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = exports.RichText = void 0;
8
+ var _react = require("react");
9
+ var _reactNative = require("react-native");
10
+ var _memize = _interopRequireDefault(require("memize"));
11
+ var _colord = require("colord");
12
+ var _reactNativeAztec = _interopRequireDefault(require("@wordpress/react-native-aztec"));
13
+ var _reactNativeBridge = require("@wordpress/react-native-bridge");
14
+ var _blockEditor = require("@wordpress/block-editor");
15
+ var _element = require("@wordpress/element");
16
+ var _compose = require("@wordpress/compose");
17
+ var _data = require("@wordpress/data");
18
+ var _blocks = require("@wordpress/blocks");
19
+ var _htmlEntities = require("@wordpress/html-entities");
20
+ var _keycodes = require("@wordpress/keycodes");
21
+ var _url = require("@wordpress/url");
22
+ var _icons = require("@wordpress/icons");
23
+ var _i18n = require("@wordpress/i18n");
24
+ var _richText = require("@wordpress/rich-text");
25
+ var _useFormatTypes = require("./use-format-types");
26
+ var _formatEdit = _interopRequireDefault(require("./format-edit"));
27
+ var _getFormatColors = require("./get-format-colors");
28
+ var _style = _interopRequireDefault(require("./style.scss"));
29
+ var _toolbarButtonWithOptions = _interopRequireDefault(require("./toolbar-button-with-options"));
30
+ /* eslint no-console: ["error", { allow: ["warn"] }] */
31
+
32
+ /**
33
+ * External dependencies
34
+ */
35
+
36
+ /**
37
+ * WordPress dependencies
38
+ */
39
+
40
+ /**
41
+ * Internal dependencies
42
+ */
43
+
44
+ const unescapeSpaces = text => {
45
+ return text.replace(/ | /gi, ' ');
46
+ };
47
+
48
+ // The flattened color palettes array is memoized to ensure that the same array instance is
49
+ // returned for the colors palettes. This value might be used as a prop, so having the same
50
+ // instance will prevent unnecessary re-renders of the RichText component.
51
+ const flatColorPalettes = (0, _memize.default)(colorsPalettes => [...(colorsPalettes?.theme || []), ...(colorsPalettes?.custom || []), ...(colorsPalettes?.default || [])]);
52
+ const getSelectionColor = (0, _memize.default)((currentSelectionColor, defaultSelectionColor, baseGlobalStyles, isBlockBasedTheme) => {
53
+ let selectionColor = defaultSelectionColor;
54
+ if (currentSelectionColor) {
55
+ selectionColor = currentSelectionColor;
56
+ }
57
+ if (isBlockBasedTheme) {
58
+ const colordTextColor = (0, _colord.colord)(selectionColor);
59
+ const colordBackgroundColor = (0, _colord.colord)(baseGlobalStyles?.color?.background);
60
+ const isColordTextReadable = colordTextColor.isReadable(colordBackgroundColor);
61
+ if (!isColordTextReadable) {
62
+ selectionColor = baseGlobalStyles?.color?.text;
63
+ }
64
+ }
65
+ return selectionColor;
66
+ });
67
+ const gutenbergFormatNamesToAztec = {
68
+ 'core/bold': 'bold',
69
+ 'core/italic': 'italic',
70
+ 'core/strikethrough': 'strikethrough',
71
+ 'core/text-color': 'mark'
72
+ };
73
+ const EMPTY_PARAGRAPH_TAGS = '<p></p>';
74
+ const DEFAULT_FONT_SIZE = 16;
75
+ const MIN_LINE_HEIGHT = 1;
76
+ class RichText extends _element.Component {
77
+ constructor({
78
+ value,
79
+ selectionStart,
80
+ selectionEnd,
81
+ __unstableMultilineTag: multiline
82
+ }) {
83
+ super(...arguments);
84
+ this.isMultiline = false;
85
+ if (multiline === true || multiline === 'p' || multiline === 'li') {
86
+ this.multilineTag = multiline === true ? 'p' : multiline;
87
+ this.isMultiline = true;
88
+ }
89
+ if (this.multilineTag === 'li') {
90
+ this.multilineWrapperTags = ['ul', 'ol'];
91
+ }
92
+ this.isIOS = _reactNative.Platform.OS === 'ios';
93
+ this.createRecord = this.createRecord.bind(this);
94
+ this.restoreParagraphTags = this.restoreParagraphTags.bind(this);
95
+ this.onChangeFromAztec = this.onChangeFromAztec.bind(this);
96
+ this.onKeyDown = this.onKeyDown.bind(this);
97
+ this.handleEnter = this.handleEnter.bind(this);
98
+ this.handleDelete = this.handleDelete.bind(this);
99
+ this.onPaste = this.onPaste.bind(this);
100
+ this.onFocus = this.onFocus.bind(this);
101
+ this.onBlur = this.onBlur.bind(this);
102
+ this.onTextUpdate = this.onTextUpdate.bind(this);
103
+ this.onContentSizeChange = this.onContentSizeChange.bind(this);
104
+ this.onFormatChange = this.onFormatChange.bind(this);
105
+ this.formatToValue = (0, _memize.default)(this.formatToValue.bind(this), {
106
+ maxSize: 1
107
+ });
108
+ this.debounceCreateUndoLevel = (0, _compose.debounce)(this.onCreateUndoLevel, 1000);
109
+ // This prevents a bug in Aztec which triggers onSelectionChange twice on format change.
110
+ this.onSelectionChange = this.onSelectionChange.bind(this);
111
+ this.onSelectionChangeFromAztec = this.onSelectionChangeFromAztec.bind(this);
112
+ this.valueToFormat = this.valueToFormat.bind(this);
113
+ this.getHtmlToRender = this.getHtmlToRender.bind(this);
114
+ this.handleSuggestionFunc = this.handleSuggestionFunc.bind(this);
115
+ this.handleUserSuggestion = this.handleSuggestionFunc(_reactNativeBridge.showUserSuggestions, '@').bind(this);
116
+ this.handleXpostSuggestion = this.handleSuggestionFunc(_reactNativeBridge.showXpostSuggestions, '+').bind(this);
117
+ this.suggestionOptions = this.suggestionOptions.bind(this);
118
+ this.insertString = this.insertString.bind(this);
119
+ this.manipulateEventCounterToForceNativeToRefresh = this.manipulateEventCounterToForceNativeToRefresh.bind(this);
120
+ this.shouldDropEventFromAztec = this.shouldDropEventFromAztec.bind(this);
121
+ this.state = {
122
+ activeFormats: [],
123
+ selectedFormat: null,
124
+ height: 0,
125
+ currentFontSize: this.getFontSize(arguments[0])
126
+ };
127
+ this.needsSelectionUpdate = false;
128
+ this.savedContent = '';
129
+ this.isTouched = false;
130
+ this.lastAztecEventType = null;
131
+ this.lastHistoryValue = value;
132
+
133
+ // Internal values that are update synchronously, unlike props.
134
+ this.value = value;
135
+ this.selectionStart = selectionStart;
136
+ this.selectionEnd = selectionEnd;
137
+ }
138
+
139
+ /**
140
+ * Get the current record (value and selection) from props and state.
141
+ *
142
+ * @return {Object} The current record (value and selection).
143
+ */
144
+ getRecord() {
145
+ const {
146
+ selectionStart: start,
147
+ selectionEnd: end,
148
+ colorPalette
149
+ } = this.props;
150
+ const {
151
+ value
152
+ } = this.props;
153
+ const currentValue = this.formatToValue(value);
154
+ const {
155
+ formats,
156
+ replacements,
157
+ text
158
+ } = currentValue;
159
+ const {
160
+ activeFormats
161
+ } = this.state;
162
+ const newFormats = (0, _getFormatColors.getFormatColors)(value, formats, colorPalette);
163
+ return {
164
+ formats: newFormats,
165
+ replacements,
166
+ text,
167
+ start,
168
+ end,
169
+ activeFormats
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Creates a RichText value "record" from the current content and selection
175
+ * information
176
+ *
177
+ *
178
+ * @return {Object} A RichText value with formats and selection.
179
+ */
180
+ createRecord() {
181
+ const {
182
+ preserveWhiteSpace
183
+ } = this.props;
184
+ const value = {
185
+ start: this.selectionStart,
186
+ end: this.selectionEnd,
187
+ ...(0, _richText.create)({
188
+ html: this.value,
189
+ range: null,
190
+ multilineTag: this.multilineTag,
191
+ multilineWrapperTags: this.multilineWrapperTags,
192
+ preserveWhiteSpace
193
+ })
194
+ };
195
+ const start = Math.min(this.selectionStart, value.text.length);
196
+ const end = Math.min(this.selectionEnd, value.text.length);
197
+ return {
198
+ ...value,
199
+ start,
200
+ end
201
+ };
202
+ }
203
+ valueToFormat(value) {
204
+ // Remove the outer root tags.
205
+ return this.removeRootTagsProducedByAztec((0, _richText.toHTMLString)({
206
+ value,
207
+ multilineTag: this.multilineTag
208
+ }));
209
+ }
210
+ getActiveFormatNames(record) {
211
+ const {
212
+ formatTypes
213
+ } = this.props;
214
+ return formatTypes.map(({
215
+ name
216
+ }) => name).filter(name => {
217
+ return (0, _richText.getActiveFormat)(record, name) !== undefined;
218
+ }).map(name => gutenbergFormatNamesToAztec[name]).filter(Boolean);
219
+ }
220
+ onFormatChange(record) {
221
+ const {
222
+ start = 0,
223
+ end = 0,
224
+ activeFormats = []
225
+ } = record;
226
+ const changeHandlers = Object.fromEntries(Object.entries(this.props).filter(([key]) => key.startsWith('format_on_change_functions_')));
227
+ Object.values(changeHandlers).forEach(changeHandler => {
228
+ changeHandler(record.formats, record.text);
229
+ });
230
+ this.value = this.valueToFormat(record);
231
+ this.props.onChange(this.value);
232
+ this.setState({
233
+ activeFormats
234
+ });
235
+ this.props.onSelectionChange(start, end);
236
+ this.selectionStart = start;
237
+ this.selectionEnd = end;
238
+ this.onCreateUndoLevel();
239
+ this.lastAztecEventType = 'format change';
240
+ }
241
+ insertString(record, string) {
242
+ if (record && string) {
243
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
244
+ const toInsert = (0, _richText.insert)(record, string);
245
+ this.onFormatChange(toInsert);
246
+ }
247
+ }
248
+ onCreateUndoLevel() {
249
+ const {
250
+ __unstableOnCreateUndoLevel: onCreateUndoLevel
251
+ } = this.props;
252
+ // If the content is the same, no level needs to be created.
253
+ if (this.lastHistoryValue === this.value) {
254
+ return;
255
+ }
256
+ onCreateUndoLevel();
257
+ this.lastHistoryValue = this.value;
258
+ }
259
+
260
+ /*
261
+ * Cleans up any root tags produced by aztec.
262
+ * TODO: This should be removed on a later version when aztec doesn't return the top tag of the text being edited
263
+ */
264
+ removeRootTagsProducedByAztec(html) {
265
+ let result = this.removeRootTag(this.props.tagName, html);
266
+ if (this.props.tagsToEliminate) {
267
+ this.props.tagsToEliminate.forEach(element => {
268
+ result = this.removeTag(element, result);
269
+ });
270
+ }
271
+ return result;
272
+ }
273
+ removeRootTag(tag, html) {
274
+ const openingTagRegexp = RegExp('^<' + tag + '[^>]*>', 'gim');
275
+ const closingTagRegexp = RegExp('</' + tag + '>$', 'gim');
276
+ return html.replace(openingTagRegexp, '').replace(closingTagRegexp, '');
277
+ }
278
+ removeTag(tag, html) {
279
+ const openingTagRegexp = RegExp('<' + tag + '>', 'gim');
280
+ const closingTagRegexp = RegExp('</' + tag + '>', 'gim');
281
+ return html.replace(openingTagRegexp, '').replace(closingTagRegexp, '');
282
+ }
283
+
284
+ /*
285
+ * Handles any case where the content of the AztecRN instance has changed
286
+ */
287
+ onChangeFromAztec(event) {
288
+ if (this.shouldDropEventFromAztec(event, 'onChange')) {
289
+ return;
290
+ }
291
+ const contentWithoutRootTag = this.removeRootTagsProducedByAztec(unescapeSpaces(event.nativeEvent.text));
292
+ // On iOS, onChange can be triggered after selection changes, even though there are no content changes.
293
+ if (contentWithoutRootTag === this.value) {
294
+ return;
295
+ }
296
+ this.lastEventCount = event.nativeEvent.eventCount;
297
+ this.comesFromAztec = true;
298
+ this.firedAfterTextChanged = true; // The onChange event always fires after the fact.
299
+ this.onTextUpdate(event);
300
+ this.lastAztecEventType = 'input';
301
+ }
302
+ onTextUpdate(event) {
303
+ const contentWithoutRootTag = this.removeRootTagsProducedByAztec(unescapeSpaces(event.nativeEvent.text));
304
+ let formattedContent = contentWithoutRootTag;
305
+ if (!this.isIOS) {
306
+ formattedContent = this.restoreParagraphTags(contentWithoutRootTag, this.multilineTag);
307
+ }
308
+ this.debounceCreateUndoLevel();
309
+ const refresh = this.value !== formattedContent;
310
+ this.value = formattedContent;
311
+
312
+ // We don't want to refresh if our goal is just to create a record.
313
+ if (refresh) {
314
+ this.props.onChange(formattedContent);
315
+ }
316
+ }
317
+ restoreParagraphTags(value, tag) {
318
+ if (tag === 'p' && (!value || !value.startsWith('<p>'))) {
319
+ return '<p>' + value + '</p>';
320
+ }
321
+ return value;
322
+ }
323
+
324
+ /*
325
+ * Handles any case where the content of the AztecRN instance has changed in size
326
+ */
327
+ onContentSizeChange(contentSize) {
328
+ this.setState(contentSize);
329
+ this.lastAztecEventType = 'content size change';
330
+ }
331
+ onKeyDown(event) {
332
+ if (event.defaultPrevented) {
333
+ return;
334
+ }
335
+
336
+ // Add stubs for conformance in downstream autocompleters logic.
337
+ this.customEditableOnKeyDown?.({
338
+ preventDefault: () => undefined,
339
+ ...event,
340
+ key: _reactNativeAztec.default.KeyCodes[event?.keyCode]
341
+ });
342
+ this.handleDelete(event);
343
+ this.handleEnter(event);
344
+ this.handleTriggerKeyCodes(event);
345
+ }
346
+ handleEnter(event) {
347
+ if (event.keyCode !== _keycodes.ENTER) {
348
+ return;
349
+ }
350
+ const {
351
+ onEnter
352
+ } = this.props;
353
+ if (!onEnter) {
354
+ return;
355
+ }
356
+ onEnter({
357
+ value: this.createRecord(),
358
+ onChange: this.onFormatChange,
359
+ shiftKey: event.shiftKey
360
+ });
361
+ this.lastAztecEventType = 'input';
362
+ }
363
+ handleDelete(event) {
364
+ if (this.shouldDropEventFromAztec(event, 'handleDelete')) {
365
+ return;
366
+ }
367
+ const {
368
+ keyCode
369
+ } = event;
370
+ if (keyCode !== _keycodes.DELETE && keyCode !== _keycodes.BACKSPACE) {
371
+ return;
372
+ }
373
+ const isReverse = keyCode === _keycodes.BACKSPACE;
374
+ const {
375
+ onDelete
376
+ } = this.props;
377
+ this.lastEventCount = event.nativeEvent.eventCount;
378
+ this.comesFromAztec = true;
379
+ this.firedAfterTextChanged = event.nativeEvent.firedAfterTextChanged;
380
+ const value = this.createRecord();
381
+ const {
382
+ start,
383
+ end,
384
+ text
385
+ } = value;
386
+ let newValue;
387
+
388
+ // Always handle full content deletion ourselves.
389
+ if (start === 0 && end !== 0 && end >= text.length) {
390
+ newValue = (0, _richText.remove)(value);
391
+ this.onFormatChange(newValue);
392
+ event.preventDefault();
393
+ return;
394
+ }
395
+
396
+ // Only process delete if the key press occurs at an uncollapsed edge.
397
+ if (!onDelete || !(0, _richText.isCollapsed)(value) || isReverse && start !== 0 || !isReverse && end !== text.length) {
398
+ return;
399
+ }
400
+ onDelete({
401
+ isReverse,
402
+ value
403
+ });
404
+ event.preventDefault();
405
+ this.lastAztecEventType = 'input';
406
+ }
407
+ handleTriggerKeyCodes(event) {
408
+ const {
409
+ keyCode
410
+ } = event;
411
+ const triggeredOption = this.suggestionOptions().find(option => {
412
+ const triggeredKeyCode = option.triggerChar.charCodeAt(0);
413
+ return triggeredKeyCode === keyCode;
414
+ });
415
+ if (triggeredOption) {
416
+ const record = this.getRecord();
417
+ const text = (0, _richText.getTextContent)(record);
418
+ // Only respond to the trigger if the selection is on the start of text or line
419
+ // or if the character before is a space.
420
+ const useTrigger = text.length === 0 || record.start === 0 || text.charAt(record.start - 1) === '\n' || text.charAt(record.start - 1) === ' ';
421
+ if (useTrigger && triggeredOption.onClick) {
422
+ triggeredOption.onClick();
423
+ } else {
424
+ this.insertString(record, triggeredOption.triggerChar);
425
+ }
426
+ }
427
+ }
428
+ suggestionOptions() {
429
+ const {
430
+ areMentionsSupported,
431
+ areXPostsSupported
432
+ } = this.props;
433
+ const allOptions = [{
434
+ supported: areMentionsSupported,
435
+ title: (0, _i18n.__)('Insert mention'),
436
+ onClick: this.handleUserSuggestion,
437
+ triggerChar: '@',
438
+ value: 'mention',
439
+ label: (0, _i18n.__)('Mention'),
440
+ icon: _icons.atSymbol
441
+ }, {
442
+ supported: areXPostsSupported,
443
+ title: (0, _i18n.__)('Insert crosspost'),
444
+ onClick: this.handleXpostSuggestion,
445
+ triggerChar: '+',
446
+ value: 'crosspost',
447
+ label: (0, _i18n.__)('Crosspost'),
448
+ icon: _icons.plus
449
+ }];
450
+ return allOptions.filter(op => op.supported);
451
+ }
452
+ handleSuggestionFunc(suggestionFunction, prefix) {
453
+ return () => {
454
+ const record = this.getRecord();
455
+ suggestionFunction().then(suggestion => {
456
+ this.insertString(record, `${prefix}${suggestion} `);
457
+ }).catch(() => {});
458
+ };
459
+ }
460
+
461
+ /**
462
+ * Handles a paste event from the native Aztec Wrapper.
463
+ *
464
+ * @param {Object} event The paste event which wraps `nativeEvent`.
465
+ */
466
+ onPaste(event) {
467
+ const {
468
+ onPaste,
469
+ onChange
470
+ } = this.props;
471
+ const {
472
+ activeFormats = []
473
+ } = this.state;
474
+ const {
475
+ pastedText,
476
+ pastedHtml,
477
+ files
478
+ } = event.nativeEvent;
479
+ const currentRecord = this.createRecord();
480
+ event.preventDefault();
481
+
482
+ // There is a selection, check if a URL is pasted.
483
+ if (!(0, _richText.isCollapsed)(currentRecord)) {
484
+ const trimmedText = (pastedHtml || pastedText).replace(/<[^>]+>/g, '').trim();
485
+
486
+ // A URL was pasted, turn the selection into a link.
487
+ if ((0, _url.isURL)(trimmedText)) {
488
+ const linkedRecord = (0, _richText.applyFormat)(currentRecord, {
489
+ type: 'a',
490
+ attributes: {
491
+ href: (0, _htmlEntities.decodeEntities)(trimmedText)
492
+ }
493
+ });
494
+ this.value = this.valueToFormat(linkedRecord);
495
+ onChange(this.value);
496
+
497
+ // Allows us to ask for this information when we get a report.
498
+ window.console.log('Created link:\n\n', trimmedText);
499
+ return;
500
+ }
501
+ }
502
+ if (onPaste) {
503
+ onPaste({
504
+ value: currentRecord,
505
+ onChange: this.onFormatChange,
506
+ html: pastedHtml,
507
+ plainText: pastedText,
508
+ files,
509
+ activeFormats
510
+ });
511
+ }
512
+ }
513
+ onFocus() {
514
+ this.isTouched = true;
515
+ const {
516
+ unstableOnFocus,
517
+ onSelectionChange
518
+ } = this.props;
519
+ if (unstableOnFocus) {
520
+ unstableOnFocus();
521
+ }
522
+
523
+ // We know for certain that on focus, the old selection is invalid. It
524
+ // will be recalculated on `selectionchange`.
525
+
526
+ onSelectionChange(this.selectionStart, this.selectionEnd);
527
+ this.lastAztecEventType = 'focus';
528
+ }
529
+ onBlur(event) {
530
+ this.isTouched = false;
531
+
532
+ // Check if value is up to date with latest state of native AztecView.
533
+ if (event.nativeEvent.text && event.nativeEvent.text !== this.props.value) {
534
+ this.onTextUpdate(event);
535
+ }
536
+ if (this.props.onBlur) {
537
+ this.props.onBlur(event);
538
+ }
539
+ this.lastAztecEventType = 'blur';
540
+ }
541
+ onSelectionChange(start, end) {
542
+ const hasChanged = this.selectionStart !== start || this.selectionEnd !== end;
543
+ this.selectionStart = start;
544
+ this.selectionEnd = end;
545
+
546
+ // This is a manual selection change event if onChange was not triggered just before
547
+ // and we did not just trigger a text update
548
+ // `onChange` could be the last event and could have been triggered a long time ago so
549
+ // this approach is not perfectly reliable.
550
+ const isManual = this.lastAztecEventType !== 'input' && this.props.value === this.value;
551
+ if (hasChanged && isManual) {
552
+ const value = this.createRecord();
553
+ const activeFormats = (0, _richText.getActiveFormats)(value);
554
+ this.setState({
555
+ activeFormats
556
+ });
557
+ }
558
+ this.props.onSelectionChange(start, end);
559
+ }
560
+ shouldDropEventFromAztec(event, logText) {
561
+ const shouldDrop = !this.isIOS && event.nativeEvent.eventCount <= this.lastEventCount;
562
+ if (shouldDrop) {
563
+ window.console.log(`Dropping ${logText} from Aztec as its event counter is older than latest sent to the native side. Got ${event.nativeEvent.eventCount} but lastEventCount is ${this.lastEventCount}.`);
564
+ }
565
+ return shouldDrop;
566
+ }
567
+
568
+ /**
569
+ * Determines whether the text input should receive focus after an update.
570
+ * For cases where a RichText with a value is merged with an empty one.
571
+ *
572
+ * @param {Object} prevProps - The previous props of the component.
573
+ * @return {boolean} True if the text input should receive focus, false otherwise.
574
+ */
575
+ shouldFocusTextInputAfterMerge(prevProps) {
576
+ const {
577
+ __unstableIsSelected: isSelected,
578
+ blockIsSelected,
579
+ selectionStart,
580
+ selectionEnd,
581
+ __unstableMobileNoFocusOnMount
582
+ } = this.props;
583
+ const {
584
+ __unstableIsSelected: prevIsSelected,
585
+ blockIsSelected: prevBlockIsSelected
586
+ } = prevProps;
587
+ const noSelectionValues = selectionStart === undefined && selectionEnd === undefined;
588
+ const textInputWasNotFocused = !prevIsSelected && !isSelected;
589
+ return !__unstableMobileNoFocusOnMount && noSelectionValues && textInputWasNotFocused && !prevBlockIsSelected && blockIsSelected;
590
+ }
591
+ onSelectionChangeFromAztec(start, end, text, event) {
592
+ if (this.shouldDropEventFromAztec(event, 'onSelectionChange')) {
593
+ return;
594
+ }
595
+
596
+ // `end` can be less than `start` on iOS
597
+ // Let's fix that here so `rich-text/slice` can work properly.
598
+ const realStart = Math.min(start, end);
599
+ const realEnd = Math.max(start, end);
600
+
601
+ // Check and dicsard stray event, where the text and selection is equal to the ones already cached.
602
+ const contentWithoutRootTag = this.removeRootTagsProducedByAztec(unescapeSpaces(event.nativeEvent.text));
603
+ if (contentWithoutRootTag === this.value && realStart === this.selectionStart && realEnd === this.selectionEnd) {
604
+ return;
605
+ }
606
+ this.comesFromAztec = true;
607
+ this.firedAfterTextChanged = true; // Selection change event always fires after the fact.
608
+
609
+ // Update text before updating selection
610
+ // Make sure there are changes made to the content before upgrading it upward.
611
+ this.onTextUpdate(event);
612
+
613
+ // Aztec can send us selection change events after it has lost focus.
614
+ // For instance the autocorrect feature will complete a partially written
615
+ // word when resigning focus, causing a selection change event.
616
+ // Forwarding this selection change could cause this RichText to regain
617
+ // focus and start a focus loop.
618
+ //
619
+ // See https://github.com/wordpress-mobile/gutenberg-mobile/issues/1696
620
+ if (this.props.__unstableIsSelected) {
621
+ this.onSelectionChange(realStart, realEnd);
622
+ }
623
+ // Update lastEventCount to prevent Aztec from re-rendering the content it just sent.
624
+ this.lastEventCount = event.nativeEvent.eventCount;
625
+ this.lastAztecEventType = 'selection change';
626
+ }
627
+ isEmpty() {
628
+ return (0, _richText.isEmpty)(this.formatToValue(this.props.value));
629
+ }
630
+ formatToValue(value) {
631
+ const {
632
+ preserveWhiteSpace
633
+ } = this.props;
634
+ // Handle deprecated `children` and `node` sources.
635
+ if (Array.isArray(value)) {
636
+ return (0, _richText.create)({
637
+ html: _blocks.childrenBlock.toHTML(value),
638
+ multilineTag: this.multilineTag,
639
+ multilineWrapperTags: this.multilineWrapperTags,
640
+ preserveWhiteSpace
641
+ });
642
+ }
643
+ if (this.props.format === 'string') {
644
+ return (0, _richText.create)({
645
+ html: value,
646
+ multilineTag: this.multilineTag,
647
+ multilineWrapperTags: this.multilineWrapperTags,
648
+ preserveWhiteSpace
649
+ });
650
+ }
651
+
652
+ // Guard for blocks passing `null` in onSplit callbacks. May be removed
653
+ // if onSplit is revised to not pass a `null` value.
654
+ if (value === null) {
655
+ return (0, _richText.create)();
656
+ }
657
+ return value;
658
+ }
659
+ manipulateEventCounterToForceNativeToRefresh() {
660
+ if (this.isIOS) {
661
+ this.lastEventCount = undefined;
662
+ return;
663
+ }
664
+ if (typeof this.lastEventCount !== 'undefined') {
665
+ this.lastEventCount += 100; // bump by a hundred, hopefully native hasn't bombarded the JS side in the meantime.
666
+ } // no need to bump when 'undefined' as native side won't receive the key when the value is undefined, and that will cause force updating anyway,
667
+ // see https://github.com/WordPress/gutenberg/blob/82e578dcc75e67891c750a41a04c1e31994192fc/packages/react-native-aztec/android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecManager.java#L213-L215
668
+ }
669
+
670
+ shouldComponentUpdate(nextProps, nextState) {
671
+ if (nextProps.tagName !== this.props.tagName || nextProps.reversed !== this.props.reversed || nextProps.start !== this.props.start) {
672
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
673
+ this.value = undefined;
674
+ return true;
675
+ }
676
+
677
+ // TODO: Please re-introduce the check to avoid updating the content right after an `onChange` call.
678
+ // It was removed in https://github.com/WordPress/gutenberg/pull/12417 to fix undo/redo problem.
679
+
680
+ // If the component is changed React side (undo/redo/merging/splitting/custom text actions)
681
+ // we need to make sure the native is updated as well.
682
+
683
+ // Also, don't trust the "this.lastContent" as on Android, incomplete text events arrive
684
+ // with only some of the text, while the virtual keyboard's suggestion system does its magic.
685
+ // ** compare with this.lastContent for optimizing performance by not forcing Aztec with text it already has
686
+ // , but compare with props.value to not lose "half word" text because of Android virtual keyb autosuggestion behavior
687
+ if (typeof nextProps.value !== 'undefined' && typeof this.props.value !== 'undefined' && (!this.comesFromAztec || !this.firedAfterTextChanged) && nextProps.value !== this.props.value) {
688
+ // Gutenberg seems to try to mirror the caret state even on events that only change the content so,
689
+ // let's force caret update if state has selection set.
690
+ if (typeof nextProps.selectionStart !== 'undefined' && typeof nextProps.selectionEnd !== 'undefined') {
691
+ this.needsSelectionUpdate = true;
692
+ }
693
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
694
+ }
695
+
696
+ if (!this.comesFromAztec) {
697
+ if (typeof nextProps.selectionStart !== 'undefined' && typeof nextProps.selectionEnd !== 'undefined' && nextProps.selectionStart !== this.props.selectionStart && nextProps.selectionStart !== this.selectionStart && nextProps.__unstableIsSelected) {
698
+ this.needsSelectionUpdate = true;
699
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
700
+ }
701
+
702
+ // For font size changes from a prop value a force refresh
703
+ // is needed without the selection update.
704
+ if (nextProps?.fontSize !== this.props?.fontSize) {
705
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
706
+ }
707
+
708
+ if (nextProps?.style?.fontSize !== this.props?.style?.fontSize && nextState.currentFontSize !== this.state.currentFontSize || nextState.currentFontSize !== this.state.currentFontSize || nextProps?.style?.lineHeight !== this.props?.style?.lineHeight) {
709
+ this.needsSelectionUpdate = true;
710
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
711
+ }
712
+ }
713
+
714
+ return true;
715
+ }
716
+ componentDidMount() {
717
+ // Request focus if wrapping block is selected and parent hasn't inhibited the focus request. This method of focusing
718
+ // is trying to implement the web-side counterpart of BlockList's `focusTabbable` where the BlockList is focusing an
719
+ // inputbox by searching the DOM. We don't have the DOM in RN so, using the combination of blockIsSelected and __unstableMobileNoFocusOnMount
720
+ // to determine if we should focus the RichText.
721
+ if (this.props.blockIsSelected && !this.props.__unstableMobileNoFocusOnMount) {
722
+ this._editor.focus();
723
+ this.onSelectionChange(this.props.selectionStart || 0, this.props.selectionEnd || 0);
724
+ }
725
+ }
726
+ componentWillUnmount() {
727
+ if (this._editor.isFocused()) {
728
+ this._editor.blur();
729
+ }
730
+ }
731
+ componentDidUpdate(prevProps) {
732
+ const {
733
+ style,
734
+ tagName
735
+ } = this.props;
736
+ const {
737
+ currentFontSize
738
+ } = this.state;
739
+ if (this.props.value !== this.value) {
740
+ this.value = this.props.value;
741
+ }
742
+ const {
743
+ __unstableIsSelected: prevIsSelected
744
+ } = prevProps;
745
+ const {
746
+ __unstableIsSelected: isSelected
747
+ } = this.props;
748
+ if (isSelected && !prevIsSelected) {
749
+ this._editor.focus();
750
+ // Update selection props explicitly when component is selected as Aztec won't call onSelectionChange
751
+ // if its internal value hasn't change. When created, default value is 0, 0.
752
+ this.onSelectionChange(this.props.selectionStart || 0, this.props.selectionEnd || 0);
753
+ } else if (this.shouldFocusTextInputAfterMerge(prevProps)) {
754
+ var _this$value$length;
755
+ // Since this is happening when merging blocks, the selection should be at the last character position.
756
+ // As a fallback the internal selectionEnd value is used.
757
+ const lastCharacterPosition = (_this$value$length = this.value?.length) !== null && _this$value$length !== void 0 ? _this$value$length : this.selectionEnd;
758
+ this._editor.focus();
759
+ this.props.onSelectionChange(lastCharacterPosition, lastCharacterPosition);
760
+ } else if (!isSelected && prevIsSelected) {
761
+ this._editor.blur();
762
+ }
763
+
764
+ // For font size values changes from the font size picker
765
+ // we compare previous values to refresh the selected font size,
766
+ // this is also used when the tag name changes
767
+ // e.g Heading block and a level change like h1->h2.
768
+ const currentFontSizeStyle = this.getParsedFontSize(style?.fontSize);
769
+ const prevFontSizeStyle = this.getParsedFontSize(prevProps?.style?.fontSize);
770
+ const isDifferentTag = prevProps.tagName !== tagName;
771
+ if (currentFontSize && (currentFontSizeStyle || prevFontSizeStyle) && currentFontSizeStyle !== currentFontSize || isDifferentTag) {
772
+ this.setState({
773
+ currentFontSize: this.getFontSize(this.props)
774
+ });
775
+ }
776
+ }
777
+ getHtmlToRender(record, tagName) {
778
+ // Save back to HTML from React tree.
779
+ let value = this.valueToFormat(record);
780
+ if (value === undefined) {
781
+ this.manipulateEventCounterToForceNativeToRefresh(); // force a refresh on the native side
782
+ value = '';
783
+ }
784
+ // On android if content is empty we need to send no content or else the placeholder will not show.
785
+ if (!this.isIOS && (value === '' || value === EMPTY_PARAGRAPH_TAGS)) {
786
+ return '';
787
+ }
788
+ if (tagName) {
789
+ let extraAttributes = ``;
790
+ if (tagName === `ol`) {
791
+ if (this.props.reversed) {
792
+ extraAttributes += ` reversed`;
793
+ }
794
+ if (this.props.start) {
795
+ extraAttributes += ` start=${this.props.start}`;
796
+ }
797
+ }
798
+ value = `<${tagName}${extraAttributes}>${value}</${tagName}>`;
799
+ }
800
+ return value;
801
+ }
802
+ getEditableProps() {
803
+ return {
804
+ // Overridable props.
805
+ style: {},
806
+ className: 'rich-text',
807
+ onKeyDown: () => null
808
+ };
809
+ }
810
+ getParsedFontSize(fontSize) {
811
+ var _getPxFromCssUnit;
812
+ const {
813
+ height,
814
+ width
815
+ } = _reactNative.Dimensions.get('window');
816
+ const cssUnitOptions = {
817
+ height,
818
+ width,
819
+ fontSize: DEFAULT_FONT_SIZE
820
+ };
821
+ if (!fontSize) {
822
+ return fontSize;
823
+ }
824
+ const selectedPxValue = (_getPxFromCssUnit = (0, _blockEditor.getPxFromCssUnit)(fontSize, cssUnitOptions)) !== null && _getPxFromCssUnit !== void 0 ? _getPxFromCssUnit : DEFAULT_FONT_SIZE;
825
+ return parseFloat(selectedPxValue);
826
+ }
827
+ getFontSize(props) {
828
+ const {
829
+ baseGlobalStyles,
830
+ tagName,
831
+ fontSize,
832
+ style
833
+ } = props;
834
+ const tagNameFontSize = baseGlobalStyles?.elements?.[tagName]?.typography?.fontSize;
835
+ let newFontSize = DEFAULT_FONT_SIZE;
836
+
837
+ // Disables line-height rendering for pre elements until we fix some issues with AztecAndroid.
838
+ if (tagName === 'pre' && !this.isIOS) {
839
+ return undefined;
840
+ }
841
+
842
+ // For block-based themes, get the default editor font size.
843
+ if (baseGlobalStyles?.typography?.fontSize && tagName === 'p') {
844
+ newFontSize = baseGlobalStyles?.typography?.fontSize;
845
+ }
846
+
847
+ // For block-based themes, get the default element font size
848
+ // e.g h1, h2.
849
+ if (tagNameFontSize) {
850
+ newFontSize = tagNameFontSize;
851
+ }
852
+
853
+ // For font size values provided from the styles,
854
+ // usually from values set from the font size picker.
855
+ if (style?.fontSize) {
856
+ newFontSize = style.fontSize;
857
+ }
858
+
859
+ // Fall-back to a font size provided from its props (if there's any)
860
+ // and there are no other default values to use.
861
+ if (fontSize && !tagNameFontSize && !style?.fontSize) {
862
+ newFontSize = fontSize;
863
+ }
864
+
865
+ // We need to always convert to px units because the selected value
866
+ // could be coming from the web where it could be stored as a different unit.
867
+ const selectedPxValue = this.getParsedFontSize(newFontSize);
868
+ return selectedPxValue;
869
+ }
870
+ getLineHeight() {
871
+ const {
872
+ baseGlobalStyles,
873
+ tagName,
874
+ lineHeight,
875
+ style
876
+ } = this.props;
877
+ const tagNameLineHeight = baseGlobalStyles?.elements?.[tagName]?.typography?.lineHeight;
878
+ let newLineHeight;
879
+
880
+ // Disables line-height rendering for pre elements until we fix some issues with AztecAndroid.
881
+ if (tagName === 'pre' && !this.isIOS) {
882
+ return undefined;
883
+ }
884
+ if (!this.getIsBlockBasedTheme()) {
885
+ return;
886
+ }
887
+
888
+ // For block-based themes, get the default editor line height.
889
+ if (baseGlobalStyles?.typography?.lineHeight && tagName === 'p') {
890
+ newLineHeight = parseFloat(baseGlobalStyles?.typography?.lineHeight);
891
+ }
892
+
893
+ // For block-based themes, get the default element line height
894
+ // e.g h1, h2.
895
+ if (tagNameLineHeight) {
896
+ newLineHeight = parseFloat(tagNameLineHeight);
897
+ }
898
+
899
+ // For line height values provided from the styles,
900
+ // usually from values set from the line height picker.
901
+ if (style?.lineHeight) {
902
+ newLineHeight = parseFloat(style.lineHeight);
903
+ }
904
+
905
+ // Fall-back to a line height provided from its props (if there's any)
906
+ // and there are no other default values to use.
907
+ if (lineHeight && !tagNameLineHeight && !style?.lineHeight) {
908
+ newLineHeight = lineHeight;
909
+ }
910
+
911
+ // Check the final value is not over the minimum supported value.
912
+ if (newLineHeight && newLineHeight < MIN_LINE_HEIGHT) {
913
+ newLineHeight = MIN_LINE_HEIGHT;
914
+ }
915
+
916
+ // Until we parse CSS values correctly, avoid passing NaN values to Aztec
917
+ if (isNaN(newLineHeight)) {
918
+ return undefined;
919
+ }
920
+ return newLineHeight;
921
+ }
922
+ getIsBlockBasedTheme() {
923
+ const {
924
+ baseGlobalStyles
925
+ } = this.props;
926
+ return baseGlobalStyles && Object.entries(baseGlobalStyles).length !== 0;
927
+ }
928
+ getBlockUseDefaultFont() {
929
+ // For block-based themes it enables using the defaultFont
930
+ // in Aztec for iOS so it allows customizing the font size
931
+ // for the Preformatted/Code and Heading blocks.
932
+ if (!this.isIOS) {
933
+ return;
934
+ }
935
+ const {
936
+ tagName
937
+ } = this.props;
938
+ const isBlockBasedTheme = this.getIsBlockBasedTheme();
939
+ const tagsToMatch = /pre|h([1-6])$/gm;
940
+ return isBlockBasedTheme && tagsToMatch.test(tagName);
941
+ }
942
+ getLinkTextColor(defaultColor) {
943
+ const {
944
+ style
945
+ } = this.props;
946
+ const customColor = style?.linkColor && (0, _colord.colord)(style.linkColor);
947
+ return customColor && customColor.isValid() ? customColor.toHex() : defaultColor;
948
+ }
949
+ getPlaceholderTextColor() {
950
+ var _ref, _ref2;
951
+ const {
952
+ baseGlobalStyles,
953
+ getStylesFromColorScheme,
954
+ placeholderTextColor,
955
+ style
956
+ } = this.props;
957
+
958
+ // Default placeholder text color.
959
+ const placeholderStyle = getStylesFromColorScheme(_style.default.richTextPlaceholder, _style.default.richTextPlaceholderDark);
960
+ const {
961
+ color: defaultPlaceholderTextColor
962
+ } = placeholderStyle;
963
+ // Custom 63% opacity for theme and inherited colors.
964
+ const placeholderOpacity = 'A1';
965
+
966
+ // Determine inherited placeholder color if available.
967
+ const inheritPlaceholderColor = style?.placeholderColor ? `${style.placeholderColor}${placeholderOpacity}` : undefined;
968
+
969
+ // If using block-based themes, derive the placeholder color from global styles.
970
+ const globalStylesPlaceholderColor = baseGlobalStyles?.color?.text ? `${baseGlobalStyles.color.text}${placeholderOpacity}` : undefined;
971
+ return (_ref = (_ref2 = inheritPlaceholderColor !== null && inheritPlaceholderColor !== void 0 ? inheritPlaceholderColor : placeholderTextColor) !== null && _ref2 !== void 0 ? _ref2 : globalStylesPlaceholderColor) !== null && _ref !== void 0 ? _ref : defaultPlaceholderTextColor;
972
+ }
973
+ render() {
974
+ const {
975
+ tagName,
976
+ style,
977
+ __unstableIsSelected: isSelected,
978
+ children,
979
+ getStylesFromColorScheme,
980
+ minWidth,
981
+ maxWidth,
982
+ formatTypes,
983
+ parentBlockStyles,
984
+ accessibilityLabel,
985
+ disableEditingMenu = false,
986
+ baseGlobalStyles,
987
+ selectionStart,
988
+ selectionEnd,
989
+ disableSuggestions,
990
+ containerWidth
991
+ } = this.props;
992
+ const {
993
+ currentFontSize
994
+ } = this.state;
995
+ const record = this.getRecord();
996
+ const html = this.getHtmlToRender(record, tagName);
997
+ const editableProps = this.getEditableProps();
998
+ const blockUseDefaultFont = this.getBlockUseDefaultFont();
999
+ const fontSize = currentFontSize;
1000
+ const lineHeight = this.getLineHeight();
1001
+ const {
1002
+ color: defaultColor,
1003
+ textDecorationColor: defaultTextDecorationColor,
1004
+ fontFamily: defaultFontFamily
1005
+ } = getStylesFromColorScheme(_style.default.richText, _style.default.richTextDark);
1006
+ const linkTextColor = this.getLinkTextColor(defaultTextDecorationColor);
1007
+ const currentSelectionStart = selectionStart !== null && selectionStart !== void 0 ? selectionStart : 0;
1008
+ const currentSelectionEnd = selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : 0;
1009
+ let selection = null;
1010
+ if (this.needsSelectionUpdate) {
1011
+ this.needsSelectionUpdate = false;
1012
+ selection = {
1013
+ start: currentSelectionStart,
1014
+ end: currentSelectionEnd
1015
+ };
1016
+
1017
+ // On AztecAndroid, setting the caret to an out-of-bounds position will crash the editor so, let's check for some cases.
1018
+ if (!this.isIOS) {
1019
+ // The following regular expression is used in Aztec here:
1020
+ // https://github.com/wordpress-mobile/AztecEditor-Android/blob/b1fad439d56fa6d4aa0b78526fef355c59d00dd3/aztec/src/main/kotlin/org/wordpress/aztec/AztecParser.kt#L656
1021
+ const brBeforeParaMatches = html.match(/(<br>)+<\/p>$/g);
1022
+ if (brBeforeParaMatches) {
1023
+ console.warn('Oops, BR tag(s) at the end of content. Aztec will remove them, adapting the selection...');
1024
+ const count = (brBeforeParaMatches[0].match(/br/g) || []).length;
1025
+ if (count > 0) {
1026
+ let newSelectionStart = currentSelectionStart - count;
1027
+ if (newSelectionStart < 0) {
1028
+ newSelectionStart = 0;
1029
+ }
1030
+ let newSelectionEnd = currentSelectionEnd - count;
1031
+ if (newSelectionEnd < 0) {
1032
+ newSelectionEnd = 0;
1033
+ }
1034
+ selection = {
1035
+ start: newSelectionStart,
1036
+ end: newSelectionEnd
1037
+ };
1038
+ }
1039
+ }
1040
+ }
1041
+ }
1042
+ if (this.comesFromAztec) {
1043
+ this.comesFromAztec = false;
1044
+ this.firedAfterTextChanged = false;
1045
+ }
1046
+
1047
+ // Logic below assures that `RichText` width will always have equal value when container is almost fully filled.
1048
+ const width = maxWidth && this.state.width && maxWidth - this.state.width < 10 ? maxWidth : this.state.width;
1049
+ const containerStyles = [style?.padding && style?.backgroundColor && {
1050
+ padding: style.padding,
1051
+ backgroundColor: style.backgroundColor
1052
+ }, containerWidth && {
1053
+ width: containerWidth
1054
+ }];
1055
+ const defaultSelectionColor = getStylesFromColorScheme(_style.default['rich-text-selection'], _style.default['rich-text-selection--dark']).color;
1056
+ const selectionColor = getSelectionColor(this.props.selectionColor, defaultSelectionColor, baseGlobalStyles, this.getIsBlockBasedTheme());
1057
+ const EditableView = props => {
1058
+ this.customEditableOnKeyDown = props?.onKeyDown;
1059
+ return (0, _react.createElement)(_react.Fragment, null);
1060
+ };
1061
+ return (0, _react.createElement)(_reactNative.View, {
1062
+ style: containerStyles
1063
+ }, children && children({
1064
+ isSelected,
1065
+ value: record,
1066
+ onChange: this.onFormatChange,
1067
+ onFocus: () => {},
1068
+ editableProps,
1069
+ editableTagName: EditableView
1070
+ }), (0, _react.createElement)(_reactNativeAztec.default, {
1071
+ accessibilityLabel: accessibilityLabel,
1072
+ ref: ref => {
1073
+ this._editor = ref;
1074
+ if (this.props.setRef) {
1075
+ this.props.setRef(ref);
1076
+ }
1077
+ },
1078
+ style: {
1079
+ backgroundColor: _style.default.richText.backgroundColor,
1080
+ ...style,
1081
+ ...(this.isIOS && minWidth && maxWidth ? {
1082
+ width
1083
+ } : {
1084
+ maxWidth
1085
+ }),
1086
+ minHeight: this.state.height
1087
+ },
1088
+ blockUseDefaultFont: blockUseDefaultFont,
1089
+ text: {
1090
+ text: html,
1091
+ eventCount: this.lastEventCount,
1092
+ selection,
1093
+ linkTextColor,
1094
+ tag: tagName
1095
+ },
1096
+ placeholder: this.props.placeholder,
1097
+ placeholderTextColor: this.getPlaceholderTextColor(),
1098
+ deleteEnter: this.props.deleteEnter,
1099
+ onChange: this.onChangeFromAztec,
1100
+ onFocus: this.onFocus,
1101
+ onBlur: this.onBlur,
1102
+ onKeyDown: this.onKeyDown,
1103
+ triggerKeyCodes: disableEditingMenu ? [] : this.suggestionOptions().map(op => op.triggerChar),
1104
+ onPaste: this.onPaste,
1105
+ activeFormats: this.getActiveFormatNames(record),
1106
+ onContentSizeChange: this.onContentSizeChange,
1107
+ onSelectionChange: this.onSelectionChangeFromAztec,
1108
+ blockType: {
1109
+ tag: tagName
1110
+ },
1111
+ color: style && style.color || parentBlockStyles && parentBlockStyles.color || baseGlobalStyles && baseGlobalStyles?.color?.text || defaultColor,
1112
+ maxImagesWidth: 200,
1113
+ fontFamily: this.props.fontFamily || defaultFontFamily,
1114
+ fontSize: fontSize,
1115
+ lineHeight: lineHeight,
1116
+ fontWeight: this.props.fontWeight,
1117
+ fontStyle: this.props.fontStyle,
1118
+ disableEditingMenu: disableEditingMenu,
1119
+ isMultiline: this.isMultiline,
1120
+ textAlign: this.props.textAlign,
1121
+ ...(this.isIOS ? {
1122
+ maxWidth
1123
+ } : {}),
1124
+ minWidth: minWidth,
1125
+ id: this.props.id,
1126
+ selectionColor: selectionColor,
1127
+ disableAutocorrection: this.props.disableAutocorrection
1128
+ }), isSelected && (0, _react.createElement)(_react.Fragment, null, (0, _react.createElement)(_formatEdit.default, {
1129
+ forwardedRef: this._editor,
1130
+ formatTypes: formatTypes,
1131
+ value: record,
1132
+ onChange: this.onFormatChange,
1133
+ onFocus: () => {}
1134
+ }), !disableSuggestions && (0, _react.createElement)(_blockEditor.BlockFormatControls, null, (0, _react.createElement)(_toolbarButtonWithOptions.default, {
1135
+ options: this.suggestionOptions()
1136
+ }))));
1137
+ }
1138
+ }
1139
+ exports.RichText = RichText;
1140
+ RichText.defaultProps = {
1141
+ format: 'string',
1142
+ value: '',
1143
+ tagName: 'div'
1144
+ };
1145
+ const withFormatTypes = WrappedComponent => props => {
1146
+ const {
1147
+ clientId,
1148
+ identifier,
1149
+ withoutInteractiveFormatting,
1150
+ allowedFormats
1151
+ } = props;
1152
+ const {
1153
+ formatTypes
1154
+ } = (0, _useFormatTypes.useFormatTypes)({
1155
+ clientId,
1156
+ identifier,
1157
+ withoutInteractiveFormatting,
1158
+ allowedFormats
1159
+ });
1160
+ return (0, _react.createElement)(WrappedComponent, {
1161
+ ...props,
1162
+ formatTypes: formatTypes
1163
+ });
1164
+ };
1165
+ var _default = (0, _compose.compose)([(0, _data.withSelect)((select, {
1166
+ clientId
1167
+ }) => {
1168
+ const {
1169
+ getBlockParents,
1170
+ getBlock,
1171
+ getSettings
1172
+ } = select('core/block-editor');
1173
+ const parents = getBlockParents(clientId, true);
1174
+ const parentBlock = parents ? getBlock(parents[0]) : undefined;
1175
+ const parentBlockStyles = parentBlock?.attributes?.childrenStyles;
1176
+ const settings = getSettings();
1177
+ const baseGlobalStyles = settings?.__experimentalGlobalStylesBaseStyles;
1178
+ const colorPalettes = settings?.__experimentalFeatures?.color?.palette;
1179
+ const colorPalette = colorPalettes ? flatColorPalettes(colorPalettes) : settings?.colors;
1180
+ return {
1181
+ areMentionsSupported: settings?.capabilities?.mentions === true,
1182
+ areXPostsSupported: settings?.capabilities?.xposts === true,
1183
+ parentBlockStyles,
1184
+ baseGlobalStyles,
1185
+ colorPalette
1186
+ };
1187
+ }), _compose.withPreferredColorScheme, withFormatTypes])(RichText);
1188
+ exports.default = _default;
1189
+ //# sourceMappingURL=index.native.js.map