Skip to content

Commit

Permalink
feat: support attribute format for some properties
Browse files Browse the repository at this point in the history
This allows users to set the locale, data source, and skin tone
emoji using HTML attributes as well as properties.

Fixes #7
  • Loading branch information
nolanlawson committed Aug 16, 2020
1 parent c7293e1 commit c3bcf11
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 5 deletions.
19 changes: 16 additions & 3 deletions README.md
Expand Up @@ -233,10 +233,10 @@ The `new Picker(options)` constructor supports several options:
Name | Type | Default | Description |
------ | ------ | ------ | ------ |
`customEmoji` | CustomEmoji[] | - | Array of custom emoji |
`dataSource` | string | "https://cdn.jsdelivr.net/npm/emojibase-data@5/en/data.json" | URL to fetch the emojibase data from |
`dataSource` | string | "https://cdn.jsdelivr.net/npm/emojibase-data@5/en/data.json" | URL to fetch the emojibase data from (`data-source` when used as an attribute) |
`i18n` | I18n | - | i18n object (see below for details) |
`locale` | string | "en" | Locale string |
`skinToneEmoji` | string | "🖐️" | The emoji to use for the skin tone picker |
`skinToneEmoji` | string | "🖐️" | The emoji to use for the skin tone picker (`skin-tone-emoji` when used as an attribute) |



Expand All @@ -251,13 +251,26 @@ const picker = new Picker({
})
```

These values can also be set at runtime, e.g.:
These values can also be set at runtime:

```js
const picker = new Picker();
picker.dataSource = '/my-emoji.json';
```

Some values can also be set as declarative attributes:

```html
<emoji-picker
locale="fr"
data-source="/fr-emoji.json"
skin-tone-emoji=""
></emoji-picker>
```

Note that complex properties like `i18n` or `customEmoji` are not supported as attributes, because the DOM only
supports string attributes, not complex objects.

#### i18n structure

Here is the default English `i18n` object (`"en"` locale):
Expand Down
13 changes: 13 additions & 0 deletions src/picker/PickerElement.js
Expand Up @@ -15,6 +15,19 @@ export default class Picker extends SveltePicker {
log('disconnectedCallback')
this.$destroy()
}

static get observedAttributes () {
return ['locale', 'data-source', 'skin-tone-emoji'] // complex objects aren't supported, also use kebab-case
}

// via https://github.com/sveltejs/svelte/issues/3852#issuecomment-665037015
attributeChangedCallback (attrName, oldValue, newValue) {
super.attributeChangedCallback(
attrName.replace(/-([a-z])/g, (_, up) => up.toUpperCase()),
oldValue,
newValue
)
}
}

customElements.define('emoji-picker', Picker)
4 changes: 2 additions & 2 deletions src/types/picker.ts
Expand Up @@ -9,10 +9,10 @@ export default class Picker extends HTMLElement {

/**
*
* @param dataSource - URL to fetch the emojibase data from
* @param dataSource - URL to fetch the emojibase data from (`data-source` when used as an attribute)
* @param locale - Locale string
* @param i18n - i18n object (see below for details)
* @param skinToneEmoji - The emoji to use for the skin tone picker
* @param skinToneEmoji - The emoji to use for the skin tone picker (`skin-tone-emoji` when used as an attribute)
* @param customEmoji - Array of custom emoji
*/
constructor({
Expand Down
47 changes: 47 additions & 0 deletions test/spec/picker/attributes.test.js
@@ -0,0 +1,47 @@
import { basicAfterEach, basicBeforeEach, FR_EMOJI, ALL_EMOJI, mockFrenchDataSource, tick } from '../shared'
import Picker from '../../../src/picker/PickerElement.js'
import { getByRole } from '@testing-library/dom'

describe('attributes tests', () => {
beforeEach(async () => {
basicBeforeEach()
mockFrenchDataSource()
})

afterEach(basicAfterEach)

test('setting initial locale/dataSource issues only one GET', async () => {
const picker = new Picker()
picker.setAttribute('locale', 'fr')
picker.setAttribute('data-source', FR_EMOJI)
document.body.appendChild(picker)
await tick(20)

expect(fetch).toHaveBeenCalledTimes(1)
expect(fetch).toHaveBeenLastCalledWith(FR_EMOJI, undefined)

expect(picker.locale).toEqual('fr')
expect(picker.dataSource).toEqual(FR_EMOJI)
expect(picker.getAttribute('locale')).toEqual('fr')
expect(picker.getAttribute('data-source')).toEqual(FR_EMOJI)
})

test('can set skintone emoji using an attribute', async () => {
const picker = new Picker()
picker.setAttribute('data-source', ALL_EMOJI)
picker.setAttribute('skin-tone-emoji', '✌')
document.body.appendChild(picker)
await tick(20)
expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
.toContain('✌')
expect(picker.skinToneEmoji).toEqual('✌')
expect(picker.getAttribute('skin-tone-emoji')).toEqual('✌')
expect(picker.locale).toEqual('en')

picker.setAttribute('skin-tone-emoji', '🏃')
await tick(20)
expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
.toContain('🏃')
expect(picker.skinToneEmoji).toEqual('🏃')
})
})

0 comments on commit c3bcf11

Please sign in to comment.