@x-plat/design-system 0.10.0 → 0.11.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 (110) hide show
  1. package/dist/components/AutoResizeTextArea/index.cjs +14 -5
  2. package/dist/components/AutoResizeTextArea/index.css +15 -0
  3. package/dist/components/AutoResizeTextArea/index.d.cts +4 -0
  4. package/dist/components/AutoResizeTextArea/index.d.ts +4 -0
  5. package/dist/components/AutoResizeTextArea/index.js +14 -5
  6. package/dist/components/Badge/index.d.cts +1 -1
  7. package/dist/components/Badge/index.d.ts +1 -1
  8. package/dist/components/ChatInput/index.cjs +20 -7
  9. package/dist/components/ChatInput/index.css +15 -0
  10. package/dist/components/ChatInput/index.d.cts +4 -0
  11. package/dist/components/ChatInput/index.d.ts +4 -0
  12. package/dist/components/ChatInput/index.js +20 -7
  13. package/dist/components/CheckBox/index.cjs +8 -3
  14. package/dist/components/CheckBox/index.css +15 -0
  15. package/dist/components/CheckBox/index.d.cts +1 -1
  16. package/dist/components/CheckBox/index.d.ts +1 -1
  17. package/dist/components/CheckBox/index.js +8 -3
  18. package/dist/components/DatePicker/index.cjs +179 -64
  19. package/dist/components/DatePicker/index.css +19 -0
  20. package/dist/components/DatePicker/index.js +179 -64
  21. package/dist/components/Drawer/index.cjs +83 -4
  22. package/dist/components/Drawer/index.js +83 -4
  23. package/dist/components/Dropdown/index.cjs +35 -7
  24. package/dist/components/Dropdown/index.js +35 -7
  25. package/dist/components/Editor/index.cjs +178 -21
  26. package/dist/components/Editor/index.js +178 -21
  27. package/dist/components/FieldMessage/index.cjs +8 -3
  28. package/dist/components/FieldMessage/index.css +15 -0
  29. package/dist/components/FieldMessage/index.d.cts +11 -4
  30. package/dist/components/FieldMessage/index.d.ts +11 -4
  31. package/dist/components/FieldMessage/index.js +8 -3
  32. package/dist/components/FileUpload/index.cjs +8 -3
  33. package/dist/components/FileUpload/index.css +15 -0
  34. package/dist/components/FileUpload/index.js +8 -3
  35. package/dist/components/ImageSelector/index.cjs +8 -3
  36. package/dist/components/ImageSelector/index.css +15 -0
  37. package/dist/components/ImageSelector/index.js +8 -3
  38. package/dist/components/Input/index.cjs +15 -5
  39. package/dist/components/Input/index.css +15 -0
  40. package/dist/components/Input/index.d.cts +4 -0
  41. package/dist/components/Input/index.d.ts +4 -0
  42. package/dist/components/Input/index.js +15 -5
  43. package/dist/components/Modal/index.cjs +84 -5
  44. package/dist/components/Modal/index.js +84 -5
  45. package/dist/components/NotificationBadge/index.d.cts +1 -1
  46. package/dist/components/NotificationBadge/index.d.ts +1 -1
  47. package/dist/components/Pagination/index.d.cts +1 -1
  48. package/dist/components/Pagination/index.d.ts +1 -1
  49. package/dist/components/PopOver/index.cjs +34 -6
  50. package/dist/components/PopOver/index.js +34 -6
  51. package/dist/components/Progress/index.d.cts +1 -1
  52. package/dist/components/Progress/index.d.ts +1 -1
  53. package/dist/components/Radio/index.cjs +8 -3
  54. package/dist/components/Radio/index.css +15 -0
  55. package/dist/components/Radio/index.d.cts +1 -1
  56. package/dist/components/Radio/index.d.ts +1 -1
  57. package/dist/components/Radio/index.js +8 -3
  58. package/dist/components/Select/index.cjs +99 -31
  59. package/dist/components/Select/index.css +54 -0
  60. package/dist/components/Select/index.d.cts +11 -0
  61. package/dist/components/Select/index.d.ts +11 -0
  62. package/dist/components/Select/index.js +99 -31
  63. package/dist/components/Spinner/index.d.cts +1 -1
  64. package/dist/components/Spinner/index.d.ts +1 -1
  65. package/dist/components/Stat/index.cjs +84 -0
  66. package/dist/components/Stat/index.css +96 -0
  67. package/dist/components/Stat/index.d.cts +37 -0
  68. package/dist/components/Stat/index.d.ts +37 -0
  69. package/dist/components/Stat/index.js +57 -0
  70. package/dist/components/Steps/index.d.cts +1 -1
  71. package/dist/components/Steps/index.d.ts +1 -1
  72. package/dist/components/Switch/index.cjs +14 -5
  73. package/dist/components/Switch/index.css +15 -0
  74. package/dist/components/Switch/index.d.cts +6 -1
  75. package/dist/components/Switch/index.d.ts +6 -1
  76. package/dist/components/Switch/index.js +14 -5
  77. package/dist/components/Tab/index.cjs +49 -25
  78. package/dist/components/Tab/index.css +4 -0
  79. package/dist/components/Tab/index.js +49 -25
  80. package/dist/components/TextArea/index.cjs +14 -4
  81. package/dist/components/TextArea/index.css +15 -0
  82. package/dist/components/TextArea/index.d.cts +4 -0
  83. package/dist/components/TextArea/index.d.ts +4 -0
  84. package/dist/components/TextArea/index.js +14 -4
  85. package/dist/components/TimePicker/index.cjs +448 -0
  86. package/dist/components/TimePicker/index.css +172 -0
  87. package/dist/components/TimePicker/index.d.cts +42 -0
  88. package/dist/components/TimePicker/index.d.ts +42 -0
  89. package/dist/components/TimePicker/index.js +411 -0
  90. package/dist/components/index.cjs +873 -359
  91. package/dist/components/index.css +275 -0
  92. package/dist/components/index.d.cts +3 -1
  93. package/dist/components/index.d.ts +3 -1
  94. package/dist/components/index.js +871 -359
  95. package/dist/index.cjs +897 -383
  96. package/dist/index.css +275 -0
  97. package/dist/index.d.cts +3 -1
  98. package/dist/index.d.ts +3 -1
  99. package/dist/index.js +895 -383
  100. package/dist/status-njWqQWFV.d.cts +20 -0
  101. package/dist/status-njWqQWFV.d.ts +20 -0
  102. package/guidelines/AGENT_PROMPT.md +3 -3
  103. package/guidelines/Guidelines.md +3 -0
  104. package/guidelines/components/editor.md +86 -0
  105. package/guidelines/components/form.md +19 -0
  106. package/guidelines/components/stat.md +31 -0
  107. package/guidelines/components/time-picker.md +49 -0
  108. package/package.json +1 -1
  109. package/dist/status-g_KP3qT6.d.cts +0 -8
  110. package/dist/status-g_KP3qT6.d.ts +0 -8
@@ -35,7 +35,7 @@ __export(Dropdown_exports, {
35
35
  module.exports = __toCommonJS(Dropdown_exports);
36
36
 
37
37
  // src/components/Dropdown/Dropdown.tsx
38
- var import_react3 = __toESM(require("react"), 1);
38
+ var import_react4 = __toESM(require("react"), 1);
39
39
 
40
40
  // src/tokens/hooks/Portal.tsx
41
41
  var import_react_dom = __toESM(require("react-dom"), 1);
@@ -132,6 +132,30 @@ var useClickOutside = (refs, handler, enabled = true) => {
132
132
  };
133
133
  var useClickOutside_default = useClickOutside;
134
134
 
135
+ // src/tokens/hooks/useOverlayKeyboard.ts
136
+ var import_react3 = __toESM(require("react"), 1);
137
+ var FOCUSABLE = [
138
+ "a[href]",
139
+ "button:not([disabled])",
140
+ "input:not([disabled]):not([type='hidden'])",
141
+ "select:not([disabled])",
142
+ "textarea:not([disabled])",
143
+ "[tabindex]:not([tabindex='-1'])"
144
+ ].join(",");
145
+ var useEscapeKey = (enabled, onEscape) => {
146
+ import_react3.default.useEffect(() => {
147
+ if (!enabled) return;
148
+ const onKey = (e) => {
149
+ if (e.key !== "Escape") return;
150
+ if (e.defaultPrevented) return;
151
+ e.preventDefault();
152
+ onEscape();
153
+ };
154
+ document.addEventListener("keydown", onKey);
155
+ return () => document.removeEventListener("keydown", onKey);
156
+ }, [enabled, onEscape]);
157
+ };
158
+
135
159
  // ../../node_modules/clsx/dist/clsx.mjs
136
160
  function r(e) {
137
161
  var t, f, n = "";
@@ -152,14 +176,18 @@ var clsx_default = clsx;
152
176
  var import_jsx_runtime = require("react/jsx-runtime");
153
177
  var Dropdown = (props) => {
154
178
  const { items, children } = props;
155
- const [isOpen, setIsOpen] = import_react3.default.useState(false);
156
- const [mounted, setMounted] = import_react3.default.useState(false);
157
- const [visible, setVisible] = import_react3.default.useState(false);
158
- const triggerRef = import_react3.default.useRef(null);
159
- const menuRef = import_react3.default.useRef(null);
179
+ const [isOpen, setIsOpen] = import_react4.default.useState(false);
180
+ const [mounted, setMounted] = import_react4.default.useState(false);
181
+ const [visible, setVisible] = import_react4.default.useState(false);
182
+ const triggerRef = import_react4.default.useRef(null);
183
+ const menuRef = import_react4.default.useRef(null);
160
184
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
161
185
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
162
- import_react3.default.useEffect(() => {
186
+ useEscapeKey(isOpen, () => {
187
+ setIsOpen(false);
188
+ triggerRef.current?.focus({ preventScroll: true });
189
+ });
190
+ import_react4.default.useEffect(() => {
163
191
  if (isOpen) {
164
192
  setMounted(true);
165
193
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -1,5 +1,5 @@
1
1
  // src/components/Dropdown/Dropdown.tsx
2
- import React3 from "react";
2
+ import React4 from "react";
3
3
 
4
4
  // src/tokens/hooks/Portal.tsx
5
5
  import ReactDOM from "react-dom";
@@ -96,6 +96,30 @@ var useClickOutside = (refs, handler, enabled = true) => {
96
96
  };
97
97
  var useClickOutside_default = useClickOutside;
98
98
 
99
+ // src/tokens/hooks/useOverlayKeyboard.ts
100
+ import React3 from "react";
101
+ var FOCUSABLE = [
102
+ "a[href]",
103
+ "button:not([disabled])",
104
+ "input:not([disabled]):not([type='hidden'])",
105
+ "select:not([disabled])",
106
+ "textarea:not([disabled])",
107
+ "[tabindex]:not([tabindex='-1'])"
108
+ ].join(",");
109
+ var useEscapeKey = (enabled, onEscape) => {
110
+ React3.useEffect(() => {
111
+ if (!enabled) return;
112
+ const onKey = (e) => {
113
+ if (e.key !== "Escape") return;
114
+ if (e.defaultPrevented) return;
115
+ e.preventDefault();
116
+ onEscape();
117
+ };
118
+ document.addEventListener("keydown", onKey);
119
+ return () => document.removeEventListener("keydown", onKey);
120
+ }, [enabled, onEscape]);
121
+ };
122
+
99
123
  // ../../node_modules/clsx/dist/clsx.mjs
100
124
  function r(e) {
101
125
  var t, f, n = "";
@@ -116,14 +140,18 @@ var clsx_default = clsx;
116
140
  import { jsx, jsxs } from "react/jsx-runtime";
117
141
  var Dropdown = (props) => {
118
142
  const { items, children } = props;
119
- const [isOpen, setIsOpen] = React3.useState(false);
120
- const [mounted, setMounted] = React3.useState(false);
121
- const [visible, setVisible] = React3.useState(false);
122
- const triggerRef = React3.useRef(null);
123
- const menuRef = React3.useRef(null);
143
+ const [isOpen, setIsOpen] = React4.useState(false);
144
+ const [mounted, setMounted] = React4.useState(false);
145
+ const [visible, setVisible] = React4.useState(false);
146
+ const triggerRef = React4.useRef(null);
147
+ const menuRef = React4.useRef(null);
124
148
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
125
149
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
126
- React3.useEffect(() => {
150
+ useEscapeKey(isOpen, () => {
151
+ setIsOpen(false);
152
+ triggerRef.current?.focus({ preventScroll: true });
153
+ });
154
+ React4.useEffect(() => {
127
155
  if (isOpen) {
128
156
  setMounted(true);
129
157
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -103,6 +103,15 @@ var ALLOWED_ATTRS = {
103
103
  a: ["href", "target", "rel"],
104
104
  img: ["src", "alt"]
105
105
  };
106
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
107
+ "script",
108
+ "style",
109
+ "noscript",
110
+ "iframe",
111
+ "object",
112
+ "embed",
113
+ "template"
114
+ ]);
106
115
  var sanitizeHtml = (input) => {
107
116
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
108
117
  const root = doc.body.firstElementChild;
@@ -111,6 +120,10 @@ var sanitizeHtml = (input) => {
111
120
  const children = Array.from(node.children);
112
121
  for (const child of children) {
113
122
  const tag = child.tagName.toLowerCase();
123
+ if (DROP_WITH_CONTENT.has(tag)) {
124
+ node.removeChild(child);
125
+ continue;
126
+ }
114
127
  if (!ALLOWED_TAGS.has(tag)) {
115
128
  while (child.firstChild) node.insertBefore(child.firstChild, child);
116
129
  node.removeChild(child);
@@ -175,12 +188,16 @@ var Editor = (props) => {
175
188
  const [linkOpen, setLinkOpen] = import_react.default.useState(false);
176
189
  const [linkValue, setLinkValue] = import_react.default.useState("");
177
190
  const [linkPos, setLinkPos] = import_react.default.useState({ top: 0, left: 0 });
191
+ const lastEmittedRef = import_react.default.useRef(null);
178
192
  import_react.default.useEffect(() => {
179
- if (!editorRef.current) return;
180
- if (editorRef.current.innerHTML !== value) {
181
- editorRef.current.innerHTML = sanitizeHtml(value || "");
182
- updateEmpty();
183
- }
193
+ const el = editorRef.current;
194
+ if (!el) return;
195
+ if (value === lastEmittedRef.current) return;
196
+ if (el.innerHTML === value) return;
197
+ el.innerHTML = sanitizeHtml(value || "");
198
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
199
+ lastEmittedRef.current = null;
200
+ updateEmpty();
184
201
  }, [value]);
185
202
  const updateEmpty = () => {
186
203
  const el = editorRef.current;
@@ -196,10 +213,19 @@ var Editor = (props) => {
196
213
  }
197
214
  };
198
215
  const restoreSelection = () => {
199
- if (!lastRangeRef.current) return;
216
+ const range = lastRangeRef.current;
217
+ if (!range) return;
218
+ if (!editorRef.current?.contains(range.startContainer)) {
219
+ lastRangeRef.current = null;
220
+ return;
221
+ }
200
222
  const sel = window.getSelection();
201
- sel?.removeAllRanges();
202
- sel?.addRange(lastRangeRef.current);
223
+ try {
224
+ sel?.removeAllRanges();
225
+ sel?.addRange(range);
226
+ } catch {
227
+ lastRangeRef.current = null;
228
+ }
203
229
  };
204
230
  const updateActiveFormats = () => {
205
231
  if (!editorRef.current) return;
@@ -228,6 +254,96 @@ var Editor = (props) => {
228
254
  const setBlock = (tag) => {
229
255
  exec("formatBlock", tag);
230
256
  };
257
+ const closestPre = () => {
258
+ const sel = window.getSelection();
259
+ const node = sel?.anchorNode;
260
+ if (!node || !editorRef.current?.contains(node)) return null;
261
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
262
+ return el?.closest("pre") ?? null;
263
+ };
264
+ const insertCodeBlock = () => {
265
+ const el = editorRef.current;
266
+ const sel = window.getSelection();
267
+ if (!el || !sel || sel.rangeCount === 0) return;
268
+ const existing = closestPre();
269
+ if (existing) {
270
+ const p = document.createElement("p");
271
+ p.textContent = existing.textContent || "";
272
+ if (!p.textContent) p.innerHTML = "<br>";
273
+ existing.replaceWith(p);
274
+ placeCaretAtEnd(p);
275
+ handleInput();
276
+ return;
277
+ }
278
+ const range = sel.getRangeAt(0);
279
+ const frag = range.cloneContents();
280
+ const holder = document.createElement("div");
281
+ holder.appendChild(frag);
282
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
283
+ const linesOf = (node) => {
284
+ const out = [];
285
+ let cur = "";
286
+ for (const child of Array.from(node.childNodes)) {
287
+ if (child.nodeType === Node.TEXT_NODE) {
288
+ cur += child.textContent || "";
289
+ } else if (child.nodeName === "BR") {
290
+ out.push(cur);
291
+ cur = "";
292
+ } else if (BLOCK.test(child.nodeName)) {
293
+ if (cur) {
294
+ out.push(cur);
295
+ cur = "";
296
+ }
297
+ const sub = linesOf(child);
298
+ out.push(...sub.length > 0 ? sub : [""]);
299
+ } else {
300
+ cur += linesOf(child).join("\n");
301
+ }
302
+ }
303
+ if (cur) out.push(cur);
304
+ return out;
305
+ };
306
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
307
+ const pre = document.createElement("pre");
308
+ const code = document.createElement("code");
309
+ code.textContent = text || "";
310
+ pre.appendChild(code);
311
+ range.deleteContents();
312
+ range.insertNode(pre);
313
+ ensureParagraphAfter(pre);
314
+ placeCaretAtEnd(code);
315
+ handleInput();
316
+ };
317
+ const insertTextAtCaret = (text) => {
318
+ const sel = window.getSelection();
319
+ if (!sel || sel.rangeCount === 0) return;
320
+ const range = sel.getRangeAt(0);
321
+ range.deleteContents();
322
+ const node = document.createTextNode(text);
323
+ range.insertNode(node);
324
+ range.setStartAfter(node);
325
+ range.collapse(true);
326
+ sel.removeAllRanges();
327
+ sel.addRange(range);
328
+ handleInput();
329
+ };
330
+ const ensureParagraphAfter = (node) => {
331
+ const next = node.nextElementSibling;
332
+ if (next && next.tagName === "P") return;
333
+ const p = document.createElement("p");
334
+ p.innerHTML = "<br>";
335
+ node.after(p);
336
+ };
337
+ const placeCaretAtEnd = (node) => {
338
+ const sel = window.getSelection();
339
+ if (!sel) return;
340
+ const r2 = document.createRange();
341
+ r2.selectNodeContents(node);
342
+ r2.collapse(false);
343
+ sel.removeAllRanges();
344
+ sel.addRange(r2);
345
+ editorRef.current?.focus();
346
+ };
231
347
  const insertDivider = () => {
232
348
  exec("insertHorizontalRule");
233
349
  const el = editorRef.current;
@@ -274,7 +390,9 @@ var Editor = (props) => {
274
390
  const range = sel.getRangeAt(0);
275
391
  slashStartRangeRef.current = range.cloneRange();
276
392
  const rect = range.getBoundingClientRect();
277
- const editorRect = editorRef.current.getBoundingClientRect();
393
+ const editorEl = editorRef.current;
394
+ if (!editorEl) return;
395
+ const editorRect = editorEl.getBoundingClientRect();
278
396
  setSlashPos({
279
397
  top: rect.bottom - editorRect.top + 4,
280
398
  left: rect.left - editorRect.left
@@ -332,7 +450,7 @@ var Editor = (props) => {
332
450
  setBlock("blockquote");
333
451
  break;
334
452
  case "code-block":
335
- setBlock("pre");
453
+ insertCodeBlock();
336
454
  break;
337
455
  case "divider":
338
456
  insertDivider();
@@ -350,7 +468,9 @@ var Editor = (props) => {
350
468
  if (!sel || sel.rangeCount === 0) return;
351
469
  const range = sel.getRangeAt(0);
352
470
  const rect = range.getBoundingClientRect();
353
- const editorRect = editorRef.current.getBoundingClientRect();
471
+ const editorEl2 = editorRef.current;
472
+ if (!editorEl2) return;
473
+ const editorRect = editorEl2.getBoundingClientRect();
354
474
  setLinkPos({
355
475
  top: rect.bottom - editorRect.top + 4,
356
476
  left: rect.left - editorRect.left
@@ -383,13 +503,13 @@ var Editor = (props) => {
383
503
  if (node.nodeType !== Node.TEXT_NODE) return false;
384
504
  const text = (node.textContent || "").slice(0, range.startOffset);
385
505
  const patterns = [
386
- [/^###\s$/, () => setBlock("h3")],
387
- [/^##\s$/, () => setBlock("h2")],
388
- [/^#\s$/, () => setBlock("h1")],
389
- [/^-\s$/, () => exec("insertUnorderedList")],
390
- [/^\*\s$/, () => exec("insertUnorderedList")],
391
- [/^1\.\s$/, () => exec("insertOrderedList")],
392
- [/^>\s$/, () => setBlock("blockquote")]
506
+ [/^###$/, () => setBlock("h3")],
507
+ [/^##$/, () => setBlock("h2")],
508
+ [/^#$/, () => setBlock("h1")],
509
+ [/^-$/, () => exec("insertUnorderedList")],
510
+ [/^\*$/, () => exec("insertUnorderedList")],
511
+ [/^1\.$/, () => exec("insertOrderedList")],
512
+ [/^>$/, () => setBlock("blockquote")]
393
513
  ];
394
514
  for (const [re, fn] of patterns) {
395
515
  if (re.test(text)) {
@@ -409,7 +529,9 @@ var Editor = (props) => {
409
529
  if (composingRef.current) return;
410
530
  const el = editorRef.current;
411
531
  if (!el) return;
412
- onChange?.(el.innerHTML);
532
+ const html = el.innerHTML;
533
+ lastEmittedRef.current = html;
534
+ onChange?.(html);
413
535
  updateEmpty();
414
536
  updateActiveFormats();
415
537
  if (slashOpen) {
@@ -437,6 +559,31 @@ var Editor = (props) => {
437
559
  };
438
560
  const handleKeyDown = (e) => {
439
561
  if (readOnly) return;
562
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
563
+ const pre = closestPre();
564
+ if (pre && !slashOpen) {
565
+ if (e.key === "Enter" && !e.shiftKey) {
566
+ const text = pre.textContent || "";
567
+ if (text.endsWith("\n\n")) {
568
+ e.preventDefault();
569
+ const code = pre.querySelector("code") ?? pre;
570
+ code.textContent = text.replace(/\n\n$/, "");
571
+ ensureParagraphAfter(pre);
572
+ const next = pre.nextElementSibling;
573
+ if (next) placeCaretAtEnd(next);
574
+ handleInput();
575
+ return;
576
+ }
577
+ e.preventDefault();
578
+ insertTextAtCaret("\n");
579
+ return;
580
+ }
581
+ if (e.key === "Tab") {
582
+ e.preventDefault();
583
+ insertTextAtCaret(" ");
584
+ return;
585
+ }
586
+ }
440
587
  if (slashOpen) {
441
588
  if (e.key === "ArrowDown") {
442
589
  e.preventDefault();
@@ -483,6 +630,7 @@ var Editor = (props) => {
483
630
  return;
484
631
  }
485
632
  }
633
+ if (pre) return;
486
634
  if (enableSlashCommand && e.key === "/") {
487
635
  setTimeout(openSlashMenu, 0);
488
636
  }
@@ -495,8 +643,12 @@ var Editor = (props) => {
495
643
  const handlePaste = (e) => {
496
644
  if (readOnly) return;
497
645
  e.preventDefault();
498
- const html = e.clipboardData.getData("text/html");
499
646
  const text = e.clipboardData.getData("text/plain");
647
+ if (closestPre()) {
648
+ insertTextAtCaret(text);
649
+ return;
650
+ }
651
+ const html = e.clipboardData.getData("text/html");
500
652
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
501
653
  document.execCommand("insertHTML", false, clean);
502
654
  handleInput();
@@ -520,6 +672,7 @@ var Editor = (props) => {
520
672
  updateActiveFormats();
521
673
  };
522
674
  const onToolbarAction = (item) => {
675
+ if (closestPre() && item !== "code-block") return;
523
676
  switch (item) {
524
677
  case "bold":
525
678
  exec("bold");
@@ -561,7 +714,7 @@ var Editor = (props) => {
561
714
  setBlock("blockquote");
562
715
  break;
563
716
  case "code-block":
564
- setBlock("pre");
717
+ insertCodeBlock();
565
718
  break;
566
719
  case "link":
567
720
  openLinkEditor();
@@ -591,6 +744,10 @@ var Editor = (props) => {
591
744
  ref: editorRef,
592
745
  contentEditable: !readOnly,
593
746
  suppressContentEditableWarning: true,
747
+ role: "textbox",
748
+ "aria-multiline": "true",
749
+ "aria-readonly": readOnly || void 0,
750
+ "aria-label": placeholder,
594
751
  className: "lib-xplat-editor__editable",
595
752
  onInput: handleInput,
596
753
  onKeyDown: handleKeyDown,