ajo-cloves 0.1.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,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2022-2026, Cristian Falcone
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # ajo-cloves
2
+
3
+ Reusable behavior primitives for Ajo components.
4
+
5
+ A clove is a plain function that attaches one UI behavior to a stateful Ajo
6
+ host and returns a live view. Applications and component libraries can compose
7
+ only the behaviors they need.
8
+
9
+ See Ajo's [Cloves: Sharing Logic](https://github.com/cristianfalcone/ajo#cloves-sharing-logic)
10
+ guide for the component pattern.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pnpm add ajo-cloves ajo
16
+ ```
17
+
18
+ `ajo-cloves` requires `ajo ^0.1.35`.
19
+
20
+ ```tsx
21
+ import type { Host } from 'ajo-cloves'
22
+ import { controlled, dismiss } from 'ajo-cloves'
23
+
24
+ type DisclosureArgs = {
25
+ open?: boolean
26
+ onOpenChange?: (open: boolean, event?: Event) => void
27
+ }
28
+
29
+ function* Disclosure(this: Host, args: DisclosureArgs) {
30
+ let trigger: HTMLButtonElement | null = null
31
+ let content: HTMLDivElement | null = null
32
+ let onOpenChange = args.onOpenChange
33
+
34
+ const open = controlled(this, {
35
+ fallback: false,
36
+ onChange: (value, event) => onOpenChange?.(value, event),
37
+ })
38
+
39
+ dismiss(this, {
40
+ active: () => open.value,
41
+ inside: () => [trigger, content],
42
+ outside: true,
43
+ onDismiss: event => open.set(false, event),
44
+ })
45
+
46
+ for (args of this) {
47
+ onOpenChange = args.onOpenChange
48
+ open.sync(args.open)
49
+
50
+ yield (
51
+ <>
52
+ <button
53
+ ref={el => trigger = el}
54
+ aria-expanded={open.value ? 'true' : 'false'}
55
+ set:onclick={event => open.set(!open.value, event)}
56
+ >
57
+ Details
58
+ </button>
59
+ {open.value && (
60
+ <div ref={el => content = el}>
61
+ Reusable behavior stays independent of component markup.
62
+ </div>
63
+ )}
64
+ </>
65
+ )
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Attr Bags
71
+
72
+ Views can expose attr bags for JSX spread when a behavior needs to apply several
73
+ attributes and handlers to one element.
74
+
75
+ Bags contain HTML attributes such as `role`, `aria-*`, `tabindex`, `id`, and
76
+ `data-*`, plus Ajo `set:on*` handlers. `ajo/html` renders the HTML attributes for
77
+ SSR, and the client attaches event handlers during hydration.
78
+
79
+ Use bags for events attached to rendered children. Ajo reapplies the bag when
80
+ keyed reconciliation reuses an element.
81
+
82
+ ## Catalog
83
+
84
+ ### Interaction
85
+
86
+ | Export | Purpose | Key options |
87
+ |---|---|---|
88
+ | `controlled` | Controlled/uncontrolled value state. | `fallback`, `onChange`; methods `sync`, `set`, `accept`, `init`. |
89
+ | `dismiss` | Escape and optional outside-pointer dismissal. | `active`, `inside`, `escape`, `outside`, `prevent`, `onDismiss`. |
90
+ | `hover` | Hover intent across named zones with open/close delays. | `openDelay`, `closeDelay`, `onChange`; methods `hold`, `release`, `sync`, `cancel`. |
91
+ | `timer` | One-shot timeout with pause/resume. | No options; methods `start`, `stop`, `pause`, `resume`; getters `running`, `remaining`. |
92
+ | `roving` | Keyboard movement over a live item list. | `items`, `orientation`, `dir`, `loop`, `current`, `onMove`. |
93
+ | `typeahead` | Printable-key buffer and prefix matching. | `items`, `text`, `delay`, `onMatch`. |
94
+ | `selection` | Single or multi selection over string values. | `multiple`, `required`, `fallback`, `onChange`; methods `has`, `toggle`, `set`, `sync`. |
95
+ | `restore` | Capture and later restore focus. | No options; methods `capture`, `restore`. |
96
+ | `move` | Pointer-drag session lifecycle with deltas and cancellation. | `onStart`, `onMove`, `onEnd`. |
97
+ | `grid` | Semantic 2D key movement for grids/calendars. | `rtl`, `onMove`; type `GridMove`. |
98
+ | `spin` | Semantic spinbutton key stepping for step, page, and edge movement. | `onMove`; type `SpinMove`. |
99
+ | `label` | Field label/control/description/error id wiring. | `prefix`; returns `LabelView` attr bags. |
100
+ | `hotkey` | Global single-chord keyboard shortcut. | `keys`, `active`, `prevent`, `onPress`. |
101
+ | `announce` | Polite/assertive screen-reader announcements. | No options; document-lifetime live regions. |
102
+ | `GridMove` | Type for semantic grid movement. | Variants: `cols`, `rows`, row/all edge, page movement. |
103
+ | `SpinMove` | Type for semantic spinbutton movement. | Variants: `step`, `page`, min/max edge. |
104
+ | `LabelView` | Type for the live field-labelling view. | Ids and label/control/button/group/description/error attr bags. |
105
+
106
+ ### Positioning
107
+
108
+ | Export | Purpose | Key options |
109
+ |---|---|---|
110
+ | `indicator` | Tracks a marked child's box as CSS variables on its container. | `target`, `of`, `on`; method `sync`. |
111
+
112
+ ### Sensors
113
+
114
+ | Export | Purpose | Key options |
115
+ |---|---|---|
116
+ | `media` | Reactive media-query match shared per query string. | `query`, `fallback`; method `sync`. |
117
+ | `scheme` | Reactive OS dark-scheme preference. | No options. |
118
+ | `storage` | Reactive `localStorage` or `sessionStorage` string value with cross-tab sync. | `key`, `fallback`, `area`. |
119
+ | `scrolling` | Frame-coalesced scroll tracking for a live element. | `target`, `onScroll`, `onEnd`; method `sync`. |
120
+ | `resize` | Shared `ResizeObserver` notifications for a live element. | `target`, `onResize`; method `sync`. |
121
+ | `overflow` | Stamps `data-overflow-x`/`-y` (`start`/`end`/`both`) while content overflows a live scrollable element. | `target`; method `sync`. |
122
+ | `visibility` | Reactive document visibility. | No options. |
123
+
124
+ ### Infrastructure
125
+
126
+ | Export | Purpose | Key options |
127
+ |---|---|---|
128
+ | `Host` | Ajo host type re-export for clove authors and consumers. | `Host<TElement, TArgs>`. |
129
+ | `browser` | Tests whether both Window and Document globals are available. | No options; false in Node, workers, and asymmetric shims. |
130
+ | `dom` | Distinguishes a real element from an ajo/html protocol-only host. | Structural cross-realm element guard. |
131
+ | `listen` | Adds a listener to a DOM host, inert under SSR. | Stops when either the host or optional caller signal aborts. |
132
+ | `statefulRootAttrs` | Maps plain component attrs onto an Ajo Stateful host. | Preserves host protocol args and prefixes DOM attrs with `attr:`. |
133
+ | `callHandler` | Composes an optional consumer event handler. | Invokes function values with the original event. |
134
+ | `callRef` | Composes an optional callback ref. | Forwards both element and `null`. |
135
+ | `clamp` | Clamps a number to an inclusive range. | `value`, `min`, `max`. |
136
+ | `remember` | Stores a value in an insertion-ordered bounded cache. | FIFO; default limit 32; positive integer limits only. |
137
+ | `id` | Monotonic per-prefix id generator. | `prefix`. |
138
+ | `shared` | Shares one lazily started source among subscribers with the same key. | `key`, `start`, callback, `signal`; stops after the last subscriber aborts. |
139
+ | `frame` | Coalesces repeated calls into one callback on the next animation frame. | Callback; returned scheduler has `cancel()`. |
140
+
141
+ ## Runtime Behavior
142
+
143
+ - Each clove handles one reusable concern and composes with other cloves.
144
+ - DOM work follows native browser behavior and accessible interaction patterns.
145
+ - Work attached to a host stops when `host.signal` aborts.
146
+ - APIs that accept a caller signal stop when either signal aborts.
147
+ - DOM helpers stay inert during SSR.
148
+ - Function options are evaluated when an operation runs, so they can read the
149
+ latest component args.