@ssv/ngx.command 4.0.0-dev.98 → 5.0.0-dev.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,21 +18,22 @@ npm install @ssv/ngx.command
18
18
 
19
19
  Choose the version corresponding to your Angular version:
20
20
 
21
- | Angular | library |
21
+ | library | Angular |
22
22
  | ------- | ------- |
23
- | 17+ | 4.x+ |
24
- | 17+ | 3.x+ |
25
- | 10+ | 2.x+ |
26
- | 4 to 9 | 1.x+ |
23
+ | 5.x+ | 17+ |
24
+ | 4.x+ | 17+ |
25
+ | 3.x+ | 17+ |
26
+ | 2.x+ | 10+ |
27
+ | 1.x+ | 4 to 9 |
27
28
 
28
29
 
29
30
  # Usage
30
31
 
31
32
  ## Command
32
- In order to start working with Command, you need to create a new instance of it.
33
+ Create a new instance of `Command`
33
34
 
34
35
  ```ts
35
- import { command, commandAsync } from "@ssv/ngx.command";
36
+ import { command } from "@ssv/ngx.command";
36
37
 
37
38
  const isValid = signal(false);
38
39
  const isValid$ = new BehaviorSubject(false);
@@ -41,12 +42,13 @@ const isValid$ = new BehaviorSubject(false);
41
42
  saveCmd = command(() => this.save(), isValid);
42
43
 
43
44
  // async - returns an observable/promise.
44
- saveCmd = commandAsync(() => Observable.timer(2000), isValid);
45
+ saveCmd = command(() => Observable.timer(2000), isValid);
45
46
 
46
47
  // can execute diff ways
47
48
  saveCmd = command(() => this.save(), () => isValid()); // reactive fn (signal)
48
49
  saveCmd = command(() => this.save(), isValid); // signal
49
50
  saveCmd = command(() => this.save(), isValid$); // rx
51
+ saveCmd = command(() => this.save(), false); // boolean (perma disabled)
50
52
  ```
51
53
 
52
54
  ## Command Attribute (Directive)
@@ -124,10 +126,10 @@ Command creator ref, directive which allows creating Command in the template and
124
126
  ```html
125
127
  @for (hero of heroes; track hero.key) {
126
128
  <div #actionCmd="ssvCommandRef" [ssvCommandRef]="{host: this, execute: removeHero$, canExecute: isValid$}" class="button-group">
127
- <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
129
+ <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="hero">
128
130
  Remove
129
131
  </button>
130
- <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
132
+ <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="hero">
131
133
  Remove
132
134
  </button>
133
135
  </div>
@@ -141,17 +143,30 @@ In order to use with `NgForm` easily, you can use the following utility method.
141
143
  This will make canExecute respond to `form.valid` and for `form.dirty` - also can optionally disable validity or dirty.
142
144
 
143
145
  ```ts
144
- import { commandAsync, canExecuteFromNgForm, canExecuteFromSignals } from "@ssv/ngx.command";
146
+ import { command, canExecuteFromNgForm, canExecuteFromSignals } from "@ssv/ngx.command";
145
147
 
146
- loginCmd = commandAsync(x => this.login(), canExecuteFromNgForm(this.form));
148
+ loginCmd = command(x => this.login(), canExecuteFromNgForm(this.form));
147
149
 
148
150
  // options - disable dirty check
149
- loginCmd = commandAsync(x => this.login(), canExecuteFromNgForm(this.form, {
151
+ loginCmd = command(x => this.login(), canExecuteFromNgForm(this.form, {
150
152
  dirty: false
151
153
  }));
152
154
 
153
155
  // similar functionality using custom signals (or form which provide signals)
154
- loginCmd = commandAsync(x => this.login(), canExecuteFromSignals({dirty: $dirty, valid: $valid}));
156
+ loginCmd = command(x => this.login(), canExecuteFromSignals({dirty: $dirty, valid: $valid}));
157
+ ```
158
+
159
+ ### Command Input (type)
160
+ Simplifies the definition when used as an input.
161
+
162
+ ```ts
163
+ // For a command with a single parameter:
164
+ readonly myCmd = input.required<CommandInput<MyType>>();
165
+ // For a command with multiple parameters:
166
+ readonly myCmd = input.required<CommandInput<[param1: string, param2: number]>>();
167
+
168
+ // instead of
169
+ readonly myCmd = input.required<Command<(param1: string, param2: number) => unknown>>();
155
170
  ```
156
171
 
157
172
 
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, assertInInjectionContext, inject, Injector, DestroyRef, signal, computed, isSignal, Renderer2, ElementRef, ChangeDetectorRef, input, effect, Directive, NgModule } from '@angular/core';
3
- import { Subject, Subscription, filter, tap, switchMap, of, finalize, take, catchError, EMPTY, concat, defer, map, distinctUntilChanged, combineLatest } from 'rxjs';
2
+ import { InjectionToken, assertInInjectionContext, inject, Injector, signal, computed, isSignal, Renderer2, ElementRef, ChangeDetectorRef, input, effect, Directive, NgModule } from '@angular/core';
3
+ import { isObservable, lastValueFrom, concat, defer, of, filter, map, distinctUntilChanged, combineLatest } from 'rxjs';
4
4
  import { toSignal } from '@angular/core/rxjs-interop';
5
5
  import { PristineChangeEvent, StatusChangeEvent } from '@angular/forms';
6
6
 
@@ -29,134 +29,87 @@ function provideSsvCommandOptions(options) {
29
29
  ];
30
30
  }
31
31
 
32
- /* eslint-disable @typescript-eslint/no-explicit-any */
33
- const COMMAND_ASYNC_DEFAULT_OPTIONS = { isAsync: true };
32
+ // todo: remove
34
33
  /** Creates an async {@link Command}. Must be used within an injection context.
35
- * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
34
+ * @deprecated Use {@link command} instead, as it handles both sync and async execute functions.
36
35
  */
37
- function commandAsync(execute, canExecute$, opts) {
38
- return command(execute, canExecute$, opts ? { ...opts, ...COMMAND_ASYNC_DEFAULT_OPTIONS } : COMMAND_ASYNC_DEFAULT_OPTIONS);
39
- }
40
- /** Creates a {@link Command}. Must be used within an injection context.
41
- * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
42
- */
43
- function command(execute, canExecute$, opts) {
36
+ const commandAsync = command;
37
+ /** Creates a {@link Command}. Must be used within an injection context (or the injector must be provided in the options). */
38
+ function command(execute, canExecute, opts) {
44
39
  if (!opts?.injector) {
45
40
  assertInInjectionContext(command);
46
41
  }
47
42
  const injector = opts?.injector ?? inject(Injector);
48
- const isAsync = opts?.isAsync ?? false;
49
- const destroyRef = injector.get(DestroyRef);
50
- const cmd = new Command(execute, canExecute$, isAsync, injector);
51
- cmd.autoDestroy = false;
52
- destroyRef.onDestroy(() => {
53
- // console.warn("[command::destroy]");
54
- cmd.destroy();
55
- });
43
+ const cmd = new Command(execute, canExecute, injector);
56
44
  return cmd;
57
45
  }
58
46
  /**
59
47
  * Command object used to encapsulate information which is needed to perform an action.
60
- *
61
48
  */
62
49
  class Command {
50
+ _execute;
63
51
  get isExecuting() { return this.$isExecuting(); }
64
52
  get canExecute() { return this.$canExecute(); }
65
53
  $isExecuting = signal(false, ...(ngDevMode ? [{ debugName: "$isExecuting" }] : []));
66
- $canExecute = computed(() => !this.$isExecuting() && this._$canExecute(), ...(ngDevMode ? [{ debugName: "$canExecute" }] : []));
67
- _$canExecute;
68
- autoDestroy = true;
69
- executionPipe$ = new Subject();
70
- executionPipe$$ = Subscription.EMPTY;
71
- subscribersCount = 0;
54
+ $canExecute = computed(() => !this.$isExecuting() && this.#canExecute(), ...(ngDevMode ? [{ debugName: "$canExecute" }] : []));
55
+ #canExecute;
72
56
  /**
73
57
  * Creates an instance of Command.
74
58
  *
75
- * @param execute Execute function to invoke - use `isAsync: true` when `Observable<any>`.
59
+ * @param execute Execute function to invoke.
76
60
  * @param canExecute Observable which determines whether it can execute or not.
77
- * @param isAsync Indicates that the execute function is async e.g. Observable.
78
61
  * @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.
79
62
  */
80
- constructor(execute, canExecute$, isAsync, injector) {
81
- if (canExecute$) {
82
- const canExecute = typeof canExecute$ === "function"
83
- ? computed(canExecute$)
84
- : canExecute$;
85
- this._$canExecute = isSignal(canExecute)
86
- ? canExecute
87
- : toSignal(canExecute, { initialValue: false, injector });
88
- }
89
- else {
90
- this._$canExecute = signal(true, ...(ngDevMode ? [{ debugName: "_$canExecute" }] : []));
91
- }
92
- this.executionPipe$$ = this.buildExecutionPipe(execute, isAsync).subscribe();
63
+ constructor(_execute, canExecute, injector) {
64
+ this._execute = _execute;
65
+ this.#canExecute = this.#buildCanExecuteSignal(canExecute, injector);
93
66
  }
94
- /** Execute function to invoke. */
67
+ /** Execute function to invoke. Returns Promise if the execute function returns Observable, otherwise returns the original type. */
95
68
  execute(...args) {
96
- // console.warn("[command::execute]", args);
97
- this.executionPipe$.next(args);
98
- }
99
- /** Disposes all resources held by subscriptions. */
100
- destroy() {
101
- // console.warn("[command::destroy]");
102
- this.executionPipe$$.unsubscribe();
103
- }
104
- subscribe() {
105
- this.subscribersCount++;
106
- }
107
- unsubscribe() {
108
- this.subscribersCount--;
109
- // console.log("[command::unsubscribe]", { autoDestroy: this.autoDestroy, subscribersCount: this.subscribersCount });
110
- if (this.autoDestroy && this.subscribersCount <= 0) {
111
- this.destroy();
69
+ if (!this.$canExecute()) {
70
+ throw new Error("Command cannot execute in its current state.");
71
+ // return Promise.reject() as ReturnType<TExecute>;
112
72
  }
113
- }
114
- buildExecutionPipe(execute, isAsync) {
115
- let pipe$ = this.executionPipe$.pipe(
116
- // tap(x => console.warn(">>>> executionPipe", this._canExecute)),
117
- filter(() => this.$canExecute()), tap(() => {
118
- // console.log("[command::executionPipe$] do#1 - set execute", { args: x });
119
- this.$isExecuting.set(true);
120
- }));
121
- const execFn = isAsync
122
- ? switchMap(args => {
123
- if (args) {
124
- return execute(...args);
125
- }
126
- return execute();
127
- })
128
- : tap((args) => {
129
- if (args) {
130
- execute(...args);
131
- return;
132
- }
133
- execute();
134
- });
135
- pipe$ = pipe$.pipe(switchMap(args => of(args).pipe(execFn, finalize(() => {
136
- // console.log("[command::executionPipe$] finalize inner#1 - set idle");
73
+ this.$isExecuting.set(true);
74
+ // console.warn("[command::execute]", args);
75
+ try {
76
+ const result = args.length > 0 ? this._execute(...args) : this._execute();
77
+ if (isObservable(result)) {
78
+ // Convert observable to promise using lastValueFrom
79
+ // This ensures fire-and-forget execution without requiring manual subscription
80
+ // Use defaultValue to handle empty observables (those that complete without emitting)
81
+ const promise = lastValueFrom(result, { defaultValue: undefined })
82
+ .finally(() => this.$isExecuting.set(false));
83
+ return promise;
84
+ }
85
+ else if (result instanceof Promise) {
86
+ // Return promise with proper cleanup
87
+ return result
88
+ .finally(() => this.$isExecuting.set(false));
89
+ }
90
+ // Sync execution
137
91
  this.$isExecuting.set(false);
138
- }), take(1), catchError(error => {
139
- console.error("Unhandled execute error", error);
140
- return EMPTY;
141
- }))), tap(() => {
142
- // console.log("[command::executionPipe$] tap#2 - set idle");
143
- // this._isExecuting$.next(false);
92
+ return result;
93
+ }
94
+ catch (err) {
144
95
  this.$isExecuting.set(false);
145
- }));
146
- return pipe$;
96
+ throw err;
97
+ }
147
98
  }
148
- }
149
- /**
150
- * Async Command object used to encapsulate information which is needed to perform an action,
151
- * which takes an execute function as Observable/Promise.
152
- * @deprecated Use {@link commandAsync} instead.
153
- */
154
- class CommandAsync extends Command {
155
- /**
156
- * @deprecated Use {@link commandAsync} instead to create an instance.
157
- */
158
- constructor(execute, canExecute$) {
159
- super(execute, canExecute$, true);
99
+ #buildCanExecuteSignal(canExecute, injector) {
100
+ if (canExecute === undefined) {
101
+ return computed(() => true);
102
+ }
103
+ if (isSignal(canExecute)) {
104
+ return canExecute;
105
+ }
106
+ if (typeof canExecute === "function") {
107
+ return computed(canExecute);
108
+ }
109
+ if (typeof canExecute === "boolean") {
110
+ return computed(() => canExecute);
111
+ }
112
+ return toSignal(canExecute, { initialValue: false, injector });
160
113
  }
161
114
  }
162
115
 
@@ -202,6 +155,8 @@ function isAssumedType(x) {
202
155
  return x !== null && typeof x === "object";
203
156
  }
204
157
 
158
+ const NAME_CAMEL$1 = "ssvCommand";
159
+ // let nextUniqueId = 0;
205
160
  /**
206
161
  * Controls the state of a component in sync with `Command`.
207
162
  *
@@ -222,13 +177,20 @@ function isAssumedType(x) {
222
177
  * This is useful for collections (loops) or using multiple actions with different args.
223
178
  * *NOTE: This will share the `isExecuting` when used with multiple controls.*
224
179
  *
225
- * #### With single param
180
+ * #### With single param (direct)
226
181
  *
227
182
  * ```html
228
- * <button [ssvCommand]="saveCmd" [ssvCommandParams]="{id: 1}">Save</button>
183
+ * <button [ssvCommand]="saveCmd" [ssvCommandParams]="hero">Save</button>
229
184
  * ```
185
+ *
186
+ * #### With single param (array)
187
+ *
188
+ * ```html
189
+ * <button [ssvCommand]="saveCmd" [ssvCommandParams]="[hero]">Save</button>
190
+ * ```
191
+ *
230
192
  * *NOTE: if you have only 1 argument as an array, it should be enclosed within an array e.g. `[['apple', 'banana']]`,
231
- * else it will spread and you will `arg1: "apple", arg2: "banana"`*
193
+ * else it will spread and you will get `arg1: "apple", arg2: "banana"`*
232
194
  *
233
195
  * #### With multi params
234
196
  * ```html
@@ -244,8 +206,6 @@ function isAssumedType(x) {
244
206
  * ```
245
207
  *
246
208
  */
247
- const NAME_CAMEL$1 = "ssvCommand";
248
- // let nextUniqueId = 0;
249
209
  class SsvCommand {
250
210
  // readonly id = `${NAME_CAMEL}-${nextUniqueId++}`;
251
211
  #options = inject(COMMAND_OPTIONS);
@@ -265,60 +225,71 @@ class SsvCommand {
265
225
  ...value,
266
226
  };
267
227
  }, ...(ngDevMode ? [{ debugName: "commandOptions" }] : []));
268
- ssvCommandParams = input(undefined, ...(ngDevMode ? [{ debugName: "ssvCommandParams" }] : []));
269
- commandParams = computed(() => this.ssvCommandParams() || this.creatorParams, ...(ngDevMode ? [{ debugName: "commandParams" }] : []));
228
+ ssvCommandParams = input(...(ngDevMode ? [undefined, { debugName: "ssvCommandParams" }] : []));
229
+ commandParams = computed(() => {
230
+ const params = this.ssvCommandParams();
231
+ if (params === undefined) {
232
+ return this.#creatorParams();
233
+ }
234
+ // Normalize single param to array format for consistent handling
235
+ return this.#normalizeParams(params);
236
+ }, ...(ngDevMode ? [{ debugName: "commandParams" }] : []));
270
237
  _hostClasses = computed(() => ["ssv-command", this.#executingClass()], ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
271
- #executingClass = computed(() => this._command.$isExecuting() ? this.commandOptions().executingCssClass : "", ...(ngDevMode ? [{ debugName: "#executingClass" }] : []));
272
- creatorParams = [];
273
- get command() { return this._command; }
274
- _command;
238
+ #executingClass = computed(() => this.#command().$isExecuting() ? this.commandOptions().executingCssClass : "", ...(ngDevMode ? [{ debugName: "#executingClass" }] : []));
239
+ #creatorParams = signal(undefined, ...(ngDevMode ? [{ debugName: "#creatorParams" }] : []));
240
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
241
+ #command = signal(undefined, ...(ngDevMode ? [{ debugName: "#command" }] : []));
242
+ command = this.#command.asReadonly();
275
243
  constructor() {
276
- const destroyRef = inject(DestroyRef);
277
- destroyRef.onDestroy(() => {
278
- this._command?.unsubscribe();
279
- });
280
244
  effect(() => {
281
- const canExecute = this._command.$canExecute();
245
+ const canExecute = this.#command().$canExecute();
282
246
  this.trySetDisabled(!canExecute);
283
247
  // console.log("[ssvCommand::canExecute$]", { canExecute: x });
284
248
  this.#cdr.markForCheck();
285
249
  });
286
250
  }
251
+ // todo: afterNextRender
287
252
  ngOnInit() {
288
253
  const commandOrCreator = this.commandOrCreator();
289
254
  // console.log("[ssvCommand::init]", this.#options);
290
255
  if (isCommand(commandOrCreator)) {
291
- this._command = commandOrCreator;
256
+ this.#command.set(commandOrCreator);
292
257
  }
293
258
  else if (isCommandCreator(commandOrCreator)) {
294
- const isAsync = commandOrCreator.isAsync || commandOrCreator.isAsync === undefined;
295
- this.creatorParams = commandOrCreator.params;
259
+ this.#creatorParams.set(this.#normalizeParams(commandOrCreator.params));
296
260
  // todo: find something like this for ivy (or angular10+)
297
261
  // const hostComponent = (this.viewContainer as any)._view.component;
298
262
  const execFn = commandOrCreator.execute.bind(commandOrCreator.host);
299
263
  const params = this.commandParams();
300
- const canExec = commandOrCreator.canExecute instanceof Function
301
- ? commandOrCreator.canExecute.bind(commandOrCreator.host, params)()
302
- : commandOrCreator.canExecute;
264
+ let canExec;
265
+ if (commandOrCreator.canExecute instanceof Function) {
266
+ const boundFn = commandOrCreator.canExecute.bind(commandOrCreator.host);
267
+ const result = Array.isArray(params) ? boundFn(...params) : boundFn();
268
+ canExec = result;
269
+ }
270
+ else {
271
+ canExec = commandOrCreator.canExecute;
272
+ }
303
273
  // console.log("[ssvCommand::init] command creator", {
304
274
  // firstParam: params ? params[0] : null,
305
275
  // params
306
276
  // });
307
- this._command = command(execFn, canExec, { isAsync, injector: this.#injector });
277
+ const cmd = command(execFn, canExec, { injector: this.#injector });
278
+ this.#command.set(cmd);
308
279
  }
309
280
  else {
310
281
  throw new Error(`${NAME_CAMEL$1}: [${NAME_CAMEL$1}] is not defined properly!`);
311
282
  }
312
- this._command.subscribe();
313
283
  }
314
284
  _handleClick() {
315
285
  const commandParams = this.commandParams();
316
286
  // console.log("[ssvCommand::onClick]", commandParams);
317
287
  if (Array.isArray(commandParams)) {
318
- this._command.execute(...commandParams);
288
+ this.#command().execute(...commandParams);
319
289
  }
320
290
  else {
321
- this._command.execute(commandParams);
291
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
+ this.#command().execute();
322
293
  }
323
294
  }
324
295
  trySetDisabled(disabled) {
@@ -327,6 +298,15 @@ class SsvCommand {
327
298
  this.#renderer.setProperty(this.#element.nativeElement, "disabled", disabled);
328
299
  }
329
300
  }
301
+ /** Normalizes params to array format for consistent execution */
302
+ #normalizeParams(params) {
303
+ // If params is already an array, return as-is
304
+ if (Array.isArray(params)) {
305
+ return params;
306
+ }
307
+ // Single non-array param - wrap it
308
+ return [params];
309
+ }
330
310
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SsvCommand, deps: [], target: i0.ɵɵFactoryTarget.Directive });
331
311
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.3", type: SsvCommand, isStandalone: true, selector: "[ssvCommand]", inputs: { commandOrCreator: { classPropertyName: "commandOrCreator", publicName: "ssvCommand", isSignal: true, isRequired: true, transformFunction: null }, ssvCommandOptions: { classPropertyName: "ssvCommandOptions", publicName: "ssvCommandOptions", isSignal: true, isRequired: false, transformFunction: null }, ssvCommandParams: { classPropertyName: "ssvCommandParams", publicName: "ssvCommandParams", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "_handleClick()" }, properties: { "class": "_hostClasses()" } }, exportAs: ["ssvCommand"], ngImport: i0 });
332
312
  }
@@ -338,6 +318,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
338
318
  "[class]": "_hostClasses()",
339
319
  "(click)": "_handleClick()",
340
320
  },
321
+ // todo: handle keydown/enter?
341
322
  exportAs: NAME_CAMEL$1,
342
323
  standalone: true,
343
324
  }]
@@ -351,10 +332,10 @@ const NAME_CAMEL = "ssvCommandRef";
351
332
  * ### Most common usage
352
333
  * ```html
353
334
  * <div #actionCmd="ssvCommandRef" [ssvCommandRef]="{host: this, execute: removeHero$, canExecute: isValid$}">
354
- * <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
335
+ * <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="[hero]">
355
336
  * Remove
356
337
  * </button>
357
- * <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
338
+ * <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="[hero]">
358
339
  * Remove
359
340
  * </button>
360
341
  * </div>
@@ -364,20 +345,17 @@ const NAME_CAMEL = "ssvCommandRef";
364
345
  class SsvCommandRef {
365
346
  #injector = inject(Injector);
366
347
  commandCreator = input.required({ ...(ngDevMode ? { debugName: "commandCreator" } : {}), alias: `ssvCommandRef` });
367
- get command() { return this._command; }
368
- _command;
369
- constructor() {
370
- const destroyRef = inject(DestroyRef);
371
- destroyRef.onDestroy(() => {
372
- this._command?.unsubscribe();
373
- });
374
- }
348
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
349
+ #command = signal(undefined, ...(ngDevMode ? [{ debugName: "#command" }] : []));
350
+ command = this.#command.asReadonly();
351
+ // todo: use afterNextRender
375
352
  ngOnInit() {
376
- if (isCommandCreator(this.commandCreator())) {
377
- const commandCreator = this.commandCreator();
378
- const isAsync = commandCreator.isAsync || commandCreator.isAsync === undefined;
353
+ const commandOrCreator = this.commandCreator();
354
+ if (isCommandCreator(commandOrCreator)) {
355
+ const commandCreator = commandOrCreator;
379
356
  const execFn = commandCreator.execute.bind(commandCreator.host);
380
- this._command = command(execFn, commandCreator.canExecute, { isAsync, injector: this.#injector });
357
+ const cmd = command(execFn, commandCreator.canExecute, { injector: this.#injector });
358
+ this.#command.set(cmd);
381
359
  }
382
360
  else {
383
361
  throw new Error(`${NAME_CAMEL}: [${NAME_CAMEL}] is not defined properly!`);
@@ -393,7 +371,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
393
371
  exportAs: NAME_CAMEL,
394
372
  standalone: true,
395
373
  }]
396
- }], ctorParameters: () => [], propDecorators: { commandCreator: [{ type: i0.Input, args: [{ isSignal: true, alias: "ssvCommandRef", required: true }] }] } });
374
+ }], propDecorators: { commandCreator: [{ type: i0.Input, args: [{ isSignal: true, alias: "ssvCommandRef", required: true }] }] } });
397
375
 
398
376
  const EXPORTED_IMPORTS = [
399
377
  SsvCommand,
@@ -415,11 +393,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
415
393
  }]
416
394
  }] });
417
395
 
418
- const VERSION = "4.0.0-dev.98";
396
+ const VERSION = "5.0.0-dev.111";
419
397
 
420
398
  /**
421
399
  * Generated bundle index. Do not edit.
422
400
  */
423
401
 
424
- export { COMMAND_OPTIONS, Command, CommandAsync, SsvCommand, SsvCommandModule, SsvCommandRef, VERSION, canExecuteFromNgForm, canExecuteFromSignals, command, commandAsync, isCommand, isCommandCreator, provideSsvCommandOptions };
402
+ export { COMMAND_OPTIONS, Command, SsvCommand, SsvCommandModule, SsvCommandRef, VERSION, canExecuteFromNgForm, canExecuteFromSignals, command, commandAsync, isCommand, isCommandCreator, provideSsvCommandOptions };
425
403
  //# sourceMappingURL=ssv-ngx.command.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssv-ngx.command.mjs","sources":["../../../../libs/ngx.command/src/command.options.ts","../../../../libs/ngx.command/src/command.ts","../../../../libs/ngx.command/src/command.util.ts","../../../../libs/ngx.command/src/command.directive.ts","../../../../libs/ngx.command/src/command-ref.directive.ts","../../../../libs/ngx.command/src/command.module.ts","../../../../libs/ngx.command/src/version.ts","../../../../libs/ngx.command/src/ssv-ngx.command.ts"],"sourcesContent":["import { InjectionToken, type Provider } from \"@angular/core\";\n\nexport interface CommandOptions {\n\t/**\n\t * Css Class which gets added/removed on the Command element's host while Command `isExecuting$`.\n\t */\n\texecutingCssClass: string;\n\n\t/** Determines whether the disabled will be handled by the directive or not.\n\t * Disable handled by directive's doesn't always play nice when used with other component/pipe/directive and they also handle disabled.\n\t * This disables the handling manually and need to pass explicitly `[disabled]=\"!saveCmd.canExecute\"`.\n\t */\n\thandleDisabled: boolean;\n}\n\nconst DEFAULT_OPTIONS = Object.freeze<CommandOptions>({\n\texecutingCssClass: \"executing\",\n\thandleDisabled: true,\n});\n\nexport const COMMAND_OPTIONS = new InjectionToken<CommandOptions>(\"SSV_COMMAND_OPTIONS\", {\n\tfactory: () => DEFAULT_OPTIONS,\n});\n\nexport function provideSsvCommandOptions(\n\toptions: Partial<CommandOptions> | ((defaults: Readonly<CommandOptions>) => Partial<CommandOptions>)\n): Provider[] {\n\treturn [\n\t\t{\n\t\t\tprovide: COMMAND_OPTIONS,\n\t\t\tuseFactory: () => {\n\t\t\t\tlet opts = typeof options === \"function\" ? options(DEFAULT_OPTIONS) : options;\n\t\t\t\topts = opts\n\t\t\t\t\t? {\n\t\t\t\t\t\t...DEFAULT_OPTIONS,\n\t\t\t\t\t\t...opts,\n\t\t\t\t\t}\n\t\t\t\t\t: DEFAULT_OPTIONS;\n\t\t\t\treturn opts;\n\t\t\t},\n\t\t},\n\t];\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n\tObservable, Subscription, Subject, of, EMPTY,\n\ttap, filter, switchMap, catchError, finalize, take,\n} from \"rxjs\";\nimport { toSignal } from \"@angular/core/rxjs-interop\";\nimport type { CanExecute, ExecuteAsyncFn, ExecuteFn, ICommand } from \"./command.model\";\nimport { assertInInjectionContext, computed, DestroyRef, inject, Injector, isSignal, signal, type Signal } from \"@angular/core\";\n\nexport interface CommandCreateOptions {\n\tisAsync: boolean,\n\tinjector?: Injector;\n}\n\nconst COMMAND_ASYNC_DEFAULT_OPTIONS: CommandCreateOptions = { isAsync: true };\n\n/** Creates an async {@link Command}. Must be used within an injection context.\n * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.\n */\nexport function commandAsync(\n\texecute: ExecuteAsyncFn,\n\tcanExecute$?: CanExecute,\n\topts?: Omit<CommandCreateOptions, \"isAsync\">,\n): Command {\n\treturn command(execute, canExecute$, opts ? { ...opts, ...COMMAND_ASYNC_DEFAULT_OPTIONS } : COMMAND_ASYNC_DEFAULT_OPTIONS);\n}\n\n/** Creates a {@link Command}. Must be used within an injection context.\n * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.\n */\nexport function command(\n\texecute: ExecuteFn,\n\tcanExecute$?: CanExecute,\n\topts?: CommandCreateOptions,\n): Command {\n\tif (!opts?.injector) {\n\t\tassertInInjectionContext(command);\n\t}\n\tconst injector = opts?.injector ?? inject(Injector);\n\tconst isAsync = opts?.isAsync ?? false;\n\tconst destroyRef = injector.get(DestroyRef);\n\tconst cmd = new Command(execute, canExecute$, isAsync, injector);\n\tcmd.autoDestroy = false;\n\n\tdestroyRef.onDestroy(() => {\n\t\t// console.warn(\"[command::destroy]\");\n\t\tcmd.destroy();\n\t});\n\treturn cmd;\n}\n\n/**\n * Command object used to encapsulate information which is needed to perform an action.\n *\n */\nexport class Command implements ICommand {\n\n\tget isExecuting(): boolean { return this.$isExecuting(); }\n\n\tget canExecute(): boolean { return this.$canExecute(); }\n\n\treadonly $isExecuting = signal(false);\n\treadonly $canExecute = computed(() => !this.$isExecuting() && this._$canExecute());\n\n\tprivate readonly _$canExecute: Signal<boolean>;\n\n\tautoDestroy = true;\n\n\tprivate executionPipe$ = new Subject<unknown[] | undefined>();\n\tprivate executionPipe$$ = Subscription.EMPTY;\n\tprivate subscribersCount = 0;\n\n\t/**\n\t * Creates an instance of Command.\n\t *\n\t * @param execute Execute function to invoke - use `isAsync: true` when `Observable<any>`.\n\t * @param canExecute Observable which determines whether it can execute or not.\n\t * @param isAsync Indicates that the execute function is async e.g. Observable.\n\t * @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.\n\t */\n\tconstructor(\n\t\texecute: ExecuteFn,\n\t\tcanExecute$?: CanExecute,\n\t\tisAsync?: boolean,\n\t\tinjector?: Injector,\n\t) {\n\t\tif (canExecute$) {\n\t\t\tconst canExecute = typeof canExecute$ === \"function\"\n\t\t\t\t? computed(canExecute$)\n\t\t\t\t: canExecute$;\n\t\t\tthis._$canExecute = isSignal(canExecute)\n\t\t\t\t? canExecute\n\t\t\t\t: toSignal(canExecute, { initialValue: false, injector });\n\t\t} else {\n\t\t\tthis._$canExecute = signal(true);\n\t\t}\n\t\tthis.executionPipe$$ = this.buildExecutionPipe(execute, isAsync).subscribe();\n\t}\n\n\t/** Execute function to invoke. */\n\texecute(...args: unknown[]): void {\n\t\t// console.warn(\"[command::execute]\", args);\n\t\tthis.executionPipe$.next(args);\n\t}\n\n\t/** Disposes all resources held by subscriptions. */\n\tdestroy(): void {\n\t\t// console.warn(\"[command::destroy]\");\n\t\tthis.executionPipe$$.unsubscribe();\n\t}\n\n\tsubscribe(): void {\n\t\tthis.subscribersCount++;\n\t}\n\n\tunsubscribe(): void {\n\t\tthis.subscribersCount--;\n\t\t// console.log(\"[command::unsubscribe]\", { autoDestroy: this.autoDestroy, subscribersCount: this.subscribersCount });\n\t\tif (this.autoDestroy && this.subscribersCount <= 0) {\n\t\t\tthis.destroy();\n\t\t}\n\t}\n\n\tprivate buildExecutionPipe(execute: (...args: unknown[]) => any, isAsync?: boolean): Observable<unknown> {\n\t\tlet pipe$ = this.executionPipe$.pipe(\n\t\t\t// tap(x => console.warn(\">>>> executionPipe\", this._canExecute)),\n\t\t\tfilter(() => this.$canExecute()),\n\t\t\ttap(() => {\n\t\t\t\t// console.log(\"[command::executionPipe$] do#1 - set execute\", { args: x });\n\t\t\t\tthis.$isExecuting.set(true);\n\t\t\t})\n\t\t);\n\n\t\tconst execFn = isAsync\n\t\t\t? switchMap<unknown[] | undefined, any[]>(args => {\n\t\t\t\tif (args) {\n\t\t\t\t\treturn execute(...args);\n\t\t\t\t}\n\t\t\t\treturn execute();\n\t\t\t})\n\t\t\t: tap((args: unknown[] | undefined) => {\n\t\t\t\tif (args) {\n\t\t\t\t\texecute(...args);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\texecute();\n\t\t\t});\n\n\t\tpipe$ = pipe$.pipe(\n\t\t\tswitchMap(args => of(args).pipe(\n\t\t\t\texecFn,\n\t\t\t\tfinalize(() => {\n\t\t\t\t\t// console.log(\"[command::executionPipe$] finalize inner#1 - set idle\");\n\t\t\t\t\tthis.$isExecuting.set(false);\n\t\t\t\t}),\n\t\t\t\ttake(1),\n\t\t\t\tcatchError(error => {\n\t\t\t\t\tconsole.error(\"Unhandled execute error\", error);\n\t\t\t\t\treturn EMPTY;\n\t\t\t\t}),\n\t\t\t)),\n\t\t\ttap(() => {\n\t\t\t\t// console.log(\"[command::executionPipe$] tap#2 - set idle\");\n\t\t\t\t// this._isExecuting$.next(false);\n\t\t\t\tthis.$isExecuting.set(false);\n\t\t\t}),\n\t\t);\n\t\treturn pipe$;\n\t}\n\n}\n\n/**\n * Async Command object used to encapsulate information which is needed to perform an action,\n * which takes an execute function as Observable/Promise.\n * @deprecated Use {@link commandAsync} instead.\n */\nexport class CommandAsync extends Command {\n\n\t/**\n\t * @deprecated Use {@link commandAsync} instead to create an instance.\n\t */\n\tconstructor(\n\t\texecute: ExecuteAsyncFn,\n\t\tcanExecute$?: CanExecute,\n\t) {\n\t\tsuper(execute, canExecute$, true);\n\t}\n\n}\n","import { AbstractControl, PristineChangeEvent, StatusChangeEvent } from \"@angular/forms\";\nimport { Observable, map, distinctUntilChanged, filter, combineLatest, of, defer, concat } from \"rxjs\";\n\nimport { CommandCreator, ICommand } from \"./command.model\";\nimport { Command } from \"./command\";\nimport { type Signal, computed } from \"@angular/core\";\n\n/** Determines whether the arg object is of type `Command`. */\nexport function isCommand(arg: unknown): arg is ICommand {\n\treturn arg instanceof Command;\n}\n\n/** Determines whether the arg object is of type `CommandCreator`. */\nexport function isCommandCreator(arg: unknown): arg is CommandCreator {\n\tif (arg instanceof Command) {\n\t\treturn false;\n\t} else if (isAssumedType<CommandCreator>(arg) && arg.execute && arg.host) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport interface CanExecuteFormOptions {\n\t/** Determines whether to check for validity. (defaults: true) */\n\tvalidity?: boolean;\n\n\t/** Determines whether to check whether UI has been touched. (defaults: true) */\n\tdirty?: boolean;\n}\n\nconst CAN_EXECUTE_FORM_OPTIONS_DEFAULTS = Object.freeze<CanExecuteFormOptions>({\n\tvalidity: true,\n\tdirty: true,\n})\n\n/** Get can execute from form validity/pristine as an observable. */\nexport function canExecuteFromNgForm(\n\tform: AbstractControl,\n\toptions?: CanExecuteFormOptions\n): Observable<boolean> {\n\tconst opts: CanExecuteFormOptions = options ?\n\t\t{ ...CAN_EXECUTE_FORM_OPTIONS_DEFAULTS, ...options }\n\t\t: CAN_EXECUTE_FORM_OPTIONS_DEFAULTS;\n\n\tconst pristine$ = opts.dirty\n\t\t? concat(\n\t\t\tdefer(() => of(form.pristine)),\n\t\t\tform.events.pipe(\n\t\t\t\tfilter(x => x instanceof PristineChangeEvent),\n\t\t\t\tmap(x => x.pristine),\n\t\t\t)\n\t\t).pipe(distinctUntilChanged(),)\n\t\t: of(true);\n\n\tconst valid$ = opts.validity\n\t\t? concat(\n\t\t\tdefer(() => of(form.valid)),\n\t\t\tform.events.pipe(\n\t\t\t\tfilter(x => x instanceof StatusChangeEvent),\n\t\t\t\tmap(x => x.status === \"VALID\"),\n\t\t\t)\n\t\t).pipe(distinctUntilChanged(),)\n\t\t: of(true);\n\n\treturn combineLatest([pristine$, valid$]).pipe(\n\t\tmap(([pristine, valid]) => !!(!opts.validity || valid) && !!(!opts.dirty || !pristine)),\n\t\tdistinctUntilChanged(),\n\t);\n}\n\n/** Can executed based on valid/dirty signal inputs. */\nexport function canExecuteFromSignals(\n\tsignals: { valid: Signal<boolean>, dirty: Signal<boolean> },\n\toptions?: CanExecuteFormOptions\n): Signal<boolean> {\n\tconst opts: CanExecuteFormOptions = options ?\n\t\t{ ...CAN_EXECUTE_FORM_OPTIONS_DEFAULTS, ...options }\n\t\t: CAN_EXECUTE_FORM_OPTIONS_DEFAULTS;\n\treturn computed(() => !!(!opts.validity || signals.valid()) && !!(!opts.dirty || signals.dirty()));\n}\n\n\nfunction isAssumedType<T = Record<string, unknown>>(x: unknown): x is Partial<T> {\n\treturn x !== null && typeof x === \"object\";\n}\n","import {\n\tDirective,\n\tOnInit,\n\tElementRef,\n\tRenderer2,\n\tChangeDetectorRef,\n\tinject,\n\teffect,\n\tinput,\n\tInjector,\n\tcomputed,\n\tDestroyRef,\n} from \"@angular/core\";\n\nimport { type CommandOptions, COMMAND_OPTIONS } from \"./command.options\";\nimport { command } from \"./command\";\nimport { isCommand, isCommandCreator } from \"./command.util\";\nimport { CommandCreator, type ICommand } from \"./command.model\";\n\n/**\n * Controls the state of a component in sync with `Command`.\n *\n * @example\n * ### Most common usage\n * ```html\n * <button [ssvCommand]=\"saveCmd\">Save</button>\n * ```\n *\n *\n * ### Usage with options\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandOptions]=\"{executingCssClass: 'in-progress'}\">Save</button>\n * ```\n *\n *\n * ### Usage with params\n * This is useful for collections (loops) or using multiple actions with different args.\n * *NOTE: This will share the `isExecuting` when used with multiple controls.*\n *\n * #### With single param\n *\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandParams]=\"{id: 1}\">Save</button>\n * ```\n * *NOTE: if you have only 1 argument as an array, it should be enclosed within an array e.g. `[['apple', 'banana']]`,\n * else it will spread and you will `arg1: \"apple\", arg2: \"banana\"`*\n *\n * #### With multi params\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandParams]=\"[{id: 1}, 'hello', hero]\">Save</button>\n * ```\n *\n * ### Usage with Command Creator\n * This is useful for collections (loops) or using multiple actions with different args, whilst not sharing `isExecuting`.\n *\n *\n * ```html\n * <button [ssvCommand]=\"{host: this, execute: removeHero$, canExecute: isValid$, params: [hero, 1337, 'xx']}\">Save</button>\n * ```\n *\n */\n\nconst NAME_CAMEL = \"ssvCommand\";\n\n// let nextUniqueId = 0;\n\n@Directive({\n\tselector: `[${NAME_CAMEL}]`,\n\thost: {\n\t\t\"[class]\": \"_hostClasses()\",\n\t\t\"(click)\": \"_handleClick()\",\n\t},\n\texportAs: NAME_CAMEL,\n\tstandalone: true,\n})\nexport class SsvCommand implements OnInit {\n\n\t// readonly id = `${NAME_CAMEL}-${nextUniqueId++}`;\n\treadonly #options = inject(COMMAND_OPTIONS);\n\treadonly #renderer = inject(Renderer2);\n\treadonly #element = inject(ElementRef);\n\treadonly #cdr = inject(ChangeDetectorRef);\n\treadonly #injector = inject(Injector);\n\n\treadonly commandOrCreator = input.required<ICommand | CommandCreator>({\n\t\talias: `ssvCommand`\n\t});\n\treadonly ssvCommandOptions = input<Partial<CommandOptions>>(this.#options);\n\treadonly commandOptions = computed<CommandOptions>(() => {\n\t\tconst value = this.ssvCommandOptions();\n\t\tif (value === this.#options) {\n\t\t\treturn this.#options;\n\t\t}\n\t\treturn {\n\t\t\t...this.#options,\n\t\t\t...value,\n\t\t};\n\t});\n\treadonly ssvCommandParams = input<unknown | unknown[]>(undefined);\n\treadonly commandParams = computed<unknown | unknown[]>(() => this.ssvCommandParams() || this.creatorParams);\n\treadonly _hostClasses = computed(() => [\"ssv-command\", this.#executingClass()]);\n\treadonly #executingClass = computed(() => this._command.$isExecuting() ? this.commandOptions().executingCssClass : \"\");\n\n\tprivate creatorParams: unknown | unknown[] = [];\n\n\tget command(): ICommand { return this._command; }\n\n\tprivate _command!: ICommand;\n\n\tconstructor() {\n\t\tconst destroyRef = inject(DestroyRef);\n\t\tdestroyRef.onDestroy(() => {\n\t\t\tthis._command?.unsubscribe();\n\t\t});\n\t\teffect(() => {\n\t\t\tconst canExecute = this._command.$canExecute();\n\t\t\tthis.trySetDisabled(!canExecute);\n\t\t\t// console.log(\"[ssvCommand::canExecute$]\", { canExecute: x });\n\t\t\tthis.#cdr.markForCheck();\n\t\t});\n\t}\n\n\tngOnInit(): void {\n\t\tconst commandOrCreator = this.commandOrCreator();\n\t\t// console.log(\"[ssvCommand::init]\", this.#options);\n\t\tif (isCommand(commandOrCreator)) {\n\t\t\tthis._command = commandOrCreator;\n\t\t} else if (isCommandCreator(commandOrCreator)) {\n\t\t\tconst isAsync = commandOrCreator.isAsync || commandOrCreator.isAsync === undefined;\n\t\t\tthis.creatorParams = commandOrCreator.params;\n\n\t\t\t// todo: find something like this for ivy (or angular10+)\n\t\t\t// const hostComponent = (this.viewContainer as any)._view.component;\n\n\t\t\tconst execFn = commandOrCreator.execute.bind(commandOrCreator.host);\n\t\t\tconst params = this.commandParams();\n\n\t\t\tconst canExec = commandOrCreator.canExecute instanceof Function\n\t\t\t\t? commandOrCreator.canExecute.bind(commandOrCreator.host, params)()\n\t\t\t\t: commandOrCreator.canExecute;\n\n\t\t\t// console.log(\"[ssvCommand::init] command creator\", {\n\t\t\t// \tfirstParam: params ? params[0] : null,\n\t\t\t// \tparams\n\t\t\t// });\n\n\t\t\tthis._command = command(execFn, canExec, { isAsync, injector: this.#injector });\n\t\t} else {\n\t\t\tthrow new Error(`${NAME_CAMEL}: [${NAME_CAMEL}] is not defined properly!`);\n\t\t}\n\n\t\tthis._command.subscribe();\n\t}\n\n\t_handleClick(): void {\n\t\tconst commandParams = this.commandParams();\n\t\t// console.log(\"[ssvCommand::onClick]\", commandParams);\n\t\tif (Array.isArray(commandParams)) {\n\t\t\tthis._command.execute(...commandParams);\n\t\t} else {\n\t\t\tthis._command.execute(commandParams);\n\t\t}\n\t}\n\n\tprivate trySetDisabled(disabled: boolean) {\n\t\tif (this.commandOptions().handleDisabled) {\n\t\t\t// console.warn(\">>>> disabled\", { id: this.id, disabled });\n\t\t\tthis.#renderer.setProperty(this.#element.nativeElement, \"disabled\", disabled);\n\t\t}\n\t}\n\n}\n\n","import { Directive, OnInit, inject, Injector, DestroyRef, input } from \"@angular/core\";\n\nimport type { ICommand, CommandCreator, CanExecute } from \"./command.model\";\nimport { isCommandCreator } from \"./command.util\";\nimport { command } from \"./command\";\n\nconst NAME_CAMEL = \"ssvCommandRef\";\n\n/**\n * Command creator ref, directive which allows creating Command in the template\n * and associate it to a command (in order to share executions).\n * @example\n * ### Most common usage\n * ```html\n * <div #actionCmd=\"ssvCommandRef\" [ssvCommandRef]=\"{host: this, execute: removeHero$, canExecute: isValid$}\">\n * <button [ssvCommand]=\"actionCmd.command\" [ssvCommandParams]=\"hero\">\n * Remove\n * </button>\n * <button [ssvCommand]=\"actionCmd.command\" [ssvCommandParams]=\"hero\">\n * Remove\n * </button>\n * </div>\n * ```\n *\n */\n@Directive({\n\tselector: `[${NAME_CAMEL}]`,\n\texportAs: NAME_CAMEL,\n\tstandalone: true,\n})\nexport class SsvCommandRef implements OnInit {\n\n\treadonly #injector = inject(Injector);\n\n\treadonly commandCreator = input.required<CommandCreator>({\n\t\talias: `ssvCommandRef`\n\t});\n\n\tget command(): ICommand { return this._command; }\n\tprivate _command!: ICommand;\n\n\tconstructor() {\n\t\tconst destroyRef = inject(DestroyRef);\n\t\tdestroyRef.onDestroy(() => {\n\t\t\tthis._command?.unsubscribe();\n\t\t});\n\t}\n\n\tngOnInit(): void {\n\t\tif (isCommandCreator(this.commandCreator())) {\n\t\t\tconst commandCreator = this.commandCreator();\n\t\t\tconst isAsync = commandCreator.isAsync || commandCreator.isAsync === undefined;\n\n\t\t\tconst execFn = commandCreator.execute.bind(commandCreator.host);\n\n\t\t\tthis._command = command(execFn, commandCreator.canExecute as CanExecute, { isAsync, injector: this.#injector });\n\t\t} else {\n\t\t\tthrow new Error(`${NAME_CAMEL}: [${NAME_CAMEL}] is not defined properly!`);\n\t\t}\n\t}\n\n}\n","import { NgModule } from \"@angular/core\";\n\nimport { SsvCommand } from \"./command.directive\";\nimport { SsvCommandRef } from \"./command-ref.directive\";\n\nconst EXPORTED_IMPORTS = [\n\tSsvCommand,\n\tSsvCommandRef\n];\n\n/** @deprecated Use standalone instead. */\n@NgModule({\n\timports: [EXPORTED_IMPORTS],\n\texports: [EXPORTED_IMPORTS]\n})\nexport class SsvCommandModule {\n\n}\n","export const VERSION = \"4.0.0-dev.98\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["NAME_CAMEL"],"mappings":";;;;;;AAeA,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAiB;AACrD,IAAA,iBAAiB,EAAE,WAAW;AAC9B,IAAA,cAAc,EAAE,IAAI;AACpB,CAAA,CAAC;MAEW,eAAe,GAAG,IAAI,cAAc,CAAiB,qBAAqB,EAAE;AACxF,IAAA,OAAO,EAAE,MAAM,eAAe;AAC9B,CAAA;AAEK,SAAU,wBAAwB,CACvC,OAAoG,EAAA;IAEpG,OAAO;AACN,QAAA;AACC,YAAA,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,MAAK;AAChB,gBAAA,IAAI,IAAI,GAAG,OAAO,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO;AAC7E,gBAAA,IAAI,GAAG;AACN,sBAAE;AACD,wBAAA,GAAG,eAAe;AAClB,wBAAA,GAAG,IAAI;AACP;sBACC,eAAe;AAClB,gBAAA,OAAO,IAAI;YACZ,CAAC;AACD,SAAA;KACD;AACF;;AC1CA;AAcA,MAAM,6BAA6B,GAAyB,EAAE,OAAO,EAAE,IAAI,EAAE;AAE7E;;AAEG;SACa,YAAY,CAC3B,OAAuB,EACvB,WAAwB,EACxB,IAA4C,EAAA;IAE5C,OAAO,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,6BAA6B,EAAE,GAAG,6BAA6B,CAAC;AAC3H;AAEA;;AAEG;SACa,OAAO,CACtB,OAAkB,EAClB,WAAwB,EACxB,IAA2B,EAAA;AAE3B,IAAA,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE;QACpB,wBAAwB,CAAC,OAAO,CAAC;IAClC;IACA,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;AACnD,IAAA,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,KAAK;IACtC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;AAC3C,IAAA,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC;AAChE,IAAA,GAAG,CAAC,WAAW,GAAG,KAAK;AAEvB,IAAA,UAAU,CAAC,SAAS,CAAC,MAAK;;QAEzB,GAAG,CAAC,OAAO,EAAE;AACd,IAAA,CAAC,CAAC;AACF,IAAA,OAAO,GAAG;AACX;AAEA;;;AAGG;MACU,OAAO,CAAA;IAEnB,IAAI,WAAW,KAAc,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAEzD,IAAI,UAAU,KAAc,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AAE9C,IAAA,YAAY,GAAG,MAAM,CAAC,KAAK,wDAAC;AAC5B,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,uDAAC;AAEjE,IAAA,YAAY;IAE7B,WAAW,GAAG,IAAI;AAEV,IAAA,cAAc,GAAG,IAAI,OAAO,EAAyB;AACrD,IAAA,eAAe,GAAG,YAAY,CAAC,KAAK;IACpC,gBAAgB,GAAG,CAAC;AAE5B;;;;;;;AAOG;AACH,IAAA,WAAA,CACC,OAAkB,EAClB,WAAwB,EACxB,OAAiB,EACjB,QAAmB,EAAA;QAEnB,IAAI,WAAW,EAAE;AAChB,YAAA,MAAM,UAAU,GAAG,OAAO,WAAW,KAAK;AACzC,kBAAE,QAAQ,CAAC,WAAW;kBACpB,WAAW;AACd,YAAA,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,UAAU;AACtC,kBAAE;AACF,kBAAE,QAAQ,CAAC,UAAU,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QAC3D;aAAO;AACN,YAAA,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,wDAAC;QACjC;AACA,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE;IAC7E;;IAGA,OAAO,CAAC,GAAG,IAAe,EAAA;;AAEzB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;IAC/B;;IAGA,OAAO,GAAA;;AAEN,QAAA,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE;IACnC;IAEA,SAAS,GAAA;QACR,IAAI,CAAC,gBAAgB,EAAE;IACxB;IAEA,WAAW,GAAA;QACV,IAAI,CAAC,gBAAgB,EAAE;;QAEvB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,EAAE;YACnD,IAAI,CAAC,OAAO,EAAE;QACf;IACD;IAEQ,kBAAkB,CAAC,OAAoC,EAAE,OAAiB,EAAA;AACjF,QAAA,IAAI,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI;;AAEnC,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,EAChC,GAAG,CAAC,MAAK;;AAER,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B,CAAC,CAAC,CACF;QAED,MAAM,MAAM,GAAG;AACd,cAAE,SAAS,CAA+B,IAAI,IAAG;gBAChD,IAAI,IAAI,EAAE;AACT,oBAAA,OAAO,OAAO,CAAC,GAAG,IAAI,CAAC;gBACxB;gBACA,OAAO,OAAO,EAAE;AACjB,YAAA,CAAC;AACD,cAAE,GAAG,CAAC,CAAC,IAA2B,KAAI;gBACrC,IAAI,IAAI,EAAE;AACT,oBAAA,OAAO,CAAC,GAAG,IAAI,CAAC;oBAChB;gBACD;AACA,gBAAA,OAAO,EAAE;AACV,YAAA,CAAC,CAAC;QAEH,KAAK,GAAG,KAAK,CAAC,IAAI,CACjB,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAC9B,MAAM,EACN,QAAQ,CAAC,MAAK;;AAEb,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B,CAAC,CAAC,EACF,IAAI,CAAC,CAAC,CAAC,EACP,UAAU,CAAC,KAAK,IAAG;AAClB,YAAA,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC;AAC/C,YAAA,OAAO,KAAK;AACb,QAAA,CAAC,CAAC,CACF,CAAC,EACF,GAAG,CAAC,MAAK;;;AAGR,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B,CAAC,CAAC,CACF;AACD,QAAA,OAAO,KAAK;IACb;AAEA;AAED;;;;AAIG;AACG,MAAO,YAAa,SAAQ,OAAO,CAAA;AAExC;;AAEG;IACH,WAAA,CACC,OAAuB,EACvB,WAAwB,EAAA;AAExB,QAAA,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC;IAClC;AAEA;;ACtLD;AACM,SAAU,SAAS,CAAC,GAAY,EAAA;IACrC,OAAO,GAAG,YAAY,OAAO;AAC9B;AAEA;AACM,SAAU,gBAAgB,CAAC,GAAY,EAAA;AAC5C,IAAA,IAAI,GAAG,YAAY,OAAO,EAAE;AAC3B,QAAA,OAAO,KAAK;IACb;AAAO,SAAA,IAAI,aAAa,CAAiB,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE;AACzE,QAAA,OAAO,IAAI;IACZ;AACA,IAAA,OAAO,KAAK;AACb;AAUA,MAAM,iCAAiC,GAAG,MAAM,CAAC,MAAM,CAAwB;AAC9E,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,KAAK,EAAE,IAAI;AACX,CAAA,CAAC;AAEF;AACM,SAAU,oBAAoB,CACnC,IAAqB,EACrB,OAA+B,EAAA;AAE/B,IAAA,MAAM,IAAI,GAA0B,OAAO;AAC1C,QAAA,EAAE,GAAG,iCAAiC,EAAE,GAAG,OAAO;UAChD,iCAAiC;AAEpC,IAAA,MAAM,SAAS,GAAG,IAAI,CAAC;UACpB,MAAM,CACP,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CACf,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,mBAAmB,CAAC,EAC7C,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CACpB,CACD,CAAC,IAAI,CAAC,oBAAoB,EAAE;AAC7B,UAAE,EAAE,CAAC,IAAI,CAAC;AAEX,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC;UACjB,MAAM,CACP,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CACf,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,iBAAiB,CAAC,EAC3C,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAC9B,CACD,CAAC,IAAI,CAAC,oBAAoB,EAAE;AAC7B,UAAE,EAAE,CAAC,IAAI,CAAC;IAEX,OAAO,aAAa,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAC7C,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,EACvF,oBAAoB,EAAE,CACtB;AACF;AAEA;AACM,SAAU,qBAAqB,CACpC,OAA2D,EAC3D,OAA+B,EAAA;AAE/B,IAAA,MAAM,IAAI,GAA0B,OAAO;AAC1C,QAAA,EAAE,GAAG,iCAAiC,EAAE,GAAG,OAAO;UAChD,iCAAiC;AACpC,IAAA,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;AACnG;AAGA,SAAS,aAAa,CAA8B,CAAU,EAAA;IAC7D,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;AAC3C;;ACjEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCG;AAEH,MAAMA,YAAU,GAAG,YAAY;AAE/B;MAWa,UAAU,CAAA;;AAGb,IAAA,QAAQ,GAAG,MAAM,CAAC,eAAe,CAAC;AAClC,IAAA,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;AAC7B,IAAA,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC;AAC7B,IAAA,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAChC,IAAA,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;IAE5B,gBAAgB,GAAG,KAAK,CAAC,QAAQ,4DACzC,KAAK,EAAE,CAAA,UAAA,CAAY,EAAA,CAClB;AACO,IAAA,iBAAiB,GAAG,KAAK,CAA0B,IAAI,CAAC,QAAQ,6DAAC;AACjE,IAAA,cAAc,GAAG,QAAQ,CAAiB,MAAK;AACvD,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE;AACtC,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,EAAE;YAC5B,OAAO,IAAI,CAAC,QAAQ;QACrB;QACA,OAAO;YACN,GAAG,IAAI,CAAC,QAAQ;AAChB,YAAA,GAAG,KAAK;SACR;AACF,IAAA,CAAC,0DAAC;AACO,IAAA,gBAAgB,GAAG,KAAK,CAAsB,SAAS,4DAAC;AACxD,IAAA,aAAa,GAAG,QAAQ,CAAsB,MAAM,IAAI,CAAC,gBAAgB,EAAE,IAAI,IAAI,CAAC,aAAa,yDAAC;AAClG,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,wDAAC;IACtE,eAAe,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,iBAAiB,GAAG,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;IAE9G,aAAa,GAAwB,EAAE;IAE/C,IAAI,OAAO,KAAe,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;AAExC,IAAA,QAAQ;AAEhB,IAAA,WAAA,GAAA;AACC,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,QAAA,UAAU,CAAC,SAAS,CAAC,MAAK;AACzB,YAAA,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE;AAC7B,QAAA,CAAC,CAAC;QACF,MAAM,CAAC,MAAK;YACX,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;AAC9C,YAAA,IAAI,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC;;AAEhC,YAAA,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;AACzB,QAAA,CAAC,CAAC;IACH;IAEA,QAAQ,GAAA;AACP,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE;;AAEhD,QAAA,IAAI,SAAS,CAAC,gBAAgB,CAAC,EAAE;AAChC,YAAA,IAAI,CAAC,QAAQ,GAAG,gBAAgB;QACjC;AAAO,aAAA,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,EAAE;YAC9C,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,IAAI,gBAAgB,CAAC,OAAO,KAAK,SAAS;AAClF,YAAA,IAAI,CAAC,aAAa,GAAG,gBAAgB,CAAC,MAAM;;;AAK5C,YAAA,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;AACnE,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE;AAEnC,YAAA,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,YAAY;AACtD,kBAAE,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC;AACjE,kBAAE,gBAAgB,CAAC,UAAU;;;;;AAO9B,YAAA,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QAChF;aAAO;YACN,MAAM,IAAI,KAAK,CAAC,CAAA,EAAGA,YAAU,CAAA,GAAA,EAAMA,YAAU,CAAA,0BAAA,CAA4B,CAAC;QAC3E;AAEA,QAAA,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;IAC1B;IAEA,YAAY,GAAA;AACX,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE;;AAE1C,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;YACjC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC;QACxC;aAAO;AACN,YAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC;QACrC;IACD;AAEQ,IAAA,cAAc,CAAC,QAAiB,EAAA;AACvC,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE;;AAEzC,YAAA,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC;QAC9E;IACD;uGA9FY,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAV,UAAU,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAV,UAAU,EAAA,UAAA,EAAA,CAAA;kBATtB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACV,QAAQ,EAAE,CAAA,CAAA,EAAIA,YAAU,CAAA,CAAA,CAAG;AAC3B,oBAAA,IAAI,EAAE;AACL,wBAAA,SAAS,EAAE,gBAAgB;AAC3B,wBAAA,SAAS,EAAE,gBAAgB;AAC3B,qBAAA;AACD,oBAAA,QAAQ,EAAEA,YAAU;AACpB,oBAAA,UAAU,EAAE,IAAI;AAChB,iBAAA;;;ACpED,MAAM,UAAU,GAAG,eAAe;AAElC;;;;;;;;;;;;;;;;AAgBG;MAMU,aAAa,CAAA;AAEhB,IAAA,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;IAE5B,cAAc,GAAG,KAAK,CAAC,QAAQ,0DACvC,KAAK,EAAE,CAAA,aAAA,CAAe,EAAA,CACrB;IAEF,IAAI,OAAO,KAAe,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxC,IAAA,QAAQ;AAEhB,IAAA,WAAA,GAAA;AACC,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,QAAA,UAAU,CAAC,SAAS,CAAC,MAAK;AACzB,YAAA,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE;AAC7B,QAAA,CAAC,CAAC;IACH;IAEA,QAAQ,GAAA;QACP,IAAI,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE;AAC5C,YAAA,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE;YAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO,KAAK,SAAS;AAE9E,YAAA,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;YAE/D,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,UAAwB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QAChH;aAAO;YACN,MAAM,IAAI,KAAK,CAAC,CAAA,EAAG,UAAU,CAAA,GAAA,EAAM,UAAU,CAAA,0BAAA,CAA4B,CAAC;QAC3E;IACD;uGA7BY,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBALzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACV,QAAQ,EAAE,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,CAAG;AAC3B,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,UAAU,EAAE,IAAI;AAChB,iBAAA;;;ACxBD,MAAM,gBAAgB,GAAG;IACxB,UAAU;IACV;CACA;AAED;MAKa,gBAAgB,CAAA;uGAAhB,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,gBAAgB,YAT5B,UAAU;AACV,YAAA,aAAa,aADb,UAAU;YACV,aAAa,CAAA,EAAA,CAAA;wGAQD,gBAAgB,EAAA,CAAA;;2FAAhB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAJ5B,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,OAAO,EAAE,CAAC,gBAAgB,CAAC;oBAC3B,OAAO,EAAE,CAAC,gBAAgB;AAC1B,iBAAA;;;ACdM,MAAM,OAAO,GAAG;;ACAvB;;AAEG;;;;"}
1
+ {"version":3,"file":"ssv-ngx.command.mjs","sources":["../../../../libs/ngx.command/src/command.options.ts","../../../../libs/ngx.command/src/command.ts","../../../../libs/ngx.command/src/command.util.ts","../../../../libs/ngx.command/src/command.directive.ts","../../../../libs/ngx.command/src/command-ref.directive.ts","../../../../libs/ngx.command/src/command.module.ts","../../../../libs/ngx.command/src/version.ts","../../../../libs/ngx.command/src/ssv-ngx.command.ts"],"sourcesContent":["import { InjectionToken, type Provider } from \"@angular/core\";\n\nexport interface CommandOptions {\n\t/**\n\t * Css Class which gets added/removed on the Command element's host while Command `isExecuting$`.\n\t */\n\texecutingCssClass: string;\n\n\t/** Determines whether the disabled will be handled by the directive or not.\n\t * Disable handled by directive's doesn't always play nice when used with other component/pipe/directive and they also handle disabled.\n\t * This disables the handling manually and need to pass explicitly `[disabled]=\"!saveCmd.canExecute\"`.\n\t */\n\thandleDisabled: boolean;\n}\n\nconst DEFAULT_OPTIONS = Object.freeze<CommandOptions>({\n\texecutingCssClass: \"executing\",\n\thandleDisabled: true,\n});\n\nexport const COMMAND_OPTIONS = new InjectionToken<CommandOptions>(\"SSV_COMMAND_OPTIONS\", {\n\tfactory: () => DEFAULT_OPTIONS,\n});\n\nexport function provideSsvCommandOptions(\n\toptions: Partial<CommandOptions> | ((defaults: Readonly<CommandOptions>) => Partial<CommandOptions>)\n): Provider[] {\n\treturn [\n\t\t{\n\t\t\tprovide: COMMAND_OPTIONS,\n\t\t\tuseFactory: () => {\n\t\t\t\tlet opts = typeof options === \"function\" ? options(DEFAULT_OPTIONS) : options;\n\t\t\t\topts = opts\n\t\t\t\t\t? {\n\t\t\t\t\t\t...DEFAULT_OPTIONS,\n\t\t\t\t\t\t...opts,\n\t\t\t\t\t}\n\t\t\t\t\t: DEFAULT_OPTIONS;\n\t\t\t\treturn opts;\n\t\t\t},\n\t\t},\n\t];\n}\n","\nimport { isObservable, lastValueFrom } from \"rxjs\";\nimport { toSignal } from \"@angular/core/rxjs-interop\";\nimport type { CanExecute, ExecuteFn, ExecuteReturnType, ICommand } from \"./command.model\";\nimport { assertInInjectionContext, computed, inject, Injector, isSignal, signal, type Signal } from \"@angular/core\";\n\nexport interface CommandCreateOptions {\n\tinjector?: Injector;\n}\n\n// todo: remove\n/** Creates an async {@link Command}. Must be used within an injection context.\n * @deprecated Use {@link command} instead, as it handles both sync and async execute functions.\n */\nexport const commandAsync = command;\n\n/** Creates a {@link Command}. Must be used within an injection context (or the injector must be provided in the options). */\nexport function command<TExecute extends ExecuteFn>(\n\texecute: TExecute,\n\tcanExecute?: CanExecute,\n\topts?: CommandCreateOptions,\n): Command<TExecute> {\n\tif (!opts?.injector) {\n\t\tassertInInjectionContext(command);\n\t}\n\tconst injector = opts?.injector ?? inject(Injector);\n\tconst cmd = new Command(execute, canExecute, injector);\n\treturn cmd;\n}\n\n/**\n * Command object used to encapsulate information which is needed to perform an action.\n */\nexport class Command<TExecute extends ExecuteFn = ExecuteFn> implements ICommand<TExecute> {\n\n\tget isExecuting(): boolean { return this.$isExecuting(); }\n\n\tget canExecute(): boolean { return this.$canExecute(); }\n\n\treadonly $isExecuting = signal(false);\n\treadonly $canExecute = computed(() => !this.$isExecuting() && this.#canExecute());\n\n\treadonly #canExecute: Signal<boolean>;\n\n\t/**\n\t * Creates an instance of Command.\n\t *\n\t * @param execute Execute function to invoke.\n\t * @param canExecute Observable which determines whether it can execute or not.\n\t * @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.\n\t */\n\tconstructor(\n\t\tprivate readonly _execute: TExecute,\n\t\tcanExecute?: CanExecute,\n\t\tinjector?: Injector,\n\t) {\n\t\tthis.#canExecute = this.#buildCanExecuteSignal(canExecute, injector);\n\t}\n\n\t/** Execute function to invoke. Returns Promise if the execute function returns Observable, otherwise returns the original type. */\n\texecute(...args: Parameters<TExecute>): ExecuteReturnType<TExecute> {\n\t\tif (!this.$canExecute()) {\n\t\t\tthrow new Error(\"Command cannot execute in its current state.\");\n\t\t\t// return Promise.reject() as ReturnType<TExecute>;\n\t\t}\n\t\tthis.$isExecuting.set(true);\n\n\t\t// console.warn(\"[command::execute]\", args);\n\n\t\ttry {\n\t\t\tconst result = args.length > 0 ? this._execute(...args) : this._execute();\n\n\t\t\tif (isObservable(result)) {\n\t\t\t\t// Convert observable to promise using lastValueFrom\n\t\t\t\t// This ensures fire-and-forget execution without requiring manual subscription\n\t\t\t\t// Use defaultValue to handle empty observables (those that complete without emitting)\n\t\t\t\tconst promise = lastValueFrom(result, { defaultValue: undefined })\n\t\t\t\t\t.finally(() => this.$isExecuting.set(false));\n\t\t\t\treturn promise as ExecuteReturnType<TExecute>;\n\t\t\t} else if (result instanceof Promise) {\n\t\t\t\t// Return promise with proper cleanup\n\t\t\t\treturn result\n\t\t\t\t\t.finally(() => this.$isExecuting.set(false)) as ExecuteReturnType<TExecute>;\n\t\t\t}\n\t\t\t// Sync execution\n\t\t\tthis.$isExecuting.set(false);\n\t\t\treturn result as ExecuteReturnType<TExecute>;\n\t\t} catch (err) {\n\t\t\tthis.$isExecuting.set(false);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t#buildCanExecuteSignal(canExecute?: CanExecute, injector?: Injector): Signal<boolean> {\n\t\tif (canExecute === undefined) {\n\t\t\treturn computed(() => true);\n\t\t}\n\t\tif (isSignal(canExecute)) {\n\t\t\treturn canExecute;\n\t\t}\n\t\tif (typeof canExecute === \"function\") {\n\t\t\treturn computed(canExecute);\n\t\t}\n\t\tif (typeof canExecute === \"boolean\") {\n\t\t\treturn computed(() => canExecute);\n\t\t}\n\t\treturn toSignal(canExecute, { initialValue: false, injector });\n\t}\n\n}\n","import { type AbstractControl, PristineChangeEvent, StatusChangeEvent } from \"@angular/forms\";\nimport { Observable, map, distinctUntilChanged, filter, combineLatest, of, defer, concat } from \"rxjs\";\n\nimport type { CommandCreator, ICommand } from \"./command.model\";\nimport { Command } from \"./command\";\nimport { type Signal, computed } from \"@angular/core\";\n\n/** Determines whether the arg object is of type `Command`. */\nexport function isCommand<T extends ICommand>(arg: unknown | T): arg is T {\n\treturn arg instanceof Command;\n}\n\n/** Determines whether the arg object is of type `CommandCreator`. */\nexport function isCommandCreator<T extends CommandCreator>(arg: unknown | T): arg is T {\n\tif (arg instanceof Command) {\n\t\treturn false;\n\t} else if (isAssumedType<T>(arg) && arg.execute && arg.host) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport interface CanExecuteFormOptions {\n\t/** Determines whether to check for validity. (defaults: true) */\n\tvalidity?: boolean;\n\n\t/** Determines whether to check whether UI has been touched. (defaults: true) */\n\tdirty?: boolean;\n}\n\nconst CAN_EXECUTE_FORM_OPTIONS_DEFAULTS = Object.freeze<CanExecuteFormOptions>({\n\tvalidity: true,\n\tdirty: true,\n})\n\n/** Get can execute from form validity/pristine as an observable. */\nexport function canExecuteFromNgForm(\n\tform: AbstractControl,\n\toptions?: CanExecuteFormOptions\n): Observable<boolean> {\n\tconst opts: CanExecuteFormOptions = options ?\n\t\t{ ...CAN_EXECUTE_FORM_OPTIONS_DEFAULTS, ...options }\n\t\t: CAN_EXECUTE_FORM_OPTIONS_DEFAULTS;\n\n\tconst pristine$ = opts.dirty\n\t\t? concat(\n\t\t\tdefer(() => of(form.pristine)),\n\t\t\tform.events.pipe(\n\t\t\t\tfilter(x => x instanceof PristineChangeEvent),\n\t\t\t\tmap(x => x.pristine),\n\t\t\t)\n\t\t).pipe(distinctUntilChanged(),)\n\t\t: of(true);\n\n\tconst valid$ = opts.validity\n\t\t? concat(\n\t\t\tdefer(() => of(form.valid)),\n\t\t\tform.events.pipe(\n\t\t\t\tfilter(x => x instanceof StatusChangeEvent),\n\t\t\t\tmap(x => x.status === \"VALID\"),\n\t\t\t)\n\t\t).pipe(distinctUntilChanged(),)\n\t\t: of(true);\n\n\treturn combineLatest([pristine$, valid$]).pipe(\n\t\tmap(([pristine, valid]) => !!(!opts.validity || valid) && !!(!opts.dirty || !pristine)),\n\t\tdistinctUntilChanged(),\n\t);\n}\n\n/** Can executed based on valid/dirty signal inputs. */\nexport function canExecuteFromSignals(\n\tsignals: { valid: Signal<boolean>, dirty: Signal<boolean> },\n\toptions?: CanExecuteFormOptions\n): Signal<boolean> {\n\tconst opts: CanExecuteFormOptions = options ?\n\t\t{ ...CAN_EXECUTE_FORM_OPTIONS_DEFAULTS, ...options }\n\t\t: CAN_EXECUTE_FORM_OPTIONS_DEFAULTS;\n\treturn computed(() => !!(!opts.validity || signals.valid()) && !!(!opts.dirty || signals.dirty()));\n}\n\n\nfunction isAssumedType<T = Record<string, unknown>>(x: unknown): x is Partial<T> {\n\treturn x !== null && typeof x === \"object\";\n}\n","import {\n\tDirective,\n\tOnInit,\n\tElementRef,\n\tRenderer2,\n\tChangeDetectorRef,\n\tinject,\n\teffect,\n\tinput,\n\tInjector,\n\tcomputed,\n\tsignal,\n} from \"@angular/core\";\n\nimport { type CommandOptions, COMMAND_OPTIONS } from \"./command.options\";\nimport { command, type Command } from \"./command\";\nimport { isCommand, isCommandCreator } from \"./command.util\";\nimport { CommandCreator, type ICommand, type CanExecute, type ExecuteFn, type CommandParams, type Simplify } from \"./command.model\";\n\n/** Helper type to extract ExecuteFn from ICommand/Command or use ExecuteFn directly */\ntype ExtractExecuteFn<T> = T extends Command<infer TExec>\n\t? TExec\n\t: T extends ICommand<infer TExec>\n\t? TExec\n\t: T extends ExecuteFn\n\t? T\n\t: never;\n\nconst NAME_CAMEL = \"ssvCommand\";\n\n// let nextUniqueId = 0;\n\n/**\n * Controls the state of a component in sync with `Command`.\n *\n * @example\n * ### Most common usage\n * ```html\n * <button [ssvCommand]=\"saveCmd\">Save</button>\n * ```\n *\n *\n * ### Usage with options\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandOptions]=\"{executingCssClass: 'in-progress'}\">Save</button>\n * ```\n *\n *\n * ### Usage with params\n * This is useful for collections (loops) or using multiple actions with different args.\n * *NOTE: This will share the `isExecuting` when used with multiple controls.*\n *\n * #### With single param (direct)\n *\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandParams]=\"hero\">Save</button>\n * ```\n *\n * #### With single param (array)\n *\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandParams]=\"[hero]\">Save</button>\n * ```\n *\n * *NOTE: if you have only 1 argument as an array, it should be enclosed within an array e.g. `[['apple', 'banana']]`,\n * else it will spread and you will get `arg1: \"apple\", arg2: \"banana\"`*\n *\n * #### With multi params\n * ```html\n * <button [ssvCommand]=\"saveCmd\" [ssvCommandParams]=\"[{id: 1}, 'hello', hero]\">Save</button>\n * ```\n *\n * ### Usage with Command Creator\n * This is useful for collections (loops) or using multiple actions with different args, whilst not sharing `isExecuting`.\n *\n *\n * ```html\n * <button [ssvCommand]=\"{host: this, execute: removeHero$, canExecute: isValid$, params: [hero, 1337, 'xx']}\">Save</button>\n * ```\n *\n */\n@Directive({\n\tselector: `[${NAME_CAMEL}]`,\n\thost: {\n\t\t\"[class]\": \"_hostClasses()\",\n\t\t\"(click)\": \"_handleClick()\",\n\t},\n\t// todo: handle keydown/enter?\n\texportAs: NAME_CAMEL,\n\tstandalone: true,\n})\nexport class SsvCommand<T extends ICommand | ExecuteFn = ExecuteFn> implements OnInit {\n\n\t// readonly id = `${NAME_CAMEL}-${nextUniqueId++}`;\n\treadonly #options = inject(COMMAND_OPTIONS);\n\treadonly #renderer = inject(Renderer2);\n\treadonly #element = inject(ElementRef);\n\treadonly #cdr = inject(ChangeDetectorRef);\n\treadonly #injector = inject(Injector);\n\n\treadonly commandOrCreator = input.required<T extends ICommand ? T : (ICommand<ExtractExecuteFn<T>> | CommandCreator<ExtractExecuteFn<T>>)>({\n\t\talias: `ssvCommand`\n\t});\n\treadonly ssvCommandOptions = input<Partial<CommandOptions>>(this.#options);\n\treadonly commandOptions = computed<CommandOptions>(() => {\n\t\tconst value = this.ssvCommandOptions();\n\t\tif (value === this.#options) {\n\t\t\treturn this.#options;\n\t\t}\n\t\treturn {\n\t\t\t...this.#options,\n\t\t\t...value,\n\t\t};\n\t});\n\treadonly ssvCommandParams = input<Simplify<CommandParams<ExtractExecuteFn<T>>>>();\n\treadonly commandParams = computed(() => {\n\t\tconst params = this.ssvCommandParams();\n\t\tif (params === undefined) {\n\t\t\treturn this.#creatorParams();\n\t\t}\n\t\t// Normalize single param to array format for consistent handling\n\t\treturn this.#normalizeParams(params as CommandParams<ExtractExecuteFn<T>>);\n\t});\n\treadonly _hostClasses = computed(() => [\"ssv-command\", this.#executingClass()]);\n\treadonly #executingClass = computed(() => this.#command().$isExecuting() ? this.commandOptions().executingCssClass : \"\");\n\n\treadonly #creatorParams = signal<Parameters<ExtractExecuteFn<T>> | undefined>(undefined);\n\n\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\treadonly #command = signal<ICommand<ExtractExecuteFn<T>>>(undefined!);\n\treadonly command = this.#command.asReadonly();\n\n\tconstructor() {\n\t\teffect(() => {\n\t\t\tconst canExecute = this.#command().$canExecute();\n\t\t\tthis.trySetDisabled(!canExecute);\n\t\t\t// console.log(\"[ssvCommand::canExecute$]\", { canExecute: x });\n\t\t\tthis.#cdr.markForCheck();\n\t\t});\n\t}\n\n\t// todo: afterNextRender\n\tngOnInit(): void {\n\t\tconst commandOrCreator = this.commandOrCreator();\n\t\t// console.log(\"[ssvCommand::init]\", this.#options);\n\t\tif (isCommand(commandOrCreator)) {\n\t\t\tthis.#command.set(commandOrCreator);\n\t\t} else if (isCommandCreator(commandOrCreator)) {\n\t\t\tthis.#creatorParams.set(this.#normalizeParams(commandOrCreator.params as CommandParams<ExtractExecuteFn<T>>));\n\n\t\t\t// todo: find something like this for ivy (or angular10+)\n\t\t\t// const hostComponent = (this.viewContainer as any)._view.component;\n\n\t\t\tconst execFn = commandOrCreator.execute.bind(commandOrCreator.host) as ExtractExecuteFn<T>;\n\t\t\tconst params = this.commandParams();\n\n\t\t\tlet canExec: CanExecute | undefined;\n\t\t\tif (commandOrCreator.canExecute instanceof Function) {\n\t\t\t\tconst boundFn = commandOrCreator.canExecute.bind(commandOrCreator.host);\n\t\t\t\tconst result = Array.isArray(params) ? boundFn(...params) : boundFn();\n\t\t\t\tcanExec = result as CanExecute;\n\t\t\t} else {\n\t\t\t\tcanExec = commandOrCreator.canExecute;\n\t\t\t}\n\n\t\t\t// console.log(\"[ssvCommand::init] command creator\", {\n\t\t\t// \tfirstParam: params ? params[0] : null,\n\t\t\t// \tparams\n\t\t\t// });\n\t\t\tconst cmd = command(execFn, canExec, { injector: this.#injector });\n\t\t\tthis.#command.set(cmd);\n\t\t} else {\n\t\t\tthrow new Error(`${NAME_CAMEL}: [${NAME_CAMEL}] is not defined properly!`);\n\t\t}\n\t}\n\n\t_handleClick(): void {\n\t\tconst commandParams = this.commandParams();\n\t\t// console.log(\"[ssvCommand::onClick]\", commandParams);\n\t\tif (Array.isArray(commandParams)) {\n\t\t\tthis.#command().execute(...commandParams);\n\t\t} else {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(this.#command().execute as any)();\n\t\t}\n\t}\n\n\tprivate trySetDisabled(disabled: boolean) {\n\t\tif (this.commandOptions().handleDisabled) {\n\t\t\t// console.warn(\">>>> disabled\", { id: this.id, disabled });\n\t\t\tthis.#renderer.setProperty(this.#element.nativeElement, \"disabled\", disabled);\n\t\t}\n\t}\n\n\t/** Normalizes params to array format for consistent execution */\n\t#normalizeParams(params: CommandParams<ExtractExecuteFn<T>>): Parameters<ExtractExecuteFn<T>> | undefined {\n\t\t// If params is already an array, return as-is\n\t\tif (Array.isArray(params)) {\n\t\t\treturn params as Parameters<ExtractExecuteFn<T>>;\n\t\t}\n\t\t// Single non-array param - wrap it\n\t\treturn [params] as Parameters<ExtractExecuteFn<T>>;\n\t}\n\n}\n","import { Directive, OnInit, inject, Injector, input, signal } from \"@angular/core\";\n\nimport type { ICommand, CommandCreator, CanExecute, ExecuteFn } from \"./command.model\";\nimport { isCommandCreator } from \"./command.util\";\nimport { command } from \"./command\";\n\nconst NAME_CAMEL = \"ssvCommandRef\";\n\n/**\n * Command creator ref, directive which allows creating Command in the template\n * and associate it to a command (in order to share executions).\n * @example\n * ### Most common usage\n * ```html\n * <div #actionCmd=\"ssvCommandRef\" [ssvCommandRef]=\"{host: this, execute: removeHero$, canExecute: isValid$}\">\n * <button [ssvCommand]=\"actionCmd.command()\" [ssvCommandParams]=\"[hero]\">\n * Remove\n * </button>\n * <button [ssvCommand]=\"actionCmd.command()\" [ssvCommandParams]=\"[hero]\">\n * Remove\n * </button>\n * </div>\n * ```\n *\n */\n@Directive({\n\tselector: `[${NAME_CAMEL}]`,\n\texportAs: NAME_CAMEL,\n\tstandalone: true,\n})\nexport class SsvCommandRef<TExecute extends ExecuteFn = ExecuteFn> implements OnInit {\n\n\treadonly #injector = inject(Injector);\n\n\treadonly commandCreator = input.required<CommandCreator<TExecute>>({\n\t\talias: `ssvCommandRef`\n\t});\n\n\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\treadonly #command = signal<ICommand<TExecute>>(undefined!);\n\treadonly command = this.#command.asReadonly();\n\n\t// todo: use afterNextRender\n\tngOnInit(): void {\n\t\tconst commandOrCreator = this.commandCreator();\n\t\tif (isCommandCreator(commandOrCreator)) {\n\t\t\tconst commandCreator = commandOrCreator;\n\n\t\t\tconst execFn = commandCreator.execute.bind(commandCreator.host) as TExecute;\n\n\t\t\tconst cmd = command(execFn, commandCreator.canExecute as CanExecute, { injector: this.#injector });\n\t\t\tthis.#command.set(cmd);\n\t\t} else {\n\t\t\tthrow new Error(`${NAME_CAMEL}: [${NAME_CAMEL}] is not defined properly!`);\n\t\t}\n\t}\n\n}\n","import { NgModule } from \"@angular/core\";\n\nimport { SsvCommand } from \"./command.directive\";\nimport { SsvCommandRef } from \"./command-ref.directive\";\n\nconst EXPORTED_IMPORTS = [\n\tSsvCommand,\n\tSsvCommandRef\n];\n\n/** @deprecated Use standalone instead. */\n@NgModule({\n\timports: [EXPORTED_IMPORTS],\n\texports: [EXPORTED_IMPORTS]\n})\nexport class SsvCommandModule {\n\n}\n","export const VERSION = \"5.0.0-dev.111\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["NAME_CAMEL"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ssv/ngx.command",
3
- "version": "4.0.0-dev.98",
3
+ "version": "5.0.0-dev.111",
4
4
  "versionSuffix": "",
5
5
  "description": "Command pattern implementation for angular. Command used to encapsulate information which is needed to perform an action.",
6
6
  "keywords": [
@@ -19,9 +19,6 @@
19
19
  "type": "git",
20
20
  "url": "https://github.com/sketch7/ssv.ngx.git"
21
21
  },
22
- "dependencies": {
23
- "tslib": "^2.3.0"
24
- },
25
22
  "peerDependencies": {
26
23
  "@angular/core": ">=17.0.0",
27
24
  "@angular/forms": ">=17.0.0",
@@ -38,5 +35,8 @@
38
35
  "types": "./types/ssv-ngx.command.d.ts",
39
36
  "default": "./fesm2022/ssv-ngx.command.mjs"
40
37
  }
38
+ },
39
+ "dependencies": {
40
+ "tslib": "^2.3.0"
41
41
  }
42
42
  }
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { Provider, InjectionToken, Signal, OnInit, Injector } from '@angular/core';
2
+ import { Provider, InjectionToken, Signal, Injector, OnInit } from '@angular/core';
3
3
  import { Observable } from 'rxjs';
4
4
  import { AbstractControl } from '@angular/forms';
5
5
 
@@ -17,10 +17,35 @@ interface CommandOptions {
17
17
  declare const COMMAND_OPTIONS: InjectionToken<CommandOptions>;
18
18
  declare function provideSsvCommandOptions(options: Partial<CommandOptions> | ((defaults: Readonly<CommandOptions>) => Partial<CommandOptions>)): Provider[];
19
19
 
20
- type ExecuteFn = (...args: any[]) => unknown;
21
- type ExecuteAsyncFn = (...args: any[]) => Observable<unknown> | Promise<unknown>;
22
- type CanExecute = (() => boolean) | Signal<boolean> | Observable<boolean>;
23
- interface ICommand {
20
+ /** Type that represents a sync or async value. */
21
+ type MaybeAsync<T> = T | Observable<T> | Promise<T>;
22
+ type SignalLike<T> = (() => T);
23
+ /** Converts Observable<T> to Promise<T>, leaves other types unchanged */
24
+ type ConvertObservableToPromise<T> = T extends Observable<infer U> ? Promise<U> : T;
25
+ /** Return type of Execute function, converting `Observable` to `Promise` if needed */
26
+ type ExecuteReturnType<TExecute extends ExecuteFn> = ConvertObservableToPromise<ReturnType<TExecute>>;
27
+ type ExecuteFn<TArgs extends any[] = any[], TReturn = unknown> = (...args: TArgs) => MaybeAsync<TReturn>;
28
+ type CanExecute = SignalLike<boolean> | Signal<boolean> | Observable<boolean> | boolean;
29
+ /**
30
+ * Type for command parameters that allows:
31
+ * - Single parameter passed directly (not in array)
32
+ * - Multiple parameters as tuple array
33
+ * - Single array parameter wrapped in array to prevent spreading
34
+ */
35
+ type CommandParams<TExec extends ExecuteFn> = Parameters<TExec> extends [infer Single] ? Single | [Single] : Parameters<TExec> extends [] ? never : Parameters<TExec>;
36
+ /** `command` input type convenience.
37
+ * @example
38
+ * For a command with a single parameter:
39
+ * ```ts
40
+ * readonly myCmd = input.required<CommandInput<MyType>>();
41
+ * ```
42
+ * For a command with multiple parameters:
43
+ * ```ts
44
+ * readonly myCmd = input.required<CommandInput<[param1: string, param2: number]>>();
45
+ * ```
46
+ */
47
+ type CommandInput<TArgs = unknown, R = unknown> = TArgs extends readonly [unknown, ...unknown[]] ? Command<(...args: TArgs) => R> : TArgs extends readonly [infer Single] ? Command<(arg: Single) => R> : Command<(arg: TArgs) => R>;
48
+ interface ICommand<TExecute extends ExecuteFn = ExecuteFn> {
24
49
  /** Determines whether the command is currently executing, as a snapshot value.
25
50
  * @deprecated Use {@link $isExecuting} signal instead.
26
51
  */
@@ -33,49 +58,117 @@ interface ICommand {
33
58
  readonly canExecute: boolean;
34
59
  /** Determines whether the command can execute or not, as a signal. */
35
60
  readonly $canExecute: Signal<boolean>;
36
- /** Determines whether to auto destroy when having 0 subscribers (defaults to `true`).
37
- * @deprecated Use using command/commandAsync is handled automatically.
38
- */
39
- autoDestroy: boolean;
40
- /** Execute function to invoke. */
41
- execute(...args: unknown[]): void;
42
- /** Disposes all resources held by subscriptions. */
43
- destroy(): void;
44
- /** Subscribe listener, in order to handle auto disposing.
45
- * @deprecated Use using command/commandAsync is handled automatically.
46
- */
47
- subscribe(): void;
48
- /**
49
- * Unsubscribe listener, in order to handle auto disposing.
50
- * @deprecated Use using command/commandAsync is handled automatically.
51
- */
52
- unsubscribe(): void;
61
+ /** Execute function to invoke. Returns Promise if the execute function returns Observable, otherwise returns the original type. */
62
+ execute(...args: Parameters<TExecute>): ExecuteReturnType<TExecute>;
53
63
  }
54
- interface CommandCreator {
55
- execute: (...args: any[]) => Observable<unknown> | Promise<unknown> | void;
56
- canExecute?: CanExecute | Function;
57
- params?: unknown | unknown[];
58
- isAsync?: boolean;
64
+ interface CommandCreator<TExecute extends ExecuteFn = ExecuteFn> {
65
+ /** Execute function to invoke. */
66
+ execute: TExecute;
67
+ /** Determines whether the command can execute or not. Can be a signal, observable, or function. */
68
+ canExecute?: CanExecute | ((...args: Parameters<TExecute>) => CanExecute);
69
+ /** Parameters to pass to the execute function. */
70
+ params?: CommandParams<TExecute>;
71
+ /** Host context for binding the execute function. */
59
72
  host: unknown;
60
73
  }
61
74
 
62
- declare class SsvCommand implements OnInit {
75
+ interface CommandCreateOptions {
76
+ injector?: Injector;
77
+ }
78
+ /** Creates an async {@link Command}. Must be used within an injection context.
79
+ * @deprecated Use {@link command} instead, as it handles both sync and async execute functions.
80
+ */
81
+ declare const commandAsync: typeof command;
82
+ /** Creates a {@link Command}. Must be used within an injection context (or the injector must be provided in the options). */
83
+ declare function command<TExecute extends ExecuteFn>(execute: TExecute, canExecute?: CanExecute, opts?: CommandCreateOptions): Command<TExecute>;
84
+ /**
85
+ * Command object used to encapsulate information which is needed to perform an action.
86
+ */
87
+ declare class Command<TExecute extends ExecuteFn = ExecuteFn> implements ICommand<TExecute> {
63
88
  #private;
64
- readonly commandOrCreator: _angular_core.InputSignal<ICommand | CommandCreator>;
89
+ private readonly _execute;
90
+ get isExecuting(): boolean;
91
+ get canExecute(): boolean;
92
+ readonly $isExecuting: _angular_core.WritableSignal<boolean>;
93
+ readonly $canExecute: Signal<boolean>;
94
+ /**
95
+ * Creates an instance of Command.
96
+ *
97
+ * @param execute Execute function to invoke.
98
+ * @param canExecute Observable which determines whether it can execute or not.
99
+ * @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.
100
+ */
101
+ constructor(_execute: TExecute, canExecute?: CanExecute, injector?: Injector);
102
+ /** Execute function to invoke. Returns Promise if the execute function returns Observable, otherwise returns the original type. */
103
+ execute(...args: Parameters<TExecute>): ExecuteReturnType<TExecute>;
104
+ }
105
+
106
+ /** Helper type to extract ExecuteFn from ICommand/Command or use ExecuteFn directly */
107
+ type ExtractExecuteFn<T> = T extends Command<infer TExec> ? TExec : T extends ICommand<infer TExec> ? TExec : T extends ExecuteFn ? T : never;
108
+ /**
109
+ * Controls the state of a component in sync with `Command`.
110
+ *
111
+ * @example
112
+ * ### Most common usage
113
+ * ```html
114
+ * <button [ssvCommand]="saveCmd">Save</button>
115
+ * ```
116
+ *
117
+ *
118
+ * ### Usage with options
119
+ * ```html
120
+ * <button [ssvCommand]="saveCmd" [ssvCommandOptions]="{executingCssClass: 'in-progress'}">Save</button>
121
+ * ```
122
+ *
123
+ *
124
+ * ### Usage with params
125
+ * This is useful for collections (loops) or using multiple actions with different args.
126
+ * *NOTE: This will share the `isExecuting` when used with multiple controls.*
127
+ *
128
+ * #### With single param (direct)
129
+ *
130
+ * ```html
131
+ * <button [ssvCommand]="saveCmd" [ssvCommandParams]="hero">Save</button>
132
+ * ```
133
+ *
134
+ * #### With single param (array)
135
+ *
136
+ * ```html
137
+ * <button [ssvCommand]="saveCmd" [ssvCommandParams]="[hero]">Save</button>
138
+ * ```
139
+ *
140
+ * *NOTE: if you have only 1 argument as an array, it should be enclosed within an array e.g. `[['apple', 'banana']]`,
141
+ * else it will spread and you will get `arg1: "apple", arg2: "banana"`*
142
+ *
143
+ * #### With multi params
144
+ * ```html
145
+ * <button [ssvCommand]="saveCmd" [ssvCommandParams]="[{id: 1}, 'hello', hero]">Save</button>
146
+ * ```
147
+ *
148
+ * ### Usage with Command Creator
149
+ * This is useful for collections (loops) or using multiple actions with different args, whilst not sharing `isExecuting`.
150
+ *
151
+ *
152
+ * ```html
153
+ * <button [ssvCommand]="{host: this, execute: removeHero$, canExecute: isValid$, params: [hero, 1337, 'xx']}">Save</button>
154
+ * ```
155
+ *
156
+ */
157
+ declare class SsvCommand<T extends ICommand | ExecuteFn = ExecuteFn> implements OnInit {
158
+ #private;
159
+ readonly commandOrCreator: _angular_core.InputSignal<T extends ICommand<ExecuteFn<any[], unknown>> ? T : ICommand<ExtractExecuteFn<T>> | CommandCreator<ExtractExecuteFn<T>>>;
65
160
  readonly ssvCommandOptions: _angular_core.InputSignal<Partial<CommandOptions>>;
66
161
  readonly commandOptions: _angular_core.Signal<CommandOptions>;
67
- readonly ssvCommandParams: _angular_core.InputSignal<unknown>;
68
- readonly commandParams: _angular_core.Signal<unknown>;
162
+ readonly ssvCommandParams: _angular_core.InputSignal<(CommandParams<ExtractExecuteFn<T>> extends infer T_1 ? { [KeyType in keyof T_1]: T_1[KeyType]; } : never) | undefined>;
163
+ readonly commandParams: _angular_core.Signal<Parameters<ExtractExecuteFn<T>> | undefined>;
69
164
  readonly _hostClasses: _angular_core.Signal<string[]>;
70
- private creatorParams;
71
- get command(): ICommand;
72
- private _command;
165
+ readonly command: _angular_core.Signal<ICommand<ExtractExecuteFn<T>>>;
73
166
  constructor();
74
167
  ngOnInit(): void;
75
168
  _handleClick(): void;
76
169
  private trySetDisabled;
77
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SsvCommand, never>;
78
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SsvCommand, "[ssvCommand]", ["ssvCommand"], { "commandOrCreator": { "alias": "ssvCommand"; "required": true; "isSignal": true; }; "ssvCommandOptions": { "alias": "ssvCommandOptions"; "required": false; "isSignal": true; }; "ssvCommandParams": { "alias": "ssvCommandParams"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
170
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SsvCommand<any>, never>;
171
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SsvCommand<any>, "[ssvCommand]", ["ssvCommand"], { "commandOrCreator": { "alias": "ssvCommand"; "required": true; "isSignal": true; }; "ssvCommandOptions": { "alias": "ssvCommandOptions"; "required": false; "isSignal": true; }; "ssvCommandParams": { "alias": "ssvCommandParams"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
79
172
  }
80
173
 
81
174
  /**
@@ -85,25 +178,23 @@ declare class SsvCommand implements OnInit {
85
178
  * ### Most common usage
86
179
  * ```html
87
180
  * <div #actionCmd="ssvCommandRef" [ssvCommandRef]="{host: this, execute: removeHero$, canExecute: isValid$}">
88
- * <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
181
+ * <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="[hero]">
89
182
  * Remove
90
183
  * </button>
91
- * <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
184
+ * <button [ssvCommand]="actionCmd.command()" [ssvCommandParams]="[hero]">
92
185
  * Remove
93
186
  * </button>
94
187
  * </div>
95
188
  * ```
96
189
  *
97
190
  */
98
- declare class SsvCommandRef implements OnInit {
191
+ declare class SsvCommandRef<TExecute extends ExecuteFn = ExecuteFn> implements OnInit {
99
192
  #private;
100
- readonly commandCreator: _angular_core.InputSignal<CommandCreator>;
101
- get command(): ICommand;
102
- private _command;
103
- constructor();
193
+ readonly commandCreator: _angular_core.InputSignal<CommandCreator<TExecute>>;
194
+ readonly command: _angular_core.Signal<ICommand<TExecute>>;
104
195
  ngOnInit(): void;
105
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SsvCommandRef, never>;
106
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SsvCommandRef, "[ssvCommandRef]", ["ssvCommandRef"], { "commandCreator": { "alias": "ssvCommandRef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
196
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SsvCommandRef<any>, never>;
197
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SsvCommandRef<any>, "[ssvCommandRef]", ["ssvCommandRef"], { "commandCreator": { "alias": "ssvCommandRef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
107
198
  }
108
199
 
109
200
  /** @deprecated Use standalone instead. */
@@ -113,65 +204,10 @@ declare class SsvCommandModule {
113
204
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<SsvCommandModule>;
114
205
  }
115
206
 
116
- interface CommandCreateOptions {
117
- isAsync: boolean;
118
- injector?: Injector;
119
- }
120
- /** Creates an async {@link Command}. Must be used within an injection context.
121
- * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
122
- */
123
- declare function commandAsync(execute: ExecuteAsyncFn, canExecute$?: CanExecute, opts?: Omit<CommandCreateOptions, "isAsync">): Command;
124
- /** Creates a {@link Command}. Must be used within an injection context.
125
- * NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
126
- */
127
- declare function command(execute: ExecuteFn, canExecute$?: CanExecute, opts?: CommandCreateOptions): Command;
128
- /**
129
- * Command object used to encapsulate information which is needed to perform an action.
130
- *
131
- */
132
- declare class Command implements ICommand {
133
- get isExecuting(): boolean;
134
- get canExecute(): boolean;
135
- readonly $isExecuting: _angular_core.WritableSignal<boolean>;
136
- readonly $canExecute: Signal<boolean>;
137
- private readonly _$canExecute;
138
- autoDestroy: boolean;
139
- private executionPipe$;
140
- private executionPipe$$;
141
- private subscribersCount;
142
- /**
143
- * Creates an instance of Command.
144
- *
145
- * @param execute Execute function to invoke - use `isAsync: true` when `Observable<any>`.
146
- * @param canExecute Observable which determines whether it can execute or not.
147
- * @param isAsync Indicates that the execute function is async e.g. Observable.
148
- * @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.
149
- */
150
- constructor(execute: ExecuteFn, canExecute$?: CanExecute, isAsync?: boolean, injector?: Injector);
151
- /** Execute function to invoke. */
152
- execute(...args: unknown[]): void;
153
- /** Disposes all resources held by subscriptions. */
154
- destroy(): void;
155
- subscribe(): void;
156
- unsubscribe(): void;
157
- private buildExecutionPipe;
158
- }
159
- /**
160
- * Async Command object used to encapsulate information which is needed to perform an action,
161
- * which takes an execute function as Observable/Promise.
162
- * @deprecated Use {@link commandAsync} instead.
163
- */
164
- declare class CommandAsync extends Command {
165
- /**
166
- * @deprecated Use {@link commandAsync} instead to create an instance.
167
- */
168
- constructor(execute: ExecuteAsyncFn, canExecute$?: CanExecute);
169
- }
170
-
171
207
  /** Determines whether the arg object is of type `Command`. */
172
- declare function isCommand(arg: unknown): arg is ICommand;
208
+ declare function isCommand<T extends ICommand>(arg: unknown | T): arg is T;
173
209
  /** Determines whether the arg object is of type `CommandCreator`. */
174
- declare function isCommandCreator(arg: unknown): arg is CommandCreator;
210
+ declare function isCommandCreator<T extends CommandCreator>(arg: unknown | T): arg is T;
175
211
  interface CanExecuteFormOptions {
176
212
  /** Determines whether to check for validity. (defaults: true) */
177
213
  validity?: boolean;
@@ -186,7 +222,7 @@ declare function canExecuteFromSignals(signals: {
186
222
  dirty: Signal<boolean>;
187
223
  }, options?: CanExecuteFormOptions): Signal<boolean>;
188
224
 
189
- declare const VERSION = "4.0.0-dev.98";
225
+ declare const VERSION = "5.0.0-dev.111";
190
226
 
191
- export { COMMAND_OPTIONS, Command, CommandAsync, SsvCommand, SsvCommandModule, SsvCommandRef, VERSION, canExecuteFromNgForm, canExecuteFromSignals, command, commandAsync, isCommand, isCommandCreator, provideSsvCommandOptions };
192
- export type { CanExecute, CanExecuteFormOptions, CommandCreateOptions, CommandCreator, CommandOptions, ExecuteAsyncFn, ExecuteFn, ICommand };
227
+ export { COMMAND_OPTIONS, Command, SsvCommand, SsvCommandModule, SsvCommandRef, VERSION, canExecuteFromNgForm, canExecuteFromSignals, command, commandAsync, isCommand, isCommandCreator, provideSsvCommandOptions };
228
+ export type { CanExecute, CanExecuteFormOptions, CommandCreateOptions, CommandCreator, CommandInput, CommandOptions, ExecuteFn, ICommand };