@domternal/react 0.4.1 → 0.5.1
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.
- package/README.md +1 -1
- package/dist/emoji-picker/DomternalEmojiPicker.d.ts.map +1 -1
- package/dist/emoji-picker/useEmojiPicker.d.ts.map +1 -1
- package/dist/index.d.ts +33 -467
- package/dist/index.js +99 -5
- package/dist/index.js.map +1 -1
- package/dist/toolbar/DomternalToolbar.d.ts.map +1 -1
- package/dist/toolbar/ToolbarDropdownPanel.d.ts.map +1 -1
- package/dist/toolbar/useKeyboardNav.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -465,6 +465,20 @@ function useKeyboardNav(controllerRef, toolbarRef, closeDropdown) {
|
|
|
465
465
|
const buttons = toolbarRef.current?.querySelectorAll(".dm-toolbar-button");
|
|
466
466
|
buttons?.[idx]?.focus();
|
|
467
467
|
}, []);
|
|
468
|
+
const focusDropdownItem = useCallback((direction, first) => {
|
|
469
|
+
const panel = toolbarRef.current?.querySelector(".dm-toolbar-dropdown-panel");
|
|
470
|
+
if (!panel) return;
|
|
471
|
+
const items = Array.from(panel.querySelectorAll('[role="menuitem"]'));
|
|
472
|
+
if (!items.length) return;
|
|
473
|
+
if (first) {
|
|
474
|
+
items[0]?.focus();
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const current = document.activeElement;
|
|
478
|
+
const idx = items.indexOf(current);
|
|
479
|
+
const next = idx === -1 ? direction > 0 ? 0 : items.length - 1 : (idx + direction + items.length) % items.length;
|
|
480
|
+
items[next]?.focus();
|
|
481
|
+
}, []);
|
|
468
482
|
const onKeyDown = useCallback((event) => {
|
|
469
483
|
const controller = controllerRef.current;
|
|
470
484
|
if (!controller) return;
|
|
@@ -479,6 +493,26 @@ function useKeyboardNav(controllerRef, toolbarRef, closeDropdown) {
|
|
|
479
493
|
controller.navigatePrev();
|
|
480
494
|
focusCurrentButton();
|
|
481
495
|
break;
|
|
496
|
+
case "ArrowDown": {
|
|
497
|
+
event.preventDefault();
|
|
498
|
+
if (controller.openDropdown) {
|
|
499
|
+
focusDropdownItem(1);
|
|
500
|
+
} else {
|
|
501
|
+
const btn = document.activeElement;
|
|
502
|
+
if (btn?.getAttribute("aria-haspopup") && btn.closest(".dm-toolbar")) {
|
|
503
|
+
btn.click();
|
|
504
|
+
requestAnimationFrame(() => focusDropdownItem(0, true));
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
case "ArrowUp": {
|
|
510
|
+
event.preventDefault();
|
|
511
|
+
if (controller.openDropdown) {
|
|
512
|
+
focusDropdownItem(-1);
|
|
513
|
+
}
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
482
516
|
case "Home":
|
|
483
517
|
event.preventDefault();
|
|
484
518
|
controller.navigateFirst();
|
|
@@ -497,7 +531,7 @@ function useKeyboardNav(controllerRef, toolbarRef, closeDropdown) {
|
|
|
497
531
|
}
|
|
498
532
|
break;
|
|
499
533
|
}
|
|
500
|
-
}, [closeDropdown, focusCurrentButton]);
|
|
534
|
+
}, [closeDropdown, focusCurrentButton, focusDropdownItem]);
|
|
501
535
|
return { onKeyDown, focusCurrentButton };
|
|
502
536
|
}
|
|
503
537
|
|
|
@@ -573,6 +607,7 @@ function ToolbarDropdownPanel({
|
|
|
573
607
|
type: "button",
|
|
574
608
|
className: `dm-color-swatch${isActive(sub.name) ? " dm-color-swatch--active" : ""}`,
|
|
575
609
|
role: "menuitem",
|
|
610
|
+
tabIndex: -1,
|
|
576
611
|
"aria-label": sub.label,
|
|
577
612
|
title: sub.label,
|
|
578
613
|
style: { backgroundColor: sub.color },
|
|
@@ -586,6 +621,7 @@ function ToolbarDropdownPanel({
|
|
|
586
621
|
type: "button",
|
|
587
622
|
className: "dm-color-palette-reset",
|
|
588
623
|
role: "menuitem",
|
|
624
|
+
tabIndex: -1,
|
|
589
625
|
"aria-label": sub.label,
|
|
590
626
|
dangerouslySetInnerHTML: { __html: getCachedItemContent(sub.icon, sub.label) },
|
|
591
627
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -609,6 +645,7 @@ function ToolbarDropdownPanel({
|
|
|
609
645
|
type: "button",
|
|
610
646
|
className: `dm-toolbar-dropdown-item${isActive(sub.name) ? " dm-toolbar-dropdown-item--active" : ""}`,
|
|
611
647
|
role: "menuitem",
|
|
648
|
+
tabIndex: -1,
|
|
612
649
|
"aria-label": sub.label,
|
|
613
650
|
ref: (el) => {
|
|
614
651
|
if (el && sub.style) el.setAttribute("style", sub.style);
|
|
@@ -700,6 +737,7 @@ function DomternalToolbar({ editor: editorProp, icons, layout }) {
|
|
|
700
737
|
return;
|
|
701
738
|
}
|
|
702
739
|
controllerRef.current?.executeCommand(item);
|
|
740
|
+
requestAnimationFrame(() => editor.view.focus());
|
|
703
741
|
}, [editor, closeDropdown]);
|
|
704
742
|
const onDropdownItemClick = useCallback((item, event) => {
|
|
705
743
|
if (!editor) return;
|
|
@@ -714,6 +752,7 @@ function DomternalToolbar({ editor: editorProp, icons, layout }) {
|
|
|
714
752
|
} else {
|
|
715
753
|
controllerRef.current?.executeCommand(item);
|
|
716
754
|
}
|
|
755
|
+
requestAnimationFrame(() => editor.view.focus());
|
|
717
756
|
}, [editor, closeDropdown]);
|
|
718
757
|
const onButtonFocus = useCallback((name) => {
|
|
719
758
|
const index = controllerRef.current?.getFlatIndex(name) ?? -1;
|
|
@@ -729,6 +768,7 @@ function DomternalToolbar({ editor: editorProp, icons, layout }) {
|
|
|
729
768
|
className: "dm-toolbar",
|
|
730
769
|
role: "toolbar",
|
|
731
770
|
"aria-label": "Editor formatting",
|
|
771
|
+
"data-dm-editor-ui": "",
|
|
732
772
|
onKeyDown,
|
|
733
773
|
children: groups.map((group, gi) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
734
774
|
gi > 0 && /* @__PURE__ */ jsx("div", { className: "dm-toolbar-separator", role: "separator" }),
|
|
@@ -1269,7 +1309,13 @@ function useEmojiPicker(editor, emojis) {
|
|
|
1269
1309
|
if (!grid) return;
|
|
1270
1310
|
const label = grid.querySelector(`[data-category="${cat}"]`);
|
|
1271
1311
|
if (label) {
|
|
1272
|
-
grid.scrollTo({ top: label.offsetTop - grid.offsetTop
|
|
1312
|
+
grid.scrollTo({ top: label.offsetTop - grid.offsetTop });
|
|
1313
|
+
setTimeout(() => {
|
|
1314
|
+
const firstSwatch = label.nextElementSibling;
|
|
1315
|
+
if (firstSwatch instanceof HTMLElement && firstSwatch.classList.contains("dm-emoji-swatch")) {
|
|
1316
|
+
firstSwatch.focus();
|
|
1317
|
+
}
|
|
1318
|
+
}, 50);
|
|
1273
1319
|
}
|
|
1274
1320
|
});
|
|
1275
1321
|
}, []);
|
|
@@ -1354,6 +1400,48 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1354
1400
|
close,
|
|
1355
1401
|
categories
|
|
1356
1402
|
} = useEmojiPicker(editor, emojis);
|
|
1403
|
+
const onGridKeyDown = useCallback((event) => {
|
|
1404
|
+
const grid = event.currentTarget;
|
|
1405
|
+
const swatches = Array.from(grid.querySelectorAll(".dm-emoji-swatch"));
|
|
1406
|
+
if (!swatches.length) return;
|
|
1407
|
+
const current = document.activeElement;
|
|
1408
|
+
let idx = swatches.indexOf(current);
|
|
1409
|
+
if (idx === -1) {
|
|
1410
|
+
if (["ArrowRight", "ArrowDown", "ArrowLeft", "ArrowUp"].includes(event.key)) {
|
|
1411
|
+
event.preventDefault();
|
|
1412
|
+
swatches[0]?.focus();
|
|
1413
|
+
}
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
const cols = 8;
|
|
1417
|
+
let next = idx;
|
|
1418
|
+
switch (event.key) {
|
|
1419
|
+
case "ArrowRight":
|
|
1420
|
+
event.preventDefault();
|
|
1421
|
+
next = Math.min(idx + 1, swatches.length - 1);
|
|
1422
|
+
break;
|
|
1423
|
+
case "ArrowLeft":
|
|
1424
|
+
event.preventDefault();
|
|
1425
|
+
next = Math.max(idx - 1, 0);
|
|
1426
|
+
break;
|
|
1427
|
+
case "ArrowDown":
|
|
1428
|
+
event.preventDefault();
|
|
1429
|
+
next = Math.min(idx + cols, swatches.length - 1);
|
|
1430
|
+
break;
|
|
1431
|
+
case "ArrowUp":
|
|
1432
|
+
event.preventDefault();
|
|
1433
|
+
next = Math.max(idx - cols, 0);
|
|
1434
|
+
break;
|
|
1435
|
+
case "Enter":
|
|
1436
|
+
case " ":
|
|
1437
|
+
event.preventDefault();
|
|
1438
|
+
swatches[idx]?.click();
|
|
1439
|
+
return;
|
|
1440
|
+
default:
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
swatches[next]?.focus();
|
|
1444
|
+
}, []);
|
|
1357
1445
|
if (!isOpen) return /* @__PURE__ */ jsx("div", { ref: pickerRef, className: "dm-emoji-picker-host" });
|
|
1358
1446
|
return /* @__PURE__ */ jsx("div", { ref: pickerRef, className: "dm-emoji-picker-host", children: /* @__PURE__ */ jsxs("div", { className: "dm-emoji-picker", children: [
|
|
1359
1447
|
/* @__PURE__ */ jsx("div", { className: "dm-emoji-picker-search", children: /* @__PURE__ */ jsx(
|
|
@@ -1361,6 +1449,7 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1361
1449
|
{
|
|
1362
1450
|
type: "text",
|
|
1363
1451
|
placeholder: "Search emoji...",
|
|
1452
|
+
"aria-label": "Search emoji",
|
|
1364
1453
|
value: searchQuery,
|
|
1365
1454
|
onChange: onSearch,
|
|
1366
1455
|
onKeyDown: (e) => {
|
|
@@ -1373,6 +1462,8 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1373
1462
|
{
|
|
1374
1463
|
type: "button",
|
|
1375
1464
|
className: `dm-emoji-picker-tab${activeCategory === cat ? " dm-emoji-picker-tab--active" : ""}`,
|
|
1465
|
+
role: "tab",
|
|
1466
|
+
"aria-selected": activeCategory === cat,
|
|
1376
1467
|
title: cat,
|
|
1377
1468
|
"aria-label": cat,
|
|
1378
1469
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -1381,11 +1472,12 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1381
1472
|
},
|
|
1382
1473
|
cat
|
|
1383
1474
|
)) }),
|
|
1384
|
-
/* @__PURE__ */ jsx("div", { className: "dm-emoji-picker-grid", onScroll: onGridScroll, children: searchQuery ? /* @__PURE__ */ jsx(Fragment$1, { children: filteredEmojis.length > 0 ? filteredEmojis.map((item) => /* @__PURE__ */ jsx(
|
|
1475
|
+
/* @__PURE__ */ jsx("div", { className: "dm-emoji-picker-grid", onScroll: onGridScroll, onKeyDown: onGridKeyDown, children: searchQuery ? /* @__PURE__ */ jsx(Fragment$1, { children: filteredEmojis.length > 0 ? filteredEmojis.map((item) => /* @__PURE__ */ jsx(
|
|
1385
1476
|
"button",
|
|
1386
1477
|
{
|
|
1387
1478
|
type: "button",
|
|
1388
1479
|
className: "dm-emoji-swatch",
|
|
1480
|
+
tabIndex: -1,
|
|
1389
1481
|
title: formatName(item.name),
|
|
1390
1482
|
"aria-label": formatName(item.name),
|
|
1391
1483
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -1401,6 +1493,7 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1401
1493
|
{
|
|
1402
1494
|
type: "button",
|
|
1403
1495
|
className: "dm-emoji-swatch",
|
|
1496
|
+
tabIndex: -1,
|
|
1404
1497
|
title: formatName(item.name),
|
|
1405
1498
|
"aria-label": formatName(item.name),
|
|
1406
1499
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -1417,6 +1510,7 @@ function DomternalEmojiPicker({ editor: editorProp, emojis }) {
|
|
|
1417
1510
|
{
|
|
1418
1511
|
type: "button",
|
|
1419
1512
|
className: "dm-emoji-swatch",
|
|
1513
|
+
tabIndex: -1,
|
|
1420
1514
|
title: formatName(item.name),
|
|
1421
1515
|
"aria-label": formatName(item.name),
|
|
1422
1516
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -1445,7 +1539,7 @@ function DomternalContent({ className }) {
|
|
|
1445
1539
|
}
|
|
1446
1540
|
}, [editor]);
|
|
1447
1541
|
const classes = className ? `dm-editor ${className}` : "dm-editor";
|
|
1448
|
-
return /* @__PURE__ */ jsx("div", { className: classes, children: /* @__PURE__ */ jsx("div", { ref: containerRef }) });
|
|
1542
|
+
return /* @__PURE__ */ jsx("div", { className: classes, "data-dm-editor-ui": "", children: /* @__PURE__ */ jsx("div", { ref: containerRef }) });
|
|
1449
1543
|
}
|
|
1450
1544
|
function DomternalLoading({ children }) {
|
|
1451
1545
|
const { editor } = useCurrentEditor();
|
|
@@ -1534,7 +1628,7 @@ var DomternalEditor = forwardRef(
|
|
|
1534
1628
|
const classes = className ? `dm-editor ${className}` : "dm-editor";
|
|
1535
1629
|
return /* @__PURE__ */ jsxs(EditorProvider, { editor, children: [
|
|
1536
1630
|
children,
|
|
1537
|
-
/* @__PURE__ */ jsx("div", { className: classes, children: /* @__PURE__ */ jsx("div", { ref: editorRef }) })
|
|
1631
|
+
/* @__PURE__ */ jsx("div", { className: classes, "data-dm-editor-ui": "", children: /* @__PURE__ */ jsx("div", { ref: editorRef }) })
|
|
1538
1632
|
] });
|
|
1539
1633
|
}
|
|
1540
1634
|
);
|