Skip to content

Commit

Permalink
feat/Autocomplete Generics (#2021)
Browse files Browse the repository at this point in the history
Co-authored-by: AdrianGonz97 <[email protected]>
  • Loading branch information
HugeLetters and AdrianGonz97 authored Sep 18, 2023
1 parent 53dc1d7 commit b92d622
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 37 deletions.
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cSpell.language": "en"
}
"cSpell.language": "en"
}
5 changes: 5 additions & 0 deletions packages/skeleton/.changeset/gold-jars-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton': minor
---

feat: Added support for generic types on values provided to Autocomplete component
Original file line number Diff line number Diff line change
@@ -1,51 +1,58 @@
<script lang="ts" context="module">
import { slide } from 'svelte/transition';
import { type Transition, type TransitionParams, prefersReducedMotionStore } from '../../index.js';
import { prefersReducedMotionStore, type Transition, type TransitionParams } from '../../index.js';
import { dynamicTransition } from '../../internal/transitions.js';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type SlideTransition = typeof slide;
type TransitionIn = Transition;
type TransitionOut = Transition;
type Value = unknown;
type Meta = unknown;
</script>

<script lang="ts" generics="TransitionIn extends Transition = SlideTransition, TransitionOut extends Transition = SlideTransition">
<script
lang="ts"
generics="Value = unknown, Meta = unknown,
TransitionIn extends Transition = SlideTransition, TransitionOut extends Transition = SlideTransition"
>
import { createEventDispatcher } from 'svelte';
// import { flip } from 'svelte/animate';
// import {slide} from 'svelte/transition';
// Types
import type { AutocompleteOption } from './types.js';
type Option = AutocompleteOption<Value, Meta>;
// Event Dispatcher
type AutocompleteEvent = {
selection: AutocompleteOption;
selection: Option;
};
const dispatch = createEventDispatcher<AutocompleteEvent>();
// Props
/**
* Bind the input value.
* @type {unknown}
* @type {Value | undefined}
*/
export let input: unknown = undefined;
export let input: Value | undefined = undefined;
/**
* Define values for the list.
* @type {AutocompleteOption[]}
*/
export let options: AutocompleteOption[] = [];
export let options: Option[] = [];
/** Limit the total number of suggestions. */
export let limit: number | undefined = undefined;
/**
* Provide allowlist values.
* @type {unknown[]}
* @type {Value[]}
*/
export let allowlist: unknown[] = [];
export let allowlist: Value[] = [];
/**
* Provide denylist values.
* @type {unknown[]}
* @type {Value[]}
*/
export let denylist: unknown[] = [];
export let denylist: Value[] = [];
/** Provide a HTML markup to display when no match is found. */
export let emptyState = 'No Results Found.';
// Props (region)
Expand Down Expand Up @@ -90,7 +97,7 @@
// Local
$: listedOptions = options;
function filterByAllowDeny(allowlist: unknown[], denylist: unknown[]) {
function filterByAllowDeny(allowlist: Value[], denylist: Value[]) {
let _options = [...options];
// Allowed Options
if (allowlist.length) {
Expand All @@ -110,7 +117,7 @@
listedOptions = _options;
}
function filterOptions(): AutocompleteOption[] {
function filterOptions(): Option[] {
// Create a local copy of options
let _options = [...listedOptions];
// Filter options
Expand All @@ -125,15 +132,15 @@
return _options;
}
function onSelection(option: AutocompleteOption) {
/** @event {AutocompleteOption} selection - Fire on option select. */
function onSelection(option: Option) {
/** @event {Option} selection - Fire on option select. */
dispatch('selection', option);
}
// State
$: filterByAllowDeny(allowlist, denylist);
$: optionsFiltered = input ? filterOptions() : listedOptions;
$: sliceLimit = limit !== undefined ? limit : optionsFiltered.length;
$: sliceLimit = limit ?? optionsFiltered.length;
// Reactive
$: classesBase = `${$$props.class ?? ''}`;
$: classesNav = `${regionNav}`;
Expand Down
10 changes: 5 additions & 5 deletions packages/skeleton/src/lib/components/Autocomplete/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Autocomplete Types

export interface AutocompleteOption {
/** provide a unique display label per option. Supports HTML. */
export interface AutocompleteOption<Value = unknown, Meta = unknown> {
/** Provide a unique display label per option. Supports HTML. */
label: string;
/** Provide a unique option value. */
value: unknown;
value: Value;
/** Provide a comma separated list of keywords. */
keywords?: any;
keywords?: string;
/** Pass arbitrary data per option. */
meta?: any;
meta?: Meta;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,45 +39,46 @@
let inputDemo = '';
let inputAllowlist = '';
const flavorOptions: AutocompleteOption[] = [
type FlavorOption = AutocompleteOption<string, { healthy: boolean }>;
const flavorOptions: FlavorOption[] = [
{ label: 'Vanilla', value: 'vanilla', keywords: 'plain, basic', meta: { healthy: false } },
{ label: 'Chocolate', value: 'chocolate', keywords: 'dark, white', meta: { healthy: false } },
{ label: 'Strawberry', value: 'strawberry', keywords: 'fruit', meta: { healthy: true } },
{ label: 'Neapolitan', value: 'neapolitan', keywords: 'mix, strawberry, chocolate, vanilla', meta: { healthy: false } },
{ label: 'Pineapple', value: 'pineapple', keywords: 'fruit', meta: { healthy: true } },
{ label: 'Peach', value: 'peach', keywords: 'fruit', meta: { healthy: true } }
];
const flavorAllowlist: string[] = ['neapolitan', 'pineapple', 'peach'];
let flavorDenylist: string[] = ['vanilla', 'chocolate'];
const flavorAllowlist = ['neapolitan', 'pineapple', 'peach'];
let flavorDenylist = ['vanilla', 'chocolate'];
// Input Chip
let inputChip = '';
let inputChipList: string[] = ['vanilla', 'chocolate'];
let inputChipList = ['vanilla', 'chocolate'];
function onDemoSelection(event: CustomEvent<AutocompleteOption>): void {
function onDemoSelection(event: CustomEvent<FlavorOption>): void {
console.log(event.detail);
inputDemo = event.detail.label;
}
function onAllowedlistSelect(event: CustomEvent<AutocompleteOption>): void {
function onAllowedlistSelect(event: CustomEvent<FlavorOption>): void {
console.log(event.detail);
inputAllowlist = event.detail.label;
}
function onDeniedlistSelect(event: CustomEvent<AutocompleteOption>): void {
function onDeniedlistSelect(event: CustomEvent<FlavorOption>): void {
console.log(event.detail);
flavorDenylist = [event.detail.value as string];
flavorDenylist = [event.detail.value];
}
function onInputChipSelect(event: CustomEvent<AutocompleteOption>): void {
function onInputChipSelect(event: CustomEvent<FlavorOption>): void {
console.log('onInputChipSelect', event.detail);
if (inputChipList.includes(event.detail.value as string) === false) {
inputChipList = [...inputChipList, event.detail.value as string];
if (inputChipList.includes(event.detail.value) === false) {
inputChipList = [...inputChipList, event.detail.value];
inputChip = '';
}
}
function onPopupDemoSelect(event: CustomEvent<AutocompleteOption>): void {
function onPopupDemoSelect(event: CustomEvent<FlavorOption>): void {
inputPopupDemo = event.detail.label;
}
</script>
Expand All @@ -101,7 +102,7 @@
<CodeBlock
language="ts"
code={`
const flavorOptions: AutocompleteOption[] = [
const flavorOptions: AutocompleteOption<string>[] = [
{ label: 'Vanilla', value: 'vanilla', keywords: 'plain, basic', meta: { healthy: false } },
{ label: 'Chocolate', value: 'chocolate', keywords: 'dark, white', meta: { healthy: false } },
{ label: 'Strawberry', value: 'strawberry', keywords: 'fruit', meta: { healthy: true } },
Expand All @@ -115,7 +116,7 @@ const flavorOptions: AutocompleteOption[] = [
<CodeBlock
language="ts"
code={`
function onFlavorSelection(event: CustomEvent<AutocompleteOption>): void {
function onFlavorSelection(event: CustomEvent<AutocompleteOption<string>>): void {
inputDemo = event.detail.label;
}
`}
Expand Down Expand Up @@ -160,7 +161,7 @@ function onFlavorSelection(event: CustomEvent<AutocompleteOption>): void {
<CodeBlock
language="ts"
code={`
const flavorOptions: AutocompleteOption[] = [
const flavorOptions: AutocompleteOption<string>[] = [
{ ..., keywords: 'mix, strawberry, chocolate, vanilla' },
{ ..., meta: { healthy: false } },
];
Expand Down

0 comments on commit b92d622

Please sign in to comment.