@itrocks/autocomplete 0.0.9 → 0.0.10

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.
Files changed (2) hide show
  1. package/README.md +231 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -7,3 +7,234 @@
7
7
  # autocomplete
8
8
 
9
9
  Editable combobox component featuring smart autocomplete from a list of id-caption pairs for it.rocks.
10
+
11
+ *This documentation was written by an artificial intelligence and may contain errors or approximations.
12
+ It has not yet been fully reviewed by a human. If anything seems unclear or incomplete,
13
+ please feel free to contact the author of this package.*
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm i @itrocks/autocomplete
19
+ ```
20
+
21
+ This package ships as a small, framework-agnostic ES module plus a CSS file.
22
+ You can use it directly in a browser bundle or through any bundler that
23
+ supports standard `import` statements.
24
+
25
+ At runtime you must also load the stylesheet `autocomplete.css` so that the
26
+ suggestions dropdown is correctly positioned and styled.
27
+
28
+ ## Usage
29
+
30
+ `@itrocks/autocomplete` provides a smart autocomplete behavior for a plain
31
+ `<input>` element. It turns the input into an editable combobox that:
32
+
33
+ - fetches suggestions from a remote HTTP endpoint,
34
+ - displays them in a dropdown list,
35
+ - lets the user navigate with the keyboard,
36
+ - completes the text directly in the input,
37
+ - optionally keeps a hidden field in sync with the selected item id.
38
+
39
+ The core API is the `AutoComplete` class, which you instantiate on a
40
+ `HTMLInputElement` that will hold the caption shown to the user.
41
+
42
+ ### Minimal example
43
+
44
+ ```html
45
+ <!-- HTML -->
46
+ <input
47
+ id="country"
48
+ type="text"
49
+ data-fetch="/api/countries"
50
+ class="empty"
51
+ >
52
+ <input id="country-id" type="hidden">
53
+
54
+ <script type="module">
55
+ import { AutoComplete } from '/node_modules/@itrocks/autocomplete/autocomplete.js'
56
+
57
+ const captionInput = document.getElementById('country')
58
+
59
+ // Attach autocomplete behavior to the visible input
60
+ new AutoComplete(captionInput)
61
+ </script>
62
+ ```
63
+
64
+ On each change of the visible input, the component will:
65
+
66
+ 1. Call `GET /api/countries?startsWith=<current value>` with
67
+ `Accept: application/json`.
68
+ 2. Expect a JSON body shaped as an array of `[id, caption]` pairs, for
69
+ example:
70
+
71
+ ```json
72
+ [["33", "France"], ["49", "Germany"], ["39", "Italy"]]
73
+ ```
74
+
75
+ 3. Display the matching captions in a dropdown list.
76
+ 4. Let the user navigate the list with arrow keys and validate with `Enter`.
77
+ 5. Keep the hidden `#country-id` input in sync with the selected item id.
78
+
79
+ ### Complete example with common behaviors
80
+
81
+ ```html
82
+ <label for="customer">Customer</label>
83
+ <input
84
+ id="customer"
85
+ name="customer-caption"
86
+ type="text"
87
+ data-fetch="/customers/summary"
88
+ class="empty"
89
+ autocomplete="off"
90
+ >
91
+ <!-- Hidden field containing the selected customer id -->
92
+ <input id="customer-id" name="customer-id" type="hidden">
93
+
94
+ <script type="module">
95
+ import { AutoComplete } from '/node_modules/@itrocks/autocomplete/autocomplete.js'
96
+
97
+ const customerCaption = document.getElementById('customer')
98
+
99
+ // Initialize the component once the DOM is ready
100
+ new AutoComplete(customerCaption)
101
+
102
+ // Optionally, react to value changes using the standard 'input' event
103
+ customerCaption.addEventListener('input', () => {
104
+ const idInput = document.getElementById('customer-id')
105
+ console.log('Customer caption:', customerCaption.value)
106
+ console.log('Customer id:', idInput.value)
107
+ })
108
+ </script>
109
+ ```
110
+
111
+ In this example:
112
+
113
+ - The backend route `/customers/summary` must return JSON like
114
+ `[["1", "Acme"], ["2", "Beta Corp"], ...]`.
115
+ - Typing in the `Customer` input shows suggestions and performs
116
+ in-place completion.
117
+ - The hidden `customer-id` input is automatically set to the id of the
118
+ currently selected suggestion when the caption matches exactly.
119
+ - When the user clears the caption or types a caption that does not match
120
+ any suggestion, the hidden id is cleared.
121
+
122
+ ## API
123
+
124
+ `@itrocks/autocomplete` exposes a single public class:
125
+
126
+ ### `class AutoComplete`
127
+
128
+ Editable combobox behavior attached to a text input element. It keeps a
129
+ dropdown list of suggestions in sync with the input value and, when
130
+ available, with a nearby hidden input used to store the selected item id.
131
+
132
+ #### Constructor
133
+
134
+ ```ts
135
+ new AutoComplete(input: HTMLInputElement)
136
+ ```
137
+
138
+ Parameters:
139
+
140
+ - `input: HTMLInputElement` – The **visible** input used to type and display
141
+ the caption. It becomes the component's main entry field.
142
+
143
+ Behavior and expectations:
144
+
145
+ - The input is considered the caption field. The user always interacts with
146
+ this field; it remains editable at all times.
147
+ - The constructor:
148
+ - stores the input as `autoComplete.input`,
149
+ - looks for a **hidden** sibling input, which may be used as the
150
+ "id" field (see below),
151
+ - registers listeners for `blur`, `keydown` and `input` events.
152
+
153
+ #### Hidden id input detection
154
+
155
+ If you provide a hidden input to store the selected id, you *do not* have to
156
+ wire it manually. The component will automatically discover it with the
157
+ following rules:
158
+
159
+ - If the next sibling of the visible input is an `HTMLInputElement` of
160
+ type `hidden`, it is used as the id input.
161
+ - Otherwise, if the previous sibling meets these conditions, it is used.
162
+ - If neither sibling qualifies, no id input is used and ids are simply
163
+ ignored.
164
+
165
+ The hidden input value is automatically updated whenever the caption changes
166
+ and there is a selected suggestion whose `caption` exactly equals the visible
167
+ input value.
168
+
169
+ #### Fetching suggestions
170
+
171
+ Suggestions are loaded asynchronously from an HTTP endpoint.
172
+
173
+ The component determines the URL from the DOM:
174
+
175
+ - First it checks `input.dataset.fetch` (`data-fetch` attribute on the input
176
+ itself).
177
+ - If not found, it walks up the DOM tree to the closest ancestor element that
178
+ has a `data-fetch` attribute and uses its value.
179
+
180
+ Once the base URL is known, requests are performed with:
181
+
182
+ ```text
183
+ GET <data-fetch>?startsWith=<current value>
184
+ Accept: application/json
185
+ ```
186
+
187
+ - When the input is empty, the `?startsWith=...` suffix is omitted.
188
+ - The response must be a JSON array of `[id, caption]` items. `id` is
189
+ converted to a number, `caption` is kept as a string.
190
+
191
+ Client-side filtering is applied so that only captions whose lowercase form
192
+ starts with the lowercase input value are proposed as suggestions.
193
+
194
+ #### Keyboard interaction
195
+
196
+ The following keys are handled while the input has focus:
197
+
198
+ - `ArrowDown` / legacy `Down` – Opens the suggestions list (if there is more
199
+ than one suggestion) or moves the selection one item down.
200
+ - `ArrowUp` / legacy `Up` – Moves the selection one item up; if already at the
201
+ first item, the list is closed.
202
+ - `Enter` – Confirms the currently selected suggestion, copies its caption
203
+ into the input, updates the hidden id input (if any) and hides the list.
204
+ - `Escape` – If the list is visible, simply closes it. If the list is hidden,
205
+ clears the input value and resets the hidden id input.
206
+
207
+ Mouse interactions (clicking on a suggestion) are also supported through the
208
+ internal implementation, thanks to the `<ul class="suggestions">` element
209
+ rendered next to the input.
210
+
211
+ #### Input value changes and events
212
+
213
+ Every time the input value is programmatically changed by the component
214
+ (`autoComplete`, suggestion selection...), the component:
215
+
216
+ 1. Stores the new value in `input.dataset.lastValue`.
217
+ 2. Dispatches a standard `input` event (with `bubbles: true`).
218
+ 3. If the input is not the active element anymore, dispatches a `change`
219
+ event as well.
220
+ 4. Maintains the `empty` CSS class:
221
+ - If the value is empty, the `empty` class is added.
222
+ - If the value is not empty, the `empty` class is removed.
223
+
224
+ You can therefore rely on standard `input` / `change` events and on the
225
+ presence of the `empty` class to react to user changes, without having to
226
+ listen to internal events.
227
+
228
+ ## Typical use cases
229
+
230
+ Here are some common scenarios where `@itrocks/autocomplete` is useful:
231
+
232
+ - **Selecting a customer, supplier or product** by name while submitting the
233
+ underlying numeric id in a form.
234
+ - **Country, city or postal code selection** in address forms.
235
+ - **Filtering long lists** (e.g. employees, projects, tags) where the user
236
+ only remembers the beginning of the name.
237
+ - **Replacing `<select>` elements with thousands of options** by a lightweight
238
+ autocomplete text field backed by a server-side search route.
239
+ - **Back-office search fields** such as "assigned to", "linked ticket" or
240
+ "parent entity" selectors.
package/package.json CHANGED
@@ -40,5 +40,5 @@
40
40
  },
41
41
  "type": "module",
42
42
  "types": "./autocomplete.d.ts",
43
- "version": "0.0.9"
43
+ "version": "0.0.10"
44
44
  }