Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion libs/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,7 @@ declare global {
"pdsChange": InputChangeEventDetail;
"pdsFocus": FocusEvent;
"pdsInput": InputInputEventDetail;
"pdsKeyDown": KeyboardEvent;
}
interface HTMLPdsInputElement extends Components.PdsInput, HTMLStencilElement {
addEventListener<K extends keyof HTMLPdsInputElementEventMap>(type: K, listener: (this: HTMLPdsInputElement, ev: PdsInputCustomEvent<HTMLPdsInputElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -2497,6 +2498,9 @@ declare global {
};
interface HTMLPdsSelectElementEventMap {
"pdsSelectChange": InputEvent;
"pdsBlur": FocusEvent;
"pdsFocus": FocusEvent;
"pdsKeyDown": KeyboardEvent;
}
interface HTMLPdsSelectElement extends Components.PdsSelect, HTMLStencilElement {
addEventListener<K extends keyof HTMLPdsSelectElementEventMap>(type: K, listener: (this: HTMLPdsSelectElement, ev: PdsSelectCustomEvent<HTMLPdsSelectElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -2673,6 +2677,7 @@ declare global {
"pdsFocus": FocusEvent;
"pdsInput": TextareaInputEventDetail;
"pdsTextareaChange": TextareaChangeEventDetail;
"pdsKeyDown": KeyboardEvent;
}
interface HTMLPdsTextareaElement extends Components.PdsTextarea, HTMLStencilElement {
addEventListener<K extends keyof HTMLPdsTextareaElementEventMap>(type: K, listener: (this: HTMLPdsTextareaElement, ev: PdsTextareaCustomEvent<HTMLPdsTextareaElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -3949,6 +3954,10 @@ declare namespace LocalJSX {
* Emitted when a keyboard input occurs.
*/
"onPdsInput"?: (event: PdsInputCustomEvent<InputInputEventDetail>) => void;
/**
* Emitted when a key is pressed down in the input.
*/
"onPdsKeyDown"?: (event: PdsInputCustomEvent<KeyboardEvent>) => void;
/**
* Specifies the regular expression that the input value is checked against.
*/
Expand Down Expand Up @@ -4356,7 +4365,19 @@ declare namespace LocalJSX {
*/
"name": string;
/**
* Emitted when a keyboard input occurs.
* Emitted when the select loses focus.
*/
"onPdsBlur"?: (event: PdsSelectCustomEvent<FocusEvent>) => void;
/**
* Emitted when the select gains focus.
*/
"onPdsFocus"?: (event: PdsSelectCustomEvent<FocusEvent>) => void;
/**
* Emitted when a key is pressed down in the select.
*/
"onPdsKeyDown"?: (event: PdsSelectCustomEvent<KeyboardEvent>) => void;
/**
* Emitted when the select value changes.
*/
"onPdsSelectChange"?: (event: PdsSelectCustomEvent<InputEvent>) => void;
/**
Expand Down Expand Up @@ -4760,6 +4781,10 @@ declare namespace LocalJSX {
* Emitted when a keyboard input occurs. For elements that accept text input (`type=text`, `type=tel`, etc.), the interface is [`InputEvent`](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent); for others, the interface is [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event). If the input is cleared on edit, the type is `null`.
*/
"onPdsInput"?: (event: PdsTextareaCustomEvent<TextareaInputEventDetail>) => void;
/**
* Emitted when a key is pressed down in the textarea.
*/
"onPdsKeyDown"?: (event: PdsTextareaCustomEvent<KeyboardEvent>) => void;
/**
* Event emitted whenever the value of the textarea changes. This event will not emit when programmatically setting the `value` property.
*/
Expand Down
10 changes: 10 additions & 0 deletions libs/core/src/components/pds-input/pds-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ export class PdsInput {
*/
@Event() pdsInput: EventEmitter<InputInputEventDetail>;

/**
* Emitted when a key is pressed down in the input.
*/
@Event() pdsKeyDown!: EventEmitter<KeyboardEvent>;

/**
* Sets focus on the native `input` in the `pds-input`. Use this method instead of the global
* `input.focus()`.
Expand Down Expand Up @@ -389,6 +394,10 @@ export class PdsInput {
this.isComposing = false;
}

private onKeyDownEvent = (ev: KeyboardEvent) => {
this.pdsKeyDown.emit(ev);
};

/**
* Emits a pdsChange event
*/
Expand Down Expand Up @@ -535,6 +544,7 @@ export class PdsInput {
onChange={this.onChangeEvent}
onBlur={this.onBlurEvent}
onFocus={this.onFocusEvent}
onKeyDown={this.onKeyDownEvent}
onCompositionstart={this.onCompositionStart}
onCompositionend={this.onCompositionEnd}
{...this.inheritedAttributes}
Expand Down
13 changes: 7 additions & 6 deletions libs/core/src/components/pds-input/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@

## Events

| Event | Description | Type |
| ----------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `pdsBlur` | Emitted when the input loses focus. | `CustomEvent<FocusEvent>` |
| `pdsChange` | Emitted when the value has changed. This event will not emit when programmatically setting the `value` property. | `CustomEvent<InputChangeEventDetail>` |
| `pdsFocus` | Emitted when the input has focus. | `CustomEvent<FocusEvent>` |
| `pdsInput` | Emitted when a keyboard input occurs. | `CustomEvent<InputInputEventDetail>` |
| Event | Description | Type |
| ------------ | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `pdsBlur` | Emitted when the input loses focus. | `CustomEvent<FocusEvent>` |
| `pdsChange` | Emitted when the value has changed. This event will not emit when programmatically setting the `value` property. | `CustomEvent<InputChangeEventDetail>` |
| `pdsFocus` | Emitted when the input has focus. | `CustomEvent<FocusEvent>` |
| `pdsInput` | Emitted when a keyboard input occurs. | `CustomEvent<InputInputEventDetail>` |
| `pdsKeyDown` | Emitted when a key is pressed down in the input. | `CustomEvent<KeyboardEvent>` |


## Methods
Expand Down
40 changes: 40 additions & 0 deletions libs/core/src/components/pds-input/test/pds-input.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,46 @@ describe('pds-input', () => {
expect(onFocusEvent).toHaveBeenCalled();
});

it('emits pdsKeyDown event when a key is pressed', async () => {
const page = await newSpecPage({
components: [PdsInput],
html: `<pds-input />`,
});

const pdsInput = page.root;
const nativeInput = pdsInput?.shadowRoot?.querySelector('input');
const onKeyDownEvent = jest.fn();
pdsInput?.addEventListener('pdsKeyDown', onKeyDownEvent);

const keyboardEvent = new KeyboardEvent('keydown', { key: 'Enter' });
nativeInput?.dispatchEvent(keyboardEvent);
await page.waitForChanges();

expect(onKeyDownEvent).toHaveBeenCalled();
});

it('emits pdsKeyDown event with correct key information', async () => {
const page = await newSpecPage({
components: [PdsInput],
html: `<pds-input />`,
});

const pdsInput = page.root;
const nativeInput = pdsInput?.shadowRoot?.querySelector('input');
let receivedEvent: KeyboardEvent | null = null;

pdsInput?.addEventListener('pdsKeyDown', (e: CustomEvent<KeyboardEvent>) => {
receivedEvent = e.detail;
});

const keyboardEvent = new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape' });
nativeInput?.dispatchEvent(keyboardEvent);
await page.waitForChanges();

expect(receivedEvent).not.toBeNull();
expect(receivedEvent?.key).toBe('Escape');
});

it('should call onChangeEvent when value is changed', async () => {
const page = await newSpecPage({
components: [PdsInput],
Expand Down
32 changes: 31 additions & 1 deletion libs/core/src/components/pds-select/pds-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,25 @@ export class PdsSelect {


/**
* Emitted when a keyboard input occurs.
* Emitted when the select value changes.
*/
@Event() pdsSelectChange: EventEmitter<InputEvent>;

/**
* Emitted when the select loses focus.
*/
@Event() pdsBlur!: EventEmitter<FocusEvent>;

/**
* Emitted when the select gains focus.
*/
@Event() pdsFocus!: EventEmitter<FocusEvent>;

/**
* Emitted when a key is pressed down in the select.
*/
@Event() pdsKeyDown!: EventEmitter<KeyboardEvent>;

@Watch('value')
/**
* Handles the change in the value of the select component.
Expand Down Expand Up @@ -184,6 +199,18 @@ export class PdsSelect {
this.pdsSelectChange.emit(e as InputEvent);
};

private onBlur = (ev: FocusEvent) => {
this.pdsBlur.emit(ev);
};

private onFocus = (ev: FocusEvent) => {
this.pdsFocus.emit(ev);
};

private onKeyDown = (ev: KeyboardEvent) => {
this.pdsKeyDown.emit(ev);
};

/**
* Handles the change event for the slot element.
* This method is triggered when the slot content changes.
Expand Down Expand Up @@ -350,7 +377,10 @@ export class PdsSelect {
id={this.componentId}
multiple={this.multiple}
name={this.name}
onBlur={this.onBlur}
onChange={this.onSelectUpdate}
onFocus={this.onFocus}
onKeyDown={this.onKeyDown}
part="select"
required={this.required}
ref={(el) => (this.selectEl = el as HTMLSelectElement)}
Expand Down
9 changes: 6 additions & 3 deletions libs/core/src/components/pds-select/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@

## Events

| Event | Description | Type |
| ----------------- | ------------------------------------- | ------------------------- |
| `pdsSelectChange` | Emitted when a keyboard input occurs. | `CustomEvent<InputEvent>` |
| Event | Description | Type |
| ----------------- | ------------------------------------------------- | ---------------------------- |
| `pdsBlur` | Emitted when the select loses focus. | `CustomEvent<FocusEvent>` |
| `pdsFocus` | Emitted when the select gains focus. | `CustomEvent<FocusEvent>` |
| `pdsKeyDown` | Emitted when a key is pressed down in the select. | `CustomEvent<KeyboardEvent>` |
| `pdsSelectChange` | Emitted when the select value changes. | `CustomEvent<InputEvent>` |


## Slots
Expand Down
76 changes: 76 additions & 0 deletions libs/core/src/components/pds-select/test/pds-select.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,82 @@ describe('onSelectUpdate', () => {
});
});

describe('event emitters', () => {
it('emits pdsBlur event when select loses focus', async () => {
const page = await newSpecPage({
components: [PdsSelect],
html: `<pds-select component-id="field-1" name="test"></pds-select>`,
});

const pdsSelect = page.root;
const nativeSelect = pdsSelect?.shadowRoot?.querySelector('select');
const onBlurEvent = jest.fn();
pdsSelect?.addEventListener('pdsBlur', onBlurEvent);

nativeSelect?.dispatchEvent(new FocusEvent('blur'));
await page.waitForChanges();

expect(onBlurEvent).toHaveBeenCalled();
});

it('emits pdsFocus event when select gains focus', async () => {
const page = await newSpecPage({
components: [PdsSelect],
html: `<pds-select component-id="field-1" name="test"></pds-select>`,
});

const pdsSelect = page.root;
const nativeSelect = pdsSelect?.shadowRoot?.querySelector('select');
const onFocusEvent = jest.fn();
pdsSelect?.addEventListener('pdsFocus', onFocusEvent);

nativeSelect?.dispatchEvent(new FocusEvent('focus'));
await page.waitForChanges();

expect(onFocusEvent).toHaveBeenCalled();
});

it('emits pdsKeyDown event when a key is pressed', async () => {
const page = await newSpecPage({
components: [PdsSelect],
html: `<pds-select component-id="field-1" name="test"></pds-select>`,
});

const pdsSelect = page.root;
const nativeSelect = pdsSelect?.shadowRoot?.querySelector('select');
const onKeyDownEvent = jest.fn();
pdsSelect?.addEventListener('pdsKeyDown', onKeyDownEvent);

const keyboardEvent = new KeyboardEvent('keydown', { key: 'ArrowDown' });
nativeSelect?.dispatchEvent(keyboardEvent);
await page.waitForChanges();

expect(onKeyDownEvent).toHaveBeenCalled();
});

it('emits pdsKeyDown event with correct key information', async () => {
const page = await newSpecPage({
components: [PdsSelect],
html: `<pds-select component-id="field-1" name="test"></pds-select>`,
});

const pdsSelect = page.root;
const nativeSelect = pdsSelect?.shadowRoot?.querySelector('select');
let receivedEvent: KeyboardEvent | null = null;

pdsSelect?.addEventListener('pdsKeyDown', (e: CustomEvent<KeyboardEvent>) => {
receivedEvent = e.detail;
});

const keyboardEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter' });
nativeSelect?.dispatchEvent(keyboardEvent);
await page.waitForChanges();

expect(receivedEvent).not.toBeNull();
expect(receivedEvent?.key).toBe('Enter');
});
});

describe('action slot', () => {
it('renders action slot content when provided', async () => {
const { root } = await newSpecPage({
Expand Down
10 changes: 10 additions & 0 deletions libs/core/src/components/pds-textarea/pds-textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ export class PdsTextarea {
*/
@Event() pdsTextareaChange: EventEmitter<TextareaChangeEventDetail>;

/**
* Emitted when a key is pressed down in the textarea.
*/
@Event() pdsKeyDown!: EventEmitter<KeyboardEvent>;

/**
* Sets focus on the native `textarea` in the `pds-textarea`. Use this method instead of the global
* `textarea.focus()`.
Expand Down Expand Up @@ -287,6 +292,10 @@ export class PdsTextarea {
this.emitValueChange(ev);
};

private onKeyDown = (ev: KeyboardEvent) => {
this.pdsKeyDown.emit(ev);
};

private textareaClassNames() {
const classNames = ['pds-textarea__field'];

Expand Down Expand Up @@ -516,6 +525,7 @@ export class PdsTextarea {
onChange={this.onTextareaChange}
onFocus={this.onFocus}
onInput={this.onInput}
onKeyDown={this.onKeyDown}
{...this.inheritedAttributes}
>
{value}
Expand Down
1 change: 1 addition & 0 deletions libs/core/src/components/pds-textarea/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
| `pdsBlur` | Emitted when the input loses focus. | `CustomEvent<FocusEvent>` |
| `pdsFocus` | Emitted when the input has focus. | `CustomEvent<FocusEvent>` |
| `pdsInput` | Emitted when a keyboard input occurs. For elements that accept text input (`type=text`, `type=tel`, etc.), the interface is [`InputEvent`](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent); for others, the interface is [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event). If the input is cleared on edit, the type is `null`. | `CustomEvent<TextareaInputEventDetail>` |
| `pdsKeyDown` | Emitted when a key is pressed down in the textarea. | `CustomEvent<KeyboardEvent>` |
| `pdsTextareaChange` | Event emitted whenever the value of the textarea changes. This event will not emit when programmatically setting the `value` property. | `CustomEvent<TextareaChangeEventDetail>` |


Expand Down
Loading