@akinon/ui-editor 1.0.3 → 1.0.5

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 (129) hide show
  1. package/dist/cjs/tiptap/components/__tests__/html-code-viewer.test.js +79 -3
  2. package/dist/cjs/tiptap/components/__tests__/html-code-viewer.test.tsx +106 -3
  3. package/dist/cjs/tiptap/components/__tests__/tiptap.test.js +42 -4
  4. package/dist/cjs/tiptap/components/__tests__/tiptap.test.tsx +57 -7
  5. package/dist/cjs/tiptap/components/format-bubble-menu.d.ts.map +1 -1
  6. package/dist/cjs/tiptap/components/format-bubble-menu.js +6 -5
  7. package/dist/cjs/tiptap/components/html-code-viewer.d.ts +2 -1
  8. package/dist/cjs/tiptap/components/html-code-viewer.d.ts.map +1 -1
  9. package/dist/cjs/tiptap/components/html-code-viewer.js +62 -22
  10. package/dist/cjs/tiptap/components/image-upload-placeholder.d.ts.map +1 -1
  11. package/dist/cjs/tiptap/components/image-upload-placeholder.js +5 -2
  12. package/dist/cjs/tiptap/components/secure-script-component.d.ts.map +1 -1
  13. package/dist/cjs/tiptap/components/secure-script-component.js +2 -5
  14. package/dist/cjs/tiptap/components/tiptap.d.ts +1 -1
  15. package/dist/cjs/tiptap/components/tiptap.d.ts.map +1 -1
  16. package/dist/cjs/tiptap/components/tiptap.js +84 -56
  17. package/dist/cjs/tiptap/constants/editor-config.d.ts +10 -1
  18. package/dist/cjs/tiptap/constants/editor-config.d.ts.map +1 -1
  19. package/dist/cjs/tiptap/constants/editor-config.js +11 -2
  20. package/dist/cjs/tiptap/constants/html-elements.d.ts +1 -0
  21. package/dist/cjs/tiptap/constants/html-elements.d.ts.map +1 -1
  22. package/dist/cjs/tiptap/constants/html-elements.js +2 -1
  23. package/dist/cjs/tiptap/extensions/comment-extension.d.ts.map +1 -1
  24. package/dist/cjs/tiptap/extensions/comment-extension.js +3 -3
  25. package/dist/cjs/tiptap/extensions/custom-table-cell-extension.d.ts.map +1 -1
  26. package/dist/cjs/tiptap/extensions/custom-table-cell-extension.js +11 -2
  27. package/dist/cjs/tiptap/extensions/custom-table-header-extension.d.ts.map +1 -1
  28. package/dist/cjs/tiptap/extensions/custom-table-header-extension.js +11 -2
  29. package/dist/cjs/tiptap/extensions/html-block-extension.d.ts.map +1 -1
  30. package/dist/cjs/tiptap/extensions/html-block-extension.js +11 -14
  31. package/dist/cjs/tiptap/extensions/html-inline-extension.d.ts.map +1 -1
  32. package/dist/cjs/tiptap/extensions/html-inline-extension.js +11 -14
  33. package/dist/cjs/tiptap/types/index.d.ts +12 -5
  34. package/dist/cjs/tiptap/types/index.d.ts.map +1 -1
  35. package/dist/cjs/tiptap/utils/__tests__/clean-html.test.d.ts +2 -0
  36. package/dist/cjs/tiptap/utils/__tests__/clean-html.test.d.ts.map +1 -0
  37. package/dist/cjs/tiptap/utils/__tests__/clean-html.test.js +93 -0
  38. package/dist/cjs/tiptap/utils/__tests__/clean-html.test.ts +129 -0
  39. package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.d.ts +2 -0
  40. package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.d.ts.map +1 -0
  41. package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.js +105 -0
  42. package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.ts +148 -0
  43. package/dist/cjs/tiptap/utils/__tests__/index.test.js +0 -2
  44. package/dist/cjs/tiptap/utils/__tests__/index.test.ts +0 -2
  45. package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.d.ts +2 -0
  46. package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.d.ts.map +1 -0
  47. package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.js +33 -0
  48. package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.ts +49 -0
  49. package/dist/cjs/tiptap/utils/__tests__/tiptap-extensions.test.js +157 -0
  50. package/dist/cjs/tiptap/utils/__tests__/tiptap-extensions.test.ts +234 -0
  51. package/dist/cjs/tiptap/utils/clean-html.d.ts +9 -0
  52. package/dist/cjs/tiptap/utils/clean-html.d.ts.map +1 -0
  53. package/dist/cjs/tiptap/utils/clean-html.js +75 -0
  54. package/dist/cjs/tiptap/utils/data-attributes-helper.d.ts +20 -0
  55. package/dist/cjs/tiptap/utils/data-attributes-helper.d.ts.map +1 -0
  56. package/dist/cjs/tiptap/utils/data-attributes-helper.js +68 -0
  57. package/dist/cjs/tiptap/utils/index.d.ts +3 -2
  58. package/dist/cjs/tiptap/utils/index.d.ts.map +1 -1
  59. package/dist/cjs/tiptap/utils/index.js +3 -2
  60. package/dist/cjs/tiptap/utils/prettier-format.d.ts +8 -0
  61. package/dist/cjs/tiptap/utils/prettier-format.d.ts.map +1 -0
  62. package/dist/cjs/tiptap/utils/prettier-format.js +26 -0
  63. package/dist/cjs/tiptap/utils/tiptap-extensions.d.ts.map +1 -1
  64. package/dist/cjs/tiptap/utils/tiptap-extensions.js +134 -14
  65. package/dist/esm/tiptap/components/__tests__/html-code-viewer.test.js +79 -3
  66. package/dist/esm/tiptap/components/__tests__/html-code-viewer.test.tsx +106 -3
  67. package/dist/esm/tiptap/components/__tests__/tiptap.test.js +42 -4
  68. package/dist/esm/tiptap/components/__tests__/tiptap.test.tsx +57 -7
  69. package/dist/esm/tiptap/components/format-bubble-menu.d.ts.map +1 -1
  70. package/dist/esm/tiptap/components/format-bubble-menu.js +6 -5
  71. package/dist/esm/tiptap/components/html-code-viewer.d.ts +2 -1
  72. package/dist/esm/tiptap/components/html-code-viewer.d.ts.map +1 -1
  73. package/dist/esm/tiptap/components/html-code-viewer.js +62 -22
  74. package/dist/esm/tiptap/components/image-upload-placeholder.d.ts.map +1 -1
  75. package/dist/esm/tiptap/components/image-upload-placeholder.js +5 -2
  76. package/dist/esm/tiptap/components/secure-script-component.d.ts.map +1 -1
  77. package/dist/esm/tiptap/components/secure-script-component.js +2 -5
  78. package/dist/esm/tiptap/components/tiptap.d.ts +1 -1
  79. package/dist/esm/tiptap/components/tiptap.d.ts.map +1 -1
  80. package/dist/esm/tiptap/components/tiptap.js +84 -56
  81. package/dist/esm/tiptap/constants/editor-config.d.ts +10 -1
  82. package/dist/esm/tiptap/constants/editor-config.d.ts.map +1 -1
  83. package/dist/esm/tiptap/constants/editor-config.js +11 -2
  84. package/dist/esm/tiptap/constants/html-elements.d.ts +1 -0
  85. package/dist/esm/tiptap/constants/html-elements.d.ts.map +1 -1
  86. package/dist/esm/tiptap/constants/html-elements.js +2 -1
  87. package/dist/esm/tiptap/extensions/comment-extension.d.ts.map +1 -1
  88. package/dist/esm/tiptap/extensions/comment-extension.js +3 -3
  89. package/dist/esm/tiptap/extensions/custom-table-cell-extension.d.ts.map +1 -1
  90. package/dist/esm/tiptap/extensions/custom-table-cell-extension.js +11 -2
  91. package/dist/esm/tiptap/extensions/custom-table-header-extension.d.ts.map +1 -1
  92. package/dist/esm/tiptap/extensions/custom-table-header-extension.js +11 -2
  93. package/dist/esm/tiptap/extensions/html-block-extension.d.ts.map +1 -1
  94. package/dist/esm/tiptap/extensions/html-block-extension.js +11 -14
  95. package/dist/esm/tiptap/extensions/html-inline-extension.d.ts.map +1 -1
  96. package/dist/esm/tiptap/extensions/html-inline-extension.js +11 -14
  97. package/dist/esm/tiptap/types/index.d.ts +12 -5
  98. package/dist/esm/tiptap/types/index.d.ts.map +1 -1
  99. package/dist/esm/tiptap/utils/__tests__/clean-html.test.d.ts +2 -0
  100. package/dist/esm/tiptap/utils/__tests__/clean-html.test.d.ts.map +1 -0
  101. package/dist/esm/tiptap/utils/__tests__/clean-html.test.js +93 -0
  102. package/dist/esm/tiptap/utils/__tests__/clean-html.test.ts +129 -0
  103. package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.d.ts +2 -0
  104. package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.d.ts.map +1 -0
  105. package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.js +105 -0
  106. package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.ts +148 -0
  107. package/dist/esm/tiptap/utils/__tests__/index.test.js +0 -2
  108. package/dist/esm/tiptap/utils/__tests__/index.test.ts +0 -2
  109. package/dist/esm/tiptap/utils/__tests__/prettier-format.test.d.ts +2 -0
  110. package/dist/esm/tiptap/utils/__tests__/prettier-format.test.d.ts.map +1 -0
  111. package/dist/esm/tiptap/utils/__tests__/prettier-format.test.js +33 -0
  112. package/dist/esm/tiptap/utils/__tests__/prettier-format.test.ts +49 -0
  113. package/dist/esm/tiptap/utils/__tests__/tiptap-extensions.test.js +157 -0
  114. package/dist/esm/tiptap/utils/__tests__/tiptap-extensions.test.ts +234 -0
  115. package/dist/esm/tiptap/utils/clean-html.d.ts +9 -0
  116. package/dist/esm/tiptap/utils/clean-html.d.ts.map +1 -0
  117. package/dist/esm/tiptap/utils/clean-html.js +75 -0
  118. package/dist/esm/tiptap/utils/data-attributes-helper.d.ts +20 -0
  119. package/dist/esm/tiptap/utils/data-attributes-helper.d.ts.map +1 -0
  120. package/dist/esm/tiptap/utils/data-attributes-helper.js +68 -0
  121. package/dist/esm/tiptap/utils/index.d.ts +3 -2
  122. package/dist/esm/tiptap/utils/index.d.ts.map +1 -1
  123. package/dist/esm/tiptap/utils/index.js +3 -2
  124. package/dist/esm/tiptap/utils/prettier-format.d.ts +8 -0
  125. package/dist/esm/tiptap/utils/prettier-format.d.ts.map +1 -0
  126. package/dist/esm/tiptap/utils/prettier-format.js +26 -0
  127. package/dist/esm/tiptap/utils/tiptap-extensions.d.ts.map +1 -1
  128. package/dist/esm/tiptap/utils/tiptap-extensions.js +134 -14
  129. package/package.json +13 -12
@@ -1,8 +1,9 @@
1
1
  import '@testing-library/jest-dom';
2
- import { fireEvent, render, screen } from '@testing-library/react';
2
+ import { createEvent, fireEvent, render, screen, waitFor } from '@testing-library/react';
3
3
  import { ConfigProvider } from 'antd';
4
4
  import React from 'react';
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
+ import { formatHtmlWithPrettier } from '../../utils';
6
7
  import { HtmlCodeViewer } from '../html-code-viewer';
7
8
  vi.mock('@ant-design/cssinjs', () => ({
8
9
  useStyleRegister: vi.fn((_config, cb) => {
@@ -11,7 +12,14 @@ vi.mock('@ant-design/cssinjs', () => ({
11
12
  })
12
13
  }));
13
14
  vi.mock('@akinon/ui-theme', () => ({
14
- useToken: () => ({ token: {}, hashId: 'hash-id' })
15
+ useToken: () => ({ token: {}, hashId: 'hash-id' }),
16
+ getSafeCustomTokens: vi.fn(() => ({
17
+ border: { borderWidthThick: '2px', borderSolid: 'solid' }
18
+ }))
19
+ }));
20
+ vi.mock('../../utils', () => ({
21
+ highlightHtml: (html) => html,
22
+ formatHtmlWithPrettier: vi.fn((html) => Promise.resolve(html))
15
23
  }));
16
24
  describe('HtmlCodeViewer', () => {
17
25
  const defaultProps = {
@@ -76,7 +84,11 @@ describe('HtmlCodeViewer', () => {
76
84
  neutral: {
77
85
  '50': '#fff',
78
86
  '1000': '#000'
79
- }
87
+ },
88
+ red: { '825': '#f00', '999': '#a00', '815': '#d00' },
89
+ blue: { '999': '#00f' },
90
+ green: { '825': '#0f0' },
91
+ ebonyClay: { '550': '#123' }
80
92
  }
81
93
  };
82
94
  render(
@@ -86,4 +98,68 @@ describe('HtmlCodeViewer', () => {
86
98
  const textarea = screen.getByRole('textbox');
87
99
  expect(textarea).toBeInTheDocument();
88
100
  });
101
+ it('should format code on mount', async () => {
102
+ const formatted = '<p> Formatted </p>';
103
+ vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
104
+ render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { value: "<p>Raw</p>" })));
105
+ await waitFor(() => {
106
+ expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
107
+ });
108
+ });
109
+ it('should handle paste event', async () => {
110
+ const formatted = '<p>Formatted Paste</p>';
111
+ vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
112
+ render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { readOnly: false })));
113
+ const textarea = screen.getByRole('textbox');
114
+ const pasteData = 'Pasted Text';
115
+ const pasteEvent = createEvent.paste(textarea, {
116
+ clipboardData: {
117
+ getData: vi.fn().mockReturnValue(pasteData)
118
+ }
119
+ });
120
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
+ pasteEvent.preventDefault = vi.fn();
122
+ fireEvent(textarea, pasteEvent);
123
+ await waitFor(() => {
124
+ var _a;
125
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
+ expect(pasteEvent.preventDefault).toHaveBeenCalled();
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ expect((_a = pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData).toHaveBeenCalledWith('text/plain');
129
+ expect(formatHtmlWithPrettier).toHaveBeenCalled();
130
+ expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
131
+ });
132
+ });
133
+ it('should not handle paste event if readOnly is true', () => {
134
+ render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { readOnly: true })));
135
+ const textarea = screen.getByRole('textbox');
136
+ const pasteEvent = createEvent.paste(textarea, {
137
+ clipboardData: {
138
+ getData: vi.fn().mockReturnValue('Some Text')
139
+ }
140
+ });
141
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
+ pasteEvent.preventDefault = vi.fn();
143
+ fireEvent(textarea, pasteEvent);
144
+ expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ expect(pasteEvent.preventDefault).not.toHaveBeenCalled();
147
+ });
148
+ it('should not handle paste event if clipboard text is empty', () => {
149
+ render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps)));
150
+ // Clear mock because formatOnMount triggers it
151
+ vi.mocked(formatHtmlWithPrettier).mockClear();
152
+ const textarea = screen.getByRole('textbox');
153
+ const pasteEvent = createEvent.paste(textarea, {
154
+ clipboardData: {
155
+ getData: vi.fn().mockReturnValue('')
156
+ }
157
+ });
158
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
+ pasteEvent.preventDefault = vi.fn();
160
+ fireEvent(textarea, pasteEvent);
161
+ expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ expect(pasteEvent.preventDefault).toHaveBeenCalled(); // preventDefault is called before check? No, line 83 calls preventDefault.
164
+ });
89
165
  });
@@ -1,10 +1,17 @@
1
1
  import '@testing-library/jest-dom';
2
2
 
3
- import { fireEvent, render, screen } from '@testing-library/react';
3
+ import {
4
+ createEvent,
5
+ fireEvent,
6
+ render,
7
+ screen,
8
+ waitFor
9
+ } from '@testing-library/react';
4
10
  import { ConfigProvider } from 'antd';
5
11
  import React from 'react';
6
12
  import { beforeEach, describe, expect, it, vi } from 'vitest';
7
13
 
14
+ import { formatHtmlWithPrettier } from '../../utils';
8
15
  import { HtmlCodeViewer } from '../html-code-viewer';
9
16
 
10
17
  vi.mock('@ant-design/cssinjs', () => ({
@@ -15,7 +22,15 @@ vi.mock('@ant-design/cssinjs', () => ({
15
22
  }));
16
23
 
17
24
  vi.mock('@akinon/ui-theme', () => ({
18
- useToken: () => ({ token: {}, hashId: 'hash-id' })
25
+ useToken: () => ({ token: {}, hashId: 'hash-id' }),
26
+ getSafeCustomTokens: vi.fn(() => ({
27
+ border: { borderWidthThick: '2px', borderSolid: 'solid' }
28
+ }))
29
+ }));
30
+
31
+ vi.mock('../../utils', () => ({
32
+ highlightHtml: (html: string) => html,
33
+ formatHtmlWithPrettier: vi.fn((html: string) => Promise.resolve(html))
19
34
  }));
20
35
 
21
36
  describe('HtmlCodeViewer', () => {
@@ -109,7 +124,11 @@ describe('HtmlCodeViewer', () => {
109
124
  neutral: {
110
125
  '50': '#fff',
111
126
  '1000': '#000'
112
- }
127
+ },
128
+ red: { '825': '#f00', '999': '#a00', '815': '#d00' },
129
+ blue: { '999': '#00f' },
130
+ green: { '825': '#0f0' },
131
+ ebonyClay: { '550': '#123' }
113
132
  }
114
133
  };
115
134
 
@@ -123,4 +142,88 @@ describe('HtmlCodeViewer', () => {
123
142
  const textarea = screen.getByRole('textbox');
124
143
  expect(textarea).toBeInTheDocument();
125
144
  });
145
+
146
+ it('should format code on mount', async () => {
147
+ const formatted = '<p> Formatted </p>';
148
+ vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
149
+
150
+ render(<HtmlCodeViewer {...defaultProps} value="<p>Raw</p>" />);
151
+
152
+ await waitFor(() => {
153
+ expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
154
+ });
155
+ });
156
+
157
+ it('should handle paste event', async () => {
158
+ const formatted = '<p>Formatted Paste</p>';
159
+ vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
160
+
161
+ render(<HtmlCodeViewer {...defaultProps} readOnly={false} />);
162
+ const textarea = screen.getByRole('textbox');
163
+
164
+ const pasteData = 'Pasted Text';
165
+
166
+ const pasteEvent = createEvent.paste(textarea, {
167
+ clipboardData: {
168
+ getData: vi.fn().mockReturnValue(pasteData)
169
+ }
170
+ });
171
+
172
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
173
+ (pasteEvent as any).preventDefault = vi.fn();
174
+
175
+ fireEvent(textarea, pasteEvent);
176
+
177
+ await waitFor(() => {
178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
+ expect((pasteEvent as any).preventDefault).toHaveBeenCalled();
180
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
181
+ expect((pasteEvent as any).clipboardData?.getData).toHaveBeenCalledWith(
182
+ 'text/plain'
183
+ );
184
+ expect(formatHtmlWithPrettier).toHaveBeenCalled();
185
+ expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
186
+ });
187
+ });
188
+
189
+ it('should not handle paste event if readOnly is true', () => {
190
+ render(<HtmlCodeViewer {...defaultProps} readOnly={true} />);
191
+ const textarea = screen.getByRole('textbox');
192
+
193
+ const pasteEvent = createEvent.paste(textarea, {
194
+ clipboardData: {
195
+ getData: vi.fn().mockReturnValue('Some Text')
196
+ }
197
+ });
198
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
+ (pasteEvent as any).preventDefault = vi.fn();
200
+
201
+ fireEvent(textarea, pasteEvent);
202
+
203
+ expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
204
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
205
+ expect((pasteEvent as any).preventDefault).not.toHaveBeenCalled();
206
+ });
207
+
208
+ it('should not handle paste event if clipboard text is empty', () => {
209
+ render(<HtmlCodeViewer {...defaultProps} />);
210
+ // Clear mock because formatOnMount triggers it
211
+ vi.mocked(formatHtmlWithPrettier).mockClear();
212
+
213
+ const textarea = screen.getByRole('textbox');
214
+
215
+ const pasteEvent = createEvent.paste(textarea, {
216
+ clipboardData: {
217
+ getData: vi.fn().mockReturnValue('')
218
+ }
219
+ });
220
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
221
+ (pasteEvent as any).preventDefault = vi.fn();
222
+
223
+ fireEvent(textarea, pasteEvent);
224
+
225
+ expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
226
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
227
+ expect((pasteEvent as any).preventDefault).toHaveBeenCalled(); // preventDefault is called before check? No, line 83 calls preventDefault.
228
+ });
126
229
  });
@@ -9,6 +9,7 @@ const { mockUseEditor, mockChangeLanguage } = vi.hoisted(() => ({
9
9
  mockUseEditor: vi.fn(),
10
10
  mockChangeLanguage: vi.fn()
11
11
  }));
12
+ vi.useFakeTimers();
12
13
  vi.mock('@tiptap/react', () => ({
13
14
  useEditor: mockUseEditor,
14
15
  useEditorState: vi.fn(() => ({})),
@@ -42,8 +43,7 @@ vi.mock('../../assets/icons', () => ({
42
43
  }));
43
44
  vi.mock('../../utils', () => ({
44
45
  getExtensions: vi.fn(() => []),
45
- formatHtml: vi.fn(html => `formatted-${html}`),
46
- normalizeHtml: vi.fn(html => `normalized-${html}`)
46
+ cleanDuplicateSpans: vi.fn(html => html)
47
47
  }));
48
48
  vi.mock('@akinon/akilocale/react', () => ({
49
49
  useTranslation: () => ({
@@ -53,7 +53,8 @@ vi.mock('@akinon/akilocale/react', () => ({
53
53
  }));
54
54
  vi.mock('@akinon/ui-theme', () => ({
55
55
  getSafeCustomTokens: vi.fn(() => ({
56
- typography: { fontWeightMedium: 500 }
56
+ typography: { fontWeightMedium: 500 },
57
+ border: { borderWidthThick: '2px', borderSolid: 'solid' }
57
58
  })),
58
59
  useToken: () => ({
59
60
  token: { colorBorder: '#ccc' },
@@ -83,6 +84,10 @@ describe('Tiptap', () => {
83
84
  }
84
85
  };
85
86
  mockUseEditor.mockReturnValue(mockEditor);
87
+ vi.useFakeTimers();
88
+ });
89
+ afterEach(() => {
90
+ vi.useRealTimers();
86
91
  });
87
92
  const renderComponent = (props = {}) => {
88
93
  return render(React.createElement(Tiptap, Object.assign({ value: "<p>Test</p>", onChange: onChange }, props)));
@@ -116,7 +121,9 @@ describe('Tiptap', () => {
116
121
  expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
117
122
  fireEvent.click(toggleButton);
118
123
  expect(screen.getByTestId('editor-content')).toBeInTheDocument();
119
- expect(mockEditor.commands.setContent).toHaveBeenCalledWith('normalized-formatted-<p>Initial Content</p>', { emitUpdate: false });
124
+ expect(mockEditor.commands.setContent).toHaveBeenCalledWith('<p>Test</p>', {
125
+ emitUpdate: false
126
+ });
120
127
  fireEvent.click(toggleButton);
121
128
  expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
122
129
  });
@@ -124,6 +131,7 @@ describe('Tiptap', () => {
124
131
  renderComponent();
125
132
  const viewer = screen.getByTestId('html-code-viewer');
126
133
  fireEvent.change(viewer, { target: { value: '<p>New Content</p>' } });
134
+ vi.advanceTimersByTime(1000);
127
135
  expect(onChange).toHaveBeenCalledWith({
128
136
  html: '<p>New Content</p>',
129
137
  json: expect.any(Object)
@@ -272,4 +280,34 @@ describe('Tiptap', () => {
272
280
  expect(resultDiv).toBe(false);
273
281
  expect(preventDefault).not.toHaveBeenCalled();
274
282
  });
283
+ it('should debounce source code changes and clear previous timeout', () => {
284
+ renderComponent();
285
+ const viewer = screen.getByTestId('html-code-viewer');
286
+ fireEvent.change(viewer, { target: { value: '<p>Change 1</p>' } });
287
+ fireEvent.change(viewer, { target: { value: '<p>Change 2</p>' } });
288
+ vi.advanceTimersByTime(300);
289
+ expect(onChange).toHaveBeenCalledWith({
290
+ html: '<p>Change 2</p>',
291
+ json: expect.any(Object)
292
+ });
293
+ expect(onChange).toHaveBeenCalledTimes(1);
294
+ });
295
+ it('should initialize with empty string if value and defaultValue are undefined', () => {
296
+ render(React.createElement(Tiptap, { onChange: onChange }));
297
+ const viewer = screen.getByTestId('html-code-viewer');
298
+ expect(viewer).toHaveValue('');
299
+ });
300
+ it('should remove type="text/inert" from script tags when switching to source mode', () => {
301
+ // Start in visual mode
302
+ render(React.createElement(Tiptap, { defaultSourceMode: false, onChange: onChange }));
303
+ // Mock editor.getHTML() to return content with inert script
304
+ mockEditor.getHTML.mockReturnValue('<script type="text/inert">console.log("test")</script>');
305
+ // Switch to source mode
306
+ const toggleButton = screen.getByTestId('toggle-source');
307
+ fireEvent.click(toggleButton);
308
+ // Verify source mode content (cleanDuplicateSpans is mocked to return input)
309
+ // The setRawHTML update triggers a re-render of HtmlCodeViewer
310
+ const viewer = screen.getByTestId('html-code-viewer');
311
+ expect(viewer).toHaveValue('<script>console.log("test")</script>');
312
+ });
275
313
  });
@@ -13,6 +13,8 @@ const { mockUseEditor, mockChangeLanguage } = vi.hoisted(() => ({
13
13
  mockChangeLanguage: vi.fn()
14
14
  }));
15
15
 
16
+ vi.useFakeTimers();
17
+
16
18
  vi.mock('@tiptap/react', () => ({
17
19
  useEditor: mockUseEditor,
18
20
  useEditorState: vi.fn(() => ({})),
@@ -71,8 +73,7 @@ vi.mock('../../assets/icons', () => ({
71
73
 
72
74
  vi.mock('../../utils', () => ({
73
75
  getExtensions: vi.fn(() => []),
74
- formatHtml: vi.fn(html => `formatted-${html}`),
75
- normalizeHtml: vi.fn(html => `normalized-${html}`)
76
+ cleanDuplicateSpans: vi.fn(html => html)
76
77
  }));
77
78
 
78
79
  vi.mock('@akinon/akilocale/react', () => ({
@@ -84,7 +85,8 @@ vi.mock('@akinon/akilocale/react', () => ({
84
85
 
85
86
  vi.mock('@akinon/ui-theme', () => ({
86
87
  getSafeCustomTokens: vi.fn(() => ({
87
- typography: { fontWeightMedium: 500 }
88
+ typography: { fontWeightMedium: 500 },
89
+ border: { borderWidthThick: '2px', borderSolid: 'solid' }
88
90
  })),
89
91
  useToken: () => ({
90
92
  token: { colorBorder: '#ccc' },
@@ -118,6 +120,11 @@ describe('Tiptap', () => {
118
120
  };
119
121
 
120
122
  mockUseEditor.mockReturnValue(mockEditor);
123
+ vi.useFakeTimers();
124
+ });
125
+
126
+ afterEach(() => {
127
+ vi.useRealTimers();
121
128
  });
122
129
 
123
130
  const renderComponent = (props = {}) => {
@@ -161,10 +168,9 @@ describe('Tiptap', () => {
161
168
 
162
169
  fireEvent.click(toggleButton);
163
170
  expect(screen.getByTestId('editor-content')).toBeInTheDocument();
164
- expect(mockEditor.commands.setContent).toHaveBeenCalledWith(
165
- 'normalized-formatted-<p>Initial Content</p>',
166
- { emitUpdate: false }
167
- );
171
+ expect(mockEditor.commands.setContent).toHaveBeenCalledWith('<p>Test</p>', {
172
+ emitUpdate: false
173
+ });
168
174
 
169
175
  fireEvent.click(toggleButton);
170
176
  expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
@@ -176,6 +182,8 @@ describe('Tiptap', () => {
176
182
 
177
183
  fireEvent.change(viewer, { target: { value: '<p>New Content</p>' } });
178
184
 
185
+ vi.advanceTimersByTime(1000);
186
+
179
187
  expect(onChange).toHaveBeenCalledWith({
180
188
  html: '<p>New Content</p>',
181
189
  json: expect.any(Object)
@@ -375,4 +383,46 @@ describe('Tiptap', () => {
375
383
  expect(resultDiv).toBe(false);
376
384
  expect(preventDefault).not.toHaveBeenCalled();
377
385
  });
386
+ it('should debounce source code changes and clear previous timeout', () => {
387
+ renderComponent();
388
+ const viewer = screen.getByTestId('html-code-viewer');
389
+
390
+ fireEvent.change(viewer, { target: { value: '<p>Change 1</p>' } });
391
+
392
+ fireEvent.change(viewer, { target: { value: '<p>Change 2</p>' } });
393
+
394
+ vi.advanceTimersByTime(300);
395
+
396
+ expect(onChange).toHaveBeenCalledWith({
397
+ html: '<p>Change 2</p>',
398
+ json: expect.any(Object)
399
+ });
400
+
401
+ expect(onChange).toHaveBeenCalledTimes(1);
402
+ });
403
+
404
+ it('should initialize with empty string if value and defaultValue are undefined', () => {
405
+ render(<Tiptap onChange={onChange} />);
406
+ const viewer = screen.getByTestId('html-code-viewer');
407
+ expect(viewer).toHaveValue('');
408
+ });
409
+
410
+ it('should remove type="text/inert" from script tags when switching to source mode', () => {
411
+ // Start in visual mode
412
+ render(<Tiptap defaultSourceMode={false} onChange={onChange} />);
413
+
414
+ // Mock editor.getHTML() to return content with inert script
415
+ mockEditor.getHTML.mockReturnValue(
416
+ '<script type="text/inert">console.log("test")</script>'
417
+ );
418
+
419
+ // Switch to source mode
420
+ const toggleButton = screen.getByTestId('toggle-source');
421
+ fireEvent.click(toggleButton);
422
+
423
+ // Verify source mode content (cleanDuplicateSpans is mocked to return input)
424
+ // The setRawHTML update triggers a re-render of HtmlCodeViewer
425
+ const viewer = screen.getByTestId('html-code-viewer');
426
+ expect(viewer).toHaveValue('<script>console.log("test")</script>');
427
+ });
378
428
  });
@@ -1 +1 @@
1
- {"version":3,"file":"format-bubble-menu.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/format-bubble-menu.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,GAAI,YAAY,qBAAqB,6BAiRjE,CAAC"}
1
+ {"version":3,"file":"format-bubble-menu.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/format-bubble-menu.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,GAAI,YAAY,qBAAqB,6BAmRjE,CAAC"}
@@ -164,6 +164,11 @@ export const FormatBubbleMenu = ({ editor }) => {
164
164
  tooltip: i18n.t('editor.toolbar.link')
165
165
  }
166
166
  ];
167
+ const handleOnInputKeyDown = (e) => {
168
+ if (e.key === 'Enter') {
169
+ handleApplyLink();
170
+ }
171
+ };
167
172
  return useStyle(React.createElement(BubbleMenu, { editor: editor, pluginKey: "link-bubble-menu", options: { placement: 'bottom' }, shouldShow: ({ editor }) => {
168
173
  if (!isTextSelection(editor.state.selection) ||
169
174
  editor.isActive('table')) {
@@ -191,11 +196,7 @@ export const FormatBubbleMenu = ({ editor }) => {
191
196
  return from !== to && editor.isFocused;
192
197
  } },
193
198
  React.createElement("div", { className: `${baseCls} ${hashId}` }, showLinkInput ? (React.createElement(React.Fragment, null,
194
- React.createElement(Input, { type: "text", placeholder: i18n.t('editor.link.url_placeholder'), value: url, autoFocus: true, onChange: e => setUrl(e.target.value), onKeyDown: e => {
195
- if (e.key === 'Enter') {
196
- handleApplyLink();
197
- }
198
- }, size: "small", className: `${baseCls}__link-input` }),
199
+ React.createElement(Input, { type: "text", placeholder: i18n.t('editor.link.url_placeholder'), value: url, autoFocus: true, onChange: e => setUrl(e.target.value), onKeyDown: handleOnInputKeyDown, size: "small", className: `${baseCls}__link-input` }),
199
200
  React.createElement("div", { className: `${baseCls}__actions` },
200
201
  React.createElement(Button, { size: "small", type: "success", icon: "katalogkontrol", onClick: handleApplyLink, disabled: !url, tooltip: i18n.t('editor.common.save') }),
201
202
  React.createElement(Button, { size: "small", type: "default", danger: true, icon: "bin", onClick: handleRemoveLink, tooltip: i18n.t('editor.common.remove') })))) : (React.createElement("div", { className: `${baseCls}__actions` }, formattingButtons.map((btn, index) => (React.createElement(Button, { key: index, type: "icon", size: "small", onClick: btn.onClick, icon: btn.icon, className: btn.isActive ? activeCls : '', tooltip: btn.tooltip }))))))));
@@ -4,7 +4,8 @@ interface HtmlCodeViewerProps {
4
4
  onChange: (value: string) => void;
5
5
  className?: string;
6
6
  readOnly?: boolean;
7
+ contentHeight?: number;
7
8
  }
8
- export declare const HtmlCodeViewer: ({ value, onChange, className, readOnly }: HtmlCodeViewerProps) => React.JSX.Element;
9
+ export declare const HtmlCodeViewer: ({ value, onChange, className, contentHeight, readOnly }: HtmlCodeViewerProps) => React.JSX.Element;
9
10
  export {};
10
11
  //# sourceMappingURL=html-code-viewer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-code-viewer.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/html-code-viewer.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAKtC,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,GAAI,0CAK5B,mBAAmB,sBAmHrB,CAAC"}
1
+ {"version":3,"file":"html-code-viewer.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/html-code-viewer.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,yDAM5B,mBAAmB,sBA2KrB,CAAC"}
@@ -1,38 +1,78 @@
1
- import { useToken } from '@akinon/ui-theme';
1
+ import { getSafeCustomTokens, useToken } from '@akinon/ui-theme';
2
2
  import { useStyleRegister } from '@ant-design/cssinjs';
3
3
  import { ConfigProvider } from 'antd';
4
- import React, { useRef } from 'react';
5
- import { EDITOR_HEIGHT } from '../constants';
6
- import { highlightHtml } from '../utils';
7
- export const HtmlCodeViewer = ({ value, onChange, className, readOnly = false }) => {
4
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
5
+ import { EDITOR_CONTENT_HEIGHT } from '../constants';
6
+ import { formatHtmlWithPrettier, highlightHtml } from '../utils';
7
+ export const HtmlCodeViewer = ({ value, onChange, className, contentHeight = EDITOR_CONTENT_HEIGHT, readOnly = false }) => {
8
8
  const { getPrefixCls, theme } = React.useContext(ConfigProvider.ConfigContext);
9
9
  const { token, hashId } = useToken();
10
10
  const baseCls = getPrefixCls('html-code-viewer');
11
11
  const preRef = useRef(null);
12
12
  const colors = (theme === null || theme === void 0 ? void 0 : theme.colors) || {};
13
- const handleScroll = (e) => {
13
+ const handleScroll = useCallback((e) => {
14
14
  if (preRef.current) {
15
15
  preRef.current.scrollTop = e.currentTarget.scrollTop;
16
16
  preRef.current.scrollLeft = e.currentTarget.scrollLeft;
17
17
  }
18
- };
18
+ }, []);
19
+ const handleChange = useCallback((e) => {
20
+ onChange(e.target.value);
21
+ }, [onChange]);
22
+ useEffect(() => {
23
+ {
24
+ /*
25
+ Auto-format on mount (switching to source mode).
26
+ The isMounted check is necessary because formatHtmlWithPrettier is async.
27
+ If the component unmounts before format completes, we must not call onChange
28
+ to avoid "state update on unmounted component" errors.
29
+ */
30
+ }
31
+ let isMounted = true;
32
+ const formatOnMount = async () => {
33
+ if (value && !readOnly) {
34
+ const formatted = await formatHtmlWithPrettier(value);
35
+ if (isMounted && formatted !== value) {
36
+ onChange(formatted);
37
+ }
38
+ }
39
+ };
40
+ formatOnMount();
41
+ return () => {
42
+ isMounted = false;
43
+ };
44
+ }, []);
45
+ const handlePaste = useCallback(async (e) => {
46
+ if (readOnly)
47
+ return;
48
+ e.preventDefault();
49
+ const pastedText = e.clipboardData.getData('text/plain');
50
+ if (!pastedText)
51
+ return;
52
+ const textarea = e.currentTarget;
53
+ const start = textarea.selectionStart;
54
+ const end = textarea.selectionEnd;
55
+ const newValue = value.substring(0, start) + pastedText + value.substring(end);
56
+ const formatted = await formatHtmlWithPrettier(newValue);
57
+ onChange(formatted);
58
+ }, [readOnly, value, onChange]);
19
59
  const useStyle = useStyleRegister({
20
60
  token: token,
21
- path: ['HtmlCodeViewer'],
61
+ path: ['HtmlCodeViewer', String(contentHeight)],
22
62
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
63
  theme: theme
24
64
  }, () => {
25
65
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
26
66
  const prefixCls = `:where(.${hashId}).${baseCls}`;
67
+ const customTokens = getSafeCustomTokens(theme);
27
68
  return {
28
69
  [prefixCls]: {
29
70
  position: 'relative',
30
- width: '100%',
31
- minHeight: EDITOR_HEIGHT,
32
- height: EDITOR_HEIGHT,
33
- marginTop: '10px',
34
- border: `1px solid ${(_a = colors.editor) === null || _a === void 0 ? void 0 : _a.border}`,
35
- borderRadius: '5px',
71
+ minHeight: `${contentHeight}px`,
72
+ height: `${contentHeight}px`,
73
+ border: `${customTokens.border.borderWidthThick} ${customTokens.border.borderSolid} ${(_a = colors.ebonyClay) === null || _a === void 0 ? void 0 : _a['550']}`,
74
+ borderBottomLeftRadius: '5px',
75
+ borderBottomRightRadius: '5px',
36
76
  backgroundColor: (_b = colors.neutral) === null || _b === void 0 ? void 0 : _b['50'],
37
77
  overflow: 'hidden',
38
78
  '& textarea, & pre': {
@@ -68,29 +108,29 @@ export const HtmlCodeViewer = ({ value, onChange, className, readOnly = false })
68
108
  color: (_d = colors.neutral) === null || _d === void 0 ? void 0 : _d['1000']
69
109
  },
70
110
  '.html-tag': {
71
- color: (_e = colors.editor) === null || _e === void 0 ? void 0 : _e.tag
111
+ color: (_e = colors.red) === null || _e === void 0 ? void 0 : _e['825']
72
112
  },
73
113
  '.html-attr': {
74
- color: (_f = colors.editor) === null || _f === void 0 ? void 0 : _f.attr
114
+ color: (_f = colors.red) === null || _f === void 0 ? void 0 : _f['999']
75
115
  },
76
116
  '.html-value': {
77
- color: (_g = colors.editor) === null || _g === void 0 ? void 0 : _g.value
117
+ color: (_g = colors.blue) === null || _g === void 0 ? void 0 : _g['999']
78
118
  },
79
119
  '.html-comment': {
80
- color: (_h = colors.editor) === null || _h === void 0 ? void 0 : _h.comment,
120
+ color: (_h = colors.green) === null || _h === void 0 ? void 0 : _h['825'],
81
121
  fontStyle: 'italic'
82
122
  },
83
123
  '.html-doctype': {
84
- color: (_j = colors.editor) === null || _j === void 0 ? void 0 : _j.tag
124
+ color: (_j = colors.red) === null || _j === void 0 ? void 0 : _j['825']
85
125
  },
86
126
  '.html-string': {
87
- color: (_k = colors.editor) === null || _k === void 0 ? void 0 : _k.string
127
+ color: (_k = colors.red) === null || _k === void 0 ? void 0 : _k['815']
88
128
  }
89
129
  }
90
130
  };
91
131
  });
92
- const highlightedHtml = highlightHtml(value) + (value.endsWith('\n') ? '<br>' : '');
132
+ const highlightedHtml = useMemo(() => highlightHtml(value) + (value.endsWith('\n') ? '<br>' : ''), [value]);
93
133
  return useStyle(React.createElement("div", { className: `${baseCls} ${hashId} ${className || ''}` },
94
- React.createElement("textarea", { value: value, onChange: e => onChange(e.target.value), onScroll: handleScroll, readOnly: readOnly, spellCheck: false, autoCapitalize: "off", autoComplete: "off", autoCorrect: "off" }),
134
+ React.createElement("textarea", { value: value, onChange: handleChange, onPaste: handlePaste, onScroll: handleScroll, readOnly: readOnly, spellCheck: false, autoCapitalize: "off", autoComplete: "off", autoCorrect: "off" }),
95
135
  React.createElement("pre", { ref: preRef, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: highlightedHtml } })));
96
136
  };
@@ -1 +1 @@
1
- {"version":3,"file":"image-upload-placeholder.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/image-upload-placeholder.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAmB,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,sBAAsB,GAAI,0BAIpC,aAAa,sBA8Ff,CAAC"}
1
+ {"version":3,"file":"image-upload-placeholder.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/image-upload-placeholder.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAmB,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,sBAAsB,GAAI,0BAIpC,aAAa,sBAiGf,CAAC"}
@@ -48,7 +48,7 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
48
48
  borderRadius: '8px',
49
49
  textAlign: 'center',
50
50
  width: '50%',
51
- backgroundColor: (_b = colors === null || colors === void 0 ? void 0 : colors.editor) === null || _b === void 0 ? void 0 : _b.imageUploadBg,
51
+ backgroundColor: (_b = colors.neutral) === null || _b === void 0 ? void 0 : _b['50-05'],
52
52
  ['.ant-upload-wrapper .ant-upload-drag']: {
53
53
  background: 'transparent',
54
54
  border: 'none',
@@ -68,6 +68,9 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
68
68
  color: (_e = colors.gray) === null || _e === void 0 ? void 0 : _e['500'],
69
69
  fontSize: '2rem'
70
70
  }
71
+ },
72
+ [`${prefixCls}-content`]: {
73
+ pointerEvents: 'none'
71
74
  }
72
75
  };
73
76
  });
@@ -86,7 +89,7 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
86
89
  return useStyle(React.createElement(NodeViewWrapper, { className: `${baseCls}-wrapper ${hashId}` },
87
90
  React.createElement("div", { className: `${baseCls} ${hashId}` },
88
91
  React.createElement(Upload.Dragger, { name: "file", multiple: false, showUploadList: false, beforeUpload: handleImageUpload },
89
- React.createElement("div", { style: { pointerEvents: 'none' } },
92
+ React.createElement("div", { className: `${baseCls}-content ${hashId}` },
90
93
  React.createElement("p", { className: "ant-upload-drag-icon" },
91
94
  React.createElement(Button, { type: "icon", icon: "add_picture", size: "small" })),
92
95
  React.createElement("p", { className: "ant-upload-text" }, i18n.t('editor.image_upload.click_to_upload')),