Skip to content

Commit 35512a5

Browse files
feat(ClipboardCopy): added onBlur and onFocus callbacks
1 parent d5053dd commit 35512a5

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

packages/react-core/src/components/ClipboardCopy/ClipboardCopy.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ export interface ClipboardCopyProps extends Omit<React.HTMLProps<HTMLDivElement>
9191
onCopy?: (event: React.ClipboardEvent<HTMLDivElement>, text?: React.ReactNode) => void;
9292
/** A function that is triggered on changing the text. */
9393
onChange?: (event: React.FormEvent, text?: string) => void;
94+
/** Callback function when text input is focused */
95+
onInputFocus?: (event?: any) => void;
96+
/** Callback function when text input is blurred (focus leaves) */
97+
onInputBlur?: (event?: any) => void;
9498
/** The text which is copied. */
9599
children: string | string[];
96100
/** Additional actions for inline clipboard copy. Should be wrapped with ClipboardCopyAction. */
@@ -177,6 +181,8 @@ class ClipboardCopy extends Component<ClipboardCopyProps, ClipboardCopyState> {
177181
/* eslint-disable @typescript-eslint/no-unused-vars */
178182
isExpanded,
179183
onChange, // Don't pass to <div>
184+
onInputFocus, // Don't pass to <div>
185+
onInputBlur, // Don't pass to <div>
180186
/* eslint-enable @typescript-eslint/no-unused-vars */
181187
isReadOnly,
182188
isCode,
@@ -297,6 +303,8 @@ class ClipboardCopy extends Component<ClipboardCopyProps, ClipboardCopyState> {
297303
value={this.state.expanded ? this.state.textWhenExpanded : copyableText}
298304
id={`text-input-${id}`}
299305
aria-label={textAriaLabel}
306+
onFocus={onInputFocus}
307+
onBlur={onInputBlur}
300308
{...(isCode && { dir: 'ltr' })}
301309
/>
302310
<ClipboardCopyButton

packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopy.test.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,66 @@ test('Does not call onChange when ClipboardCopy textinput is not typed in', asyn
338338
expect(onChangeMock).not.toHaveBeenCalled();
339339
});
340340

341+
test('Calls onFocus when ClipboardCopy textinput is focused', async () => {
342+
const onFocusMock = jest.fn();
343+
const user = userEvent.setup();
344+
345+
render(<ClipboardCopy onInputFocus={onFocusMock}>{children}</ClipboardCopy>);
346+
347+
await user.click(screen.getByRole('textbox'));
348+
349+
expect(onFocusMock).toHaveBeenCalledTimes(1);
350+
});
351+
352+
test('Does not call onFocus when ClipboardCopy textinput is not focused', async () => {
353+
const onFocusMock = jest.fn();
354+
const user = userEvent.setup();
355+
356+
render(
357+
<>
358+
<ClipboardCopy onInputFocus={onFocusMock}>{children}</ClipboardCopy>
359+
<input aria-label="native input" />
360+
</>
361+
);
362+
363+
await user.click(screen.getByRole('textbox', { name: 'native input' }));
364+
365+
expect(onFocusMock).not.toHaveBeenCalled();
366+
});
367+
368+
test('Calls onBlur when ClipboardCopy textinput loses focus', async () => {
369+
const onBlurMock = jest.fn();
370+
const user = userEvent.setup();
371+
372+
render(
373+
<>
374+
<ClipboardCopy onInputBlur={onBlurMock}>{children}</ClipboardCopy>
375+
<input aria-label="native input" />
376+
</>
377+
);
378+
379+
await user.click(screen.getByRole('textbox', { name: 'Copyable input' }));
380+
await user.click(screen.getByRole('textbox', { name: 'native input' }));
381+
382+
expect(onBlurMock).toHaveBeenCalledTimes(1);
383+
});
384+
385+
test('Does not call onBlur when ClipboardCopy textinput does not lose focus', async () => {
386+
const onBlurMock = jest.fn();
387+
const user = userEvent.setup();
388+
389+
render(
390+
<>
391+
<ClipboardCopy onInputBlur={onBlurMock}>{children}</ClipboardCopy>
392+
<input aria-label="native input" />
393+
</>
394+
);
395+
396+
await user.click(screen.getByRole('textbox', { name: 'native input' }));
397+
398+
expect(onBlurMock).not.toHaveBeenCalled();
399+
});
400+
341401
test('Calls onCopy when ClipboardCopyButton is clicked', async () => {
342402
const onCopyMock = jest.fn();
343403
const user = userEvent.setup();

packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopy.test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ exports[`Matches snapshot 1`] = `
1818
<input
1919
aria-invalid="false"
2020
aria-label="Copyable input"
21-
data-ouia-component-id="OUIA-Generated-TextInputBase-36"
21+
data-ouia-component-id="OUIA-Generated-TextInputBase-40"
2222
data-ouia-component-type="PF6/TextInput"
2323
data-ouia-safe="true"
2424
id="text-input-generated-id"

0 commit comments

Comments
 (0)