@ai-table/grid 0.1.12 → 0.1.13

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, input, EventEmitter, inject, ElementRef, effect, Output, ChangeDetectionStrategy, Component, signal, computed, output, Input, ChangeDetectorRef, ViewChild, Renderer2, Pipe, model, booleanAttribute, Injectable, DestroyRef, NgZone, ViewContainerRef, viewChild, afterNextRender, untracked } from '@angular/core';
2
+ import { InjectionToken, input, EventEmitter, inject, ElementRef, effect, Output, ChangeDetectionStrategy, Component, signal, computed, output, Input, ChangeDetectorRef, ViewChild, Renderer2, Pipe, Injectable, DestroyRef, model, booleanAttribute, NgZone, ViewContainerRef, viewChild, afterNextRender, untracked } from '@angular/core';
3
3
  import Konva from 'konva';
4
4
  import { Shape } from 'konva/lib/Shape';
5
5
  import { Sprite } from 'konva/lib/shapes/Sprite';
@@ -25,7 +25,7 @@ import { Transformer } from 'konva/lib/shapes/Transformer';
25
25
  import { Wedge } from 'konva/lib/shapes/Wedge';
26
26
  import * as i1$1 from 'ngx-tethys/popover';
27
27
  import { ThyPopoverRef, ThyPopover, ThyPopoverModule } from 'ngx-tethys/popover';
28
- import { AITableFieldGroup, AITableFieldType, AITableRowColumnType, DragType, isUndefinedOrNull, isUrl, AITableSelectOptionStyle, isEmpty, AITableFilterOperation, AttachmentFieldBase, DateFieldBase, isDateValid, SelectFieldBase, LinkFieldBase, MemberFieldBase, NumberFieldBase, ProgressFieldBase, RateFieldBase, RichTextFieldBase, TextFieldBase, FieldModelBaseMap } from '@ai-table/utils';
28
+ import { AITableFieldGroup, AITableFieldType, AITableRowColumnType, DragType, isUndefinedOrNull, idCreator as idCreator$1, isUrl, AITableSelectOptionStyle, isEmpty, AITableFilterOperation, AttachmentFieldBase, DateFieldBase, isDateValid, SelectFieldBase, generateOptionsByTexts, LinkFieldBase, MemberFieldBase, NumberFieldBase, ProgressFieldBase, RateFieldBase, RichTextFieldBase, TextFieldBase, FieldModelBaseMap } from '@ai-table/utils';
29
29
  import ObjectID from 'bson-objectid';
30
30
  import { customAlphabet } from 'nanoid';
31
31
  import * as _ from 'lodash';
@@ -53,23 +53,23 @@ import { ThySelect, ThySelectModule } from 'ngx-tethys/select';
53
53
  import { ThyDot } from 'ngx-tethys/dot';
54
54
  import { ThyIcon } from 'ngx-tethys/icon';
55
55
  import { ThyTag } from 'ngx-tethys/tag';
56
- import { ThyDropdownMenuComponent, ThyDropdownMenuGroup, ThyDropdownDirective, ThyDropdownMenuItemDirective, ThyDropdownMenuItemIconDirective, ThyDropdownMenuItemNameDirective, ThyDropdownMenuItemExtendIconDirective, ThyDropdownAbstractMenu, ThyDropdownMenuItemMetaDirective } from 'ngx-tethys/dropdown';
56
+ import { ThyDropdownAbstractMenu, ThyDropdownMenuItemDirective, ThyDropdownMenuItemNameDirective, ThyDropdownMenuItemIconDirective, ThyDropdownMenuItemMetaDirective, ThyDropdownMenuComponent, ThyDropdownMenuGroup, ThyDropdownDirective, ThyDropdownMenuItemExtendIconDirective } from 'ngx-tethys/dropdown';
57
57
  import { ThySwitch } from 'ngx-tethys/switch';
58
- import { of, Subject, fromEvent, debounceTime, mergeWith, animationFrames, filter } from 'rxjs';
58
+ import { Subject, fromEvent, debounceTime, of, mergeWith, animationFrames, filter } from 'rxjs';
59
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
59
60
  import { ThyDivider } from 'ngx-tethys/divider';
61
+ import { isKeyHotkey } from 'is-hotkey';
62
+ import { fromUnixTime, subDays } from 'date-fns';
63
+ import { isArray, TinyDate, helpers } from 'ngx-tethys/util';
64
+ import { DEFAULT_COLORS } from 'ngx-tethys/color-picker';
65
+ import { LRUCache } from 'lru-cache';
66
+ import GraphemeSplitter from 'grapheme-splitter';
60
67
  import * as i4 from 'ngx-tethys/avatar';
61
68
  import { ThyAvatarModule } from 'ngx-tethys/avatar';
62
69
  import * as i3$1 from 'ngx-tethys/checkbox';
63
70
  import { ThyCheckboxModule } from 'ngx-tethys/checkbox';
64
71
  import { ThyProgress } from 'ngx-tethys/progress';
65
72
  import { ThyRate } from 'ngx-tethys/rate';
66
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
67
- import { fromUnixTime, subDays } from 'date-fns';
68
- import { isArray, TinyDate, helpers } from 'ngx-tethys/util';
69
- import { DEFAULT_COLORS } from 'ngx-tethys/color-picker';
70
- import { isKeyHotkey } from 'is-hotkey';
71
- import { LRUCache } from 'lru-cache';
72
- import GraphemeSplitter from 'grapheme-splitter';
73
73
  import { takeWhile, map } from 'rxjs/operators';
74
74
 
75
75
  const KO_CONTAINER_TOKEN = new InjectionToken('KO_CONTAINER_TOKEN');
@@ -1245,7 +1245,7 @@ function isSameFieldOption(fieldOption, field) {
1245
1245
  function createDefaultField(aiTable, type = AITableFieldType.text) {
1246
1246
  const fieldOptions = getFieldOptions(aiTable);
1247
1247
  const fieldOption = fieldOptions.find((item) => item.type === type);
1248
- return { _id: idCreator(), type, name: createDefaultFieldName(aiTable, fieldOption) };
1248
+ return { _id: idCreator$1(), type, name: createDefaultFieldName(aiTable, fieldOption) };
1249
1249
  }
1250
1250
 
1251
1251
  function getFieldValue(record, field) {
@@ -1943,317 +1943,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
1943
1943
  }]
1944
1944
  }] });
1945
1945
 
1946
- class AITableFieldSetting {
1947
- constructor() {
1948
- this.aiEditField = model.required();
1949
- this.aiTable = input.required();
1950
- this.aiExternalTemplate = input(null);
1951
- this.isUpdate = input(false, { transform: booleanAttribute });
1952
- this.addField = output();
1953
- this.setField = output();
1954
- this.selectedFieldOption = computed(() => {
1955
- return getFieldOptionByField(this.aiTable(), this.aiEditField());
1956
- });
1957
- this.fieldMaxLength = 32;
1958
- this.validatorConfig = computed(() => {
1959
- return {
1960
- validationMessages: {
1961
- fieldName: {
1962
- required: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldNameRequired),
1963
- thyUniqueCheck: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldNameDuplicate)
1964
- }
1965
- }
1966
- };
1967
- });
1968
- this.fieldOptions = computed(() => {
1969
- const fieldOptions = getFieldOptions(this.aiTable());
1970
- return _.groupBy(fieldOptions, 'group');
1971
- });
1972
- this.aITableFieldType = AITableFieldType;
1973
- this.isMultipleMember = false;
1974
- this.isManualInputName = signal(false);
1975
- this.thyPopoverRef = inject((ThyPopoverRef));
1976
- this.checkUniqueName = (fieldName) => {
1977
- fieldName = fieldName?.trim();
1978
- return of(!!this.aiTable()
1979
- .fields()
1980
- ?.find((field) => field.name === fieldName && this.aiEditField()?._id !== field._id));
1981
- };
1982
- this.i18nTexts = computed(() => {
1983
- return {
1984
- columnName: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldColumnName),
1985
- columnNamePlaceholder: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldColumnNamePlaceholder),
1986
- fieldType: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldType),
1987
- allowMultipleMembers: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.allowMultipleMembers),
1988
- cancel: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.cancel),
1989
- confirm: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.confirm),
1990
- base: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldGroupBase),
1991
- advanced: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldGroupAdvanced)
1992
- };
1993
- });
1994
- }
1995
- ngOnInit() {
1996
- this.isMultipleMember =
1997
- this.aiEditField().type === AITableFieldType.member && !!this.aiEditField().settings?.is_multiple;
1998
- }
1999
- selectFieldType(field) {
2000
- const fieldsSizeMap = this.aiTable().gridData().fieldsSizeMap;
2001
- this.aiEditField.update((item) => {
2002
- const width = fieldsSizeMap[item._id] ?? field.width;
2003
- const settings = field.settings || {};
2004
- const name = this.isManualInputName() ? item.name : createDefaultFieldName(this.aiTable(), field);
2005
- return { ...item, ...field, width, name, settings };
2006
- });
2007
- setTimeout(() => {
2008
- this.thyPopoverRef.updatePosition();
2009
- }, 0);
2010
- }
2011
- editFieldProperty() {
2012
- if (this.isUpdate()) {
2013
- this.setField.emit({
2014
- field: this.aiEditField(),
2015
- path: [this.aiEditField()._id]
1946
+ const buildGridLinearRows = (visibleRecords, isAddingVisible = true) => {
1947
+ const linearRows = [];
1948
+ let displayRowIndex = 0;
1949
+ [...visibleRecords, { _id: '' }].forEach((row) => {
1950
+ if (row._id) {
1951
+ displayRowIndex++;
1952
+ linearRows.push({
1953
+ type: AITableRowType.record,
1954
+ _id: row._id,
1955
+ displayIndex: displayRowIndex
2016
1956
  });
2017
1957
  }
2018
- else {
2019
- this.addField.emit(this.aiEditField());
1958
+ if (isAddingVisible && !row._id) {
1959
+ linearRows.push({
1960
+ type: AITableRowType.add,
1961
+ _id: ''
1962
+ });
2020
1963
  }
2021
- this.thyPopoverRef.close();
2022
- }
2023
- multipleMemberChange() {
2024
- this.aiEditField.set({
2025
- ...this.aiEditField(),
2026
- settings: {
2027
- ...(this.aiEditField().settings || {}),
2028
- is_multiple: this.isMultipleMember
2029
- }
2030
- });
2031
- }
2032
- fieldTypeClick(e) {
2033
- e.preventDefault();
2034
- e.stopPropagation();
2035
- }
2036
- nameChange(event) {
2037
- this.isManualInputName.set(true);
2038
- }
2039
- cancel() {
2040
- this.thyPopoverRef.close();
2041
- }
2042
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldSetting, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2043
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableFieldSetting, isStandalone: true, selector: "ai-table-field-setting", inputs: { aiEditField: { classPropertyName: "aiEditField", publicName: "aiEditField", isSignal: true, isRequired: true, transformFunction: null }, aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: true, isRequired: true, transformFunction: null }, aiExternalTemplate: { classPropertyName: "aiExternalTemplate", publicName: "aiExternalTemplate", isSignal: true, isRequired: false, transformFunction: null }, isUpdate: { classPropertyName: "isUpdate", publicName: "isUpdate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { aiEditField: "aiEditFieldChange", addField: "addField", setField: "setField" }, host: { classAttribute: "field-setting d-block pl-5 pr-5 pb-5 pt-4" }, ngImport: i0, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig()\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired [thyLabelText]=\"i18nTexts().columnName\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiEditField().name\"\n (ngModelChange)=\"nameChange($event)\"\n required\n [placeholder]=\"i18nTexts().columnNamePlaceholder\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group [thyLabelText]=\"i18nTexts().fieldType\">\n <div class=\"thy-dropdown-menu py-0\">\n <div class=\"ml-n5 mr-n5\">\n <span\n thyDropdownMenuItem\n [thyDropdown]=\"menu\"\n [thyDisabled]=\"isUpdate()\"\n thyTrigger=\"hover\"\n thyPlacement=\"right\"\n (click)=\"fieldTypeClick($event)\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"selectedFieldOption().icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ selectedFieldOption().name }}</span>\n <thy-icon thyDropdownMenuItemExtendIcon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </span>\n </div>\n </div>\n\n @if (selectedFieldOption().type === aITableFieldType.member) {\n <div class=\"d-flex justify-content-between mt-3\">\n {{ i18nTexts().allowMultipleMembers }}\n <thy-switch\n name=\"isMultipleMember\"\n [thyDisabled]=\"isUpdate()\"\n [(ngModel)]=\"isMultipleMember\"\n (ngModelChange)=\"multipleMemberChange()\"\n thySize=\"sm\"\n ></thy-switch>\n </div>\n }\n </thy-form-group>\n @if (aiExternalTemplate()) {\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate()\"></ng-container>\n }\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">{{ i18nTexts().cancel }}</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">{{ i18nTexts().confirm }}</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().base\">\n @for (item of fieldOptions().base; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().advanced\">\n @for (item of fieldOptions().advanced; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyInputGroup, selector: "thy-input-group", inputs: ["thyAppendText", "thyAppendTextTranslateKey", "thyPrependText", "thyPrependTextTranslateKey", "thySize"] }, { kind: "component", type: ThyInputCount, selector: "thy-input-count", inputs: ["thyInput"] }, { kind: "directive", type: ThyInputDirective, selector: "input[thyInput], select[thyInput], textarea[thyInput]", inputs: ["thySize"], exportAs: ["thyInput"] }, { kind: "directive", type: ThyUniqueCheckValidator, selector: "[thyUniqueCheck]", inputs: ["thyUniqueCheck"] }, { kind: "component", type: ThyDropdownMenuComponent, selector: "thy-dropdown-menu", inputs: ["thyWidth", "thyImmediateRender"] }, { kind: "component", type: ThyDropdownMenuGroup, selector: "thy-dropdown-menu-group", inputs: ["thyTitle"] }, { kind: "directive", type: ThyDropdownDirective, selector: "[thyDropdown]", inputs: ["thyDropdownMenu", "thyDropdown", "thyTrigger", "thyShowDelay", "thyHideDelay", "thyActiveClass", "thyPopoverOptions", "thyPlacement", "thyMenuInsideClosable", "thyPanelClass"], outputs: ["thyActiveChange"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemIconDirective, selector: "[thyDropdownMenuItemIcon]" }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "directive", type: ThyDropdownMenuItemExtendIconDirective, selector: "[thyDropdownMenuItemExtendIcon]" }, { kind: "component", type: ThyButton, selector: "thy-button,[thy-button],[thyButton]", inputs: ["thyButton", "thyType", "thyLoading", "thyLoadingText", "thySize", "thyIcon", "thyBlock"] }, { kind: "component", type: ThySwitch, selector: "thy-switch", inputs: ["thyType", "thySize", "thyDisabled", "thyLoading"], outputs: ["thyChange"] }, { kind: "ngmodule", type: ThyFormModule }, { kind: "directive", type: i2.ThyFormDirective, selector: "[thyForm],[thy-form]", inputs: ["thyLayout", "thyEnterKeyMode", "thyFormValidatorConfig"], exportAs: ["thyForm"] }, { kind: "component", type: i2.ThyFormGroup, selector: "thy-form-group", inputs: ["thyLabelText", "thyLabelTextTranslateKey", "thyLabelRequired", "thyLabelPaddingTopClear", "thyFeedbackIcon", "thyTipsMode", "thyTips", "thyTipsTranslateKey", "thyRowFill"] }, { kind: "directive", type: i2.ThyFormSubmitDirective, selector: "[thyFormSubmit],[thy-form-submit]", outputs: ["thyFormSubmit"] }, { kind: "component", type: i2.ThyFormGroupFooter, selector: "thy-form-group-footer", inputs: ["thyAlign"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ThyAutofocusDirective, selector: "input[thyAutofocus],textarea[thyAutofocus]", inputs: ["thyAutofocus", "thyAutoSelect"] }, { kind: "pipe", type: AITableFieldIsSameOptionPipe, name: "fieldIsSameOption" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2044
- }
2045
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldSetting, decorators: [{
2046
- type: Component,
2047
- args: [{ selector: 'ai-table-field-setting', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2048
- NgClass,
2049
- FormsModule,
2050
- ThyIcon,
2051
- ThyInputGroup,
2052
- ThyInputCount,
2053
- ThyInputDirective,
2054
- ThyUniqueCheckValidator,
2055
- ThyDropdownMenuComponent,
2056
- ThyDropdownMenuGroup,
2057
- ThyDropdownDirective,
2058
- ThyDropdownMenuItemDirective,
2059
- ThyDropdownMenuItemIconDirective,
2060
- ThyDropdownMenuItemNameDirective,
2061
- ThyDropdownMenuItemExtendIconDirective,
2062
- ThyButton,
2063
- ThySwitch,
2064
- ThyFormModule,
2065
- NgTemplateOutlet,
2066
- ThyAutofocusDirective,
2067
- AITableFieldIsSameOptionPipe
2068
- ], host: {
2069
- class: 'field-setting d-block pl-5 pr-5 pb-5 pt-4'
2070
- }, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig()\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired [thyLabelText]=\"i18nTexts().columnName\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiEditField().name\"\n (ngModelChange)=\"nameChange($event)\"\n required\n [placeholder]=\"i18nTexts().columnNamePlaceholder\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group [thyLabelText]=\"i18nTexts().fieldType\">\n <div class=\"thy-dropdown-menu py-0\">\n <div class=\"ml-n5 mr-n5\">\n <span\n thyDropdownMenuItem\n [thyDropdown]=\"menu\"\n [thyDisabled]=\"isUpdate()\"\n thyTrigger=\"hover\"\n thyPlacement=\"right\"\n (click)=\"fieldTypeClick($event)\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"selectedFieldOption().icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ selectedFieldOption().name }}</span>\n <thy-icon thyDropdownMenuItemExtendIcon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </span>\n </div>\n </div>\n\n @if (selectedFieldOption().type === aITableFieldType.member) {\n <div class=\"d-flex justify-content-between mt-3\">\n {{ i18nTexts().allowMultipleMembers }}\n <thy-switch\n name=\"isMultipleMember\"\n [thyDisabled]=\"isUpdate()\"\n [(ngModel)]=\"isMultipleMember\"\n (ngModelChange)=\"multipleMemberChange()\"\n thySize=\"sm\"\n ></thy-switch>\n </div>\n }\n </thy-form-group>\n @if (aiExternalTemplate()) {\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate()\"></ng-container>\n }\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">{{ i18nTexts().cancel }}</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">{{ i18nTexts().confirm }}</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().base\">\n @for (item of fieldOptions().base; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().advanced\">\n @for (item of fieldOptions().advanced; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"] }]
2071
- }] });
2072
-
2073
- class AITableGridSelectionService {
2074
- constructor() {
2075
- this.selectAllState = computed(() => {
2076
- const selectedRecords = this.aiTable.selection().selectedRecords;
2077
- return selectedRecords.size === this.aiTable.records().length
2078
- ? AITableSelectAllState.all
2079
- : selectedRecords.size === 0
2080
- ? AITableSelectAllState.none
2081
- : AITableSelectAllState.partial;
2082
- });
2083
- }
2084
- initialize(aiTable) {
2085
- this.aiTable = aiTable;
2086
- }
2087
- clearSelection() {
2088
- this.aiTable.selection.set({
2089
- selectedRecords: new Set(),
2090
- selectedFields: new Set(),
2091
- selectedCells: new Set(),
2092
- activeCell: null,
2093
- expandCell: null,
2094
- selectAllState: AITableSelectAllState.none
2095
- });
2096
- }
2097
- setActiveCell(activeCell) {
2098
- this.aiTable.selection().activeCell = activeCell;
2099
- }
2100
- setExpandCell(expandCell) {
2101
- this.aiTable.selection.set({
2102
- ...this.aiTable.selection(),
2103
- expandCell: expandCell
2104
- });
2105
- }
2106
- selectField(fieldId) {
2107
- if (this.aiTable.selection().selectedFields.has(fieldId)) {
2108
- return;
2109
- }
2110
- this.clearSelection();
2111
- this.aiTable.selection().selectedFields.add(fieldId);
2112
- }
2113
- get selectedFields() {
2114
- return this.aiTable.selection().selectedFields;
2115
- }
2116
- get selectedRecords() {
2117
- return this.aiTable.selection().selectedRecords;
2118
- }
2119
- selectRecord(recordId) {
2120
- if (this.aiTable.selection().selectedRecords.has(recordId)) {
2121
- this.aiTable.selection().selectedRecords.delete(recordId);
2122
- }
2123
- else {
2124
- this.aiTable.selection().selectedRecords.add(recordId);
2125
- }
2126
- const selectedRecords = this.aiTable.selection().selectedRecords;
2127
- this.aiTable.selection.set({
2128
- selectedRecords: selectedRecords,
2129
- selectedFields: new Set(),
2130
- selectedCells: new Set(),
2131
- activeCell: null,
2132
- expandCell: null,
2133
- selectAllState: this.selectAllState()
2134
- });
2135
- }
2136
- toggleSelectAll(checked) {
2137
- if (checked) {
2138
- if (this.aiTable.records().length === 0) {
2139
- this.aiTable.selection.set({
2140
- ...this.aiTable.selection(),
2141
- selectAllState: AITableSelectAllState.all
2142
- });
2143
- }
2144
- else {
2145
- this.aiTable.records().forEach((item) => {
2146
- this.selectRecord(item._id);
2147
- });
2148
- }
2149
- }
2150
- else {
2151
- this.clearSelection();
2152
- }
2153
- }
2154
- updateSelect(event) {
2155
- const target = event?.target;
2156
- if (!target) {
2157
- return;
2158
- }
2159
- const cellDom = target.closest('.grid-cell');
2160
- const colDom = target.closest('.grid-field');
2161
- const checkbox = target.tagName === 'INPUT' && target.type === 'checkbox' && target.closest('.grid-checkbox');
2162
- const fieldAction = target.closest('.grid-field-action');
2163
- if (cellDom) {
2164
- const fieldId = cellDom.getAttribute('fieldId');
2165
- const recordId = cellDom.getAttribute('recordId');
2166
- fieldId && recordId && this.selectCells([recordId, fieldId]);
2167
- }
2168
- if (colDom && !fieldAction) {
2169
- const fieldId = colDom.getAttribute('fieldId');
2170
- fieldId && this.selectField(fieldId);
2171
- }
2172
- if (!cellDom && !colDom && !checkbox) {
2173
- this.clearSelection();
2174
- }
2175
- }
2176
- selectCells(startCell, endCell) {
2177
- const [startRecordId, startFieldId] = startCell;
2178
- const records = this.aiTable.context.linearRows();
2179
- const fields = AITable.getVisibleFields(this.aiTable);
2180
- const selectedCells = new Set();
2181
- if (!endCell) {
2182
- selectedCells.add(`${startRecordId}:${startFieldId}`);
2183
- }
2184
- else {
2185
- const [endRecordId, endFieldId] = endCell;
2186
- const startRowIndex = this.aiTable.context.visibleRowsIndexMap().get(startRecordId);
2187
- const endRowIndex = this.aiTable.context.visibleRowsIndexMap().get(endRecordId);
2188
- const startColIndex = this.aiTable.context.visibleColumnsIndexMap().get(startFieldId);
2189
- const endColIndex = this.aiTable.context.visibleColumnsIndexMap().get(endFieldId);
2190
- const minRowIndex = Math.min(startRowIndex, endRowIndex);
2191
- const maxRowIndex = Math.max(startRowIndex, endRowIndex);
2192
- const minColIndex = Math.min(startColIndex, endColIndex);
2193
- const maxColIndex = Math.max(startColIndex, endColIndex);
2194
- for (let i = minRowIndex; i <= maxRowIndex; i++) {
2195
- for (let j = minColIndex; j <= maxColIndex; j++) {
2196
- selectedCells.add(`${records[i]._id}:${fields[j]._id}`);
2197
- }
2198
- }
2199
- }
2200
- this.clearSelection();
2201
- this.setActiveCell(startCell);
2202
- this.aiTable.selection().selectedCells = selectedCells;
2203
- }
2204
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2205
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService }); }
2206
- }
2207
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService, decorators: [{
2208
- type: Injectable
2209
- }], ctorParameters: () => [] });
2210
-
2211
- class AITableContextMenu extends ThyDropdownAbstractMenu {
2212
- constructor() {
2213
- super(...arguments);
2214
- this.aiTableGridSelectionService = inject(AITableGridSelectionService);
2215
- this.notifyService = inject(ThyNotifyService);
2216
- this.thyPopoverRef = inject(ThyPopoverRef);
2217
- this.aiTable = input.required();
2218
- this.menuItems = input.required();
2219
- this.targetName = input.required();
2220
- this.position = input.required();
2221
- this.maxCount = computed(() => this.aiTable().context?.maxRecords() - this.aiTable().records().length);
2222
- }
2223
- execute(menu) {
2224
- if ((menu.disabled && !menu.disabled(this.aiTable(), this.targetName(), this.position())) || !menu.disabled) {
2225
- menu.exec &&
2226
- menu.exec(this.aiTable(), this.targetName(), this.position(), this.aiTableGridSelectionService, this.notifyService, menu.count);
2227
- }
2228
- }
2229
- inputNumberFocus(e) {
2230
- e.target.focus();
2231
- }
2232
- itemEnterHandle(e, menu) {
2233
- this.execute(menu);
2234
- this.thyPopoverRef.close();
2235
- }
2236
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableContextMenu, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2237
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableContextMenu, isStandalone: true, selector: "ai-table-context-menu", inputs: { aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: true, isRequired: true, transformFunction: null }, menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: true, transformFunction: null }, targetName: { classPropertyName: "targetName", publicName: "targetName", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "context-menu" }, usesInheritance: true, ngImport: i0, template: "@for (menu of menuItems(); track $index) {\n @if ((menu.hidden && !menu.hidden(aiTable(), targetName(), position())) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider thyStyle=\"solid\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable(), targetName(), position()));\n @let isRemoveRecords = menu.type === 'removeRecords';\n @let isPreventClearSelection =\n menu.type === 'copyCells' ||\n menu.type === 'pasteCells' ||\n menu.type === 'removeRecords' ||\n menu.type === 'insertUpwardRecords' ||\n menu.type === 'insertDownwardRecords';\n\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n 'remove-record': isRemoveRecords && !disabled,\n 'ai-table-prevent-clear-selection': isPreventClearSelection && !disabled\n }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"menu.icon!\"></thy-icon>\n @if (menu?.isInputNumber) {\n <span thyDropdownMenuItemName class=\"d-flex align-items-center\">\n {{ menu.name }}\n <thy-input-number\n #inputNumber\n class=\"mx-2\"\n thySize=\"sm\"\n [(ngModel)]=\"menu.count\"\n [thyStep]=\"1\"\n [thyMin]=\"1\"\n [thyMax]=\"maxCount()\"\n (click)=\"inputNumberFocus($event)\"\n (thyEnter)=\"itemEnterHandle($event, menu)\"\n thyStopPropagation\n ></thy-input-number>\n {{ menu.nameSuffix }}\n </span>\n } @else {\n <span thyDropdownMenuItemName>{{ menu.name }}</span>\n }\n <span thyDropdownMenuItemMeta class=\"text-desc\">{{ menu.shortcutKey }}</span>\n </a>\n }\n }\n}\n", dependencies: [{ kind: "component", type: ThyInputNumber, selector: "thy-input-number", inputs: ["thyAutoFocus", "thyPlaceholder", "thyDisabled", "thyMax", "thyMin", "thyStep", "thyStepDelay", "thySize", "thyPrecision", "thySuffix"], outputs: ["thyBlur", "thyFocus", "thyStepChange"] }, { 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: "directive", type: ThyEnterDirective, selector: "[thyEnter]", outputs: ["thyEnter"] }, { kind: "directive", type: ThyStopPropagationDirective, selector: "[thyStopPropagation]", inputs: ["thyStopPropagation"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "directive", type: ThyDropdownMenuItemIconDirective, selector: "[thyDropdownMenuItemIcon]" }, { kind: "directive", type: ThyDropdownMenuItemMetaDirective, selector: "[thyDropdownMenuItemMeta]" }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ThyDivider, selector: "thy-divider", inputs: ["thyVertical", "thyStyle", "thyColor", "thyText", "thyTextDirection", "thyDeeper"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2238
- }
2239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableContextMenu, decorators: [{
2240
- type: Component,
2241
- args: [{ selector: 'ai-table-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2242
- class: 'context-menu'
2243
- }, imports: [
2244
- ThyInputNumber,
2245
- FormsModule,
2246
- ThyEnterDirective,
2247
- ThyStopPropagationDirective,
2248
- ThyDropdownMenuItemDirective,
2249
- ThyDropdownMenuItemNameDirective,
2250
- ThyDropdownMenuItemIconDirective,
2251
- ThyDropdownMenuItemMetaDirective,
2252
- ThyIcon,
2253
- NgClass,
2254
- ThyDivider
2255
- ], template: "@for (menu of menuItems(); track $index) {\n @if ((menu.hidden && !menu.hidden(aiTable(), targetName(), position())) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider thyStyle=\"solid\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable(), targetName(), position()));\n @let isRemoveRecords = menu.type === 'removeRecords';\n @let isPreventClearSelection =\n menu.type === 'copyCells' ||\n menu.type === 'pasteCells' ||\n menu.type === 'removeRecords' ||\n menu.type === 'insertUpwardRecords' ||\n menu.type === 'insertDownwardRecords';\n\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n 'remove-record': isRemoveRecords && !disabled,\n 'ai-table-prevent-clear-selection': isPreventClearSelection && !disabled\n }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"menu.icon!\"></thy-icon>\n @if (menu?.isInputNumber) {\n <span thyDropdownMenuItemName class=\"d-flex align-items-center\">\n {{ menu.name }}\n <thy-input-number\n #inputNumber\n class=\"mx-2\"\n thySize=\"sm\"\n [(ngModel)]=\"menu.count\"\n [thyStep]=\"1\"\n [thyMin]=\"1\"\n [thyMax]=\"maxCount()\"\n (click)=\"inputNumberFocus($event)\"\n (thyEnter)=\"itemEnterHandle($event, menu)\"\n thyStopPropagation\n ></thy-input-number>\n {{ menu.nameSuffix }}\n </span>\n } @else {\n <span thyDropdownMenuItemName>{{ menu.name }}</span>\n }\n <span thyDropdownMenuItemMeta class=\"text-desc\">{{ menu.shortcutKey }}</span>\n </a>\n }\n }\n}\n" }]
2256
- }] });
1964
+ });
1965
+ return linearRows;
1966
+ };
1967
+ const buildGridData = (aiTable, recordValue, fieldsValue) => {
1968
+ const fieldOptions = getFieldOptions(aiTable);
1969
+ const fields = fieldsValue.map((value) => {
1970
+ const fieldOption = fieldOptions.find((item) => item.type === value.type);
1971
+ return {
1972
+ ...value,
1973
+ icon: value.icon || fieldOption.icon
1974
+ };
1975
+ });
1976
+ return {
1977
+ type: 'grid',
1978
+ fields,
1979
+ records: recordValue
1980
+ };
1981
+ };
2257
1982
 
2258
1983
  const GRID_CELL_EDITOR_MAP = {
2259
1984
  [AITableFieldType.text]: TextCellEditorComponent,
@@ -2432,142 +2157,516 @@ const DEFAULT_TEXT_SCALE = 1;
2432
2157
  const DEFAULT_TEXT_MAX_CACHE = 500;
2433
2158
  const FONT_SIZE_SM = 12;
2434
2159
 
2435
- const buildGridLinearRows = (visibleRecords, isAddingVisible = true) => {
2436
- const linearRows = [];
2437
- let displayRowIndex = 0;
2438
- [...visibleRecords, { _id: '' }].forEach((row) => {
2439
- if (row._id) {
2440
- displayRowIndex++;
2441
- linearRows.push({
2442
- type: AITableRowType.record,
2443
- _id: row._id,
2444
- displayIndex: displayRowIndex
2445
- });
2446
- }
2447
- if (isAddingVisible && !row._id) {
2448
- linearRows.push({
2449
- type: AITableRowType.add,
2450
- _id: ''
2451
- });
2452
- }
2453
- });
2454
- return linearRows;
2455
- };
2456
- const buildGridData = (aiTable, recordValue, fieldsValue) => {
2457
- const fieldOptions = getFieldOptions(aiTable);
2458
- const fields = fieldsValue.map((value) => {
2459
- const fieldOption = fieldOptions.find((item) => item.type === value.type);
2460
- return {
2461
- ...value,
2462
- icon: value.icon || fieldOption.icon
2463
- };
2464
- });
2465
- return {
2466
- type: 'grid',
2467
- fields,
2468
- records: recordValue
2469
- };
2470
- };
2471
-
2472
- class AITableFieldMenu extends ThyDropdownAbstractMenu {
2160
+ class AITableGridSelectionService {
2473
2161
  constructor() {
2474
- super(...arguments);
2475
- this.field = computed(() => {
2476
- return this.aiTable.fields().find((item) => item._id === this.fieldId);
2162
+ this.selectAllState = computed(() => {
2163
+ const selectedRecords = this.aiTable.selection().selectedRecords;
2164
+ return selectedRecords.size === this.aiTable.records().length
2165
+ ? AITableSelectAllState.all
2166
+ : selectedRecords.size === 0
2167
+ ? AITableSelectAllState.none
2168
+ : AITableSelectAllState.partial;
2477
2169
  });
2478
2170
  }
2479
- execute(menu) {
2480
- if ((menu.disabled && !menu.disabled(this.aiTable, this.field)) || !menu.disabled) {
2481
- menu.exec && menu.exec(this.aiTable, this.field, this.origin, this.position);
2482
- }
2483
- }
2484
- getMenuName(menu, field) {
2485
- if (typeof menu.name === 'function') {
2486
- return menu.name(field);
2487
- }
2488
- return menu.name || '';
2171
+ initialize(aiTable) {
2172
+ this.aiTable = aiTable;
2489
2173
  }
2490
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldMenu, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2491
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableFieldMenu, isStandalone: true, selector: "ai-table-field-menu", inputs: { fieldId: "fieldId", aiTable: "aiTable", fieldMenus: "fieldMenus", origin: "origin", position: "position" }, host: { classAttribute: "field-menu" }, usesInheritance: true, ngImport: i0, template: "@if (field()) {\n @for (menu of fieldMenus; track index; let index = $index) {\n @if ((menu.hidden && !menu.hidden(aiTable, field)) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable, field));\n @let isRemoveField = menu.type === 'removeField';\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{ 'remove-field': isRemoveField && !disabled }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ getMenuName(menu, field()) }}</span>\n </a>\n }\n }\n }\n}\n", dependencies: [{ kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyDivider, selector: "thy-divider", inputs: ["thyVertical", "thyStyle", "thyColor", "thyText", "thyTextDirection", "thyDeeper"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2492
- }
2493
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldMenu, decorators: [{
2494
- type: Component,
2495
- args: [{ selector: 'ai-table-field-menu', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2496
- class: 'field-menu'
2497
- }, imports: [ThyIcon, ThyDivider, ThyDropdownMenuItemDirective, NgClass], template: "@if (field()) {\n @for (menu of fieldMenus; track index; let index = $index) {\n @if ((menu.hidden && !menu.hidden(aiTable, field)) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable, field));\n @let isRemoveField = menu.type === 'removeField';\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{ 'remove-field': isRemoveField && !disabled }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ getMenuName(menu, field()) }}</span>\n </a>\n }\n }\n }\n}\n" }]
2498
- }], propDecorators: { fieldId: [{
2499
- type: Input,
2500
- args: [{ required: true }]
2501
- }], aiTable: [{
2502
- type: Input,
2503
- args: [{ required: true }]
2504
- }], fieldMenus: [{
2505
- type: Input,
2506
- args: [{ required: true }]
2507
- }], origin: [{
2508
- type: Input
2509
- }], position: [{
2510
- type: Input
2511
- }] } });
2512
-
2513
- const AI_TABLE_GRID_FIELD_SERVICE_MAP = new WeakMap();
2514
- class AITableGridFieldService {
2515
- constructor(thyPopover) {
2516
- this.thyPopover = thyPopover;
2174
+ clearSelection() {
2175
+ this.aiTable.selection.set({
2176
+ selectedRecords: new Set(),
2177
+ selectedFields: new Set(),
2178
+ selectedCells: new Set(),
2179
+ activeCell: null,
2180
+ expandCell: null,
2181
+ selectAllState: AITableSelectAllState.none
2182
+ });
2517
2183
  }
2518
- initAIFieldConfig(aiFieldConfig) {
2519
- this.aiFieldConfig = aiFieldConfig;
2184
+ setActiveCell(activeCell) {
2185
+ this.aiTable.selection().activeCell = activeCell;
2520
2186
  }
2521
- editFieldProperty(aiTable, options) {
2522
- const { field, isUpdate, origin, position } = options;
2523
- const component = this.aiFieldConfig?.fieldSettingComponent ?? AITableFieldSetting;
2524
- return this.thyPopover.open(component, {
2525
- origin,
2526
- originPosition: position,
2527
- placement: 'bottomLeft',
2528
- manualClosure: true,
2529
- originActiveClass: undefined,
2530
- height: 'auto',
2531
- panelClass: 'ai-table-field-setting-panel',
2532
- initialState: {
2533
- aiTable,
2534
- aiEditField: field,
2535
- isUpdate
2536
- }
2187
+ setExpandCell(expandCell) {
2188
+ this.aiTable.selection.set({
2189
+ ...this.aiTable.selection(),
2190
+ expandCell: expandCell
2537
2191
  });
2538
2192
  }
2539
- openFieldMenu(aiTable, options) {
2540
- const { origin, editOrigin, position, fieldId, fieldMenus } = options;
2541
- const ref = this.thyPopover.open(AITableFieldMenu, {
2542
- origin,
2543
- originPosition: position,
2544
- placement: 'bottomLeft',
2545
- originActiveClass: undefined,
2546
- insideClosable: true,
2547
- initialState: {
2548
- origin: editOrigin,
2549
- position: options.editFieldPosition,
2550
- aiTable,
2551
- fieldId,
2552
- fieldMenus
2553
- }
2554
- });
2555
- return ref;
2193
+ selectField(fieldId) {
2194
+ if (this.aiTable.selection().selectedFields.has(fieldId)) {
2195
+ return;
2196
+ }
2197
+ this.clearSelection();
2198
+ this.aiTable.selection().selectedFields.add(fieldId);
2556
2199
  }
2557
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService, deps: [{ token: i1$1.ThyPopover }], target: i0.ɵɵFactoryTarget.Injectable }); }
2558
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService }); }
2559
- }
2560
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService, decorators: [{
2561
- type: Injectable
2562
- }], ctorParameters: () => [{ type: i1$1.ThyPopover }] });
2563
-
2564
- const zhIntlCollator = typeof Intl !== 'undefined' ? new Intl.Collator('zh-CN') : undefined;
2565
- function compareNumber(a, b) {
2566
- if (isEmpty(a) && isEmpty(b)) {
2567
- return 0;
2200
+ get selectedFields() {
2201
+ return this.aiTable.selection().selectedFields;
2568
2202
  }
2569
- if (isEmpty(a)) {
2570
- return -1;
2203
+ get selectedRecords() {
2204
+ return this.aiTable.selection().selectedRecords;
2205
+ }
2206
+ selectRecord(recordId) {
2207
+ if (this.aiTable.selection().selectedRecords.has(recordId)) {
2208
+ this.aiTable.selection().selectedRecords.delete(recordId);
2209
+ }
2210
+ else {
2211
+ this.aiTable.selection().selectedRecords.add(recordId);
2212
+ }
2213
+ const selectedRecords = this.aiTable.selection().selectedRecords;
2214
+ this.aiTable.selection.set({
2215
+ selectedRecords: selectedRecords,
2216
+ selectedFields: new Set(),
2217
+ selectedCells: new Set(),
2218
+ activeCell: null,
2219
+ expandCell: null,
2220
+ selectAllState: this.selectAllState()
2221
+ });
2222
+ }
2223
+ toggleSelectAll(checked) {
2224
+ if (checked) {
2225
+ if (this.aiTable.records().length === 0) {
2226
+ this.aiTable.selection.set({
2227
+ ...this.aiTable.selection(),
2228
+ selectAllState: AITableSelectAllState.all
2229
+ });
2230
+ }
2231
+ else {
2232
+ this.aiTable.records().forEach((item) => {
2233
+ this.selectRecord(item._id);
2234
+ });
2235
+ }
2236
+ }
2237
+ else {
2238
+ this.clearSelection();
2239
+ }
2240
+ }
2241
+ updateSelect(event) {
2242
+ const target = event?.target;
2243
+ if (!target) {
2244
+ return;
2245
+ }
2246
+ const cellDom = target.closest('.grid-cell');
2247
+ const colDom = target.closest('.grid-field');
2248
+ const checkbox = target.tagName === 'INPUT' && target.type === 'checkbox' && target.closest('.grid-checkbox');
2249
+ const fieldAction = target.closest('.grid-field-action');
2250
+ if (cellDom) {
2251
+ const fieldId = cellDom.getAttribute('fieldId');
2252
+ const recordId = cellDom.getAttribute('recordId');
2253
+ fieldId && recordId && this.selectCells([recordId, fieldId]);
2254
+ }
2255
+ if (colDom && !fieldAction) {
2256
+ const fieldId = colDom.getAttribute('fieldId');
2257
+ fieldId && this.selectField(fieldId);
2258
+ }
2259
+ if (!cellDom && !colDom && !checkbox) {
2260
+ this.clearSelection();
2261
+ }
2262
+ }
2263
+ selectCells(startCell, endCell) {
2264
+ const [startRecordId, startFieldId] = startCell;
2265
+ const records = this.aiTable.context.linearRows();
2266
+ const fields = AITable.getVisibleFields(this.aiTable);
2267
+ const selectedCells = new Set();
2268
+ if (!endCell) {
2269
+ selectedCells.add(`${startRecordId}:${startFieldId}`);
2270
+ }
2271
+ else {
2272
+ const [endRecordId, endFieldId] = endCell;
2273
+ const startRowIndex = this.aiTable.context.visibleRowsIndexMap().get(startRecordId);
2274
+ const endRowIndex = this.aiTable.context.visibleRowsIndexMap().get(endRecordId);
2275
+ const startColIndex = this.aiTable.context.visibleColumnsIndexMap().get(startFieldId);
2276
+ const endColIndex = this.aiTable.context.visibleColumnsIndexMap().get(endFieldId);
2277
+ const minRowIndex = Math.min(startRowIndex, endRowIndex);
2278
+ const maxRowIndex = Math.max(startRowIndex, endRowIndex);
2279
+ const minColIndex = Math.min(startColIndex, endColIndex);
2280
+ const maxColIndex = Math.max(startColIndex, endColIndex);
2281
+ for (let i = minRowIndex; i <= maxRowIndex; i++) {
2282
+ for (let j = minColIndex; j <= maxColIndex; j++) {
2283
+ selectedCells.add(`${records[i]._id}:${fields[j]._id}`);
2284
+ }
2285
+ }
2286
+ }
2287
+ this.clearSelection();
2288
+ this.setActiveCell(startCell);
2289
+ this.aiTable.selection().selectedCells = selectedCells;
2290
+ }
2291
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2292
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService }); }
2293
+ }
2294
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridSelectionService, decorators: [{
2295
+ type: Injectable
2296
+ }], ctorParameters: () => [] });
2297
+
2298
+ class AITableContextMenu extends ThyDropdownAbstractMenu {
2299
+ constructor() {
2300
+ super(...arguments);
2301
+ this.aiTableGridSelectionService = inject(AITableGridSelectionService);
2302
+ this.notifyService = inject(ThyNotifyService);
2303
+ this.thyPopoverRef = inject(ThyPopoverRef);
2304
+ this.aiTable = input.required();
2305
+ this.menuItems = input.required();
2306
+ this.targetName = input.required();
2307
+ this.position = input.required();
2308
+ this.maxCount = computed(() => this.aiTable().context?.maxRecords() - this.aiTable().records().length);
2309
+ }
2310
+ execute(menu) {
2311
+ if ((menu.disabled && !menu.disabled(this.aiTable(), this.targetName(), this.position())) || !menu.disabled) {
2312
+ menu.exec &&
2313
+ menu.exec(this.aiTable(), this.targetName(), this.position(), this.aiTableGridSelectionService, this.notifyService, menu.count);
2314
+ }
2315
+ }
2316
+ inputNumberFocus(e) {
2317
+ e.target.focus();
2318
+ }
2319
+ itemEnterHandle(e, menu) {
2320
+ this.execute(menu);
2321
+ this.thyPopoverRef.close();
2322
+ }
2323
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableContextMenu, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2324
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableContextMenu, isStandalone: true, selector: "ai-table-context-menu", inputs: { aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: true, isRequired: true, transformFunction: null }, menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: true, transformFunction: null }, targetName: { classPropertyName: "targetName", publicName: "targetName", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "context-menu" }, usesInheritance: true, ngImport: i0, template: "@for (menu of menuItems(); track $index) {\n @if ((menu.hidden && !menu.hidden(aiTable(), targetName(), position())) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider thyStyle=\"solid\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable(), targetName(), position()));\n @let isRemoveRecords = menu.type === 'removeRecords';\n @let isPreventClearSelection =\n menu.type === 'copyCells' ||\n menu.type === 'pasteCells' ||\n menu.type === 'removeRecords' ||\n menu.type === 'insertUpwardRecords' ||\n menu.type === 'insertDownwardRecords';\n\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n 'remove-record': isRemoveRecords && !disabled,\n 'ai-table-prevent-clear-selection': isPreventClearSelection && !disabled\n }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"menu.icon!\"></thy-icon>\n @if (menu?.isInputNumber) {\n <span thyDropdownMenuItemName class=\"d-flex align-items-center\">\n {{ menu.name }}\n <thy-input-number\n #inputNumber\n class=\"mx-2\"\n thySize=\"sm\"\n [(ngModel)]=\"menu.count\"\n [thyStep]=\"1\"\n [thyMin]=\"1\"\n [thyMax]=\"maxCount()\"\n (click)=\"inputNumberFocus($event)\"\n (thyEnter)=\"itemEnterHandle($event, menu)\"\n thyStopPropagation\n ></thy-input-number>\n {{ menu.nameSuffix }}\n </span>\n } @else {\n <span thyDropdownMenuItemName>{{ menu.name }}</span>\n }\n <span thyDropdownMenuItemMeta class=\"text-desc\">{{ menu.shortcutKey }}</span>\n </a>\n }\n }\n}\n", dependencies: [{ kind: "component", type: ThyInputNumber, selector: "thy-input-number", inputs: ["thyAutoFocus", "thyPlaceholder", "thyDisabled", "thyMax", "thyMin", "thyStep", "thyStepDelay", "thySize", "thyPrecision", "thySuffix"], outputs: ["thyBlur", "thyFocus", "thyStepChange"] }, { 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: "directive", type: ThyEnterDirective, selector: "[thyEnter]", outputs: ["thyEnter"] }, { kind: "directive", type: ThyStopPropagationDirective, selector: "[thyStopPropagation]", inputs: ["thyStopPropagation"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "directive", type: ThyDropdownMenuItemIconDirective, selector: "[thyDropdownMenuItemIcon]" }, { kind: "directive", type: ThyDropdownMenuItemMetaDirective, selector: "[thyDropdownMenuItemMeta]" }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ThyDivider, selector: "thy-divider", inputs: ["thyVertical", "thyStyle", "thyColor", "thyText", "thyTextDirection", "thyDeeper"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2325
+ }
2326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableContextMenu, decorators: [{
2327
+ type: Component,
2328
+ args: [{ selector: 'ai-table-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2329
+ class: 'context-menu'
2330
+ }, imports: [
2331
+ ThyInputNumber,
2332
+ FormsModule,
2333
+ ThyEnterDirective,
2334
+ ThyStopPropagationDirective,
2335
+ ThyDropdownMenuItemDirective,
2336
+ ThyDropdownMenuItemNameDirective,
2337
+ ThyDropdownMenuItemIconDirective,
2338
+ ThyDropdownMenuItemMetaDirective,
2339
+ ThyIcon,
2340
+ NgClass,
2341
+ ThyDivider
2342
+ ], template: "@for (menu of menuItems(); track $index) {\n @if ((menu.hidden && !menu.hidden(aiTable(), targetName(), position())) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider thyStyle=\"solid\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable(), targetName(), position()));\n @let isRemoveRecords = menu.type === 'removeRecords';\n @let isPreventClearSelection =\n menu.type === 'copyCells' ||\n menu.type === 'pasteCells' ||\n menu.type === 'removeRecords' ||\n menu.type === 'insertUpwardRecords' ||\n menu.type === 'insertDownwardRecords';\n\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n 'remove-record': isRemoveRecords && !disabled,\n 'ai-table-prevent-clear-selection': isPreventClearSelection && !disabled\n }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"menu.icon!\"></thy-icon>\n @if (menu?.isInputNumber) {\n <span thyDropdownMenuItemName class=\"d-flex align-items-center\">\n {{ menu.name }}\n <thy-input-number\n #inputNumber\n class=\"mx-2\"\n thySize=\"sm\"\n [(ngModel)]=\"menu.count\"\n [thyStep]=\"1\"\n [thyMin]=\"1\"\n [thyMax]=\"maxCount()\"\n (click)=\"inputNumberFocus($event)\"\n (thyEnter)=\"itemEnterHandle($event, menu)\"\n thyStopPropagation\n ></thy-input-number>\n {{ menu.nameSuffix }}\n </span>\n } @else {\n <span thyDropdownMenuItemName>{{ menu.name }}</span>\n }\n <span thyDropdownMenuItemMeta class=\"text-desc\">{{ menu.shortcutKey }}</span>\n </a>\n }\n }\n}\n" }]
2343
+ }] });
2344
+
2345
+ class AITableGridEventService {
2346
+ constructor() {
2347
+ this.dblClickEvent$ = new Subject();
2348
+ this.mousedownEvent$ = new Subject();
2349
+ this.mouseoverEvent$ = new Subject();
2350
+ this.globalMouseoverEvent$ = new Subject();
2351
+ this.globalMousedownEvent$ = new Subject();
2352
+ this.destroyRef = inject(DestroyRef);
2353
+ this.thyPopover = inject(ThyPopover);
2354
+ }
2355
+ initialize(aiTable, aiFieldRenderers) {
2356
+ this.aiTable = aiTable;
2357
+ this.aiFieldRenderers = aiFieldRenderers;
2358
+ }
2359
+ registerEvents(element) {
2360
+ fromEvent(element, 'dblclick', { passive: true })
2361
+ .pipe(takeUntilDestroyed(this.destroyRef))
2362
+ .subscribe((event) => {
2363
+ this.dblClickEvent$.next(event);
2364
+ });
2365
+ fromEvent(element, 'mouseover', { passive: true })
2366
+ .pipe(debounceTime(80), takeUntilDestroyed(this.destroyRef))
2367
+ .subscribe((event) => {
2368
+ this.mouseoverEvent$.next(event);
2369
+ });
2370
+ fromEvent(document, 'mouseover', { passive: true })
2371
+ .pipe(takeUntilDestroyed(this.destroyRef))
2372
+ .subscribe((event) => {
2373
+ this.globalMouseoverEvent$.next(event);
2374
+ });
2375
+ fromEvent(element, 'mousedown', { passive: true })
2376
+ .pipe(takeUntilDestroyed(this.destroyRef))
2377
+ .subscribe((event) => {
2378
+ this.mousedownEvent$.next(event);
2379
+ });
2380
+ fromEvent(document, 'mousedown', { passive: true })
2381
+ .pipe(takeUntilDestroyed(this.destroyRef))
2382
+ .subscribe((event) => {
2383
+ this.globalMousedownEvent$.next(event);
2384
+ });
2385
+ }
2386
+ getEditorComponent(type) {
2387
+ const filedRenderSchema = this.aiFieldRenderers && this.aiFieldRenderers[type];
2388
+ if (filedRenderSchema && filedRenderSchema.editor) {
2389
+ return {
2390
+ component: filedRenderSchema.editor,
2391
+ isInternalComponent: false
2392
+ };
2393
+ }
2394
+ return {
2395
+ component: GRID_CELL_EDITOR_MAP[type],
2396
+ isInternalComponent: true
2397
+ };
2398
+ }
2399
+ openEdit(cellDom) {
2400
+ const { x, y, width, height } = cellDom.getBoundingClientRect();
2401
+ const fieldId = cellDom.getAttribute('fieldId');
2402
+ const recordId = cellDom.getAttribute('recordId');
2403
+ const { component } = this.getEditorComponent(this.aiTable.fieldsMap()[fieldId].type);
2404
+ const ref = this.thyPopover.open(component, {
2405
+ origin: cellDom,
2406
+ originPosition: {
2407
+ x: x - 1,
2408
+ y: y + 1,
2409
+ width: width + 2,
2410
+ height: height + 2
2411
+ },
2412
+ width: width + 1 + 'px',
2413
+ height: height + 2 + 'px',
2414
+ placement: 'top',
2415
+ offset: -(height + 4),
2416
+ minWidth: width,
2417
+ initialState: {
2418
+ fieldId: fieldId,
2419
+ recordId: recordId,
2420
+ aiTable: this.aiTable
2421
+ },
2422
+ panelClass: 'grid-cell-editor',
2423
+ outsideClosable: false,
2424
+ hasBackdrop: false,
2425
+ manualClosure: true,
2426
+ animationDisabled: true,
2427
+ autoAdaptive: true
2428
+ });
2429
+ return ref;
2430
+ }
2431
+ getOriginPosition(aiTable, options) {
2432
+ const { container, coordinate, recordId, fieldId } = options;
2433
+ const { scrollState } = aiTable.context;
2434
+ const { rowHeight, columnCount } = coordinate;
2435
+ const cell = [recordId, fieldId];
2436
+ const { rowIndex, columnIndex } = AITable.getCellIndex(aiTable, cell);
2437
+ const originX = coordinate.getColumnOffset(columnIndex);
2438
+ const originY = coordinate.getRowOffset(rowIndex);
2439
+ const columnWidth = coordinate.getColumnWidth(columnIndex);
2440
+ const { width: originWidth, offset: originOffset } = getCellHorizontalPosition({
2441
+ columnWidth,
2442
+ columnIndex,
2443
+ columnCount
2444
+ });
2445
+ const originRect = container.getBoundingClientRect();
2446
+ const isFrozenColumn = AITable.isFrozenColumn(aiTable, columnIndex);
2447
+ const scrollLeft = isFrozenColumn ? 0 : scrollState().scrollLeft;
2448
+ const scrollTop = scrollState().scrollTop;
2449
+ const originPosition = {
2450
+ x: originX + originOffset - scrollLeft + originRect.x,
2451
+ y: originY - scrollTop + originRect.y,
2452
+ width: originWidth,
2453
+ height: rowHeight
2454
+ };
2455
+ let x = originPosition.x + getEditorBoxOffset();
2456
+ let y = originPosition.y + getEditorBoxOffset();
2457
+ let width = getEditorSpace(originPosition.width);
2458
+ let height = getEditorSpace(originPosition.height);
2459
+ return {
2460
+ ...originPosition,
2461
+ x: x,
2462
+ y: y,
2463
+ width: width,
2464
+ height: height
2465
+ };
2466
+ }
2467
+ openCellEditor(aiTable, options) {
2468
+ const { container, recordId, fieldId, references } = options;
2469
+ const fieldType = this.aiTable.fieldsMap()[fieldId].type;
2470
+ const { component, isInternalComponent } = this.getEditorComponent(fieldType);
2471
+ const offsetOriginPosition = this.getOriginPosition(aiTable, options);
2472
+ this.cellEditorPopoverRef = this.thyPopover.open(component, {
2473
+ viewContainerRef: isInternalComponent ? undefined : options?.viewContainerRef,
2474
+ origin: container,
2475
+ originPosition: offsetOriginPosition,
2476
+ width: offsetOriginPosition.width + 'px',
2477
+ height: offsetOriginPosition.height + 'px',
2478
+ minWidth: offsetOriginPosition.width + 'px',
2479
+ placement: 'bottom',
2480
+ offset: -offsetOriginPosition.height,
2481
+ initialState: {
2482
+ fieldId: fieldId,
2483
+ recordId: recordId,
2484
+ references,
2485
+ aiTable: aiTable,
2486
+ isSelectAll: options.isSelectAll,
2487
+ },
2488
+ panelClass: 'grid-cell-editor',
2489
+ outsideClosable: fieldType === AITableFieldType.link ? true : false,
2490
+ hasBackdrop: false,
2491
+ manualClosure: true,
2492
+ animationDisabled: true,
2493
+ autoAdaptive: true
2494
+ });
2495
+ if (this.cellEditorPopoverRef) {
2496
+ const wheelEvent = fromEvent(this.cellEditorPopoverRef.componentInstance.elementRef.nativeElement, 'wheel').subscribe((event) => {
2497
+ const field = aiTable.fieldsMap()[fieldId];
2498
+ if (field.type === AITableFieldType.text || field.type === AITableFieldType.richText) {
2499
+ return;
2500
+ }
2501
+ event.preventDefault();
2502
+ this.aiTable.context?.scrollAction({
2503
+ deltaX: event.deltaX,
2504
+ deltaY: event.deltaY,
2505
+ shiftKey: event.shiftKey,
2506
+ callback: () => {
2507
+ const originPosition = this.getOriginPosition(aiTable, options);
2508
+ const positionStrategy = this.cellEditorPopoverRef
2509
+ .getOverlayRef()
2510
+ .getConfig().positionStrategy;
2511
+ positionStrategy.setOrigin(originPosition);
2512
+ positionStrategy.apply();
2513
+ }
2514
+ });
2515
+ });
2516
+ this.cellEditorPopoverRef.afterClosed().subscribe(() => {
2517
+ wheelEvent.unsubscribe();
2518
+ this.cellEditorPopoverRef = null;
2519
+ });
2520
+ this.cellEditorPopoverRef.componentInstance.updateFieldValue.subscribe((value) => {
2521
+ options.updateFieldValue(value);
2522
+ });
2523
+ }
2524
+ return this.cellEditorPopoverRef;
2525
+ }
2526
+ closeCellEditor() {
2527
+ if (this.cellEditorPopoverRef) {
2528
+ this.cellEditorPopoverRef.close();
2529
+ this.cellEditorPopoverRef = null;
2530
+ }
2531
+ }
2532
+ getCurrentEditCell() {
2533
+ if (this.cellEditorPopoverRef) {
2534
+ const recordId = this.cellEditorPopoverRef.componentInstance?.recordId;
2535
+ const fieldId = this.cellEditorPopoverRef.componentInstance?.fieldId;
2536
+ if (recordId && fieldId) {
2537
+ return {
2538
+ recordId,
2539
+ fieldId
2540
+ };
2541
+ }
2542
+ return null;
2543
+ }
2544
+ return null;
2545
+ }
2546
+ openContextMenu(aiTable, options) {
2547
+ const { origin, position, menuItems, targetName, viewContainerRef } = options;
2548
+ const ref = this.thyPopover.open(AITableContextMenu, {
2549
+ origin: origin,
2550
+ originPosition: position,
2551
+ placement: 'bottomLeft',
2552
+ insideClosable: true,
2553
+ viewContainerRef,
2554
+ initialState: {
2555
+ aiTable,
2556
+ menuItems,
2557
+ targetName,
2558
+ position
2559
+ }
2560
+ });
2561
+ return ref;
2562
+ }
2563
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2564
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService }); }
2565
+ }
2566
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService, decorators: [{
2567
+ type: Injectable
2568
+ }] });
2569
+
2570
+ class AITableFieldMenu extends ThyDropdownAbstractMenu {
2571
+ constructor() {
2572
+ super(...arguments);
2573
+ this.field = computed(() => {
2574
+ return this.aiTable.fields().find((item) => item._id === this.fieldId);
2575
+ });
2576
+ }
2577
+ execute(menu) {
2578
+ if ((menu.disabled && !menu.disabled(this.aiTable, this.field)) || !menu.disabled) {
2579
+ menu.exec && menu.exec(this.aiTable, this.field, this.origin, this.position);
2580
+ }
2581
+ }
2582
+ getMenuName(menu, field) {
2583
+ if (typeof menu.name === 'function') {
2584
+ return menu.name(field);
2585
+ }
2586
+ return menu.name || '';
2587
+ }
2588
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldMenu, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2589
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableFieldMenu, isStandalone: true, selector: "ai-table-field-menu", inputs: { fieldId: "fieldId", aiTable: "aiTable", fieldMenus: "fieldMenus", origin: "origin", position: "position" }, host: { classAttribute: "field-menu" }, usesInheritance: true, ngImport: i0, template: "@if (field()) {\n @for (menu of fieldMenus; track index; let index = $index) {\n @if ((menu.hidden && !menu.hidden(aiTable, field)) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable, field));\n @let isRemoveField = menu.type === 'removeField';\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{ 'remove-field': isRemoveField && !disabled }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ getMenuName(menu, field()) }}</span>\n </a>\n }\n }\n }\n}\n", dependencies: [{ kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyDivider, selector: "thy-divider", inputs: ["thyVertical", "thyStyle", "thyColor", "thyText", "thyTextDirection", "thyDeeper"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2590
+ }
2591
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldMenu, decorators: [{
2592
+ type: Component,
2593
+ args: [{ selector: 'ai-table-field-menu', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2594
+ class: 'field-menu'
2595
+ }, imports: [ThyIcon, ThyDivider, ThyDropdownMenuItemDirective, NgClass], template: "@if (field()) {\n @for (menu of fieldMenus; track index; let index = $index) {\n @if ((menu.hidden && !menu.hidden(aiTable, field)) || !menu.hidden) {\n @if (menu.type === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n @let disabled = !!(menu.disabled && menu.disabled(aiTable, field));\n @let isRemoveField = menu.type === 'removeField';\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{ 'remove-field': isRemoveField && !disabled }\"\n (click)=\"execute(menu)\"\n [thyDisabled]=\"disabled\"\n >\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ getMenuName(menu, field()) }}</span>\n </a>\n }\n }\n }\n}\n" }]
2596
+ }], propDecorators: { fieldId: [{
2597
+ type: Input,
2598
+ args: [{ required: true }]
2599
+ }], aiTable: [{
2600
+ type: Input,
2601
+ args: [{ required: true }]
2602
+ }], fieldMenus: [{
2603
+ type: Input,
2604
+ args: [{ required: true }]
2605
+ }], origin: [{
2606
+ type: Input
2607
+ }], position: [{
2608
+ type: Input
2609
+ }] } });
2610
+
2611
+ const AI_TABLE_GRID_FIELD_SERVICE_MAP = new WeakMap();
2612
+ class AITableGridFieldService {
2613
+ constructor(thyPopover) {
2614
+ this.thyPopover = thyPopover;
2615
+ }
2616
+ initAIFieldConfig(aiFieldConfig) {
2617
+ this.aiFieldConfig = aiFieldConfig;
2618
+ }
2619
+ editFieldProperty(aiTable, options) {
2620
+ const { field, isUpdate, origin, position, references } = options;
2621
+ const component = this.aiFieldConfig?.fieldSettingComponent ?? AITableFieldSetting;
2622
+ return this.thyPopover.open(component, {
2623
+ origin,
2624
+ originPosition: position,
2625
+ placement: 'bottomLeft',
2626
+ manualClosure: true,
2627
+ originActiveClass: undefined,
2628
+ height: 'auto',
2629
+ panelClass: 'ai-table-field-setting-panel',
2630
+ initialState: {
2631
+ aiTable,
2632
+ aiReferences: references,
2633
+ aiEditField: field,
2634
+ isUpdate
2635
+ }
2636
+ });
2637
+ }
2638
+ openFieldMenu(aiTable, options) {
2639
+ const { origin, editOrigin, position, fieldId, fieldMenus } = options;
2640
+ const ref = this.thyPopover.open(AITableFieldMenu, {
2641
+ origin,
2642
+ originPosition: position,
2643
+ placement: 'bottomLeft',
2644
+ originActiveClass: undefined,
2645
+ insideClosable: true,
2646
+ initialState: {
2647
+ origin: editOrigin,
2648
+ position: options.editFieldPosition,
2649
+ aiTable,
2650
+ fieldId,
2651
+ fieldMenus
2652
+ }
2653
+ });
2654
+ return ref;
2655
+ }
2656
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService, deps: [{ token: i1$1.ThyPopover }], target: i0.ɵɵFactoryTarget.Injectable }); }
2657
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService }); }
2658
+ }
2659
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridFieldService, decorators: [{
2660
+ type: Injectable
2661
+ }], ctorParameters: () => [{ type: i1$1.ThyPopover }] });
2662
+
2663
+ const zhIntlCollator = typeof Intl !== 'undefined' ? new Intl.Collator('zh-CN') : undefined;
2664
+ function compareNumber(a, b) {
2665
+ if (isEmpty(a) && isEmpty(b)) {
2666
+ return 0;
2667
+ }
2668
+ if (isEmpty(a)) {
2669
+ return -1;
2571
2670
  }
2572
2671
  if (isEmpty(b)) {
2573
2672
  return 1;
@@ -3102,7 +3201,57 @@ class SelectField extends SelectFieldBase {
3102
3201
  }
3103
3202
  }
3104
3203
  function toSelectFieldValue(plainText, targetField, originData) {
3105
- return null;
3204
+ const targetFieldOptions = targetField.settings?.options || [];
3205
+ const isMultiple = targetField.settings?.is_multiple;
3206
+ const { field, cellValue } = originData || {};
3207
+ let value = [];
3208
+ if (field && field.type === AITableFieldType.select) {
3209
+ value = getValidCellValue(cellValue, targetFieldOptions);
3210
+ }
3211
+ else {
3212
+ const cellFullTexts = plainText
3213
+ .split(',')
3214
+ .map((text) => text.trim())
3215
+ .filter((text) => !!text);
3216
+ cellFullTexts.forEach((text) => {
3217
+ const option = targetFieldOptions.find((option) => option.text.trim() === text);
3218
+ if (option) {
3219
+ value.push(option._id);
3220
+ }
3221
+ });
3222
+ }
3223
+ if (value.length) {
3224
+ return isMultiple ? value : [value[0]];
3225
+ }
3226
+ else {
3227
+ return null;
3228
+ }
3229
+ }
3230
+ function getOptionsByFieldAndRecords(aiTable, field, references) {
3231
+ let records = aiTable.records();
3232
+ let options = [];
3233
+ let optionStyle = AITableSelectOptionStyle.text;
3234
+ if (field.type === AITableFieldType.select) {
3235
+ options = field.settings?.options || [];
3236
+ optionStyle = field.settings?.option_style || AITableSelectOptionStyle.text;
3237
+ }
3238
+ else {
3239
+ const originFieldModel = FieldModelMap[field.type];
3240
+ let optionTexts = [];
3241
+ records.forEach((record) => {
3242
+ const cellValue = isSystemField(field)
3243
+ ? AITableQueries.getSystemFieldValue(record, field.type)
3244
+ : AITableQueries.getFieldValue(aiTable, [record._id, field._id]);
3245
+ const transformValue = originFieldModel.transformCellValue(cellValue, {
3246
+ aiTable,
3247
+ field
3248
+ });
3249
+ const texts = originFieldModel.cellFullText(transformValue, field, references) || [];
3250
+ optionTexts = [...optionTexts, ...texts];
3251
+ });
3252
+ options = generateOptionsByTexts(optionTexts);
3253
+ }
3254
+ return { options, optionStyle };
3106
3255
  }
3107
3256
  function processPastedValueForSelect(plainText, targetField, originData) {
3108
3257
  const targetFieldOptions = targetField.settings?.options || [];
@@ -3169,7 +3318,7 @@ function processPastedValueForSelect(plainText, targetField, originData) {
3169
3318
  }
3170
3319
  function copyOption(originOption, targetFieldOptions, targetOptionStyle) {
3171
3320
  let newOption = {
3172
- _id: idCreator(),
3321
+ _id: idCreator$1(),
3173
3322
  text: originOption.text
3174
3323
  };
3175
3324
  if (targetOptionStyle !== AITableSelectOptionStyle.text) {
@@ -3305,7 +3454,7 @@ function appendField(aiTable, originField, actions) {
3305
3454
  defaultFieldValue = {
3306
3455
  ...originField,
3307
3456
  name: createDefaultFieldName(aiTable, fieldOptions.find((item) => item.type === originField.type)),
3308
- _id: idCreator()
3457
+ _id: idCreator$1()
3309
3458
  };
3310
3459
  }
3311
3460
  else {
@@ -3686,16 +3835,26 @@ function toRateFieldValue(plainText, targetField, originData) {
3686
3835
  value = optionsMap[cellValue[0]]?.text;
3687
3836
  }
3688
3837
  break;
3838
+ case AITableFieldType.date:
3839
+ value = null;
3840
+ break;
3689
3841
  default:
3690
3842
  break;
3691
3843
  }
3692
3844
  }
3693
3845
  if (!isEmpty(value) || isNumber(value)) {
3694
3846
  const rateValue = Number(value);
3695
- if (!Number.isNaN(rateValue) && rateValue > 0 && rateValue < 5) {
3696
- return Math.round(rateValue);
3847
+ if (!Number.isNaN(rateValue)) {
3848
+ if (rateValue < 0) {
3849
+ return null;
3850
+ }
3851
+ else if (rateValue >= 0 && rateValue < 5) {
3852
+ return Math.round(rateValue);
3853
+ }
3854
+ else {
3855
+ return 5;
3856
+ }
3697
3857
  }
3698
- return 5;
3699
3858
  }
3700
3859
  return null;
3701
3860
  }
@@ -9210,229 +9369,136 @@ function aiTableRectConfigToKonvaConfig(rectConfig, options) {
9210
9369
  return result;
9211
9370
  }
9212
9371
 
9213
- class AITableGridEventService {
9372
+ class AITableFieldSetting {
9214
9373
  constructor() {
9215
- this.dblClickEvent$ = new Subject();
9216
- this.mousedownEvent$ = new Subject();
9217
- this.mouseoverEvent$ = new Subject();
9218
- this.globalMouseoverEvent$ = new Subject();
9219
- this.globalMousedownEvent$ = new Subject();
9220
- this.destroyRef = inject(DestroyRef);
9221
- this.thyPopover = inject(ThyPopover);
9222
- }
9223
- initialize(aiTable, aiFieldRenderers) {
9224
- this.aiTable = aiTable;
9225
- this.aiFieldRenderers = aiFieldRenderers;
9226
- }
9227
- registerEvents(element) {
9228
- fromEvent(element, 'dblclick', { passive: true })
9229
- .pipe(takeUntilDestroyed(this.destroyRef))
9230
- .subscribe((event) => {
9231
- this.dblClickEvent$.next(event);
9232
- });
9233
- fromEvent(element, 'mouseover', { passive: true })
9234
- .pipe(debounceTime(80), takeUntilDestroyed(this.destroyRef))
9235
- .subscribe((event) => {
9236
- this.mouseoverEvent$.next(event);
9237
- });
9238
- fromEvent(document, 'mouseover', { passive: true })
9239
- .pipe(takeUntilDestroyed(this.destroyRef))
9240
- .subscribe((event) => {
9241
- this.globalMouseoverEvent$.next(event);
9374
+ this.aiEditField = model.required();
9375
+ this.aiTable = input.required();
9376
+ this.aiExternalTemplate = input(null);
9377
+ this.aiReferences = input();
9378
+ this.isUpdate = input(false, { transform: booleanAttribute });
9379
+ this.addField = output();
9380
+ this.setField = output();
9381
+ this.selectedFieldOption = computed(() => {
9382
+ return getFieldOptionByField(this.aiTable(), this.aiEditField());
9242
9383
  });
9243
- fromEvent(element, 'mousedown', { passive: true })
9244
- .pipe(takeUntilDestroyed(this.destroyRef))
9245
- .subscribe((event) => {
9246
- this.mousedownEvent$.next(event);
9384
+ this.fieldMaxLength = 32;
9385
+ this.validatorConfig = computed(() => {
9386
+ return {
9387
+ validationMessages: {
9388
+ fieldName: {
9389
+ required: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldNameRequired),
9390
+ thyUniqueCheck: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldNameDuplicate)
9391
+ }
9392
+ }
9393
+ };
9247
9394
  });
9248
- fromEvent(document, 'mousedown', { passive: true })
9249
- .pipe(takeUntilDestroyed(this.destroyRef))
9250
- .subscribe((event) => {
9251
- this.globalMousedownEvent$.next(event);
9395
+ this.fieldOptions = computed(() => {
9396
+ const fieldOptions = getFieldOptions(this.aiTable());
9397
+ return _.groupBy(fieldOptions, 'group');
9252
9398
  });
9253
- }
9254
- getEditorComponent(type) {
9255
- const filedRenderSchema = this.aiFieldRenderers && this.aiFieldRenderers[type];
9256
- if (filedRenderSchema && filedRenderSchema.editor) {
9399
+ this.aITableFieldType = AITableFieldType;
9400
+ this.isMultipleMember = false;
9401
+ this.isManualInputName = signal(false);
9402
+ this.thyPopoverRef = inject((ThyPopoverRef));
9403
+ this.checkUniqueName = (fieldName) => {
9404
+ fieldName = fieldName?.trim();
9405
+ return of(!!this.aiTable()
9406
+ .fields()
9407
+ ?.find((field) => field.name === fieldName && this.aiEditField()?._id !== field._id));
9408
+ };
9409
+ this.i18nTexts = computed(() => {
9257
9410
  return {
9258
- component: filedRenderSchema.editor,
9259
- isInternalComponent: false
9411
+ columnName: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldColumnName),
9412
+ columnNamePlaceholder: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldColumnNamePlaceholder),
9413
+ fieldType: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldType),
9414
+ allowMultipleMembers: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.allowMultipleMembers),
9415
+ cancel: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.cancel),
9416
+ confirm: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.confirm),
9417
+ base: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldGroupBase),
9418
+ advanced: getI18nTextByKey(this.aiTable(), AITableGridI18nKey.fieldGroupAdvanced)
9260
9419
  };
9261
- }
9262
- return {
9263
- component: GRID_CELL_EDITOR_MAP[type],
9264
- isInternalComponent: true
9265
- };
9266
- }
9267
- openEdit(cellDom) {
9268
- const { x, y, width, height } = cellDom.getBoundingClientRect();
9269
- const fieldId = cellDom.getAttribute('fieldId');
9270
- const recordId = cellDom.getAttribute('recordId');
9271
- const { component } = this.getEditorComponent(this.aiTable.fieldsMap()[fieldId].type);
9272
- const ref = this.thyPopover.open(component, {
9273
- origin: cellDom,
9274
- originPosition: {
9275
- x: x - 1,
9276
- y: y + 1,
9277
- width: width + 2,
9278
- height: height + 2
9279
- },
9280
- width: width + 1 + 'px',
9281
- height: height + 2 + 'px',
9282
- placement: 'top',
9283
- offset: -(height + 4),
9284
- minWidth: width,
9285
- initialState: {
9286
- fieldId: fieldId,
9287
- recordId: recordId,
9288
- aiTable: this.aiTable
9289
- },
9290
- panelClass: 'grid-cell-editor',
9291
- outsideClosable: false,
9292
- hasBackdrop: false,
9293
- manualClosure: true,
9294
- animationDisabled: true,
9295
- autoAdaptive: true
9296
9420
  });
9297
- return ref;
9298
9421
  }
9299
- getOriginPosition(aiTable, options) {
9300
- const { container, coordinate, recordId, fieldId } = options;
9301
- const { scrollState } = aiTable.context;
9302
- const { rowHeight, columnCount } = coordinate;
9303
- const cell = [recordId, fieldId];
9304
- const { rowIndex, columnIndex } = AITable.getCellIndex(aiTable, cell);
9305
- const originX = coordinate.getColumnOffset(columnIndex);
9306
- const originY = coordinate.getRowOffset(rowIndex);
9307
- const columnWidth = coordinate.getColumnWidth(columnIndex);
9308
- const { width: originWidth, offset: originOffset } = getCellHorizontalPosition({
9309
- columnWidth,
9310
- columnIndex,
9311
- columnCount
9312
- });
9313
- const originRect = container.getBoundingClientRect();
9314
- const isFrozenColumn = AITable.isFrozenColumn(aiTable, columnIndex);
9315
- const scrollLeft = isFrozenColumn ? 0 : scrollState().scrollLeft;
9316
- const scrollTop = scrollState().scrollTop;
9317
- const originPosition = {
9318
- x: originX + originOffset - scrollLeft + originRect.x,
9319
- y: originY - scrollTop + originRect.y,
9320
- width: originWidth,
9321
- height: rowHeight
9322
- };
9323
- let x = originPosition.x + getEditorBoxOffset();
9324
- let y = originPosition.y + getEditorBoxOffset();
9325
- let width = getEditorSpace(originPosition.width);
9326
- let height = getEditorSpace(originPosition.height);
9327
- return {
9328
- ...originPosition,
9329
- x: x,
9330
- y: y,
9331
- width: width,
9332
- height: height
9333
- };
9422
+ ngOnInit() {
9423
+ this.isMultipleMember =
9424
+ this.aiEditField().type === AITableFieldType.member && !!this.aiEditField().settings?.is_multiple;
9334
9425
  }
9335
- openCellEditor(aiTable, options) {
9336
- const { container, recordId, fieldId, references } = options;
9337
- const fieldType = this.aiTable.fieldsMap()[fieldId].type;
9338
- const { component, isInternalComponent } = this.getEditorComponent(fieldType);
9339
- const offsetOriginPosition = this.getOriginPosition(aiTable, options);
9340
- this.cellEditorPopoverRef = this.thyPopover.open(component, {
9341
- viewContainerRef: isInternalComponent ? undefined : options?.viewContainerRef,
9342
- origin: container,
9343
- originPosition: offsetOriginPosition,
9344
- width: offsetOriginPosition.width + 'px',
9345
- height: offsetOriginPosition.height + 'px',
9346
- minWidth: offsetOriginPosition.width + 'px',
9347
- placement: 'bottom',
9348
- offset: -offsetOriginPosition.height,
9349
- initialState: {
9350
- fieldId: fieldId,
9351
- recordId: recordId,
9352
- references,
9353
- aiTable: aiTable,
9354
- isSelectAll: options.isSelectAll,
9355
- },
9356
- panelClass: 'grid-cell-editor',
9357
- outsideClosable: fieldType === AITableFieldType.link ? true : false,
9358
- hasBackdrop: false,
9359
- manualClosure: true,
9360
- animationDisabled: true,
9361
- autoAdaptive: true
9426
+ selectFieldType(field) {
9427
+ const fieldsSizeMap = this.aiTable().gridData().fieldsSizeMap;
9428
+ this.aiEditField.update((item) => {
9429
+ const width = fieldsSizeMap[item._id] ?? field.width;
9430
+ const name = this.isManualInputName() ? item.name : createDefaultFieldName(this.aiTable(), field);
9431
+ let settings = field.settings || {};
9432
+ if (this.isUpdate() && field.type === AITableFieldType.select) {
9433
+ const { options, optionStyle } = getOptionsByFieldAndRecords(this.aiTable(), this.aiEditField(), this.aiReferences());
9434
+ settings = { ...settings, options, option_style: optionStyle };
9435
+ }
9436
+ return { ...item, ...field, width, name, settings };
9362
9437
  });
9363
- if (this.cellEditorPopoverRef) {
9364
- const wheelEvent = fromEvent(this.cellEditorPopoverRef.componentInstance.elementRef.nativeElement, 'wheel').subscribe((event) => {
9365
- const field = aiTable.fieldsMap()[fieldId];
9366
- if (field.type === AITableFieldType.text || field.type === AITableFieldType.richText) {
9367
- return;
9368
- }
9369
- event.preventDefault();
9370
- this.aiTable.context?.scrollAction({
9371
- deltaX: event.deltaX,
9372
- deltaY: event.deltaY,
9373
- shiftKey: event.shiftKey,
9374
- callback: () => {
9375
- const originPosition = this.getOriginPosition(aiTable, options);
9376
- const positionStrategy = this.cellEditorPopoverRef
9377
- .getOverlayRef()
9378
- .getConfig().positionStrategy;
9379
- positionStrategy.setOrigin(originPosition);
9380
- positionStrategy.apply();
9381
- }
9382
- });
9383
- });
9384
- this.cellEditorPopoverRef.afterClosed().subscribe(() => {
9385
- wheelEvent.unsubscribe();
9386
- this.cellEditorPopoverRef = null;
9387
- });
9388
- this.cellEditorPopoverRef.componentInstance.updateFieldValue.subscribe((value) => {
9389
- options.updateFieldValue(value);
9390
- });
9391
- }
9392
- return this.cellEditorPopoverRef;
9438
+ setTimeout(() => {
9439
+ this.thyPopoverRef.updatePosition();
9440
+ }, 0);
9393
9441
  }
9394
- closeCellEditor() {
9395
- if (this.cellEditorPopoverRef) {
9396
- this.cellEditorPopoverRef.close();
9397
- this.cellEditorPopoverRef = null;
9442
+ editFieldProperty() {
9443
+ if (this.isUpdate()) {
9444
+ this.setField.emit({
9445
+ field: this.aiEditField(),
9446
+ path: [this.aiEditField()._id]
9447
+ });
9398
9448
  }
9399
- }
9400
- getCurrentEditCell() {
9401
- if (this.cellEditorPopoverRef) {
9402
- const recordId = this.cellEditorPopoverRef.componentInstance?.recordId;
9403
- const fieldId = this.cellEditorPopoverRef.componentInstance?.fieldId;
9404
- if (recordId && fieldId) {
9405
- return {
9406
- recordId,
9407
- fieldId
9408
- };
9409
- }
9410
- return null;
9449
+ else {
9450
+ this.addField.emit(this.aiEditField());
9411
9451
  }
9412
- return null;
9452
+ this.thyPopoverRef.close();
9413
9453
  }
9414
- openContextMenu(aiTable, options) {
9415
- const { origin, position, menuItems, targetName, viewContainerRef } = options;
9416
- const ref = this.thyPopover.open(AITableContextMenu, {
9417
- origin: origin,
9418
- originPosition: position,
9419
- placement: 'bottomLeft',
9420
- insideClosable: true,
9421
- viewContainerRef,
9422
- initialState: {
9423
- aiTable,
9424
- menuItems,
9425
- targetName,
9426
- position
9454
+ multipleMemberChange() {
9455
+ this.aiEditField.set({
9456
+ ...this.aiEditField(),
9457
+ settings: {
9458
+ ...(this.aiEditField().settings || {}),
9459
+ is_multiple: this.isMultipleMember
9427
9460
  }
9428
9461
  });
9429
- return ref;
9430
9462
  }
9431
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9432
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService }); }
9463
+ fieldTypeClick(e) {
9464
+ e.preventDefault();
9465
+ e.stopPropagation();
9466
+ }
9467
+ nameChange(event) {
9468
+ this.isManualInputName.set(true);
9469
+ }
9470
+ cancel() {
9471
+ this.thyPopoverRef.close();
9472
+ }
9473
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldSetting, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9474
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AITableFieldSetting, isStandalone: true, selector: "ai-table-field-setting", inputs: { aiEditField: { classPropertyName: "aiEditField", publicName: "aiEditField", isSignal: true, isRequired: true, transformFunction: null }, aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: true, isRequired: true, transformFunction: null }, aiExternalTemplate: { classPropertyName: "aiExternalTemplate", publicName: "aiExternalTemplate", isSignal: true, isRequired: false, transformFunction: null }, aiReferences: { classPropertyName: "aiReferences", publicName: "aiReferences", isSignal: true, isRequired: false, transformFunction: null }, isUpdate: { classPropertyName: "isUpdate", publicName: "isUpdate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { aiEditField: "aiEditFieldChange", addField: "addField", setField: "setField" }, host: { classAttribute: "field-setting d-block pl-5 pr-5 pb-5 pt-4" }, ngImport: i0, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig()\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired [thyLabelText]=\"i18nTexts().columnName\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiEditField().name\"\n (ngModelChange)=\"nameChange($event)\"\n required\n [placeholder]=\"i18nTexts().columnNamePlaceholder\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group [thyLabelText]=\"i18nTexts().fieldType\">\n <div class=\"thy-dropdown-menu py-0\">\n <div class=\"ml-n5 mr-n5\">\n <span thyDropdownMenuItem [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" (click)=\"fieldTypeClick($event)\">\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"selectedFieldOption().icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ selectedFieldOption().name }}</span>\n <thy-icon thyDropdownMenuItemExtendIcon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </span>\n </div>\n </div>\n\n @if (selectedFieldOption().type === aITableFieldType.member) {\n <div class=\"d-flex justify-content-between mt-3\">\n {{ i18nTexts().allowMultipleMembers }}\n <thy-switch\n name=\"isMultipleMember\"\n [(ngModel)]=\"isMultipleMember\"\n (ngModelChange)=\"multipleMemberChange()\"\n thySize=\"sm\"\n ></thy-switch>\n </div>\n }\n </thy-form-group>\n @if (aiExternalTemplate()) {\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate()\"></ng-container>\n }\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">{{ i18nTexts().cancel }}</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">{{ i18nTexts().confirm }}</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().base\">\n @for (item of fieldOptions().base; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().advanced\">\n @for (item of fieldOptions().advanced; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyInputGroup, selector: "thy-input-group", inputs: ["thyAppendText", "thyAppendTextTranslateKey", "thyPrependText", "thyPrependTextTranslateKey", "thySize"] }, { kind: "component", type: ThyInputCount, selector: "thy-input-count", inputs: ["thyInput"] }, { kind: "directive", type: ThyInputDirective, selector: "input[thyInput], select[thyInput], textarea[thyInput]", inputs: ["thySize"], exportAs: ["thyInput"] }, { kind: "directive", type: ThyUniqueCheckValidator, selector: "[thyUniqueCheck]", inputs: ["thyUniqueCheck"] }, { kind: "component", type: ThyDropdownMenuComponent, selector: "thy-dropdown-menu", inputs: ["thyWidth", "thyImmediateRender"] }, { kind: "component", type: ThyDropdownMenuGroup, selector: "thy-dropdown-menu-group", inputs: ["thyTitle"] }, { kind: "directive", type: ThyDropdownDirective, selector: "[thyDropdown]", inputs: ["thyDropdownMenu", "thyDropdown", "thyTrigger", "thyShowDelay", "thyHideDelay", "thyActiveClass", "thyPopoverOptions", "thyPlacement", "thyMenuInsideClosable", "thyPanelClass"], outputs: ["thyActiveChange"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemIconDirective, selector: "[thyDropdownMenuItemIcon]" }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "directive", type: ThyDropdownMenuItemExtendIconDirective, selector: "[thyDropdownMenuItemExtendIcon]" }, { kind: "component", type: ThyButton, selector: "thy-button,[thy-button],[thyButton]", inputs: ["thyButton", "thyType", "thyLoading", "thyLoadingText", "thySize", "thyIcon", "thyBlock"] }, { kind: "component", type: ThySwitch, selector: "thy-switch", inputs: ["thyType", "thySize", "thyDisabled", "thyLoading"], outputs: ["thyChange"] }, { kind: "ngmodule", type: ThyFormModule }, { kind: "directive", type: i2.ThyFormDirective, selector: "[thyForm],[thy-form]", inputs: ["thyLayout", "thyEnterKeyMode", "thyFormValidatorConfig"], exportAs: ["thyForm"] }, { kind: "component", type: i2.ThyFormGroup, selector: "thy-form-group", inputs: ["thyLabelText", "thyLabelTextTranslateKey", "thyLabelRequired", "thyLabelPaddingTopClear", "thyFeedbackIcon", "thyTipsMode", "thyTips", "thyTipsTranslateKey", "thyRowFill"] }, { kind: "directive", type: i2.ThyFormSubmitDirective, selector: "[thyFormSubmit],[thy-form-submit]", outputs: ["thyFormSubmit"] }, { kind: "component", type: i2.ThyFormGroupFooter, selector: "thy-form-group-footer", inputs: ["thyAlign"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ThyAutofocusDirective, selector: "input[thyAutofocus],textarea[thyAutofocus]", inputs: ["thyAutofocus", "thyAutoSelect"] }, { kind: "pipe", type: AITableFieldIsSameOptionPipe, name: "fieldIsSameOption" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9433
9475
  }
9434
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableGridEventService, decorators: [{
9435
- type: Injectable
9476
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AITableFieldSetting, decorators: [{
9477
+ type: Component,
9478
+ args: [{ selector: 'ai-table-field-setting', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
9479
+ NgClass,
9480
+ FormsModule,
9481
+ ThyIcon,
9482
+ ThyInputGroup,
9483
+ ThyInputCount,
9484
+ ThyInputDirective,
9485
+ ThyUniqueCheckValidator,
9486
+ ThyDropdownMenuComponent,
9487
+ ThyDropdownMenuGroup,
9488
+ ThyDropdownDirective,
9489
+ ThyDropdownMenuItemDirective,
9490
+ ThyDropdownMenuItemIconDirective,
9491
+ ThyDropdownMenuItemNameDirective,
9492
+ ThyDropdownMenuItemExtendIconDirective,
9493
+ ThyButton,
9494
+ ThySwitch,
9495
+ ThyFormModule,
9496
+ NgTemplateOutlet,
9497
+ ThyAutofocusDirective,
9498
+ AITableFieldIsSameOptionPipe
9499
+ ], host: {
9500
+ class: 'field-setting d-block pl-5 pr-5 pb-5 pt-4'
9501
+ }, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig()\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired [thyLabelText]=\"i18nTexts().columnName\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiEditField().name\"\n (ngModelChange)=\"nameChange($event)\"\n required\n [placeholder]=\"i18nTexts().columnNamePlaceholder\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group [thyLabelText]=\"i18nTexts().fieldType\">\n <div class=\"thy-dropdown-menu py-0\">\n <div class=\"ml-n5 mr-n5\">\n <span thyDropdownMenuItem [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" (click)=\"fieldTypeClick($event)\">\n <thy-icon thyDropdownMenuItemIcon [thyIconName]=\"selectedFieldOption().icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ selectedFieldOption().name }}</span>\n <thy-icon thyDropdownMenuItemExtendIcon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </span>\n </div>\n </div>\n\n @if (selectedFieldOption().type === aITableFieldType.member) {\n <div class=\"d-flex justify-content-between mt-3\">\n {{ i18nTexts().allowMultipleMembers }}\n <thy-switch\n name=\"isMultipleMember\"\n [(ngModel)]=\"isMultipleMember\"\n (ngModelChange)=\"multipleMemberChange()\"\n thySize=\"sm\"\n ></thy-switch>\n </div>\n }\n </thy-form-group>\n @if (aiExternalTemplate()) {\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate()\"></ng-container>\n }\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">{{ i18nTexts().cancel }}</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">{{ i18nTexts().confirm }}</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().base\">\n @for (item of fieldOptions().base; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n\n <thy-dropdown-menu-group [thyTitle]=\"i18nTexts().advanced\">\n @for (item of fieldOptions().advanced; track $index) {\n <a\n thyDropdownMenuItem\n href=\"javascript:;\"\n [ngClass]=\"{\n active: (item | fieldIsSameOption: aiEditField())\n }\"\n (click)=\"selectFieldType(item)\"\n >\n <thy-icon [thyIconName]=\"item.icon!\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n </thy-dropdown-menu-group>\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"] }]
9436
9502
  }] });
9437
9503
 
9438
9504
  class AITableGridBase {
@@ -9535,7 +9601,8 @@ class AITableGridBase {
9535
9601
  field,
9536
9602
  isUpdate: false,
9537
9603
  origin: gridColumnBlank,
9538
- position
9604
+ position,
9605
+ references: this.aiReferences()
9539
9606
  });
9540
9607
  if (popoverRef && !this.aiFieldConfig()?.fieldSettingComponent) {
9541
9608
  popoverRef.componentInstance.addField.subscribe((defaultValue) => {
@@ -10984,8 +11051,9 @@ class AITableGrid extends AITableGridBase {
10984
11051
  const scrollTop = position.y - scrollState.scrollTop;
10985
11052
  const nextCellIndex = coordinate.getColumnStartIndex(endCellLeft + scrollLeft);
10986
11053
  const nextRowIndex = coordinate.getRowStartIndex(endCellTop + scrollTop);
11054
+ const isHorizontalScroll = scrollLeft !== 0;
10987
11055
  // 向左滚动,单元格向后退一格,防止选区进入冻结列
10988
- const nextField = gridData.fields[isSelectionOnlyOnFrozenColumn || scrollLeft > 0 ? nextCellIndex : nextCellIndex + 1];
11056
+ const nextField = gridData.fields[!isHorizontalScroll || scrollLeft > 0 ? nextCellIndex : nextCellIndex + 1];
10989
11057
  const nextRecord = gridData.records[nextRowIndex];
10990
11058
  if (nextField && nextRecord) {
10991
11059
  this.aiTableGridSelectionService.selectCells([startCell[0], nextField._id], [nextRecord._id, startCell[1]]);
@@ -11008,5 +11076,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
11008
11076
  * Generated bundle index. Do not edit.
11009
11077
  */
11010
11078
 
11011
- export { AITable, AITableActionIcon, AITableAddField, AITableAreaType, AITableAvatarSize, AITableAvatarType, AITableCellAttachment, AITableCellLink, AITableCellProgress, AITableCellRate, AITableCellRichText, AITableCells, AITableCheckType, AITableColumnHeads, AITableContextMenu, AITableDomGrid, AITableFieldHead, AITableFieldIcon, AITableFieldIsSameOptionPipe, AITableFieldSetting, AITableFrozenCells, AITableFrozenColumnHeads, AITableFrozenPlaceholderCells, AITableGrid, AITableGridEventService, AITableGridFieldService, AITableGridI18nKey, AITableGridSelectionService, AITableHoverRowHeads, AITableIcon, AITableMemberType, AITableMouseDownType, AITableOtherRows, AITablePlaceholderCells, AITableQueries, AITableRenderer, AITableRowType, AITableSelectAllState, AITableTextComponent, AI_TABLE_ACTION_COMMON_RADIUS, AI_TABLE_ACTION_COMMON_RIGHT_PADDING, AI_TABLE_ACTION_COMMON_SIZE, AI_TABLE_AUTO_SCROLL_BOTTOM_THRESHOLD, AI_TABLE_AUTO_SCROLL_LEFT_THRESHOLD, AI_TABLE_AUTO_SCROLL_RIGHT_THRESHOLD, AI_TABLE_AUTO_SCROLL_TOP_THRESHOLD, AI_TABLE_BLANK, AI_TABLE_CELL, AI_TABLE_CELL_ACTIVE_BORDER_WIDTH, AI_TABLE_CELL_ADD_ITEM_BUTTON_SIZE, AI_TABLE_CELL_ATTACHMENT_ADD, AI_TABLE_CELL_ATTACHMENT_FILE, AI_TABLE_CELL_BORDER, AI_TABLE_CELL_DELETE_ITEM_BUTTON_SIZE, AI_TABLE_CELL_DELETE_ITEM_BUTTON_SIZE_OFFSET, AI_TABLE_CELL_EDIT, AI_TABLE_CELL_EMOJI_PADDING, AI_TABLE_CELL_EMOJI_SIZE, AI_TABLE_CELL_FIELD_ITEM_HEIGHT, AI_TABLE_CELL_MAX_ROW_COUNT, AI_TABLE_CELL_MEMBER_ITEM_HEIGHT, AI_TABLE_CELL_MEMBER_ITEM_PADDING, AI_TABLE_CELL_MEMBER_MAX_HEIGHT, AI_TABLE_CELL_MULTI_DOT_RADIUS, AI_TABLE_CELL_MULTI_ITEM_MARGIN_LEFT, AI_TABLE_CELL_MULTI_ITEM_MARGIN_TOP, AI_TABLE_CELL_MULTI_ITEM_MIN_WIDTH, AI_TABLE_CELL_MULTI_PADDING_LEFT, AI_TABLE_CELL_MULTI_PADDING_TOP, AI_TABLE_CELL_PADDING, AI_TABLE_COMMON_FONT_SIZE, AI_TABLE_DEFAULT_COLUMN_WIDTH, AI_TABLE_DOT_RADIUS, AI_TABLE_FIELD_ADD_BUTTON, AI_TABLE_FIELD_ADD_BUTTON_WIDTH, AI_TABLE_FIELD_HEAD, AI_TABLE_FIELD_HEAD_HEIGHT, AI_TABLE_FIELD_HEAD_ICON_GAP_SIZE, AI_TABLE_FIELD_HEAD_MORE, AI_TABLE_FIELD_HEAD_OPACITY_LINE, AI_TABLE_FIELD_HEAD_SELECT_CHECKBOX, AI_TABLE_FIELD_HEAD_TEXT_MIN_WIDTH, AI_TABLE_FIELD_ITEM_MARGIN_RIGHT, AI_TABLE_FIELD_MAX_WIDTH, AI_TABLE_FIELD_MIDDLE_WIDTH, AI_TABLE_FIELD_MINI_WIDTH, AI_TABLE_FIELD_MIN_WIDTH, AI_TABLE_FILE_ICON_ITEM_HEIGHT, AI_TABLE_FILE_ICON_SIZE, AI_TABLE_GRID_FIELD_SERVICE_MAP, AI_TABLE_ICON_COMMON_SIZE, AI_TABLE_MEMBER_AVATAR_SIZE, AI_TABLE_MEMBER_ITEM_AVATAR_MARGIN_RIGHT, AI_TABLE_MEMBER_ITEM_PADDING_RIGHT, AI_TABLE_MIN_TEXT_WIDTH, AI_TABLE_OFFSET, AI_TABLE_OPTION_ITEM_FONT_SIZE, AI_TABLE_OPTION_ITEM_HEIGHT, AI_TABLE_OPTION_ITEM_PADDING, AI_TABLE_OPTION_ITEM_RADIUS, AI_TABLE_PIECE_RADIUS, AI_TABLE_PIECE_WIDTH, AI_TABLE_POPOVER_LEFT_OFFSET, AI_TABLE_PREVENT_CLEAR_SELECTION_CLASS, AI_TABLE_PROGRESS_BAR_HEIGHT, AI_TABLE_PROGRESS_BAR_POINTER_HEIGHT, AI_TABLE_PROGRESS_BAR_POINTER_WIDTH, AI_TABLE_PROGRESS_BAR_RADIUS, AI_TABLE_PROGRESS_TEXT_WIDTH, AI_TABLE_RATE_MAX, AI_TABLE_ROW_ADD_BUTTON, AI_TABLE_ROW_BLANK_HEIGHT, AI_TABLE_ROW_DRAG, AI_TABLE_ROW_DRAG_ICON_WIDTH, AI_TABLE_ROW_HEAD, AI_TABLE_ROW_HEAD_SIZE, AI_TABLE_ROW_HEAD_WIDTH, AI_TABLE_ROW_HEIGHT, AI_TABLE_ROW_SELECT_CHECKBOX, AI_TABLE_SCROLL_BAR_PADDING, AI_TABLE_SCROLL_BAR_SIZE, AI_TABLE_TAG_FONT_SIZE, AI_TABLE_TAG_PADDING, AI_TABLE_TEXT_GAP, AbstractEditCellEditor, AddOutlinedPath, AttachmentField, AttachmentPath, CellDrawer, Check, Colors, ColumnCalendarFilledPath, ColumnLinkOutlinedPath, ColumnMemberFilledPath, ColumnMultipleFillPath, ColumnNumberFilledPath, ColumnProgressFilledPath, ColumnRatingFilledPath, ColumnRichTextFilledPath, ColumnSelectFilledPath, ColumnTextFilledPath, Coordinate, CoverCellComponent, DBL_CLICK_EDIT_TYPE, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_FONT_STYLE, DEFAULT_FONT_WEIGHT, DEFAULT_ICON_SHAPE, DEFAULT_ICON_SIZE, DEFAULT_POINT_POSITION, DEFAULT_SCROLL_STATE, DEFAULT_TEXT_ALIGN_CENTER, DEFAULT_TEXT_ALIGN_LEFT, DEFAULT_TEXT_ALIGN_RIGHT, DEFAULT_TEXT_DECORATION, DEFAULT_TEXT_ELLIPSIS, DEFAULT_TEXT_FILL, DEFAULT_TEXT_LINE_HEIGHT, DEFAULT_TEXT_LISTENING, DEFAULT_TEXT_MAX_CACHE, DEFAULT_TEXT_MAX_HEIGHT, DEFAULT_TEXT_SCALE, DEFAULT_TEXT_TRANSFORMS_ENABLED, DEFAULT_TEXT_VERTICAL_ALIGN_MIDDLE, DEFAULT_TEXT_VERTICAL_ALIGN_TOP, DEFAULT_TEXT_WRAP, DEFAULT_WRAP_TEXT_MAX_ROW, DateCellEditorComponent, DateField, DepartmentOutlinedPath, Drawer, EditPath, FONT_SIZE_SM, FieldModelMap, GRID_CELL_EDITOR_MAP, IconPathMap, IsSelectRecordPipe, KO_CONTAINER_TOKEN, KoComponent, KoContainer, KoShape, KoShapeTypes, KoStage, LinkCellEditorComponent, LinkField, MIN_COLUMN_WIDTH, MemberField, MemberSettingPipe, MoreStandOutlinedPath, NumberCellEditorComponent, NumberField, ProgressField, RateField, RendererContext, RichTextField, RowDragPath, RowHeight, SelectCellEditorComponent, SelectField, SelectOptionComponent, SelectOptionPipe, SelectOptionsPipe, SelectSettingPipe, StarFill, TextCellEditorComponent, TextField, TextMeasure, Unchecked, UserPipe, WebOutlinedPath, aiTableFragmentAttribute, aiTableImageConfigToKonvaConfig, aiTableRectConfigToKonvaConfig, aiTableTextConfigToKonvaConfig, applyNodeProps, buildClipboardData, buildGridData, buildGridLinearRows, castToString, cellDrawer, clearCells, compareNumber, compareOption, compareString, createAITable, createActiveCellBorder, createCells, createDefaultField, createDefaultFieldName, createListener, defaultFieldOptions, drawer, expandCell, extractLinkUrl, extractText, generateNewName, generateTargetName, getAvatarBgColor, getAvatarShortName, getCellEditorBorderSpace, getCellHorizontalPosition, getColumnIndicesSizeMap, getCoverCell, getDefaultFieldValue, getDefaultI18nTextByKey, getDetailByTargetName, getEditorBoxOffset, getEditorSpace, getFieldOptionByField, getFieldOptionMap, getFieldOptions, getFieldValue, getFileThumbnailSvgString, getHoverEditorBoxOffset, getHoverEditorSpace, getI18nTextByKey, getMousePosition, getName, getPlaceHolderCellsConfigs, getSystemFieldValue, getTargetName, getTextWidth, getVisibleRangeInfo, graphemeSplitter, handleMouseStyle, hasIntersect, idCreator, idsCreator, imageCache, isActiveCell, isArrayField, isCellMatchKeywords, isClipboardReadSupported, isClipboardReadTextSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isDateFiled, isEmptyOrNot, isMac, isMeetFilter, isNumberFiled, isSameFieldOption, isSelectedField, isSystemField, isVirtualKey, isWindows, isWindowsOS, isWithinFrozenColumnBoundary, processPastedValueForSelect, readFromClipboard, scrollMax, setMouseStyle, shortIdCreator, shortIdsCreator, stringInclude, textDataCache, toAttachmentFieldValue, toDateFieldValue, toLinkFieldValue, toMemberFieldValue, toNumberFieldValue, toProgressFieldValue, toRateFieldValue, toRichTextFieldValue, toSelectFieldValue, toTextFieldValue, transformCellValue, updatePicture, writeToAITable, writeToClipboard, zhIntlCollator };
11079
+ export { AITable, AITableActionIcon, AITableAddField, AITableAreaType, AITableAvatarSize, AITableAvatarType, AITableCellAttachment, AITableCellLink, AITableCellProgress, AITableCellRate, AITableCellRichText, AITableCells, AITableCheckType, AITableColumnHeads, AITableContextMenu, AITableDomGrid, AITableFieldHead, AITableFieldIcon, AITableFieldIsSameOptionPipe, AITableFieldSetting, AITableFrozenCells, AITableFrozenColumnHeads, AITableFrozenPlaceholderCells, AITableGrid, AITableGridEventService, AITableGridFieldService, AITableGridI18nKey, AITableGridSelectionService, AITableHoverRowHeads, AITableIcon, AITableMemberType, AITableMouseDownType, AITableOtherRows, AITablePlaceholderCells, AITableQueries, AITableRenderer, AITableRowType, AITableSelectAllState, AITableTextComponent, AI_TABLE_ACTION_COMMON_RADIUS, AI_TABLE_ACTION_COMMON_RIGHT_PADDING, AI_TABLE_ACTION_COMMON_SIZE, AI_TABLE_AUTO_SCROLL_BOTTOM_THRESHOLD, AI_TABLE_AUTO_SCROLL_LEFT_THRESHOLD, AI_TABLE_AUTO_SCROLL_RIGHT_THRESHOLD, AI_TABLE_AUTO_SCROLL_TOP_THRESHOLD, AI_TABLE_BLANK, AI_TABLE_CELL, AI_TABLE_CELL_ACTIVE_BORDER_WIDTH, AI_TABLE_CELL_ADD_ITEM_BUTTON_SIZE, AI_TABLE_CELL_ATTACHMENT_ADD, AI_TABLE_CELL_ATTACHMENT_FILE, AI_TABLE_CELL_BORDER, AI_TABLE_CELL_DELETE_ITEM_BUTTON_SIZE, AI_TABLE_CELL_DELETE_ITEM_BUTTON_SIZE_OFFSET, AI_TABLE_CELL_EDIT, AI_TABLE_CELL_EMOJI_PADDING, AI_TABLE_CELL_EMOJI_SIZE, AI_TABLE_CELL_FIELD_ITEM_HEIGHT, AI_TABLE_CELL_MAX_ROW_COUNT, AI_TABLE_CELL_MEMBER_ITEM_HEIGHT, AI_TABLE_CELL_MEMBER_ITEM_PADDING, AI_TABLE_CELL_MEMBER_MAX_HEIGHT, AI_TABLE_CELL_MULTI_DOT_RADIUS, AI_TABLE_CELL_MULTI_ITEM_MARGIN_LEFT, AI_TABLE_CELL_MULTI_ITEM_MARGIN_TOP, AI_TABLE_CELL_MULTI_ITEM_MIN_WIDTH, AI_TABLE_CELL_MULTI_PADDING_LEFT, AI_TABLE_CELL_MULTI_PADDING_TOP, AI_TABLE_CELL_PADDING, AI_TABLE_COMMON_FONT_SIZE, AI_TABLE_DEFAULT_COLUMN_WIDTH, AI_TABLE_DOT_RADIUS, AI_TABLE_FIELD_ADD_BUTTON, AI_TABLE_FIELD_ADD_BUTTON_WIDTH, AI_TABLE_FIELD_HEAD, AI_TABLE_FIELD_HEAD_HEIGHT, AI_TABLE_FIELD_HEAD_ICON_GAP_SIZE, AI_TABLE_FIELD_HEAD_MORE, AI_TABLE_FIELD_HEAD_OPACITY_LINE, AI_TABLE_FIELD_HEAD_SELECT_CHECKBOX, AI_TABLE_FIELD_HEAD_TEXT_MIN_WIDTH, AI_TABLE_FIELD_ITEM_MARGIN_RIGHT, AI_TABLE_FIELD_MAX_WIDTH, AI_TABLE_FIELD_MIDDLE_WIDTH, AI_TABLE_FIELD_MINI_WIDTH, AI_TABLE_FIELD_MIN_WIDTH, AI_TABLE_FILE_ICON_ITEM_HEIGHT, AI_TABLE_FILE_ICON_SIZE, AI_TABLE_GRID_FIELD_SERVICE_MAP, AI_TABLE_ICON_COMMON_SIZE, AI_TABLE_MEMBER_AVATAR_SIZE, AI_TABLE_MEMBER_ITEM_AVATAR_MARGIN_RIGHT, AI_TABLE_MEMBER_ITEM_PADDING_RIGHT, AI_TABLE_MIN_TEXT_WIDTH, AI_TABLE_OFFSET, AI_TABLE_OPTION_ITEM_FONT_SIZE, AI_TABLE_OPTION_ITEM_HEIGHT, AI_TABLE_OPTION_ITEM_PADDING, AI_TABLE_OPTION_ITEM_RADIUS, AI_TABLE_PIECE_RADIUS, AI_TABLE_PIECE_WIDTH, AI_TABLE_POPOVER_LEFT_OFFSET, AI_TABLE_PREVENT_CLEAR_SELECTION_CLASS, AI_TABLE_PROGRESS_BAR_HEIGHT, AI_TABLE_PROGRESS_BAR_POINTER_HEIGHT, AI_TABLE_PROGRESS_BAR_POINTER_WIDTH, AI_TABLE_PROGRESS_BAR_RADIUS, AI_TABLE_PROGRESS_TEXT_WIDTH, AI_TABLE_RATE_MAX, AI_TABLE_ROW_ADD_BUTTON, AI_TABLE_ROW_BLANK_HEIGHT, AI_TABLE_ROW_DRAG, AI_TABLE_ROW_DRAG_ICON_WIDTH, AI_TABLE_ROW_HEAD, AI_TABLE_ROW_HEAD_SIZE, AI_TABLE_ROW_HEAD_WIDTH, AI_TABLE_ROW_HEIGHT, AI_TABLE_ROW_SELECT_CHECKBOX, AI_TABLE_SCROLL_BAR_PADDING, AI_TABLE_SCROLL_BAR_SIZE, AI_TABLE_TAG_FONT_SIZE, AI_TABLE_TAG_PADDING, AI_TABLE_TEXT_GAP, AbstractEditCellEditor, AddOutlinedPath, AttachmentField, AttachmentPath, CellDrawer, Check, Colors, ColumnCalendarFilledPath, ColumnLinkOutlinedPath, ColumnMemberFilledPath, ColumnMultipleFillPath, ColumnNumberFilledPath, ColumnProgressFilledPath, ColumnRatingFilledPath, ColumnRichTextFilledPath, ColumnSelectFilledPath, ColumnTextFilledPath, Coordinate, CoverCellComponent, DBL_CLICK_EDIT_TYPE, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_FONT_STYLE, DEFAULT_FONT_WEIGHT, DEFAULT_ICON_SHAPE, DEFAULT_ICON_SIZE, DEFAULT_POINT_POSITION, DEFAULT_SCROLL_STATE, DEFAULT_TEXT_ALIGN_CENTER, DEFAULT_TEXT_ALIGN_LEFT, DEFAULT_TEXT_ALIGN_RIGHT, DEFAULT_TEXT_DECORATION, DEFAULT_TEXT_ELLIPSIS, DEFAULT_TEXT_FILL, DEFAULT_TEXT_LINE_HEIGHT, DEFAULT_TEXT_LISTENING, DEFAULT_TEXT_MAX_CACHE, DEFAULT_TEXT_MAX_HEIGHT, DEFAULT_TEXT_SCALE, DEFAULT_TEXT_TRANSFORMS_ENABLED, DEFAULT_TEXT_VERTICAL_ALIGN_MIDDLE, DEFAULT_TEXT_VERTICAL_ALIGN_TOP, DEFAULT_TEXT_WRAP, DEFAULT_WRAP_TEXT_MAX_ROW, DateCellEditorComponent, DateField, DepartmentOutlinedPath, Drawer, EditPath, FONT_SIZE_SM, FieldModelMap, GRID_CELL_EDITOR_MAP, IconPathMap, IsSelectRecordPipe, KO_CONTAINER_TOKEN, KoComponent, KoContainer, KoShape, KoShapeTypes, KoStage, LinkCellEditorComponent, LinkField, MIN_COLUMN_WIDTH, MemberField, MemberSettingPipe, MoreStandOutlinedPath, NumberCellEditorComponent, NumberField, ProgressField, RateField, RendererContext, RichTextField, RowDragPath, RowHeight, SelectCellEditorComponent, SelectField, SelectOptionComponent, SelectOptionPipe, SelectOptionsPipe, SelectSettingPipe, StarFill, TextCellEditorComponent, TextField, TextMeasure, Unchecked, UserPipe, WebOutlinedPath, aiTableFragmentAttribute, aiTableImageConfigToKonvaConfig, aiTableRectConfigToKonvaConfig, aiTableTextConfigToKonvaConfig, applyNodeProps, buildClipboardData, buildGridData, buildGridLinearRows, castToString, cellDrawer, clearCells, compareNumber, compareOption, compareString, createAITable, createActiveCellBorder, createCells, createDefaultField, createDefaultFieldName, createListener, defaultFieldOptions, drawer, expandCell, extractLinkUrl, extractText, generateNewName, generateTargetName, getAvatarBgColor, getAvatarShortName, getCellEditorBorderSpace, getCellHorizontalPosition, getColumnIndicesSizeMap, getCoverCell, getDefaultFieldValue, getDefaultI18nTextByKey, getDetailByTargetName, getEditorBoxOffset, getEditorSpace, getFieldOptionByField, getFieldOptionMap, getFieldOptions, getFieldValue, getFileThumbnailSvgString, getHoverEditorBoxOffset, getHoverEditorSpace, getI18nTextByKey, getMousePosition, getName, getOptionsByFieldAndRecords, getPlaceHolderCellsConfigs, getSystemFieldValue, getTargetName, getTextWidth, getVisibleRangeInfo, graphemeSplitter, handleMouseStyle, hasIntersect, idCreator, idsCreator, imageCache, isActiveCell, isArrayField, isCellMatchKeywords, isClipboardReadSupported, isClipboardReadTextSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isDateFiled, isEmptyOrNot, isMac, isMeetFilter, isNumberFiled, isSameFieldOption, isSelectedField, isSystemField, isVirtualKey, isWindows, isWindowsOS, isWithinFrozenColumnBoundary, processPastedValueForSelect, readFromClipboard, scrollMax, setMouseStyle, shortIdCreator, shortIdsCreator, stringInclude, textDataCache, toAttachmentFieldValue, toDateFieldValue, toLinkFieldValue, toMemberFieldValue, toNumberFieldValue, toProgressFieldValue, toRateFieldValue, toRichTextFieldValue, toSelectFieldValue, toTextFieldValue, transformCellValue, updatePicture, writeToAITable, writeToClipboard, zhIntlCollator };
11012
11080
  //# sourceMappingURL=ai-table-grid.mjs.map