@lofcz/platejs-tabbable 52.0.11 → 52.3.6

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.
@@ -1,4 +1,4 @@
1
- import { KEYS, PathApi, createTSlatePlugin } from "platejs";
1
+ import { KEYS, createTSlatePlugin } from "platejs";
2
2
 
3
3
  //#region src/lib/BaseTabbablePlugin.ts
4
4
  const BaseTabbablePlugin = createTSlatePlugin({
@@ -12,6 +12,13 @@ const BaseTabbablePlugin = createTSlatePlugin({
12
12
 
13
13
  //#endregion
14
14
  //#region src/lib/findTabDestination.ts
15
+ const comparePaths = (a, b) => {
16
+ const minLength = Math.min(a.length, b.length);
17
+ for (let index = 0; index < minLength; index++) if (a[index] !== b[index]) return a[index] - b[index];
18
+ return a.length - b.length;
19
+ };
20
+ const isPathBefore = (a, b) => comparePaths(a, b) < 0;
21
+ const isPathEqual = (a, b) => comparePaths(a, b) === 0;
15
22
  const findTabDestination = (editor, { activeTabbableEntry, direction, tabbableEntries }) => {
16
23
  if (activeTabbableEntry) {
17
24
  const nextTabbableEntry$1 = tabbableEntries[tabbableEntries.indexOf(activeTabbableEntry) + (direction === "forward" ? 1 : -1)];
@@ -33,7 +40,7 @@ const findTabDestination = (editor, { activeTabbableEntry, direction, tabbableEn
33
40
  * - We're in the last tabbable element of a popover.
34
41
  * - There is no next tabbable element.
35
42
  */
36
- if (nextTabbableEntry$1 && PathApi.equals(activeTabbableEntry.path, nextTabbableEntry$1.path)) return {
43
+ if (nextTabbableEntry$1 && isPathEqual(activeTabbableEntry.path, nextTabbableEntry$1.path)) return {
37
44
  domNode: nextTabbableEntry$1.domNode,
38
45
  type: "dom-node"
39
46
  };
@@ -57,7 +64,7 @@ const findTabDestination = (editor, { activeTabbableEntry, direction, tabbableEn
57
64
  };
58
65
  }
59
66
  const selectionPath = editor.selection?.anchor?.path || [];
60
- const nextTabbableEntry = direction === "forward" ? tabbableEntries.find((entry) => !PathApi.isBefore(entry.path, selectionPath)) : [...tabbableEntries].reverse().find((entry) => PathApi.isBefore(entry.path, selectionPath));
67
+ const nextTabbableEntry = direction === "forward" ? tabbableEntries.find((entry) => !isPathBefore(entry.path, selectionPath)) : [...tabbableEntries].reverse().find((entry) => isPathBefore(entry.path, selectionPath));
61
68
  if (nextTabbableEntry) return {
62
69
  domNode: nextTabbableEntry.domNode,
63
70
  type: "dom-node"
@@ -66,5 +73,4 @@ const findTabDestination = (editor, { activeTabbableEntry, direction, tabbableEn
66
73
  };
67
74
 
68
75
  //#endregion
69
- export { BaseTabbablePlugin as n, findTabDestination as t };
70
- //# sourceMappingURL=findTabDestination-VIYSr_9z.js.map
76
+ export { BaseTabbablePlugin as n, findTabDestination as t };
@@ -0,0 +1,95 @@
1
+ import * as platejs0 from "platejs";
2
+ import { PluginConfig, SlateEditor } from "platejs";
3
+
4
+ //#region src/lib/types.d.ts
5
+ type Path = number[];
6
+ type TabbableEntry = {
7
+ domNode: HTMLElement;
8
+ path: Path;
9
+ slateNode: any;
10
+ };
11
+ type TabDestination = TabDestinationDOMNode | TabDestinationPath;
12
+ type TabDestinationDOMNode = {
13
+ domNode: HTMLElement;
14
+ type: 'dom-node';
15
+ };
16
+ type TabDestinationPath = {
17
+ path: Path;
18
+ type: 'path';
19
+ };
20
+ //#endregion
21
+ //#region src/lib/BaseTabbablePlugin.d.ts
22
+ type TabblableConfig = PluginConfig<'tabbable', {
23
+ /**
24
+ * When true, the plugin will add its event listener to the document instead
25
+ * of the editor, allowing it to capture events from outside the editor.
26
+ *
27
+ * @default: false
28
+ */
29
+ globalEventListener?: boolean;
30
+ /**
31
+ * Add additional tabbables to the list of tabbables. Useful for adding
32
+ * tabbables that are not contained within the editor. Ignores
33
+ * `isTabbable`.
34
+ *
35
+ * @default: () => []
36
+ */
37
+ insertTabbableEntries?: (event: KeyboardEvent) => TabbableEntry[];
38
+ /**
39
+ * Determine whether an element should be included in the tabbable list.
40
+ *
41
+ * @default: (editor, tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)
42
+ */
43
+ isTabbable?: (entry: TabbableEntry) => boolean;
44
+ /**
45
+ * Dynamically enable or disable the plugin.
46
+ *
47
+ * @default: () => true
48
+ */
49
+ query?: (event: KeyboardEvent) => boolean;
50
+ }>;
51
+ declare const BaseTabbablePlugin: platejs0.SlatePlugin<PluginConfig<"tabbable", {
52
+ isTabbable: (tabbableEntry: TabbableEntry) => boolean;
53
+ } & {
54
+ /**
55
+ * When true, the plugin will add its event listener to the document instead
56
+ * of the editor, allowing it to capture events from outside the editor.
57
+ *
58
+ * @default: false
59
+ */
60
+ globalEventListener?: boolean;
61
+ /**
62
+ * Add additional tabbables to the list of tabbables. Useful for adding
63
+ * tabbables that are not contained within the editor. Ignores
64
+ * `isTabbable`.
65
+ *
66
+ * @default: () => []
67
+ */
68
+ insertTabbableEntries?: (event: KeyboardEvent) => TabbableEntry[];
69
+ /**
70
+ * Determine whether an element should be included in the tabbable list.
71
+ *
72
+ * @default: (editor, tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)
73
+ */
74
+ isTabbable?: (entry: TabbableEntry) => boolean;
75
+ /**
76
+ * Dynamically enable or disable the plugin.
77
+ *
78
+ * @default: () => true
79
+ */
80
+ query?: (event: KeyboardEvent) => boolean;
81
+ }, {}, {}, {}>>;
82
+ //#endregion
83
+ //#region src/lib/findTabDestination.d.ts
84
+ type FindTabDestinationOptions = {
85
+ activeTabbableEntry: TabbableEntry | null;
86
+ direction: 'backward' | 'forward';
87
+ tabbableEntries: TabbableEntry[];
88
+ };
89
+ declare const findTabDestination: (editor: SlateEditor, {
90
+ activeTabbableEntry,
91
+ direction,
92
+ tabbableEntries
93
+ }: FindTabDestinationOptions) => TabDestination | null;
94
+ //#endregion
95
+ export { TabDestination as a, TabbableEntry as c, TabblableConfig as i, findTabDestination as n, TabDestinationDOMNode as o, BaseTabbablePlugin as r, TabDestinationPath as s, FindTabDestinationOptions as t };
package/dist/index.d.ts CHANGED
@@ -1,64 +1,2 @@
1
- import { Path, PluginConfig, SlateEditor, TElement } from "platejs";
2
-
3
- //#region src/lib/types.d.ts
4
- type TabbableEntry = {
5
- domNode: HTMLElement;
6
- path: Path;
7
- slateNode: TElement;
8
- };
9
- type TabDestination = TabDestinationDOMNode | TabDestinationPath;
10
- type TabDestinationDOMNode = {
11
- domNode: HTMLElement;
12
- type: 'dom-node';
13
- };
14
- type TabDestinationPath = {
15
- path: Path;
16
- type: 'path';
17
- };
18
- //#endregion
19
- //#region src/lib/BaseTabbablePlugin.d.ts
20
- type TabblableConfig = PluginConfig<'tabbable', {
21
- /**
22
- * When true, the plugin will add its event listener to the document instead
23
- * of the editor, allowing it to capture events from outside the editor.
24
- *
25
- * @default: false
26
- */
27
- globalEventListener?: boolean;
28
- /**
29
- * Add additional tabbables to the list of tabbables. Useful for adding
30
- * tabbables that are not contained within the editor. Ignores
31
- * `isTabbable`.
32
- *
33
- * @default: () => []
34
- */
35
- insertTabbableEntries?: (event: KeyboardEvent) => TabbableEntry[];
36
- /**
37
- * Determine whether an element should be included in the tabbable list.
38
- *
39
- * @default: (editor, tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)
40
- */
41
- isTabbable?: (entry: TabbableEntry) => boolean;
42
- /**
43
- * Dynamically enable or disable the plugin.
44
- *
45
- * @default: () => true
46
- */
47
- query?: (event: KeyboardEvent) => boolean;
48
- }>;
49
- declare const BaseTabbablePlugin: any;
50
- //#endregion
51
- //#region src/lib/findTabDestination.d.ts
52
- type FindTabDestinationOptions = {
53
- activeTabbableEntry: TabbableEntry | null;
54
- direction: 'backward' | 'forward';
55
- tabbableEntries: TabbableEntry[];
56
- };
57
- declare const findTabDestination: (editor: SlateEditor, {
58
- activeTabbableEntry,
59
- direction,
60
- tabbableEntries
61
- }: FindTabDestinationOptions) => TabDestination | null;
62
- //#endregion
63
- export { BaseTabbablePlugin, FindTabDestinationOptions, TabDestination, TabDestinationDOMNode, TabDestinationPath, TabbableEntry, TabblableConfig, findTabDestination };
64
- //# sourceMappingURL=index.d.ts.map
1
+ import { a as TabDestination, c as TabbableEntry, i as TabblableConfig, n as findTabDestination, o as TabDestinationDOMNode, r as BaseTabbablePlugin, s as TabDestinationPath, t as FindTabDestinationOptions } from "./index-BMY6qrfQ";
2
+ export { BaseTabbablePlugin, FindTabDestinationOptions, TabDestination, TabDestinationDOMNode, TabDestinationPath, TabbableEntry, TabblableConfig, findTabDestination };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { n as BaseTabbablePlugin, t as findTabDestination } from "./findTabDestination-VIYSr_9z.js";
1
+ import { n as BaseTabbablePlugin, t as findTabDestination } from "./findTabDestination-n0egeAhf.js";
2
2
 
3
3
  export { BaseTabbablePlugin, findTabDestination };
@@ -1,8 +1,18 @@
1
+ import { c as TabbableEntry } from "../index-BMY6qrfQ";
2
+ import * as platejs0 from "platejs";
3
+ import * as platejs_react0 from "platejs/react";
4
+
1
5
  //#region src/react/TabbableEffects.d.ts
2
6
  declare function TabbableEffects(): null;
3
7
  //#endregion
4
8
  //#region src/react/TabbablePlugin.d.ts
5
- declare const TabbablePlugin: any;
9
+ declare const TabbablePlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<"tabbable", {
10
+ isTabbable: (tabbableEntry: TabbableEntry) => boolean;
11
+ } & {
12
+ globalEventListener?: boolean;
13
+ insertTabbableEntries?: (event: KeyboardEvent) => TabbableEntry[];
14
+ isTabbable?: (entry: TabbableEntry) => boolean;
15
+ query?: (event: KeyboardEvent) => boolean;
16
+ }, {}, {}, {}>>;
6
17
  //#endregion
7
- export { TabbableEffects, TabbablePlugin };
8
- //# sourceMappingURL=index.d.ts.map
18
+ export { TabbableEffects, TabbablePlugin };
@@ -1,11 +1,15 @@
1
- import { n as BaseTabbablePlugin, t as findTabDestination } from "../findTabDestination-VIYSr_9z.js";
2
- import { PathApi } from "platejs";
1
+ import { n as BaseTabbablePlugin, t as findTabDestination } from "../findTabDestination-n0egeAhf.js";
3
2
  import { c } from "react-compiler-runtime";
4
3
  import React from "react";
5
4
  import { toPlatePlugin, useEditorReadOnly, useEditorRef } from "platejs/react";
6
5
  import { tabbable } from "tabbable";
7
6
 
8
7
  //#region src/react/TabbableEffects.tsx
8
+ const comparePaths = (a, b) => {
9
+ const minLength = Math.min(a.length, b.length);
10
+ for (let index = 0; index < minLength; index++) if (a[index] !== b[index]) return a[index] - b[index];
11
+ return a.length - b.length;
12
+ };
9
13
  function TabbableEffects() {
10
14
  const $ = c(4);
11
15
  const editor = useEditorRef();
@@ -85,7 +89,7 @@ function _temp3(domNode_1) {
85
89
  }, 0);
86
90
  }
87
91
  function _temp2(a, b) {
88
- return PathApi.compare(a.path, b.path);
92
+ return comparePaths(a.path, b.path);
89
93
  }
90
94
  function _temp(t0) {
91
95
  const { domNode } = t0;
@@ -97,5 +101,4 @@ function _temp(t0) {
97
101
  const TabbablePlugin = toPlatePlugin(BaseTabbablePlugin, { render: { afterEditable: TabbableEffects } });
98
102
 
99
103
  //#endregion
100
- export { TabbableEffects, TabbablePlugin };
101
- //# sourceMappingURL=index.js.map
104
+ export { TabbableEffects, TabbablePlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lofcz/platejs-tabbable",
3
- "version": "52.0.11",
3
+ "version": "52.3.6",
4
4
  "description": "Tab into and out of void nodes and other elements",
5
5
  "keywords": [
6
6
  "plate",
@@ -33,6 +33,7 @@
33
33
  "tabbable": "^6.2.0"
34
34
  },
35
35
  "devDependencies": {
36
+ "platejs": "npm:@lofcz/platejs@52.3.6",
36
37
  "@plate/scripts": "1.0.0"
37
38
  },
38
39
  "peerDependencies": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"findTabDestination-VIYSr_9z.js","names":["PluginConfig","createTSlatePlugin","KEYS","TabbableEntry","TabblableConfig","globalEventListener","insertTabbableEntries","event","KeyboardEvent","isTabbable","entry","query","BaseTabbablePlugin","key","tabbable","options","extend","editor","tabbableEntry","api","isVoid","slateNode","SlateEditor","PathApi","TabbableEntry","TabDestination","FindTabDestinationOptions","activeTabbableEntry","direction","tabbableEntries","findTabDestination","editor","activeTabbableEntryIndex","indexOf","nextTabbableEntryIndex","nextTabbableEntry","equals","path","domNode","type","pointAfter","api","after","point","selectionPath","selection","anchor","find","entry","isBefore","reverse"],"sources":["../src/lib/BaseTabbablePlugin.ts","../src/lib/findTabDestination.ts"],"sourcesContent":["import { type PluginConfig, createTSlatePlugin, KEYS } from 'platejs';\n\nimport type { TabbableEntry } from './types';\n\nexport type TabblableConfig = PluginConfig<\n 'tabbable',\n {\n /**\n * When true, the plugin will add its event listener to the document instead\n * of the editor, allowing it to capture events from outside the editor.\n *\n * @default: false\n */\n globalEventListener?: boolean;\n /**\n * Add additional tabbables to the list of tabbables. Useful for adding\n * tabbables that are not contained within the editor. Ignores\n * `isTabbable`.\n *\n * @default: () => []\n */\n insertTabbableEntries?: (event: KeyboardEvent) => TabbableEntry[];\n /**\n * Determine whether an element should be included in the tabbable list.\n *\n * @default: (editor, tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)\n */\n isTabbable?: (entry: TabbableEntry) => boolean;\n /**\n * Dynamically enable or disable the plugin.\n *\n * @default: () => true\n */\n query?: (event: KeyboardEvent) => boolean;\n }\n>;\n\nexport const BaseTabbablePlugin = createTSlatePlugin<TabblableConfig>({\n key: KEYS.tabbable,\n options: {\n globalEventListener: false,\n insertTabbableEntries: () => [],\n query: () => true,\n },\n}).extend(({ editor }) => ({\n options: {\n isTabbable: (tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode),\n },\n}));\n","import { type SlateEditor, PathApi } from 'platejs';\n\nimport type { TabbableEntry, TabDestination } from './types';\n\nexport type FindTabDestinationOptions = {\n activeTabbableEntry: TabbableEntry | null;\n direction: 'backward' | 'forward';\n tabbableEntries: TabbableEntry[];\n};\n\nexport const findTabDestination = (\n editor: SlateEditor,\n { activeTabbableEntry, direction, tabbableEntries }: FindTabDestinationOptions\n): TabDestination | null => {\n // Case 1: A tabbable entry was active before tab was pressed\n if (activeTabbableEntry) {\n // Find the next tabbable entry after the active one\n const activeTabbableEntryIndex =\n tabbableEntries.indexOf(activeTabbableEntry);\n const nextTabbableEntryIndex =\n activeTabbableEntryIndex + (direction === 'forward' ? 1 : -1);\n const nextTabbableEntry = tabbableEntries[nextTabbableEntryIndex];\n\n /**\n * If the next tabbable entry originated from the same path as the active\n * tabbable entry, focus it.\n *\n * Examples of when this is true:\n *\n * - We're inside a void node and there is an additional tabbable inside the\n * same void node.\n * - We're inside a popover containing multiple tabbable elements all anchored\n * to the same slate node, and there is an additional tabbable inside the\n * same popover.\n *\n * Examples of when this is false:\n *\n * - We're inside a void node and the next tabbable is outside the void node.\n * - We're in the last tabbable element of a popover.\n * - There is no next tabbable element.\n */\n if (\n nextTabbableEntry &&\n PathApi.equals(activeTabbableEntry.path, nextTabbableEntry.path)\n ) {\n return {\n domNode: nextTabbableEntry.domNode,\n type: 'dom-node',\n };\n }\n /**\n * Otherwise, return the focus to the editor. If we're moving forward, focus\n * the first point after the active tabbable's path. If we're moving\n * backward, focus the point of the active tabbable's path. TODO: Let a\n * tabbable entry specify custom before and after points.\n */\n if (direction === 'forward') {\n const pointAfter = editor.api.after(activeTabbableEntry.path);\n\n if (!pointAfter) return null;\n\n return {\n path: pointAfter.path,\n type: 'path',\n };\n }\n\n return {\n path: editor.api.point(activeTabbableEntry.path)!.path,\n type: 'path',\n };\n }\n\n // Case 2: No tabbable entry was active before tab was pressed\n\n const selectionPath = editor.selection?.anchor?.path || [];\n\n // Find the first tabbable entry after the selection\n const nextTabbableEntry =\n direction === 'forward'\n ? tabbableEntries.find(\n (entry) => !PathApi.isBefore(entry.path, selectionPath)\n )\n : [...tabbableEntries]\n .reverse()\n .find((entry) => PathApi.isBefore(entry.path, selectionPath));\n\n // If it exists, focus it\n if (nextTabbableEntry) {\n return {\n domNode: nextTabbableEntry.domNode,\n type: 'dom-node',\n };\n }\n\n // Otherwise, use the default behaviour\n return null;\n};\n"],"mappings":";;;AAqCA,MAAaY,qBAAqBX,mBAAoC;CACpEY,KAAKX,KAAKY;CACVC,SAAS;EACPV,qBAAqB;EACrBC,6BAA6B,EAAE;EAC/BK,aAAa;EACf;CACD,CAAC,CAACK,QAAQ,EAAEC,cAAc,EACzBF,SAAS,EACPN,aAAaS,kBAAkBD,OAAOE,IAAIC,OAAOF,cAAcG,UAAS,EAC1E,EACD,EAAE;;;;ACtCH,MAAaS,sBACXC,QACA,EAAEJ,qBAAqBC,WAAWC,sBACR;AAE1B,KAAIF,qBAAqB;EAMvB,MAAMQ,sBAAoBN,gBAHxBA,gBAAgBI,QAAQN,oBAAoB,IAEhBC,cAAc,YAAY,IAAI;;;;;;;;;;;;;;;;;;;AAqB5D,MACEO,uBACAZ,QAAQa,OAAOT,oBAAoBU,MAAMF,oBAAkBE,KAAK,CAEhE,QAAO;GACLC,SAASH,oBAAkBG;GAC3BC,MAAM;GACP;;;;;;;AAQH,MAAIX,cAAc,WAAW;GAC3B,MAAMY,aAAaT,OAAOU,IAAIC,MAAMf,oBAAoBU,KAAK;AAE7D,OAAI,CAACG,WAAY,QAAO;AAExB,UAAO;IACLH,MAAMG,WAAWH;IACjBE,MAAM;IACP;;AAGH,SAAO;GACLF,MAAMN,OAAOU,IAAIE,MAAMhB,oBAAoBU,KAAK,CAAEA;GAClDE,MAAM;GACP;;CAKH,MAAMK,gBAAgBb,OAAOc,WAAWC,QAAQT,QAAQ,EAAE;CAG1D,MAAMF,oBACJP,cAAc,YACVC,gBAAgBkB,MACbC,UAAU,CAACzB,QAAQ0B,SAASD,MAAMX,MAAMO,cAC3C,CAAC,GACD,CAAC,GAAGf,gBAAgB,CACjBqB,SAAS,CACTH,MAAMC,UAAUzB,QAAQ0B,SAASD,MAAMX,MAAMO,cAAc,CAAC;AAGrE,KAAIT,kBACF,QAAO;EACLG,SAASH,kBAAkBG;EAC3BC,MAAM;EACP;AAIH,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/lib/types.ts","../src/lib/BaseTabbablePlugin.ts","../src/lib/findTabDestination.ts"],"sourcesContent":[],"mappings":";;;KAEY,aAAA;WACD;EADC,IAAA,EAEJ,IAFI;EACD,SAAA,EAEE,QAFF;CACH;AACK,KAGD,cAAA,GAAiB,qBAHhB,GAGwC,kBAHxC;AAAQ,KAKT,qBAAA,GALS;EAGT,OAAA,EAGD,WAHe;EAEd,IAAA,EAAA,UAAA;AAKZ,CAAA;KAAY,kBAAA;QACJ;;ACZR,CAAA;;;KAAY,eAAA,GAAkB;EDFlB;;;;;AAMZ;EAEY,mBAAA,CAAA,EAAA,OAAqB;EAKrB;;;;ACXZ;;;EAuByB,qBAAA,CAAA,EAAA,CAAA,KAAA,EANW,aAMX,EAAA,GAN6B,aAM7B,EAAA;EAML;;;AAIpB;;uBAVyB;;ACvBzB;AAMA;;;EAEE,KAAA,CAAA,EAAA,CAAA,KAAA,EDqBkB,aCrBlB,EAAA,GAAA,OAAA;CAAA,CAAA;AAAqD,cDyB1C,kBCzB0C,EAAA,GAAA;;;KAR3C,yBAAA;EFFA,mBAAa,EEGF,aFHE,GAAA,IAAA;EACd,SAAA,EAAA,UAAA,GAAA,SAAA;EACH,eAAA,EEGW,aFHX,EAAA;CACK;AAAQ,cEKR,kBFLQ,EAAA,CAAA,MAAA,EEMX,WFNW,EAAA;EAAA,mBAAA;EAAA,SAAA;EAAA;AAAA,CAAA,EEOkC,yBFPlC,EAAA,GEQlB,cFRkB,GAAA,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/react/TabbableEffects.tsx","../../src/react/TabbablePlugin.tsx"],"sourcesContent":[],"mappings":";iBAWgB,eAAA,CAAA;;;cCNH"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["React","PathApi","useEditorReadOnly","useEditorRef","tabbable","TabbableEntry","BaseTabbablePlugin","findTabDestination","TabbableEffects","$","_c","editor","readOnly","t0","t1","globalEventListener","insertTabbableEntries","isTabbable","query","getOptions","editorDOMNode","api","toDOMNode","handler","event","key","defaultPrevented","insertedTabbableEntries","target","map","_temp","some","container","contains","Node","tabbableDOMNodes","HTMLElement","defaultTabbableEntries","domNode_0","slateNode","toSlateNode","domNode","path","findPath","filter","entry","tabbableEntries","sort","_temp2","activeElement","document","activeTabbableEntry","find","entry_0","tabDestination","direction","shiftKey","preventDefault","bb76","type","focus","tf","at","anchor","offset","forEach","_temp3","eventListenerNode","body","addEventListener","removeEventListener","useEffect","domNode_1","oldTabIndex","getAttribute","setAttribute","setTimeout","removeAttribute","a","b","compare","toPlatePlugin","BaseTabbablePlugin","TabbableEffects","TabbablePlugin","render","afterEditable"],"sources":["../../src/react/TabbableEffects.tsx","../../src/react/TabbablePlugin.tsx"],"sourcesContent":["import React from 'react';\n\nimport { PathApi } from 'platejs';\nimport { useEditorReadOnly, useEditorRef } from 'platejs/react';\nimport { tabbable } from 'tabbable';\n\nimport type { TabbableEntry } from '../lib/types';\n\nimport { BaseTabbablePlugin } from '../lib/BaseTabbablePlugin';\nimport { findTabDestination } from '../lib/findTabDestination';\n\nexport function TabbableEffects() {\n const editor = useEditorRef();\n const readOnly = useEditorReadOnly();\n\n React.useEffect(() => {\n if (readOnly) return;\n\n const { globalEventListener, insertTabbableEntries, isTabbable, query } =\n editor.getOptions(BaseTabbablePlugin);\n\n const editorDOMNode = editor.api.toDOMNode(editor);\n\n if (!editorDOMNode) return;\n\n const handler = (event: KeyboardEvent) => {\n // Check if the keydown is a tab key that should be handled\n if (event.key !== 'Tab' || event.defaultPrevented || !query?.(event)) {\n return;\n }\n\n /**\n * Get the list of additional tabbable entries specified in the plugin\n * options\n */\n const insertedTabbableEntries = insertTabbableEntries?.(\n event\n ) as TabbableEntry[];\n\n /**\n * Global event listener only. Do not handle the tab event if the keydown\n * was sent to an element other than the editor or one of the additional\n * tabbable elements.\n */\n if (\n globalEventListener &&\n event.target &&\n ![\n editorDOMNode,\n ...insertedTabbableEntries.map(({ domNode }) => domNode),\n ].some((container) => container.contains(event.target as Node))\n ) {\n return;\n }\n\n // Get all tabbable DOM nodes in the editor\n const tabbableDOMNodes = tabbable(editorDOMNode) as HTMLElement[];\n\n /**\n * Construct a tabbable entry for each tabbable Slate node, filtered by\n * the `isTabbable` option (defaulting to only void nodes).\n */\n const defaultTabbableEntries = tabbableDOMNodes\n .map((domNode) => {\n const slateNode = editor.api.toSlateNode(domNode);\n\n if (!slateNode) return null;\n\n return {\n domNode,\n path: editor.api.findPath(slateNode),\n slateNode,\n } as TabbableEntry;\n })\n .filter((entry) => entry && isTabbable?.(entry)) as TabbableEntry[];\n\n /**\n * The list of all tabbable entries. Sorting by path ensures a consistent\n * tab order.\n */\n const tabbableEntries = [\n ...insertedTabbableEntries,\n ...defaultTabbableEntries,\n ].sort((a, b) => PathApi.compare(a.path, b.path));\n\n /**\n * TODO: Refactor everything ABOVE this line into a util function and test\n * separately\n */\n\n // Check if any tabbable entry is the active element\n const { activeElement } = document;\n const activeTabbableEntry =\n (activeElement &&\n tabbableEntries.find((entry) => entry.domNode === activeElement)) ??\n null;\n\n // Find the next Slate node or DOM node to focus\n const tabDestination = findTabDestination(editor, {\n activeTabbableEntry,\n direction: event.shiftKey ? 'backward' : 'forward',\n tabbableEntries,\n });\n\n if (tabDestination) {\n event.preventDefault();\n\n switch (tabDestination.type) {\n case 'dom-node': {\n tabDestination.domNode.focus();\n\n break;\n }\n case 'path': {\n editor.tf.focus({\n at: {\n anchor: { offset: 0, path: tabDestination.path },\n focus: { offset: 0, path: tabDestination.path },\n },\n });\n\n break;\n }\n }\n\n return;\n }\n\n /**\n * There was no tab destination, so let the browser handle the tab event.\n * We don't want the browser to focus anything that could have been\n * focused by us, so we make make all tabbable DOM nodes in the editor\n * unfocusable. This ensures that the focus exits the editor cleanly.\n */\n tabbableDOMNodes.forEach((domNode) => {\n const oldTabIndex = domNode.getAttribute('tabindex');\n domNode.setAttribute('tabindex', '-1');\n\n setTimeout(() => {\n if (oldTabIndex) {\n domNode.setAttribute('tabindex', oldTabIndex);\n } else {\n domNode.removeAttribute('tabindex');\n }\n }, 0);\n });\n };\n\n const eventListenerNode = globalEventListener\n ? document.body\n : editorDOMNode;\n\n eventListenerNode.addEventListener('keydown', handler, true);\n\n return () =>\n eventListenerNode.removeEventListener('keydown', handler, true);\n }, [readOnly, editor]);\n\n return null;\n}\n","import { toPlatePlugin } from 'platejs/react';\n\nimport { BaseTabbablePlugin } from '../lib/BaseTabbablePlugin';\nimport { TabbableEffects } from './TabbableEffects';\n\nexport const TabbablePlugin = toPlatePlugin(BaseTabbablePlugin, {\n render: { afterEditable: TabbableEffects },\n});\n"],"mappings":";;;;;;;;AAWA,SAAOQ,kBAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CACL,MAAAC,SAAeR,cAAc;CAC7B,MAAAS,WAAiBV,mBAAmB;CAAC,IAAAW;CAAA,IAAAC;AAAA,KAAAL,EAAA,OAAAE,UAAAF,EAAA,OAAAG,UAAA;AAErBC,aAAA;AACd,OAAID,SAAQ;GAEZ,MAAA,EAAAG,qBAAAC,uBAAAC,YAAAC,UACEP,OAAMQ,WAAYb,mBAAmB;GAEvC,MAAAc,gBAAsBT,OAAMU,IAAIC,UAAWX,OAAO;AAElD,OAAI,CAACS,cAAa;GAElB,MAAAG,WAAgBC,UAAA;AAEd,QAAIA,MAAKC,QAAS,SAASD,MAAKE,oBAA5B,CAAkDR,QAAQM,MAAM,CAAA;IAQpE,MAAAG,0BAAgCX,wBAC9BQ,MACD;AAOD,QACET,uBACAS,MAAKI,UADL,CAEC,CACCR,eAAa,GACVO,wBAAuBE,IAAKC,MAAyB,CACzD,CAAAC,MAAMC,cAAeA,UAASC,SAAUT,MAAKI,OAAgB,CAAC,CAAA;IAMjE,MAAAO,mBAAyB/B,SAASgB,cAAc;IAMhD,MAAAiB,yBAA+BF,iBAAgBN,KACxCS,cAAA;KACH,MAAAC,YAAkB5B,OAAMU,IAAImB,YAAaC,UAAQ;AAEjD,SAAI,CAACF,UAAS,QAAS;AAAK,YAErB;MAAAE,SACLA;MAAOC,MACD/B,OAAMU,IAAIsB,SAAUJ,UAAU;MAAAA;MAErC;MACD,CAAAK,QACMC,UAAWA,SAAS5B,aAAa4B,MAAM,CAAC;IAMlD,MAAAC,kBAAwB,CAAA,GACnBnB,yBAAuB,GACvBU,uBACJ,CAAAU,KAAMC,OAA0C;IAQjD,MAAA,EAAAC,kBAA0BC;IAO1B,MAAAI,iBAAuB/C,mBAAmBI,QAAQ;KAAAwC,sBAL/CF,iBACCH,gBAAeM,MAAMC,YAAWR,QAAKJ,YAAaQ,cAChD,KAFJ;KAKgDM,WAErC/B,MAAKgC,WAAL,aAAA;KAAuCV;KAEnD,CAAC;AAEF,QAAIQ,gBAAc;AAChB9B,WAAKiC,gBAAiB;AAAAC,UAEtB,SAAQJ,eAAcK,MAAtB;MAA2B,KACpB;AACHL,sBAAcb,QAAQmB,OAAQ;AAE9B,aAAAF;MAAM,KAEH,OACH/C,QAAMkD,GAAGD,MAAO,EAAAE,IACV;OAAAC,QACM;QAAAC,QAAU;QAACtB,MAAQY,eAAcZ;QAAO;OAAAkB,OACzC;QAAAI,QAAU;QAACtB,MAAQY,eAAcZ;QAAM;OAChD,EACD,CAAC;;AAIL;;AAWHP,qBAAgB8B,QAASC,OAWvB;;GAGJ,MAAAC,oBAA0BpD,sBACtBmC,SAAQkB,OADchD;AAI1B+C,qBAAiBE,iBAAkB,WAAW9C,SAAS,KAAK;AAAA,gBAG1D4C,kBAAiBG,oBAAqB,WAAW/C,SAAS,KAAK;;AAChET,OAAA,CAACF,UAAUD,OAAO;AAAAF,IAAA,KAAAE;AAAAF,IAAA,KAAAG;AAAAH,IAAA,KAAAI;AAAAJ,IAAA,KAAAK;QAAA;AAAAD,OAAAJ,EAAA;AAAAK,OAAAL,EAAA;;AA7IrBT,OAAKuE,UAAW1D,IA6IbC,GAAmB;AAAA,QAEf;;AAnJF,SAAAoD,OAAAM,WAAA;CA4HC,MAAAC,cAAoBhC,UAAOiC,aAAc,WAAW;AACpDjC,WAAOkC,aAAc,YAAY,KAAK;AAEtCC,kBAAW;AACT,MAAIH,YACFhC,WAAOkC,aAAc,YAAYF,YAAY;MAE7ChC,WAAOoC,gBAAiB,WAAW;IAEpC,EAAE;;AArIN,SAAA7B,OAAA8B,GAAAC,GAAA;AAAA,QAwEgB9E,QAAO+E,QAASF,EAACpC,MAAOqC,EAACrC,KAAM;;AAxE/C,SAAAZ,MAAAjB,IAAA;CAsCmC,MAAA,EAAA4B,YAAA5B;AAAW,QAAK4B;;;;;AC5C1D,MAAa2C,iBAAiBH,cAAcC,oBAAoB,EAC9DG,QAAQ,EAAEC,eAAeH,iBAAgB,EAC1C,CAAC"}