elastic-input 0.1.0 → 0.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 CHANGED
@@ -4,7 +4,7 @@ A syntax-aware smart autocomplete input for building structured queries. Support
4
4
 
5
5
  Built with React functional components and hooks (compatible with React 16.8+), zero runtime dependencies beyond React/ReactDOM, and fully inline-styled (no CSS imports required).
6
6
 
7
- Vibe-coded as a proof of concept with Claude Code
7
+ **[Live Demo](https://krtools.github.io/elastic-input/)**
8
8
 
9
9
  ## Features
10
10
 
@@ -19,6 +19,12 @@ Vibe-coded as a proof of concept with Claude Code
19
19
  - **Fully configurable** — colors, structural styles, fonts, and layout are all customizable via props
20
20
  - **Dark mode ready** — ships with `DARK_COLORS` and `DARK_STYLES` presets
21
21
 
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install elastic-input
26
+ ```
27
+
22
28
  ## Quick Start
23
29
 
24
30
  ```tsx
@@ -30,8 +36,8 @@ const fields: FieldConfig[] = [
30
36
  name: 'status',
31
37
  label: 'Status',
32
38
  type: 'string',
33
- suggestions: ['active', 'inactive', 'pending'],
34
39
  description: 'Account status',
40
+ placeholder: 'Search statuses...',
35
41
  },
36
42
  {
37
43
  name: 'created',
@@ -103,9 +109,9 @@ Implicit AND is supported — `status:active level:ERROR` is equivalent to `stat
103
109
  | `onValidationChange` | `(errors) => void` | — | Called when validation errors change |
104
110
  | `value` | `string` | — | Controlled input value |
105
111
  | `defaultValue` | `string` | — | Initial uncontrolled value |
106
- | `savedSearches` | `SavedSearch[] \| () => Promise<SavedSearch[]>` | — | Saved search definitions (sync or async) |
107
- | `searchHistory` | `HistoryEntry[] \| () => Promise<HistoryEntry[]>` | — | Search history entries (sync or async) |
108
- | `fetchSuggestions` | `(field, partial) => Promise<SuggestionItem[]>` | — | Async suggestion provider for field values |
112
+ | `savedSearches` | `SavedSearch[] \| (partial) => Promise<SavedSearch[]>` | — | Saved search definitions (sync array or async callback with partial) |
113
+ | `searchHistory` | `HistoryEntry[] \| (partial) => Promise<HistoryEntry[]>` | — | Search history entries (sync array or async callback with partial) |
114
+ | `fetchSuggestions` | `(field, partial) => Promise<SuggestionItem[]>` | — | Async suggestion provider for field values (called for all non-boolean fields) |
109
115
  | `colors` | `ColorConfig` | `DEFAULT_COLORS` | Syntax highlighting and UI colors |
110
116
  | `styles` | `StyleConfig` | `DEFAULT_STYLES` | Structural/layout style overrides |
111
117
  | `placeholder` | `string` | `"Search..."` | Placeholder text |
@@ -124,12 +130,13 @@ Implicit AND is supported — `status:active level:ERROR` is equivalent to `stat
124
130
 
125
131
  ```typescript
126
132
  interface FieldConfig {
127
- name: string; // Field identifier used in queries
128
- label?: string; // Display label (used in autocomplete)
129
- type: FieldType; // 'string' | 'number' | 'date' | 'boolean' | 'ip'
130
- suggestions?: string[];// Autocomplete values (any field type can have suggestions)
131
- operators?: string[]; // Allowed operators (future use)
132
- description?: string; // Shown in autocomplete dropdown
133
+ name: string; // Field identifier used in queries
134
+ label?: string; // Display label (used in autocomplete)
135
+ type: FieldType; // 'string' | 'number' | 'date' | 'boolean' | 'ip'
136
+ aliases?: string[]; // Alternative names that resolve to this field
137
+ operators?: string[]; // Allowed operators (future use)
138
+ description?: string; // Shown in autocomplete dropdown
139
+ placeholder?: string | false; // Hint shown while typing a value (false to suppress)
133
140
  }
134
141
  ```
135
142
 
@@ -233,12 +240,15 @@ const savedSearches = [
233
240
 
234
241
  Type `#` in the input to see saved search suggestions. Selecting one replaces the `#token` with the saved query text.
235
242
 
236
- Supports async loading:
243
+ Supports async loading with per-keystroke filtering:
237
244
 
238
245
  ```tsx
239
246
  <ElasticInput
240
247
  fields={fields}
241
- savedSearches={() => fetch('/api/saved-searches').then(r => r.json())}
248
+ savedSearches={async (partial) => {
249
+ const res = await fetch(`/api/saved-searches?q=${partial}`);
250
+ return res.json();
251
+ }}
242
252
  />
243
253
  ```
244
254
 
@@ -260,9 +270,21 @@ const history = [
260
270
 
261
271
  Type `!` to see history suggestions. Selecting one inserts the query (wrapped in parentheses if it contains boolean operators).
262
272
 
273
+ Supports async loading with per-keystroke filtering:
274
+
275
+ ```tsx
276
+ <ElasticInput
277
+ fields={fields}
278
+ searchHistory={async (partial) => {
279
+ const res = await fetch(`/api/history?q=${partial}`);
280
+ return res.json();
281
+ }}
282
+ />
283
+ ```
284
+
263
285
  ## Async Suggestions
264
286
 
265
- Provide dynamic suggestions for field values:
287
+ Provide dynamic suggestions for field values. Called for all non-boolean field value contexts when provided:
266
288
 
267
289
  ```tsx
268
290
  <ElasticInput
@@ -395,7 +417,7 @@ const ast = parser.parse();
395
417
 
396
418
  // Validate
397
419
  const fields: FieldConfig[] = [
398
- { name: 'status', type: 'string', suggestions: ['active', 'inactive'] },
420
+ { name: 'status', type: 'string' },
399
421
  { name: 'price', type: 'number' },
400
422
  ];
401
423
  const validator = new Validator(fields);
@@ -12,6 +12,10 @@ export interface AutocompleteResult {
12
12
  export interface AutocompleteOptions {
13
13
  showSavedSearchHint?: boolean;
14
14
  showHistoryHint?: boolean;
15
+ /** Set to true when a savedSearches callback is provided (for hints even when no sync data). */
16
+ hasSavedSearchProvider?: boolean;
17
+ /** Set to true when a searchHistory callback is provided (for hints even when no sync data). */
18
+ hasHistoryProvider?: boolean;
15
19
  }
16
20
  export declare class AutocompleteEngine {
17
21
  private fields;
@@ -33,4 +37,10 @@ export declare class AutocompleteEngine {
33
37
  private getSpecialHints;
34
38
  private getSavedSearchSuggestions;
35
39
  private getHistorySuggestions;
40
+ /**
41
+ * Wraps a history query in parens if the top-level AST node is a BooleanExpr
42
+ * (explicit AND/OR or implicit adjacency). Already-grouped expressions
43
+ * like -(a AND b) or (a OR b)^2 don't need extra wrapping.
44
+ */
45
+ static wrapHistoryQuery(query: string): string;
36
46
  }