@shival99/z-ui 1.4.22 → 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();
@@ -355,29 +387,33 @@ class ZTableEditCellComponent {
355
387
  newValue,
356
388
  });
357
389
  }
358
- _emitChangeWithDebounce(oldValue, newValue) {
390
+ ngOnInit() {
359
391
  const config = this.editConfig();
360
- const debounceTime = config?.debounceTime;
361
- // If no debounceTime configured, emit immediately
362
- if (!debounceTime || debounceTime <= 0) {
363
- this._emitChange(oldValue, newValue);
364
- return;
365
- }
366
- // Clear previous timeout
367
- if (this._debounceTimeout) {
368
- clearTimeout(this._debounceTimeout);
369
- }
370
- // Schedule debounced emit
371
- this._debounceTimeout = setTimeout(() => {
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 }) => {
372
397
  this._emitChange(oldValue, newValue);
373
- this._debounceTimeout = null;
374
- }, 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
+ });
375
404
  }
376
- ngOnDestroy() {
377
- if (this._debounceTimeout) {
378
- clearTimeout(this._debounceTimeout);
379
- this._debounceTimeout = null;
380
- }
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
+ });
381
417
  }
382
418
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableEditCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
383
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: `
@@ -392,6 +428,16 @@ class ZTableEditCellComponent {
392
428
  />
393
429
  </div>
394
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
+ }
395
441
  @case ('number') {
396
442
  <z-input
397
443
  zType="number"
@@ -404,6 +450,7 @@ class ZTableEditCellComponent {
404
450
  [zDisabled]="isDisabled()"
405
451
  [ngModel]="numericValue()"
406
452
  (ngModelChange)="onValueChange($event)"
453
+ (zControl)="onInputControlReady($event)"
407
454
  class="w-full"
408
455
  />
409
456
  }
@@ -443,6 +490,7 @@ class ZTableEditCellComponent {
443
490
  [zDisabled]="isDisabled()"
444
491
  [ngModel]="stringValue()"
445
492
  (ngModelChange)="onValueChange($event)"
493
+ (zControl)="onInputControlReady($event)"
446
494
  class="w-full"
447
495
  />
448
496
  }
@@ -454,15 +502,16 @@ class ZTableEditCellComponent {
454
502
  [zDisabled]="isDisabled()"
455
503
  [ngModel]="stringValue()"
456
504
  (ngModelChange)="onValueChange($event)"
505
+ (zControl)="onInputControlReady($event)"
457
506
  class="w-full"
458
507
  />
459
508
  }
460
509
  }
461
- `, 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 });
462
511
  }
463
512
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZTableEditCellComponent, decorators: [{
464
513
  type: Component,
465
- 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: `
466
515
  @switch (editType()) {
467
516
  @case ('checkbox') {
468
517
  <div class="flex items-center justify-center">
@@ -474,6 +523,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
474
523
  />
475
524
  </div>
476
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
+ }
477
536
  @case ('number') {
478
537
  <z-input
479
538
  zType="number"
@@ -486,6 +545,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
486
545
  [zDisabled]="isDisabled()"
487
546
  [ngModel]="numericValue()"
488
547
  (ngModelChange)="onValueChange($event)"
548
+ (zControl)="onInputControlReady($event)"
489
549
  class="w-full"
490
550
  />
491
551
  }
@@ -525,6 +585,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
525
585
  [zDisabled]="isDisabled()"
526
586
  [ngModel]="stringValue()"
527
587
  (ngModelChange)="onValueChange($event)"
588
+ (zControl)="onInputControlReady($event)"
528
589
  class="w-full"
529
590
  />
530
591
  }
@@ -536,6 +597,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
536
597
  [zDisabled]="isDisabled()"
537
598
  [ngModel]="stringValue()"
538
599
  (ngModelChange)="onValueChange($event)"
600
+ (zControl)="onInputControlReady($event)"
539
601
  class="w-full"
540
602
  />
541
603
  }