@ngstato/angular 0.1.2 → 0.1.3

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "lib": {
4
+ "entryFile": "src/index.ts"
5
+ },
6
+ "dest": "dist"
7
+ }
package/package.json CHANGED
@@ -1,36 +1,25 @@
1
1
  {
2
2
  "name": "@ngstato/angular",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
- "description": "Stato — Angular adapter with native Signals",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
14
- }
15
- },
5
+ "description": "ngStato — Angular adapter with native Signals",
16
6
  "scripts": {
17
- "build": "tsup",
18
- "test": "vitest run",
19
- "dev": "tsup --watch"
7
+ "build": "ng-packagr -p ng-package.json",
8
+ "test": "vitest run",
9
+ "dev": "ng-packagr -p ng-package.json --watch"
20
10
  },
21
11
  "peerDependencies": {
12
+ "@angular/core": ">=17.0.0",
22
13
  "@angular/common": ">=17.0.0",
23
- "@angular/core": ">=17.0.0"
24
- },
25
- "dependencies": {
26
- "@ngstato/angular": "^0.1.2",
27
- "@ngstato/core": "^0.1.2"
14
+ "@ngstato/core": "^0.1.2"
28
15
  },
29
16
  "devDependencies": {
30
- "@angular/common": "^18.2.14",
31
- "@angular/core": "^17.0.0",
32
- "tsup": "^8.0.0",
33
- "typescript": "^5.4.0",
34
- "vitest": "^1.6.0"
17
+ "ng-packagr": "^18.0.0",
18
+ "@angular/compiler-cli": "^18.0.0",
19
+ "@angular/compiler": "^18.0.0",
20
+ "@angular/common": "^18.0.0",
21
+ "typescript": "~5.5.0",
22
+ "tsup": "^8.0.0",
23
+ "vitest": "^1.6.0"
35
24
  }
36
25
  }
package/dist/index.d.mts DELETED
@@ -1,50 +0,0 @@
1
- import * as _angular_core from '@angular/core';
2
- import { Type, OnInit, OnDestroy } from '@angular/core';
3
- import { StatoConfig, StatoStoreConfig, ActionLog } from '@ngstato/core';
4
-
5
- declare function injectStore<T>(store: Type<T>): T;
6
-
7
- interface StatoAngularConfig {
8
- http?: StatoConfig;
9
- devtools?: boolean;
10
- }
11
- declare function provideStato(config?: StatoAngularConfig): _angular_core.EnvironmentProviders;
12
-
13
- declare function createAngularStore<S extends object>(config: S & StatoStoreConfig<S>): any;
14
-
15
- declare class StatoDevToolsComponent implements OnInit, OnDestroy {
16
- private config;
17
- private unsub?;
18
- isOpen: _angular_core.WritableSignal<boolean>;
19
- isMinimized: _angular_core.WritableSignal<boolean>;
20
- activeTab: _angular_core.WritableSignal<"actions" | "state">;
21
- logs: _angular_core.WritableSignal<ActionLog[]>;
22
- selectedLog: _angular_core.WritableSignal<ActionLog | null>;
23
- posX: _angular_core.WritableSignal<number>;
24
- posY: _angular_core.WritableSignal<number>;
25
- panelWidth: _angular_core.WritableSignal<number>;
26
- panelHeight: _angular_core.WritableSignal<number>;
27
- private isDragging;
28
- private isResizing;
29
- private dragOffsetX;
30
- private dragOffsetY;
31
- private startW;
32
- private startH;
33
- private startX;
34
- private startY;
35
- private boundMouseMove;
36
- private boundMouseUp;
37
- ngOnInit(): void;
38
- ngOnDestroy(): void;
39
- toggle(): void;
40
- toggleMinimize(): void;
41
- clear(): void;
42
- selectLog(log: ActionLog): void;
43
- formatTime(iso: string): string;
44
- onDragStart(e: MouseEvent): void;
45
- onResizeStart(e: MouseEvent): void;
46
- onMouseMove(e: MouseEvent): void;
47
- onMouseUp(): void;
48
- }
49
-
50
- export { type StatoAngularConfig, StatoDevToolsComponent, createAngularStore, injectStore, provideStato };
package/dist/index.js DELETED
@@ -1,542 +0,0 @@
1
- 'use strict';
2
-
3
- var core = require('@angular/core');
4
- var core$1 = require('@ngstato/core');
5
- var common = require('@angular/common');
6
-
7
- var __defProp = Object.defineProperty;
8
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
- function injectStore(store) {
10
- return core.inject(store);
11
- }
12
- __name(injectStore, "injectStore");
13
- var STATO_CONFIG = new core.InjectionToken("STATO_CONFIG");
14
- function provideStato(config = {}) {
15
- if (config.http) {
16
- core$1.configureHttp(config.http);
17
- }
18
- if (config.devtools && core.isDevMode()) {
19
- console.info("%c[Stato] \u{1F6E0} DevTools activ\xE9s", "background:#1e40af;color:white;padding:4px 8px;border-radius:4px;font-weight:bold");
20
- core$1.devTools.open();
21
- }
22
- return core.makeEnvironmentProviders([
23
- {
24
- provide: STATO_CONFIG,
25
- useValue: config
26
- }
27
- ]);
28
- }
29
- __name(provideStato, "provideStato");
30
- function _ts_decorate(decorators, target, key, desc) {
31
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
32
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
33
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
34
- return c > 3 && r && Object.defineProperty(target, key, r), r;
35
- }
36
- __name(_ts_decorate, "_ts_decorate");
37
- function createAngularStore(config) {
38
- const coreStore = core$1.createStore(config);
39
- const signals = {};
40
- const initialState = coreStore.getState();
41
- for (const key of Object.keys(initialState)) {
42
- signals[key] = core.signal(initialState[key]);
43
- }
44
- coreStore.subscribe((newState) => {
45
- for (const key of Object.keys(newState)) {
46
- if (signals[key]) {
47
- signals[key].set(newState[key]);
48
- }
49
- }
50
- });
51
- const angularStore = {
52
- __store__: coreStore.__store__
53
- };
54
- for (const key of Object.keys(initialState)) {
55
- Object.defineProperty(angularStore, key, {
56
- get: /* @__PURE__ */ __name(() => signals[key], "get"),
57
- enumerable: true,
58
- configurable: true
59
- });
60
- }
61
- const { computed: computedConfig } = config;
62
- if (computedConfig) {
63
- for (const key of Object.keys(computedConfig)) {
64
- const computedSignal = core.computed(() => coreStore[key]);
65
- Object.defineProperty(angularStore, key, {
66
- get: /* @__PURE__ */ __name(() => computedSignal, "get"),
67
- enumerable: true,
68
- configurable: true
69
- });
70
- }
71
- }
72
- const { actions } = config;
73
- if (actions) {
74
- for (const name of Object.keys(actions)) {
75
- angularStore[name] = (...args) => coreStore.__store__.dispatch(name, ...args);
76
- }
77
- }
78
- const { hooks } = config;
79
- if (hooks?.onInit) {
80
- hooks.onInit(angularStore);
81
- }
82
- angularStore.__destroy__ = () => {
83
- coreStore.__store__.destroy(angularStore);
84
- };
85
- return angularStore;
86
- }
87
- __name(createAngularStore, "createAngularStore");
88
- var StatoStoreBase = class {
89
- static {
90
- __name(this, "StatoStoreBase");
91
- }
92
- storeInstance;
93
- initStore(config) {
94
- this.storeInstance = createAngularStore(config);
95
- for (const key of Object.keys(this.storeInstance)) {
96
- if (key !== "__store__" && key !== "__destroy__") {
97
- Object.defineProperty(this, key, {
98
- get: /* @__PURE__ */ __name(() => this.storeInstance[key], "get"),
99
- enumerable: true,
100
- configurable: true
101
- });
102
- }
103
- }
104
- const { actions } = config;
105
- if (actions) {
106
- for (const name of Object.keys(actions)) {
107
- Object.defineProperty(this, name, {
108
- get: /* @__PURE__ */ __name(() => this.storeInstance[name], "get"),
109
- enumerable: true,
110
- configurable: true
111
- });
112
- }
113
- }
114
- }
115
- ngOnDestroy() {
116
- this.storeInstance?.__destroy__();
117
- }
118
- };
119
- StatoStoreBase = _ts_decorate([
120
- core.Injectable()
121
- ], StatoStoreBase);
122
- function _ts_decorate2(decorators, target, key, desc) {
123
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
124
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
125
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
126
- return c > 3 && r && Object.defineProperty(target, key, r), r;
127
- }
128
- __name(_ts_decorate2, "_ts_decorate");
129
- exports.StatoDevToolsComponent = class StatoDevToolsComponent {
130
- static {
131
- __name(this, "StatoDevToolsComponent");
132
- }
133
- config = core.inject(STATO_CONFIG, {
134
- optional: true
135
- });
136
- unsub;
137
- // State UI
138
- isOpen = core.signal(false);
139
- isMinimized = core.signal(false);
140
- activeTab = core.signal("actions");
141
- logs = core.signal([]);
142
- selectedLog = core.signal(null);
143
- // Position et taille
144
- posX = core.signal(24);
145
- posY = core.signal(window.innerHeight - 500);
146
- panelWidth = core.signal(420);
147
- panelHeight = core.signal(460);
148
- // Drag state
149
- isDragging = false;
150
- isResizing = false;
151
- dragOffsetX = 0;
152
- dragOffsetY = 0;
153
- startW = 0;
154
- startH = 0;
155
- startX = 0;
156
- startY = 0;
157
- // Bound listeners
158
- boundMouseMove = this.onMouseMove.bind(this);
159
- boundMouseUp = this.onMouseUp.bind(this);
160
- ngOnInit() {
161
- this.unsub = core$1.devTools.subscribe((state) => {
162
- this.logs.set(state.logs);
163
- this.isOpen.set(state.isOpen);
164
- });
165
- document.addEventListener("mousemove", this.boundMouseMove);
166
- document.addEventListener("mouseup", this.boundMouseUp);
167
- }
168
- ngOnDestroy() {
169
- this.unsub?.();
170
- document.removeEventListener("mousemove", this.boundMouseMove);
171
- document.removeEventListener("mouseup", this.boundMouseUp);
172
- }
173
- // ── Toggle ─────────────────────────────────────────
174
- toggle() {
175
- core$1.devTools.toggle();
176
- }
177
- toggleMinimize() {
178
- this.isMinimized.update((v) => !v);
179
- }
180
- clear() {
181
- core$1.devTools.clear();
182
- this.selectedLog.set(null);
183
- }
184
- selectLog(log) {
185
- this.selectedLog.set(this.selectedLog()?.id === log.id ? null : log);
186
- }
187
- formatTime(iso) {
188
- return new Date(iso).toTimeString().slice(0, 8);
189
- }
190
- // ── Drag ───────────────────────────────────────────
191
- onDragStart(e) {
192
- if (e.target.classList.contains("btn-icon")) return;
193
- this.isDragging = true;
194
- this.dragOffsetX = e.clientX - this.posX();
195
- this.dragOffsetY = e.clientY - this.posY();
196
- e.preventDefault();
197
- }
198
- // ── Resize ─────────────────────────────────────────
199
- onResizeStart(e) {
200
- this.isResizing = true;
201
- this.startW = this.panelWidth();
202
- this.startH = this.panelHeight();
203
- this.startX = e.clientX;
204
- this.startY = e.clientY;
205
- e.preventDefault();
206
- e.stopPropagation();
207
- }
208
- // ── Mouse Move ─────────────────────────────────────
209
- onMouseMove(e) {
210
- if (this.isDragging) {
211
- this.posX.set(Math.max(0, e.clientX - this.dragOffsetX));
212
- this.posY.set(Math.max(0, e.clientY - this.dragOffsetY));
213
- }
214
- if (this.isResizing) {
215
- const newW = Math.max(300, this.startW + e.clientX - this.startX);
216
- const newH = Math.max(200, this.startH + e.clientY - this.startY);
217
- this.panelWidth.set(newW);
218
- this.panelHeight.set(newH);
219
- }
220
- }
221
- // ── Mouse Up ───────────────────────────────────────
222
- onMouseUp() {
223
- this.isDragging = false;
224
- this.isResizing = false;
225
- }
226
- };
227
- exports.StatoDevToolsComponent = _ts_decorate2([
228
- core.Component({
229
- selector: "ngstato-devtools",
230
- standalone: true,
231
- imports: [
232
- common.CommonModule
233
- ],
234
- template: `
235
- <!-- Bouton flottant -->
236
- @if (!isOpen()) {
237
- <button class="devtools-fab" (click)="toggle()">
238
- \u{1F6E0} Stato
239
- </button>
240
- }
241
-
242
- <!-- Panel -->
243
- @if (isOpen()) {
244
- <div
245
- class="devtools-panel"
246
- [class.devtools-panel--minimized]="isMinimized()"
247
- [style.left.px]="posX()"
248
- [style.top.px]="posY()"
249
- [style.width.px]="isMinimized() ? 200 : panelWidth()"
250
- [style.height]="isMinimized() ? 'auto' : panelHeight() + 'px'"
251
- >
252
-
253
- <!-- Header \u2014 draggable -->
254
- <div
255
- class="devtools-header"
256
- (mousedown)="onDragStart($event)"
257
- >
258
- <span class="devtools-title">\u{1F6E0} Stato</span>
259
- <div class="devtools-header-actions">
260
- @if (!isMinimized()) {
261
- <button class="btn-icon" (click)="clear()" title="Vider">\u{1F5D1}</button>
262
- }
263
- <button class="btn-icon" (click)="toggleMinimize()" title="Minimiser/Agrandir">
264
- {{ isMinimized() ? '\u25B2' : '\u25BC' }}
265
- </button>
266
- <button class="btn-icon" (click)="toggle()" title="Fermer">\u2715</button>
267
- </div>
268
- </div>
269
-
270
- <!-- Resize handle \u2014 coin bas droite -->
271
- @if (!isMinimized()) {
272
- <div
273
- class="devtools-resize"
274
- (mousedown)="onResizeStart($event)"
275
- >\u22BF</div>
276
- }
277
-
278
- @if (!isMinimized()) {
279
-
280
- <!-- Tabs -->
281
- <div class="devtools-tabs">
282
- <button
283
- class="tab"
284
- [class.tab--active]="activeTab() === 'actions'"
285
- (click)="activeTab.set('actions')"
286
- >
287
- Actions ({{ logs().length }})
288
- </button>
289
- <button
290
- class="tab"
291
- [class.tab--active]="activeTab() === 'state'"
292
- (click)="activeTab.set('state')"
293
- >
294
- State
295
- </button>
296
- </div>
297
-
298
- <!-- Tab Actions -->
299
- @if (activeTab() === 'actions') {
300
- <div class="devtools-content">
301
- @if (!logs().length) {
302
- <div class="devtools-empty">Aucune action pour l'instant</div>
303
- }
304
- @for (log of logs(); track log.id) {
305
- <div
306
- class="log-item"
307
- [class.log-item--error]="log.status === 'error'"
308
- (click)="selectLog(log)"
309
- >
310
- <div class="log-item__left">
311
- <span class="log-status">{{ log.status === 'success' ? '\u2713' : '\u2717' }}</span>
312
- <span class="log-name">{{ log.name }}</span>
313
- </div>
314
- <div class="log-item__right">
315
- @if (log.status === 'error') {
316
- <span class="log-error-badge">erreur</span>
317
- } @else {
318
- <span class="log-duration">{{ log.duration }}ms</span>
319
- }
320
- <span class="log-time">{{ formatTime(log.at) }}</span>
321
- </div>
322
- </div>
323
-
324
- @if (selectedLog()?.id === log.id) {
325
- <div class="log-detail">
326
- @if (log.error) {
327
- <div class="log-detail__error">{{ log.error }}</div>
328
- }
329
- <div class="log-detail__section">
330
- <span class="log-detail__label">Avant</span>
331
- <pre>{{ log.prevState | json }}</pre>
332
- </div>
333
- <div class="log-detail__section">
334
- <span class="log-detail__label">Apr\xE8s</span>
335
- <pre>{{ log.nextState | json }}</pre>
336
- </div>
337
- </div>
338
- }
339
- }
340
- </div>
341
- }
342
-
343
- <!-- Tab State -->
344
- @if (activeTab() === 'state') {
345
- <div class="devtools-content">
346
- @if (logs().length) {
347
- <pre class="state-view">{{ logs()[0].nextState | json }}</pre>
348
- } @else {
349
- <div class="devtools-empty">Aucun state disponible</div>
350
- }
351
- </div>
352
- }
353
- }
354
-
355
- </div>
356
- }
357
- `,
358
- styles: [
359
- `
360
- .devtools-fab {
361
- position: fixed;
362
- bottom: 1.5rem;
363
- left: 1.5rem;
364
- background: #1e293b;
365
- color: white;
366
- border: none;
367
- border-radius: 999px;
368
- padding: 0.5rem 1rem;
369
- font-size: 0.85rem;
370
- font-weight: 600;
371
- cursor: pointer;
372
- z-index: 9999;
373
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
374
- transition: background 0.15s;
375
- }
376
- .devtools-fab:hover { background: #334155; }
377
-
378
- .devtools-panel {
379
- position: fixed;
380
- background: #0f172a;
381
- border-radius: 12px;
382
- box-shadow: 0 8px 32px rgba(0,0,0,0.4);
383
- z-index: 9999;
384
- display: flex;
385
- flex-direction: column;
386
- overflow: hidden;
387
- font-family: 'Courier New', monospace;
388
- min-width: 200px;
389
- min-height: 40px;
390
- }
391
-
392
- .devtools-panel--minimized {
393
- border-radius: 8px;
394
- }
395
-
396
- .devtools-header {
397
- display: flex;
398
- justify-content: space-between;
399
- align-items: center;
400
- padding: 0.6rem 0.75rem;
401
- background: #1e293b;
402
- border-bottom: 1px solid #334155;
403
- cursor: grab;
404
- user-select: none;
405
- }
406
- .devtools-header:active { cursor: grabbing; }
407
-
408
- .devtools-title {
409
- color: #e2e8f0;
410
- font-size: 0.82rem;
411
- font-weight: 600;
412
- font-family: system-ui;
413
- }
414
-
415
- .devtools-header-actions { display: flex; gap: 0.25rem; }
416
-
417
- .btn-icon {
418
- background: transparent;
419
- color: #64748b;
420
- border: none;
421
- cursor: pointer;
422
- font-size: 0.8rem;
423
- padding: 0.15rem 0.35rem;
424
- border-radius: 4px;
425
- line-height: 1;
426
- }
427
- .btn-icon:hover { background: #334155; color: white; }
428
-
429
- .devtools-resize {
430
- position: absolute;
431
- bottom: 2px;
432
- right: 4px;
433
- color: #334155;
434
- font-size: 0.9rem;
435
- cursor: nwse-resize;
436
- user-select: none;
437
- line-height: 1;
438
- }
439
- .devtools-resize:hover { color: #64748b; }
440
-
441
- .devtools-tabs {
442
- display: flex;
443
- background: #1e293b;
444
- border-bottom: 1px solid #334155;
445
- }
446
- .tab {
447
- padding: 0.4rem 0.75rem;
448
- background: transparent;
449
- color: #64748b;
450
- border: none;
451
- cursor: pointer;
452
- font-size: 0.78rem;
453
- font-family: system-ui;
454
- }
455
- .tab:hover { color: #e2e8f0; }
456
- .tab--active { color: #3b82f6; border-bottom: 2px solid #3b82f6; }
457
-
458
- .devtools-content {
459
- overflow-y: auto;
460
- flex: 1;
461
- padding: 0.25rem 0;
462
- }
463
-
464
- .devtools-empty {
465
- padding: 2rem;
466
- text-align: center;
467
- color: #475569;
468
- font-size: 0.78rem;
469
- font-family: system-ui;
470
- }
471
-
472
- .log-item {
473
- display: flex;
474
- justify-content: space-between;
475
- align-items: center;
476
- padding: 0.35rem 0.75rem;
477
- cursor: pointer;
478
- border-bottom: 1px solid #1e293b;
479
- }
480
- .log-item:hover { background: #1e293b; }
481
- .log-item--error { background: #1a0a0a; }
482
-
483
- .log-item__left { display: flex; align-items: center; gap: 0.4rem; overflow: hidden; }
484
- .log-item__right { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }
485
-
486
- .log-status { font-size: 0.72rem; color: #22c55e; flex-shrink: 0; }
487
- .log-item--error .log-status { color: #ef4444; }
488
- .log-name { color: #e2e8f0; font-size: 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
489
- .log-duration { color: #64748b; font-size: 0.7rem; }
490
- .log-time { color: #475569; font-size: 0.68rem; }
491
-
492
- .log-error-badge {
493
- background: #7f1d1d;
494
- color: #fca5a5;
495
- font-size: 0.68rem;
496
- padding: 0.1rem 0.35rem;
497
- border-radius: 4px;
498
- }
499
-
500
- .log-detail {
501
- background: #0a0f1a;
502
- padding: 0.6rem 0.75rem;
503
- border-left: 3px solid #3b82f6;
504
- margin: 0 0.4rem 0.4rem;
505
- border-radius: 0 4px 4px 0;
506
- }
507
- .log-detail__error { color: #fca5a5; font-size: 0.72rem; margin-bottom: 0.4rem; }
508
- .log-detail__section { margin-bottom: 0.4rem; }
509
- .log-detail__label {
510
- color: #64748b;
511
- font-size: 0.68rem;
512
- display: block;
513
- margin-bottom: 0.2rem;
514
- font-family: system-ui;
515
- }
516
- pre {
517
- color: #86efac;
518
- font-size: 0.7rem;
519
- margin: 0;
520
- white-space: pre-wrap;
521
- word-break: break-all;
522
- max-height: 140px;
523
- overflow-y: auto;
524
- }
525
- .state-view {
526
- color: #86efac;
527
- font-size: 0.7rem;
528
- padding: 0.75rem;
529
- margin: 0;
530
- white-space: pre-wrap;
531
- word-break: break-all;
532
- }
533
- `
534
- ]
535
- })
536
- ], exports.StatoDevToolsComponent);
537
-
538
- exports.createAngularStore = createAngularStore;
539
- exports.injectStore = injectStore;
540
- exports.provideStato = provideStato;
541
- //# sourceMappingURL=index.js.map
542
- //# sourceMappingURL=index.js.map