@pega/cosmos-react-rte 9.0.0-build.9.9 → 9.0.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 (191) hide show
  1. package/lib/components/DynamicContentEditor/DynamicContentEditor.d.ts +4 -2
  2. package/lib/components/DynamicContentEditor/DynamicContentEditor.d.ts.map +1 -1
  3. package/lib/components/DynamicContentEditor/DynamicContentEditor.js +64 -59
  4. package/lib/components/DynamicContentEditor/DynamicContentEditor.js.map +1 -1
  5. package/lib/components/Editor/Editor.context.d.ts +6 -6
  6. package/lib/components/Editor/Editor.context.d.ts.map +1 -1
  7. package/lib/components/Editor/Editor.context.js +1 -1
  8. package/lib/components/Editor/Editor.context.js.map +1 -1
  9. package/lib/components/Editor/Editor.d.ts +1 -10
  10. package/lib/components/Editor/Editor.d.ts.map +1 -1
  11. package/lib/components/Editor/Editor.js +301 -490
  12. package/lib/components/Editor/Editor.js.map +1 -1
  13. package/lib/components/Editor/Editor.styles.d.ts +37 -7
  14. package/lib/components/Editor/Editor.styles.d.ts.map +1 -1
  15. package/lib/components/Editor/Editor.styles.js +60 -30
  16. package/lib/components/Editor/Editor.styles.js.map +1 -1
  17. package/lib/components/Editor/Editor.test-ids.d.ts +2 -1
  18. package/lib/components/Editor/Editor.test-ids.d.ts.map +1 -1
  19. package/lib/components/Editor/Editor.test-ids.js +2 -0
  20. package/lib/components/Editor/Editor.test-ids.js.map +1 -1
  21. package/lib/components/Editor/Editor.types.d.ts +34 -14
  22. package/lib/components/Editor/Editor.types.d.ts.map +1 -1
  23. package/lib/components/Editor/Editor.types.js.map +1 -1
  24. package/lib/components/Editor/IframeTiptapEditor.d.ts +30 -0
  25. package/lib/components/Editor/IframeTiptapEditor.d.ts.map +1 -0
  26. package/lib/components/Editor/IframeTiptapEditor.js +695 -0
  27. package/lib/components/Editor/IframeTiptapEditor.js.map +1 -0
  28. package/lib/components/Editor/ImageActionButtons.d.ts +20 -0
  29. package/lib/components/Editor/ImageActionButtons.d.ts.map +1 -0
  30. package/lib/components/Editor/ImageActionButtons.js +84 -0
  31. package/lib/components/Editor/ImageActionButtons.js.map +1 -0
  32. package/lib/components/Editor/ImageEditDialog.d.ts +17 -0
  33. package/lib/components/Editor/ImageEditDialog.d.ts.map +1 -0
  34. package/lib/components/Editor/ImageEditDialog.js +90 -0
  35. package/lib/components/Editor/ImageEditDialog.js.map +1 -0
  36. package/lib/components/Editor/TableCellMenu.d.ts +35 -0
  37. package/lib/components/Editor/TableCellMenu.d.ts.map +1 -0
  38. package/lib/components/Editor/TableCellMenu.js +120 -0
  39. package/lib/components/Editor/TableCellMenu.js.map +1 -0
  40. package/lib/components/Editor/Toolbar/AIRewriteButton.d.ts +17 -0
  41. package/lib/components/Editor/Toolbar/AIRewriteButton.d.ts.map +1 -0
  42. package/lib/components/Editor/Toolbar/AIRewriteButton.js +79 -0
  43. package/lib/components/Editor/Toolbar/AIRewriteButton.js.map +1 -0
  44. package/lib/components/Editor/Toolbar/AlignmentSelect.d.ts +8 -0
  45. package/lib/components/Editor/Toolbar/AlignmentSelect.d.ts.map +1 -0
  46. package/lib/components/Editor/Toolbar/AlignmentSelect.js +137 -0
  47. package/lib/components/Editor/Toolbar/AlignmentSelect.js.map +1 -0
  48. package/lib/components/Editor/Toolbar/AnchorButton.d.ts +3 -4
  49. package/lib/components/Editor/Toolbar/AnchorButton.d.ts.map +1 -1
  50. package/lib/components/Editor/Toolbar/AnchorButton.js +156 -82
  51. package/lib/components/Editor/Toolbar/AnchorButton.js.map +1 -1
  52. package/lib/components/Editor/Toolbar/ColorPickerButton.d.ts +9 -0
  53. package/lib/components/Editor/Toolbar/ColorPickerButton.d.ts.map +1 -0
  54. package/lib/components/Editor/Toolbar/ColorPickerButton.js +190 -0
  55. package/lib/components/Editor/Toolbar/ColorPickerButton.js.map +1 -0
  56. package/lib/components/Editor/Toolbar/FontFamilySelect.d.ts +8 -0
  57. package/lib/components/Editor/Toolbar/FontFamilySelect.d.ts.map +1 -0
  58. package/lib/components/Editor/Toolbar/FontFamilySelect.js +150 -0
  59. package/lib/components/Editor/Toolbar/FontFamilySelect.js.map +1 -0
  60. package/lib/components/Editor/Toolbar/FontSizeSelect.d.ts +8 -0
  61. package/lib/components/Editor/Toolbar/FontSizeSelect.d.ts.map +1 -0
  62. package/lib/components/Editor/Toolbar/FontSizeSelect.js +145 -0
  63. package/lib/components/Editor/Toolbar/FontSizeSelect.js.map +1 -0
  64. package/lib/components/Editor/Toolbar/ImageButton.d.ts +5 -5
  65. package/lib/components/Editor/Toolbar/ImageButton.d.ts.map +1 -1
  66. package/lib/components/Editor/Toolbar/ImageButton.js +131 -18
  67. package/lib/components/Editor/Toolbar/ImageButton.js.map +1 -1
  68. package/lib/components/Editor/Toolbar/SourceCodeButton.d.ts +8 -0
  69. package/lib/components/Editor/Toolbar/SourceCodeButton.d.ts.map +1 -0
  70. package/lib/components/Editor/Toolbar/SourceCodeButton.js +49 -0
  71. package/lib/components/Editor/Toolbar/SourceCodeButton.js.map +1 -0
  72. package/lib/components/Editor/Toolbar/TableButton.d.ts +8 -0
  73. package/lib/components/Editor/Toolbar/TableButton.d.ts.map +1 -0
  74. package/lib/components/Editor/Toolbar/TableButton.js +291 -0
  75. package/lib/components/Editor/Toolbar/TableButton.js.map +1 -0
  76. package/lib/components/Editor/Toolbar/TextSelect.d.ts +4 -5
  77. package/lib/components/Editor/Toolbar/TextSelect.d.ts.map +1 -1
  78. package/lib/components/Editor/Toolbar/TextSelect.js +61 -30
  79. package/lib/components/Editor/Toolbar/TextSelect.js.map +1 -1
  80. package/lib/components/Editor/Toolbar/Toolbar.d.ts +17 -6
  81. package/lib/components/Editor/Toolbar/Toolbar.d.ts.map +1 -1
  82. package/lib/components/Editor/Toolbar/Toolbar.js +169 -47
  83. package/lib/components/Editor/Toolbar/Toolbar.js.map +1 -1
  84. package/lib/components/Editor/Toolbar/Toolbar.test-ids.d.ts +2 -2
  85. package/lib/components/Editor/Toolbar/Toolbar.test-ids.d.ts.map +1 -1
  86. package/lib/components/Editor/Toolbar/Toolbar.test-ids.js +17 -1
  87. package/lib/components/Editor/Toolbar/Toolbar.test-ids.js.map +1 -1
  88. package/lib/components/Editor/Toolbar/WordCount.d.ts +8 -0
  89. package/lib/components/Editor/Toolbar/WordCount.d.ts.map +1 -0
  90. package/lib/components/Editor/Toolbar/WordCount.js +31 -0
  91. package/lib/components/Editor/Toolbar/WordCount.js.map +1 -0
  92. package/lib/components/Editor/extensions/FontSize.d.ts +21 -0
  93. package/lib/components/Editor/extensions/FontSize.d.ts.map +1 -0
  94. package/lib/components/Editor/extensions/FontSize.js +42 -0
  95. package/lib/components/Editor/extensions/FontSize.js.map +1 -0
  96. package/lib/components/Editor/extensions/PreserveDiv.d.ts +13 -0
  97. package/lib/components/Editor/extensions/PreserveDiv.d.ts.map +1 -0
  98. package/lib/components/Editor/extensions/PreserveDiv.js +73 -0
  99. package/lib/components/Editor/extensions/PreserveDiv.js.map +1 -0
  100. package/lib/components/Editor/extensions/TableCellSelection.d.ts +4 -0
  101. package/lib/components/Editor/extensions/TableCellSelection.d.ts.map +1 -0
  102. package/lib/components/Editor/extensions/TableCellSelection.js +53 -0
  103. package/lib/components/Editor/extensions/TableCellSelection.js.map +1 -0
  104. package/lib/components/Editor/extensions/TextIndent.d.ts +22 -0
  105. package/lib/components/Editor/extensions/TextIndent.d.ts.map +1 -0
  106. package/lib/components/Editor/extensions/TextIndent.js +137 -0
  107. package/lib/components/Editor/extensions/TextIndent.js.map +1 -0
  108. package/lib/components/Editor/hooks/useCloseOnEditorClick.d.ts +5 -0
  109. package/lib/components/Editor/hooks/useCloseOnEditorClick.d.ts.map +1 -0
  110. package/lib/components/Editor/hooks/useCloseOnEditorClick.js +18 -0
  111. package/lib/components/Editor/hooks/useCloseOnEditorClick.js.map +1 -0
  112. package/lib/components/Editor/hooks/useEscapeKey.d.ts +4 -0
  113. package/lib/components/Editor/hooks/useEscapeKey.d.ts.map +1 -0
  114. package/lib/components/Editor/hooks/useEscapeKey.js +24 -0
  115. package/lib/components/Editor/hooks/useEscapeKey.js.map +1 -0
  116. package/lib/components/Editor/hooks/useIframeSetup.d.ts +54 -0
  117. package/lib/components/Editor/hooks/useIframeSetup.d.ts.map +1 -0
  118. package/lib/components/Editor/hooks/useIframeSetup.js +284 -0
  119. package/lib/components/Editor/hooks/useIframeSetup.js.map +1 -0
  120. package/lib/components/Editor/hooks/useImageActions.d.ts +19 -0
  121. package/lib/components/Editor/hooks/useImageActions.d.ts.map +1 -0
  122. package/lib/components/Editor/hooks/useImageActions.js +198 -0
  123. package/lib/components/Editor/hooks/useImageActions.js.map +1 -0
  124. package/lib/components/Editor/hooks/useTableCellMenu.d.ts +22 -0
  125. package/lib/components/Editor/hooks/useTableCellMenu.d.ts.map +1 -0
  126. package/lib/components/Editor/hooks/useTableCellMenu.js +120 -0
  127. package/lib/components/Editor/hooks/useTableCellMenu.js.map +1 -0
  128. package/lib/components/Editor/iframeContentStyles.d.ts +10 -0
  129. package/lib/components/Editor/iframeContentStyles.d.ts.map +1 -0
  130. package/lib/components/Editor/iframeContentStyles.js +162 -0
  131. package/lib/components/Editor/iframeContentStyles.js.map +1 -0
  132. package/lib/components/Editor/index.d.ts +2 -0
  133. package/lib/components/Editor/index.d.ts.map +1 -1
  134. package/lib/components/Editor/index.js +1 -0
  135. package/lib/components/Editor/index.js.map +1 -1
  136. package/lib/components/Editor/sanitize.d.ts +3 -0
  137. package/lib/components/Editor/sanitize.d.ts.map +1 -0
  138. package/lib/components/Editor/sanitize.js +11 -0
  139. package/lib/components/Editor/sanitize.js.map +1 -0
  140. package/lib/components/Editor/utils/htmlPlaceholder.d.ts +69 -0
  141. package/lib/components/Editor/utils/htmlPlaceholder.d.ts.map +1 -0
  142. package/lib/components/Editor/utils/htmlPlaceholder.js +154 -0
  143. package/lib/components/Editor/utils/htmlPlaceholder.js.map +1 -0
  144. package/lib/components/RichTextEditor/DecoratorComponents/Table.d.ts +6 -4
  145. package/lib/components/RichTextEditor/DecoratorComponents/Table.d.ts.map +1 -1
  146. package/lib/components/RichTextEditor/DecoratorComponents/Table.js +10 -8
  147. package/lib/components/RichTextEditor/DecoratorComponents/Table.js.map +1 -1
  148. package/lib/components/RichTextEditor/RichTextEditor.d.ts.map +1 -1
  149. package/lib/components/RichTextEditor/RichTextEditor.js +15 -2
  150. package/lib/components/RichTextEditor/RichTextEditor.js.map +1 -1
  151. package/lib/components/RichTextEditor/RichTextEditor.styles.d.ts +5 -5
  152. package/lib/components/RichTextEditor/RichTextEditor.styles.d.ts.map +1 -1
  153. package/lib/components/RichTextEditor/RichTextEditor.styles.js +3 -5
  154. package/lib/components/RichTextEditor/RichTextEditor.styles.js.map +1 -1
  155. package/lib/components/RichTextEditor/RichTextEditor.types.d.ts +5 -0
  156. package/lib/components/RichTextEditor/RichTextEditor.types.d.ts.map +1 -1
  157. package/lib/components/RichTextEditor/RichTextEditor.types.js.map +1 -1
  158. package/lib/components/RichTextEditor/RichTextViewer.d.ts.map +1 -1
  159. package/lib/components/RichTextEditor/RichTextViewer.js +9 -2
  160. package/lib/components/RichTextEditor/RichTextViewer.js.map +1 -1
  161. package/lib/components/RichTextEditor/Toolbar/Toolbar.js +1 -1
  162. package/lib/components/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  163. package/lib/components/RichTextEditor/Toolbar/Toolbar.types.d.ts +4 -4
  164. package/lib/components/RichTextEditor/Toolbar/Toolbar.types.d.ts.map +1 -1
  165. package/lib/components/RichTextEditor/Toolbar/Toolbar.types.js.map +1 -1
  166. package/lib/components/RichTextEditor/Toolbar/ToolbarButton.d.ts.map +1 -1
  167. package/lib/components/RichTextEditor/Toolbar/ToolbarButton.js +41 -26
  168. package/lib/components/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
  169. package/lib/components/RichTextEditor/utils/htmlConverter.d.ts +2 -0
  170. package/lib/components/RichTextEditor/utils/htmlConverter.d.ts.map +1 -1
  171. package/lib/components/RichTextEditor/utils/htmlConverter.js +12 -0
  172. package/lib/components/RichTextEditor/utils/htmlConverter.js.map +1 -1
  173. package/lib/components/RichTextEditor/utils/interactionRenderer.d.ts.map +1 -1
  174. package/lib/components/RichTextEditor/utils/interactionRenderer.js +20 -19
  175. package/lib/components/RichTextEditor/utils/interactionRenderer.js.map +1 -1
  176. package/lib/components/RichTextEditor/utils/markdownConverter.d.ts.map +1 -1
  177. package/lib/components/RichTextEditor/utils/markdownConverter.js +131 -30
  178. package/lib/components/RichTextEditor/utils/markdownConverter.js.map +1 -1
  179. package/lib/components/RichTextEditor/utils/renderers.d.ts +5 -3
  180. package/lib/components/RichTextEditor/utils/renderers.d.ts.map +1 -1
  181. package/lib/components/RichTextEditor/utils/renderers.js +62 -34
  182. package/lib/components/RichTextEditor/utils/renderers.js.map +1 -1
  183. package/lib/components/RichTextEditor/utils/slateConverter.d.ts +4 -3
  184. package/lib/components/RichTextEditor/utils/slateConverter.d.ts.map +1 -1
  185. package/lib/components/RichTextEditor/utils/slateConverter.js +86 -38
  186. package/lib/components/RichTextEditor/utils/slateConverter.js.map +1 -1
  187. package/package.json +30 -8
  188. package/lib/components/Editor/ImageEditor.d.ts +0 -10
  189. package/lib/components/Editor/ImageEditor.d.ts.map +0 -1
  190. package/lib/components/Editor/ImageEditor.js +0 -292
  191. package/lib/components/Editor/ImageEditor.js.map +0 -1
@@ -1,4 +1,11 @@
1
- import { Element, Text } from 'slate';
1
+ import { Element as SlateElement, Text as SlateText } from 'slate';
2
+ import { disallowedURI } from '@pega/cosmos-react-core';
3
+ const EXCLUDED_ATTR_KEYS = new Set([
4
+ 'type',
5
+ 'children',
6
+ 'isHeaderCell',
7
+ 'isHeaderRow'
8
+ ]);
2
9
  export const slateToHtmlMap = {
3
10
  link: 'a',
4
11
  'heading-1': 'h1',
@@ -13,6 +20,7 @@ export const slateToHtmlMap = {
13
20
  'code-block': 'pre',
14
21
  'horizontal-rule': 'hr',
15
22
  table: 'table',
23
+ 'table-head': 'thead',
16
24
  'table-body': 'tbody',
17
25
  'table-row': 'tr',
18
26
  'table-cell': 'td',
@@ -29,65 +37,105 @@ export const slateToHtmlMap = {
29
37
  const getAttrs = (el) => {
30
38
  // eslint-disable-next-line sonarjs/no-small-switch
31
39
  switch (el.type) {
32
- case 'list-item':
33
- return [
34
- { name: 'data-id', value: el.id },
35
- { name: 'data-parent-id', value: el.parentId },
36
- { name: 'data-order', value: el.order },
37
- { name: 'data-level', value: el.level }
38
- ].reduce((acc, attr) => {
39
- if (attr.value) {
40
- return `${acc} ${attr.name}='${attr.value}'`;
41
- }
42
- return acc;
43
- }, '');
40
+ case 'list-item': {
41
+ const attrs = [];
42
+ if (el.id) {
43
+ attrs.push(['data-id', el.id]);
44
+ }
45
+ if (el.parentId) {
46
+ attrs.push(['data-parent-id', el.parentId]);
47
+ }
48
+ if (el.order !== undefined) {
49
+ attrs.push(['data-order', `${el.order}`]);
50
+ }
51
+ if (el.level !== undefined) {
52
+ attrs.push(['data-level', `${el.level}`]);
53
+ }
54
+ return attrs;
55
+ }
44
56
  default:
45
- return Object.keys(el).reduce((innerAcc, key) => {
46
- return key !== 'type' && key !== 'children'
47
- ? `${innerAcc} ${key}='${el[key]}'`
48
- : innerAcc;
49
- }, '');
57
+ return Object.entries(el).flatMap(([key, value]) => {
58
+ const lowerKey = key.toLowerCase();
59
+ if (EXCLUDED_ATTR_KEYS.has(key) ||
60
+ // Strip event handlers.
61
+ lowerKey.startsWith('on') ||
62
+ value === undefined) {
63
+ return [];
64
+ }
65
+ if (lowerKey === 'href' && disallowedURI.test(value)) {
66
+ return [];
67
+ }
68
+ return [[lowerKey, `${value}`]];
69
+ });
50
70
  }
51
71
  };
52
72
  // Recursive function to reduce Slate Nodes into an HTML string
53
73
  export const constructHtml = (nodes) => {
54
74
  return nodes.reduce((acc, node) => {
55
- if (Element.isElement(node) &&
75
+ if (SlateElement.isElement(node) &&
56
76
  (node.type === 'image-placeholder' || node.type === 'custom' || node.type === 'override'))
57
77
  return acc;
58
- const htmlTag = Element.isElement(node) ? slateToHtmlMap[node.type] : undefined;
59
- let html;
60
- if (Text.isText(node)) {
78
+ const isElement = SlateElement.isElement(node);
79
+ if (SlateText.isText(node)) {
61
80
  const { text, ...restNode } = node;
62
81
  // Reducing inline style properties from a single Slate Node into the correct HTML tags
63
- html = Object.keys(restNode).reduce((innerAcc, key, i) => {
82
+ const html = Object.keys(restNode).reduce((innerAcc, key, i) => {
64
83
  const tag = slateToHtmlMap[key];
65
- // Add the href attribute if needed
66
- const firstInnerTag = tag === 'a' ? `${tag} href='${restNode[key]}'` : tag;
84
+ if (!tag)
85
+ return innerAcc;
86
+ let innerEl;
87
+ if (tag === 'a') {
88
+ const anchor = document.createElement(tag);
89
+ if (restNode.href && !disallowedURI.test(restNode.href)) {
90
+ anchor.setAttribute('href', restNode.href);
91
+ }
92
+ innerEl = anchor;
93
+ }
94
+ else {
95
+ innerEl = document.createElement(tag);
96
+ }
67
97
  if (i === 0) {
68
- return `<${firstInnerTag}>${text}</${tag}>`;
98
+ innerEl.textContent = text;
99
+ return innerEl;
69
100
  }
70
- return `<${firstInnerTag}>${innerAcc}</${tag}>`;
71
- }, '');
72
- if (!html) {
73
- html = text;
101
+ if (innerAcc) {
102
+ innerEl.appendChild(innerAcc);
103
+ }
104
+ return innerEl;
105
+ }, null);
106
+ if (html) {
107
+ return acc.concat(html);
74
108
  }
109
+ return acc.concat(document.createTextNode(text));
75
110
  }
76
- else {
77
- const attrs = getAttrs(node);
78
- html = `<${htmlTag}${attrs}>${constructHtml(node.children || [])}</${htmlTag}>`;
111
+ let htmlTag = isElement ? slateToHtmlMap[node.type] : undefined;
112
+ if (isElement && node.type === 'table-cell' && node.isHeaderCell) {
113
+ htmlTag = 'th';
79
114
  }
80
- return `${acc}${html}`;
81
- }, '');
115
+ if (!htmlTag)
116
+ return acc;
117
+ const el = document.createElement(htmlTag);
118
+ for (const [attr, val] of getAttrs(node)) {
119
+ el.setAttribute(attr, val);
120
+ }
121
+ for (const child of constructHtml(node.children)) {
122
+ el.appendChild(child);
123
+ }
124
+ return acc.concat(el);
125
+ }, []);
82
126
  };
83
127
  export const convertSlateToHtml = (nodes) => {
84
128
  if (nodes.length === 1 &&
85
- Element.isElement(nodes[0]) &&
86
- Text.isText(nodes[0].children[0]) &&
129
+ SlateElement.isElement(nodes[0]) &&
130
+ SlateText.isText(nodes[0].children[0]) &&
87
131
  nodes[0].children[0].text === '') {
88
132
  return '';
89
133
  }
90
134
  const htmlNodes = constructHtml(nodes);
91
- return `<body>${htmlNodes}</body>`;
135
+ const body = document.createElement('body');
136
+ for (const node of htmlNodes) {
137
+ body.appendChild(node);
138
+ }
139
+ return body.outerHTML;
92
140
  };
93
141
  //# sourceMappingURL=slateConverter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slateConverter.js","sourceRoot":"","sources":["../../../../src/components/RichTextEditor/utils/slateConverter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Element, Text } from 'slate';\nimport type { PegaCustom } from 'slate';\n\nimport type { ExcludeStrict } from '@pega/cosmos-react-core';\n\nexport const slateToHtmlMap = {\n link: 'a',\n 'heading-1': 'h1',\n 'heading-2': 'h2',\n 'heading-3': 'h3',\n 'heading-4': 'h4',\n 'unordered-list': 'ul',\n 'ordered-list': 'ol',\n 'list-item': 'li',\n 'block-quote': 'blockquote',\n // FIXME: Should render <pre><code>, but I don't know if this is really used anymore.\n 'code-block': 'pre',\n 'horizontal-rule': 'hr',\n table: 'table',\n 'table-body': 'tbody',\n 'table-row': 'tr',\n 'table-cell': 'td',\n text: 'span',\n paragraph: 'p',\n bold: 'b',\n 'line-through': 'del',\n italic: 'i',\n code: 'code',\n href: 'a',\n image: 'img'\n};\n\n// Reduces the properties in a slate node into the correct html attributes, mostly used for list-items at the moment\nconst getAttrs = (\n el: ExcludeStrict<Element, PegaCustom.ImagePlaceholderElement | PegaCustom.CustomElement>\n) => {\n // eslint-disable-next-line sonarjs/no-small-switch\n switch (el.type) {\n case 'list-item':\n return [\n { name: 'data-id', value: el.id },\n { name: 'data-parent-id', value: el.parentId },\n { name: 'data-order', value: el.order },\n { name: 'data-level', value: el.level }\n ].reduce((acc, attr) => {\n if (attr.value) {\n return `${acc} ${attr.name}='${attr.value}'`;\n }\n return acc;\n }, '');\n default:\n return Object.keys(el).reduce((innerAcc, key) => {\n return key !== 'type' && key !== 'children'\n ? `${innerAcc} ${key}='${el[key as keyof Element]}'`\n : innerAcc;\n }, '');\n }\n};\n\n// Recursive function to reduce Slate Nodes into an HTML string\nexport const constructHtml = (nodes: (Element | Text)[]): string => {\n return nodes.reduce((acc, node) => {\n if (\n Element.isElement(node) &&\n (node.type === 'image-placeholder' || node.type === 'custom' || node.type === 'override')\n )\n return acc;\n\n const htmlTag = Element.isElement(node) ? slateToHtmlMap[node.type] : undefined;\n let html;\n if (Text.isText(node)) {\n const { text, ...restNode } = node;\n // Reducing inline style properties from a single Slate Node into the correct HTML tags\n html = Object.keys(restNode).reduce((innerAcc, key, i) => {\n const tag = slateToHtmlMap[key as 'bold' | 'line-through' | 'italic' | 'href'];\n // Add the href attribute if needed\n const firstInnerTag = tag === 'a' ? `${tag} href='${restNode[key as 'href']}'` : tag;\n\n if (i === 0) {\n return `<${firstInnerTag}>${text}</${tag}>`;\n }\n return `<${firstInnerTag}>${innerAcc}</${tag}>`;\n }, '');\n if (!html) {\n html = text;\n }\n } else {\n const attrs = getAttrs(node);\n html = `<${htmlTag}${attrs}>${constructHtml(\n (node.children as (Element | Text)[]) || []\n )}</${htmlTag}>`;\n }\n return `${acc}${html}`;\n }, '');\n};\n\nexport const convertSlateToHtml = (nodes: (Element | Text)[]): string => {\n if (\n nodes.length === 1 &&\n Element.isElement(nodes[0]) &&\n Text.isText(nodes[0].children[0]) &&\n nodes[0].children[0].text === ''\n ) {\n return '';\n }\n const htmlNodes = constructHtml(nodes);\n return `<body>${htmlNodes}</body>`;\n};\n"]}
1
+ {"version":3,"file":"slateConverter.js","sourceRoot":"","sources":["../../../../src/components/RichTextEditor/utils/slateConverter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Element as SlateElement, Text as SlateText } from 'slate';\nimport type { PegaCustom } from 'slate';\n\nimport { disallowedURI } from '@pega/cosmos-react-core';\nimport type { ExcludeStrict } from '@pega/cosmos-react-core';\n\nconst EXCLUDED_ATTR_KEYS: ReadonlySet<string> = new Set([\n 'type',\n 'children',\n 'isHeaderCell',\n 'isHeaderRow'\n]);\n\nexport const slateToHtmlMap = {\n link: 'a',\n 'heading-1': 'h1',\n 'heading-2': 'h2',\n 'heading-3': 'h3',\n 'heading-4': 'h4',\n 'unordered-list': 'ul',\n 'ordered-list': 'ol',\n 'list-item': 'li',\n 'block-quote': 'blockquote',\n // FIXME: Should render <pre><code>, but I don't know if this is really used anymore.\n 'code-block': 'pre',\n 'horizontal-rule': 'hr',\n table: 'table',\n 'table-head': 'thead',\n 'table-body': 'tbody',\n 'table-row': 'tr',\n 'table-cell': 'td',\n text: 'span',\n paragraph: 'p',\n bold: 'b',\n 'line-through': 'del',\n italic: 'i',\n code: 'code',\n href: 'a',\n image: 'img'\n};\n\n// Reduces the properties in a slate node into the correct html attributes, mostly used for list-items at the moment\nconst getAttrs = (\n el: ExcludeStrict<SlateElement, PegaCustom.ImagePlaceholderElement | PegaCustom.CustomElement>\n): [string, string][] => {\n // eslint-disable-next-line sonarjs/no-small-switch\n switch (el.type) {\n case 'list-item': {\n const attrs: [string, string][] = [];\n\n if (el.id) {\n attrs.push(['data-id', el.id]);\n }\n\n if (el.parentId) {\n attrs.push(['data-parent-id', el.parentId]);\n }\n\n if (el.order !== undefined) {\n attrs.push(['data-order', `${el.order}`]);\n }\n\n if (el.level !== undefined) {\n attrs.push(['data-level', `${el.level}`]);\n }\n\n return attrs;\n }\n\n default:\n return Object.entries(el).flatMap(([key, value]) => {\n const lowerKey = key.toLowerCase();\n\n if (\n EXCLUDED_ATTR_KEYS.has(key) ||\n // Strip event handlers.\n lowerKey.startsWith('on') ||\n value === undefined\n ) {\n return [];\n }\n\n if (lowerKey === 'href' && disallowedURI.test(value)) {\n return [];\n }\n\n return [[lowerKey, `${value}`]];\n });\n }\n};\n\n// Recursive function to reduce Slate Nodes into an HTML string\nexport const constructHtml = (nodes: (SlateElement | SlateText)[]): Node[] => {\n return nodes.reduce((acc: Node[], node) => {\n if (\n SlateElement.isElement(node) &&\n (node.type === 'image-placeholder' || node.type === 'custom' || node.type === 'override')\n )\n return acc;\n\n const isElement = SlateElement.isElement(node);\n\n if (SlateText.isText(node)) {\n const { text, ...restNode } = node;\n // Reducing inline style properties from a single Slate Node into the correct HTML tags\n const html = Object.keys(restNode).reduce((innerAcc: Element | null, key, i) => {\n const tag = slateToHtmlMap[key as 'bold' | 'line-through' | 'italic' | 'href'];\n\n if (!tag) return innerAcc;\n\n let innerEl: HTMLElement;\n\n if (tag === 'a') {\n const anchor = document.createElement(tag);\n if (restNode.href && !disallowedURI.test(restNode.href)) {\n anchor.setAttribute('href', restNode.href);\n }\n innerEl = anchor;\n } else {\n innerEl = document.createElement(tag);\n }\n\n if (i === 0) {\n innerEl.textContent = text;\n return innerEl;\n }\n\n if (innerAcc) {\n innerEl.appendChild(innerAcc);\n }\n\n return innerEl;\n }, null);\n\n if (html) {\n return acc.concat(html);\n }\n\n return acc.concat(document.createTextNode(text));\n }\n\n let htmlTag = isElement ? slateToHtmlMap[node.type] : undefined;\n if (isElement && node.type === 'table-cell' && node.isHeaderCell) {\n htmlTag = 'th';\n }\n\n if (!htmlTag) return acc;\n\n const el = document.createElement(htmlTag);\n\n for (const [attr, val] of getAttrs(node)) {\n el.setAttribute(attr, val);\n }\n\n for (const child of constructHtml(node.children)) {\n el.appendChild(child);\n }\n\n return acc.concat(el);\n }, []);\n};\n\nexport const convertSlateToHtml = (nodes: (SlateElement | SlateText)[]): string => {\n if (\n nodes.length === 1 &&\n SlateElement.isElement(nodes[0]) &&\n SlateText.isText(nodes[0].children[0]) &&\n nodes[0].children[0].text === ''\n ) {\n return '';\n }\n\n const htmlNodes = constructHtml(nodes);\n const body = document.createElement('body');\n for (const node of htmlNodes) {\n body.appendChild(node);\n }\n\n return body.outerHTML;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/cosmos-react-rte",
3
- "version": "9.0.0-build.9.9",
3
+ "version": "9.0.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "author": "Pegasystems",
6
6
  "sideEffects": false,
@@ -14,13 +14,35 @@
14
14
  "build": "tsc -b tsconfig.build.json"
15
15
  },
16
16
  "dependencies": {
17
- "@pega/cosmos-react-core": "9.0.0-build.9.9",
17
+ "@intevation/tiptap-extension-office-paste": "^0.1.2",
18
+ "@pega/cosmos-react-core": "9.0.0",
18
19
  "@popperjs/core": "^2.11.6",
20
+ "@tiptap/core": "^3.12.1",
21
+ "@tiptap/extension-blockquote": "^3.12.1",
22
+ "@tiptap/extension-color": "^3.12.1",
23
+ "@tiptap/extension-font-family": "^3.12.1",
24
+ "@tiptap/extension-highlight": "^3.12.1",
25
+ "@tiptap/extension-image": "^3.12.1",
26
+ "@tiptap/extension-link": "^3.12.1",
27
+ "@tiptap/extension-paragraph": "^3.12.1",
28
+ "@tiptap/extension-placeholder": "^3.12.1",
29
+ "@tiptap/extension-subscript": "^3.12.1",
30
+ "@tiptap/extension-superscript": "^3.12.1",
31
+ "@tiptap/extension-table": "^3.12.1",
32
+ "@tiptap/extension-table-cell": "^3.12.1",
33
+ "@tiptap/extension-table-header": "^3.12.1",
34
+ "@tiptap/extension-table-row": "^3.12.1",
35
+ "@tiptap/extension-text-align": "^3.12.1",
36
+ "@tiptap/extension-text-style": "^3.12.1",
37
+ "@tiptap/extension-underline": "^3.12.1",
38
+ "@tiptap/pm": "^3.12.1",
39
+ "@tiptap/react": "^3.12.1",
40
+ "@tiptap/starter-kit": "^3.12.1",
19
41
  "@types/parse5": "^6.0.0",
20
42
  "@types/react": "^17.0.62 || ^18.3.3",
21
43
  "@types/react-dom": "^17.0.20 || ^18.3.0",
22
- "@types/styled-components": "^5.1.26",
23
- "@types/stylis": "^4.0.2",
44
+ "@types/stylis": "^4.2.7",
45
+ "dompurify": "^3.2.6",
24
46
  "global-tld-list": "0.0.862",
25
47
  "marked": "^15.0.6",
26
48
  "parse5": "^6.0.1",
@@ -31,15 +53,15 @@
31
53
  "slate": "^0.76.1",
32
54
  "slate-history": "^0.66.0",
33
55
  "slate-react": "^0.76.1",
34
- "styled-components": "^5.2.0",
35
- "stylis": "^4.0.13",
36
- "tinymce": "^6.8.5"
56
+ "styled-components": "~6.3.11",
57
+ "stylis": "^4.3.6"
37
58
  },
38
59
  "devDependencies": {
39
60
  "@storybook/addon-actions": "~8.2.9",
40
61
  "@storybook/react": "~8.2.9",
41
62
  "@storybook/theming": "~8.2.9",
42
63
  "@testing-library/react": "^16.0.0",
43
- "typescript": "~5.8.3"
64
+ "@testing-library/user-event": "^14.6.1",
65
+ "typescript": "~5.9.3"
44
66
  }
45
67
  }
@@ -1,10 +0,0 @@
1
- import type { FC } from 'react';
2
- import type { Editor } from 'tinymce';
3
- export declare const imgHoverClass: string;
4
- declare const ImageEditor: FC<{
5
- editorEl: HTMLElement;
6
- editor: Editor;
7
- onChange: () => void;
8
- }>;
9
- export default ImageEditor;
10
- //# sourceMappingURL=ImageEditor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ImageEditor.d.ts","sourceRoot":"","sources":["../../../src/components/Editor/ImageEditor.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,EAAE,EAKH,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA0BtC,eAAO,MAAM,aAAa,QAAc,CAAC;AAEzC,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAAE,CA0YpF,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,292 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState, useLayoutEffect } from 'react';
3
- import styled from 'styled-components';
4
- import { remToPx, stripUnit } from 'polished';
5
- import { Button, Checkbox, createUID, Grid, Icon, Input, NumberInput, useAfterInitialEffect, useElement, useI18n, useTheme, useUID, VisuallyHiddenText } from '@pega/cosmos-react-core';
6
- import { StyledFormDialog } from './Editor.styles';
7
- const IgnoreMouseEventsIcon = styled(Icon) `
8
- pointer-events: none;
9
- `;
10
- export const imgHoverClass = createUID();
11
- const ImageEditor = ({ editorEl, editor, onChange }) => {
12
- const t = useI18n();
13
- const id = useUID();
14
- const theme = useTheme();
15
- const [showImageDialog, setShowImageDialog] = useState(false);
16
- const [imageEditHover, setImageEditHover] = useState(false);
17
- const [imageEditFocus, setImageEditFocus] = useState(false);
18
- const [canShowButtons, setCanShowButtons] = useState(false);
19
- const [imgEl, setImageEl] = useState(null);
20
- const [imgElements, setImageElements] = useState([]);
21
- const [editButtonEl, setEditButtonEl] = useElement(null);
22
- const [deleteButtonEl, setDeleteButtonEl] = useElement(null);
23
- const [width, setWidth] = useState(0);
24
- const [height, setHeight] = useState(0);
25
- const [aspectRatio, setAspectRatio] = useState(0);
26
- const [altText, setAltText] = useState('');
27
- const [customSize, setCustomSize] = useState(false);
28
- const [keyCommandText, setKeyCommandText] = useState('');
29
- const imageDialogRef = useRef(null);
30
- const altTextInputRef = useRef(null);
31
- const editorOpenedWithEnter = useRef(false);
32
- const [btnStyle, setBtnStyle] = useState({});
33
- const onImageClick = (e) => {
34
- e.preventDefault();
35
- e.stopPropagation();
36
- setShowImageDialog(true);
37
- };
38
- const calculateBtnStyles = (el) => {
39
- const elementRect = el.getBoundingClientRect();
40
- const padding = Number(stripUnit(remToPx(theme.base.spacing)));
41
- return {
42
- position: 'absolute',
43
- display: 'flex',
44
- top: elementRect.top + padding,
45
- left: elementRect.right +
46
- padding -
47
- ((editButtonEl?.scrollWidth ?? 0) + (deleteButtonEl?.scrollWidth ?? 0) * 2)
48
- };
49
- };
50
- const onImageMouseEnter = (e) => {
51
- if (!showImageDialog) {
52
- const el = e.target;
53
- setImageEditHover(true);
54
- setImageEl(el);
55
- }
56
- };
57
- const onImageMouseLeave = (e) => {
58
- if (e.relatedTarget && e.relatedTarget.id !== id && !showImageDialog) {
59
- setImageEl(null);
60
- setImageEditHover(false);
61
- }
62
- };
63
- const setImageState = () => {
64
- if (imgEl) {
65
- let imgHeight;
66
- let imgWidth;
67
- let hasHeightOrWidthAttribute = false;
68
- if (imgEl.getAttribute('height')) {
69
- imgHeight = parseInt(imgEl.getAttribute('height'), 10);
70
- hasHeightOrWidthAttribute = true;
71
- }
72
- else {
73
- imgHeight = imgEl.naturalHeight;
74
- }
75
- if (imgEl.getAttribute('width')) {
76
- imgWidth = parseInt(imgEl.getAttribute('width'), 10);
77
- hasHeightOrWidthAttribute = true;
78
- }
79
- else {
80
- imgWidth = imgEl.naturalWidth;
81
- }
82
- setAltText(imgEl.getAttribute('alt') || '');
83
- setHeight(imgHeight);
84
- setWidth(imgWidth);
85
- setAspectRatio(imgWidth / imgHeight);
86
- setCustomSize(hasHeightOrWidthAttribute);
87
- }
88
- };
89
- const onCheckBoxClick = (e) => {
90
- e.stopPropagation();
91
- };
92
- const onInputClick = (e) => {
93
- e.stopPropagation();
94
- e.preventDefault();
95
- };
96
- const onInputFocus = (e) => {
97
- e.stopPropagation();
98
- };
99
- const onAltTextChange = (e) => {
100
- setAltText(e.target.value);
101
- };
102
- // The next two functions handle changing the height and width of the selected image element.
103
- // If the value entered is too small, the value will be defaulted.
104
- // When the height is input, a new width will be calculated and vice versa.
105
- const onHeightChange = (incomingValue) => {
106
- const inputHeight = parseInt(incomingValue, 10);
107
- setHeight(inputHeight);
108
- setWidth(inputHeight * aspectRatio);
109
- };
110
- const onWidthChange = (incomingValue) => {
111
- const inputWidth = parseInt(incomingValue, 10);
112
- setWidth(inputWidth);
113
- setHeight(inputWidth / aspectRatio);
114
- };
115
- const onImageChangeSubmit = () => {
116
- if (imgEl) {
117
- if (customSize) {
118
- if (Number.isNaN(height) || Number.isNaN(width)) {
119
- imgEl.removeAttribute('height');
120
- imgEl.removeAttribute('width');
121
- setHeight(imgEl.naturalHeight);
122
- setWidth(imgEl.naturalWidth);
123
- }
124
- else {
125
- imgEl.setAttribute('height', height.toString());
126
- imgEl.setAttribute('width', width.toString());
127
- }
128
- }
129
- else {
130
- imgEl.removeAttribute('height');
131
- imgEl.removeAttribute('width');
132
- }
133
- imgEl.setAttribute('alt', altText);
134
- }
135
- editor.selection.select(editor.dom.select(`img[src="${imgEl?.src}"]`)[0]);
136
- setImageEl(null);
137
- setShowImageDialog(false);
138
- onChange();
139
- };
140
- const onImageChangeCancel = () => {
141
- setImageEl(null);
142
- setShowImageDialog(false);
143
- };
144
- const onImageDelete = () => {
145
- if (imgEl) {
146
- imgEl.remove();
147
- }
148
- setImageEl(null);
149
- setShowImageDialog(false);
150
- setImageEditFocus(false);
151
- onChange();
152
- };
153
- // Keeps the imageElements state up to date with existing and newly added img tags inside of TinyMCE
154
- useEffect(() => {
155
- const iframeDoc = editor.getDoc();
156
- const imageElements = iframeDoc?.querySelectorAll('img') ?? [];
157
- setImageElements(() => {
158
- return [...imageElements];
159
- });
160
- const observer = new MutationObserver(mutations => {
161
- mutations.forEach(mutation => {
162
- if (mutation.type === 'childList' &&
163
- (mutation.addedNodes.length || mutation.removedNodes.length)) {
164
- const newImageElements = iframeDoc?.querySelectorAll('img') ?? [];
165
- setImageElements(() => [...newImageElements]);
166
- }
167
- });
168
- });
169
- if (iframeDoc) {
170
- observer.observe(iframeDoc.body, { childList: true, subtree: true });
171
- }
172
- return () => {
173
- observer.disconnect();
174
- };
175
- }, [editorEl, editor, setImageElements]);
176
- // Adds event listeners to HTML img elements inside of TinyMCE
177
- // This has to be done because there are no react components for these images
178
- useEffect(() => {
179
- imgElements.forEach(imgElement => {
180
- imgElement.addEventListener('mouseenter', onImageMouseEnter);
181
- imgElement.addEventListener('mouseout', onImageMouseLeave);
182
- imgElement.addEventListener('click', onImageClick);
183
- });
184
- return () => {
185
- imgElements.forEach(imgElement => {
186
- imgElement.removeEventListener('mouseenter', onImageMouseEnter);
187
- imgElement.removeEventListener('mouseout', onImageMouseLeave);
188
- imgElement.removeEventListener('click', onImageClick);
189
- });
190
- };
191
- }, [imgElements, onImageMouseEnter, onImageMouseLeave, onImageClick]);
192
- useEffect(() => {
193
- setImageState();
194
- imgEl?.setAttribute('class', imgHoverClass);
195
- if (imgEl && imgEl.clientHeight > 64 && imgEl.clientWidth > 104) {
196
- setCanShowButtons(true);
197
- }
198
- else {
199
- setCanShowButtons(false);
200
- }
201
- return () => {
202
- imgEl?.removeAttribute('class');
203
- };
204
- }, [imgEl]);
205
- useEffect(() => {
206
- const onKeyUp = () => {
207
- const selection = editor.selection.getSel();
208
- let nextToImg = false;
209
- // If your selection is next to an image on it's own line (not breaking text)
210
- if (selection &&
211
- selection.anchorNode?.childNodes.length === 1 &&
212
- selection.anchorNode?.firstChild?.nodeName === 'IMG' &&
213
- selection.anchorOffset === 0) {
214
- setImageEl(selection.anchorNode.firstChild);
215
- setImageEditFocus(true);
216
- nextToImg = true;
217
- // If your selection is next to an image that breaks text up inside of a paragraph
218
- }
219
- else if (selection?.anchorNode?.nextSibling?.nodeName === 'IMG') {
220
- setImageEl(selection.anchorNode.nextSibling);
221
- setImageEditFocus(true);
222
- nextToImg = true;
223
- }
224
- else if (selection && imgEl && imageEditFocus) {
225
- setImageEl(null);
226
- setImageEditFocus(false);
227
- setKeyCommandText('');
228
- }
229
- if (nextToImg) {
230
- setKeyCommandText(t('rte_image_key_command'));
231
- }
232
- };
233
- const onMouseUp = () => {
234
- const selection = editor.selection.getSel();
235
- // If your selection is next to an image
236
- if (selection?.anchorNode?.firstChild?.nodeName === 'IMG') {
237
- setImageEl(selection.anchorNode.firstChild);
238
- setImageEditFocus(true);
239
- }
240
- };
241
- const onKeyDown = (e) => {
242
- if (e.key === 'Enter' && imageEditFocus) {
243
- e.stopPropagation();
244
- e.preventDefault();
245
- editorOpenedWithEnter.current = true;
246
- setShowImageDialog(true);
247
- }
248
- else if ((e.key === 'Del' || e.key === 'Backspace') && imageEditFocus) {
249
- onImageDelete();
250
- }
251
- };
252
- editor.on('keyup', onKeyUp);
253
- editor.on('mouseup', onMouseUp);
254
- editor.on('keydown', onKeyDown, true);
255
- return () => {
256
- editor.off('keyup', onKeyUp);
257
- editor.off('mouseup', onMouseUp);
258
- editor.off('keydown', onKeyDown);
259
- };
260
- }, [editor, imgEl, imageEditFocus]);
261
- useAfterInitialEffect(() => {
262
- if (showImageDialog) {
263
- editor.selection.getSel()?.collapseToEnd();
264
- if (editorOpenedWithEnter.current) {
265
- altTextInputRef.current?.focus();
266
- editorOpenedWithEnter.current = false;
267
- }
268
- }
269
- else {
270
- editor.focus();
271
- }
272
- }, [showImageDialog]);
273
- useLayoutEffect(() => {
274
- if (imgEl && editButtonEl && deleteButtonEl) {
275
- setBtnStyle(calculateBtnStyles(imgEl));
276
- }
277
- }, [imgEl, editButtonEl, deleteButtonEl]);
278
- return (_jsxs(_Fragment, { children: [(imageEditFocus || imageEditHover) && imgEl && canShowButtons && (_jsxs("div", { id: id, style: btnStyle, children: [_jsx(Button, { ref: setEditButtonEl, icon: true, label: t('rte_edit_image'), "aria-label": t('rte_edit_image', [altText]), onClick: () => {
279
- setShowImageDialog(true);
280
- }, children: _jsx(IgnoreMouseEventsIcon, { name: 'pencil' }) }), _jsx(Button, { ref: setDeleteButtonEl, icon: true, label: t('rte_delete_image'), "aria-label": t('rte_delete_image', [altText]), onClick: onImageDelete, children: _jsx(IgnoreMouseEventsIcon, { name: 'trash' }) })] })), _jsx(VisuallyHiddenText, { "aria-live": 'polite', children: keyCommandText }), showImageDialog && (editButtonEl || !canShowButtons) && imgEl && (_jsx(StyledFormDialog, { ref: imageDialogRef, target: editButtonEl && canShowButtons ? editButtonEl : imgEl, heading: t('rte_image_settings'), onCancel: onImageChangeCancel, onSubmit: onImageChangeSubmit, onDismiss: () => {
281
- setShowImageDialog(false);
282
- }, children: _jsxs(Grid, { container: {
283
- gap: 2,
284
- areas: customSize
285
- ? '"desc desc" "radio radio" "width height"'
286
- : '"desc desc" "radio radio"'
287
- }, children: [_jsx(Grid, { item: { area: 'desc' }, children: _jsx(Input, { label: t('description'), value: altText, onClick: onInputClick, onChange: onAltTextChange, onFocus: onInputFocus, info: t('rte_image_description_info'), ref: altTextInputRef }) }), _jsx(Grid, { item: { area: 'radio' }, children: _jsx(Checkbox, { checked: customSize, label: t('rte_image_custom_size'), onClick: onCheckBoxClick, onChange: (e) => {
288
- setCustomSize(e.target.checked);
289
- } }) }), customSize && (_jsxs(_Fragment, { children: [_jsx(Grid, { item: { area: 'width' }, children: _jsx(NumberInput, { label: t('rte_width_in_pixels'), value: Math.floor(Math.max(width, 1)).toString(), onClick: onInputClick, onChange: onWidthChange }) }), _jsx(Grid, { item: { area: 'height' }, children: _jsx(NumberInput, { label: t('rte_height_in_pixels'), value: Math.floor(Math.max(height, 1)).toString(), onClick: onInputClick, onChange: onHeightChange }) })] }))] }) }))] }));
290
- };
291
- export default ImageEditor;
292
- //# sourceMappingURL=ImageEditor.js.map