Skip to content

Commit 16df6ff

Browse files
committed
handling blur event
1 parent bd65a96 commit 16df6ff

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
ariaLabelledBy=this.ariaLabelledBy
5555
value=@value
5656
language=@language
57+
onBlur=@onBlur
5758
onInput=this.onInput
5859
onSetup=this.onSetup
5960
}}

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

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface HdsCodeEditorSignature {
2525
isStandalone?: boolean;
2626
language?: HdsCodeEditorModifierSignature['Args']['Named']['language'];
2727
value?: HdsCodeEditorModifierSignature['Args']['Named']['value'];
28+
onBlur?: HdsCodeEditorModifierSignature['Args']['Named']['onBlur'];
2829
onInput?: HdsCodeEditorModifierSignature['Args']['Named']['onInput'];
2930
onSetup?: HdsCodeEditorModifierSignature['Args']['Named']['onSetup'];
3031
};

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

+43-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import type {
2222
import type { Extension } from '@codemirror/state';
2323
import type { EditorView, ViewUpdate } from '@codemirror/view';
2424

25+
type HdsCodeEditorBlurHandler = (editor: EditorView, event: FocusEvent) => void;
26+
2527
export interface HdsCodeEditorSignature {
2628
Args: {
2729
Named: {
@@ -30,7 +32,7 @@ export interface HdsCodeEditorSignature {
3032
language?: HdsCodeEditorLanguages;
3133
value?: string;
3234
onInput?: (newVal: string) => void;
33-
onBlur?: (editor: EditorView, event: FocusEvent) => void;
35+
onBlur?: HdsCodeEditorBlurHandler;
3436
onSetup?: (editor: EditorView) => unknown;
3537
};
3638
};
@@ -81,8 +83,10 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
8183
editor!: EditorView;
8284
element!: HTMLElement;
8385

86+
onBlur: HdsCodeEditorSignature['Args']['Named']['onBlur'];
8487
onInput: HdsCodeEditorSignature['Args']['Named']['onInput'];
8588

89+
blurHandler!: (event: FocusEvent) => void;
8690
observer!: IntersectionObserver;
8791

8892
constructor(
@@ -91,7 +95,13 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
9195
) {
9296
super(owner, args);
9397

94-
registerDestructor(this, () => this.observer?.disconnect());
98+
registerDestructor(this, () => {
99+
this.observer?.disconnect();
100+
101+
if (this.onBlur !== undefined) {
102+
this.element.removeEventListener('blur', this.blurHandler);
103+
}
104+
});
95105
}
96106

97107
modify(
@@ -122,6 +132,21 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
122132
}
123133
}
124134

135+
private _setupEditorBlurHandler(
136+
element: HTMLElement,
137+
onBlur: HdsCodeEditorBlurHandler
138+
) {
139+
const inputElement = element.querySelector('.cm-content');
140+
141+
if (inputElement === null) {
142+
return;
143+
}
144+
145+
this.blurHandler = (event: FocusEvent) => onBlur(this.editor, event);
146+
147+
(inputElement as HTMLElement).addEventListener('blur', this.blurHandler);
148+
}
149+
125150
private _setupEditorAriaAttributes(
126151
editor: EditorView,
127152
{
@@ -282,11 +307,20 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
282307
_positional: PositionalArgs<HdsCodeEditorSignature>,
283308
named: NamedArgs<HdsCodeEditorSignature>
284309
) => {
285-
const { onInput, onSetup, ariaLabel, ariaLabelledBy, language, value } =
286-
named;
310+
const {
311+
onBlur,
312+
onInput,
313+
onSetup,
314+
ariaLabel,
315+
ariaLabelledBy,
316+
language,
317+
value,
318+
} = named;
287319

288-
this.element = element;
289320
this.onInput = onInput;
321+
this.onBlur = onBlur;
322+
323+
this.element = element;
290324

291325
const editor = await this._createEditorTask.perform(element, {
292326
language,
@@ -299,6 +333,10 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
299333

300334
this.editor = editor;
301335

336+
if (onBlur !== undefined) {
337+
this._setupEditorBlurHandler(element, onBlur);
338+
}
339+
302340
this._setupEditorAriaAttributes(editor, { ariaLabel, ariaLabelledBy });
303341

304342
onSetup?.(this.editor);

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

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { module, test } from 'qunit';
22
import { setupRenderingTest } from 'ember-qunit';
3-
import { render, waitFor, setupOnerror } from '@ember/test-helpers';
3+
import {
4+
render,
5+
waitFor,
6+
setupOnerror,
7+
focus,
8+
blur,
9+
} from '@ember/test-helpers';
410
import { hbs } from 'ember-cli-htmlbars';
511
import sinon from 'sinon';
612

@@ -31,6 +37,22 @@ module('Integration | Modifier | hds-code-editor', function (hooks) {
3137
assert.dom('#code-editor-wrapper .cm-editor').includesText(val);
3238
});
3339

40+
// onBlur
41+
test('it should call the onBlur action when the code editor loses focus', async function (assert) {
42+
const blurSpy = sinon.spy();
43+
44+
this.set('handleBlur', blurSpy);
45+
46+
await setupCodeEditor(
47+
hbs`<div id="code-editor-wrapper" {{hds-code-editor ariaLabel="test" onBlur=this.handleBlur}} />`
48+
);
49+
50+
await focus('.cm-content');
51+
await blur('.cm-content');
52+
53+
assert.ok(blurSpy.calledOnce);
54+
});
55+
3456
// onInput
3557
test('it should call the onInput action when the code editor value changes', async function (assert) {
3658
const inputSpy = sinon.spy();

0 commit comments

Comments
 (0)