@masterteam/components 0.0.169 → 0.0.171

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.
Files changed (30) hide show
  1. package/assets/common.css +1 -1
  2. package/assets/i18n/ar.json +273 -278
  3. package/assets/i18n/en.json +273 -257
  4. package/fesm2022/masterteam-components-entities.mjs +97 -3
  5. package/fesm2022/masterteam-components-entities.mjs.map +1 -1
  6. package/fesm2022/masterteam-components-location-field.mjs +315 -0
  7. package/fesm2022/masterteam-components-location-field.mjs.map +1 -0
  8. package/fesm2022/masterteam-components-multi-select-field.mjs +2 -2
  9. package/fesm2022/masterteam-components-multi-select-field.mjs.map +1 -1
  10. package/fesm2022/masterteam-components-radio-cards-field.mjs +7 -4
  11. package/fesm2022/masterteam-components-radio-cards-field.mjs.map +1 -1
  12. package/fesm2022/masterteam-components-runtime-action.mjs +69 -34
  13. package/fesm2022/masterteam-components-runtime-action.mjs.map +1 -1
  14. package/fesm2022/masterteam-components-select-field.mjs +2 -2
  15. package/fesm2022/masterteam-components-select-field.mjs.map +1 -1
  16. package/fesm2022/masterteam-components-sidebar.mjs +2 -2
  17. package/fesm2022/masterteam-components-sidebar.mjs.map +1 -1
  18. package/fesm2022/masterteam-components-table.mjs +36 -8
  19. package/fesm2022/masterteam-components-table.mjs.map +1 -1
  20. package/fesm2022/masterteam-components-tabs.mjs +31 -3
  21. package/fesm2022/masterteam-components-tabs.mjs.map +1 -1
  22. package/fesm2022/masterteam-components.mjs +12 -1
  23. package/fesm2022/masterteam-components.mjs.map +1 -1
  24. package/package.json +5 -1
  25. package/types/masterteam-components-entities.d.ts +24 -5
  26. package/types/masterteam-components-location-field.d.ts +95 -0
  27. package/types/masterteam-components-radio-cards-field.d.ts +2 -1
  28. package/types/masterteam-components-runtime-action.d.ts +2 -1
  29. package/types/masterteam-components-tabs.d.ts +3 -0
  30. package/types/masterteam-components.d.ts +13 -3
@@ -291,7 +291,8 @@ class TableValueResolver {
291
291
  static matchesFilter(item, key, filterValue, column) {
292
292
  if (filterValue === null ||
293
293
  filterValue === undefined ||
294
- filterValue === '') {
294
+ filterValue === '' ||
295
+ (typeof filterValue === 'string' && filterValue.trim() === '')) {
295
296
  return true;
296
297
  }
297
298
  if (Array.isArray(filterValue)) {
@@ -370,9 +371,11 @@ class TableValueResolver {
370
371
  }
371
372
  if (typeof normalizedFilterValue === 'string' ||
372
373
  typeof normalizedFilterValue === 'number') {
374
+ // Trim the query so " john " matches "john smith"; the whitespace-only
375
+ // case already short-circuited via the guard above.
373
376
  return String(normalizedFilterValue)
374
377
  .toLowerCase()
375
- .includes(String(filterValue).toLowerCase());
378
+ .includes(String(filterValue).trim().toLowerCase());
376
379
  }
377
380
  return normalizedFilterValue === filterValue;
378
381
  }
@@ -396,6 +399,12 @@ class TableValueResolver {
396
399
  if (value === null || value === undefined || value === '') {
397
400
  return false;
398
401
  }
402
+ // A whitespace-only text filter is not a real value — keeps it out of the
403
+ // active-filter count and makes the column-filter Apply clear instead of
404
+ // committing " ".
405
+ if (typeof value === 'string') {
406
+ return value.trim().length > 0;
407
+ }
399
408
  if (Array.isArray(value)) {
400
409
  return value.length > 0;
401
410
  }
@@ -749,7 +758,7 @@ class TableFilterField {
749
758
  this.value.set({ ...current, [part]: next });
750
759
  }
751
760
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableFilterField, deps: [], target: i0.ɵɵFactoryTarget.Component });
752
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TableFilterField, isStandalone: true, selector: "mt-table-filter-field", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "@switch (getFilterType()) {\r\n @case (\"text\") {\r\n <mt-text-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n />\r\n }\r\n @case (\"select\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"userSelect\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [markCurrentUser]=\"true\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"date\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('from')\"\r\n (ngModelChange)=\"updateDate('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('to')\"\r\n (ngModelChange)=\"updateDate('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n @case (\"boolean\") {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"booleanOptions()\"\r\n [placeholder]=\"'components.table.select' | transloco\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n showClear\r\n />\r\n }\r\n @case (\"user\") {\r\n <mt-user-search-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"column().filterConfig?.label || column().label\"\r\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\r\n [context]=\"column().filterConfig?.context\"\r\n />\r\n }\r\n @case (\"numberRange\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('from')\"\r\n (ngModelChange)=\"updateNumber('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('to')\"\r\n (ngModelChange)=\"updateNumber('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: UserSearchField, selector: "mt-user-search-field", inputs: ["hint", "label", "placeholder", "class", "readonly", "required", "isMultiple", "apiUrl", "dataKey", "paramName", "context", "size"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
761
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TableFilterField, isStandalone: true, selector: "mt-table-filter-field", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "@switch (getFilterType()) {\r\n @case (\"text\") {\r\n <mt-text-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n />\r\n }\r\n @case (\"select\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"userSelect\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [markCurrentUser]=\"true\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"date\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('from')\"\r\n (ngModelChange)=\"updateDate('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('to')\"\r\n (ngModelChange)=\"updateDate('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n @case (\"boolean\") {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"booleanOptions()\"\r\n [placeholder]=\"'components.table.select' | transloco\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n @case (\"user\") {\r\n <mt-user-search-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"column().filterConfig?.label || column().label\"\r\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\r\n [context]=\"column().filterConfig?.context\"\r\n />\r\n }\r\n @case (\"numberRange\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('from')\"\r\n (ngModelChange)=\"updateNumber('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('to')\"\r\n (ngModelChange)=\"updateNumber('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: UserSearchField, selector: "mt-user-search-field", inputs: ["hint", "label", "placeholder", "class", "readonly", "required", "isMultiple", "apiUrl", "dataKey", "paramName", "context", "size"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
753
762
  }
754
763
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableFilterField, decorators: [{
755
764
  type: Component,
@@ -762,7 +771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
762
771
  DateField,
763
772
  UserSearchField,
764
773
  TranslocoModule,
765
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (getFilterType()) {\r\n @case (\"text\") {\r\n <mt-text-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n />\r\n }\r\n @case (\"select\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"userSelect\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [markCurrentUser]=\"true\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"date\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('from')\"\r\n (ngModelChange)=\"updateDate('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('to')\"\r\n (ngModelChange)=\"updateDate('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n @case (\"boolean\") {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"booleanOptions()\"\r\n [placeholder]=\"'components.table.select' | transloco\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n showClear\r\n />\r\n }\r\n @case (\"user\") {\r\n <mt-user-search-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"column().filterConfig?.label || column().label\"\r\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\r\n [context]=\"column().filterConfig?.context\"\r\n />\r\n }\r\n @case (\"numberRange\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('from')\"\r\n (ngModelChange)=\"updateNumber('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('to')\"\r\n (ngModelChange)=\"updateNumber('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n}\r\n" }]
774
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (getFilterType()) {\r\n @case (\"text\") {\r\n <mt-text-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n />\r\n }\r\n @case (\"select\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"userSelect\") {\r\n @if (isMultiple()) {\r\n <mt-multi-select-field\r\n [ngModel]=\"multiValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n filterBy=\"label\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"filterOptions()\"\r\n [placeholder]=\"\r\n ('components.table.select' | transloco) +\r\n ' ' +\r\n (column().filterConfig?.label || column().label)\r\n \"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [markCurrentUser]=\"true\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n }\r\n @case (\"date\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('from')\"\r\n (ngModelChange)=\"updateDate('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-date-field\r\n [ngModel]=\"getDateRangeValue('to')\"\r\n (ngModelChange)=\"updateDate('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n @case (\"boolean\") {\r\n <mt-select-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [options]=\"booleanOptions()\"\r\n [placeholder]=\"'components.table.select' | transloco\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n showClear\r\n />\r\n }\r\n @case (\"user\") {\r\n <mt-user-search-field\r\n [ngModel]=\"getScalarValue()\"\r\n (ngModelChange)=\"updateScalar($event)\"\r\n [placeholder]=\"column().filterConfig?.label || column().label\"\r\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\r\n [context]=\"column().filterConfig?.context\"\r\n />\r\n }\r\n @case (\"numberRange\") {\r\n <div class=\"space-y-3\">\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.from\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('from')\"\r\n (ngModelChange)=\"updateNumber('from', $event)\"\r\n [placeholder]=\"'components.table.from' | transloco\"\r\n />\r\n </div>\r\n <div class=\"space-y-1\">\r\n <label\r\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\r\n >\r\n {{ \"components.table.to\" | transloco }}\r\n </label>\r\n <mt-number-field\r\n [ngModel]=\"getNumberRangeValue('to')\"\r\n (ngModelChange)=\"updateNumber('to', $event)\"\r\n [placeholder]=\"'components.table.to' | transloco\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n}\r\n" }]
766
775
  }], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
767
776
 
768
777
  class TableFilter {
@@ -886,8 +895,16 @@ class TableCaption {
886
895
  (this.tabs()?.length ?? 0) > 0 ||
887
896
  this.actions().length > 0, ...(ngDevMode ? [{ debugName: "showsAnything" }] : /* istanbul ignore next */ []));
888
897
  onSearch(term) {
889
- this.filterTerm.set(term);
890
- this.searchChange.emit(term);
898
+ // Single source of truth for the search box shared by mt-table and the
899
+ // cards view. A whitespace-only query is meaningless, so collapse it to
900
+ // '' here — otherwise a literal " " substring-matches almost every row
901
+ // (local) or is sent verbatim as `generalSearch` (lazy). `.trim()` is
902
+ // idempotent against typing multi-word terms ("John Doe"): a trailing
903
+ // space yields the same value as before, the model signal doesn't
904
+ // re-emit, and the input keeps the space the user just typed.
905
+ const normalized = term.trim();
906
+ this.filterTerm.set(normalized);
907
+ this.searchChange.emit(normalized);
891
908
  }
892
909
  onFilterApplied(next) {
893
910
  this.filters.set(next);
@@ -952,6 +969,11 @@ class TableColumnFilter {
952
969
  cloneValue(value) {
953
970
  if (value === null || value === undefined)
954
971
  return null;
972
+ // Arrays must stay arrays — `{ ...array }` would turn a multi-select
973
+ // value (e.g. ["a","b"]) into {0:"a",1:"b"}, which then matches no
974
+ // option when the popover is reopened, dropping the selection.
975
+ if (Array.isArray(value))
976
+ return [...value];
955
977
  if (typeof value === 'object')
956
978
  return { ...value };
957
979
  return value;
@@ -1373,7 +1395,9 @@ class Table {
1373
1395
  const data = this.data();
1374
1396
  const applyLocalSearch = !this.lazy() || this.lazyLocalSearch();
1375
1397
  const applyLocalSort = !this.lazy() || this.lazyLocalSort();
1376
- const searchTerm = applyLocalSearch ? this.filterTerm().toLowerCase() : '';
1398
+ const searchTerm = applyLocalSearch
1399
+ ? this.filterTerm().trim().toLowerCase()
1400
+ : '';
1377
1401
  const filters = this.filters();
1378
1402
  const filterKeys = this.lazy() ? [] : Object.keys(filters);
1379
1403
  let result = data;
@@ -1642,7 +1666,11 @@ class Table {
1642
1666
  this.first.set(0);
1643
1667
  this.currentPage.set(0);
1644
1668
  if (this.lazy() && !this.lazyLocalSearch()) {
1645
- this.filters.set({ ...this.filters(), generalSearch: searchTerm });
1669
+ const trimmedSearchTerm = searchTerm.trim();
1670
+ this.filters.set({
1671
+ ...this.filters(),
1672
+ generalSearch: trimmedSearchTerm,
1673
+ });
1646
1674
  this.emitLazyLoad({});
1647
1675
  }
1648
1676
  }