feat: add skin-tone-change event and types for events
This commit is contained in:
parent
fa3ca2045f
commit
144b72863f
70
README.md
70
README.md
|
@ -378,24 +378,68 @@ all wait for this promise to resolve before doing anything.
|
|||
|
||||
<!-- database API end -->
|
||||
|
||||
### Emoji object
|
||||
### Events
|
||||
|
||||
This object is returned as the Event `detail` in the `emoji-click` event, or when querying the Database. Here is the format:
|
||||
#### `emoji-click`
|
||||
|
||||
```ts
|
||||
interface Emoji {
|
||||
annotation: string;
|
||||
emoticon?: string;
|
||||
group: number;
|
||||
name: string;
|
||||
order: number;
|
||||
shortcodes: string[];
|
||||
tags?: string[];
|
||||
version: number;
|
||||
unicode: string;
|
||||
The `emoji-click` event is fired when an emoji is selected by the user. Example format:
|
||||
|
||||
```javascript
|
||||
{
|
||||
emoji: {
|
||||
annotation: 'thumbs up',
|
||||
group: 1,
|
||||
order: 280,
|
||||
shortcodes: ['thumbsup', '+1', 'yes'],
|
||||
tags: ['+1', 'hand', 'thumb', 'up'],
|
||||
tokens: ['+1', 'hand', 'thumb', 'thumbs', 'thumbsup', 'up', 'yes'],
|
||||
unicode: '👍️',
|
||||
version: 0.6,
|
||||
skins: [
|
||||
{ tone: 1, unicode: '👍🏻', version: 1 },
|
||||
{ tone: 2, unicode: '👍🏼', version: 1 },
|
||||
{ tone: 3, unicode: '👍🏽', version: 1 },
|
||||
{ tone: 4, unicode: '👍🏾', version: 1 },
|
||||
{ tone: 5, unicode: '👍🏿', version: 1 }
|
||||
]
|
||||
},
|
||||
skinTone: 4,
|
||||
unicode: '👍🏾'
|
||||
}
|
||||
```
|
||||
|
||||
And usage:
|
||||
|
||||
```js
|
||||
picker.addEventListener('emoji-click', event => {
|
||||
console.log(event.detail); // will log something like the above
|
||||
});
|
||||
```
|
||||
|
||||
Note that `unicode` will represent whatever the emoji should look like
|
||||
with the given `skinTone`. If the `skinTone` is 0, or if the emoji has
|
||||
no skin tones, then no skin tone is applied to `unicode`.
|
||||
|
||||
#### `skin-tone-change`
|
||||
|
||||
This event is fired whenever the user selects a new skin tone. Example format:
|
||||
|
||||
```js
|
||||
{
|
||||
skinTone: 6
|
||||
}
|
||||
```
|
||||
|
||||
And usage:
|
||||
|
||||
```js
|
||||
picker.addEventListener('skin-tone-change', event => {
|
||||
console.log(event.detail); // will log something like the above
|
||||
})
|
||||
```
|
||||
|
||||
Note that skin tones are an integer from 0 (default) to 1 (light) through 6 (dark).
|
||||
|
||||
### Tree-shaking
|
||||
|
||||
If you want to import the `Database` without the `Picker`, or you want to code-split them separately, then do:
|
||||
|
|
|
@ -282,6 +282,14 @@ function onNavKeydown (event) {
|
|||
}
|
||||
}
|
||||
|
||||
function fireEvent (name, detail) {
|
||||
rootElement.dispatchEvent(new CustomEvent(name, {
|
||||
detail,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}))
|
||||
}
|
||||
|
||||
async function clickEmoji (unicode) {
|
||||
const [emojiSupportLevel, emoji] = await Promise.all([
|
||||
emojiSupportLevelPromise,
|
||||
|
@ -293,15 +301,11 @@ async function clickEmoji (unicode) {
|
|||
unicode = foundSkin.unicode
|
||||
}
|
||||
}
|
||||
rootElement.dispatchEvent(new CustomEvent('emoji-click', {
|
||||
detail: {
|
||||
emoji,
|
||||
skinTone: currentSkinTone,
|
||||
unicode
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}))
|
||||
fireEvent('emoji-click', {
|
||||
emoji,
|
||||
skinTone: currentSkinTone,
|
||||
unicode
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
@ -331,6 +335,7 @@ function onClickSkinToneOption (event) {
|
|||
currentSkinTone = skinTone
|
||||
skinTonePickerExpanded = false
|
||||
focus('skintone-button')
|
||||
fireEvent('skin-tone-change', { skinTone })
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {I18n, PickerConstructorOptions} from "./shared";
|
||||
import {I18n, PickerConstructorOptions, EmojiPickerEventMap, EmojiClickEvent, SkinToneChangeEvent} from "./shared";
|
||||
|
||||
export default class Picker extends HTMLElement {
|
||||
dataSource: string;
|
||||
|
@ -18,6 +18,12 @@ export default class Picker extends HTMLElement {
|
|||
}: PickerConstructorOptions = {}) {
|
||||
super()
|
||||
}
|
||||
|
||||
// Adding types for addEventListener is hard... I basically just copy-pasted this from lib.dom.d.ts. Not sure
|
||||
// Why I need the @ts-ignore
|
||||
addEventListener<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: TextTrackCue, ev: EmojiPickerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
// @ts-ignore
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
}
|
||||
|
||||
// see https://justinfagnani.com/2019/11/01/how-to-publish-web-components-to-npm/
|
||||
|
|
|
@ -47,4 +47,30 @@ export interface I18nCategories {
|
|||
objects: string,
|
||||
symbols: string,
|
||||
flags: string
|
||||
}
|
||||
|
||||
export interface EmojiClickEventDetail {
|
||||
emoji: Emoji,
|
||||
skinTone: number,
|
||||
unicode: string,
|
||||
}
|
||||
|
||||
export interface SkinToneChangeEventDetail {
|
||||
skinTone: number
|
||||
}
|
||||
|
||||
// via https://stackoverflow.com/a/55032655/680742
|
||||
type Modify<T, R> = Omit<T, keyof R> & R;
|
||||
|
||||
export type EmojiClickEvent = Modify<UIEvent, {
|
||||
detail: EmojiClickEventDetail
|
||||
}>
|
||||
|
||||
export type SkinToneChangeEvent = Modify<UIEvent, {
|
||||
detail: SkinToneChangeEventDetail
|
||||
}>
|
||||
|
||||
export interface EmojiPickerEventMap {
|
||||
"emoji-click": EmojiClickEvent;
|
||||
"skin-tone-change": SkinToneChangeEvent;
|
||||
}
|
|
@ -61,6 +61,10 @@ describe('Picker tests', () => {
|
|||
})
|
||||
|
||||
test('basic skintone test', async () => {
|
||||
let event
|
||||
picker.addEventListener('skin-tone-change', newEvent => {
|
||||
event = newEvent
|
||||
})
|
||||
await waitFor(() => expect(getByRole('button', { name: 'Choose a skin tone (currently Default)' })).toBeVisible())
|
||||
expect(queryAllByRole('listbox', { name: 'Skin tones' })).toHaveLength(0)
|
||||
await fireEvent.click(getByRole('button', { name: 'Choose a skin tone (currently Default)' }))
|
||||
|
@ -74,16 +78,23 @@ describe('Picker tests', () => {
|
|||
await waitFor(() => expect(getByRole('option', { name, selected: true })).toBe(activeElement()))
|
||||
}
|
||||
|
||||
await pressKeyAndExpectActiveOption('ArrowDown', 'Light')
|
||||
await pressKeyAndExpectActiveOption('ArrowDown', 'Medium-Light')
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Light')
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Default')
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Dark')
|
||||
await pressKeyAndExpectActiveOption('ArrowDown', 'Light', 1)
|
||||
await pressKeyAndExpectActiveOption('ArrowDown', 'Medium-Light', 2)
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Light', 1)
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Default', 0)
|
||||
await pressKeyAndExpectActiveOption('ArrowUp', 'Dark', 5)
|
||||
|
||||
await fireEvent.click(activeElement(), { key: 'Enter', code: 'Enter' })
|
||||
|
||||
await waitFor(() => expect(event && event.detail).toStrictEqual({ skinTone: 5 }))
|
||||
await waitFor(() => expect(queryAllByRole('listbox', { name: 'Skin tones' })).toHaveLength(0))
|
||||
expect(getByRole('button', { name: 'Choose a skin tone (currently Dark)' })).toBeVisible()
|
||||
|
||||
getByRole('button', { name: 'Choose a skin tone (currently Dark)' }).click()
|
||||
await waitFor(() => expect(queryAllByRole('listbox', { name: 'Skin tones' })).toHaveLength(1))
|
||||
getByRole('option', { name: 'Default' }).click()
|
||||
await waitFor(() => expect(event && event.detail).toStrictEqual({ skinTone: 0 }))
|
||||
expect(getByRole('button', { name: 'Choose a skin tone (currently Default)' })).toBeVisible()
|
||||
})
|
||||
|
||||
test('nav keyboard test', async () => {
|
||||
|
|
Loading…
Reference in New Issue