diff --git a/etc/lime-elements.api.md b/etc/lime-elements.api.md index c62e374886..5be191d6a8 100644 --- a/etc/lime-elements.api.md +++ b/etc/lime-elements.api.md @@ -197,7 +197,6 @@ export namespace Components { // @beta "type"?: ChipType; } - // (undocumented) export interface LimelChipSet { "clearAllButton": boolean; "delimiter": string; @@ -1000,7 +999,6 @@ namespace JSX_2 { // @beta "type"?: ChipType; } - // (undocumented) interface LimelChipSet { "clearAllButton"?: boolean; "delimiter"?: string; diff --git a/src/components/chip-set/chip-set.e2e.ts b/src/components/chip-set/chip-set.e2e.ts index 143b525b9e..60651b9f56 100644 --- a/src/components/chip-set/chip-set.e2e.ts +++ b/src/components/chip-set/chip-set.e2e.ts @@ -279,6 +279,17 @@ describe('limel-chip-set', () => { describe('when a chip is clicked', () => { beforeEach(async () => { + await page.evaluate(() => { + (window as any).customEventTestResults = {}; + document.addEventListener('click', (e) => { + const hasCustomProperty = + !!(e as any).Lime && !!(e as any).Lime.chip; + ( + window as any + ).customEventTestResults.clickCustomProperty = + hasCustomProperty; + }); + }); spy = await chipSet.spyOnEvent('interact'); await chips[0].click(); }); @@ -291,6 +302,15 @@ describe('limel-chip-set', () => { removable: true, }); }); + + it('attaches the chip to the click event', async () => { + const hasCustomProperty = await page.evaluate( + () => + (window as any).customEventTestResults + .clickCustomProperty, + ); + expect(hasCustomProperty).toBeTruthy(); + }); }); describe('when disabled', () => { diff --git a/src/components/chip-set/chip-set.tsx b/src/components/chip-set/chip-set.tsx index fbc6e6d7b5..d64dfb5499 100644 --- a/src/components/chip-set/chip-set.tsx +++ b/src/components/chip-set/chip-set.tsx @@ -21,6 +21,36 @@ import { LimelChipCustomEvent } from 'src/components'; const INPUT_FIELD_TABINDEX = 1; /** + * :::note + * **Regarding `click` and `interact` events:** + * + * The `interact` event is emitted when a chip is interacted with, and is + * the recommended way to listen for chip interactions. + * + * However, if you need to handle clicks differently depending on which chip + * was clicked, or whether the click was on a chip or elsewhere, you need to + * listen to the native `click` event instead. + * + * Native `click` events are passed through, and if the click came from + * a chip, the chip object is available in the event object under + * `.Lime.chip`. + * + * Example usage: + * ```ts + * private handleClick(event: Event) { + * if (event && 'Lime' in event && (event.Lime as any).chip) { + * if ((event.Lime as { chip: Chip }).chip.href) { + * // Chip has href, so let the browser open the link. + * return; + * } + * // handle click on chip without href + * } else { + * // handle click elsewhere + * } + * } + * ``` + * ::: + * * @exampleComponent limel-example-chip-set * @exampleComponent limel-example-chip-set-choice * @exampleComponent limel-example-chip-set-filter @@ -615,7 +645,20 @@ export class ChipSet { }; } - private catchInputChipClicks = (chip: Chip) => () => { + private catchInputChipClicks = (chip: Chip) => (event: Event) => { + /* + * We need to add the `chip` to the event object so that the consumer + * can get the chip object when the chip is clicked. + * This is necessary for the consumer to be able to handle the click + * event itself, based on which chip was clicked, or whether the click + * was on a chip or elsewhere. The reason the consumer can't just look + * at the event target is that that information is hidden by the + * shadow DOM. + * + * See documentation for the `interact` event for more information. + */ + (event as any).Lime = { chip: chip }; + if (this.isSelectableChip(chip)) { this.updateSelectedChipIds(chip); this.change.emit(chip); diff --git a/src/components/file/file.tsx b/src/components/file/file.tsx index 75d8179d4d..b0829aeab8 100644 --- a/src/components/file/file.tsx +++ b/src/components/file/file.tsx @@ -201,7 +201,7 @@ export class File { leadingIcon="upload_to_cloud" language={this.language} onChange={this.handleChipSetChange} - onClick={this.handleFileSelection} + onClick={this.handleClick} onInteract={this.handleChipInteract} onKeyDown={this.handleKeyDown} onKeyUp={this.handleKeyUp} @@ -273,6 +273,15 @@ export class File { } } + private handleClick = (event: Event) => { + if (event && 'Lime' in event && (event.Lime as any).chip) { + // This is a click on a chip, so we don't need to do anything here. + return; + } + + this.handleFileSelection(event); + }; + private handleFileSelection(event: Event) { event.stopPropagation(); event.preventDefault();