From e0c8909a8ecb1b31b769cc9f23d417313888165b Mon Sep 17 00:00:00 2001 From: tpluscode Date: Fri, 4 Nov 2022 21:27:45 +0100 Subject: [PATCH] feat: debounce and spin autocomplete --- .changeset/few-actors-peel.md | 5 +++ .changeset/polite-ducks-divide.md | 5 +++ packages/wc-shoelace/README.md | 16 +++---- .../wc-shoelace/components/autocomplete.ts | 3 +- packages/wc-shoelace/custom-elements.json | 20 +++++++++ .../elements/sh-sl-autocomplete.ts | 42 +++++++++++++++---- packages/wc-shoelace/package.json | 3 +- .../test/components/autocomplete.test.ts | 17 ++++++++ .../test/elements/sh-sl-autocomplete.test.ts | 8 ++++ yarn.lock | 5 +++ 10 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 .changeset/few-actors-peel.md create mode 100644 .changeset/polite-ducks-divide.md diff --git a/.changeset/few-actors-peel.md b/.changeset/few-actors-peel.md new file mode 100644 index 00000000..e5c55571 --- /dev/null +++ b/.changeset/few-actors-peel.md @@ -0,0 +1,5 @@ +--- +"@hydrofoil/shaperone-wc-shoelace": patch +--- + +To not trigger search immediately when typing in auto complete editor diff --git a/.changeset/polite-ducks-divide.md b/.changeset/polite-ducks-divide.md new file mode 100644 index 00000000..a19163f3 --- /dev/null +++ b/.changeset/polite-ducks-divide.md @@ -0,0 +1,5 @@ +--- +"@hydrofoil/shaperone-wc-shoelace": patch +--- + +When loading, chage the icon to spinning arrows diff --git a/packages/wc-shoelace/README.md b/packages/wc-shoelace/README.md index f41f57cf..277b0c5b 100644 --- a/packages/wc-shoelace/README.md +++ b/packages/wc-shoelace/README.md @@ -2,13 +2,15 @@ ## Properties -| Property | Attribute | Type | Default | -|--------------|--------------|--------------------------------------------------|---------| -| `empty` | `empty` | `boolean` | true | -| `hoist` | `hoist` | `boolean` | true | -| `inputValue` | `inputValue` | `string` | "" | -| `readonly` | `readonly` | `boolean` | false | -| `selected` | `selected` | `GraphPointer> \| undefined` | | +| Property | Attribute | Type | Default | +|-------------------|--------------------|--------------------------------------------------|---------| +| `debounceTimeout` | `debounce-timeout` | `number` | 350 | +| `empty` | `empty` | `boolean` | true | +| `hoist` | `hoist` | `boolean` | true | +| `inputValue` | `inputValue` | `string` | "" | +| `loading` | `loading` | `boolean \| undefined` | | +| `readonly` | `readonly` | `boolean` | false | +| `selected` | `selected` | `GraphPointer> \| undefined` | | ## Methods diff --git a/packages/wc-shoelace/components/autocomplete.ts b/packages/wc-shoelace/components/autocomplete.ts index 01931b07..0341a5cd 100644 --- a/packages/wc-shoelace/components/autocomplete.ts +++ b/packages/wc-shoelace/components/autocomplete.ts @@ -37,7 +37,7 @@ export const autocomplete: Lazy & Options = { const { value, property } = params const pointers = value.componentState.instances || [] const freetextQuery = value.componentState.freetextQuery || '' - const { selected } = value.componentState + const { selected, loading } = value.componentState const search = (e: CustomEvent) => { params.updateComponentState({ @@ -71,6 +71,7 @@ export const autocomplete: Lazy & Options = { @itemSelected=${itemSelected} .readonly="${property.shape.readOnly || false}" .hoist="${settings.hoist}" + ?loading="${loading || false}" > ${repeat(pointers, renderItem)} ` diff --git a/packages/wc-shoelace/custom-elements.json b/packages/wc-shoelace/custom-elements.json index b70ad68e..6b3b56f8 100644 --- a/packages/wc-shoelace/custom-elements.json +++ b/packages/wc-shoelace/custom-elements.json @@ -28,6 +28,15 @@ "name": "readonly", "type": "boolean", "default": "false" + }, + { + "name": "debounce-timeout", + "type": "number", + "default": "350" + }, + { + "name": "loading", + "type": "boolean | undefined" } ], "properties": [ @@ -59,6 +68,17 @@ "attribute": "readonly", "type": "boolean", "default": "false" + }, + { + "name": "debounceTimeout", + "attribute": "debounce-timeout", + "type": "number", + "default": "350" + }, + { + "name": "loading", + "attribute": "loading", + "type": "boolean | undefined" } ], "events": [ diff --git a/packages/wc-shoelace/elements/sh-sl-autocomplete.ts b/packages/wc-shoelace/elements/sh-sl-autocomplete.ts index a78293d3..bc894de8 100644 --- a/packages/wc-shoelace/elements/sh-sl-autocomplete.ts +++ b/packages/wc-shoelace/elements/sh-sl-autocomplete.ts @@ -2,6 +2,7 @@ import { css, html, LitElement } from 'lit' import { customElement, property, query } from 'lit/decorators.js' import type { GraphPointer } from 'clownface' import { SlInput } from '@shoelace-style/shoelace' +import debounce from 'p-debounce' import { stop } from '../lib/handlers.js' import '@shoelace-style/shoelace/dist/components/input/input.js' import '@shoelace-style/shoelace/dist/components/icon/icon.js' @@ -16,33 +17,60 @@ export class ShSlAutocomplete extends LitElement { [hidden] { display: none; } + + :host([loading]) sl-input sl-icon { + animation-name: spin; + animation-duration: 500ms; + animation-iteration-count: infinite; + animation-timing-function: linear; + } + + @keyframes spin { + from { + transform:rotate(0deg); + } + to { + transform:rotate(360deg); + } + } + + sl-input sl-icon[slot=suffix] { + padding-right: 0; + margin-right: var(--sl-input-spacing-medium); + } ` } @property({ type: Object }) - selected?: GraphPointer + public selected?: GraphPointer @property({ type: String }) - inputValue = '' + public inputValue = '' @property({ type: Boolean }) - empty = true + public empty = true @property({ type: Boolean }) - hoist = true + public hoist = true @property({ type: Boolean }) public readonly = false + @property({ type: Number, attribute: 'debounce-timeout' }) + public debounceTimeout = 350 + + @property({ type: Boolean, reflect: true }) + public loading?: boolean + @query('sl-input') - _input!: SlInput + private _input!: SlInput render() { return html` - + @sl-input="${debounce(this.dispatchSearch, this.debounceTimeout)}"> + { // then expect(result.readonly).to.be.true }) + + it('sets loading attribute', async () => { + // given + const graph = cf({ dataset: $rdf.dataset() }) + const { params, actions } = editorTestParams({ + object: graph.literal(''), + componentState: { + loading: true, + }, + }) + + // when + const result = await fixture(component.render(params, actions)) + + // then + expect(result).to.have.attr('loading') + }) }) diff --git a/packages/wc-shoelace/test/elements/sh-sl-autocomplete.test.ts b/packages/wc-shoelace/test/elements/sh-sl-autocomplete.test.ts index 3f889fd0..2e342d97 100644 --- a/packages/wc-shoelace/test/elements/sh-sl-autocomplete.test.ts +++ b/packages/wc-shoelace/test/elements/sh-sl-autocomplete.test.ts @@ -26,4 +26,12 @@ describe('wc-shoelace/elements/sh-sl-autocomplete', () => { // expect expect(el.renderRoot.querySelector('sl-dropdown')?.disabled).to.be.true }) + + it('spins the icon when [loading]', async () => { + // when + const el = await fixture(html``) + + // expect + expect(el.renderRoot.querySelector('sl-input sl-icon')).to.have.style('animation-name', 'spin') + }) }) diff --git a/yarn.lock b/yarn.lock index 0d0d4007..2354c627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10493,6 +10493,11 @@ p-cancelable@^1.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== +p-debounce@^4: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-debounce/-/p-debounce-4.0.0.tgz#348e3f44489baa9435cc7d807f17b3bb2fb16b24" + integrity sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A== + p-event@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5"