abaabil 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abaabil
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,395 @@
1
+ # abaabil
2
+
3
+ Minimal, themeable, accessible React components. Zero dependencies.
4
+
5
+ Eight components: button, dialog, combobox, input, checkbox, radio, select, accordion.
6
+
7
+ ```js
8
+ import Button from 'abaabil/button/a11y'
9
+ import 'abaabil/theme.css'
10
+
11
+ function Example() {
12
+ return <Button onClick={() => console.log('clicked')}>Save</Button>
13
+ }
14
+ ```
15
+
16
+ Each component ships three tiers, `normal`, `styled`, `a11y`, so you only pay for what you use. Two facts worth knowing up front:
17
+
18
+ - A fully accessible `dialog/a11y` is **674 B gzipped**, against `@radix-ui/react-dialog` at **3,422 B**, both measured the same way: the component imported alone, bundled with esbuild, `react`/`react-dom` external, minified, then gzipped. Both numbers are JS only; Radix ships no stylesheet of its own, and it also bundles its own positioning and portal logic and predates a usable native `<dialog>`, so it isn't attempting exactly what abaabil does. The difference is mostly what the platform now gives you for free, not a claim of doing more with less.
19
+ - `accordion/a11y` needs **no JavaScript at all**. Every tier of accordion, including `a11y`, is server-renderable, because it's built on native `<details>`/`<summary>` rather than a scripted widget.
20
+
21
+ ## Install
22
+
23
+ ```
24
+ npm install abaabil
25
+ ```
26
+
27
+ `react` and `react-dom` are peer dependencies (`^19.0.0`); abaabil has zero runtime dependencies of its own.
28
+
29
+ ## The three tiers
30
+
31
+ Every component ships as three separate entry points so you only pay for what you use. For most components, each tier builds on the one before it: `styled` adds abaabil's CSS on top of `normal`, and `a11y` adds ARIA wiring and keyboard handling on top of `styled`.
32
+
33
+ Combobox is the exception: its `a11y` tier is an independent implementation that imports `combobox.css` directly, rather than building on `styled`, because its ARIA attributes have to sit on specific elements (the input and the listbox) that the `styled`/`normal` markup does not expose as separate parts.
34
+
35
+ ### Delivered size
36
+
37
+ The gzipped cost of importing each entry point on its own, React treated as external (a peer, not bundled):
38
+
39
+ | Entry | JS | CSS |
40
+ |---|---:|---:|
41
+ | `abaabil/button` | 189 B | - |
42
+ | `abaabil/button/styled` | 200 B | 555 B |
43
+ | `abaabil/button/a11y` | 559 B | 555 B |
44
+ | `abaabil/dialog` | 161 B | - |
45
+ | `abaabil/dialog/styled` | 171 B | 373 B |
46
+ | `abaabil/dialog/a11y` | 572 B | 373 B |
47
+ | `abaabil/combobox` | 454 B | - |
48
+ | `abaabil/combobox/styled` | 456 B | 626 B |
49
+ | `abaabil/combobox/a11y` | 1090 B | 626 B |
50
+ | `abaabil/input` | 160 B | - |
51
+ | `abaabil/input/styled` | 171 B | 500 B |
52
+ | `abaabil/input/a11y` | 485 B | 500 B |
53
+ | `abaabil/checkbox` | 161 B | - |
54
+ | `abaabil/checkbox/styled` | 171 B | 636 B |
55
+ | `abaabil/checkbox/a11y` | 600 B | 636 B |
56
+ | `abaabil/radio` | 157 B | - |
57
+ | `abaabil/radio/styled` | 168 B | 545 B |
58
+ | `abaabil/radio/a11y` | 542 B | 545 B |
59
+ | `abaabil/select` | 202 B | - |
60
+ | `abaabil/select/styled` | 212 B | 769 B |
61
+ | `abaabil/select/a11y` | 488 B | 769 B |
62
+ | `abaabil/accordion` | 323 B | - |
63
+ | `abaabil/accordion/styled` | 334 B | 533 B |
64
+ | `abaabil/accordion/a11y` | 383 B | 533 B |
65
+
66
+ Each entry point is bundled on its own with its full module graph (so, for example, `button/styled`'s cost already includes the `button` markup it imports) using Rollup (the same plugins as the real build: `@rollup/plugin-node-resolve` and `esbuild` in minify mode), `react`/`react-dom`/`*.css` external, then gzipped. The `styled` and `a11y` tiers also pull in their component's stylesheet as a side-effect import; the CSS column is that stylesheet's own gzipped size, separate from the JS number. `normal` tier entries have no CSS column because they import none.
67
+
68
+ This is different from the per-file numbers in `SIZES.md`, which are produced with `preserveModules` and so under-count any tier that imports another module, such as `styled.js`, which shows only the bytes of its own file, not the `index.js` it re-exports. Re-run this yourself with the same setup (each entry bundled alone, React external, gzip the output) to reproduce these numbers.
69
+
70
+ Import the tier you need directly:
71
+
72
+ ```js
73
+ import Button from 'abaabil/button/a11y'
74
+ import Dialog from 'abaabil/dialog/a11y'
75
+ import Combobox from 'abaabil/combobox/a11y'
76
+ import Input from 'abaabil/input/a11y'
77
+ import Checkbox from 'abaabil/checkbox/a11y'
78
+ import Radio from 'abaabil/radio/a11y'
79
+ import Select from 'abaabil/select/a11y'
80
+ import { Accordion } from 'abaabil/accordion/a11y'
81
+ ```
82
+
83
+ ### Bundler required for `styled` and `a11y` tiers
84
+
85
+ The `styled` and `a11y` entry points (all sixteen across the eight components) import their
86
+ component's CSS as a JS side effect (`import 'abaabil/button/button.css'` style, resolved
87
+ relative to the package). That works in any bundler that understands CSS imports, which
88
+ covers Next.js, Vite, and webpack. It does **not** work if you run the built file directly in
89
+ plain Node with no bundler in front of it (for example `node --input-type=module -e "import(...)"`):
90
+ Node has no loader for `.css` and throws `ERR_UNKNOWN_FILE_EXTENSION`.
91
+
92
+ If you need a bundler-free environment, use the `normal` tier and import the component's
93
+ stylesheet yourself, which is why each component's CSS is exported separately:
94
+
95
+ ```js
96
+ import Button from 'abaabil/button'
97
+ import 'abaabil/button.css'
98
+ ```
99
+
100
+ The `normal` tier (`abaabil/button`, `abaabil/dialog`, `abaabil/combobox`, `abaabil/input`,
101
+ `abaabil/checkbox`, `abaabil/radio`, `abaabil/select`, `abaabil/accordion`) never imports CSS and
102
+ loads cleanly with no bundler.
103
+
104
+ ### Why a `normal`-tier component can still look styled
105
+
106
+ The `normal` tier ships no CSS, but shipping no CSS is not the same as rendering unstyled. All
107
+ three tiers of a component render the same class name (for example `abaabil-button`), and
108
+ `button.css` styles that class globally, not per tier. So if anything in your app imports the
109
+ `styled` or `a11y` tier of a component, every `normal`-tier instance of that same component on
110
+ the page picks up those styles too, purely because the stylesheet got loaded somewhere:
111
+
112
+ ```js
113
+ import Button from 'abaabil/button' // no CSS import
114
+ import ButtonA11y from 'abaabil/button/a11y' // imports button.css
115
+
116
+ // Both render class="abaabil-button". Once button.css is loaded anywhere
117
+ // on the page, both are styled, because the rule targets the class, not
118
+ // the import site.
119
+ ```
120
+
121
+ If you chose `normal` in order to style the component yourself, this works in your favor: the
122
+ library's own rules live in `@layer abaabil.components`, and ordinary unlayered CSS always beats
123
+ a layered rule, so your styles win with no `!important` needed.
124
+
125
+ To get a genuinely unstyled component, import only its `normal` tier and make sure nothing else
126
+ in your app imports that component's stylesheet (directly or through its `styled`/`a11y` tier).
127
+
128
+ ## Theming
129
+
130
+ abaabil ships design tokens in `abaabil/theme.css`. Override the CSS custom properties in your own stylesheet to retheme every component:
131
+
132
+ ```css
133
+ @import 'abaabil/theme.css';
134
+ @import 'abaabil/styles.css';
135
+
136
+ :root {
137
+ --color-primary: #7c3aed;
138
+ --radius-md: 0.75rem;
139
+ }
140
+ ```
141
+
142
+ abaabil's own component rules live inside `@layer abaabil.components`. CSS layers give unlayered rules the higher priority by default, so any selector you write in your normal (unlayered) application CSS beats the library's layered styles automatically, with no `!important` needed:
143
+
144
+ ```css
145
+ /* this wins over abaabil's layered .btn rules, with no !important */
146
+ .btn {
147
+ border-radius: 999px;
148
+ }
149
+ ```
150
+
151
+ ## Server Components
152
+
153
+ Only the entry points that need interactivity are marked `"use client"`. The rest render inside a React Server Component tree as plain server components, shipping zero client JS:
154
+
155
+ | Entry point | `"use client"` |
156
+ |---|---|
157
+ | `abaabil/button` | no |
158
+ | `abaabil/button/styled` | no |
159
+ | `abaabil/button/a11y` | no |
160
+ | `abaabil/dialog` | no |
161
+ | `abaabil/dialog/styled` | no |
162
+ | `abaabil/dialog/a11y` | yes |
163
+ | `abaabil/combobox` | yes |
164
+ | `abaabil/combobox/styled` | yes (see note) |
165
+ | `abaabil/combobox/a11y` | yes |
166
+ | `abaabil/input` | no |
167
+ | `abaabil/input/styled` | no |
168
+ | `abaabil/input/a11y` | yes |
169
+ | `abaabil/checkbox` | no |
170
+ | `abaabil/checkbox/styled` | no |
171
+ | `abaabil/checkbox/a11y` | yes |
172
+ | `abaabil/radio` | no |
173
+ | `abaabil/radio/styled` | no |
174
+ | `abaabil/radio/a11y` | yes |
175
+ | `abaabil/select` | no |
176
+ | `abaabil/select/styled` | no |
177
+ | `abaabil/select/a11y` | yes |
178
+ | `abaabil/accordion` | no |
179
+ | `abaabil/accordion/styled` | no |
180
+ | `abaabil/accordion/a11y` | no |
181
+
182
+ Button (all tiers), accordion (all tiers), and every `normal`/`styled` tier of dialog, input, checkbox, radio and select carry no client directive and can be rendered from a Server Component with zero client JS. Accordion is the only component whose `a11y` tier is also server-renderable: it has no hooks and needs no JavaScript at all, so all three of its tiers stay server components. Dialog's `a11y` tier, every combobox tier, and the `a11y` tier of input, checkbox, radio and select are client components.
183
+
184
+ `abaabil/combobox/styled` has no literal `"use client"` directive of its own; it only re-exports `abaabil/combobox`, which does carry one, so the client boundary is already established there and the directive isn't duplicated. It still behaves as a client module once bundled, which is why it's marked "yes" above.
185
+
186
+ This split is enforced at build time by `scripts/check-directives.js`, which runs as part of `npm run build` and fails the build in both directions: a required `"use client"` that got stripped, or an accidental one on a component that's supposed to stay server-only. That gate is checked against the built output, not just the source, so this table can't silently drift from what actually ships.
187
+
188
+ `button/a11y` has no hooks and stays server-renderable even though it wires up click suppression and Space/Enter activation: it only attaches `onClick`/`onKeyDown` to the underlying element when they are actually needed (you passed a handler yourself, or the case requires suppressing a click: `disabled` with `keepFocusable`, or a disabled link-button). A plain `<Button>Save</Button>` with no handlers and no `disabled` renders with no function props at all, which is what keeps it serializable from a server module. Since passing your own `onClick` already puts you in a client component, this never puts a function prop where the flight serializer would reject it.
189
+
190
+ ## Props
191
+
192
+ Prop tables below cover the props each tier adds on top of standard HTML attributes (`className`, `id`, `aria-*`, event handlers, etc., which all pass through). "Default" is the value used when the prop is omitted.
193
+
194
+ ### Button
195
+
196
+ `normal` and `styled` (`abaabil/button`, `abaabil/button/styled`):
197
+
198
+ | Prop | Type | Default | Description |
199
+ |---|---|---|---|
200
+ | `as` | `string \| Component` | `'button'` | Element or component to render. |
201
+ | `type` | `string` | `'button'` (only when `as` renders a `<button>`) | Native button type. |
202
+ | `className` | `string` | — | Merged with the base class. |
203
+
204
+ `a11y` (`abaabil/button/a11y`), in addition to the above:
205
+
206
+ | Prop | Type | Default | Description |
207
+ |---|---|---|---|
208
+ | `disabled` | `boolean` | `false` | Disables the button. On a non-`button` `as`, sets `aria-disabled` and removes it from the tab order instead (elements like `<a>` have no native disabled state). |
209
+ | `keepFocusable` | `boolean` | `false` | Use `aria-disabled` instead of the native `disabled` attribute, so the button stays focusable and screen reader users can still find it. Clicks are still suppressed. |
210
+ | `leftIcon` | `ReactNode` | — | Rendered before the children, marked `aria-hidden`. Warns in dev if the button has no accessible name. |
211
+ | `rightIcon` | `ReactNode` | — | Rendered after the children, marked `aria-hidden`. Same accessible-name warning as `leftIcon`. |
212
+
213
+ ### Dialog
214
+
215
+ `normal`/`styled` (`abaabil/dialog`, `abaabil/dialog/styled`) render a plain `<dialog>` and accept no props beyond standard HTML attributes; you drive `showModal()`/`close()` yourself through a `ref`.
216
+
217
+ `a11y` (`abaabil/dialog/a11y`):
218
+
219
+ | Prop | Type | Default | Description |
220
+ |---|---|---|---|
221
+ | `open` | `boolean` | `false` | Calls `showModal()`/`close()` on the underlying `<dialog>` as it changes. |
222
+ | `onClose` | `() => void` | — | Called when the dialog closes, whether via `open` becoming `false`, Escape, or a backdrop click. |
223
+ | `label` | `string` | — | Accessible name, rendered as the dialog's heading and wired to `aria-labelledby`. The platform supplies no name on its own; omitting this warns in dev. |
224
+
225
+ ### Combobox
226
+
227
+ Uncontrolled at every tier: there is no `value` prop, the input manages its own text, and you observe the selection through `onChange`.
228
+
229
+ `normal` (`abaabil/combobox`, `abaabil/combobox/styled`):
230
+
231
+ | Prop | Type | Default | Description |
232
+ |---|---|---|---|
233
+ | `options` | `Array<{ value: string, label: string }>` | `[]` | The full option list; filtered client-side against the typed text. |
234
+ | `placeholder` | `string` | — | Passed to the input. |
235
+ | `onChange` | `(value: string) => void` | — | Called with the selected option's `value` when an option is chosen. |
236
+ | `className` | `string` | — | Merged with the wrapper's base class. |
237
+
238
+ `a11y` (`abaabil/combobox/a11y`), in addition to the above:
239
+
240
+ | Prop | Type | Default | Description |
241
+ |---|---|---|---|
242
+ | `label` | `string` | — | Accessible name for the input, wired to `aria-labelledby`. Required for the combobox to have a usable accessible name; omitting it warns in dev. |
243
+ | `hideLabel` | `boolean` | `false` | Visually hides the label (it is always present in the accessibility tree). Set to `true` to visually hide it. |
244
+ | `onChange` | `(value: string \| null) => void` | — | Called with the selected option's `value`, or `null` when the query is cleared via Escape. |
245
+
246
+ ### Input
247
+
248
+ `normal` and `styled` (`abaabil/input`, `abaabil/input/styled`):
249
+
250
+ | Prop | Type | Default | Description |
251
+ |---|---|---|---|
252
+ | `type` | `string` | `'text'` | Native input type. |
253
+ | `className` | `string` | - | Merged with the base class. |
254
+
255
+ `a11y` (`abaabil/input/a11y`), in addition to the above:
256
+
257
+ | Prop | Type | Default | Description |
258
+ |---|---|---|---|
259
+ | `label` | `string` | - | Rendered as a real `<label>`, associated with the input via `htmlFor`/`id`. |
260
+ | `hideLabel` | `boolean` | `false` | Visually hides the label (it is always present in the accessibility tree, still a real `<label>` associated via `htmlFor`/`id`). Set to `true` to visually hide it. Matches combobox's `hideLabel` semantics and default. |
261
+ | `description` | `string` | - | Rendered as help text and wired into `aria-describedby`. |
262
+ | `error` | `string` | - | Rendered as an error message, sets `aria-invalid`, and is wired into `aria-describedby` alongside the description. |
263
+ | `required` | `boolean` | `false` | Passed to the underlying input. |
264
+ | `id` | `string` | - | Overrides the generated input id. |
265
+
266
+ This is the tier that carries `input`'s reason for existing: a real associated `<label>` (not just `aria-label`), `description` and `error` both joined into a single `aria-describedby`, and `aria-invalid` set when `error` is present. If you pass your own `aria-describedby`, it's merged with the generated description/error ids, not discarded. Without a `label` (and no `aria-label`/`aria-labelledby`), the input has no accessible name and this tier warns in dev.
267
+
268
+ ### Checkbox
269
+
270
+ `normal` and `styled` (`abaabil/checkbox`, `abaabil/checkbox/styled`):
271
+
272
+ | Prop | Type | Default | Description |
273
+ |---|---|---|---|
274
+ | `className` | `string` | - | Merged with the base class. |
275
+
276
+ `a11y` (`abaabil/checkbox/a11y`), in addition to the above:
277
+
278
+ | Prop | Type | Default | Description |
279
+ |---|---|---|---|
280
+ | `label` | `string` | - | Accessible name, rendered as a real `<label>`. The platform supplies none on its own; omitting it warns in dev. |
281
+ | `description` | `string` | - | Rendered text, wired into `aria-describedby`. |
282
+ | `indeterminate` | `boolean` | `false` | Puts the checkbox in a mixed state. `indeterminate` is a DOM property, not an HTML attribute, so it cannot be set through JSX at all; this tier applies it to the underlying input via a ref and an effect, and mirrors it to `aria-checked="mixed"` so it's also exposed correctly to assistive tech. |
283
+ | `id` | `string` | - | Overrides the generated input id. |
284
+
285
+ A consumer-supplied `ref` composes with the ref this tier uses internally for `indeterminate`, so passing your own doesn't silently break it.
286
+
287
+ `CheckboxGroup` (`abaabil/checkbox/a11y` only; there is no `normal`/`styled` version) renders a `<fieldset>`/`<legend>` pair, the accessible way to group checkboxes under a shared label:
288
+
289
+ | Prop | Type | Default | Description |
290
+ |---|---|---|---|
291
+ | `label` | `string` | - | Group label, rendered as the `<legend>`. |
292
+ | `className` | `string` | - | Merged with the group wrapper's base class. |
293
+
294
+ ### Radio
295
+
296
+ `normal` and `styled` (`abaabil/radio`, `abaabil/radio/styled`):
297
+
298
+ | Prop | Type | Default | Description |
299
+ |---|---|---|---|
300
+ | `className` | `string` | - | Merged with the base class. |
301
+
302
+ `a11y` (`abaabil/radio/a11y`), in addition to the above:
303
+
304
+ | Prop | Type | Default | Description |
305
+ |---|---|---|---|
306
+ | `label` | `string` | - | Accessible name, rendered as a real `<label>`. Omitting it warns in dev. |
307
+ | `description` | `string` | - | Rendered text, wired into `aria-describedby`. |
308
+ | `name` | `string` | inherited from `RadioGroup` | Overrides the shared name a `RadioGroup` ancestor supplies through context. |
309
+ | `id` | `string` | - | Overrides the generated input id. |
310
+
311
+ `RadioGroup` shares one `name` with every descendant `Radio` through context, which is what makes them one native group rather than several independent radios. This matters because nothing visible tells you when it's broken: radios that don't share a `name` render fine, but arrow-key navigation and single-selection both key off that shared attribute, so an ungrouped set silently allows multiple radios to appear selected at once.
312
+
313
+ `RadioGroup` (`abaabil/radio/a11y` only) renders a `<fieldset>`/`<legend>` pair and supplies that shared `name`, generating one via `useId` if you don't pass one:
314
+
315
+ | Prop | Type | Default | Description |
316
+ |---|---|---|---|
317
+ | `label` | `string` | - | Group label, rendered as the `<legend>`. |
318
+ | `name` | `string` | generated via `useId` | Shared name for every radio in the group. |
319
+ | `className` | `string` | - | Merged with the group wrapper's base class. |
320
+
321
+ ### Select
322
+
323
+ `normal` and `styled` (`abaabil/select`, `abaabil/select/styled`) render a real native `<select>`, styled, not a custom listbox:
324
+
325
+ | Prop | Type | Default | Description |
326
+ |---|---|---|---|
327
+ | `options` | `Array<{ value: string, label: string }>` | - | Rendered as `<option>` elements. Only consulted when given; pass `children` instead for `<optgroup>` or hand-written `<option>` markup, since the two never fight over which one renders. |
328
+ | `className` | `string` | - | Merged with the base class. |
329
+
330
+ `a11y` (`abaabil/select/a11y`), in addition to the above:
331
+
332
+ | Prop | Type | Default | Description |
333
+ |---|---|---|---|
334
+ | `label` | `string` | - | Accessible name, rendered as a real `<label>`. |
335
+ | `hideLabel` | `boolean` | `false` | Visually hides the label (it is always present in the accessibility tree, still a real `<label>` associated via `htmlFor`/`id`). Set to `true` to visually hide it. Matches combobox's `hideLabel` semantics and default. |
336
+ | `description` | `string` | - | Rendered and wired into `aria-describedby`. |
337
+ | `error` | `string` | - | Rendered, sets `aria-invalid`, and is joined into `aria-describedby` alongside the description. |
338
+ | `id` | `string` | - | Overrides the generated select id. |
339
+
340
+ CSS customizable select (`appearance: base-select`) was deliberately not used to build this. It is not Baseline: support is Chrome 135 only, with no Firefox support at all, far above this library's Chrome 116 / Firefox 125 / Safari 17 floor.
341
+
342
+ ### Accordion
343
+
344
+ Accordion is the only component whose every tier, including `a11y`, is server-renderable: no `"use client"`, no hooks, no JavaScript. Exclusive open/close (opening one panel closes its siblings) comes entirely from the native `name` attribute on `<details>`.
345
+
346
+ `Disclosure` (`abaabil/accordion`, `abaabil/accordion/styled`), a single native `<details>`/`<summary>` pair:
347
+
348
+ | Prop | Type | Default | Description |
349
+ |---|---|---|---|
350
+ | `summary` | `ReactNode` | - | Content for the `<summary>` element. |
351
+ | `className` | `string` | - | Merged with the base class. |
352
+ | `summaryClassName` | `string` | - | Merged with the summary's base class. |
353
+
354
+ `Accordion` (`abaabil/accordion`, `abaabil/accordion/styled`), a list of `Disclosure`s that share a `name`:
355
+
356
+ | Prop | Type | Default | Description |
357
+ |---|---|---|---|
358
+ | `items` | `Array<{ key?, summary, children? }>` | - | One entry per disclosure. |
359
+ | `name` | `string` | `'abaabil-accordion'` | Shared native group name. Pass `name={undefined}` explicitly to opt out of exclusive behavior. |
360
+ | `className` | `string` | - | Merged onto the wrapping element. |
361
+
362
+ `a11y` (`abaabil/accordion/a11y`): `Disclosure` is re-exported unchanged, since `<summary>` already carries the correct implicit role and expanded/collapsed state and there's nothing this tier can add to a single disclosure. `Accordion_a11y`, in addition to `Accordion`'s props above:
363
+
364
+ | Prop | Type | Default | Description |
365
+ |---|---|---|---|
366
+ | `label` | `string` | - | Accessible name for the group as a whole. When given, applies `role="group"` and `aria-label` to the wrapper. Left unset by default: an unnamed group announces to screen readers as "group" with no name, which is worse than not grouping at all, and each panel's own summary text already names it. |
367
+
368
+ **Deliberate limitation:** `Accordion_a11y` offers no `headingLevel` prop, and this is intentional, not an oversight. `<summary>` has an implicit ARIA role of `button` in some browsers, and a heading nested inside a button is not reliably exposed to assistive technology (VoiceOver, for one, does not expose a heading nested inside `<summary>` as a heading). The reverse, wrapping `<summary>` in a heading element, isn't an option either: `<summary>` must be the literal first child of `<details>` for the browser to recognize it as the disclosure trigger. Consumers who need reliable heading navigation across sections need the button-in-heading accordion pattern instead (an explicit heading wrapping a button, with `aria-expanded` and `aria-controls`), a different, ARIA-driven widget that this component does not attempt to be.
369
+
370
+ ## Combobox: uncontrolled in 1.0.0
371
+
372
+ The combobox is uncontrolled in this release: it does not accept a `value` prop. Observe the selected value through the `onChange` callback instead of driving it from external state.
373
+
374
+ ## Browser support
375
+
376
+ The floor is Chrome 99, Firefox 98, Safari 15.4, set by `@layer` (needed from Chrome 99 and Safari 15.4) and by Firefox's `<dialog>`/`showModal()` support (Firefox 98). `:focus-visible` and `<details>`/`<summary>` need less everywhere and don't raise the floor. A few features are used only as progressive enhancement and degrade safely instead of raising it:
377
+
378
+ | Feature | Needs | Degrades to |
379
+ |---|---|---|
380
+ | `<details name>` | Chrome 120, Firefox 130, Safari 17.2 | multiple panels open at once |
381
+ | `@starting-style` | Chrome 117, Firefox 129, Safari 17.5 | no entry animation |
382
+ | CSS anchor positioning | Chrome 125, Firefox 147, Safari 26 | absolute positioning, behind `@supports` |
383
+
384
+ ## Accessibility
385
+
386
+ - The combobox implements the [WAI-ARIA Authoring Practices Guide 1.2 combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).
387
+ - Dialog modality (focus containment, inert background, Escape to close) is handled natively by the browser's `showModal()` on `<dialog>`, not by a JavaScript focus trap.
388
+ - Checkbox's `indeterminate` is mirrored to `aria-checked="mixed"`, because `indeterminate` itself is a DOM property with no attribute equivalent, so it's invisible to assistive tech unless something does this explicitly.
389
+ - `RadioGroup` supplies the shared `name` every descendant `Radio` needs to behave as one native group; without it, arrow-key navigation and single-selection silently stop working.
390
+ - Accordion's `a11y` tier needs no JavaScript at all: every tier, including `a11y`, is server-renderable, and exclusive open/close comes from the native `name` attribute on `<details>`.
391
+ - `a11y` tiers are the recommended default for production use; `normal` and `styled` tiers exist for cases where you want to compose your own accessibility behavior.
392
+
393
+ ## License
394
+
395
+ MIT
@@ -0,0 +1 @@
1
+ import{jsx as i}from"react/jsx-runtime";import"./accordion.css";import{Accordion as l}from"./index.js";import{Disclosure as a}from"./index.js";function e({label:r,...o}){return i(l,{...r?{role:"group","aria-label":r}:null,...o})}export{e as Accordion_a11y,a as Disclosure};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-accordion-group{border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:clip}.abaabil-accordion-group .abaabil-accordion+.abaabil-accordion{border-top:1px solid var(--color-border)}.abaabil-accordion{color:var(--color-text)}.abaabil-accordion__summary{list-style:none}.abaabil-accordion__summary::-webkit-details-marker{display:none}.abaabil-accordion__summary{justify-content:space-between;align-items:center;gap:var(--space-2);min-height:var(--control-height-md);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;-webkit-user-select:none;user-select:none;line-height:1.3;display:flex}.abaabil-accordion__summary:hover{background:var(--color-muted)}.abaabil-accordion__summary:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:-2px}.abaabil-accordion__summary:after{content:"";block-size:.5rem;inline-size:.5rem;transition:transform var(--duration-fast) ease;border-bottom:2px solid;border-right:2px solid;flex:none;transform:rotate(45deg)}.abaabil-accordion[open]>.abaabil-accordion__summary:after{transform:rotate(-135deg)}.abaabil-accordion__panel{padding:0 var(--space-4) var(--space-3)}@media (prefers-reduced-motion:reduce){.abaabil-accordion__summary:after{transition:none}}}
@@ -0,0 +1 @@
1
+ import{jsxs as b,jsx as r}from"react/jsx-runtime";function l({summary:i,className:c,summaryClassName:a,children:s,...n}){const m=c?`abaabil-accordion ${c}`:"abaabil-accordion",o=a?`abaabil-accordion__summary ${a}`:"abaabil-accordion__summary";return b("details",{className:m,...n,children:[r("summary",{className:o,children:i}),r("div",{className:"abaabil-accordion__panel",children:s})]})}function u({items:i,name:c="abaabil-accordion",className:a,...s}){const n=a?`abaabil-accordion-group ${a}`:"abaabil-accordion-group";return r("div",{className:n,...s,children:i.map(({key:m,summary:o,children:e},d)=>r(l,{name:c,summary:o,children:e},m??d))})}export{u as Accordion,l as Disclosure};
@@ -0,0 +1 @@
1
+ import"./accordion.css";import{Accordion as i,Disclosure as e}from"./index.js";export{i as Accordion,e as Disclosure};
@@ -0,0 +1 @@
1
+ import{jsxs as v,jsx as p}from"react/jsx-runtime";import"./button.css";import w from"./index.js";function x({as:n="button",disabled:e=!1,keepFocusable:b=!1,leftIcon:o,rightIcon:t,onClick:r,onKeyDown:d,children:l,...i}){const f=i["aria-label"]??i["aria-labelledby"],h=typeof l=="string"?l.trim().length>0:!!l;typeof process<"u"&&process.env.NODE_ENV!=="production"&&(o||t)&&!h&&!f&&console.warn("abaabil/button: an icon-only button has no accessible name. Pass aria-label or aria-labelledby.");const c=a=>u=>{if(e){u.preventDefault();return}a?.(u)},y=n==="button"?b?{"aria-disabled":e||void 0}:{disabled:e}:{role:"button",tabIndex:e?-1:0,"aria-disabled":e||void 0},m=a=>{n!=="button"&&(a.key===" "||a.key==="Enter")&&(a.preventDefault(),c(r)(a)),d?.(a)},D=!!r||e&&b||n!=="button"&&e,k=n!=="button"||!!d,s={};return D&&(s.onClick=c(r)),k&&(s.onKeyDown=m),v(w,{as:n,...y,...s,...i,children:[o?p("span",{"aria-hidden":"true",children:o}):null,l,t?p("span",{"aria-hidden":"true",children:t}):null]})}export{x as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-button{--btn-bg:var(--color-primary);--btn-fg:var(--color-primary-fg);--btn-border:var(--color-primary);--btn-height:var(--control-height-md);--btn-padding-x:max(.375rem, calc((var(--btn-height) - var(--font-size-sm)) / 2));--btn-radius:var(--radius-md);justify-content:center;align-items:center;gap:var(--space-2);height:var(--btn-height);padding-inline:var(--btn-padding-x);border:1px solid var(--btn-border);border-radius:var(--btn-radius);background:var(--btn-bg);color:var(--btn-fg);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);white-space:nowrap;cursor:pointer;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;line-height:1;text-decoration:none;display:inline-flex}.abaabil-button:hover{--btn-bg:var(--color-primary-hover);--btn-border:var(--color-primary-hover)}.abaabil-button:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-button[data-variant=secondary]{--btn-bg:transparent;--btn-fg:var(--color-text);--btn-border:var(--color-border)}.abaabil-button[data-variant=ghost]{--btn-bg:transparent;--btn-fg:var(--color-text);--btn-border:transparent}.abaabil-button[data-size=sm]{--btn-height:2rem}.abaabil-button[data-size=lg]{--btn-height:3rem}.abaabil-button:disabled,.abaabil-button[aria-disabled=true]{opacity:.5;cursor:not-allowed}@media (prefers-reduced-motion:reduce){.abaabil-button{transition:none}}}
@@ -0,0 +1 @@
1
+ import{jsx as o}from"react/jsx-runtime";function u({as:t="button",type:n,className:a,children:l,...b}){const e=a?`abaabil-button ${a}`:"abaabil-button";return o(t,{className:e,...t==="button"?{type:n??"button"}:null,...b,children:l})}export{u as default};
@@ -0,0 +1 @@
1
+ import"./button.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as u,jsx as c}from"react/jsx-runtime";import{useRef as x,useId as k,useCallback as N,useEffect as _}from"react";import"./checkbox.css";import g from"./index.js";function y({label:a,description:l,indeterminate:r=!1,id:i,ref:e,"aria-describedby":p,...n}){const o=x(null),b=k(),t=i??b,d=`${b}-description`,h=[p,l?d:null].filter(Boolean).join(" ")||void 0,m=N(s=>{o.current=s,typeof e=="function"?e(s):e&&(e.current=s)},[e]),f=!!(a||n["aria-label"]||n["aria-labelledby"]);return typeof process<"u"&&process.env.NODE_ENV!=="production"&&!f&&console.warn("abaabil/checkbox: no `label` given, so the checkbox has no accessible name and screen readers announce it as unnamed."),_(()=>{o.current&&(o.current.indeterminate=r)},[r]),u("span",{className:"abaabil-checkbox__wrapper",children:[c(g,{...n,ref:m,id:t,"aria-describedby":h,"aria-checked":r?"mixed":void 0}),a?c("label",{htmlFor:t,className:"abaabil-checkbox__label",children:a}):null,l?c("span",{id:d,className:"abaabil-checkbox__description",children:l}):null]})}function v({label:a,className:l,children:r,...i}){const e=l?`abaabil-checkbox-group ${l}`:"abaabil-checkbox-group";return u("fieldset",{className:e,...i,children:[a?c("legend",{className:"abaabil-checkbox-group__legend",children:a}):null,r]})}export{v as CheckboxGroup,y as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-checkbox{--checkbox-radius:min(var(--radius-md), .25rem);appearance:none;border:1px solid var(--color-border);border-radius:var(--checkbox-radius);background:var(--color-surface);cursor:pointer;width:1.125rem;height:1.125rem;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;flex-shrink:0;place-content:center;margin:0;display:inline-grid}.abaabil-checkbox:before{content:"";background:var(--color-primary-fg);clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%);width:.65rem;height:.65rem;transition:transform var(--duration-fast) ease;transform:scale(0)}.abaabil-checkbox:checked,.abaabil-checkbox:indeterminate{background:var(--color-primary);border-color:var(--color-primary)}.abaabil-checkbox:checked:before,.abaabil-checkbox:indeterminate:before{transform:scale(1)}.abaabil-checkbox:indeterminate:before{clip-path:none;border-radius:1px;width:.65rem;height:.125rem}.abaabil-checkbox:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-checkbox:disabled{opacity:.5;cursor:not-allowed}.abaabil-checkbox__wrapper{align-items:flex-start;gap:var(--space-2);display:inline-flex}.abaabil-checkbox__label{font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-checkbox__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;display:block}.abaabil-checkbox-group{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3)}.abaabil-checkbox-group__legend{padding-inline:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text)}@media (prefers-reduced-motion:reduce){.abaabil-checkbox,.abaabil-checkbox:before{transition:none}}}
@@ -0,0 +1 @@
1
+ import{jsx as o}from"react/jsx-runtime";function t({className:a,...c}){const e=a?`abaabil-checkbox ${a}`:"abaabil-checkbox";return o("input",{type:"checkbox",className:e,...c})}export{t as default};
@@ -0,0 +1 @@
1
+ import"./checkbox.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as j,jsx as r}from"react/jsx-runtime";import{useId as F,useState as b,useEffect as S}from"react";import"./combobox.css";function V({options:C=[],onChange:x,label:g,placeholder:$,className:_,hideLabel:E=!1,...n}){const c=F(),D=`${c}-listbox`,u=`${c}-label`,d=e=>`${c}-option-${e}`,B=!!(g||n["aria-label"]||n["aria-labelledby"]);typeof process<"u"&&process.env.NODE_ENV!=="production"&&!B&&console.warn("abaabil/combobox: no `label` given, so the combobox has no accessible name and screen readers announce it as unnamed.");const[k,p]=b(""),[t,o]=b(!1),[m,s]=b(-1),[w,y]=b(null),i=C.filter(e=>e.label.toLowerCase().includes(k.trim().toLowerCase())),l=m>=0&&m<i.length?m:-1,f=i.length,v=t&&f>0;S(()=>{l<0||document.getElementById(d(l))?.scrollIntoView?.({block:"nearest"})},[l]);const h=e=>{const a=i[e];a&&(p(a.label),y(a.value),o(!1),s(-1),x?.(a.value))},N=e=>{if(!i.length)return;o(!0);const a=l+e;a<0?s(i.length-1):a>=i.length?s(0):s(a)},I=e=>{if(!e.nativeEvent?.isComposing)switch(e.key){case"ArrowDown":e.preventDefault(),N(1);break;case"ArrowUp":e.preventDefault(),N(-1);break;case"Enter":t&&l>=0&&(e.preventDefault(),h(l));break;case"Escape":e.preventDefault(),t?(o(!1),s(-1)):(p(""),y(null),w!==null&&x?.(null));break;case"Tab":t&&l>=0&&h(l),o(!1);break}},A=()=>{o(!1),s(-1)},K=_?`abaabil-combobox ${_}`:"abaabil-combobox";return j("div",{className:K,children:[r("span",{id:u,className:E?"abaabil-combobox__label":"abaabil-combobox__label--visible",children:g}),r("input",{...n,className:"abaabil-combobox__input",type:"text",role:"combobox",value:k,placeholder:$,autoComplete:"off","aria-labelledby":u,"aria-expanded":v,"aria-controls":D,"aria-autocomplete":"list","aria-haspopup":"listbox","aria-activedescendant":v&&l>=0?d(l):void 0,onFocus:e=>{n.onFocus?.(e),o(!0)},onClick:e=>{n.onClick?.(e),o(!0)},onBlur:e=>{n.onBlur?.(e),A()},onKeyDown:e=>{n.onKeyDown?.(e),I(e)},onChange:e=>{p(e.target.value),o(!0),s(-1)}}),r("ul",{id:D,role:"listbox","aria-labelledby":u,className:"abaabil-combobox__list",hidden:!v,children:i.map((e,a)=>r("li",{id:d(a),role:"option","aria-selected":w===e.value,"data-active":a===l,className:"abaabil-combobox__option",onMouseDown:L=>{L.preventDefault(),h(a)},children:e.label},e.value))}),r("div",{className:"abaabil-visually-hidden","aria-live":"polite",children:t?`${f} result${f===1?"":"s"}`:""})]})}export{V as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-combobox{display:inline-block;position:relative}.abaabil-combobox__label{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.abaabil-combobox__label--visible{margin-bottom:var(--space-1);font-size:var(--font-size-sm);color:var(--color-text);display:block}.abaabil-combobox__input{height:var(--control-height-md);--input-padding-x:max(.375rem, calc((var(--control-height-md) - var(--font-size-sm)) / 2));padding-inline:var(--input-padding-x);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text);font-size:var(--font-size-sm);width:100%}.abaabil-combobox__input:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-combobox__list{z-index:10;width:100%;max-height:15rem;padding:var(--space-1);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);margin:0;list-style:none;position:absolute;inset-block-start:calc(100% + var(--space-1));inset-inline-start:0;overflow-y:auto}.abaabil-combobox__option{padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-combobox__option:hover,.abaabil-combobox__option[data-active=true]{background:var(--color-muted)}@supports (anchor-name:--x){.abaabil-combobox__input{anchor-name:--abaabil-combobox-input}.abaabil-combobox__list{position-anchor:--abaabil-combobox-input;position-area:block-end span-inline-end;position-try-fallbacks:block-start span-inline-end;width:anchor-size(width);position:fixed;inset:auto}}}
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as x,jsx as e}from"react/jsx-runtime";import{useState as r}from"react";function h({options:i=[],onChange:u,placeholder:c,className:s,...o}){const[t,n]=r(""),[m,l]=r(!1),b=i.filter(a=>a.label.toLowerCase().includes(t.trim().toLowerCase())),p=a=>{n(a.label),l(!1),u?.(a.value)},f=s?`abaabil-combobox ${s}`:"abaabil-combobox";return x("div",{className:f,children:[e("input",{...o,className:"abaabil-combobox__input",type:"text",value:t,placeholder:c,onFocus:a=>{o.onFocus?.(a),l(!0)},onChange:a=>{n(a.target.value),l(!0)},onBlur:a=>{o.onBlur?.(a),l(!1)}}),m&&b.length>0?e("ul",{className:"abaabil-combobox__list",children:b.map(a=>e("li",{className:"abaabil-combobox__option",onMouseDown:d=>{d.preventDefault(),p(a)},children:a.label},a.value))}):null]})}export{h as default};
@@ -0,0 +1 @@
1
+ import"./combobox.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as m,jsx as p}from"react/jsx-runtime";import{useRef as v,useId as y,useCallback as h,useEffect as s}from"react";import"./dialog.css";import w from"./index.js";function g({open:o=!1,onClose:a,label:t,children:u,ref:n,onMouseDown:d,...l}){const r=v(null),c=y(),f=h(e=>{r.current=e,typeof n=="function"?n(e):n&&(n.current=e)},[n]),b=!!(t||l["aria-label"]||l["aria-labelledby"]);return typeof process<"u"&&process.env.NODE_ENV!=="production"&&!b&&console.warn("abaabil/dialog: no `label` given, so the dialog has no accessible name and screen readers announce it as unnamed."),s(()=>{const e=r.current;e&&(o&&!e.open?e.showModal():!o&&e.open&&e.close())},[o]),s(()=>{const e=r.current;if(!e)return;const i=()=>a?.();return e.addEventListener("close",i),()=>e.removeEventListener("close",i)},[a]),s(()=>{if(!o)return;const e=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=e}},[o]),m(w,{ref:f,"aria-labelledby":t?c:void 0,onMouseDown:e=>{d?.(e),e.target===r.current&&r.current.close()},...l,children:[t?p("h2",{id:c,className:"abaabil-dialog__title",children:t}):null,u]})}export{g as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-dialog{--dialog-width:32rem;--dialog-padding:var(--space-4);width:min(var(--dialog-width), calc(100vw - 2rem));padding:var(--dialog-padding);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text)}.abaabil-dialog::backdrop{background:var(--color-overlay)}.abaabil-dialog__title{margin:0 0 var(--space-3);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold)}@starting-style{.abaabil-dialog[open]{opacity:0;transform:translateY(.5rem)}}.abaabil-dialog[open]{opacity:1;transition:opacity var(--duration-fast) ease, transform var(--duration-fast) ease;transform:none}@media (prefers-reduced-motion:reduce){.abaabil-dialog[open]{transition:none}@starting-style{.abaabil-dialog[open]{opacity:1;transform:none}}}}
@@ -0,0 +1 @@
1
+ import{jsx as d}from"react/jsx-runtime";function e({className:a,children:i,...l}){const o=a?`abaabil-dialog ${a}`:"abaabil-dialog";return d("dialog",{className:o,...l,children:i})}export{e as default};
@@ -0,0 +1 @@
1
+ import"./dialog.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as f,jsx as l}from"react/jsx-runtime";import{useId as _}from"react";import"./input.css";import h from"./index.js";function v({label:e,hideLabel:d=!1,description:i,error:a,required:t=!1,id:u,"aria-describedby":c,...r}){const o=_(),n=u??`${o}-input`,s=`${o}-description`,b=`${o}-error`,p=!!(e||r["aria-label"]||r["aria-labelledby"]);typeof process<"u"&&process.env.NODE_ENV!=="production"&&!p&&console.warn("abaabil/input: no `label` given, so the input has no accessible name. Pass `label`, `aria-label`, or `aria-labelledby`.");const m=[c,i?s:null,a?b:null].filter(Boolean).join(" ")||void 0;return f("div",{className:"abaabil-input-group",children:[e?l("label",{htmlFor:n,className:d?"abaabil-input__label abaabil-visually-hidden":"abaabil-input__label",children:e}):null,l(h,{...r,id:n,required:t,"aria-invalid":a?!0:void 0,"aria-describedby":m}),i?l("div",{id:s,className:"abaabil-input__description",children:i}):null,a?l("div",{id:b,className:"abaabil-input__error",role:"alert",children:a}):null]})}export{v as default};
@@ -0,0 +1 @@
1
+ import{jsx as i}from"react/jsx-runtime";function n({type:t="text",className:a,...e}){const p=a?`abaabil-input ${a}`:"abaabil-input";return i("input",{type:t,className:p,...e})}export{n as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-input{--input-height:var(--control-height-md);--input-padding-x:max(.375rem, calc((var(--input-height) - var(--font-size-sm)) / 2));--input-border:var(--color-border);--input-placeholder-fg:var(--color-placeholder);width:100%;height:var(--input-height);padding-inline:var(--input-padding-x);border:1px solid var(--input-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text);font-size:var(--font-size-sm);transition:border-color var(--duration-fast) ease;display:block}.abaabil-input::placeholder{color:var(--input-placeholder-fg)}.abaabil-input:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-input:disabled{opacity:.5;cursor:not-allowed}.abaabil-input[aria-invalid=true]{--input-border:var(--color-danger)}.abaabil-input-group{gap:var(--space-1);flex-direction:column;display:flex}.abaabil-input__label{font-size:var(--font-size-sm);color:var(--color-text)}.abaabil-input__description{--input-description-fg:var(--color-text-muted);font-size:var(--font-size-sm);color:var(--input-description-fg)}.abaabil-input__error{font-size:var(--font-size-sm);color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.abaabil-input{transition:none}}}
@@ -0,0 +1 @@
1
+ import"./input.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as b,jsx as r}from"react/jsx-runtime";import{createContext as h,useContext as _,useId as m}from"react";import"./radio.css";import N from"./index.js";const u=h(null);function g({label:a,description:e,name:i,id:n,"aria-describedby":o,...l}){const s=_(u),d=m(),c=n??d,t=`${d}-description`,p=[o,e?t:null].filter(Boolean).join(" ")||void 0,f=!!(a||l["aria-label"]||l["aria-labelledby"]);return typeof process<"u"&&process.env.NODE_ENV!=="production"&&!f&&console.warn("abaabil/radio: no `label` given, so the radio has no accessible name and screen readers announce it as unnamed."),b("span",{className:"abaabil-radio__wrapper",children:[r(N,{...l,id:c,name:i??s?.name,"aria-describedby":p}),a?r("label",{htmlFor:c,className:"abaabil-radio__label",children:a}):null,e?r("span",{id:t,className:"abaabil-radio__description",children:e}):null]})}function v({label:a,name:e,className:i,children:n,...o}){const l=m(),s=i?`abaabil-radio-group ${i}`:"abaabil-radio-group";return r(u.Provider,{value:{name:e??l},children:b("fieldset",{className:s,...o,children:[a?r("legend",{className:"abaabil-radio-group__legend",children:a}):null,n]})})}export{v as RadioGroup,g as default};
@@ -0,0 +1 @@
1
+ import{jsx as r}from"react/jsx-runtime";function t({className:a,...o}){const i=a?`abaabil-radio ${a}`:"abaabil-radio";return r("input",{type:"radio",className:i,...o})}export{t as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-radio{appearance:none;border:1px solid var(--color-border);background:var(--color-surface);cursor:pointer;width:1.125rem;height:1.125rem;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;border-radius:50%;flex-shrink:0;place-content:center;margin:0;display:inline-grid}.abaabil-radio:before{content:"";background:var(--color-primary-fg);width:.5rem;height:.5rem;transition:transform var(--duration-fast) ease;border-radius:50%;transform:scale(0)}.abaabil-radio:checked{background:var(--color-primary);border-color:var(--color-primary)}.abaabil-radio:checked:before{transform:scale(1)}.abaabil-radio:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-radio:disabled{opacity:.5;cursor:not-allowed}.abaabil-radio__wrapper{align-items:flex-start;gap:var(--space-2);display:inline-flex}.abaabil-radio__label{font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-radio__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;display:block}.abaabil-radio-group{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3)}.abaabil-radio-group__legend{padding-inline:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text)}@media (prefers-reduced-motion:reduce){.abaabil-radio,.abaabil-radio:before{transition:none}}}
@@ -0,0 +1 @@
1
+ import"./radio.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsxs as f,jsx as a}from"react/jsx-runtime";import{useId as h}from"react";import"./select.css";import _ from"./index.js";function N({label:l,hideLabel:b=!1,description:i,error:e,id:t,className:o,"aria-describedby":p,...r}){const s=h(),n=t??`${s}-select`,c=i?`${s}-description`:void 0,d=e?`${s}-error`:void 0,m=[p,c,d].filter(Boolean).join(" ")||void 0,u=!!(l||r["aria-label"]||r["aria-labelledby"]);typeof process<"u"&&process.env.NODE_ENV!=="production"&&!u&&console.warn("abaabil/select: no `label` given, so the select has no accessible name and screen readers announce it as unnamed.");const v=o?`abaabil-select-group ${o}`:"abaabil-select-group";return f("div",{className:v,children:[l?a("label",{htmlFor:n,className:b?"abaabil-select__label abaabil-visually-hidden":"abaabil-select__label",children:l}):null,a(_,{...r,id:n,"aria-describedby":m,"aria-invalid":e?!0:void 0}),i?a("p",{id:c,className:"abaabil-select__description",children:i}):null,e?a("p",{id:d,className:"abaabil-select__error",children:e}):null]})}export{N as default};
@@ -0,0 +1 @@
1
+ import{jsx as s}from"react/jsx-runtime";function n({options:e,className:l,children:t,...c}){const i=l?`abaabil-select ${l}`:"abaabil-select";return s("select",{className:i,...c,children:e?e.map(a=>s("option",{value:a.value,children:a.label},a.value)):t})}export{n as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.components{.abaabil-select{--select-height:var(--control-height-md);--select-padding-x:max(.375rem, calc((var(--select-height) - var(--font-size-sm)) / 2));appearance:none;height:var(--select-height);padding-inline:var(--select-padding-x);border:1px solid var(--color-border);border-radius:var(--radius-md);background-color:var(--color-surface);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--select-padding-x) center;color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;transition:border-color var(--duration-fast) ease;background-size:.75rem .75rem;padding-inline-end:calc(var(--select-padding-x) + 1.125rem);line-height:1}.abaabil-select:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){background-position:left var(--select-padding-x) center;padding-inline-start:calc(var(--select-padding-x) + 1.125rem);padding-inline-end:var(--select-padding-x)}.abaabil-select:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-select:disabled{opacity:.5;cursor:not-allowed}.abaabil-select-group{gap:var(--space-1);flex-direction:column;display:flex}.abaabil-select__label{font-size:var(--font-size-sm);color:var(--color-text)}.abaabil-select__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;margin:0}.abaabil-select__error{font-size:var(--font-size-sm);color:var(--color-danger);margin:0}.abaabil-select[aria-invalid=true]{border-color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.abaabil-select{transition:none}}}
@@ -0,0 +1 @@
1
+ import"./select.css";import{default as e}from"./index.js";export{e as default};
@@ -0,0 +1 @@
1
+ @layer abaabil.reset;@layer abaabil.tokens{:root{--abaabil-blue-500:#2563eb;--abaabil-blue-400:#3b82f6;--abaabil-gray-900:#111827;--abaabil-gray-300:#d1d5db;--abaabil-gray-100:#f3f4f6;--abaabil-white:#fff;--abaabil-red-600:#dc2626;--color-primary:var(--abaabil-blue-500);--color-primary-hover:var(--abaabil-blue-400);--color-primary-fg:var(--abaabil-white);--color-surface:var(--abaabil-white);--color-text:var(--abaabil-gray-900);--color-border:var(--abaabil-gray-300);--color-muted:var(--abaabil-gray-100);--color-danger:var(--abaabil-red-600);--color-focus-ring:var(--abaabil-blue-500);--color-overlay:#00000080;--color-text-muted:#6b7280;--color-placeholder:#9ca3af;--radius-md:.375rem;--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--font-size-sm:.875rem;--font-size-lg:1.125rem;--font-weight-semibold:600;--control-height-md:2.5rem;--duration-fast:.15s}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--color-surface:#0b0f19;--color-text:#e5e7eb;--color-border:#374151;--color-muted:#1f2937;--color-text-muted:#9ca3af;--color-placeholder:#6b7280}}:root[data-theme=dark]{--color-surface:#0b0f19;--color-text:#e5e7eb;--color-border:#374151;--color-muted:#1f2937;--color-text-muted:#9ca3af;--color-placeholder:#6b7280}}@layer abaabil.base{.abaabil-visually-hidden{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}}@layer abaabil.components{.abaabil-accordion-group{border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:clip}.abaabil-accordion-group .abaabil-accordion+.abaabil-accordion{border-top:1px solid var(--color-border)}.abaabil-accordion{color:var(--color-text)}.abaabil-accordion__summary{list-style:none}.abaabil-accordion__summary::-webkit-details-marker{display:none}.abaabil-accordion__summary{justify-content:space-between;align-items:center;gap:var(--space-2);min-height:var(--control-height-md);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;-webkit-user-select:none;user-select:none;line-height:1.3;display:flex}.abaabil-accordion__summary:hover{background:var(--color-muted)}.abaabil-accordion__summary:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:-2px}.abaabil-accordion__summary:after{content:"";block-size:.5rem;inline-size:.5rem;transition:transform var(--duration-fast) ease;border-bottom:2px solid;border-right:2px solid;flex:none;transform:rotate(45deg)}.abaabil-accordion[open]>.abaabil-accordion__summary:after{transform:rotate(-135deg)}.abaabil-accordion__panel{padding:0 var(--space-4) var(--space-3)}@media (prefers-reduced-motion:reduce){.abaabil-accordion__summary:after{transition:none}}.abaabil-button{--btn-bg:var(--color-primary);--btn-fg:var(--color-primary-fg);--btn-border:var(--color-primary);--btn-height:var(--control-height-md);--btn-padding-x:max(.375rem, calc((var(--btn-height) - var(--font-size-sm)) / 2));--btn-radius:var(--radius-md);justify-content:center;align-items:center;gap:var(--space-2);height:var(--btn-height);padding-inline:var(--btn-padding-x);border:1px solid var(--btn-border);border-radius:var(--btn-radius);background:var(--btn-bg);color:var(--btn-fg);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);white-space:nowrap;cursor:pointer;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;line-height:1;text-decoration:none;display:inline-flex}.abaabil-button:hover{--btn-bg:var(--color-primary-hover);--btn-border:var(--color-primary-hover)}.abaabil-button:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-button[data-variant=secondary]{--btn-bg:transparent;--btn-fg:var(--color-text);--btn-border:var(--color-border)}.abaabil-button[data-variant=ghost]{--btn-bg:transparent;--btn-fg:var(--color-text);--btn-border:transparent}.abaabil-button[data-size=sm]{--btn-height:2rem}.abaabil-button[data-size=lg]{--btn-height:3rem}.abaabil-button:disabled,.abaabil-button[aria-disabled=true]{opacity:.5;cursor:not-allowed}@media (prefers-reduced-motion:reduce){.abaabil-button{transition:none}}.abaabil-checkbox{--checkbox-radius:min(var(--radius-md), .25rem);appearance:none;border:1px solid var(--color-border);border-radius:var(--checkbox-radius);background:var(--color-surface);cursor:pointer;width:1.125rem;height:1.125rem;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;flex-shrink:0;place-content:center;margin:0;display:inline-grid}.abaabil-checkbox:before{content:"";background:var(--color-primary-fg);clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%);width:.65rem;height:.65rem;transition:transform var(--duration-fast) ease;transform:scale(0)}.abaabil-checkbox:checked,.abaabil-checkbox:indeterminate{background:var(--color-primary);border-color:var(--color-primary)}.abaabil-checkbox:checked:before,.abaabil-checkbox:indeterminate:before{transform:scale(1)}.abaabil-checkbox:indeterminate:before{clip-path:none;border-radius:1px;width:.65rem;height:.125rem}.abaabil-checkbox:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-checkbox:disabled{opacity:.5;cursor:not-allowed}.abaabil-checkbox__wrapper{align-items:flex-start;gap:var(--space-2);display:inline-flex}.abaabil-checkbox__label{font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-checkbox__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;display:block}.abaabil-checkbox-group{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3)}.abaabil-checkbox-group__legend{padding-inline:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text)}@media (prefers-reduced-motion:reduce){.abaabil-checkbox,.abaabil-checkbox:before{transition:none}}.abaabil-combobox{display:inline-block;position:relative}.abaabil-combobox__label{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.abaabil-combobox__label--visible{margin-bottom:var(--space-1);font-size:var(--font-size-sm);color:var(--color-text);display:block}.abaabil-combobox__input{height:var(--control-height-md);--input-padding-x:max(.375rem, calc((var(--control-height-md) - var(--font-size-sm)) / 2));padding-inline:var(--input-padding-x);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text);font-size:var(--font-size-sm);width:100%}.abaabil-combobox__input:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-combobox__list{z-index:10;width:100%;max-height:15rem;padding:var(--space-1);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);margin:0;list-style:none;position:absolute;inset-block-start:calc(100% + var(--space-1));inset-inline-start:0;overflow-y:auto}.abaabil-combobox__option{padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-combobox__option:hover,.abaabil-combobox__option[data-active=true]{background:var(--color-muted)}@supports (anchor-name:--x){.abaabil-combobox__input{anchor-name:--abaabil-combobox-input}.abaabil-combobox__list{position-anchor:--abaabil-combobox-input;position-area:block-end span-inline-end;position-try-fallbacks:block-start span-inline-end;width:anchor-size(width);position:fixed;inset:auto}}.abaabil-dialog{--dialog-width:32rem;--dialog-padding:var(--space-4);width:min(var(--dialog-width), calc(100vw - 2rem));padding:var(--dialog-padding);border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text)}.abaabil-dialog::backdrop{background:var(--color-overlay)}.abaabil-dialog__title{margin:0 0 var(--space-3);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold)}@starting-style{.abaabil-dialog[open]{opacity:0;transform:translateY(.5rem)}}.abaabil-dialog[open]{opacity:1;transition:opacity var(--duration-fast) ease, transform var(--duration-fast) ease;transform:none}@media (prefers-reduced-motion:reduce){.abaabil-dialog[open]{transition:none}@starting-style{.abaabil-dialog[open]{opacity:1;transform:none}}}.abaabil-input{--input-height:var(--control-height-md);--input-padding-x:max(.375rem, calc((var(--input-height) - var(--font-size-sm)) / 2));--input-border:var(--color-border);--input-placeholder-fg:var(--color-placeholder);width:100%;height:var(--input-height);padding-inline:var(--input-padding-x);border:1px solid var(--input-border);border-radius:var(--radius-md);background:var(--color-surface);color:var(--color-text);font-size:var(--font-size-sm);transition:border-color var(--duration-fast) ease;display:block}.abaabil-input::placeholder{color:var(--input-placeholder-fg)}.abaabil-input:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-input:disabled{opacity:.5;cursor:not-allowed}.abaabil-input[aria-invalid=true]{--input-border:var(--color-danger)}.abaabil-input-group{gap:var(--space-1);flex-direction:column;display:flex}.abaabil-input__label{font-size:var(--font-size-sm);color:var(--color-text)}.abaabil-input__description{--input-description-fg:var(--color-text-muted);font-size:var(--font-size-sm);color:var(--input-description-fg)}.abaabil-input__error{font-size:var(--font-size-sm);color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.abaabil-input{transition:none}}.abaabil-radio{appearance:none;border:1px solid var(--color-border);background:var(--color-surface);cursor:pointer;width:1.125rem;height:1.125rem;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;border-radius:50%;flex-shrink:0;place-content:center;margin:0;display:inline-grid}.abaabil-radio:before{content:"";background:var(--color-primary-fg);width:.5rem;height:.5rem;transition:transform var(--duration-fast) ease;border-radius:50%;transform:scale(0)}.abaabil-radio:checked{background:var(--color-primary);border-color:var(--color-primary)}.abaabil-radio:checked:before{transform:scale(1)}.abaabil-radio:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-radio:disabled{opacity:.5;cursor:not-allowed}.abaabil-radio__wrapper{align-items:flex-start;gap:var(--space-2);display:inline-flex}.abaabil-radio__label{font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.abaabil-radio__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;display:block}.abaabil-radio-group{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3)}.abaabil-radio-group__legend{padding-inline:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text)}@media (prefers-reduced-motion:reduce){.abaabil-radio,.abaabil-radio:before{transition:none}}.abaabil-select{--select-height:var(--control-height-md);--select-padding-x:max(.375rem, calc((var(--select-height) - var(--font-size-sm)) / 2));appearance:none;height:var(--select-height);padding-inline:var(--select-padding-x);border:1px solid var(--color-border);border-radius:var(--radius-md);background-color:var(--color-surface);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--select-padding-x) center;color:var(--color-text);font-size:var(--font-size-sm);cursor:pointer;transition:border-color var(--duration-fast) ease;background-size:.75rem .75rem;padding-inline-end:calc(var(--select-padding-x) + 1.125rem);line-height:1}.abaabil-select:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){background-position:left var(--select-padding-x) center;padding-inline-start:calc(var(--select-padding-x) + 1.125rem);padding-inline-end:var(--select-padding-x)}.abaabil-select:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:2px}.abaabil-select:disabled{opacity:.5;cursor:not-allowed}.abaabil-select-group{gap:var(--space-1);flex-direction:column;display:flex}.abaabil-select__label{font-size:var(--font-size-sm);color:var(--color-text)}.abaabil-select__description{font-size:var(--font-size-sm);color:var(--color-text);opacity:.75;margin:0}.abaabil-select__error{font-size:var(--font-size-sm);color:var(--color-danger);margin:0}.abaabil-select[aria-invalid=true]{border-color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.abaabil-select{transition:none}}}
package/dist/theme.css ADDED
@@ -0,0 +1 @@
1
+ @layer abaabil.reset;@layer abaabil.tokens{:root{--abaabil-blue-500:#2563eb;--abaabil-blue-400:#3b82f6;--abaabil-gray-900:#111827;--abaabil-gray-300:#d1d5db;--abaabil-gray-100:#f3f4f6;--abaabil-white:#fff;--abaabil-red-600:#dc2626;--color-primary:var(--abaabil-blue-500);--color-primary-hover:var(--abaabil-blue-400);--color-primary-fg:var(--abaabil-white);--color-surface:var(--abaabil-white);--color-text:var(--abaabil-gray-900);--color-border:var(--abaabil-gray-300);--color-muted:var(--abaabil-gray-100);--color-danger:var(--abaabil-red-600);--color-focus-ring:var(--abaabil-blue-500);--color-overlay:#00000080;--color-text-muted:#6b7280;--color-placeholder:#9ca3af;--radius-md:.375rem;--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--font-size-sm:.875rem;--font-size-lg:1.125rem;--font-weight-semibold:600;--control-height-md:2.5rem;--duration-fast:.15s}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--color-surface:#0b0f19;--color-text:#e5e7eb;--color-border:#374151;--color-muted:#1f2937;--color-text-muted:#9ca3af;--color-placeholder:#6b7280}}:root[data-theme=dark]{--color-surface:#0b0f19;--color-text:#e5e7eb;--color-border:#374151;--color-muted:#1f2937;--color-text-muted:#9ca3af;--color-placeholder:#6b7280}}@layer abaabil.base{.abaabil-visually-hidden{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}}@layer abaabil.components;
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "abaabil",
3
+ "version": "1.0.0",
4
+ "description": "Minimal, themeable, accessible React components. Zero dependencies.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/w3debugger/abaabil.ui.git"
9
+ },
10
+ "homepage": "https://github.com/w3debugger/abaabil.ui#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/w3debugger/abaabil.ui/issues"
13
+ },
14
+ "author": "Abaabil",
15
+ "keywords": [
16
+ "react",
17
+ "components",
18
+ "accessible",
19
+ "accessibility",
20
+ "headless",
21
+ "css-variables",
22
+ "apg",
23
+ "aria",
24
+ "design-system",
25
+ "ui",
26
+ "react-19"
27
+ ],
28
+ "type": "module",
29
+ "sideEffects": [
30
+ "*.css"
31
+ ],
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "exports": {
36
+ "./button": "./dist/button/index.js",
37
+ "./button/styled": "./dist/button/styled.js",
38
+ "./button/a11y": "./dist/button/a11y.js",
39
+ "./dialog": "./dist/dialog/index.js",
40
+ "./dialog/styled": "./dist/dialog/styled.js",
41
+ "./dialog/a11y": "./dist/dialog/a11y.js",
42
+ "./combobox": "./dist/combobox/index.js",
43
+ "./combobox/styled": "./dist/combobox/styled.js",
44
+ "./combobox/a11y": "./dist/combobox/a11y.js",
45
+ "./input": "./dist/input/index.js",
46
+ "./input/styled": "./dist/input/styled.js",
47
+ "./input/a11y": "./dist/input/a11y.js",
48
+ "./checkbox": "./dist/checkbox/index.js",
49
+ "./checkbox/styled": "./dist/checkbox/styled.js",
50
+ "./checkbox/a11y": "./dist/checkbox/a11y.js",
51
+ "./radio": "./dist/radio/index.js",
52
+ "./radio/styled": "./dist/radio/styled.js",
53
+ "./radio/a11y": "./dist/radio/a11y.js",
54
+ "./select": "./dist/select/index.js",
55
+ "./select/styled": "./dist/select/styled.js",
56
+ "./select/a11y": "./dist/select/a11y.js",
57
+ "./accordion": "./dist/accordion/index.js",
58
+ "./accordion/styled": "./dist/accordion/styled.js",
59
+ "./accordion/a11y": "./dist/accordion/a11y.js",
60
+ "./theme.css": "./dist/theme.css",
61
+ "./styles.css": "./dist/styles.css",
62
+ "./button.css": "./dist/button/button.css",
63
+ "./dialog.css": "./dist/dialog/dialog.css",
64
+ "./combobox.css": "./dist/combobox/combobox.css",
65
+ "./input.css": "./dist/input/input.css",
66
+ "./checkbox.css": "./dist/checkbox/checkbox.css",
67
+ "./radio.css": "./dist/radio/radio.css",
68
+ "./select.css": "./dist/select/select.css",
69
+ "./accordion.css": "./dist/accordion/accordion.css"
70
+ },
71
+ "scripts": {
72
+ "build": "node scripts/build-css.js && rollup -c && node scripts/check-directives.js && node scripts/measure.js",
73
+ "test": "vitest run",
74
+ "test:watch": "vitest",
75
+ "prepublishOnly": "npm run build && node scripts/check-package.js"
76
+ },
77
+ "peerDependencies": {
78
+ "react": "^19.0.0",
79
+ "react-dom": "^19.0.0"
80
+ },
81
+ "devDependencies": {
82
+ "@rollup/plugin-node-resolve": "^16.0.0",
83
+ "@testing-library/dom": "^10.4.0",
84
+ "@testing-library/jest-dom": "^6.6.3",
85
+ "@testing-library/react": "^16.1.0",
86
+ "@testing-library/user-event": "^14.5.2",
87
+ "jest-axe": "^9.0.0",
88
+ "jsdom": "^25.0.1",
89
+ "lightningcss": "^1.29.1",
90
+ "react": "^19.0.0",
91
+ "react-dom": "^19.0.0",
92
+ "rollup": "^4.30.1",
93
+ "rollup-plugin-esbuild": "^6.1.1",
94
+ "rollup-plugin-preserve-directives": "^0.4.0",
95
+ "vitest": "^3.0.0"
96
+ }
97
+ }