taga11y 1.0.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/LICENSE +21 -0
- package/README.md +309 -0
- package/dist/a11y.d.ts +8 -0
- package/dist/a11y.d.ts.map +1 -0
- package/dist/core/dropdown.d.ts +63 -0
- package/dist/core/dropdown.d.ts.map +1 -0
- package/dist/core/input.d.ts +42 -0
- package/dist/core/input.d.ts.map +1 -0
- package/dist/core/keyboard.d.ts +37 -0
- package/dist/core/keyboard.d.ts.map +1 -0
- package/dist/core/selection.d.ts +24 -0
- package/dist/core/selection.d.ts.map +1 -0
- package/dist/dom/chips.d.ts +6 -0
- package/dist/dom/chips.d.ts.map +1 -0
- package/dist/dom/listbox.d.ts +5 -0
- package/dist/dom/listbox.d.ts.map +1 -0
- package/dist/dom/render.d.ts +24 -0
- package/dist/dom/render.d.ts.map +1 -0
- package/dist/i18n.d.ts +44 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/index.d.ts +212 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/locales/ar.json +28 -0
- package/dist/locales/pt.json +21 -0
- package/dist/react/index.d.ts +46 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react.cjs +1 -0
- package/dist/react.mjs +83 -0
- package/dist/taga11y.cjs +1 -0
- package/dist/taga11y.css +2 -0
- package/dist/taga11y.iife.js +1 -0
- package/dist/taga11y.mjs +829 -0
- package/dist/types.d.ts +201 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/debounce.d.ts +5 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/filter.d.ts +5 -0
- package/dist/utils/filter.d.ts.map +1 -0
- package/dist/utils/id.d.ts +11 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/vue/index.d.ts +155 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue.cjs +1 -0
- package/dist/vue.mjs +127 -0
- package/package.json +111 -0
- package/src/a11y.ts +85 -0
- package/src/aria-notify.d.ts +9 -0
- package/src/core/dropdown.ts +331 -0
- package/src/core/input.ts +172 -0
- package/src/core/keyboard.ts +200 -0
- package/src/core/selection.ts +78 -0
- package/src/dom/chips.ts +80 -0
- package/src/dom/listbox.ts +49 -0
- package/src/dom/render.ts +154 -0
- package/src/i18n.ts +131 -0
- package/src/index.ts +900 -0
- package/src/react/index.tsx +223 -0
- package/src/styles/index.css +367 -0
- package/src/types.ts +224 -0
- package/src/utils/debounce.ts +27 -0
- package/src/utils/filter.ts +14 -0
- package/src/utils/id.ts +30 -0
- package/src/vite-env.d.ts +1 -0
- package/src/vue/index.ts +145 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BinaryUnit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# taga11y
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/taga11y)
|
|
6
|
+
[](https://bundlephobia.com/package/taga11y)
|
|
7
|
+
[](https://www.npmjs.com/package/taga11y)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
|
|
10
|
+
### Accessible tagging, built in — not bolted on.
|
|
11
|
+
|
|
12
|
+
A zero-dependency multi-select / tag input with inline chips, built to the
|
|
13
|
+
**WAI-ARIA APG combobox pattern** exactly — `aria-activedescendant` keeps focus
|
|
14
|
+
on the input throughout dropdown navigation. Keyboard, switch-device, and
|
|
15
|
+
screen-reader support aren't features here; they're the product.
|
|
16
|
+
|
|
17
|
+
Out of the box it renders as close to a **native form control** as it gets,
|
|
18
|
+
blending into any page untouched, yet it's fully customizable.
|
|
19
|
+
|
|
20
|
+
**~8 KB gzipped** · **zero dependencies** · **vanilla JS · React · Vue**
|
|
21
|
+
|
|
22
|
+
<sub><b>WAI-ARIA APG combobox</b> · SR matrix: NVDA · JAWS · VoiceOver · TalkBack · axe-core + Chromium/Firefox/WebKit e2e</sub>
|
|
23
|
+
|
|
24
|
+
### **[➡️ Try the live demos & read the docs ⬅️](https://binaryunit.codeberg.page/taga11y/)**
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- **Accessible by default** — full WAI-ARIA APG combobox pattern, screen reader announcements, keyboard and switch device support
|
|
33
|
+
- **Progressive enhancement** — the original `<input>` is enhanced in place and works as a form control without JavaScript
|
|
34
|
+
- **Three suggestion modes** — static arrays, pre-fetched async, and dynamic per-keystroke callbacks
|
|
35
|
+
- **Whitelist mode** — restrict to predefined suggestions with `enforceSuggestions: true`
|
|
36
|
+
- **Configurable** — delimiters, max tags, debounce, theming, custom serializers
|
|
37
|
+
- **Dark mode** — automatic (`prefers-color-scheme`) or forced (`data-theme`)
|
|
38
|
+
- **CSS custom properties** — retheme from ~6 base tokens; 9 derived tokens cascade automatically (per-token opt-out preserved)
|
|
39
|
+
- **Native form integration** — hidden input with serialised values, form reset support
|
|
40
|
+
- **Zero dependencies** — bundles to a single ESM/CJS/IIFE file via Vite
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
### npm
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npm install taga11y
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Import the core class and the stylesheet:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import Taga11y from 'taga11y';
|
|
54
|
+
import 'taga11y/dist/taga11y.css';
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### CDN / IIFE
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<script src="https://unpkg.com/taga11y/dist/taga11y.iife.js"></script>
|
|
61
|
+
<link rel="stylesheet" href="https://unpkg.com/taga11y/dist/taga11y.css">
|
|
62
|
+
|
|
63
|
+
<script>
|
|
64
|
+
const widget = new Taga11y(inputEl, {
|
|
65
|
+
suggestions: ['JavaScript', 'TypeScript'],
|
|
66
|
+
});
|
|
67
|
+
</script>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Also available on [jsDelivr](https://www.jsdelivr.com/), often faster in
|
|
71
|
+
Europe and Asia:
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<script src="https://cdn.jsdelivr.net/npm/taga11y/dist/taga11y.iife.js"></script>
|
|
75
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/taga11y/dist/taga11y.css">
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<label for="tags">Select tags:</label>
|
|
82
|
+
<input id="tags" type="text">
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const input = document.querySelector('#tags');
|
|
87
|
+
const widget = new Taga11y(input, {
|
|
88
|
+
suggestions: ['JavaScript', 'TypeScript', 'Rust', 'Go', 'Python'],
|
|
89
|
+
maxTags: 10,
|
|
90
|
+
delimiter: [',', 'Enter'],
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Framework wrappers
|
|
95
|
+
|
|
96
|
+
First-party React and Vue components are shipped from subpath exports. Both
|
|
97
|
+
wrap the same vanilla `Taga11y` class, support controlled and uncontrolled
|
|
98
|
+
binding, forward every event, expose the underlying instance, and mount
|
|
99
|
+
client-only (SSR-safe). Import the stylesheet once, as with the core.
|
|
100
|
+
|
|
101
|
+
> Peer dependencies: React 19 (`taga11y/react`) or Vue 3 (`taga11y/vue`).
|
|
102
|
+
|
|
103
|
+
### React
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { useState } from 'react';
|
|
107
|
+
import { Taga11yInput } from 'taga11y/react';
|
|
108
|
+
import 'taga11y/dist/taga11y.css';
|
|
109
|
+
|
|
110
|
+
function Example() {
|
|
111
|
+
const [tags, setTags] = useState(['JavaScript']);
|
|
112
|
+
return (
|
|
113
|
+
<Taga11yInput
|
|
114
|
+
value={tags} // controlled; omit and use defaultValue for uncontrolled
|
|
115
|
+
onChange={(values) => setTags(values)}
|
|
116
|
+
suggestions={['JavaScript', 'TypeScript', 'Rust']}
|
|
117
|
+
maxTags={5}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Props: every `Taga11yOptions` key, plus `value`/`defaultValue` (string arrays),
|
|
124
|
+
the event callbacks `onAdd`/`onRemove`/`onClear`/`onChange`/`onPaste`/`onDestroy`,
|
|
125
|
+
and `instanceRef` to receive the live `Taga11y` instance. A standard `ref`
|
|
126
|
+
resolves to the underlying `<input>` element (use `instanceRef` for the
|
|
127
|
+
instance). Unknown props pass through to the underlying `<input>`.
|
|
128
|
+
|
|
129
|
+
#### With react-hook-form
|
|
130
|
+
|
|
131
|
+
Because `onChange` is value-first and `ref` resolves to the `<input>`, the
|
|
132
|
+
component drops into a `<Controller>` via `{...field}`:
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
136
|
+
import { Taga11yInput } from 'taga11y/react';
|
|
137
|
+
|
|
138
|
+
function TagsField() {
|
|
139
|
+
const { control } = useForm({ defaultValues: { tags: [] } });
|
|
140
|
+
return (
|
|
141
|
+
<Controller
|
|
142
|
+
name="tags"
|
|
143
|
+
control={control}
|
|
144
|
+
render={({ field }) => (
|
|
145
|
+
<Taga11yInput {...field} suggestions={['JavaScript', 'TypeScript', 'Rust']} />
|
|
146
|
+
)}
|
|
147
|
+
/>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`field.onChange` receives the tag array on every mutation, and `field.ref` gets
|
|
153
|
+
the input node so focus-on-validation-error works.
|
|
154
|
+
|
|
155
|
+
### Vue
|
|
156
|
+
|
|
157
|
+
```vue
|
|
158
|
+
<script setup>
|
|
159
|
+
import { ref } from 'vue';
|
|
160
|
+
import { Taga11yInput } from 'taga11y/vue';
|
|
161
|
+
import 'taga11y/dist/taga11y.css';
|
|
162
|
+
|
|
163
|
+
const tags = ref(['JavaScript']);
|
|
164
|
+
</script>
|
|
165
|
+
|
|
166
|
+
<template>
|
|
167
|
+
<Taga11yInput
|
|
168
|
+
v-model="tags"
|
|
169
|
+
:suggestions="['JavaScript', 'TypeScript', 'Rust']"
|
|
170
|
+
:max-tags="5"
|
|
171
|
+
/>
|
|
172
|
+
</template>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Use `v-model` (controlled) or `defaultValue` (uncontrolled). Emits `add`,
|
|
176
|
+
`remove`, `clear`, `change`, `paste`, `destroy`; the instance is available via a
|
|
177
|
+
template ref (`expose()`).
|
|
178
|
+
|
|
179
|
+
> **Notes** — `onDestroy`/`destroy` fire during unmount; your framework's own
|
|
180
|
+
> unmount hook is usually the better place for teardown. The `i18n` option is
|
|
181
|
+
> init-only: change it by remounting, not by updating the prop.
|
|
182
|
+
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
All options are optional.
|
|
186
|
+
|
|
187
|
+
| Option | Type | Default | Description |
|
|
188
|
+
|---|---|---|---|
|
|
189
|
+
| `suggestions` | `SuggestionItem[] \| { once } \| { query }` | — | Suggestion source: static array, pre-fetched async (`{ once: () => Promise<SuggestionItem[]> }`), or dynamic per-keystroke (`{ query: (input, signal) => Promise<SuggestionItem[]> }`). Omit for free-text mode. |
|
|
190
|
+
| `maxTags` | `number` | — | Maximum number of tags. No limit when omitted. |
|
|
191
|
+
| `maxSuggestions` | `number` | `10` | Maximum suggestions rendered in the dropdown at once. `0` shows none; to show all matches pass a large number (e.g. `9999999`). Negative values are clamped to `0`. |
|
|
192
|
+
| `delimiter` | `string \| string[]` | `[',', 'Enter']` | Character(s) that commit the current input as a tag. `'Tab'` is a valid value. |
|
|
193
|
+
| `enforceSuggestions` | `boolean` | `false` | When `true`, only suggestions from the source can be committed. Free-text is rejected. |
|
|
194
|
+
| `name` | `string` | inherited from `input.name` | `name` on the hidden form input. The original input's `name` is removed on init (prevents double submission) and restored on `destroy()`. Override only when you need a different name. |
|
|
195
|
+
| `label` | `string` | — | Injects a `<label>` inside the widget wrapper. Only use when no page-level `<label for="…">` exists — existing page labels work automatically via the preserved `id`. Do not combine both. |
|
|
196
|
+
| `disabled` | `boolean` | `false` | Renders the component in a disabled state. |
|
|
197
|
+
| `theme` | `'dark' \| 'light' \| null` | `null` | Forces a colour scheme. `null` follows `prefers-color-scheme`. |
|
|
198
|
+
| `serialize` | `(tags: TagData[]) => string` | comma-join values | Custom serializer for the hidden input value. |
|
|
199
|
+
| `deserialize` | `(raw: string) => SuggestionItem[]` | split on `,`, trim, drop empties | Custom parser for the original input's `value` on init and on form reset. Pair with `serialize` to round-trip a non-comma format (e.g. JSON). String items resolve labels from loaded suggestions; `{ label, value }` items are used as-is. |
|
|
200
|
+
| `debounceMs` | `number` | `200` | Debounce delay (ms) for dynamic suggestion requests. Negative values are clamped to `0`. |
|
|
201
|
+
| `i18n` | `{ locale: string; dir?: 'ltr' \| 'rtl'; strings?: Partial<I18nStrings> }` | — | Internationalisation. `locale` is a BCP 47 tag; `dir` (optional) stamps direction on the wrapper, otherwise it cascades; `strings` partially overrides the built-in English map (missing keys fall back to English with a dev `console.warn`). **Init-only** — ignored by `settings()`; switch locale via `destroy()` + `new Taga11y()`. See the [i18n guide](docs/guides/i18n.md). |
|
|
202
|
+
|
|
203
|
+
## Events
|
|
204
|
+
|
|
205
|
+
The widget dispatches custom events on the original `<input>` element. All events bubble, are non-cancelable, and carry a `detail` payload. Use `widget.on(name, handler)` or `inputEl.addEventListener(name, handler)`.
|
|
206
|
+
|
|
207
|
+
| Event | Detail | When fired |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| `taga11y:add` | `{ tag: TagData }` | After a single tag is added (typing, suggestion select, `addTag`, `addTags`, or each chunk of a delimited paste). |
|
|
210
|
+
| `taga11y:remove` | `{ tag: TagData }` | After a tag is removed (chip button, Backspace on empty input, or `removeTag`). |
|
|
211
|
+
| `taga11y:clear` | `{ tags: TagData[] }` | After all tags are cleared via `clearTags` or `setTags` (fired before the new tags are added). |
|
|
212
|
+
| `taga11y:change` | `{ tags: TagData[] }` | After any mutation, with the final tag set. Fired once per `addTags` / `setTags` / delimited paste, after all per-chunk `taga11y:add` events. |
|
|
213
|
+
| `taga11y:paste` | `{ added: TagData[], skipped: string[] }` | Once after a paste gesture that contained a configured single-character delimiter. `skipped` lists chunks rejected (not in suggestion list in whitelist mode, already selected, or `maxTags` reached). Not fired for paste without a delimiter. |
|
|
214
|
+
| `taga11y:destroy` | `{}` | After `destroy()` tears down the widget. |
|
|
215
|
+
|
|
216
|
+
See [docs/guides/events.md](docs/guides/events.md) for full per-event reference and examples.
|
|
217
|
+
|
|
218
|
+
## API Docs
|
|
219
|
+
|
|
220
|
+
Full API documentation with all classes, methods, types, and options is generated by TypeDoc and available at [the API reference](https://binaryunit.codeberg.page/taga11y/api/).
|
|
221
|
+
|
|
222
|
+
- [Taga11y class](https://binaryunit.codeberg.page/taga11y/api/classes/Taga11y.html) — constructor, methods, computed getters
|
|
223
|
+
- [Types & interfaces](https://binaryunit.codeberg.page/taga11y/api/modules.html) — `TagData`, `Taga11yOptions`, `SuggestionsSource`, `SuggestionItem`
|
|
224
|
+
|
|
225
|
+
## Bundle size
|
|
226
|
+
|
|
227
|
+
Tiny, zero-dependency, and tree-shakeable. Gzipped:
|
|
228
|
+
|
|
229
|
+
| Artifact | Gzipped |
|
|
230
|
+
|---|---|
|
|
231
|
+
| Core (`taga11y.mjs`) | ~8.0 KB |
|
|
232
|
+
| Stylesheet (`taga11y.css`) | ~1.6 KB |
|
|
233
|
+
| React wrapper (`taga11y/react`) | ~1.0 KB + core |
|
|
234
|
+
| Vue wrapper (`taga11y/vue`) | ~1.0 KB + core |
|
|
235
|
+
|
|
236
|
+
The framework wrappers import the core rather than duplicating it, so a React or
|
|
237
|
+
Vue app pays the wrapper cost once on top of the shared core.
|
|
238
|
+
|
|
239
|
+
## Browser support
|
|
240
|
+
|
|
241
|
+
Modern evergreen browsers — the 2023+ baseline of **Chrome/Edge 120+,
|
|
242
|
+
Firefox 120+, and Safari 17+**. No Internet Explorer.
|
|
243
|
+
|
|
244
|
+
The baseline is set by the CSS `:dir()` pseudo-class (used for RTL layout);
|
|
245
|
+
below it, RTL layout falls back to LTR and every other feature still works.
|
|
246
|
+
taga11y also relies on `ResizeObserver`, `AbortController`/`AbortSignal`,
|
|
247
|
+
`Intl.PluralRules`, `crypto.getRandomValues`, and the CSS `inset` property —
|
|
248
|
+
all available across this baseline.
|
|
249
|
+
|
|
250
|
+
The dropdown's viewport-flip (opening upward when clipped below the fold) is a
|
|
251
|
+
**progressive enhancement** built on CSS Anchor Positioning (`anchor-name`,
|
|
252
|
+
`position-try-fallbacks`), currently Chromium 125+. It's gated behind
|
|
253
|
+
`@supports`, so browsers without anchor positioning simply keep the standard
|
|
254
|
+
absolute-positioned dropdown — no functionality is lost.
|
|
255
|
+
|
|
256
|
+
## Guides
|
|
257
|
+
|
|
258
|
+
- [Theming](docs/guides/theming.md) — CSS custom properties, dark mode, custom themes
|
|
259
|
+
- [Accessibility](docs/guides/accessibility.md) — ARIA pattern, keyboard navigation, AT compatibility
|
|
260
|
+
- [Migration from Tagify / Choices.js](docs/guides/migration.md) — API mapping, DOM differences
|
|
261
|
+
- [Custom Events](docs/guides/events.md) — `taga11y:add`, `taga11y:remove`, `taga11y:clear`, `taga11y:change`, `taga11y:paste`, `taga11y:destroy`
|
|
262
|
+
- [Limitations](docs/guides/limitations.md) — Known limitations and design trade-offs
|
|
263
|
+
|
|
264
|
+
## Contributing
|
|
265
|
+
|
|
266
|
+
Guides for contributors verifying and extending taga11y:
|
|
267
|
+
|
|
268
|
+
- [Testing](docs/guides/testing.md) — four-layer test strategy (unit, integration, screen reader, modality)
|
|
269
|
+
- [Screen Reader Verification](docs/guides/sr-verification.md) — AT pairing matrix and manual steps
|
|
270
|
+
- [Modality Checklist](docs/guides/modality-checklist.md) — keyboard, touch, voice, switch-device checklists
|
|
271
|
+
- [PR Accessibility Checklist](docs/guides/pr-a11y-checklist.md) — a11y review checklist for pull requests
|
|
272
|
+
|
|
273
|
+
## Examples
|
|
274
|
+
|
|
275
|
+
See the `examples/` directory for runnable demos:
|
|
276
|
+
|
|
277
|
+
Run the examples locally:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
npm run dev
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
- [Basic ESM](examples/basic-esm.html) — ES Module inclusion
|
|
284
|
+
- [Basic CJS](examples/basic-cjs.html) — CommonJS inclusion
|
|
285
|
+
- [Basic IIFE](examples/basic-iife.html) — Script tag inclusion
|
|
286
|
+
- [Whitelist mode](examples/whitelist.html)
|
|
287
|
+
- [Custom delimiter](examples/delimiter.html)
|
|
288
|
+
- [Dynamic suggestions (mock API)](examples/dynamic.html)
|
|
289
|
+
- [Fetch error demo](examples/error-fetch.html)
|
|
290
|
+
- [Pre-fetched suggestions](examples/prefetch.html)
|
|
291
|
+
- [Dropdown viewport flip](examples/viewport-flip.html)
|
|
292
|
+
- [Dark mode](examples/dark-mode.html)
|
|
293
|
+
- [Multiple themes on one page](examples/multi-theme.html)
|
|
294
|
+
- [Custom theme](examples/custom-theme.html)
|
|
295
|
+
- [Internationalisation — Portuguese + Arabic RTL](examples/i18n.html)
|
|
296
|
+
- [Disabled state](examples/disabled.html)
|
|
297
|
+
- [Form integration](examples/form.html)
|
|
298
|
+
- [Custom serializer & deserializer](examples/serialize.html)
|
|
299
|
+
- [Programmatic API](examples/programmatic.html)
|
|
300
|
+
- [Accessibility / keyboard demo](examples/a11y-demo.html)
|
|
301
|
+
- [All custom events demo](examples/events.html) — live event log for `taga11y:add`, `taga11y:remove`, `taga11y:clear`, `taga11y:change`, `taga11y:paste`, `taga11y:destroy`
|
|
302
|
+
- [Debug — keyboard & input event trace](examples/debug-events.html)
|
|
303
|
+
- [React — controlled (value / onChange)](examples/react.html)
|
|
304
|
+
- [react-hook-form — Controller integration](examples/react-hook-form.html)
|
|
305
|
+
- [Vue — controlled (v-model)](examples/vue.html)
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
[MIT](./LICENSE)
|
package/dist/a11y.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { I18nStrings, TagData } from './types.js';
|
|
2
|
+
export declare function showError(error: HTMLDivElement, message: string, errorChip?: HTMLElement): void;
|
|
3
|
+
export declare function announceTagAdded(announcer: HTMLDivElement, strings: I18nStrings, locale: string, label: string): void;
|
|
4
|
+
export declare function announceTagRemoved(announcer: HTMLDivElement, strings: I18nStrings, locale: string, label: string): void;
|
|
5
|
+
export declare function announceTagsCleared(announcer: HTMLDivElement, strings: I18nStrings, locale: string): void;
|
|
6
|
+
export declare function announceTagsSummary(announcer: HTMLDivElement, strings: I18nStrings, locale: string, tags: TagData[]): void;
|
|
7
|
+
export declare function announceRejection(error: HTMLDivElement, strings: I18nStrings, locale: string, reason: 'duplicate' | 'max-reached' | 'not-in-list', label: string, errorChip?: HTMLElement): void;
|
|
8
|
+
//# sourceMappingURL=a11y.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../src/a11y.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,SAAS,CACvB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,WAAW,GACtB,IAAI,CAWN;AAOD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAEN;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAEN;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAEN;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EAAE,GACd,IAAI,CAUN;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,aAAa,EACnD,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,WAAW,GACtB,IAAI,CAQN"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { SuggestionItem, SuggestionsSource, I18nStrings } from '../types.js';
|
|
2
|
+
import type { DerivedIds } from '../utils/id.js';
|
|
3
|
+
export declare class DropdownManager {
|
|
4
|
+
private readonly listbox;
|
|
5
|
+
private readonly input;
|
|
6
|
+
private readonly loading;
|
|
7
|
+
private readonly wrapper;
|
|
8
|
+
private readonly ids;
|
|
9
|
+
private readonly strings;
|
|
10
|
+
private readonly locale;
|
|
11
|
+
private maxSuggestions;
|
|
12
|
+
private source;
|
|
13
|
+
private readonly getSelectedValues;
|
|
14
|
+
private readonly onAnnounce;
|
|
15
|
+
private readonly onLoadError;
|
|
16
|
+
private readonly onOptionSelect;
|
|
17
|
+
isOpen: boolean;
|
|
18
|
+
private activeIndex;
|
|
19
|
+
filteredSuggestions: SuggestionItem[];
|
|
20
|
+
private isLoading;
|
|
21
|
+
private cachedItems;
|
|
22
|
+
private _isPrefetching;
|
|
23
|
+
private abortController;
|
|
24
|
+
private debouncedQuery;
|
|
25
|
+
private readonly resizeObserver;
|
|
26
|
+
constructor(elements: {
|
|
27
|
+
listbox: HTMLUListElement;
|
|
28
|
+
input: HTMLInputElement;
|
|
29
|
+
loading: HTMLLIElement;
|
|
30
|
+
wrapper: HTMLElement;
|
|
31
|
+
}, options: {
|
|
32
|
+
suggestions?: SuggestionsSource;
|
|
33
|
+
debounceMs: number;
|
|
34
|
+
maxSuggestions: number;
|
|
35
|
+
getSelectedValues: () => string[];
|
|
36
|
+
ids: DerivedIds;
|
|
37
|
+
strings: I18nStrings;
|
|
38
|
+
locale: string;
|
|
39
|
+
onAnnounce?: (message: string) => void;
|
|
40
|
+
onLoadError?: (message: string) => void;
|
|
41
|
+
onOptionSelect?: (item: SuggestionItem) => void;
|
|
42
|
+
});
|
|
43
|
+
private startPrefetch;
|
|
44
|
+
private executeDynamicQuery;
|
|
45
|
+
open(): void;
|
|
46
|
+
close(): void;
|
|
47
|
+
toggle(): void;
|
|
48
|
+
filter(query: string): void;
|
|
49
|
+
setActiveIndex(index: number): void;
|
|
50
|
+
highlightFirst(): void;
|
|
51
|
+
highlightPrev(): void;
|
|
52
|
+
highlightNext(): void;
|
|
53
|
+
highlightHome(): void;
|
|
54
|
+
highlightEnd(): void;
|
|
55
|
+
selectActive(): SuggestionItem | null;
|
|
56
|
+
setLoading(value: boolean): void;
|
|
57
|
+
setSource(source: SuggestionsSource | undefined, debounceMs: number): void;
|
|
58
|
+
setDebounceMs(debounceMs: number): void;
|
|
59
|
+
setMaxSuggestions(maxSuggestions: number): void;
|
|
60
|
+
getAllSuggestions(): SuggestionItem[];
|
|
61
|
+
destroy(): void;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=dropdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dropdown.d.ts","sourceRoot":"","sources":["../../src/core/dropdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAMjD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAE9E,MAAM,UAAS;IACf,OAAO,CAAC,WAAW,CAAM;IACzB,mBAAmB,EAAE,cAAc,EAAE,CAAM;IAC3C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAG9C,QAAQ,EAAE;QACR,OAAO,EAAE,gBAAgB,CAAC;QAC1B,KAAK,EAAE,gBAAgB,CAAC;QACxB,OAAO,EAAE,aAAa,CAAC;QACvB,OAAO,EAAE,WAAW,CAAC;KACtB,EACD,OAAO,EAAE;QACP,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,MAAM,EAAE,CAAC;QAClC,GAAG,EAAE,UAAU,CAAC;QAChB,OAAO,EAAE,WAAW,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QACvC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QACxC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;KACjD;YA6CW,aAAa;YAiBb,mBAAmB;IAyCjC,IAAI,IAAI,IAAI;IAMZ,KAAK,IAAI,IAAI;IAcb,MAAM,IAAI,IAAI;IAQd,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA0C3B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAmBnC,cAAc,IAAI,IAAI;IAItB,aAAa,IAAI,IAAI;IAOrB,aAAa,IAAI,IAAI;IAOrB,aAAa,IAAI,IAAI;IAIrB,YAAY,IAAI,IAAI;IAIpB,YAAY,IAAI,cAAc,GAAG,IAAI;IAKrC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAShC,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAsB1E,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IASvC,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAK/C,iBAAiB,IAAI,cAAc,EAAE;IAOrC,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { SuggestionItem } from '../types.js';
|
|
2
|
+
export declare class InputManager {
|
|
3
|
+
private readonly input;
|
|
4
|
+
private readonly onInput;
|
|
5
|
+
private readonly onBlurCommit;
|
|
6
|
+
private readonly onBlurClose;
|
|
7
|
+
private readonly onFocus;
|
|
8
|
+
private readonly getDelimiters;
|
|
9
|
+
private readonly isEnforceSuggestions;
|
|
10
|
+
private readonly getLoadedSuggestions;
|
|
11
|
+
private readonly onCommit;
|
|
12
|
+
private readonly onCommitRejected;
|
|
13
|
+
private readonly onPaste;
|
|
14
|
+
private readonly onCloseDropdown;
|
|
15
|
+
private currentValue;
|
|
16
|
+
private blurTimer;
|
|
17
|
+
private readonly handleInput;
|
|
18
|
+
private readonly handleFocus;
|
|
19
|
+
private readonly handleBlur;
|
|
20
|
+
private readonly handlePaste;
|
|
21
|
+
constructor(input: HTMLInputElement, callbacks: {
|
|
22
|
+
onInput: (value: string) => void;
|
|
23
|
+
onBlurCommit: (value: string) => void;
|
|
24
|
+
onBlurClose: () => void;
|
|
25
|
+
onFocus?: () => void;
|
|
26
|
+
getDelimiters?: () => string[];
|
|
27
|
+
isEnforceSuggestions?: () => boolean;
|
|
28
|
+
getLoadedSuggestions?: () => SuggestionItem[];
|
|
29
|
+
onCommit?: (value: string) => void;
|
|
30
|
+
onCommitRejected?: (value: string) => void;
|
|
31
|
+
onPaste?: (chunks: string[]) => void;
|
|
32
|
+
onCloseDropdown?: () => void;
|
|
33
|
+
});
|
|
34
|
+
clearValue(): void;
|
|
35
|
+
getValue(): string;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
private getCharDelimiters;
|
|
38
|
+
private containsAny;
|
|
39
|
+
private extractAndCommit;
|
|
40
|
+
private commitChunk;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/core/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0B;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAgB;IACrD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAa;IAE7C,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,SAAS,CAA4C;IAE7D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAGxD,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE;QACT,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACjC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACtC,WAAW,EAAE,MAAM,IAAI,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;QAC/B,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC;QACrC,oBAAoB,CAAC,EAAE,MAAM,cAAc,EAAE,CAAC;QAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;QACrC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;KAC9B;IA2DH,UAAU,IAAI,IAAI;IAKlB,QAAQ,IAAI,MAAM;IAIlB,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;CAepB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SuggestionsSource, SuggestionItem } from '../types.js';
|
|
2
|
+
import type { DropdownManager } from './dropdown.js';
|
|
3
|
+
export declare class KeyboardManager {
|
|
4
|
+
private readonly input;
|
|
5
|
+
private readonly onCommit;
|
|
6
|
+
private readonly onCommitRejected;
|
|
7
|
+
private readonly onRemoveLast;
|
|
8
|
+
private readonly clearInput;
|
|
9
|
+
private readonly hasChips;
|
|
10
|
+
private readonly getDropdown;
|
|
11
|
+
private readonly getDelimiters;
|
|
12
|
+
private readonly isEnforceSuggestions;
|
|
13
|
+
private readonly getSuggestionSource;
|
|
14
|
+
private readonly getLoadedSuggestions;
|
|
15
|
+
private readonly handleKeydown;
|
|
16
|
+
constructor(input: HTMLInputElement, callbacks: {
|
|
17
|
+
onCommit: (value: string) => void;
|
|
18
|
+
onCommitRejected: (value: string) => void;
|
|
19
|
+
onRemoveLast: () => void;
|
|
20
|
+
clearInput: () => void;
|
|
21
|
+
hasChips: () => boolean;
|
|
22
|
+
getDropdown: () => DropdownManager;
|
|
23
|
+
getDelimiters: () => string[];
|
|
24
|
+
isEnforceSuggestions: () => boolean;
|
|
25
|
+
getSuggestionSource: () => SuggestionsSource | undefined;
|
|
26
|
+
getLoadedSuggestions: () => SuggestionItem[];
|
|
27
|
+
});
|
|
28
|
+
private routeKey;
|
|
29
|
+
private handleArrowDown;
|
|
30
|
+
private handleArrowUp;
|
|
31
|
+
private handleEnter;
|
|
32
|
+
private handleTab;
|
|
33
|
+
private handleBackspace;
|
|
34
|
+
private commit;
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/core/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAgB;IACrD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsC;IAC1E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAE9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;gBAGzD,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE;QACT,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAC1C,YAAY,EAAE,MAAM,IAAI,CAAC;QACzB,UAAU,EAAE,MAAM,IAAI,CAAC;QACvB,QAAQ,EAAE,MAAM,OAAO,CAAC;QACxB,WAAW,EAAE,MAAM,eAAe,CAAC;QACnC,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;QAC9B,oBAAoB,EAAE,MAAM,OAAO,CAAC;QACpC,mBAAmB,EAAE,MAAM,iBAAiB,GAAG,SAAS,CAAC;QACzD,oBAAoB,EAAE,MAAM,cAAc,EAAE,CAAC;KAC9C;IAkBH,OAAO,CAAC,QAAQ;IA4DhB,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,MAAM;IAkBd,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TagData, SuggestionItem } from '../types.js';
|
|
2
|
+
export type AddTagResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
tag: TagData;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
reason: 'duplicate' | 'max-reached';
|
|
8
|
+
};
|
|
9
|
+
export declare class SelectionManager {
|
|
10
|
+
private tags;
|
|
11
|
+
private nextId;
|
|
12
|
+
private readonly base;
|
|
13
|
+
private maxTags;
|
|
14
|
+
constructor(base: string, maxTags?: number);
|
|
15
|
+
addTag(value: string, label?: string): AddTagResult;
|
|
16
|
+
removeTag(id: string): TagData | null;
|
|
17
|
+
clearTags(): TagData[];
|
|
18
|
+
getTags(): TagData[];
|
|
19
|
+
addTags(items: SuggestionItem[]): TagData[];
|
|
20
|
+
setTags(items: SuggestionItem[]): TagData[];
|
|
21
|
+
isTagged(value: string): boolean;
|
|
22
|
+
setMaxTags(maxTags: number | undefined): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/core/selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG3D,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,aAAa,CAAA;CAAE,CAAC;AAEvD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAqB;gBAExB,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAK1C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY;IAoBnD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAOrC,SAAS,IAAI,OAAO,EAAE;IAOtB,OAAO,IAAI,OAAO,EAAE;IAIpB,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE;IAS3C,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE;IAK3C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;CAG9C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TagData, I18nStrings } from '../types.js';
|
|
2
|
+
export declare function createTagsContainer(): HTMLDivElement;
|
|
3
|
+
export declare function createTagList(strings: I18nStrings, locale: string): HTMLUListElement;
|
|
4
|
+
export declare function createErrorChip(text: string): HTMLLIElement;
|
|
5
|
+
export declare function updateChips(tagList: HTMLUListElement, tags: TagData[], onRemove: (id: string) => void, strings: I18nStrings, locale: string, errorChip?: HTMLLIElement, afterRemove?: () => void): void;
|
|
6
|
+
//# sourceMappingURL=chips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chips.d.ts","sourceRoot":"","sources":["../../src/dom/chips.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxD,wBAAgB,mBAAmB,IAAI,cAAc,CAIpD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,gBAAgB,CAKlB;AAgCD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAU3D;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,OAAO,EAAE,EACf,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EAC9B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,aAAa,EACzB,WAAW,CAAC,EAAE,MAAM,IAAI,GACvB,IAAI,CAUN"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SuggestionItem } from '../types.js';
|
|
2
|
+
import type { DerivedIds } from '../utils/id.js';
|
|
3
|
+
export declare function createListbox(ids: DerivedIds): HTMLUListElement;
|
|
4
|
+
export declare function updateListbox(listbox: HTMLUListElement, loading: HTMLLIElement, input: HTMLInputElement, items: SuggestionItem[], isLoading: boolean, ids: DerivedIds): void;
|
|
5
|
+
//# sourceMappingURL=listbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listbox.d.ts","sourceRoot":"","sources":["../../src/dom/listbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,gBAAgB,CAO/D;AAmBD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,SAAS,EAAE,OAAO,EAClB,GAAG,EAAE,UAAU,GACd,IAAI,CAWN"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DerivedIds } from '../utils/id.js';
|
|
2
|
+
import type { I18nStrings } from '../types.js';
|
|
3
|
+
export interface DomElements {
|
|
4
|
+
wrapper: HTMLDivElement;
|
|
5
|
+
tagsContainer: HTMLDivElement;
|
|
6
|
+
tagList: HTMLUListElement;
|
|
7
|
+
listbox: HTMLUListElement;
|
|
8
|
+
loading: HTMLLIElement;
|
|
9
|
+
error: HTMLDivElement;
|
|
10
|
+
announcer: HTMLDivElement;
|
|
11
|
+
hiddenInput: HTMLInputElement;
|
|
12
|
+
}
|
|
13
|
+
export declare function setupCombobox(input: HTMLInputElement, ids: DerivedIds): void;
|
|
14
|
+
export declare function createHiddenInput(name: string, initialValue: string): HTMLInputElement;
|
|
15
|
+
export declare function ariaNotifySupported(): boolean;
|
|
16
|
+
export declare function announce(region: HTMLDivElement, message: string, priority?: 'normal' | 'high'): void;
|
|
17
|
+
export declare function render(input: HTMLInputElement, ids: DerivedIds, opts: {
|
|
18
|
+
label?: string;
|
|
19
|
+
name: string;
|
|
20
|
+
initialValue: string;
|
|
21
|
+
strings: I18nStrings;
|
|
22
|
+
locale: string;
|
|
23
|
+
}): DomElements;
|
|
24
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/dom/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,EAAE,cAAc,CAAC;IAC9B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AA2CD,wBAAgB,aAAa,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAa5E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAOtF;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,wBAAgB,QAAQ,CACtB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,QAAQ,GAAG,MAAiB,GACrC,IAAI,CASN;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,WAAW,CA0Cb"}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { I18nStrings, I18nKey } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in English defaults. Eleven plain strings plus the plural-shaped
|
|
4
|
+
* `a11y.resultsCount`. These are the fallback for any key not supplied
|
|
5
|
+
* via the `i18n.strings` option.
|
|
6
|
+
*/
|
|
7
|
+
export declare const EN: I18nStrings;
|
|
8
|
+
/**
|
|
9
|
+
* Merges a partial string map over the English defaults at the slot level
|
|
10
|
+
* (a supplied `a11y.resultsCount` wholly replaces the English default for
|
|
11
|
+
* that slot — there is no per-category merge). When `provided` is given,
|
|
12
|
+
* emits a single `console.warn` listing every key that fell back to
|
|
13
|
+
* English. The plural slot counts as satisfied when present (it must
|
|
14
|
+
* carry `other`); absent optional CLDR categories are not warned.
|
|
15
|
+
*
|
|
16
|
+
* @param provided - Partial overrides, or `undefined` for pure English.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveStrings(provided?: Partial<I18nStrings>): I18nStrings;
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a string slot for the given locale and interpolation vars.
|
|
21
|
+
*
|
|
22
|
+
* For the plural-shaped slot, when `vars.n` is present the CLDR category
|
|
23
|
+
* is selected via `Intl.PluralRules(locale).select(Number(vars.n))`,
|
|
24
|
+
* falling back to the required `other` form if that category is absent.
|
|
25
|
+
* Plain-string slots ignore `locale` and resolve placeholders directly.
|
|
26
|
+
*
|
|
27
|
+
* @param strings - Resolved string map (post `resolveStrings`).
|
|
28
|
+
* @param locale - Active widget locale (BCP 47).
|
|
29
|
+
* @param key - Dot-key slot to resolve.
|
|
30
|
+
* @param vars - Optional `{placeholder}` substitutions.
|
|
31
|
+
*/
|
|
32
|
+
export declare function t(strings: I18nStrings, locale: string, key: I18nKey, vars?: Record<string, string | number>): string;
|
|
33
|
+
/**
|
|
34
|
+
* Stamps `lang` on the wrapper when the widget locale differs from the
|
|
35
|
+
* document's primary language subtag (or the document has no `lang`).
|
|
36
|
+
* Stamps `dir` only when explicitly provided — direction otherwise
|
|
37
|
+
* cascades from the parent hierarchy.
|
|
38
|
+
*
|
|
39
|
+
* @param wrapper - The widget wrapper element (already in the DOM).
|
|
40
|
+
* @param locale - Active widget locale.
|
|
41
|
+
* @param dir - Explicit direction, or `undefined` to inherit.
|
|
42
|
+
*/
|
|
43
|
+
export declare function applyLocale(wrapper: HTMLElement, locale: string, dir?: 'ltr' | 'rtl'): void;
|
|
44
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAe,MAAM,YAAY,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,EAAE,EAAE,WAoBhB,CAAC;AAIF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAc3E;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAgB,CAAC,CACf,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,OAAO,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACrC,MAAM,CAeR;AAOD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,GAClB,IAAI,CAQN"}
|