@shival99/z-ui 1.4.21 → 1.4.23

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.
@@ -2,7 +2,7 @@ import { moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
2
2
  import { ScrollingModule } from '@angular/cdk/scrolling';
3
3
  import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
4
4
  import * as i0 from '@angular/core';
5
- import { input, output, computed, ChangeDetectionStrategy, Component, signal, inject, ElementRef, Renderer2, Directive, NgZone, Pipe, TemplateRef, viewChild, viewChildren, untracked, effect, afterNextRender } from '@angular/core';
5
+ import { input, output, computed, ChangeDetectionStrategy, Component, inject, DestroyRef, signal, ElementRef, Renderer2, Directive, NgZone, Pipe, TemplateRef, viewChild, viewChildren, untracked, effect, afterNextRender } from '@angular/core';
6
6
  import { TranslatePipe } from '@ngx-translate/core';
7
7
  import { injectVirtualizer } from '@shival99/angular-virtual';
8
8
  import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
@@ -23,10 +23,13 @@ import { NgScrollbar } from 'ngx-scrollbar';
23
23
  import { explicitEffect } from 'ngxtension/explicit-effect';
24
24
  import { injectDestroy } from 'ngxtension/inject-destroy';
25
25
  import { ZDropdownMenuComponent } from '@shival99/z-ui/components/z-dropdown-menu';
26
+ import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
26
27
  import * as i1 from '@angular/forms';
27
28
  import { FormsModule } from '@angular/forms';
28
29
  import { ZCalendarComponent } from '@shival99/z-ui/components/z-calendar';
29
30
  import { ZSelectComponent } from '@shival99/z-ui/components/z-select';
31
+ import { ZSwitchComponent } from '@shival99/z-ui/components/z-switch';
32
+ import { Subject, debounceTime, distinctUntilChanged, map, pairwise, filter } from 'rxjs';
30
33
 
31
34
  const Z_DEFAULT_ROW_HEIGHT = 40;
32
35
  const Z_DEFAULT_VIRTUAL_OVERSCAN = 5;
@@ -240,6 +243,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
240
243
  }], propDecorators: { zConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "zConfig", required: true }] }], zRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRow", required: true }] }], zRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRowId", required: true }] }], zDropdownButtonSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDropdownButtonSize", required: false }] }], zActionClick: [{ type: i0.Output, args: ["zActionClick"] }] } });
241
244
 
242
245
  class ZTableEditCellComponent {
246
+ _destroyRef = inject(DestroyRef);
243
247
  zRow = input.required(...(ngDevMode ? [{ debugName: "zRow" }] : []));
244
248
  zRowId = input.required(...(ngDevMode ? [{ debugName: "zRowId" }] : []));
245
249
  zRowIndex = input.required(...(ngDevMode ? [{ debugName: "zRowIndex" }] : []));
@@ -248,8 +252,11 @@ class ZTableEditCellComponent {
248
252
  zEditConfig = input(...(ngDevMode ? [undefined, { debugName: "zEditConfig" }] : []));
249
253
  zChange = output();
250
254
  _currentValue = signal(undefined, ...(ngDevMode ? [{ debugName: "_currentValue" }] : []));
255
+ _valueChange$ = new Subject();
251
256
  _initialized = false;
252
- _debounceTimeout = null;
257
+ _pendingBlurValue = undefined;
258
+ _hasPendingBlur = false;
259
+ _inputControl = null;
253
260
  editConfig = computed(() => {
254
261
  const config = this.zEditConfig();
255
262
  if (!config || typeof config === 'boolean') {
@@ -320,8 +327,33 @@ class ZTableEditCellComponent {
320
327
  const oldValue = this.zValue();
321
328
  this._currentValue.set(newValue);
322
329
  this._initialized = true;
323
- // Use debounce for typing controls (text, number, textarea)
324
- this._emitChangeWithDebounce(oldValue, newValue);
330
+ const config = this.editConfig();
331
+ // If blurEdit is enabled, store pending value and wait for blur
332
+ if (config?.blurEdit) {
333
+ this._pendingBlurValue = newValue;
334
+ this._hasPendingBlur = true;
335
+ return;
336
+ }
337
+ // Use RxJS Subject for debounce
338
+ this._valueChange$.next({ oldValue, newValue });
339
+ }
340
+ onInputControlReady(control) {
341
+ this._inputControl = control;
342
+ this._setupBlurWatcher();
343
+ }
344
+ _handleInputBlur() {
345
+ // Only emit if blurEdit is enabled and there's a pending value
346
+ if (!this._hasPendingBlur)
347
+ return;
348
+ const oldValue = this.zValue();
349
+ this._hasPendingBlur = false;
350
+ this._emitChange(oldValue, this._pendingBlurValue);
351
+ }
352
+ onToggleChange(checked) {
353
+ const oldValue = this.zValue();
354
+ this._currentValue.set(checked);
355
+ this._initialized = true;
356
+ this._emitChange(oldValue, checked);
325
357
  }
326
358
  onSelectChange(newValue) {
327
359
  const oldValue = this.zValue();
@@ -346,10 +378,6 @@ class ZTableEditCellComponent {
346
378
  this._emitChange(oldValue, checked);
347
379
  }
348
380
  _emitChange(oldValue, newValue) {
349
- const config = this.editConfig();
350
- if (config?.onChange) {
351
- config.onChange(newValue, this.zRow(), this.zColumnId());
352
- }
353
381
  this.zChange.emit({
354
382
  row: this.zRow(),
355
383
  rowId: this.zRowId(),
@@ -359,29 +387,33 @@ class ZTableEditCellComponent {
359
387
  newValue,
360
388
  });
361
389
  }
362
- _emitChangeWithDebounce(oldValue, newValue) {
390
+ ngOnInit() {
363
391
  const config = this.editConfig();
364
- const debounceTime = config?.debounceTime;
365
- // If no debounceTime configured, emit immediately
366
- if (!debounceTime || debounceTime <= 0) {
392
+ const debounceMs = config?.debounceTime ?? 0;
393
+ // Setup debounced value change subscription
394
+ this._valueChange$
395
+ .pipe(debounceTime(debounceMs), distinctUntilChanged((a, b) => a.newValue === b.newValue), takeUntilDestroyed(this._destroyRef))
396
+ .subscribe(({ oldValue, newValue }) => {
367
397
  this._emitChange(oldValue, newValue);
368
- return;
369
- }
370
- // Clear previous timeout
371
- if (this._debounceTimeout) {
372
- clearTimeout(this._debounceTimeout);
373
- }
374
- // Schedule debounced emit
375
- this._debounceTimeout = setTimeout(() => {
376
- this._emitChange(oldValue, newValue);
377
- this._debounceTimeout = null;
378
- }, debounceTime);
398
+ });
399
+ // Watch input control state for blur (for blurEdit feature)
400
+ // This is done via effect-like polling since control is set async
401
+ this._destroyRef.onDestroy(() => {
402
+ this._valueChange$.complete();
403
+ });
379
404
  }
380
- ngOnDestroy() {
381
- if (this._debounceTimeout) {
382
- clearTimeout(this._debounceTimeout);
383
- this._debounceTimeout = null;
384
- }
405
+ // Called from template when input control is ready
406
+ // We watch the state signal for blur changes using toObservable
407
+ _setupBlurWatcher() {
408
+ if (!this._inputControl || !this.editConfig()?.blurEdit)
409
+ return;
410
+ // Convert state signal to observable and watch for blur transitions
411
+ toObservable(this._inputControl.state)
412
+ .pipe(map(state => state.blurred), pairwise(), filter(([prev, curr]) => !prev && curr), // Only when transitioning to blurred
413
+ takeUntilDestroyed(this._destroyRef))
414
+ .subscribe(() => {
415
+ this._handleInputBlur();
416
+ });
385
417
  }
386
418
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableEditCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
387
419
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZTableEditCellComponent, isStandalone: true, selector: "z-table-edit-cell", inputs: { zRow: { classPropertyName: "zRow", publicName: "zRow", isSignal: true, isRequired: true, transformFunction: null }, zRowId: { classPropertyName: "zRowId", publicName: "zRowId", isSignal: true, isRequired: true, transformFunction: null }, zRowIndex: { classPropertyName: "zRowIndex", publicName: "zRowIndex", isSignal: true, isRequired: true, transformFunction: null }, zColumnId: { classPropertyName: "zColumnId", publicName: "zColumnId", isSignal: true, isRequired: true, transformFunction: null }, zValue: { classPropertyName: "zValue", publicName: "zValue", isSignal: true, isRequired: false, transformFunction: null }, zEditConfig: { classPropertyName: "zEditConfig", publicName: "zEditConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zChange: "zChange" }, host: { classAttribute: "z-table-edit-cell block" }, ngImport: i0, template: `
@@ -396,6 +428,16 @@ class ZTableEditCellComponent {
396
428
  />
397
429
  </div>
398
430
  }
431
+ @case ('toggle') {
432
+ <div class="flex items-center justify-center">
433
+ <z-switch
434
+ [zSize]="size()"
435
+ [zChecked]="booleanValue()"
436
+ [zDisabled]="isDisabled()"
437
+ (zChange)="onToggleChange($event)"
438
+ />
439
+ </div>
440
+ }
399
441
  @case ('number') {
400
442
  <z-input
401
443
  zType="number"
@@ -408,6 +450,7 @@ class ZTableEditCellComponent {
408
450
  [zDisabled]="isDisabled()"
409
451
  [ngModel]="numericValue()"
410
452
  (ngModelChange)="onValueChange($event)"
453
+ (zControl)="onInputControlReady($event)"
411
454
  class="w-full"
412
455
  />
413
456
  }
@@ -447,6 +490,7 @@ class ZTableEditCellComponent {
447
490
  [zDisabled]="isDisabled()"
448
491
  [ngModel]="stringValue()"
449
492
  (ngModelChange)="onValueChange($event)"
493
+ (zControl)="onInputControlReady($event)"
450
494
  class="w-full"
451
495
  />
452
496
  }
@@ -458,15 +502,16 @@ class ZTableEditCellComponent {
458
502
  [zDisabled]="isDisabled()"
459
503
  [ngModel]="stringValue()"
460
504
  (ngModelChange)="onValueChange($event)"
505
+ (zControl)="onInputControlReady($event)"
461
506
  class="w-full"
462
507
  />
463
508
  }
464
509
  }
465
- `, isInline: true, styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest"], outputs: ["zOnSearch", "zOnChange", "zControl"], exportAs: ["zInput"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zControl"], exportAs: ["zSelect"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange"], exportAs: ["zCalendar"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zChange", "zGroupChange", "zControl", "zCheckedChange", "zGroupValueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
510
+ `, isInline: true, styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest"], outputs: ["zOnSearch", "zOnChange", "zControl"], exportAs: ["zInput"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zControl"], exportAs: ["zSelect"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange"], exportAs: ["zCalendar"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zChange", "zGroupChange", "zControl", "zCheckedChange", "zGroupValueChange"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSize", "zLabel", "zText", "zDisabled", "zLoading", "zTextPosition", "zChecked"], outputs: ["zChange", "zCheckedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
466
511
  }
467
512
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableEditCellComponent, decorators: [{
468
513
  type: Component,
469
- args: [{ selector: 'z-table-edit-cell', imports: [FormsModule, ZInputComponent, ZSelectComponent, ZCalendarComponent, ZCheckboxComponent], standalone: true, template: `
514
+ args: [{ selector: 'z-table-edit-cell', imports: [FormsModule, ZInputComponent, ZSelectComponent, ZCalendarComponent, ZCheckboxComponent, ZSwitchComponent], standalone: true, template: `
470
515
  @switch (editType()) {
471
516
  @case ('checkbox') {
472
517
  <div class="flex items-center justify-center">
@@ -478,6 +523,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
478
523
  />
479
524
  </div>
480
525
  }
526
+ @case ('toggle') {
527
+ <div class="flex items-center justify-center">
528
+ <z-switch
529
+ [zSize]="size()"
530
+ [zChecked]="booleanValue()"
531
+ [zDisabled]="isDisabled()"
532
+ (zChange)="onToggleChange($event)"
533
+ />
534
+ </div>
535
+ }
481
536
  @case ('number') {
482
537
  <z-input
483
538
  zType="number"
@@ -490,6 +545,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
490
545
  [zDisabled]="isDisabled()"
491
546
  [ngModel]="numericValue()"
492
547
  (ngModelChange)="onValueChange($event)"
548
+ (zControl)="onInputControlReady($event)"
493
549
  class="w-full"
494
550
  />
495
551
  }
@@ -529,6 +585,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
529
585
  [zDisabled]="isDisabled()"
530
586
  [ngModel]="stringValue()"
531
587
  (ngModelChange)="onValueChange($event)"
588
+ (zControl)="onInputControlReady($event)"
532
589
  class="w-full"
533
590
  />
534
591
  }
@@ -540,6 +597,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
540
597
  [zDisabled]="isDisabled()"
541
598
  [ngModel]="stringValue()"
542
599
  (ngModelChange)="onValueChange($event)"
600
+ (zControl)="onInputControlReady($event)"
543
601
  class="w-full"
544
602
  />
545
603
  }