@alwatr/flux 9.19.0 → 9.20.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 +43 -43
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -58,22 +58,22 @@ Through TypeScript's **Declaration Merging**, the entire action bus is fully typ
|
|
|
58
58
|
// Define your actions once
|
|
59
59
|
declare module '@alwatr/flux' {
|
|
60
60
|
interface ActionRecord {
|
|
61
|
-
add_to_cart: {productId: number; qty: number};
|
|
62
|
-
open_drawer: 'menu' | 'settings';
|
|
63
|
-
logout: void;
|
|
61
|
+
'ui:add_to_cart': {productId: number; qty: number};
|
|
62
|
+
'ui:open_drawer': 'menu' | 'settings';
|
|
63
|
+
'ui:logout': void;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Get compile-time safety everywhere — handler receives the full Action object
|
|
68
|
-
onAction('add_to_cart', (action) => {
|
|
68
|
+
onAction('ui:add_to_cart', (action) => {
|
|
69
69
|
// action.payload is typed as {productId: number; qty: number}
|
|
70
70
|
cartService.add(action.payload.productId, action.payload.qty);
|
|
71
71
|
// action.context is the nearest [action-context] ancestor value (or undefined)
|
|
72
72
|
console.log(action.context); // e.g. 'product-list'
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
dispatchAction({type: 'add_to_cart', payload: {productId: 42, qty: 1}}); // ✅
|
|
76
|
-
dispatchAction({type: 'add_to_cart', payload: 'wrong'}); // ❌ Compile error
|
|
75
|
+
dispatchAction({type: 'ui:add_to_cart', payload: {productId: 42, qty: 1}}); // ✅
|
|
76
|
+
dispatchAction({type: 'ui:add_to_cart', payload: 'wrong'}); // ❌ Compile error
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
---
|
|
@@ -126,17 +126,17 @@ Connect DOM events to typed actions without writing JavaScript. Wrap elements in
|
|
|
126
126
|
|
|
127
127
|
```html
|
|
128
128
|
<!-- Simple action -->
|
|
129
|
-
<button on-click="open_drawer:menu">Menu</button>
|
|
129
|
+
<button on-click="ui:open_drawer:menu">Menu</button>
|
|
130
130
|
|
|
131
131
|
<!-- Dynamic payload from input value -->
|
|
132
132
|
<input
|
|
133
|
-
on-input="search_query:$value"
|
|
133
|
+
on-input="ui:search_query:$value"
|
|
134
134
|
placeholder="Search..."
|
|
135
135
|
/>
|
|
136
136
|
|
|
137
137
|
<!-- Form submission with validation -->
|
|
138
138
|
<form
|
|
139
|
-
on-submit="submit_form:$formdata; prevent,validate"
|
|
139
|
+
on-submit="ui:submit_form:$formdata; prevent,validate"
|
|
140
140
|
novalidate
|
|
141
141
|
>
|
|
142
142
|
<input
|
|
@@ -150,30 +150,30 @@ Connect DOM events to typed actions without writing JavaScript. Wrap elements in
|
|
|
150
150
|
<!-- Checkbox state -->
|
|
151
151
|
<input
|
|
152
152
|
type="checkbox"
|
|
153
|
-
on-change="toggle_feature:$checked"
|
|
153
|
+
on-change="ui:toggle_feature:$checked"
|
|
154
154
|
/>
|
|
155
155
|
|
|
156
156
|
<!-- Fire once and remove -->
|
|
157
|
-
<button on-click="track_impression:hero_banner; once">Learn More</button>
|
|
157
|
+
<button on-click="ui:track_impression:hero_banner; once">Learn More</button>
|
|
158
158
|
|
|
159
159
|
<!-- Context scoping — same action type, different regions -->
|
|
160
160
|
<section action-context="volume">
|
|
161
161
|
<input
|
|
162
162
|
type="range"
|
|
163
|
-
on-input="
|
|
163
|
+
on-input="ui:slider_change:$value"
|
|
164
164
|
/>
|
|
165
165
|
</section>
|
|
166
166
|
<section action-context="brightness">
|
|
167
167
|
<input
|
|
168
168
|
type="range"
|
|
169
|
-
on-input="
|
|
169
|
+
on-input="ui:slider_change:$value"
|
|
170
170
|
/>
|
|
171
171
|
</section>
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
```typescript
|
|
175
175
|
// Handler receives the full Action object — payload, context, and meta together
|
|
176
|
-
onAction('
|
|
176
|
+
onAction('ui:slider_change', (action) => {
|
|
177
177
|
if (action.context === 'volume') audioService.setVolume(Number(action.payload));
|
|
178
178
|
if (action.context === 'brightness') displayService.setBrightness(Number(action.payload));
|
|
179
179
|
});
|
|
@@ -392,7 +392,7 @@ Flux implements a **strict layered architecture** where each layer has a single
|
|
|
392
392
|
│ • Dispatches Actions via on-<event> attributes │
|
|
393
393
|
│ • Never manipulates state directly │
|
|
394
394
|
└──────────────────┬────────────────────────────────────────┘
|
|
395
|
-
│ on-click="add_to_cart:42"
|
|
395
|
+
│ on-click="ui:add_to_cart:42"
|
|
396
396
|
▼
|
|
397
397
|
┌───────────────────────────────────────────────────────────┐
|
|
398
398
|
│ ACTION LAYER │
|
|
@@ -406,7 +406,7 @@ Flux implements a **strict layered architecture** where each layer has a single
|
|
|
406
406
|
│ • Resolves payload ($value, $formdata) │
|
|
407
407
|
│ • Dispatches full Action {type, payload, context, meta} │
|
|
408
408
|
└──────────────────┬────────────────────────────────────────┘
|
|
409
|
-
│ dispatchAction({type: 'add_to_cart', payload: 42, context: 'cart'})
|
|
409
|
+
│ dispatchAction({type: 'ui:add_to_cart', payload: 42, context: 'cart'})
|
|
410
410
|
▼
|
|
411
411
|
┌───────────────────────────────────────────────────────────┐
|
|
412
412
|
│ CONTROLLER LAYER │
|
|
@@ -480,8 +480,8 @@ interface Action<K extends keyof ActionRecord> {
|
|
|
480
480
|
This unified structure replaces the previous two-argument `(id, payload)` API. Every handler now receives the full picture:
|
|
481
481
|
|
|
482
482
|
```typescript
|
|
483
|
-
onAction('add_to_cart', (action) => {
|
|
484
|
-
console.log(action.type); // 'add_to_cart'
|
|
483
|
+
onAction('ui:add_to_cart', (action) => {
|
|
484
|
+
console.log(action.type); // 'ui:add_to_cart'
|
|
485
485
|
console.log(action.payload); // {productId: 42, qty: 1} — fully typed
|
|
486
486
|
console.log(action.context); // 'product-list' — from [action-context] ancestor
|
|
487
487
|
console.log(action.meta); // {traceId: '…'} — set by modifiers, or undefined
|
|
@@ -501,7 +501,7 @@ registerModifier('trace', (_event, _element, action) => {
|
|
|
501
501
|
```
|
|
502
502
|
|
|
503
503
|
```html
|
|
504
|
-
<button on-click="submit_order:42; trace">Place Order</button>
|
|
504
|
+
<button on-click="ui:submit_order:42; trace">Place Order</button>
|
|
505
505
|
```
|
|
506
506
|
|
|
507
507
|
---
|
|
@@ -546,9 +546,9 @@ dispatchPageReady();
|
|
|
546
546
|
// src/actions.ts
|
|
547
547
|
declare module '@alwatr/flux' {
|
|
548
548
|
interface ActionRecord {
|
|
549
|
-
increment: void;
|
|
550
|
-
decrement: void;
|
|
551
|
-
set_count: number;
|
|
549
|
+
'ui:increment': void;
|
|
550
|
+
'ui:decrement': void;
|
|
551
|
+
'ui:set_count': number;
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
```
|
|
@@ -572,16 +572,16 @@ export const counterSignal = createStateSignal({
|
|
|
572
572
|
import {onAction} from '@alwatr/flux';
|
|
573
573
|
import {counterSignal} from './state.js';
|
|
574
574
|
|
|
575
|
-
onAction('increment', () => {
|
|
575
|
+
onAction('ui:increment', () => {
|
|
576
576
|
counterSignal.update((count) => count + 1);
|
|
577
577
|
});
|
|
578
578
|
|
|
579
|
-
onAction('decrement', () => {
|
|
579
|
+
onAction('ui:decrement', () => {
|
|
580
580
|
counterSignal.update((count) => count - 1);
|
|
581
581
|
});
|
|
582
582
|
|
|
583
583
|
// Handler receives the full Action object — payload is typed from ActionRecord
|
|
584
|
-
onAction('set_count', (action) => {
|
|
584
|
+
onAction('ui:set_count', (action) => {
|
|
585
585
|
counterSignal.set(action.payload); // action.payload: number
|
|
586
586
|
});
|
|
587
587
|
```
|
|
@@ -597,11 +597,11 @@ onAction('set_count', (action) => {
|
|
|
597
597
|
Counter:
|
|
598
598
|
<span id="count">0</span>
|
|
599
599
|
</h1>
|
|
600
|
-
<button on-click="decrement">-</button>
|
|
601
|
-
<button on-click="increment">+</button>
|
|
600
|
+
<button on-click="ui:decrement">-</button>
|
|
601
|
+
<button on-click="ui:increment">+</button>
|
|
602
602
|
<input
|
|
603
603
|
type="number"
|
|
604
|
-
on-input="set_count:$value"
|
|
604
|
+
on-input="ui:set_count:$value"
|
|
605
605
|
value="0"
|
|
606
606
|
/>
|
|
607
607
|
</div>
|
|
@@ -755,7 +755,7 @@ setupActionDelegation([...DEFAULT_DELEGATED_EVENTS, 'keydown', 'focus']);
|
|
|
755
755
|
Subscribes to a typed action. The handler receives the full `Action<K>` object.
|
|
756
756
|
|
|
757
757
|
```typescript
|
|
758
|
-
const sub = onAction('add_to_cart', (action) => {
|
|
758
|
+
const sub = onAction('ui:add_to_cart', (action) => {
|
|
759
759
|
cartService.add(action.payload.productId, action.payload.qty);
|
|
760
760
|
console.log(action.context); // e.g. 'product-list' or undefined
|
|
761
761
|
console.log(action.meta); // any metadata set by modifiers
|
|
@@ -770,12 +770,12 @@ Dispatches a typed action programmatically. Takes a full `Action<K>` object.
|
|
|
770
770
|
|
|
771
771
|
```typescript
|
|
772
772
|
dispatchAction({type: 'navigate', payload: '/home'});
|
|
773
|
-
dispatchAction({type: '
|
|
773
|
+
dispatchAction({type: 'auth_expired', payload: undefined}); // void payload
|
|
774
774
|
|
|
775
775
|
// With context and meta
|
|
776
776
|
dispatchAction({
|
|
777
|
-
type: '
|
|
778
|
-
payload:
|
|
777
|
+
type: 'upload_complete',
|
|
778
|
+
payload: fileId,
|
|
779
779
|
context: 'product-list',
|
|
780
780
|
meta: {source: 'recommendation'},
|
|
781
781
|
});
|
|
@@ -799,7 +799,7 @@ registerModifier('trace', (_event, _element, action) => {
|
|
|
799
799
|
```
|
|
800
800
|
|
|
801
801
|
```html
|
|
802
|
-
<button on-click="delete_item:42; confirm,trace">Delete</button>
|
|
802
|
+
<button on-click="ui:delete_item:42; confirm,trace">Delete</button>
|
|
803
803
|
```
|
|
804
804
|
|
|
805
805
|
#### `registerPayloadResolver(name, resolver)`
|
|
@@ -814,7 +814,7 @@ registerPayloadResolver('$data-id', (_event, element) => {
|
|
|
814
814
|
|
|
815
815
|
```html
|
|
816
816
|
<button
|
|
817
|
-
on-click="select:$data-id"
|
|
817
|
+
on-click="ui:select:$data-id"
|
|
818
818
|
data-id="42"
|
|
819
819
|
>
|
|
820
820
|
Select
|
|
@@ -1210,9 +1210,9 @@ const status = (isLoading: boolean) => html`
|
|
|
1210
1210
|
// actions.ts
|
|
1211
1211
|
declare module '@alwatr/flux' {
|
|
1212
1212
|
interface ActionRecord {
|
|
1213
|
-
'add_todo': string;
|
|
1214
|
-
'toggle_todo': number;
|
|
1215
|
-
'remove_todo': number;
|
|
1213
|
+
'ui:add_todo': string;
|
|
1214
|
+
'ui:toggle_todo': number;
|
|
1215
|
+
'ui:remove_todo': number;
|
|
1216
1216
|
}
|
|
1217
1217
|
}
|
|
1218
1218
|
|
|
@@ -1236,14 +1236,14 @@ import {todosSignal} from './state.js';
|
|
|
1236
1236
|
|
|
1237
1237
|
let nextId = 1;
|
|
1238
1238
|
|
|
1239
|
-
onAction('add_todo', (action) => {
|
|
1239
|
+
onAction('ui:add_todo', (action) => {
|
|
1240
1240
|
todosSignal.update((todos) => [
|
|
1241
1241
|
...todos,
|
|
1242
1242
|
{id: nextId++, text: action.payload, done: false},
|
|
1243
1243
|
]);
|
|
1244
1244
|
});
|
|
1245
1245
|
|
|
1246
|
-
onAction('toggle_todo', (action) => {
|
|
1246
|
+
onAction('ui:toggle_todo', (action) => {
|
|
1247
1247
|
todosSignal.update((todos) =>
|
|
1248
1248
|
todos.map((todo) =>
|
|
1249
1249
|
todo.id === action.payload ? {...todo, done: !todo.done} : todo
|
|
@@ -1251,13 +1251,13 @@ onAction('toggle_todo', (action) => {
|
|
|
1251
1251
|
);
|
|
1252
1252
|
});
|
|
1253
1253
|
|
|
1254
|
-
onAction('remove_todo', (action) => {
|
|
1254
|
+
onAction('ui:remove_todo', (action) => {
|
|
1255
1255
|
todosSignal.update((todos) => todos.filter((t) => t.id !== action.payload));
|
|
1256
1256
|
});
|
|
1257
1257
|
|
|
1258
1258
|
// view.html
|
|
1259
1259
|
<div id="app">
|
|
1260
|
-
<input id="new-todo" on-change="add_todo:$value" placeholder="What needs to be done?" />
|
|
1260
|
+
<input id="new-todo" on-change="ui:add_todo:$value" placeholder="What needs to be done?" />
|
|
1261
1261
|
<ul id="todo-list"></ul>
|
|
1262
1262
|
</div>
|
|
1263
1263
|
|
|
@@ -1276,10 +1276,10 @@ todosSignal.subscribe((todos) => {
|
|
|
1276
1276
|
<input
|
|
1277
1277
|
type="checkbox"
|
|
1278
1278
|
.checked=${todo.done}
|
|
1279
|
-
on-change="toggle_todo:${todo.id}"
|
|
1279
|
+
on-change="ui:toggle_todo:${todo.id}"
|
|
1280
1280
|
/>
|
|
1281
1281
|
<span style="${todo.done ? 'text-decoration: line-through' : ''}">${todo.text}</span>
|
|
1282
|
-
<button on-click="remove_todo:${todo.id}">×</button>
|
|
1282
|
+
<button on-click="ui:remove_todo:${todo.id}">×</button>
|
|
1283
1283
|
</li>
|
|
1284
1284
|
`)}
|
|
1285
1285
|
`,
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* 📦 @alwatr/flux v9.
|
|
1
|
+
/* 📦 @alwatr/flux v9.20.0 */
|
|
2
2
|
export*from"@alwatr/signal";export*from"@alwatr/action";export*from"@alwatr/directive";export*from"@alwatr/embedded-data";export*from"@alwatr/render-state";export*from"@alwatr/local-storage";export*from"@alwatr/session-storage";export*from"@alwatr/page-ready";import{html as e,render as t,noChange as a,nothing as p}from"lit-html";import{ifDefined as n}from"lit-html/directives/if-defined.js";import{cache as g}from"lit-html/directives/cache.js";import{classMap as i}from"lit-html/directives/class-map.js";import{when as s}from"lit-html/directives/when.js";export{s as when,t as render,p as nothing,a as noChange,n as ifDefined,e as html,i as classMap,g as cache};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=FFDF9C9E1A81FDA864756E2164756E21
|
|
5
5
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"/**\n * Curated re-exports from `lit-html` for use within `@alwatr/flux`.\n *\n * Only the subset of `lit-html` APIs that are commonly needed in a Flux-based\n * application is exported here. This keeps the public surface minimal and\n * avoids pulling in advanced directive utilities that most consumers never use.\n *\n * **Exported APIs:**\n * - `html` — tagged template literal that produces a `TemplateResult`\n * - `render` — renders a `TemplateResult` into a DOM container\n * - `noChange` — sentinel that tells lit-html to leave the current part value unchanged\n * - `nothing` — sentinel that renders nothing (removes the node/attribute)\n * - `ifDefined` — renders a value only when it is not `undefined`\n * - `cache` — caches rendered templates to avoid re-parsing on state changes\n * - `classMap` — efficiently sets/removes CSS classes from an object map\n * - `when` — conditional rendering helper (`when(condition, trueCase, falseCase)`)\n *\n * @example\n * ```typescript\n * import {html, render, classMap, when} from '@alwatr/flux';\n *\n * const template = (isActive: boolean) => html`\n * <div class=${classMap({active: isActive, hidden: !isActive})}>\n * ${when(isActive, () => html`<span>Active</span>`, () => html`<span>Inactive</span>`)}\n * </div>\n * `;\n *\n * render(template(true), document.getElementById('app')!);\n * ```\n */\nexport {html, render, noChange, nothing} from 'lit-html';\n// export {Directive, PartType, directive} from 'lit-html/directive.js';\n// export {AsyncDirective} from 'lit-html/async-directive.js';\n// export {unsafeSVG} from 'lit-html/directives/unsafe-svg.js';\nexport {ifDefined} from 'lit-html/directives/if-defined.js';\nexport {cache} from 'lit-html/directives/cache.js';\nexport {classMap} from 'lit-html/directives/class-map.js';\nexport {when} from 'lit-html/directives/when.js';\n\n// export type {Part, PartInfo} from 'lit-html/directive.js';\n// export type {LitUnstable} from 'lit-html';\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": ";AAGA,4BACA,4BACA,+BACA,mCACA,kCACA,mCACA,qCACA,gCCoBA,eAAQ,YAAM,cAAQ,aAAU,iBAIhC,oBAAQ,0CACR,gBAAQ,qCACR,mBAAQ,yCACR,eAAQ",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "FFDF9C9E1A81FDA864756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwatr/flux",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.20.0",
|
|
4
4
|
"description": "UI and reactive library bundle for ECMAScript (JavaScript/TypeScript) projects — signals, actions, directives, and storage.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "S. Ali Mihandoost <ali.mihandoost@gmail.com> (https://ali.mihandoost.com)",
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
"sideEffects": false,
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@alwatr/action": "9.
|
|
25
|
-
"@alwatr/directive": "9.
|
|
26
|
-
"@alwatr/embedded-data": "9.19.
|
|
24
|
+
"@alwatr/action": "9.20.0",
|
|
25
|
+
"@alwatr/directive": "9.20.0",
|
|
26
|
+
"@alwatr/embedded-data": "9.19.1",
|
|
27
27
|
"@alwatr/local-storage": "9.16.0",
|
|
28
|
-
"@alwatr/page-ready": "9.
|
|
28
|
+
"@alwatr/page-ready": "9.20.0",
|
|
29
29
|
"@alwatr/render-state": "9.16.0",
|
|
30
30
|
"@alwatr/session-storage": "9.16.0",
|
|
31
|
-
"@alwatr/signal": "9.
|
|
31
|
+
"@alwatr/signal": "9.20.0",
|
|
32
32
|
"@alwatr/type-helper": "9.14.0",
|
|
33
33
|
"lit-html": "^3.3.2"
|
|
34
34
|
},
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"ui",
|
|
84
84
|
"unidirectional-data-flow"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "6e47fd80a2da33bb78e12b1d51258f11e2caec72"
|
|
87
87
|
}
|