solid-suggest 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.cjs +26 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +27 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# solid-suggest
|
|
2
2
|
|
|
3
|
+
[](https://npmjs.org/package/solid-suggest)
|
|
4
|
+
|
|
3
5
|
solid-suggest is a UI component for SolidJS developers that renders a text input with dropdown suggestions. It can be used in scenarios such as search suggestions or results triggered by text input.
|
|
4
6
|
|
|
5
7
|
It's a *super* simple library without many batteries included. See following sections for what it can and can't do for you.
|
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,9 @@ var _tmpl$ = /*#__PURE__*/web.template(`<div class=s-sug-container role=combobox
|
|
|
7
7
|
_tmpl$2 = /*#__PURE__*/web.template(`<ul class=s-sug-suggestions role=listbox>`),
|
|
8
8
|
_tmpl$3 = /*#__PURE__*/web.template(`<li class=s-sug-suggestion role=option>`);
|
|
9
9
|
function Suggest(props) {
|
|
10
|
+
// Suggestions to be rendered
|
|
11
|
+
const [suggestions, setSuggestions] = solidJs.createSignal([]);
|
|
12
|
+
const numSuggestions = solidJs.createMemo(() => suggestions().length);
|
|
10
13
|
// Basic signals for component state
|
|
11
14
|
const [query, setQuery] = solidJs.createSignal('');
|
|
12
15
|
const [staged, setStaged] = solidJs.createSignal(null);
|
|
@@ -14,8 +17,15 @@ function Suggest(props) {
|
|
|
14
17
|
const [debouncedQuery, setDebouncedQuery] = solidJs.createSignal('');
|
|
15
18
|
// Just a variable to store debounce timeout, if applicable
|
|
16
19
|
let debounceTimeout = null;
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
// Effect to update suggestions when debouncedQuery changes
|
|
21
|
+
solidJs.createEffect(() => {
|
|
22
|
+
const result = props.onQuery(debouncedQuery());
|
|
23
|
+
if (result instanceof Promise) {
|
|
24
|
+
result.then(setSuggestions);
|
|
25
|
+
} else {
|
|
26
|
+
setSuggestions(result);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
19
29
|
function handleInput(e) {
|
|
20
30
|
const value = e.currentTarget.value;
|
|
21
31
|
setQuery(value);
|
|
@@ -99,10 +109,10 @@ function Suggest(props) {
|
|
|
99
109
|
web.addEventListener(_el$4, "mouseenter", () => stageSuggestion(i));
|
|
100
110
|
web.insert(_el$4, () => props.renderSuggestion(s));
|
|
101
111
|
web.effect(_p$ => {
|
|
102
|
-
var _v$ = staged() === i,
|
|
103
|
-
_v$
|
|
104
|
-
_v$ !== _p$.e && web.setAttribute(_el$4, "data-staged", _p$.e = _v$);
|
|
105
|
-
_v$
|
|
112
|
+
var _v$3 = staged() === i,
|
|
113
|
+
_v$4 = staged() === i ? 'true' : 'false';
|
|
114
|
+
_v$3 !== _p$.e && web.setAttribute(_el$4, "data-staged", _p$.e = _v$3);
|
|
115
|
+
_v$4 !== _p$.t && web.setAttribute(_el$4, "aria-selected", _p$.t = _v$4);
|
|
106
116
|
return _p$;
|
|
107
117
|
}, {
|
|
108
118
|
e: undefined,
|
|
@@ -113,7 +123,16 @@ function Suggest(props) {
|
|
|
113
123
|
return _el$3;
|
|
114
124
|
})();
|
|
115
125
|
})(), null);
|
|
116
|
-
web.effect(
|
|
126
|
+
web.effect(_p$ => {
|
|
127
|
+
var _v$ = numSuggestions() > 0,
|
|
128
|
+
_v$2 = props.placeholder ?? '';
|
|
129
|
+
_v$ !== _p$.e && web.setAttribute(_el$, "aria-expanded", _p$.e = _v$);
|
|
130
|
+
_v$2 !== _p$.t && web.setAttribute(_el$2, "placeholder", _p$.t = _v$2);
|
|
131
|
+
return _p$;
|
|
132
|
+
}, {
|
|
133
|
+
e: undefined,
|
|
134
|
+
t: undefined
|
|
135
|
+
});
|
|
117
136
|
web.effect(() => _el$2.value = query());
|
|
118
137
|
return _el$;
|
|
119
138
|
})();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/index.tsx"],"sourcesContent":["import { createMemo, createSignal } from 'solid-js'\n\nexport interface SuggestProps<T
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.tsx"],"sourcesContent":["import { createMemo, createSignal, createEffect, JSX } from 'solid-js'\n\nexport interface SuggestProps<T> {\n onQuery: (query: string) => T[] | Promise<T[]>, // Can return array or Promise\n onSelect: (suggestion: T) => void,\n renderSuggestion: (suggestion: T) => HTMLElement | JSX.Element,\n placeholder?: string,\n reverseKeyInput?: boolean,\n debounceMs?: number, // Debounce period in milliseconds\n}\n\nexport default function Suggest<T = string>(props: SuggestProps<T>) {\n // Suggestions to be rendered\n const [suggestions, setSuggestions] = createSignal<T[]>([]);\n const numSuggestions = createMemo(() => suggestions().length);\n\n // Basic signals for component state\n const [query, setQuery] = createSignal('');\n const [staged, setStaged] = createSignal<number | null>(null);\n // Internal signal for user input, separate from query to handle optional debounce\n const [debouncedQuery, setDebouncedQuery] = createSignal('');\n\n // Just a variable to store debounce timeout, if applicable\n let debounceTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Effect to update suggestions when debouncedQuery changes\n createEffect(() => {\n const result = props.onQuery(debouncedQuery());\n if (result instanceof Promise) {\n result.then(setSuggestions);\n } else {\n setSuggestions(result);\n }\n });\n\n function handleInput(e: Event) {\n const value = (e.currentTarget as HTMLInputElement).value;\n setQuery(value);\n if (typeof props.debounceMs === 'number' && props.debounceMs > 0) {\n if (debounceTimeout) clearTimeout(debounceTimeout);\n debounceTimeout = setTimeout(() => {\n setDebouncedQuery(value);\n }, props.debounceMs);\n } else {\n setDebouncedQuery(value);\n }\n }\n\n function stageSuggestion(index: number) {\n setStaged(index);\n }\n\n function stageNextSuggestion() {\n setStaged(s => {\n if (suggestions().length === 0) return null;\n const current = s ?? -1;\n return (current + 1) % numSuggestions();\n });\n };\n\n function stagePrevSuggestion() {\n setStaged(s => {\n if (numSuggestions() === 0) return null;\n const current = s ?? 0;\n return (current - 1 + numSuggestions()) % numSuggestions();\n });\n };\n\n function selectStagedSuggestion() {\n const index = staged()\n if (index !== null) {\n props.onSelect(suggestions()[index]);\n reset();\n }\n }\n\n function reset() {\n setQuery('');\n setDebouncedQuery('');\n setStaged(null);\n if (debounceTimeout) clearTimeout(debounceTimeout);\n }\n\n // Handles special input for suggestion behavior\n function handleKeyDown(e: KeyboardEvent) {\n const keyInputReversed = props.reverseKeyInput ?? false;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (keyInputReversed) {\n stagePrevSuggestion();\n } else {\n stageNextSuggestion();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (keyInputReversed) {\n stageNextSuggestion();\n } else {\n stagePrevSuggestion();\n }\n } else if (e.key === 'Enter') {\n e.preventDefault();\n selectStagedSuggestion();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n reset();\n }\n // else -> propagates up to allow input\n }\n\n return <div\n class='s-sug-container'\n role='combobox'\n aria-expanded={numSuggestions() > 0}\n aria-haspopup='listbox'\n >\n <input\n type='search'\n class='s-sug-search'\n value={query()}\n placeholder={props.placeholder ?? ''}\n on:input={handleInput}\n on:keydown={handleKeyDown}\n aria-autocomplete='list'\n />\n {numSuggestions() > 0 &&\n <ul class='s-sug-suggestions' role='listbox'>\n {suggestions().map((s, i) => (\n <li\n class='s-sug-suggestion'\n data-staged={staged() === i}\n role='option'\n on:mouseenter={() => stageSuggestion(i)}\n on:click={selectStagedSuggestion}\n aria-selected={staged() === i ? 'true' : 'false'}\n >\n {props.renderSuggestion(s)}\n </li>)\n )}\n </ul>\n }\n </div>\n}\n"],"names":["Suggest","props","suggestions","setSuggestions","createSignal","numSuggestions","createMemo","length","query","setQuery","staged","setStaged","debouncedQuery","setDebouncedQuery","debounceTimeout","createEffect","result","onQuery","Promise","then","handleInput","e","value","currentTarget","debounceMs","clearTimeout","setTimeout","stageSuggestion","index","stageNextSuggestion","s","current","stagePrevSuggestion","selectStagedSuggestion","onSelect","reset","handleKeyDown","keyInputReversed","reverseKeyInput","key","preventDefault","_el$","_tmpl$","_el$2","firstChild","_$addEventListener","_$insert","_c$","_$memo","_el$3","_tmpl$2","map","i","_el$4","_tmpl$3","renderSuggestion","_$effect","_p$","_v$3","_v$4","_$setAttribute","t","undefined","_v$","_v$2","placeholder"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
export interface SuggestProps<T> {
|
|
3
|
+
onQuery: (query: string) => T[] | Promise<T[]>;
|
|
3
4
|
onSelect: (suggestion: T) => void;
|
|
4
|
-
renderSuggestion: (suggestion: T) => HTMLElement;
|
|
5
|
+
renderSuggestion: (suggestion: T) => HTMLElement | JSX.Element;
|
|
6
|
+
placeholder?: string;
|
|
5
7
|
reverseKeyInput?: boolean;
|
|
6
8
|
debounceMs?: number;
|
|
7
9
|
}
|
|
8
|
-
export default function Suggest(props: SuggestProps):
|
|
10
|
+
export default function Suggest<T = string>(props: SuggestProps<T>): JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { template, addEventListener, insert, memo, effect, setAttribute } from 'solid-js/web';
|
|
2
|
-
import { createSignal, createMemo } from 'solid-js';
|
|
2
|
+
import { createSignal, createMemo, createEffect } from 'solid-js';
|
|
3
3
|
|
|
4
4
|
var _tmpl$ = /*#__PURE__*/template(`<div class=s-sug-container role=combobox aria-haspopup=listbox><input type=search class=s-sug-search aria-autocomplete=list>`),
|
|
5
5
|
_tmpl$2 = /*#__PURE__*/template(`<ul class=s-sug-suggestions role=listbox>`),
|
|
6
6
|
_tmpl$3 = /*#__PURE__*/template(`<li class=s-sug-suggestion role=option>`);
|
|
7
7
|
function Suggest(props) {
|
|
8
|
+
// Suggestions to be rendered
|
|
9
|
+
const [suggestions, setSuggestions] = createSignal([]);
|
|
10
|
+
const numSuggestions = createMemo(() => suggestions().length);
|
|
8
11
|
// Basic signals for component state
|
|
9
12
|
const [query, setQuery] = createSignal('');
|
|
10
13
|
const [staged, setStaged] = createSignal(null);
|
|
@@ -12,8 +15,15 @@ function Suggest(props) {
|
|
|
12
15
|
const [debouncedQuery, setDebouncedQuery] = createSignal('');
|
|
13
16
|
// Just a variable to store debounce timeout, if applicable
|
|
14
17
|
let debounceTimeout = null;
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
// Effect to update suggestions when debouncedQuery changes
|
|
19
|
+
createEffect(() => {
|
|
20
|
+
const result = props.onQuery(debouncedQuery());
|
|
21
|
+
if (result instanceof Promise) {
|
|
22
|
+
result.then(setSuggestions);
|
|
23
|
+
} else {
|
|
24
|
+
setSuggestions(result);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
17
27
|
function handleInput(e) {
|
|
18
28
|
const value = e.currentTarget.value;
|
|
19
29
|
setQuery(value);
|
|
@@ -97,10 +107,10 @@ function Suggest(props) {
|
|
|
97
107
|
addEventListener(_el$4, "mouseenter", () => stageSuggestion(i));
|
|
98
108
|
insert(_el$4, () => props.renderSuggestion(s));
|
|
99
109
|
effect(_p$ => {
|
|
100
|
-
var _v$ = staged() === i,
|
|
101
|
-
_v$
|
|
102
|
-
_v$ !== _p$.e && setAttribute(_el$4, "data-staged", _p$.e = _v$);
|
|
103
|
-
_v$
|
|
110
|
+
var _v$3 = staged() === i,
|
|
111
|
+
_v$4 = staged() === i ? 'true' : 'false';
|
|
112
|
+
_v$3 !== _p$.e && setAttribute(_el$4, "data-staged", _p$.e = _v$3);
|
|
113
|
+
_v$4 !== _p$.t && setAttribute(_el$4, "aria-selected", _p$.t = _v$4);
|
|
104
114
|
return _p$;
|
|
105
115
|
}, {
|
|
106
116
|
e: undefined,
|
|
@@ -111,7 +121,16 @@ function Suggest(props) {
|
|
|
111
121
|
return _el$3;
|
|
112
122
|
})();
|
|
113
123
|
})(), null);
|
|
114
|
-
effect(
|
|
124
|
+
effect(_p$ => {
|
|
125
|
+
var _v$ = numSuggestions() > 0,
|
|
126
|
+
_v$2 = props.placeholder ?? '';
|
|
127
|
+
_v$ !== _p$.e && setAttribute(_el$, "aria-expanded", _p$.e = _v$);
|
|
128
|
+
_v$2 !== _p$.t && setAttribute(_el$2, "placeholder", _p$.t = _v$2);
|
|
129
|
+
return _p$;
|
|
130
|
+
}, {
|
|
131
|
+
e: undefined,
|
|
132
|
+
t: undefined
|
|
133
|
+
});
|
|
115
134
|
effect(() => _el$2.value = query());
|
|
116
135
|
return _el$;
|
|
117
136
|
})();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import { createMemo, createSignal } from 'solid-js'\n\nexport interface SuggestProps<T
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import { createMemo, createSignal, createEffect, JSX } from 'solid-js'\n\nexport interface SuggestProps<T> {\n onQuery: (query: string) => T[] | Promise<T[]>, // Can return array or Promise\n onSelect: (suggestion: T) => void,\n renderSuggestion: (suggestion: T) => HTMLElement | JSX.Element,\n placeholder?: string,\n reverseKeyInput?: boolean,\n debounceMs?: number, // Debounce period in milliseconds\n}\n\nexport default function Suggest<T = string>(props: SuggestProps<T>) {\n // Suggestions to be rendered\n const [suggestions, setSuggestions] = createSignal<T[]>([]);\n const numSuggestions = createMemo(() => suggestions().length);\n\n // Basic signals for component state\n const [query, setQuery] = createSignal('');\n const [staged, setStaged] = createSignal<number | null>(null);\n // Internal signal for user input, separate from query to handle optional debounce\n const [debouncedQuery, setDebouncedQuery] = createSignal('');\n\n // Just a variable to store debounce timeout, if applicable\n let debounceTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Effect to update suggestions when debouncedQuery changes\n createEffect(() => {\n const result = props.onQuery(debouncedQuery());\n if (result instanceof Promise) {\n result.then(setSuggestions);\n } else {\n setSuggestions(result);\n }\n });\n\n function handleInput(e: Event) {\n const value = (e.currentTarget as HTMLInputElement).value;\n setQuery(value);\n if (typeof props.debounceMs === 'number' && props.debounceMs > 0) {\n if (debounceTimeout) clearTimeout(debounceTimeout);\n debounceTimeout = setTimeout(() => {\n setDebouncedQuery(value);\n }, props.debounceMs);\n } else {\n setDebouncedQuery(value);\n }\n }\n\n function stageSuggestion(index: number) {\n setStaged(index);\n }\n\n function stageNextSuggestion() {\n setStaged(s => {\n if (suggestions().length === 0) return null;\n const current = s ?? -1;\n return (current + 1) % numSuggestions();\n });\n };\n\n function stagePrevSuggestion() {\n setStaged(s => {\n if (numSuggestions() === 0) return null;\n const current = s ?? 0;\n return (current - 1 + numSuggestions()) % numSuggestions();\n });\n };\n\n function selectStagedSuggestion() {\n const index = staged()\n if (index !== null) {\n props.onSelect(suggestions()[index]);\n reset();\n }\n }\n\n function reset() {\n setQuery('');\n setDebouncedQuery('');\n setStaged(null);\n if (debounceTimeout) clearTimeout(debounceTimeout);\n }\n\n // Handles special input for suggestion behavior\n function handleKeyDown(e: KeyboardEvent) {\n const keyInputReversed = props.reverseKeyInput ?? false;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (keyInputReversed) {\n stagePrevSuggestion();\n } else {\n stageNextSuggestion();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (keyInputReversed) {\n stageNextSuggestion();\n } else {\n stagePrevSuggestion();\n }\n } else if (e.key === 'Enter') {\n e.preventDefault();\n selectStagedSuggestion();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n reset();\n }\n // else -> propagates up to allow input\n }\n\n return <div\n class='s-sug-container'\n role='combobox'\n aria-expanded={numSuggestions() > 0}\n aria-haspopup='listbox'\n >\n <input\n type='search'\n class='s-sug-search'\n value={query()}\n placeholder={props.placeholder ?? ''}\n on:input={handleInput}\n on:keydown={handleKeyDown}\n aria-autocomplete='list'\n />\n {numSuggestions() > 0 &&\n <ul class='s-sug-suggestions' role='listbox'>\n {suggestions().map((s, i) => (\n <li\n class='s-sug-suggestion'\n data-staged={staged() === i}\n role='option'\n on:mouseenter={() => stageSuggestion(i)}\n on:click={selectStagedSuggestion}\n aria-selected={staged() === i ? 'true' : 'false'}\n >\n {props.renderSuggestion(s)}\n </li>)\n )}\n </ul>\n }\n </div>\n}\n"],"names":["Suggest","props","suggestions","setSuggestions","createSignal","numSuggestions","createMemo","length","query","setQuery","staged","setStaged","debouncedQuery","setDebouncedQuery","debounceTimeout","createEffect","result","onQuery","Promise","then","handleInput","e","value","currentTarget","debounceMs","clearTimeout","setTimeout","stageSuggestion","index","stageNextSuggestion","s","current","stagePrevSuggestion","selectStagedSuggestion","onSelect","reset","handleKeyDown","keyInputReversed","reverseKeyInput","key","preventDefault","_el$","_tmpl$","_el$2","firstChild","_$addEventListener","_$insert","_c$","_$memo","_el$3","_tmpl$2","map","i","_el$4","_tmpl$3","renderSuggestion","_$effect","_p$","_v$3","_v$4","_$setAttribute","t","undefined","_v$","_v$2","placeholder"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid-suggest",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Headless search suggestion dropdown UI library for SolidJS",
|
|
5
5
|
"homepage": "https://antrikshy.com/solid-suggest",
|
|
6
6
|
"repository": {
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
"author": "Antriksh Yadav",
|
|
22
22
|
"license": "ISC",
|
|
23
23
|
"type": "module",
|
|
24
|
-
"main": "./dist/
|
|
25
|
-
"module": "./dist/
|
|
26
|
-
"types": "./dist/
|
|
24
|
+
"main": "./dist/index.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
|
-
"import": "./dist/
|
|
30
|
-
"require": "./dist/
|
|
31
|
-
"types": "./dist/
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"require": "./dist/index.cjs",
|
|
31
|
+
"types": "./dist/index.d.ts"
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"files": [
|