@dxos/keyboard 0.3.10-main.560f82b → 0.3.10-main.dcfebef

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.
@@ -10,12 +10,6 @@ import {
10
10
  // packages/common/keyboard/src/keyboard.ts
11
11
  import { invariant } from "@dxos/invariant";
12
12
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keyboard/src/keyboard.ts";
13
- var modifiers = [
14
- "alt",
15
- "ctrl",
16
- "shift",
17
- "meta"
18
- ];
19
13
  var KeyboardContext = class {
20
14
  constructor() {
21
15
  this._keyMap = /* @__PURE__ */ new Map();
@@ -29,10 +23,15 @@ var KeyboardContext = class {
29
23
  bind(config) {
30
24
  const { binding } = config;
31
25
  const parts = binding.split("+");
32
- const mods = parts.filter((key) => modifiers.includes(key)).sort();
26
+ const mods = parts.filter((key) => [
27
+ "alt",
28
+ "ctrl",
29
+ "meta",
30
+ "shift"
31
+ ].includes(key)).sort();
33
32
  invariant(mods.length === 0 || mods.length === parts.length - 1, void 0, {
34
33
  F: __dxlog_file,
35
- L: 39,
34
+ L: 36,
36
35
  S: this,
37
36
  A: [
38
37
  "mods.length === 0 || mods.length === parts.length - 1",
@@ -78,22 +77,9 @@ var Keyboard = class _Keyboard {
78
77
  destroy() {
79
78
  document.removeEventListener("keydown", this._keyHandler);
80
79
  }
81
- setCurrentContext(path = ROOT) {
80
+ setContext(path = ROOT) {
82
81
  this._path = path;
83
82
  }
84
- getCurrentContext() {
85
- return this._path;
86
- }
87
- getContext(path = ROOT) {
88
- let context = this._keyMap.get(path);
89
- if (!context) {
90
- context = new KeyboardContext();
91
- this._keyMap.set(path, context);
92
- this._contexts.push(path);
93
- this._contexts.sort();
94
- }
95
- return context;
96
- }
97
83
  getBindings() {
98
84
  const bindings = /* @__PURE__ */ new Map();
99
85
  for (let i = 0; i < this._contexts.length; ++i) {
@@ -106,23 +92,31 @@ var Keyboard = class _Keyboard {
106
92
  }
107
93
  return Array.from(bindings.values());
108
94
  }
95
+ getContext(path = ROOT) {
96
+ let context = this._keyMap.get(path);
97
+ if (!context) {
98
+ context = new KeyboardContext();
99
+ this._keyMap.set(path, context);
100
+ this._contexts.push(path);
101
+ this._contexts.sort();
102
+ }
103
+ return context;
104
+ }
109
105
  handleKeyDown(event) {
110
106
  const { altKey, ctrlKey, metaKey, shiftKey, key } = event;
111
107
  if (key !== "Alt" && key !== "Control" && key !== "Meta" && key !== "Shift") {
112
- const tagName = event.target?.tagName;
113
- const isInput = tagName === "INPUT" || tagName === "TEXTAREA" || event.target?.getAttribute("contenteditable");
114
108
  const str = [
115
109
  altKey && "alt",
116
110
  ctrlKey && "ctrl",
117
- shiftKey && "shift",
118
111
  metaKey && "meta",
112
+ shiftKey && "shift",
119
113
  key
120
114
  ].filter(Boolean).join("+");
121
115
  for (let i = this._contexts.length - 1; i >= 0; --i) {
122
116
  const path = this._contexts[i];
123
117
  if (this._path.startsWith(path)) {
124
- const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};
125
- if (handler && (!isInput || !disableInput)) {
118
+ const { data, handler } = this.getContext(path).get(str) ?? {};
119
+ if (handler) {
126
120
  const result = handler({
127
121
  context: path,
128
122
  binding: str,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/keyboard.ts", "../../../src/util.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n binding: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n binding: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\nconst modifiers = ['alt', 'ctrl', 'shift', 'meta'];\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n // Normalize order of modifiers.\n const { binding } = config;\n const parts = binding.split('+');\n const mods = parts.filter((key) => modifiers.includes(key)).sort();\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n if (mods.length) {\n config.binding = [...mods, parts[parts.length - 1]].join('+');\n }\n\n // console.log('bind', config);\n this._keyMap.set(config.binding, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setCurrentContext(path = ROOT) {\n this._path = path;\n }\n\n getCurrentContext() {\n return this._path;\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.binding, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // Binding option to check for input or contenteditable.\n const tagName = (event.target as any)?.tagName;\n const isInput =\n tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');\n\n // Normalized key binding.\n const str = [altKey && 'alt', ctrlKey && 'ctrl', shiftKey && 'shift', metaKey && 'meta', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};\n // console.log('>>>', path, str, handler);\n if (handler && (!isInput || !disableInput)) {\n const result = handler({ context: path, binding: str, data, event });\n if (result !== false) {\n // TODO(burdon): Doesn't prevent actions in markdown editor.\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\n// TODO(burdon): Show Mac/Windows/Linux variants.\nconst symbols: Record<string, string> = {\n // Mods.\n ctrl: '⌃',\n shift: '⇧',\n alt: '⌥',\n meta: '⌘',\n\n // Special keys.\n Backspace: '⌫',\n Enter: '⏎',\n Escape: '⎋',\n Space: '␣',\n Tab: '⇥',\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map((part) => symbols[part] ?? part.toUpperCase());\n};\n"],
5
- "mappings": "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",
6
- "names": ["invariant", "modifiers", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "parts", "split", "mods", "filter", "key", "includes", "sort", "length", "join", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "symbols", "ctrl", "shift", "alt", "meta", "Backspace", "Enter", "Escape", "Space", "Tab", "keySymbols", "keyBinding", "parts", "split", "map", "part", "toUpperCase"]
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n binding: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n binding: string;\n handler: KeyHandler;\n data?: any;\n};\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n // Normalize order of modifiers.\n const { binding } = config;\n const parts = binding.split('+');\n const mods = parts.filter((key) => ['alt', 'ctrl', 'meta', 'shift'].includes(key)).sort();\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n if (mods.length) {\n config.binding = [...mods, parts[parts.length - 1]].join('+');\n }\n\n // console.log('bind', config);\n this._keyMap.set(config.binding, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setContext(path = ROOT) {\n this._path = path;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.binding, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // TODO(burdon): Option to call anywhere.\n // TODO(burdon): Check for contenteditable.\n // const tagName = (event.target as any)?.tagName;\n // if (tagName === 'INPUT' || tagName === 'TEXTAREA') {\n // return;\n // }\n\n const str = [altKey && 'alt', ctrlKey && 'ctrl', metaKey && 'meta', shiftKey && 'shift', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler } = this.getContext(path).get(str) ?? {};\n // console.log('>>>', path, str, handler);\n if (handler) {\n const result = handler({ context: path, binding: str, data, event });\n if (result !== false) {\n // TODO(burdon): Doesn't prevent actions in markdown editor.\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\n// TODO(burdon): Show Mac/Windows/Linux variants.\nconst symbols: Record<string, string> = {\n // Mods.\n ctrl: '⌃',\n shift: '⇧',\n alt: '⌥',\n meta: '⌘',\n\n // Special keys.\n Backspace: '⌫',\n Enter: '⏎',\n Escape: '⎋',\n Space: '␣',\n Tab: '⇥',\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map((part) => symbols[part] ?? part.toUpperCase());\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["invariant", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "parts", "split", "mods", "filter", "key", "includes", "sort", "length", "join", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setContext", "path", "getBindings", "i", "startsWith", "getContext", "forEach", "context", "push", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "str", "Boolean", "data", "handler", "result", "preventDefault", "stopPropagation", "symbols", "ctrl", "shift", "alt", "meta", "Backspace", "Enter", "Escape", "Space", "Tab", "keySymbols", "keyBinding", "parts", "split", "map", "part", "toUpperCase"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/keyboard.ts":{"bytes":15051,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":2733,"imports":[{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":8707},"packages/common/keyboard/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"inject-globals:@inject-globals":{"bytesInOutput":79},"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3589},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":362}},"bytes":4256}}}
1
+ {"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/keyboard.ts":{"bytes":14347,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":2733,"imports":[{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":8209},"packages/common/keyboard/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"inject-globals:@inject-globals":{"bytesInOutput":79},"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3316},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":362}},"bytes":3983}}}
@@ -24,12 +24,6 @@ __export(node_exports, {
24
24
  module.exports = __toCommonJS(node_exports);
25
25
  var import_invariant = require("@dxos/invariant");
26
26
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keyboard/src/keyboard.ts";
27
- var modifiers = [
28
- "alt",
29
- "ctrl",
30
- "shift",
31
- "meta"
32
- ];
33
27
  var KeyboardContext = class {
34
28
  constructor() {
35
29
  this._keyMap = /* @__PURE__ */ new Map();
@@ -43,10 +37,15 @@ var KeyboardContext = class {
43
37
  bind(config) {
44
38
  const { binding } = config;
45
39
  const parts = binding.split("+");
46
- const mods = parts.filter((key) => modifiers.includes(key)).sort();
40
+ const mods = parts.filter((key) => [
41
+ "alt",
42
+ "ctrl",
43
+ "meta",
44
+ "shift"
45
+ ].includes(key)).sort();
47
46
  (0, import_invariant.invariant)(mods.length === 0 || mods.length === parts.length - 1, void 0, {
48
47
  F: __dxlog_file,
49
- L: 39,
48
+ L: 36,
50
49
  S: this,
51
50
  A: [
52
51
  "mods.length === 0 || mods.length === parts.length - 1",
@@ -92,22 +91,9 @@ var Keyboard = class _Keyboard {
92
91
  destroy() {
93
92
  document.removeEventListener("keydown", this._keyHandler);
94
93
  }
95
- setCurrentContext(path = ROOT) {
94
+ setContext(path = ROOT) {
96
95
  this._path = path;
97
96
  }
98
- getCurrentContext() {
99
- return this._path;
100
- }
101
- getContext(path = ROOT) {
102
- let context = this._keyMap.get(path);
103
- if (!context) {
104
- context = new KeyboardContext();
105
- this._keyMap.set(path, context);
106
- this._contexts.push(path);
107
- this._contexts.sort();
108
- }
109
- return context;
110
- }
111
97
  getBindings() {
112
98
  const bindings = /* @__PURE__ */ new Map();
113
99
  for (let i = 0; i < this._contexts.length; ++i) {
@@ -120,23 +106,31 @@ var Keyboard = class _Keyboard {
120
106
  }
121
107
  return Array.from(bindings.values());
122
108
  }
109
+ getContext(path = ROOT) {
110
+ let context = this._keyMap.get(path);
111
+ if (!context) {
112
+ context = new KeyboardContext();
113
+ this._keyMap.set(path, context);
114
+ this._contexts.push(path);
115
+ this._contexts.sort();
116
+ }
117
+ return context;
118
+ }
123
119
  handleKeyDown(event) {
124
120
  const { altKey, ctrlKey, metaKey, shiftKey, key } = event;
125
121
  if (key !== "Alt" && key !== "Control" && key !== "Meta" && key !== "Shift") {
126
- const tagName = event.target?.tagName;
127
- const isInput = tagName === "INPUT" || tagName === "TEXTAREA" || event.target?.getAttribute("contenteditable");
128
122
  const str = [
129
123
  altKey && "alt",
130
124
  ctrlKey && "ctrl",
131
- shiftKey && "shift",
132
125
  metaKey && "meta",
126
+ shiftKey && "shift",
133
127
  key
134
128
  ].filter(Boolean).join("+");
135
129
  for (let i = this._contexts.length - 1; i >= 0; --i) {
136
130
  const path = this._contexts[i];
137
131
  if (this._path.startsWith(path)) {
138
- const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};
139
- if (handler && (!isInput || !disableInput)) {
132
+ const { data, handler } = this.getContext(path).get(str) ?? {};
133
+ if (handler) {
140
134
  const result = handler({
141
135
  context: path,
142
136
  binding: str,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/keyboard.ts", "../../../src/util.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n binding: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n binding: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\nconst modifiers = ['alt', 'ctrl', 'shift', 'meta'];\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n // Normalize order of modifiers.\n const { binding } = config;\n const parts = binding.split('+');\n const mods = parts.filter((key) => modifiers.includes(key)).sort();\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n if (mods.length) {\n config.binding = [...mods, parts[parts.length - 1]].join('+');\n }\n\n // console.log('bind', config);\n this._keyMap.set(config.binding, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setCurrentContext(path = ROOT) {\n this._path = path;\n }\n\n getCurrentContext() {\n return this._path;\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.binding, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // Binding option to check for input or contenteditable.\n const tagName = (event.target as any)?.tagName;\n const isInput =\n tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');\n\n // Normalized key binding.\n const str = [altKey && 'alt', ctrlKey && 'ctrl', shiftKey && 'shift', metaKey && 'meta', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};\n // console.log('>>>', path, str, handler);\n if (handler && (!isInput || !disableInput)) {\n const result = handler({ context: path, binding: str, data, event });\n if (result !== false) {\n // TODO(burdon): Doesn't prevent actions in markdown editor.\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\n// TODO(burdon): Show Mac/Windows/Linux variants.\nconst symbols: Record<string, string> = {\n // Mods.\n ctrl: '⌃',\n shift: '⇧',\n alt: '⌥',\n meta: '⌘',\n\n // Special keys.\n Backspace: '⌫',\n Enter: '⏎',\n Escape: '⎋',\n Space: '␣',\n Tab: '⇥',\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map((part) => symbols[part] ?? part.toUpperCase());\n};\n"],
5
- "mappings": "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",
6
- "names": ["modifiers", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "parts", "split", "mods", "filter", "key", "includes", "sort", "invariant", "length", "join", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "symbols", "ctrl", "shift", "alt", "meta", "Backspace", "Enter", "Escape", "Space", "Tab", "keySymbols", "keyBinding", "map", "part", "toUpperCase"]
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n binding: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n binding: string;\n handler: KeyHandler;\n data?: any;\n};\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n // Normalize order of modifiers.\n const { binding } = config;\n const parts = binding.split('+');\n const mods = parts.filter((key) => ['alt', 'ctrl', 'meta', 'shift'].includes(key)).sort();\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n if (mods.length) {\n config.binding = [...mods, parts[parts.length - 1]].join('+');\n }\n\n // console.log('bind', config);\n this._keyMap.set(config.binding, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setContext(path = ROOT) {\n this._path = path;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.binding, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // TODO(burdon): Option to call anywhere.\n // TODO(burdon): Check for contenteditable.\n // const tagName = (event.target as any)?.tagName;\n // if (tagName === 'INPUT' || tagName === 'TEXTAREA') {\n // return;\n // }\n\n const str = [altKey && 'alt', ctrlKey && 'ctrl', metaKey && 'meta', shiftKey && 'shift', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler } = this.getContext(path).get(str) ?? {};\n // console.log('>>>', path, str, handler);\n if (handler) {\n const result = handler({ context: path, binding: str, data, event });\n if (result !== false) {\n // TODO(burdon): Doesn't prevent actions in markdown editor.\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\n// TODO(burdon): Show Mac/Windows/Linux variants.\nconst symbols: Record<string, string> = {\n // Mods.\n ctrl: '⌃',\n shift: '⇧',\n alt: '⌥',\n meta: '⌘',\n\n // Special keys.\n Backspace: '⌫',\n Enter: '⏎',\n Escape: '⎋',\n Space: '␣',\n Tab: '⇥',\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map((part) => symbols[part] ?? part.toUpperCase());\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "parts", "split", "mods", "filter", "key", "includes", "sort", "invariant", "length", "join", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setContext", "path", "getBindings", "i", "startsWith", "getContext", "forEach", "context", "push", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "str", "Boolean", "data", "handler", "result", "preventDefault", "stopPropagation", "symbols", "ctrl", "shift", "alt", "meta", "Backspace", "Enter", "Escape", "Space", "Tab", "keySymbols", "keyBinding", "map", "part", "toUpperCase"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytes":15051,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":2733,"imports":[],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":8698},"packages/common/keyboard/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3589},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":362}},"bytes":4108}}}
1
+ {"inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytes":14347,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":2733,"imports":[],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":8200},"packages/common/keyboard/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3316},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":362}},"bytes":3835}}}
@@ -7,7 +7,6 @@ export type KeyHandler = (props: {
7
7
  export type KeyBinding = {
8
8
  binding: string;
9
9
  handler: KeyHandler;
10
- disableInput?: boolean;
11
10
  data?: any;
12
11
  };
13
12
  declare class KeyboardContext {
@@ -31,10 +30,9 @@ export declare class Keyboard {
31
30
  destroy(): void;
32
31
  bind: (config: KeyBinding) => void;
33
32
  unbind: (binding: string) => void;
34
- setCurrentContext(path?: string): void;
35
- getCurrentContext(): string;
36
- getContext(path?: string): KeyboardContext;
33
+ setContext(path?: string): void;
37
34
  getBindings(): KeyBinding[];
35
+ getContext(path?: string): KeyboardContext;
38
36
  handleKeyDown(event: KeyboardEvent): void;
39
37
  }
40
38
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/keyboard.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,aAAa,CAAC;CACtB,KAAK,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;AAIF,cAAM,eAAe;IACnB,QAAQ,CAAC,OAAO,0BAAiC;IAEjD,IAAI,QAAQ,iBAEX;IAED,GAAG,CAAC,OAAO,EAAE,MAAM;IAInB,IAAI,CAAC,MAAM,EAAE,UAAU;IAcvB,MAAM,CAAC,OAAO,EAAE,MAAM;CAGvB;AAID;;GAEG;AACH,qBAAa,QAAQ;IACnB,MAAM,CAAC,SAAS,WAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0D;IAClF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAC7D,OAAO,CAAC,KAAK,CAAQ;IAErB,UAAU;IAIV,OAAO;IAIP,IAAI,+BAAoC;IACxC,MAAM,4BAAsC;IAE5C,iBAAiB,CAAC,IAAI,SAAO;IAI7B,iBAAiB;IAIjB,UAAU,CAAC,IAAI,SAAO,GAAG,eAAe;IAYxC,WAAW;IAcX,aAAa,CAAC,KAAK,EAAE,aAAa;CAkCnC"}
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/keyboard.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,aAAa,CAAC;CACtB,KAAK,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;AAEF,cAAM,eAAe;IACnB,QAAQ,CAAC,OAAO,0BAAiC;IAEjD,IAAI,QAAQ,iBAEX;IAED,GAAG,CAAC,OAAO,EAAE,MAAM;IAInB,IAAI,CAAC,MAAM,EAAE,UAAU;IAcvB,MAAM,CAAC,OAAO,EAAE,MAAM;CAGvB;AAID;;GAEG;AACH,qBAAa,QAAQ;IACnB,MAAM,CAAC,SAAS,WAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0D;IAClF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAC7D,OAAO,CAAC,KAAK,CAAQ;IAErB,UAAU;IAIV,OAAO;IAIP,IAAI,+BAAoC;IACxC,MAAM,4BAAsC;IAE5C,UAAU,CAAC,IAAI,SAAO;IAItB,WAAW;IAcX,UAAU,CAAC,IAAI,SAAO,GAAG,eAAe;IAYxC,aAAa,CAAC,KAAK,EAAE,aAAa;CAmCnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/keyboard",
3
- "version": "0.3.10-main.560f82b",
3
+ "version": "0.3.10-main.dcfebef",
4
4
  "description": "Keyboard bindings",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,15 +16,15 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@dxos/node-std": "0.3.10-main.560f82b",
20
- "@dxos/invariant": "0.3.10-main.560f82b"
19
+ "@dxos/invariant": "0.3.10-main.dcfebef",
20
+ "@dxos/node-std": "0.3.10-main.dcfebef"
21
21
  },
22
22
  "devDependencies": {
23
23
  "react": "^18.2.0",
24
24
  "react-dom": "^18.2.0",
25
- "@dxos/react-ui": "0.3.10-main.560f82b",
26
- "@dxos/react-ui-theme": "0.3.10-main.560f82b",
27
- "@dxos/storybook-utils": "0.3.10-main.560f82b"
25
+ "@dxos/react-ui": "0.3.10-main.dcfebef",
26
+ "@dxos/react-ui-theme": "0.3.10-main.dcfebef",
27
+ "@dxos/storybook-utils": "0.3.10-main.dcfebef"
28
28
  },
29
29
  "publishConfig": {
30
30
  "access": "public"
@@ -32,7 +32,7 @@ const Story = () => {
32
32
  }, []);
33
33
 
34
34
  const handleChange = (path: string) => {
35
- Keyboard.singleton.setCurrentContext(path);
35
+ Keyboard.singleton.setContext(path);
36
36
  setContext(path);
37
37
  setBindings(Keyboard.singleton.getBindings());
38
38
  };
package/src/keyboard.ts CHANGED
@@ -14,12 +14,9 @@ export type KeyHandler = (props: {
14
14
  export type KeyBinding = {
15
15
  binding: string;
16
16
  handler: KeyHandler;
17
- disableInput?: boolean;
18
17
  data?: any;
19
18
  };
20
19
 
21
- const modifiers = ['alt', 'ctrl', 'shift', 'meta'];
22
-
23
20
  class KeyboardContext {
24
21
  readonly _keyMap = new Map<string, KeyBinding>();
25
22
 
@@ -35,7 +32,7 @@ class KeyboardContext {
35
32
  // Normalize order of modifiers.
36
33
  const { binding } = config;
37
34
  const parts = binding.split('+');
38
- const mods = parts.filter((key) => modifiers.includes(key)).sort();
35
+ const mods = parts.filter((key) => ['alt', 'ctrl', 'meta', 'shift'].includes(key)).sort();
39
36
  invariant(mods.length === 0 || mods.length === parts.length - 1);
40
37
  if (mods.length) {
41
38
  config.binding = [...mods, parts[parts.length - 1]].join('+');
@@ -75,26 +72,10 @@ export class Keyboard {
75
72
  bind = this._root.bind.bind(this._root);
76
73
  unbind = this._root.unbind.bind(this._root);
77
74
 
78
- setCurrentContext(path = ROOT) {
75
+ setContext(path = ROOT) {
79
76
  this._path = path;
80
77
  }
81
78
 
82
- getCurrentContext() {
83
- return this._path;
84
- }
85
-
86
- getContext(path = ROOT): KeyboardContext {
87
- let context = this._keyMap.get(path);
88
- if (!context) {
89
- context = new KeyboardContext();
90
- this._keyMap.set(path, context);
91
- this._contexts.push(path);
92
- this._contexts.sort();
93
- }
94
-
95
- return context;
96
- }
97
-
98
79
  getBindings() {
99
80
  const bindings = new Map<string, KeyBinding>();
100
81
  for (let i = 0; i < this._contexts.length; ++i) {
@@ -109,17 +90,30 @@ export class Keyboard {
109
90
  return Array.from(bindings.values());
110
91
  }
111
92
 
93
+ getContext(path = ROOT): KeyboardContext {
94
+ let context = this._keyMap.get(path);
95
+ if (!context) {
96
+ context = new KeyboardContext();
97
+ this._keyMap.set(path, context);
98
+ this._contexts.push(path);
99
+ this._contexts.sort();
100
+ }
101
+
102
+ return context;
103
+ }
104
+
112
105
  handleKeyDown(event: KeyboardEvent) {
113
106
  const { altKey, ctrlKey, metaKey, shiftKey, key } = event;
114
107
 
115
108
  if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {
116
- // Binding option to check for input or contenteditable.
117
- const tagName = (event.target as any)?.tagName;
118
- const isInput =
119
- tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');
120
-
121
- // Normalized key binding.
122
- const str = [altKey && 'alt', ctrlKey && 'ctrl', shiftKey && 'shift', metaKey && 'meta', key]
109
+ // TODO(burdon): Option to call anywhere.
110
+ // TODO(burdon): Check for contenteditable.
111
+ // const tagName = (event.target as any)?.tagName;
112
+ // if (tagName === 'INPUT' || tagName === 'TEXTAREA') {
113
+ // return;
114
+ // }
115
+
116
+ const str = [altKey && 'alt', ctrlKey && 'ctrl', metaKey && 'meta', shiftKey && 'shift', key]
123
117
  .filter(Boolean)
124
118
  .join('+');
125
119
 
@@ -127,9 +121,9 @@ export class Keyboard {
127
121
  for (let i = this._contexts.length - 1; i >= 0; --i) {
128
122
  const path = this._contexts[i];
129
123
  if (this._path.startsWith(path)) {
130
- const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};
124
+ const { data, handler } = this.getContext(path).get(str) ?? {};
131
125
  // console.log('>>>', path, str, handler);
132
- if (handler && (!isInput || !disableInput)) {
126
+ if (handler) {
133
127
  const result = handler({ context: path, binding: str, data, event });
134
128
  if (result !== false) {
135
129
  // TODO(burdon): Doesn't prevent actions in markdown editor.