@alwatr/action 9.26.0 → 9.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  **Declarative DOM action-dispatch — the Action layer for Unidirectional Data Flow.**
4
4
 
5
- `@alwatr/action` bridges HTML `on-<eventType>` attributes to typed signal handlers using **global event delegation**. One listener on `document.body` covers every element on the page including elements added dynamically after bootstrap with O(1) initialization cost regardless of how many elements exist.
5
+ `@alwatr/action` bridges HTML `on-<eventType>` attributes to typed signal handlers using **global event delegation**. It is implemented as a factory service (`ActionService`) with all state and listeners encapsulated. A pre-instantiated singleton `actionService` is exported for immediate use.
6
+
7
+ One listener on `document.body` covers every element on the page — including elements added dynamically after bootstrap — with O(1) initialization cost regardless of how many elements exist.
6
8
 
7
9
  ---
8
10
 
@@ -40,7 +42,7 @@ document.body capture listener (1 listener per event type)
40
42
  parse attribute → 'ui_add_to_cart:42'
41
43
  run modifiers → none
42
44
  resolve payload → '42'
43
- internalChannel_.dispatch('ui_add_to_cart', {
45
+ actionService.dispatch({
44
46
  type: 'ui_add_to_cart',
45
47
  payload: '42',
46
48
  context: 'product-list',
@@ -99,15 +101,24 @@ declare module '@alwatr/action' {
99
101
 
100
102
  ### 2. Bootstrap delegation
101
103
 
104
+ Use the pre-instantiated singleton `actionService`:
105
+
102
106
  ```ts
103
- import {setupActionDelegation, onAction} from '@alwatr/action';
107
+ import {actionService} from '@alwatr/action';
104
108
  import './action-record.js'; // ensure the declaration is loaded
105
109
 
106
- setupActionDelegation();
110
+ // Initialize global event delegation
111
+ actionService.setupDelegation();
107
112
 
108
113
  // The handler receives the full Action<K> object — payload, context, and meta in one place.
109
- onAction('ui_open_drawer', (action) => openDrawer(action.payload)); // action.payload: string
110
- onAction('ui_add_to_cart', (action) => {
114
+ actionService.on('ui_open_drawer', (action) => openDrawer(action.payload)); // action.payload: string
115
+
116
+ // Subscribe to multiple action types using an array
117
+ actionService.on(['ui_open_drawer', 'ui_close_drawer'], (action) => {
118
+ console.log(action.type, action.payload);
119
+ });
120
+
121
+ actionService.on('ui_add_to_cart', (action) => {
111
122
  cartService.add(action.payload.productId, action.payload.qty); // fully typed
112
123
  console.log(action.context); // e.g. 'product-list' — from nearest [action-context] ancestor
113
124
  });
@@ -167,7 +178,7 @@ Wrap a group of elements in an `[action-context]` container to scope their actio
167
178
  ```
168
179
 
169
180
  ```ts
170
- onAction('ui_slider_change', (action) => {
181
+ actionService.on('ui_slider_change', (action) => {
171
182
  if (action.context === 'volume') audioService.setVolume(Number(action.payload));
172
183
  if (action.context === 'brightness') displayService.setBrightness(Number(action.payload));
173
184
  });
@@ -177,20 +188,20 @@ Context is `undefined` when no `[action-context]` ancestor exists — programmat
177
188
 
178
189
  ### 5. Programmatic dispatch
179
190
 
180
- Use `dispatchAction` for code-originated actions (after async operations, from services, etc.).
191
+ Use `actionService.dispatch` for code-originated actions (after async operations, from services, etc.).
181
192
  These actions should **not** use the `ui_` prefix — that prefix is reserved for DOM-originated actions.
182
193
 
183
194
  ```ts
184
- import {dispatchAction} from '@alwatr/action';
195
+ import {actionService} from '@alwatr/action';
185
196
 
186
197
  // Code-originated actions — no 'ui_' prefix
187
198
  await uploadFile(file);
188
- dispatchAction({type: 'upload_complete', payload: fileId});
199
+ actionService.dispatch({type: 'upload_complete', payload: fileId});
189
200
 
190
- dispatchAction({type: 'navigate', payload: '/dashboard'});
201
+ actionService.dispatch({type: 'navigate', payload: '/dashboard'});
191
202
 
192
203
  // With explicit context and meta
193
- dispatchAction({
204
+ actionService.dispatch({
194
205
  type: 'slider_change',
195
206
  payload: 75,
196
207
  context: 'volume',
@@ -260,10 +271,10 @@ interface Action<K extends keyof ActionRecord> {
260
271
  Modifiers in the delegation pipeline receive the mutable `action` object and can enrich `meta` before the action reaches subscribers:
261
272
 
262
273
  ```ts
263
- import {registerModifier} from '@alwatr/action';
274
+ import {actionService} from '@alwatr/action';
264
275
 
265
276
  // A modifier that stamps a trace ID into meta
266
- registerModifier('trace', (_event, _element, action) => {
277
+ actionService.registerModifier('trace', (_event, _element, action) => {
267
278
  action.meta ??= {};
268
279
  action.meta['traceId'] = crypto.randomUUID();
269
280
  return true;
@@ -275,7 +286,7 @@ registerModifier('trace', (_event, _element, action) => {
275
286
  ```
276
287
 
277
288
  ```ts
278
- onAction('ui_submit_order', (action) => {
289
+ actionService.on('ui_submit_order', (action) => {
279
290
  console.log(action.meta?.['traceId']); // e.g. 'a1b2-c3d4-…'
280
291
  });
281
292
  ```
@@ -284,182 +295,101 @@ onAction('ui_submit_order', (action) => {
284
295
 
285
296
  ## API Reference
286
297
 
287
- ### `Action<K>` (interface)
298
+ ### `actionService` (Singleton instance of `ActionService`)
288
299
 
289
- The Alwatr Flux Standard Action object. Every dispatch and every handler callback uses this structure.
300
+ The pre-instantiated factory service exported for standard usage.
290
301
 
291
- ```ts
292
- import type {Action} from '@alwatr/action';
293
-
294
- // Reading fields in a handler
295
- onAction('ui_add_to_cart', (action: Action<'ui_add_to_cart'>) => {
296
- console.log(action.type); // 'ui_add_to_cart'
297
- console.log(action.payload); // {productId: number; qty: number}
298
- console.log(action.context); // string | undefined
299
- console.log(action.meta); // Record<string, unknown> | undefined
300
- });
301
- ```
302
+ #### `actionService.on(type, handler)`
302
303
 
303
- ---
304
+ Subscribes to a single action or an array of actions. O(1) routing via `ChannelSignal`.
304
305
 
305
- ### `ActionRecord` (interface)
306
+ ```ts
307
+ actionService.on<K extends keyof ActionRecord>(
308
+ type: K | K[],
309
+ handler: (action: Action<K>) => Awaitable<void>
310
+ ): SubscribeResult;
306
311
 
307
- The global action type registry. Extend via declaration merging to register typed actions.
312
+ // Usage:
313
+ // Subscribe to a single action
314
+ actionService.on('ui_open_drawer', (action) => { ... });
308
315
 
309
- ```ts
310
- declare module '@alwatr/action' {
311
- interface ActionRecord {
312
- ui_open_drawer: string;
313
- ui_logout: void;
314
- }
315
- }
316
+ // Subscribe to multiple action types
317
+ actionService.on(['ui_open_drawer', 'ui_close_drawer'], (action) => { ... });
316
318
  ```
317
319
 
318
- ---
319
-
320
- ### `setupActionDelegation(eventTypes?)`
320
+ #### `actionService.dispatch(action)`
321
321
 
322
- Registers global event delegation on `document.body`. Call once at bootstrap. Idempotent.
322
+ Dispatches an action to all subscribers.
323
323
 
324
324
  ```ts
325
- function setupActionDelegation(eventTypes?: readonly string[]): void;
326
- ```
327
-
328
- Defaults to `DEFAULT_DELEGATED_EVENTS`: `['click', 'submit', 'input', 'change']`.
325
+ actionService.dispatch<K extends keyof ActionRecord>(action: DispatchParam<K>): void;
329
326
 
330
- ```ts
331
- import {setupActionDelegation, DEFAULT_DELEGATED_EVENTS} from '@alwatr/action';
327
+ // Usage:
328
+ // Dispatch a typed action (payload is required)
329
+ actionService.dispatch({type: 'upload_complete', payload: 'file-123'});
332
330
 
333
- setupActionDelegation([...DEFAULT_DELEGATED_EVENTS, 'keydown']);
331
+ // Dispatch a void action (payload can be omitted)
332
+ actionService.dispatch({type: 'auth_expired'});
334
333
  ```
335
334
 
336
- ---
337
-
338
- ### `teardownActionDelegation()`
335
+ #### `actionService.setupDelegation(eventTypes?)`
339
336
 
340
- Removes all delegation listeners and clears the descriptor cache. Useful in tests or micro-frontend teardown.
337
+ Registers global capture listeners on `document.body`. Defaults to `['click', 'submit', 'input', 'change']`.
341
338
 
342
339
  ```ts
343
- function teardownActionDelegation(): void;
340
+ actionService.setupDelegation(eventTypes?: readonly string[]): void;
344
341
  ```
345
342
 
346
- ---
343
+ #### `actionService.teardownDelegation()`
347
344
 
348
- ### `onAction(type, handler)`
349
-
350
- Subscribes to a single named action or an array of actions. O(1) routing via `ChannelSignal`. The handler receives the full `Action<K>` object.
345
+ Unregisters all delegation listeners and clears the descriptor cache.
351
346
 
352
347
  ```ts
353
- function onAction<K extends keyof ActionRecord>(
354
- type: K | K[],
355
- handler: (action: Action<K>) => Awaitable<void>,
356
- ): SubscribeResult;
348
+ actionService.teardownDelegation(): void;
357
349
  ```
358
350
 
359
- ```ts
360
- // Subscribe to a single action
361
- const sub = onAction('ui_open_drawer', (action) => {
362
- openDrawer(action.payload); // payload: string
363
- console.log(action.context); // e.g. 'sidebar' or undefined
364
- });
351
+ #### `actionService.registerModifier(name, handler)`
365
352
 
366
- // Subscribe to multiple actions with a single handler
367
- const multiSub = onAction(['ui_increment', 'ui_decrement'], (action) => {
368
- console.log('Action triggered:', action.type);
369
- });
370
-
371
- sub.unsubscribe(); // prevent memory leaks
372
- multiSub.unsubscribe();
373
- ```
374
-
375
- ---
376
-
377
- ### `dispatchAction(action)`
378
-
379
- Dispatches a named action. Payload type is enforced by `ActionRecord`.
353
+ Registers custom modifiers.
380
354
 
381
355
  ```ts
382
- function dispatchAction<K extends keyof ActionRecord>(action: Action<K>): void;
356
+ actionService.registerModifier(name: string, handler: ModifierHandler): void;
383
357
  ```
384
358
 
385
- ```ts
386
- // With payload (code-originated — no 'ui_' prefix)
387
- dispatchAction({type: 'navigate', payload: 'settings'});
359
+ #### `actionService.registerPayloadResolver(name, resolver)`
388
360
 
389
- // Void payload
390
- dispatchAction({type: 'auth_expired', payload: undefined});
361
+ Registers custom payload resolvers.
391
362
 
392
- // With context and meta
393
- dispatchAction({
394
- type: 'navigate',
395
- payload: 'settings',
396
- context: 'header',
397
- meta: {triggeredBy: 'keyboard'},
398
- });
363
+ ```ts
364
+ actionService.registerPayloadResolver(name: string, resolver: PayloadResolver): void;
399
365
  ```
400
366
 
401
367
  ---
402
368
 
403
- ### `registerModifier(name, handler)`
404
-
405
- Registers a custom modifier. Return `false` to cancel the dispatch.
369
+ ### `ActionService` (Class)
406
370
 
407
- Handler signature: `(event: Event, element: HTMLElement, action: Action) => boolean`
408
-
409
- The handler receives the mutable `action` object and may write to `action.meta`.
371
+ The class constructor, allowing creation of independent instances of the action bus and delegation pipeline if needed (e.g. in multi-app or test micro-environments).
410
372
 
411
373
  ```ts
412
- import {registerModifier} from '@alwatr/action';
413
-
414
- registerModifier('not_disabled', (_event, element) => {
415
- return !(element as HTMLButtonElement).disabled;
416
- });
374
+ import {ActionService} from '@alwatr/action';
417
375
 
418
- // A modifier that enriches meta before dispatch
419
- registerModifier('timestamp', (_event, _element, action) => {
420
- action.meta ??= {};
421
- action.meta['ts'] = Date.now();
422
- return true;
423
- });
424
- ```
425
-
426
- ```html
427
- <button
428
- on-click="ui_select_item:$data_id; not_disabled,timestamp"
429
- data-id="42"
430
- >
431
- Select
432
- </button>
376
+ const myService = new ActionService();
377
+ myService.setupDelegation(['click']);
433
378
  ```
434
379
 
435
380
  ---
436
381
 
437
- ### `registerPayloadResolver(name, resolver)`
382
+ ### Deprecated Global Functions (Backwards Compatibility)
438
383
 
439
- Registers a custom payload resolver.
384
+ For backwards compatibility with previous versions, the following wrapper functions are exported. They delegate directly to the `actionService` singleton instance and are marked as **deprecated**.
440
385
 
441
- Handler signature: `(event: Event, element: HTMLElement) => unknown`
442
-
443
- ```ts
444
- import {registerPayloadResolver} from '@alwatr/action';
445
-
446
- registerPayloadResolver('$data_id', (_event, element) => {
447
- return (element as HTMLElement).dataset.id ?? null;
448
- });
449
- ```
450
-
451
- ```html
452
- <input
453
- type="checkbox"
454
- on-change="ui_toggle_feature:$checked"
455
- />
456
- <li
457
- on-click="ui_select_item:$data_id"
458
- data-id="42"
459
- >
460
- Item
461
- </li>
462
- ```
386
+ - `onAction(type, handler)` (deprecated wrapper for `actionService.on`)
387
+ - `dispatchAction(action)` (deprecated wrapper for `actionService.dispatch`)
388
+ - `setupActionDelegation(eventTypes?)` (deprecated wrapper for `actionService.setupDelegation`)
389
+ - `teardownActionDelegation()` (deprecated wrapper for `actionService.teardownDelegation`)
390
+ - `registerModifier(name, handler)` (deprecated wrapper for `actionService.registerModifier`)
391
+ - `registerPayloadResolver(name, resolver)` (deprecated wrapper for `actionService.registerPayloadResolver`)
392
+ - `DEFAULT_DELEGATED_EVENTS` (constant mapped to `ActionService.DEFAULT_DELEGATED_EVENTS`)
463
393
 
464
394
  ---
465
395
 
@@ -472,8 +402,8 @@ registerPayloadResolver('$data_id', (_event, element) => {
472
402
  │ <button on-click="ui_add_to_cart:42">Add</button> │
473
403
  │ </section> │
474
404
  └─────────────────────────┬──────────────────────────────────┘
475
- │ DOM event bubbles to body
476
-
405
+ │ DOM event bubbles to body
406
+
477
407
  ┌────────────────────────────────────────────────────────────┐
478
408
  │ Action Layer (@alwatr/action) │
479
409
  │ document.body capture listener (1 per event type) │
@@ -481,26 +411,26 @@ registerPayloadResolver('$data_id', (_event, element) => {
481
411
  │ → closest('[action-context]') → context = 'cart' │
482
412
  │ → run modifiers (may enrich action.meta) │
483
413
  │ → resolve payload → '42' │
484
- │ → dispatch Action {type, payload, context, meta} [O(1)]
414
+ │ → actionService.dispatch(Action) [O(1)]
485
415
  └─────────────────────────┬──────────────────────────────────┘
486
- │ O(1) routing via ChannelSignal
487
-
416
+ │ O(1) routing via ChannelSignal
417
+
488
418
  ┌────────────────────────────────────────────────────────────┐
489
419
  │ Business Logic Layer │
490
- onAction('ui_add_to_cart', (action) => {
420
+ actionService.on('ui_add_to_cart', (action) => {
491
421
  │ cartService.add(action.payload); │
492
422
  │ // action.context === 'cart' │
493
423
  │ }) │
494
424
  └─────────────────────────┬──────────────────────────────────┘
495
- │ state update
496
-
425
+ │ state update
426
+
497
427
  ┌────────────────────────────────────────────────────────────┐
498
428
  │ State Layer (@alwatr/signal) │
499
429
  │ cartSignal.set(newCartState) │
500
430
  └─────────────────────────┬──────────────────────────────────┘
501
- │ state flows down to UI
502
-
503
- UI re-renders
431
+ │ state flows down to UI
432
+
433
+ UI re-renders
504
434
  ```
505
435
 
506
436
  ---
@@ -555,60 +485,25 @@ onAction('ui_add_to_cart', (action) => {
555
485
  });
556
486
  ```
557
487
 
558
- ### `registerModifier` handler signature changed
559
-
560
- Modifier handlers now receive a third `action` argument for `meta` enrichment.
561
-
562
- **Before:**
563
-
564
- ```ts
565
- registerModifier('not_disabled', (_event, element) => {
566
- return !(element as HTMLButtonElement).disabled;
567
- });
568
- ```
569
-
570
- **After (backward-compatible — third arg is optional to use):**
488
+ ### Automated AI Migration Prompt
571
489
 
572
- ```ts
573
- registerModifier('not_disabled', (_event, element, _action) => {
574
- return !(element as HTMLButtonElement).disabled;
575
- });
576
- ```
490
+ If you are using an AI coding assistant (like Cursor, Gemini, Copilot, or Antigravity) to migrate your files to the new `actionService` API, you can use the following prompt to automate the refactoring:
577
491
 
578
- ### Attribute syntax changed
579
-
580
- The event type is now encoded in the **attribute name** instead of the value, and modifiers are listed after a semicolon instead of dot-chained before the arrow.
581
-
582
- **Before:**
492
+ ```text
493
+ Refactor this file to migrate from the deprecated global `@alwatr/action` (or `@alwatr/flux`) functions to the new `actionService` singleton API.
583
494
 
584
- ```html
585
- <button on-action="click->ui_open_drawer:main">Open</button>
586
- <form
587
- on-action="submit.prevent.validate->ui_submit_form:$formdata"
588
- novalidate
589
- >
590
-
591
- </form>
592
- <button on-action="click.once->ui_welcome_dismissed">Got it</button>
495
+ Follow these rules:
496
+ 1. Replace imports of `onAction`, `dispatchAction`, `setupActionDelegation`, `teardownActionDelegation`, `registerModifier`, or `registerPayloadResolver` from `@alwatr/action` (or `@alwatr/flux`) with `actionService`.
497
+ 2. Convert all calls:
498
+ - `onAction(...)` ➔ `actionService.on(...)`
499
+ - `dispatchAction(...)` ➔ `actionService.dispatch(...)`
500
+ - `setupActionDelegation(...)` ➔ `actionService.setupDelegation(...)`
501
+ - `teardownActionDelegation(...)` ➔ `actionService.teardownDelegation(...)`
502
+ - `registerModifier(...)` ➔ `actionService.registerModifier(...)`
503
+ - `registerPayloadResolver(...)` ➔ `actionService.registerPayloadResolver(...)`
504
+ 3. Maintain exact type safety, callback parameter types, and business logic.
593
505
  ```
594
506
 
595
- **After:**
596
-
597
- ```html
598
- <button on-click="ui_open_drawer:main">Open</button>
599
- <form
600
- on-submit="ui_submit_form:$formdata; prevent,validate"
601
- novalidate
602
- >
603
-
604
- </form>
605
- <button on-click="ui_welcome_dismissed; once">Got it</button>
606
- ```
607
-
608
- ### `page-ready` moved to `@alwatr/page-ready`
609
-
610
- `dispatchPageId` / `onPageReady` are no longer part of this package.
611
-
612
507
  ---
613
508
 
614
509
  ## 🌊 Part of Alwatr Flux
@@ -620,7 +515,7 @@ View (HTML on-<event> attributes + action-context)
620
515
 
621
516
  Action Layer (@alwatr/action) — global delegation, O(1) routing, AFSA objects
622
517
 
623
- Controller (business logic via onAction — receives full Action object)
518
+ Controller (business logic via actionService.on — receives full Action object)
624
519
 
625
520
  State Layer (@alwatr/signal) — fine-grained reactivity
626
521
 
@@ -633,10 +528,10 @@ View (re-render only affected nodes)
633
528
 
634
529
  ```typescript
635
530
  // Use @alwatr/flux for the complete architecture
636
- import {setupActionDelegation, onAction, createStateSignal} from '@alwatr/flux';
531
+ import {actionService, createStateSignal} from '@alwatr/flux';
637
532
 
638
533
  // Or use @alwatr/action standalone for just the action bus
639
- import {setupActionDelegation, onAction, dispatchAction} from '@alwatr/action';
534
+ import {actionService} from '@alwatr/action';
640
535
  ```
641
536
 
642
537
  → [View the complete Flux documentation](https://github.com/Alwatr/alwatr/tree/next/pkg/flux)
@@ -0,0 +1,178 @@
1
+ import type { SubscribeResult } from '@alwatr/signal';
2
+ import type { Awaitable } from '@alwatr/type-helper';
3
+ import type { Action, ActionRecord, DispatchParam, ModifierHandler, PayloadResolver } from './type.js';
4
+ /**
5
+ * Parsed representation of an action attribute descriptor.
6
+ * @internal
7
+ */
8
+ interface ActionDescriptor {
9
+ readonly modifiers: ReadonlySet<string>;
10
+ readonly actionId: string;
11
+ readonly payload: string | undefined;
12
+ }
13
+ /**
14
+ * Service to manage declarative DOM actions, programmatic dispatch,
15
+ * modifiers, payload resolvers, and global event delegation.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import {ActionService} from '@alwatr/action';
20
+ *
21
+ * const customActionService = new ActionService();
22
+ * ```
23
+ */
24
+ export declare class ActionService {
25
+ /**
26
+ * Default DOM event types that cover the vast majority of interactive elements.
27
+ */
28
+ static readonly DEFAULT_DELEGATED_EVENTS: readonly string[];
29
+ protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
30
+ /**
31
+ * Internal ChannelSignal used for routing dispatched actions.
32
+ * @protected
33
+ */
34
+ protected readonly internalChannel_: import("@alwatr/signal").ChannelSignal<Record<string, Action<never>>>;
35
+ /**
36
+ * Registry mapping custom modifiers to their handlers.
37
+ * @protected
38
+ */
39
+ protected readonly modifierRegistry_: Map<string, ModifierHandler>;
40
+ /**
41
+ * Registry mapping custom payload resolvers to their functions.
42
+ * @protected
43
+ */
44
+ protected readonly payloadRegistry_: Map<string, PayloadResolver>;
45
+ /**
46
+ * Cache of parsed action descriptors to prevent redundant regex evaluation.
47
+ * @protected
48
+ */
49
+ protected readonly descriptorCache_: Map<string, ActionDescriptor | null>;
50
+ /**
51
+ * Tracked event types currently delegated to `document.body`.
52
+ * @protected
53
+ */
54
+ protected readonly delegatedEventTypes_: Set<string>;
55
+ /**
56
+ * Bound delegation handler for add/removeEventListener.
57
+ * @private
58
+ */
59
+ private readonly handleDelegatedEventBound__;
60
+ constructor();
61
+ /**
62
+ * Subscribes to a named action dispatched anywhere in the application.
63
+ *
64
+ * @template K - A key of ActionRecord.
65
+ * @param type - Action type or array of action types to subscribe to.
66
+ * @param handler - Callback invoked with the full Action object.
67
+ * @returns SubscribeResult containing an `unsubscribe` method.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * // Subscribe to a single action
72
+ * const sub1 = actionService.on('ui_open_drawer', (action) => {
73
+ * console.log(action.payload);
74
+ * });
75
+ *
76
+ * // Subscribe to multiple action types
77
+ * const sub2 = actionService.on(['ui_open_drawer', 'ui_close_drawer'], (action) => {
78
+ * console.log(action.type, action.payload);
79
+ * });
80
+ * ```
81
+ */
82
+ on<K extends keyof ActionRecord>(type: K | K[], handler: (action: Action<K>) => Awaitable<void>): SubscribeResult;
83
+ /**
84
+ * Dispatches an action to all subscribers matching `action.type`.
85
+ *
86
+ * @template K - A key of ActionRecord.
87
+ * @param action - Action object containing `type` and `payload`.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * // Dispatches a typed action (payload is required)
92
+ * actionService.dispatch({type: 'upload_complete', payload: 'file-123'});
93
+ *
94
+ * // Dispatches a void action (payload can be omitted)
95
+ * actionService.dispatch({type: 'auth_expired'});
96
+ * ```
97
+ */
98
+ dispatch<K extends keyof ActionRecord>(action: DispatchParam<K>): void;
99
+ /**
100
+ * Registers a custom modifier to enrich or filter actions before dispatch.
101
+ *
102
+ * @param name - Modifier name (lowercase, alphanumeric).
103
+ * @param handler - Function called when modifier is invoked.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * actionService.registerModifier('trace', (_event, _element, action) => {
108
+ * action.meta ??= {};
109
+ * action.meta['time'] = Date.now();
110
+ * return true;
111
+ * });
112
+ * ```
113
+ */
114
+ registerModifier(name: string, handler: ModifierHandler): void;
115
+ /**
116
+ * Registers a custom payload resolver to map DOM state to action payload.
117
+ *
118
+ * @param name - Resolver token (by convention starting with `$`).
119
+ * @param resolver - Function yielding payload from the event and element.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * actionService.registerPayloadResolver('$data-id', (_event, element) => {
124
+ * return element.dataset.id;
125
+ * });
126
+ * ```
127
+ */
128
+ registerPayloadResolver(name: string, resolver: PayloadResolver): void;
129
+ /**
130
+ * Registers global event delegation listeners on `document.body`.
131
+ *
132
+ * @param eventTypes - List of event types to delegate. Defaults to ActionService.DEFAULT_DELEGATED_EVENTS.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * actionService.setupDelegation();
137
+ * ```
138
+ */
139
+ setupDelegation(eventTypes?: readonly string[]): void;
140
+ /**
141
+ * Unregisters all global event delegation listeners.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * actionService.teardownDelegation();
146
+ * ```
147
+ */
148
+ teardownDelegation(): void;
149
+ /**
150
+ * Parses attribute values into action descriptor, utilizing the internal cache.
151
+ * @protected
152
+ */
153
+ protected parseDescriptor_(attributeValue: string): ActionDescriptor | null;
154
+ /**
155
+ * Global event delegation handler.
156
+ * @protected
157
+ */
158
+ protected handleDelegatedEvent_(event: Event): void;
159
+ /**
160
+ * Registers default modifiers and resolvers.
161
+ * @private
162
+ */
163
+ private registerDefaultModifiersAndResolvers__;
164
+ }
165
+ /**
166
+ * Singleton instance of the ActionService.
167
+ * Ready for immediate use.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * import {actionService} from '@alwatr/action';
172
+ *
173
+ * actionService.setupDelegation();
174
+ * ```
175
+ */
176
+ export declare const actionService: ActionService;
177
+ export {};
178
+ //# sourceMappingURL=action-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-service.d.ts","sourceRoot":"","sources":["../src/action-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAC,SAAS,EAAW,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAC,MAAM,WAAW,CAAC;AAErG;;;GAGG;AACH,UAAU,gBAAgB;IACxB,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAQD;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,wBAAwB,EAAE,SAAS,MAAM,EAAE,CAA0C;IAErG,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAkC;IAE5D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,wEAAyE;IAE5G;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,iBAAiB,+BAAsC;IAE1E;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,+BAAsC;IAEzE;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,uCAA8C;IAEjF;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,oBAAoB,cAAqB;IAE5D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAyC;;IAOrF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,GAAG,eAAe;IAuBjH;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAKtE;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAS9D;;;;;;;;;;;;OAYG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAStE;;;;;;;;;OASG;IACH,eAAe,CAAC,UAAU,GAAE,SAAS,MAAM,EAA2C,GAAG,IAAI;IAc7F;;;;;;;OAOG;IACH,kBAAkB,IAAI,IAAI;IAY1B;;;OAGG;IACH,SAAS,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAuB3E;;;OAGG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAkFnD;;;OAGG;IACH,OAAO,CAAC,sCAAsC;CA6B/C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,eAAsB,CAAC"}