Skip to content

Commit abcabaf

Browse files
authored
Code Editor - Support custom keybinding (#2776)
1 parent 2376ab0 commit abcabaf

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

.changeset/four-avocados-smoke.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@hashicorp/design-system-components": minor
3+
---
4+
5+
`hds-code-editor` modifier - Add `extraKeys` argument which supports custom keybinding
6+
7+
`CodeEditor` - Add `@extraKeys` argument which supports custom keybinding

packages/components/src/components/hds/code-editor/index.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
ariaDescribedBy=this.ariaDescribedBy
5656
ariaLabel=@ariaLabel
5757
ariaLabelledBy=this.ariaLabelledBy
58+
extraKeys=@extraKeys
5859
hasLineWrapping=@hasLineWrapping
5960
language=@language
6061
value=@value

packages/components/src/modifiers/hds-code-editor.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
import type { Extension } from '@codemirror/state';
2525
import type {
2626
EditorView as EditorViewType,
27+
KeyBinding,
2728
ViewUpdate,
2829
} from '@codemirror/view';
2930
import type Owner from '@ember/owner';
@@ -33,13 +34,18 @@ type HdsCodeEditorBlurHandler = (
3334
event: FocusEvent
3435
) => void;
3536

37+
interface HdsCodeEditorExtraKeys {
38+
[key: string]: () => void;
39+
}
40+
3641
export interface HdsCodeEditorSignature {
3742
Args: {
3843
Named: {
3944
ariaDescribedBy?: string;
4045
ariaLabel?: string;
4146
ariaLabelledBy?: string;
4247
cspNonce?: string;
48+
extraKeys?: HdsCodeEditorExtraKeys;
4349
hasLineWrapping?: boolean;
4450
language?: HdsCodeEditorLanguages;
4551
value?: string;
@@ -298,7 +304,7 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
298304

299305
private _buildExtensionsTask = task(
300306
{ drop: true },
301-
async ({ cspNonce, language, hasLineWrapping }) => {
307+
async ({ cspNonce, extraKeys, language, hasLineWrapping }) => {
302308
const [
303309
{
304310
keymap,
@@ -355,6 +361,15 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
355361
syntaxHighlighting(hdsDarkHighlightStyle),
356362
];
357363

364+
if (extraKeys !== undefined) {
365+
const customKeyMap = Object.entries(extraKeys).map(([key, value]) => ({
366+
key: key,
367+
run: value,
368+
}));
369+
370+
extensions = [keymap.of(customKeyMap as KeyBinding[]), ...extensions];
371+
}
372+
358373
if (languageExtension !== undefined) {
359374
extensions = [languageExtension, ...extensions];
360375
}
@@ -377,18 +392,20 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
377392
{
378393
cspNonce,
379394
language,
395+
extraKeys,
380396
value,
381397
hasLineWrapping,
382398
}: Pick<
383399
HdsCodeEditorSignature['Args']['Named'],
384-
'cspNonce' | 'language' | 'value' | 'hasLineWrapping'
400+
'cspNonce' | 'language' | 'extraKeys' | 'value' | 'hasLineWrapping'
385401
>
386402
) => {
387403
try {
388404
const { EditorState } = await import('@codemirror/state');
389405

390406
const extensions = await this._buildExtensionsTask.perform({
391407
cspNonce,
408+
extraKeys,
392409
language,
393410
hasLineWrapping: hasLineWrapping ?? false,
394411
});
@@ -427,6 +444,7 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
427444
ariaLabel,
428445
ariaLabelledBy,
429446
cspNonce,
447+
extraKeys,
430448
hasLineWrapping,
431449
language,
432450
value,
@@ -439,6 +457,7 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
439457

440458
const editor = await this._createEditorTask.perform(element, {
441459
cspNonce,
460+
extraKeys,
442461
language,
443462
value,
444463
hasLineWrapping,

showcase/tests/integration/modifiers/hds-code-editor-test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,30 @@ module('Integration | Modifier | hds-code-editor', function (hooks) {
139139
assert.ok(document.querySelector('style[nonce="test-nonce"]'));
140140
});
141141

142+
// extraKeys
143+
test('setting extraKeys should add the provided keybindings to the editor', async function (assert) {
144+
const saveSpy = sinon.spy(() => console.log('Save!'));
145+
146+
this.set('extraKeys', {
147+
'Shift-Enter': saveSpy,
148+
});
149+
150+
await setupCodeEditor(
151+
hbs`<div id="code-editor-wrapper" {{hds-code-editor ariaLabel="test" extraKeys=this.extraKeys}} />`
152+
);
153+
154+
const event = new KeyboardEvent('keydown', {
155+
key: 'Enter',
156+
code: 'Enter',
157+
shiftKey: true,
158+
bubbles: true,
159+
});
160+
161+
document.querySelector('.cm-content').dispatchEvent(event);
162+
163+
assert.ok(saveSpy.calledOnce);
164+
});
165+
142166
// ASSERTIONS
143167

144168
test('it should throw an assertion if both ariaLabel and ariaLabelledBy are ommitted', async function (assert) {

0 commit comments

Comments
 (0)