Skip to content

Commit

Permalink
feat: support attribute format for some properties (#33)
Browse files Browse the repository at this point in the history
* feat: support attribute format for some properties

This allows users to set the locale, data source, and skin tone
emoji using HTML attributes as well as properties.

Fixes #7

* fix: increment bundlesize
  • Loading branch information
nolanlawson committed Aug 21, 2020
1 parent f083ace commit 83e516c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 6 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
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -177,7 +177,7 @@
"bundlesize": [
{
"path": "./bundle.js",
"maxSize": "40 kB",
"maxSize": "40.5 kB",
"compression": "none"
},
{
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 83e516c

Please sign in to comment.