@tmjeee/w-lib 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+
9
+ ## [0.1.1] - 2026-06-01
10
+ - added `template-selection` , a convenient Angular template marker
11
+ - separate each utilities into it's own example file
12
+
8
13
  ## [0.1.0] - 2026-05-29
9
14
  - added initial version of
10
15
  - event emitter
package/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@tmjeee/w-lib.svg)](https://www.npmjs.com/package/@tmjeee/w-lib)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- Disclaimer: Contains codes from [jyoung4242](https://github.com/jyoung4242/Game-Dev-Library).
7
6
 
8
7
  ## Development
9
8
  See [here](./README_DEV.md) for more info.
@@ -21,7 +20,7 @@ npm install @tmjeee/w-lib
21
20
  This package is **ESM-only**.
22
21
 
23
22
 
24
- ### loading-state
23
+ ### loading-state (Angular)
25
24
  ```typescript
26
25
  import {createLoadingState} from '@tmjeee/w-lib';
27
26
 
@@ -36,7 +35,7 @@ const isLoading = loadingState.is('assets'); // signal<boolean> - true when load
36
35
  loadingState.set('assets', false); // explicitly mark 'asset' as false
37
36
  ```
38
37
 
39
- ### Finite state machine
38
+ ### Finite state machine (Generic)
40
39
  ```typescript
41
40
  import {FsmState, Fsm} from '@tmjeee/w-lib';
42
41
 
@@ -79,7 +78,7 @@ import {FsmState, Fsm} from '@tmjeee/w-lib';
79
78
  ```
80
79
 
81
80
 
82
- ### State Management
81
+ ### State Management (Generic)
83
82
  ```typescript
84
83
  const store = createStateStore<State>({
85
84
  name: 'jim',
@@ -115,7 +114,7 @@ import {FsmState, Fsm} from '@tmjeee/w-lib';
115
114
  ```
116
115
 
117
116
 
118
- ### Event Emitter
117
+ ### Event Emitter (Generic)
119
118
  ```typescript
120
119
  const emitter1 = new JsEventEmitter();
121
120
  const emitter2 = new JsEventEmitter();
@@ -135,6 +134,107 @@ import {FsmState, Fsm} from '@tmjeee/w-lib';
135
134
 
136
135
 
137
136
 
137
+ ### TemplateSelection Directive (Angular)
138
+
139
+ A lightweight directive that marks a template (or element) with a name. This allows you to define multiple named templates and then query + render them manually at runtime.
140
+
141
+ It is especially useful when you want to let a component support multiple "slots" or conditional template rendering without hardcoding them.
142
+
143
+ #### Import
144
+
145
+ ```ts
146
+ import { TemplateSelection } from '@tmjeee/w-lib';
147
+ ```
148
+
149
+ #### Supported Syntax
150
+
151
+ You can use it in two ways:
152
+
153
+ ```html
154
+ <!-- Recommended: on ng-template -->
155
+ <ng-template templateSelection="header">Header content</ng-template>
156
+ <ng-template templateSelection="footer">Footer content</ng-template>
157
+
158
+ <!-- Also supported: structural directive syntax -->
159
+ <div *templateSelection="'sidebar'">Sidebar content</div>
160
+ ```
161
+
162
+ You can also bind the name dynamically:
163
+
164
+ ```html
165
+ <ng-template [templateSelection]="templateName">...</ng-template>
166
+ ```
167
+
168
+ #### Querying Templates
169
+
170
+ Use Angular's `viewChildren` or `contentChildren` to collect the templates:
171
+
172
+ ```ts
173
+ @Component({...})
174
+ export class MyComponent {
175
+ // Use viewChildren when templates are defined inside this component
176
+ templates = viewChildren(TemplateSelection);
177
+
178
+ // Use contentChildren when accepting templates via content projection
179
+ // projectedTemplates = contentChildren(TemplateSelection);
180
+ }
181
+ ```
182
+
183
+ #### Full Example
184
+
185
+ ```ts
186
+ import { Component, viewChildren, ViewContainerRef, inject, afterNextRender } from '@angular/core';
187
+ import { TemplateSelection } from '@tmjeee/w-lib';
188
+
189
+ @Component({
190
+ selector: 'my-component',
191
+ standalone: true,
192
+ imports: [TemplateSelection],
193
+ template: `
194
+ <ng-template templateSelection="header">
195
+ <h1>My Header</h1>
196
+ </ng-template>
197
+
198
+ <div *templateSelection="'content'">
199
+ Main content here
200
+ </div>
201
+ `
202
+ })
203
+ export class MyComponent {
204
+ private vcr = inject(ViewContainerRef);
205
+ templates = viewChildren(TemplateSelection);
206
+
207
+ constructor() {
208
+ afterNextRender(() => {
209
+ const headerTpl = this.templates()
210
+ .find(t => t.name() === 'header')
211
+ ?.templateRef;
212
+
213
+ if (headerTpl) {
214
+ this.vcr.createEmbeddedView(headerTpl);
215
+ }
216
+ });
217
+ }
218
+
219
+ getTemplate(name: string) {
220
+ return this.templates().find(t => t.name() === name)?.templateRef;
221
+ }
222
+ }
223
+ ```
224
+
225
+ You can then use the retrieved `TemplateRef` with `*ngTemplateOutlet` or `ViewContainerRef.createEmbeddedView()`.
226
+
227
+ #### Notes
228
+
229
+ - The directive is **standalone**.
230
+ - Use `viewChildren(TemplateSelection)` for templates defined inside the component.
231
+ - Use `contentChildren(TemplateSelection)` when the templates are provided by the parent via content projection.
232
+
233
+
234
+ ## Disclaimer
235
+
236
+ Disclaimer: Contains codes from [jyoung4242](https://github.com/jyoung4242/Game-Dev-Library).
237
+
138
238
  ## License
139
239
 
140
240
  MIT © 2026 tmjeee
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Signal } from "@angular/core";
1
+ import * as _angular_core0 from "@angular/core";
2
+ import { Signal, TemplateRef } from "@angular/core";
2
3
  import { Subject } from "rxjs";
3
4
 
4
5
  //#region src/loading-state.d.ts
@@ -140,5 +141,64 @@ declare class FsmState {
140
141
  update(..._params: any): void | Promise<void>;
141
142
  }
142
143
  //#endregion
143
- export { BatchContext, ChangePayload, EventEmitter, EventEmitterHandler, EventEmitterSubscription, Fsm, FsmResult, FsmState, JsEventEmitter, LoadingKey, Path, PathValue, RxEventEmitter, StateStore, createLoadingState, createStateStore };
144
+ //#region src/template-selection.d.ts
145
+ /**
146
+ * A directive that marks a template (or element) with a name so it can be
147
+ * queried and rendered manually.
148
+ *
149
+ * This is useful in two main scenarios:
150
+ * - Defining multiple named templates inside a component and choosing which one to render at runtime.
151
+ * - Accepting named templates from a parent component via content projection.
152
+ *
153
+ * ## Supported Syntaxes
154
+ *
155
+ * ```html
156
+ * <!-- On ng-template (recommended for pure templates) -->
157
+ * <ng-template templateSelection="header">...</ng-template>
158
+ * <ng-template templateSelection="footer">...</ng-template>
159
+ *
160
+ * <!-- Using structural directive syntax (also supported) -->
161
+ * <div *templateSelection="'sidebar'">Sidebar content</div>
162
+ * ```
163
+ *
164
+ * ## Consumption Example
165
+ *
166
+ * You can query the templates using either `viewChildren()` or `contentChildren()`,
167
+ * depending on your use case:
168
+ *
169
+ * ```ts
170
+ * @Component({...})
171
+ * export class MyComponent {
172
+ * // Use viewChildren() if the templates are defined inside this component's own template
173
+ * internalTemplates = viewChildren(TemplateSelection);
174
+ *
175
+ * // Use contentChildren() if you want to accept named templates from the parent via content projection
176
+ * projectedTemplates = contentChildren(TemplateSelection);
177
+ *
178
+ * getTemplate(name: string): TemplateRef<any> | undefined {
179
+ * return this.internalTemplates()
180
+ * .find(t => t.name() === name)
181
+ * ?.templateRef;
182
+ * }
183
+ * }
184
+ * ```
185
+ *
186
+ * Then in the template:
187
+ * ```html
188
+ * <ng-container *ngTemplateOutlet="getTemplate('header')"></ng-container>
189
+ * ```
190
+ */
191
+ declare class TemplateSelection {
192
+ /**
193
+ * The name used to identify this template.
194
+ * Can be bound as `templateSelection="myName"` or `[templateSelection]="someVariable"`.
195
+ */
196
+ name: _angular_core0.InputSignal<string>;
197
+ /**
198
+ * The underlying TemplateRef that can be used with *ngTemplateOutlet or ViewContainerRef.
199
+ */
200
+ readonly templateRef: TemplateRef<any>;
201
+ }
202
+ //#endregion
203
+ export { BatchContext, ChangePayload, EventEmitter, EventEmitterHandler, EventEmitterSubscription, Fsm, FsmResult, FsmState, JsEventEmitter, LoadingKey, Path, PathValue, RxEventEmitter, StateStore, TemplateSelection, createLoadingState, createStateStore };
144
204
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/loading-state.ts","../src/event-emitter.ts","../src/state-management.ts","../src/finite-state-machine.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/loading-state.ts","../src/event-emitter.ts","../src/state-management.ts","../src/finite-state-machine.ts","../src/template-selection.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { computed, signal } from "@angular/core";
1
+ import { Directive, TemplateRef, computed, inject, input, signal } from "@angular/core";
2
2
  import { Subject } from "rxjs";
3
3
  import { take } from "rxjs/operators";
4
4
 
@@ -424,5 +424,22 @@ var FsmState = class {
424
424
  };
425
425
 
426
426
  //#endregion
427
- export { Fsm, FsmState, JsEventEmitter, RxEventEmitter, createLoadingState, createStateStore };
427
+ //#region src/template-selection.ts
428
+ var TemplateSelection = @Directive({
429
+ selector: "[templateSelection]",
430
+ standalone: true
431
+ }) class {
432
+ /**
433
+ * The name used to identify this template.
434
+ * Can be bound as `templateSelection="myName"` or `[templateSelection]="someVariable"`.
435
+ */
436
+ name = input.required({ alias: "templateSelection" });
437
+ /**
438
+ * The underlying TemplateRef that can be used with *ngTemplateOutlet or ViewContainerRef.
439
+ */
440
+ templateRef = inject(TemplateRef);
441
+ };
442
+
443
+ //#endregion
444
+ export { Fsm, FsmState, JsEventEmitter, RxEventEmitter, TemplateSelection, createLoadingState, createStateStore };
428
445
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/loading-state.ts","../src/event-emitter.ts","../src/state-management.ts","../src/finite-state-machine.ts"],"sourcesContent":["import { computed, signal, Signal } from '@angular/core';\n\n/**\n * A lightweight utility for managing per-action loading states using signals.\n *\n * Philosophy:\n * - Most errors should propagate to GlobalErrorHandler.\n * - This utility helps manage UI loading states cleanly without forcing try/catch everywhere.\n * - Use it when you need to disable buttons / show spinners during async actions.\n *\n * Recommended usage:\n *\n * const loading = createLoadingState<'creatingBoard' | 'deletingBoard'>();\n *\n * async createBoard() {\n * const title = await openDialog();\n * if (!title) return;\n *\n * await loading.withLoading('creatingBoard', async () => {\n * const board = await this.boardService.createBoard(...);\n * this.router.navigate(...);\n * });\n * }\n *\n * In template:\n * <button [disabled]=\"loading.is('creatingBoard')()\">\n * {{ loading.is('creatingBoard')() ? 'Creating...' : 'Create Board' }}\n * </button>\n */\nexport function createLoadingState<T extends string = string>() {\n const loadingMap = signal<Partial<Record<T, boolean>>>({});\n const signalCache = new Map<T, Signal<boolean>>();\n\n /**\n * Returns a reactive signal indicating if a specific action is loading.\n * The returned signal is stable (same reference) for the same key.\n */\n const is = (key: T): Signal<boolean> => {\n if (!signalCache.has(key)) {\n signalCache.set(\n key,\n computed(() => loadingMap()[key] ?? false)\n );\n }\n return signalCache.get(key)!;\n };\n\n /**\n * Manually set the loading state for a key.\n */\n const set = (key: T, value: boolean): void => {\n loadingMap.update((map) => ({ ...map, [key]: value }));\n };\n\n /**\n * Runs an async function while automatically managing the loading state.\n * Errors are allowed to propagate (as per project convention).\n */\n const withLoading = async <R>(key: T, fn: () => Promise<R>): Promise<R> => {\n set(key, true);\n try {\n return await fn();\n } finally {\n set(key, false);\n }\n };\n\n /**\n * Raw access to the loading map (rarely needed).\n */\n const states = loadingMap.asReadonly();\n\n return {\n is,\n set,\n withLoading,\n states,\n };\n}\n\n/**\n * Type helper for action loading keys.\n * Example: type UserAction = 'addingToWorkspace' | 'removingFromWorkspace';\n */\nexport type LoadingKey = string;\n","\nexport interface EventEmitterHandler<T> {\n (change:T):void;\n}\n\nexport interface EventEmitterSubscription {\n unsubscribe:()=>void;\n}\n\n\nexport interface EventEmitter<T> {\n emit(event: string, payload: T): void;\n on(event: string, handler: EventEmitterHandler<T>): void;\n off(event: string, handler?: EventEmitterHandler<T>): void;\n once(event: string, handler: EventEmitterHandler<T>): void;\n}\n\n// =============================================================\n// ============== RxJs =========================================\n// =============================================================\n\nimport {Subject} from 'rxjs';\nimport {take} from 'rxjs/operators';\n\nexport class RxEventEmitter<T> implements EventEmitter<T> {\n\n _listeners: Record<string, Subject<T>> = {};\n\n emit(event: string, payload: T): void {\n const handlers = this._listeners[event];\n if (handlers) {\n handlers.next(payload);\n }\n }\n on(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = new Subject();\n }\n this._listeners[event].subscribe(handler)\n }\n off(event: string, handler?: EventEmitterHandler<T>): void {\n const s = this._listeners[event];\n if (s) {\n this._listeners[event].complete();\n delete this._listeners[event];\n }\n }\n once(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = new Subject();\n }\n this._listeners[event].pipe(\n take(1)\n ).subscribe(handler);\n }\n}\n\n\n// =============================================================\n// ============== Js ===========================================\n// =============================================================\n\nexport class JsEventEmitter<T> implements EventEmitter<T> {\n\n _listeners: Record<string, EventEmitterHandler<T>[]> = {};\n\n emit(event: string, payload: T): void {\n const handlers = this._listeners[event];\n if (handlers && handlers.length) {\n handlers.forEach(h => {\n h(payload);\n })\n }\n }\n on(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n const exists = this._listeners[event].find(h => h == handler);\n if (!exists) {\n this._listeners[event].push(handler);\n }\n }\n off(event: string, handler?: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n if (handler) {\n const idx = this._listeners[event].findIndex(h => h == handler);\n if (idx >= 0) {\n this._listeners[event].splice(idx, 1);\n }\n } else {\n delete this._listeners[event];\n }\n }\n once(event: string, handler:EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n const onceOnlyHandler = (evt: T) => {\n try {\n handler(evt);\n } finally {\n this.off(event, onceOnlyHandler);\n }\n };\n this._listeners[event].push(onceOnlyHandler);\n }\n}","// ─── Path Typing ────────────────────────────────────────────────────────────\nimport {EventEmitter, JsEventEmitter} from './event-emitter';\n\ntype Primitive = string | number | boolean | null | undefined;\n\ntype PathsOf<T, Prefix extends string = \"\"> = T extends Primitive\n ? never\n : T extends Array<infer _>\n ? never\n : {\n [K in keyof T & string]: Prefix extends \"\"\n ? K | (T[K] extends Primitive ? never : PathsOf<T[K], K>)\n : `${Prefix}.${K}` | (T[K] extends Primitive ? never : PathsOf<T[K], `${Prefix}.${K}`>);\n }[keyof T & string];\n\nexport type Path<T> = PathsOf<T>;\n\nexport type PathValue<T, P extends string> = P extends keyof T\n ? T[P]\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? Rest extends Path<T[K]>\n ? PathValue<T[K], Rest>\n : never\n : never\n : never;\n\n// ─── Event Types ─────────────────────────────────────────────────────────────\n\nexport interface ChangePayload<State, V = unknown> {\n path: string;\n previousValue: V;\n value: V;\n previousState: Readonly<State>;\n state: Readonly<State>;\n}\n\ntype ChangeEventMap<State> = {\n change: ChangePayload<State>;\n [key: `change:${string}`]: ChangePayload<State>;\n};\n\n// ─── StateStore Interface ────────────────────────────────────────────────────\n\nexport interface StateStore<State extends object> {\n get(): Readonly<State>;\n get<K extends Path<State>>(path: K): Readonly<PathValue<State, K>>;\n select<T>(selector: (state: Readonly<State>) => T): Readonly<T>;\n\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void;\n update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void;\n patch(partial: DeepPartial<State>): void;\n batch(fn: (store: BatchContext<State>) => void): void;\n\n on<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void;\n off<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void;\n\n subscribe<K extends Path<State>>(path: K, handler: (payload: ChangePayload<State, PathValue<State, K>>) => void): () => void;\n\n serialize(): string;\n reset(): void;\n}\n\nexport interface BatchContext<State extends object> {\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void;\n update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void;\n patch(partial: DeepPartial<State>): void;\n}\n\ntype DeepPartial<T> = T extends Primitive ? T : { [K in keyof T]?: DeepPartial<T[K]> };\n\n// ─── Utility Helpers ─────────────────────────────────────────────────────────\n\nfunction parsePath(path: string): string[] {\n return path.split(\".\");\n}\n\nfunction deepFreeze<T>(obj: T): Readonly<T> {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.getOwnPropertyNames(obj).forEach(name => {\n const val = (obj as Record<string, unknown>)[name];\n if (val && typeof val === \"object\") deepFreeze(val);\n });\n return Object.freeze(obj);\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n if (Array.isArray(obj)) return (obj as unknown[]).map(deepClone) as unknown as T;\n const result = {} as Record<string, unknown>;\n for (const key of Object.keys(obj as object)) {\n result[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return result as T;\n}\n\nfunction getAtPath<T>(obj: T, segments: string[]): unknown {\n let current: unknown = obj;\n for (const seg of segments) {\n if (current === null || typeof current !== \"object\") {\n throw new Error(`Invalid path segment \"${seg}\": not an object`);\n }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n\nfunction setAtPath<T extends object>(obj: T, segments: string[], value: unknown): T {\n if (segments.length === 0) return value as T;\n const [head, ...tail] = segments;\n if (typeof obj !== \"object\" || obj === null) {\n throw new Error(`Cannot set path on non-object at segment \"${head}\"`);\n }\n const record = obj as Record<string, unknown>;\n const updated = { ...record };\n if (tail.length === 0) {\n updated[head] = value;\n } else {\n const child = record[head];\n if (child === null || typeof child !== \"object\") {\n throw new Error(`Path segment \"${head}\" is not an object`);\n }\n updated[head] = setAtPath(child as object, tail, value);\n }\n return updated as T;\n}\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (typeof a !== \"object\" || typeof b !== \"object\") return false;\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if ((a as Record<string, unknown>)[k] !== (b as Record<string, unknown>)[k]) return false;\n }\n return true;\n}\n\nfunction deepMerge<T extends object>(base: T, partial: DeepPartial<T>): T {\n const result = { ...base } as Record<string, unknown>;\n for (const key of Object.keys(partial as object)) {\n const pVal = (partial as Record<string, unknown>)[key];\n const bVal = (base as Record<string, unknown>)[key];\n if (\n pVal !== undefined &&\n pVal !== null &&\n typeof pVal === \"object\" &&\n !Array.isArray(pVal) &&\n bVal !== null &&\n typeof bVal === \"object\"\n ) {\n result[key] = deepMerge(bVal as object, pVal as DeepPartial<object>);\n } else if (pVal !== undefined) {\n result[key] = pVal;\n }\n }\n return result as T;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createStateStore<State extends object>(\n initialState: State, \n eventEmitter: EventEmitter<ChangePayload<State>> = new JsEventEmitter<ChangePayload<State>>()\n): StateStore<State> {\n\n const _initial: Readonly<State> = deepFreeze(deepClone(initialState));\n let _state: Readonly<State> = _initial;\n\n const _emitter = eventEmitter;\n\n function _emit(path: string, previousValue: unknown, value: unknown, previousState: Readonly<State>): void {\n const payload: ChangePayload<State> = {\n path,\n previousValue,\n value,\n previousState,\n state: _state,\n };\n _emitter.emit(\"change\", payload);\n _emitter.emit(`change:${path}` as `change:${string}`, payload);\n }\n\n function _applySet(currentState: Readonly<State>, segments: string[], value: unknown): Readonly<State> {\n return deepFreeze(setAtPath(deepClone(currentState), segments, value));\n }\n\n // Overloaded get\n function get(): Readonly<State>;\n function get<K extends Path<State>>(path: K): Readonly<PathValue<State, K>>;\n function get<K extends Path<State>>(path?: K): Readonly<State> | Readonly<PathValue<State, K>> {\n if (path === undefined) return _state;\n const segments = parsePath(path);\n const val = getAtPath(_state, segments);\n return deepFreeze(deepClone(val)) as Readonly<PathValue<State, K>>;\n }\n\n function select<T>(selector: (state: Readonly<State>) => T): Readonly<T> {\n const result = selector(_state);\n if (result !== null && typeof result === \"object\") {\n return deepFreeze(deepClone(result)) as Readonly<T>;\n }\n return result as Readonly<T>;\n }\n\n function set<K extends Path<State>>(path: K, value: PathValue<State, K>): void {\n const segments = parsePath(path);\n const previousValue = getAtPath(_state, segments);\n if (shallowEqual(previousValue, value)) return;\n const previousState = _state;\n _state = _applySet(_state, segments, value);\n _emit(path, previousValue, value, previousState);\n }\n\n function update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void {\n const segments = parsePath(path);\n const current = getAtPath(_state, segments) as PathValue<State, K>;\n const next = fn(deepClone(current));\n set(path, next);\n }\n\n function patch(partial: DeepPartial<State>): void {\n const merged = deepMerge(_state as State, partial);\n const nextState = deepFreeze(merged);\n const changedPaths: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", _state, nextState, changedPaths);\n if (changedPaths.length === 0) return;\n const previousState = _state;\n _state = nextState;\n for (const entry of changedPaths) {\n _emit(entry.path, entry.prev, entry.next, previousState);\n }\n }\n\n function collectChangedPaths(\n prefix: string,\n prev: unknown,\n next: unknown,\n out: Array<{ path: string; prev: unknown; next: unknown }>,\n ): void {\n if (prev === next) return;\n if (\n prev !== null &&\n next !== null &&\n typeof prev === \"object\" &&\n typeof next === \"object\" &&\n !Array.isArray(prev) &&\n !Array.isArray(next)\n ) {\n const allKeys = new Set([...Object.keys(prev as object), ...Object.keys(next as object)]);\n for (const k of allKeys) {\n const pv = (prev as Record<string, unknown>)[k];\n const nv = (next as Record<string, unknown>)[k];\n const childPath = prefix ? `${prefix}.${k}` : k;\n collectChangedPaths(childPath, pv, nv, out);\n }\n } else if (!shallowEqual(prev, next)) {\n out.push({ path: prefix, prev, next });\n }\n }\n\n function batch(fn: (ctx: BatchContext<State>) => void): void {\n let pendingState = _state;\n const changes: Array<{ path: string; prev: unknown; next: unknown; prevState: Readonly<State> }> = [];\n\n const ctx: BatchContext<State> = {\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void {\n const segments = parsePath(path);\n const previousValue = getAtPath(pendingState, segments);\n if (shallowEqual(previousValue, value)) return;\n const prevState = pendingState;\n pendingState = deepFreeze(setAtPath(deepClone(pendingState), segments, value));\n changes.push({ path, prev: previousValue, next: value, prevState });\n },\n update<K extends Path<State>>(path: K, fn2: (current: PathValue<State, K>) => PathValue<State, K>): void {\n const segments = parsePath(path);\n const current = getAtPath(pendingState, segments) as PathValue<State, K>;\n const next = fn2(deepClone(current));\n ctx.set(path, next);\n },\n patch(partial: DeepPartial<State>): void {\n const merged = deepFreeze(deepMerge(pendingState as State, partial));\n const changedPaths: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", pendingState, merged, changedPaths);\n if (changedPaths.length === 0) return;\n const prevState = pendingState;\n pendingState = merged;\n for (const entry of changedPaths) {\n changes.push({ path: entry.path, prev: entry.prev, next: entry.next, prevState });\n }\n },\n };\n\n fn(ctx);\n\n if (pendingState === _state) return;\n _state = pendingState;\n\n for (const change of changes) {\n _emit(change.path, change.prev, change.next, change.prevState);\n }\n }\n\n function on<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void {\n _emitter.on(event, handler as (payload: ChangeEventMap<State>[E]) => void);\n }\n\n function off<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void {\n _emitter.off(event, handler as (payload: ChangeEventMap<State>[E]) => void);\n }\n\n function subscribe<K extends Path<State>>(\n path: K,\n handler: (payload: ChangePayload<State, PathValue<State, K>>) => void,\n ): () => void {\n const eventName = `change:${path}` as `change:${string}`;\n const wrapped = (payload: ChangePayload<State>) => handler(payload as unknown as ChangePayload<State, PathValue<State, K>>);\n _emitter.on(eventName, wrapped);\n return () => _emitter.off(eventName, wrapped);\n }\n\n function serialize(): string {\n return JSON.stringify(_state);\n }\n\n function reset(): void {\n const previousState = _state;\n _state = _initial;\n const changes: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", previousState, _state, changes);\n for (const change of changes) {\n _emit(change.path, change.prev, change.next, previousState);\n }\n }\n\n return { get, select, set, update, patch, batch, on, off, subscribe, serialize, reset };\n}","export type FsmResult<T = void> = {\n success: boolean;\n message?: string;\n value?: T;\n};\n\nexport class Fsm {\n public states = new Map<string, FsmState>();\n public current: FsmState | null = null;\n public currentParams: any[] = [];\n public currentTime: number = 0;\n\n constructor() {}\n\n /** Register new states, returns array of registered ExState */\n register(...types: (string | FsmState)[]): FsmResult<FsmState[]> {\n const generatedStates: FsmState[] = [];\n\n for (const state of types) {\n const newState = typeof state === \"string\" ? new FsmState(state) : state;\n\n if (this.states.has(newState.name)) {\n console.warn(`State \"${newState.name}\" is already registered and will be overwritten.`);\n }\n\n this.states.set(newState.name, newState);\n generatedStates.push(newState);\n }\n\n return { success: true, value: generatedStates };\n }\n\n /** Change current state */\n set(state: string | FsmState, ...params: any[]): FsmResult<FsmState> | Promise<FsmResult<FsmState>> {\n const name = typeof state === \"string\" ? state : state.name;\n const next = this.states.get(name);\n\n if (!next) return { success: false, message: `State \"${name}\" not found` };\n\n const finalize = () => {\n this.current = next;\n this.currentParams = params;\n this.currentTime = Date.now();\n return { success: true, value: next };\n };\n\n // No current state, only enter next\n if (!this.current) {\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n }\n\n // Handle current exit\n const leaving = this.current.exit(next, ...params);\n if (leaving instanceof Promise) {\n return leaving.then(() => {\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n });\n }\n\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n }\n\n /** Check if a state is registered */\n has(state: string | FsmState): boolean {\n const name = typeof state === \"string\" ? state : state.name;\n return this.states.has(name);\n }\n\n /** Get current state */\n get(): FsmResult<FsmState> {\n if (!this.current) return { success: false, message: \"No state set\" };\n return { success: true, value: this.current };\n }\n\n /** Reset FSM */\n reset(): FsmResult<void> {\n this.current = null;\n this.currentParams = [];\n this.currentTime = 0;\n return { success: true };\n }\n\n /** Update current state */\n update(): FsmResult<void> | Promise<FsmResult<void>> {\n if (!this.current) return { success: false, message: \"No current state\" };\n\n const result = this.current.update(...this.currentParams);\n return result instanceof Promise ? result.then(() => ({ success: true })) : { success: true };\n }\n}\n\nexport class FsmState {\n constructor(public name: string) {}\n\n enter(_previous: FsmState | null, ..._params: any): void | Promise<void> {}\n exit(_next: FsmState | null, ..._params: any): void | Promise<void> {}\n update(..._params: any): void | Promise<void> {}\n}"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/loading-state.ts","../src/event-emitter.ts","../src/state-management.ts","../src/finite-state-machine.ts","../src/template-selection.ts"],"sourcesContent":["import { computed, signal, Signal } from '@angular/core';\n\n/**\n * A lightweight utility for managing per-action loading states using signals.\n *\n * Philosophy:\n * - Most errors should propagate to GlobalErrorHandler.\n * - This utility helps manage UI loading states cleanly without forcing try/catch everywhere.\n * - Use it when you need to disable buttons / show spinners during async actions.\n *\n * Recommended usage:\n *\n * const loading = createLoadingState<'creatingBoard' | 'deletingBoard'>();\n *\n * async createBoard() {\n * const title = await openDialog();\n * if (!title) return;\n *\n * await loading.withLoading('creatingBoard', async () => {\n * const board = await this.boardService.createBoard(...);\n * this.router.navigate(...);\n * });\n * }\n *\n * In template:\n * <button [disabled]=\"loading.is('creatingBoard')()\">\n * {{ loading.is('creatingBoard')() ? 'Creating...' : 'Create Board' }}\n * </button>\n */\nexport function createLoadingState<T extends string = string>() {\n const loadingMap = signal<Partial<Record<T, boolean>>>({});\n const signalCache = new Map<T, Signal<boolean>>();\n\n /**\n * Returns a reactive signal indicating if a specific action is loading.\n * The returned signal is stable (same reference) for the same key.\n */\n const is = (key: T): Signal<boolean> => {\n if (!signalCache.has(key)) {\n signalCache.set(\n key,\n computed(() => loadingMap()[key] ?? false)\n );\n }\n return signalCache.get(key)!;\n };\n\n /**\n * Manually set the loading state for a key.\n */\n const set = (key: T, value: boolean): void => {\n loadingMap.update((map) => ({ ...map, [key]: value }));\n };\n\n /**\n * Runs an async function while automatically managing the loading state.\n * Errors are allowed to propagate (as per project convention).\n */\n const withLoading = async <R>(key: T, fn: () => Promise<R>): Promise<R> => {\n set(key, true);\n try {\n return await fn();\n } finally {\n set(key, false);\n }\n };\n\n /**\n * Raw access to the loading map (rarely needed).\n */\n const states = loadingMap.asReadonly();\n\n return {\n is,\n set,\n withLoading,\n states,\n };\n}\n\n/**\n * Type helper for action loading keys.\n * Example: type UserAction = 'addingToWorkspace' | 'removingFromWorkspace';\n */\nexport type LoadingKey = string;\n","\nexport interface EventEmitterHandler<T> {\n (change:T):void;\n}\n\nexport interface EventEmitterSubscription {\n unsubscribe:()=>void;\n}\n\n\nexport interface EventEmitter<T> {\n emit(event: string, payload: T): void;\n on(event: string, handler: EventEmitterHandler<T>): void;\n off(event: string, handler?: EventEmitterHandler<T>): void;\n once(event: string, handler: EventEmitterHandler<T>): void;\n}\n\n// =============================================================\n// ============== RxJs =========================================\n// =============================================================\n\nimport {Subject} from 'rxjs';\nimport {take} from 'rxjs/operators';\n\nexport class RxEventEmitter<T> implements EventEmitter<T> {\n\n _listeners: Record<string, Subject<T>> = {};\n\n emit(event: string, payload: T): void {\n const handlers = this._listeners[event];\n if (handlers) {\n handlers.next(payload);\n }\n }\n on(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = new Subject();\n }\n this._listeners[event].subscribe(handler)\n }\n off(event: string, handler?: EventEmitterHandler<T>): void {\n const s = this._listeners[event];\n if (s) {\n this._listeners[event].complete();\n delete this._listeners[event];\n }\n }\n once(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = new Subject();\n }\n this._listeners[event].pipe(\n take(1)\n ).subscribe(handler);\n }\n}\n\n\n// =============================================================\n// ============== Js ===========================================\n// =============================================================\n\nexport class JsEventEmitter<T> implements EventEmitter<T> {\n\n _listeners: Record<string, EventEmitterHandler<T>[]> = {};\n\n emit(event: string, payload: T): void {\n const handlers = this._listeners[event];\n if (handlers && handlers.length) {\n handlers.forEach(h => {\n h(payload);\n })\n }\n }\n on(event: string, handler: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n const exists = this._listeners[event].find(h => h == handler);\n if (!exists) {\n this._listeners[event].push(handler);\n }\n }\n off(event: string, handler?: EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n if (handler) {\n const idx = this._listeners[event].findIndex(h => h == handler);\n if (idx >= 0) {\n this._listeners[event].splice(idx, 1);\n }\n } else {\n delete this._listeners[event];\n }\n }\n once(event: string, handler:EventEmitterHandler<T>): void {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n const onceOnlyHandler = (evt: T) => {\n try {\n handler(evt);\n } finally {\n this.off(event, onceOnlyHandler);\n }\n };\n this._listeners[event].push(onceOnlyHandler);\n }\n}","// ─── Path Typing ────────────────────────────────────────────────────────────\nimport {EventEmitter, JsEventEmitter} from './event-emitter';\n\ntype Primitive = string | number | boolean | null | undefined;\n\ntype PathsOf<T, Prefix extends string = \"\"> = T extends Primitive\n ? never\n : T extends Array<infer _>\n ? never\n : {\n [K in keyof T & string]: Prefix extends \"\"\n ? K | (T[K] extends Primitive ? never : PathsOf<T[K], K>)\n : `${Prefix}.${K}` | (T[K] extends Primitive ? never : PathsOf<T[K], `${Prefix}.${K}`>);\n }[keyof T & string];\n\nexport type Path<T> = PathsOf<T>;\n\nexport type PathValue<T, P extends string> = P extends keyof T\n ? T[P]\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? Rest extends Path<T[K]>\n ? PathValue<T[K], Rest>\n : never\n : never\n : never;\n\n// ─── Event Types ─────────────────────────────────────────────────────────────\n\nexport interface ChangePayload<State, V = unknown> {\n path: string;\n previousValue: V;\n value: V;\n previousState: Readonly<State>;\n state: Readonly<State>;\n}\n\ntype ChangeEventMap<State> = {\n change: ChangePayload<State>;\n [key: `change:${string}`]: ChangePayload<State>;\n};\n\n// ─── StateStore Interface ────────────────────────────────────────────────────\n\nexport interface StateStore<State extends object> {\n get(): Readonly<State>;\n get<K extends Path<State>>(path: K): Readonly<PathValue<State, K>>;\n select<T>(selector: (state: Readonly<State>) => T): Readonly<T>;\n\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void;\n update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void;\n patch(partial: DeepPartial<State>): void;\n batch(fn: (store: BatchContext<State>) => void): void;\n\n on<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void;\n off<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void;\n\n subscribe<K extends Path<State>>(path: K, handler: (payload: ChangePayload<State, PathValue<State, K>>) => void): () => void;\n\n serialize(): string;\n reset(): void;\n}\n\nexport interface BatchContext<State extends object> {\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void;\n update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void;\n patch(partial: DeepPartial<State>): void;\n}\n\ntype DeepPartial<T> = T extends Primitive ? T : { [K in keyof T]?: DeepPartial<T[K]> };\n\n// ─── Utility Helpers ─────────────────────────────────────────────────────────\n\nfunction parsePath(path: string): string[] {\n return path.split(\".\");\n}\n\nfunction deepFreeze<T>(obj: T): Readonly<T> {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.getOwnPropertyNames(obj).forEach(name => {\n const val = (obj as Record<string, unknown>)[name];\n if (val && typeof val === \"object\") deepFreeze(val);\n });\n return Object.freeze(obj);\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n if (Array.isArray(obj)) return (obj as unknown[]).map(deepClone) as unknown as T;\n const result = {} as Record<string, unknown>;\n for (const key of Object.keys(obj as object)) {\n result[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return result as T;\n}\n\nfunction getAtPath<T>(obj: T, segments: string[]): unknown {\n let current: unknown = obj;\n for (const seg of segments) {\n if (current === null || typeof current !== \"object\") {\n throw new Error(`Invalid path segment \"${seg}\": not an object`);\n }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n\nfunction setAtPath<T extends object>(obj: T, segments: string[], value: unknown): T {\n if (segments.length === 0) return value as T;\n const [head, ...tail] = segments;\n if (typeof obj !== \"object\" || obj === null) {\n throw new Error(`Cannot set path on non-object at segment \"${head}\"`);\n }\n const record = obj as Record<string, unknown>;\n const updated = { ...record };\n if (tail.length === 0) {\n updated[head] = value;\n } else {\n const child = record[head];\n if (child === null || typeof child !== \"object\") {\n throw new Error(`Path segment \"${head}\" is not an object`);\n }\n updated[head] = setAtPath(child as object, tail, value);\n }\n return updated as T;\n}\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (typeof a !== \"object\" || typeof b !== \"object\") return false;\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n for (const k of keysA) {\n if ((a as Record<string, unknown>)[k] !== (b as Record<string, unknown>)[k]) return false;\n }\n return true;\n}\n\nfunction deepMerge<T extends object>(base: T, partial: DeepPartial<T>): T {\n const result = { ...base } as Record<string, unknown>;\n for (const key of Object.keys(partial as object)) {\n const pVal = (partial as Record<string, unknown>)[key];\n const bVal = (base as Record<string, unknown>)[key];\n if (\n pVal !== undefined &&\n pVal !== null &&\n typeof pVal === \"object\" &&\n !Array.isArray(pVal) &&\n bVal !== null &&\n typeof bVal === \"object\"\n ) {\n result[key] = deepMerge(bVal as object, pVal as DeepPartial<object>);\n } else if (pVal !== undefined) {\n result[key] = pVal;\n }\n }\n return result as T;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createStateStore<State extends object>(\n initialState: State, \n eventEmitter: EventEmitter<ChangePayload<State>> = new JsEventEmitter<ChangePayload<State>>()\n): StateStore<State> {\n\n const _initial: Readonly<State> = deepFreeze(deepClone(initialState));\n let _state: Readonly<State> = _initial;\n\n const _emitter = eventEmitter;\n\n function _emit(path: string, previousValue: unknown, value: unknown, previousState: Readonly<State>): void {\n const payload: ChangePayload<State> = {\n path,\n previousValue,\n value,\n previousState,\n state: _state,\n };\n _emitter.emit(\"change\", payload);\n _emitter.emit(`change:${path}` as `change:${string}`, payload);\n }\n\n function _applySet(currentState: Readonly<State>, segments: string[], value: unknown): Readonly<State> {\n return deepFreeze(setAtPath(deepClone(currentState), segments, value));\n }\n\n // Overloaded get\n function get(): Readonly<State>;\n function get<K extends Path<State>>(path: K): Readonly<PathValue<State, K>>;\n function get<K extends Path<State>>(path?: K): Readonly<State> | Readonly<PathValue<State, K>> {\n if (path === undefined) return _state;\n const segments = parsePath(path);\n const val = getAtPath(_state, segments);\n return deepFreeze(deepClone(val)) as Readonly<PathValue<State, K>>;\n }\n\n function select<T>(selector: (state: Readonly<State>) => T): Readonly<T> {\n const result = selector(_state);\n if (result !== null && typeof result === \"object\") {\n return deepFreeze(deepClone(result)) as Readonly<T>;\n }\n return result as Readonly<T>;\n }\n\n function set<K extends Path<State>>(path: K, value: PathValue<State, K>): void {\n const segments = parsePath(path);\n const previousValue = getAtPath(_state, segments);\n if (shallowEqual(previousValue, value)) return;\n const previousState = _state;\n _state = _applySet(_state, segments, value);\n _emit(path, previousValue, value, previousState);\n }\n\n function update<K extends Path<State>>(path: K, fn: (current: PathValue<State, K>) => PathValue<State, K>): void {\n const segments = parsePath(path);\n const current = getAtPath(_state, segments) as PathValue<State, K>;\n const next = fn(deepClone(current));\n set(path, next);\n }\n\n function patch(partial: DeepPartial<State>): void {\n const merged = deepMerge(_state as State, partial);\n const nextState = deepFreeze(merged);\n const changedPaths: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", _state, nextState, changedPaths);\n if (changedPaths.length === 0) return;\n const previousState = _state;\n _state = nextState;\n for (const entry of changedPaths) {\n _emit(entry.path, entry.prev, entry.next, previousState);\n }\n }\n\n function collectChangedPaths(\n prefix: string,\n prev: unknown,\n next: unknown,\n out: Array<{ path: string; prev: unknown; next: unknown }>,\n ): void {\n if (prev === next) return;\n if (\n prev !== null &&\n next !== null &&\n typeof prev === \"object\" &&\n typeof next === \"object\" &&\n !Array.isArray(prev) &&\n !Array.isArray(next)\n ) {\n const allKeys = new Set([...Object.keys(prev as object), ...Object.keys(next as object)]);\n for (const k of allKeys) {\n const pv = (prev as Record<string, unknown>)[k];\n const nv = (next as Record<string, unknown>)[k];\n const childPath = prefix ? `${prefix}.${k}` : k;\n collectChangedPaths(childPath, pv, nv, out);\n }\n } else if (!shallowEqual(prev, next)) {\n out.push({ path: prefix, prev, next });\n }\n }\n\n function batch(fn: (ctx: BatchContext<State>) => void): void {\n let pendingState = _state;\n const changes: Array<{ path: string; prev: unknown; next: unknown; prevState: Readonly<State> }> = [];\n\n const ctx: BatchContext<State> = {\n set<K extends Path<State>>(path: K, value: PathValue<State, K>): void {\n const segments = parsePath(path);\n const previousValue = getAtPath(pendingState, segments);\n if (shallowEqual(previousValue, value)) return;\n const prevState = pendingState;\n pendingState = deepFreeze(setAtPath(deepClone(pendingState), segments, value));\n changes.push({ path, prev: previousValue, next: value, prevState });\n },\n update<K extends Path<State>>(path: K, fn2: (current: PathValue<State, K>) => PathValue<State, K>): void {\n const segments = parsePath(path);\n const current = getAtPath(pendingState, segments) as PathValue<State, K>;\n const next = fn2(deepClone(current));\n ctx.set(path, next);\n },\n patch(partial: DeepPartial<State>): void {\n const merged = deepFreeze(deepMerge(pendingState as State, partial));\n const changedPaths: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", pendingState, merged, changedPaths);\n if (changedPaths.length === 0) return;\n const prevState = pendingState;\n pendingState = merged;\n for (const entry of changedPaths) {\n changes.push({ path: entry.path, prev: entry.prev, next: entry.next, prevState });\n }\n },\n };\n\n fn(ctx);\n\n if (pendingState === _state) return;\n _state = pendingState;\n\n for (const change of changes) {\n _emit(change.path, change.prev, change.next, change.prevState);\n }\n }\n\n function on<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void {\n _emitter.on(event, handler as (payload: ChangeEventMap<State>[E]) => void);\n }\n\n function off<E extends keyof ChangeEventMap<State>>(event: E, handler: (payload: ChangeEventMap<State>[E]) => void): void {\n _emitter.off(event, handler as (payload: ChangeEventMap<State>[E]) => void);\n }\n\n function subscribe<K extends Path<State>>(\n path: K,\n handler: (payload: ChangePayload<State, PathValue<State, K>>) => void,\n ): () => void {\n const eventName = `change:${path}` as `change:${string}`;\n const wrapped = (payload: ChangePayload<State>) => handler(payload as unknown as ChangePayload<State, PathValue<State, K>>);\n _emitter.on(eventName, wrapped);\n return () => _emitter.off(eventName, wrapped);\n }\n\n function serialize(): string {\n return JSON.stringify(_state);\n }\n\n function reset(): void {\n const previousState = _state;\n _state = _initial;\n const changes: Array<{ path: string; prev: unknown; next: unknown }> = [];\n collectChangedPaths(\"\", previousState, _state, changes);\n for (const change of changes) {\n _emit(change.path, change.prev, change.next, previousState);\n }\n }\n\n return { get, select, set, update, patch, batch, on, off, subscribe, serialize, reset };\n}","export type FsmResult<T = void> = {\n success: boolean;\n message?: string;\n value?: T;\n};\n\nexport class Fsm {\n public states = new Map<string, FsmState>();\n public current: FsmState | null = null;\n public currentParams: any[] = [];\n public currentTime: number = 0;\n\n constructor() {}\n\n /** Register new states, returns array of registered ExState */\n register(...types: (string | FsmState)[]): FsmResult<FsmState[]> {\n const generatedStates: FsmState[] = [];\n\n for (const state of types) {\n const newState = typeof state === \"string\" ? new FsmState(state) : state;\n\n if (this.states.has(newState.name)) {\n console.warn(`State \"${newState.name}\" is already registered and will be overwritten.`);\n }\n\n this.states.set(newState.name, newState);\n generatedStates.push(newState);\n }\n\n return { success: true, value: generatedStates };\n }\n\n /** Change current state */\n set(state: string | FsmState, ...params: any[]): FsmResult<FsmState> | Promise<FsmResult<FsmState>> {\n const name = typeof state === \"string\" ? state : state.name;\n const next = this.states.get(name);\n\n if (!next) return { success: false, message: `State \"${name}\" not found` };\n\n const finalize = () => {\n this.current = next;\n this.currentParams = params;\n this.currentTime = Date.now();\n return { success: true, value: next };\n };\n\n // No current state, only enter next\n if (!this.current) {\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n }\n\n // Handle current exit\n const leaving = this.current.exit(next, ...params);\n if (leaving instanceof Promise) {\n return leaving.then(() => {\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n });\n }\n\n const entering = next.enter(this.current, ...params);\n return entering instanceof Promise ? entering.then(finalize) : finalize();\n }\n\n /** Check if a state is registered */\n has(state: string | FsmState): boolean {\n const name = typeof state === \"string\" ? state : state.name;\n return this.states.has(name);\n }\n\n /** Get current state */\n get(): FsmResult<FsmState> {\n if (!this.current) return { success: false, message: \"No state set\" };\n return { success: true, value: this.current };\n }\n\n /** Reset FSM */\n reset(): FsmResult<void> {\n this.current = null;\n this.currentParams = [];\n this.currentTime = 0;\n return { success: true };\n }\n\n /** Update current state */\n update(): FsmResult<void> | Promise<FsmResult<void>> {\n if (!this.current) return { success: false, message: \"No current state\" };\n\n const result = this.current.update(...this.currentParams);\n return result instanceof Promise ? result.then(() => ({ success: true })) : { success: true };\n }\n}\n\nexport class FsmState {\n constructor(public name: string) {}\n\n enter(_previous: FsmState | null, ..._params: any): void | Promise<void> {}\n exit(_next: FsmState | null, ..._params: any): void | Promise<void> {}\n update(..._params: any): void | Promise<void> {}\n}","import { Directive, TemplateRef, input, inject } from '@angular/core';\n\n/**\n * A directive that marks a template (or element) with a name so it can be\n * queried and rendered manually.\n *\n * This is useful in two main scenarios:\n * - Defining multiple named templates inside a component and choosing which one to render at runtime.\n * - Accepting named templates from a parent component via content projection.\n *\n * ## Supported Syntaxes\n *\n * ```html\n * <!-- On ng-template (recommended for pure templates) -->\n * <ng-template templateSelection=\"header\">...</ng-template>\n * <ng-template templateSelection=\"footer\">...</ng-template>\n *\n * <!-- Using structural directive syntax (also supported) -->\n * <div *templateSelection=\"'sidebar'\">Sidebar content</div>\n * ```\n *\n * ## Consumption Example\n *\n * You can query the templates using either `viewChildren()` or `contentChildren()`,\n * depending on your use case:\n *\n * ```ts\n * @Component({...})\n * export class MyComponent {\n * // Use viewChildren() if the templates are defined inside this component's own template\n * internalTemplates = viewChildren(TemplateSelection);\n *\n * // Use contentChildren() if you want to accept named templates from the parent via content projection\n * projectedTemplates = contentChildren(TemplateSelection);\n *\n * getTemplate(name: string): TemplateRef<any> | undefined {\n * return this.internalTemplates()\n * .find(t => t.name() === name)\n * ?.templateRef;\n * }\n * }\n * ```\n *\n * Then in the template:\n * ```html\n * <ng-container *ngTemplateOutlet=\"getTemplate('header')\"></ng-container>\n * ```\n */\n@Directive({\n selector: '[templateSelection]',\n standalone: true,\n})\nexport class TemplateSelection {\n /**\n * The name used to identify this template.\n * Can be bound as `templateSelection=\"myName\"` or `[templateSelection]=\"someVariable\"`.\n */\n name = input.required<string>({ alias: 'templateSelection' });\n\n /**\n * The underlying TemplateRef that can be used with *ngTemplateOutlet or ViewContainerRef.\n */\n readonly templateRef = inject(TemplateRef);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmjeee/w-lib",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A minimal, modern TypeScript library skeleton ready for publishing to npmjs.com. Includes helloWorld sample.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -66,6 +66,7 @@
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "^22.15.0",
69
+ "jsdom": "^29.1.1",
69
70
  "tsdown": "^0.20.3",
70
71
  "typescript": "^5.9.3",
71
72
  "vitest": "^4.0.8"