Skip to content

Commit

Permalink
Merge pull request #34 from DKhalil/patch-1
Browse files Browse the repository at this point in the history
feat: allow continuation of expander menu
  • Loading branch information
keithamus authored Jun 14, 2023
2 parents 6c915ae + 7cb2f3c commit f970a70
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ The returned fragment should be consisted of filtered `[role=option]` items to b
- `key`: The matched key; for example: `:`.
- `item`: The selected item. This would be one of the `[role=option]`. Use this to work out the `value`.
- `value`: A null value placeholder to replace the query. To replace the text query, simply re-assign this value.
- `continue`: A boolean value to specify whether to continue autocompletion after inserting a value. Defaults to `false`. If set to `true`, will not add a space after inserted value and will keep firing the `text-expander-change` event.
```js
const expander = document.querySelector('text-expander')
Expand Down
17 changes: 13 additions & 4 deletions src/text-expander-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,18 @@ class TextExpander {
const beginning = this.input.value.substring(0, match.position - match.key.length)
const remaining = this.input.value.substring(match.position + match.text.length)

const detail = {item, key: match.key, value: null}
const detail = {item, key: match.key, value: null, continue: false}
const canceled = !this.expander.dispatchEvent(new CustomEvent('text-expander-value', {cancelable: true, detail}))
if (canceled) return

if (!detail.value) return
const suffix = this.expander.getAttribute('suffix') ?? ' '

let suffix = this.expander.getAttribute('suffix') ?? ' '

if (detail.continue) {
suffix = ''
}

const value = `${detail.value}${suffix}`

this.input.value = beginning + value + remaining
Expand All @@ -139,8 +145,11 @@ class TextExpander {

this.input.selectionStart = cursor
this.input.selectionEnd = cursor
this.lookBackIndex = cursor
this.match = null

if (!detail.continue) {
this.lookBackIndex = cursor
this.match = null
}

this.expander.dispatchEvent(
new CustomEvent('text-expander-committed', {cancelable: false, detail: {input: this.input}})
Expand Down
71 changes: 71 additions & 0 deletions test/text-expander-element-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,77 @@ describe('text-expander element', function () {

assert.deepEqual(receivedText, expectedText)
})

it('dispatches value event after selecting item and closes', async function () {
const expander = document.querySelector('text-expander')
const input = expander.querySelector('textarea')
const menu = document.createElement('ul')
const item = document.createElement('li')
item.setAttribute('role', 'option')
menu.appendChild(item)

expander.addEventListener('text-expander-change', event => {
const {provide} = event.detail
provide(Promise.resolve({matched: true, fragment: menu}))
})

expander.addEventListener('text-expander-value', event => {
event.detail.value = ':1'
})

input.focus()
triggerInput(input, ':')
await waitForAnimationFrame()
assert.exists(expander.querySelector('ul'))

const result = once(expander, 'text-expander-value')
expander.querySelector('li').click()
const event = await result
assert.equal(false, event.detail.continue)

assert.equal(input.value, ':1 ')

await waitForAnimationFrame()
assert.isNull(expander.querySelector('ul'))
})

it('dispatches value event after selecting item and keeps menu open', async function () {
const expander = document.querySelector('text-expander')
const input = expander.querySelector('textarea')
const menu = document.createElement('ul')
const item = document.createElement('li')
item.setAttribute('role', 'option')
menu.appendChild(item)

expander.addEventListener('text-expander-change', event => {
const {provide} = event.detail
// eslint-disable-next-line no-console
console.log('ASDFSDF', event.detail)
provide(Promise.resolve({matched: true, fragment: menu}))
})

expander.addEventListener('text-expander-value', event => {
event.detail.value = ':1'
event.detail.continue = true
})

input.focus()
triggerInput(input, ':')
await waitForAnimationFrame()
assert.exists(expander.querySelector('ul'))

const result = once(expander, 'text-expander-value')
expander.querySelector('li').click()
const event = await result
assert.equal(true, event.detail.continue)

triggerInput(input, '#1', true)

assert.equal(input.value, ':1#1')

await waitForAnimationFrame()
assert.exists(expander.querySelector('ul'))
})
})

describe('multi-word scenarios', function () {
Expand Down

0 comments on commit f970a70

Please sign in to comment.