-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #230 from hypermedia-app/multi-select
feat: autocomplete and multi-select
- Loading branch information
Showing
39 changed files
with
561 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@hydrofoil/shaperone-core": patch | ||
--- | ||
|
||
Added a module which exports `sh1` namespace for extensions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@hydrofoil/shaperone-core": patch | ||
"@hydrofoil/shaperone-wc": patch | ||
--- | ||
|
||
Export default metadata for multi instances select editor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@hydrofoil/shaperone-hydra": patch | ||
--- | ||
|
||
Apply search decorator to multi instance editor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@hydrofoil/shaperone-wc-shoelace": patch | ||
--- | ||
|
||
Added `dash:AutocompleteEditor` and `sh1:InstanceMultiSelectEditor` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
types/ | ||
node_modules/ | ||
dist/ | ||
*.snap.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" /> | ||
<meta name="Description" content="Put your description here."> | ||
<link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/dist/themes/light.css" /> | ||
<script>try{new EventTarget}catch(e){document.write('<script src="https://unpkg.com/@ungap/[email protected]/min.js"><\x2fscript>')}</script> | ||
|
||
<style> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import $rdf from '@rdf-esm/data-model' | ||
import { dash, rdf } from '@tpluscode/rdf-ns-builders' | ||
import sh1 from './ns.js' | ||
|
||
export default [ | ||
$rdf.quad(sh1.InstancesMultiSelectEditor, rdf.type, dash.MultiEditor), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import namespace from '@rdf-esm/namespace' | ||
|
||
export default namespace('https://hypermedia.app/shaperone#') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import sh1 from '@hydrofoil/shaperone-core/ns.js' | ||
import { ComponentDecorator } from '@hydrofoil/shaperone-core/models/components' | ||
import { InstancesSelectEditor } from '@hydrofoil/shaperone-core/lib/components/instancesSelect' | ||
import { decorator as searchDecorator } from './searchDecorator.js' | ||
|
||
export function decorator(...args: Parameters<typeof searchDecorator>): ComponentDecorator<InstancesSelectEditor> { | ||
return { | ||
...searchDecorator(...args), | ||
applicableTo(component) { | ||
return component.editor.equals(sh1.InstancesMultiSelectEditor) | ||
}, | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
packages/hydra/test/lib/components/multiInstanceSelector.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { expect } from '@open-wc/testing' | ||
import sh1 from '@hydrofoil/shaperone-core/ns.js' | ||
import { decorator } from '../../../lib/components/multiInstanceSelector' | ||
|
||
describe('hydra/lib/components/multiInstancesSelector', () => { | ||
describe('decorator', () => { | ||
it('applies to Multi Instances Selector', () => { | ||
// given | ||
const component = { | ||
editor: sh1.InstancesMultiSelectEditor, | ||
} | ||
|
||
// then | ||
expect(decorator().applicableTo(component)).to.be.true | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { | ||
instancesSelect, | ||
} from '@hydrofoil/shaperone-core/components.js' | ||
import * as select from '@hydrofoil/shaperone-core/lib/components/base/instancesSelect.js' | ||
import sh1 from '@hydrofoil/shaperone-core/ns.js' | ||
import { html } from 'lit' | ||
import { repeat } from 'lit/directives/repeat.js' | ||
import { Lazy, MultiEditorComponent } from '@hydrofoil/shaperone-wc' | ||
import { difference } from '@ngard/tiny-difference' | ||
import { SlSelect } from '@shoelace-style/shoelace' | ||
import type { GraphPointer } from 'clownface' | ||
import { renderItem } from './lib/components.js' | ||
import { stop } from './lib/handlers.js' | ||
import { settings } from './settings.js' | ||
|
||
export const instancesMultiSelectEditor: Lazy<MultiEditorComponent> = { | ||
...select, | ||
editor: sh1.InstancesMultiSelectEditor, | ||
init(...args: [any, any]) { | ||
return instancesSelect.init?.call(this, ...args) || true | ||
}, | ||
async lazyRender() { | ||
return ({ property, componentState }, { update }) => { | ||
const values = property.objects.map(o => o.object?.value).filter(isDef) | ||
const pointers: GraphPointer[] = componentState.instances || [] | ||
|
||
function onChange(e: CustomEvent) { | ||
const target = e.target as SlSelect | ||
|
||
if (Array.isArray(target.value) && difference(target.value, values).length !== 0) { | ||
const selected = pointers | ||
.filter(({ value }) => target.value.includes(value)) | ||
.map(({ term }) => term) | ||
|
||
update(selected) | ||
} | ||
} | ||
|
||
function selectAll() { | ||
const all = pointers.map(({ term }) => term) | ||
update(all) | ||
} | ||
|
||
return html` | ||
<sl-select ?hoist="${settings.hoist}" multiple clearable .value=${values} @sl-hide=${stop} @sl-change=${onChange}> | ||
${repeat(pointers || [], renderItem)} | ||
</sl-select> | ||
<sl-button @click=${selectAll}> | ||
Select all | ||
</sl-button>` | ||
} | ||
}, | ||
} | ||
|
||
function isDef<T>(x: T | undefined): x is T { | ||
return !!x | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { Lazy } from '@hydrofoil/shaperone-core' | ||
import * as Core from '@hydrofoil/shaperone-core/components.js' | ||
import { dash, rdfs } from '@tpluscode/rdf-ns-builders' | ||
import { html } from 'lit' | ||
import { repeat } from 'lit/directives/repeat.js' | ||
import { localizedLabel } from '@rdfjs-elements/lit-helpers/localizedLabel.js' | ||
import isGraphPointer from 'is-graph-pointer' | ||
import { NamedNode } from 'rdf-js' | ||
import { SingleEditorRenderParams } from '@hydrofoil/shaperone-core/models/components' | ||
import type { GraphPointer } from 'clownface' | ||
import { renderItem } from '../lib/components.js' | ||
import { settings } from '../settings.js' | ||
|
||
interface Options { | ||
labelProperties: NamedNode | NamedNode[] | ||
} | ||
|
||
export interface AutoCompleteEditor extends Core.AutoCompleteEditor { | ||
initLabel(arg: SingleEditorRenderParams): void | ||
} | ||
|
||
declare module '@hydrofoil/shaperone-core/components' { | ||
/* eslint-disable @typescript-eslint/no-empty-interface */ | ||
interface AutoComplete { | ||
selected?: GraphPointer | ||
} | ||
} | ||
|
||
export const autocomplete: Lazy<AutoCompleteEditor> & Options = { | ||
...Core.instancesSelect, | ||
labelProperties: rdfs.label, | ||
editor: dash.AutoCompleteEditor, | ||
async lazyRender() { | ||
await import('../elements/sh-sl-autocomplete.js') | ||
|
||
return (params, { update }) => { | ||
const { value } = params | ||
const pointers = value.componentState.instances || [] | ||
const freetextQuery = value.componentState.freetextQuery || '' | ||
const { selected } = value.componentState | ||
|
||
const search = (e: CustomEvent) => { | ||
params.updateComponentState({ | ||
freetextQuery: e.detail.value, | ||
}) | ||
} | ||
|
||
const itemSelected = (e: CustomEvent) => { | ||
const selected = pointers.find(({ value }) => value === e.detail.value) | ||
|
||
params.updateComponentState({ | ||
freetextQuery: '', | ||
selected, | ||
}) | ||
if (selected) { | ||
update(selected.term) | ||
} | ||
} | ||
|
||
let nodeValue = value.object?.value | ||
if (isGraphPointer.isNamedNode(value.object)) { | ||
const nodeUrl = new URL(value.object.value) | ||
nodeValue = nodeUrl.hash || nodeUrl.pathname | ||
} | ||
const fallback = nodeValue || freetextQuery | ||
|
||
return html` | ||
<sh-sl-autocomplete .selected=${selected} | ||
.inputValue=${localizedLabel(selected, { property: autocomplete.labelProperties, fallback })} | ||
@search=${search} | ||
@itemSelected=${itemSelected} | ||
.hoist="${settings.hoist}" | ||
> | ||
${repeat(pointers, renderItem)} | ||
</sh-sl-autocomplete>` | ||
} | ||
}, | ||
initLabel(this: AutoCompleteEditor, { property: { shape }, value, updateComponentState }) { | ||
const { | ||
object, | ||
componentState: { freetextQuery, selectionLoading }, | ||
} = value | ||
|
||
if (object && !freetextQuery && !selectionLoading) { | ||
const selectionLoading = this.loadInstance({ property: shape, value: object }) | ||
.then((resource) => { | ||
updateComponentState({ | ||
selected: resource, | ||
}) | ||
}) | ||
|
||
updateComponentState({ selectionLoading }) | ||
} | ||
}, | ||
init(...args) { | ||
Core.instancesSelect.init?.call(this, ...args) | ||
|
||
this.initLabel(args[0]) | ||
|
||
return true | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Lazy } from '@hydrofoil/shaperone-core' | ||
import * as Core from '@hydrofoil/shaperone-core/components.js' | ||
|
||
export const enumSelect: Lazy<Core.EnumSelectEditor> = { | ||
...Core.enumSelect, | ||
async lazyRender() { | ||
const { select } = await import('./select.js') | ||
|
||
return ({ value, componentState }, { update }) => { | ||
const pointers = componentState.instances || [] | ||
|
||
return select(value, pointers, update) | ||
} | ||
}, | ||
} |
Oops, something went wrong.