@ai-table/state 0.1.43 → 0.1.45

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.
@@ -733,7 +733,6 @@ class GroupCalculator {
733
733
  const linearRows = [];
734
734
  let lastGroupDepth = -1;
735
735
  let currentGroupRecords = [];
736
- let currentGroupIds = [];
737
736
  let currentGroupRecordIndices = []; // 记录当前分组中每个记录的原始索引
738
737
  // 开始添加一个空白行
739
738
  linearRows.push({
@@ -747,11 +746,10 @@ class GroupCalculator {
747
746
  if (groupTabRows.length > 0) {
748
747
  // 如果有新的分组标签,先处理上一个分组的结束
749
748
  if (currentGroupRecords.length > 0) {
750
- this.handleGroupEnd(currentGroupRecords, linearRows, currentGroupIds, currentGroupRecordIndices);
749
+ this.handleGroupEnd(currentGroupRecords, linearRows, currentGroupRecordIndices);
751
750
  currentGroupRecords = [];
752
751
  currentGroupRecordIndices = [];
753
752
  }
754
- currentGroupIds = groupTabRows.map((row) => row.groupId);
755
753
  const depths = groupTabRows.filter((d) => d.depth !== undefined).map((d) => d.depth);
756
754
  const minDepth = depths.length > 0 ? Math.min(...depths) : 0;
757
755
  // 如果当前分组的最小深度小于等于上一个分组的深度,说明是同级或上级分组,需添加空白行
@@ -762,9 +760,7 @@ class GroupCalculator {
762
760
  depth: minDepth
763
761
  });
764
762
  }
765
- // 只添加未被父级折叠的分组
766
- const visibleGroupTabRows = this.filterVisibleGroupTabs(groupTabRows);
767
- linearRows.push(...visibleGroupTabRows);
763
+ linearRows.push(...groupTabRows);
768
764
  lastGroupDepth = depths.length > 0 ? Math.max(...depths) : 0;
769
765
  }
770
766
  // 将记录添加到当前分组
@@ -773,7 +769,7 @@ class GroupCalculator {
773
769
  });
774
770
  // 处理最后一个分组
775
771
  if (currentGroupRecords.length > 0) {
776
- this.handleGroupEnd(currentGroupRecords, linearRows, currentGroupIds, currentGroupRecordIndices);
772
+ this.handleGroupEnd(currentGroupRecords, linearRows, currentGroupRecordIndices);
777
773
  }
778
774
  // 添加分组结束的空白行
779
775
  if (lastGroupDepth >= 0) {
@@ -785,12 +781,11 @@ class GroupCalculator {
785
781
  }
786
782
  return linearRows;
787
783
  }
788
- handleGroupEnd(currentGroupRecords, linearRows, currentGroupIds, currentGroupRecordIndices) {
789
- // 分组结束时添加该分组的记录和add行
784
+ handleGroupEnd(currentGroupRecords, linearRows, currentGroupRecordIndices) {
790
785
  let groupDisplayRowIndex = 0;
786
+ const lastLinearRow = linearRows[linearRows.length - 1];
791
787
  currentGroupRecords.forEach((record, i) => {
792
- const recordIndex = currentGroupRecordIndices?.[i] ?? 0;
793
- if (this.shouldShowRecord(recordIndex)) {
788
+ if (lastLinearRow?.type === AITableRowType.group && !lastLinearRow.isCollapsed) {
794
789
  groupDisplayRowIndex++;
795
790
  linearRows.push({
796
791
  type: AITableRowType.record,
@@ -801,7 +796,7 @@ class GroupCalculator {
801
796
  }
802
797
  });
803
798
  // 分组未折叠,为每个分组添加add新增行
804
- if (currentGroupRecords.length > 0 && this.shouldShowAddRow(currentGroupIds)) {
799
+ if (currentGroupRecords.length > 0 && lastLinearRow?.type === AITableRowType.group && !lastLinearRow.isCollapsed) {
805
800
  let startRecordIndex = 0;
806
801
  let endRecordIndex = 0;
807
802
  if (currentGroupRecordIndices) {
@@ -826,20 +821,23 @@ class GroupCalculator {
826
821
  const field = this.fieldsMap[groupField.field_id];
827
822
  if (!field)
828
823
  return;
829
- const groupValue = AITableQueries.getFieldValue(this.aiTable, [record._id, field._id]);
830
824
  const breakpointIndex = breakpoints.indexOf(recordIndex);
831
825
  const groupId = this.generateGroupId(groupField.field_id, depth, breakpointIndex);
832
- const recordRange = this.calculateGroupRecordRange(groupField.field_id, breakpointIndex, totalRecords);
833
- groupTabRows.push({
834
- type: AITableRowType.group,
835
- _id: nanoid(),
836
- depth,
837
- fieldId: groupField.field_id,
838
- groupValue,
839
- isCollapsed: this.groupCollapseState.has(groupId),
840
- range: recordRange,
841
- groupId
842
- });
826
+ const isParentCollapsed = this.isParentGroupCollapsed(depth, recordIndex);
827
+ if (!isParentCollapsed) {
828
+ const groupValue = AITableQueries.getFieldValue(this.aiTable, [record._id, field._id]);
829
+ const recordRange = this.calculateGroupRecordRange(groupField.field_id, breakpointIndex, totalRecords);
830
+ groupTabRows.push({
831
+ type: AITableRowType.group,
832
+ _id: nanoid(),
833
+ depth,
834
+ fieldId: groupField.field_id,
835
+ groupValue,
836
+ isCollapsed: this.groupCollapseState.has(groupId),
837
+ range: recordRange,
838
+ groupId
839
+ });
840
+ }
843
841
  }
844
842
  });
845
843
  return groupTabRows;
@@ -863,61 +861,27 @@ class GroupCalculator {
863
861
  // 通过字段ID、深度和断点索引确保唯一
864
862
  return `${fieldId}_${depth}_${breakpointIndex}`;
865
863
  }
866
- shouldShowRecord(recordIndex) {
867
- for (let depth = 0; depth < this.groups.length; depth++) {
868
- const groupField = this.groups[depth];
869
- const breakpoints = this.groupBreakpoints.get(groupField.field_id) || [];
870
- // 找到当前记录所属的分组断点
871
- let belongsToBreakpointIndex = -1;
872
- for (let i = breakpoints.length - 1; i >= 0; i--) {
873
- if (breakpoints[i] <= recordIndex) {
874
- belongsToBreakpointIndex = i;
864
+ // 检查所有父级分组是否被折叠
865
+ isParentGroupCollapsed(currentDepth, recordIndex) {
866
+ for (let parentDepth = 0; parentDepth < currentDepth; parentDepth++) {
867
+ const parentGroupField = this.groups[parentDepth];
868
+ const parentBreakpoints = this.groupBreakpoints.get(parentGroupField.field_id) || [];
869
+ let parentBreakpointIndex = -1;
870
+ for (let i = parentBreakpoints.length - 1; i >= 0; i--) {
871
+ if (parentBreakpoints[i] <= recordIndex) {
872
+ parentBreakpointIndex = i;
875
873
  break;
876
874
  }
877
875
  }
878
- if (belongsToBreakpointIndex >= 0) {
879
- const groupId = this.generateGroupId(groupField.field_id, depth, belongsToBreakpointIndex);
880
- if (this.groupCollapseState.has(groupId)) {
881
- return false; // 父级分组被折叠,不显示记录
882
- }
883
- }
884
- }
885
- return true;
886
- }
887
- // 检查当前分组是否应该显示添加行
888
- shouldShowAddRow(currentGroupIds) {
889
- if (!currentGroupIds || currentGroupIds.length === 0) {
890
- return true; // 默认显示
891
- }
892
- // 检查当前组的所有分组层级是否都展开
893
- for (const groupId of currentGroupIds) {
894
- if (this.groupCollapseState.has(groupId)) {
895
- return false; // 有层级被折叠,不显示添加行
896
- }
897
- }
898
- return true;
899
- }
900
- // 过滤可见的分组标签
901
- filterVisibleGroupTabs(groupTabRows) {
902
- const visibleRows = [];
903
- for (let i = 0; i < groupTabRows.length; i++) {
904
- const currentRow = groupTabRows[i];
905
- let show = true;
906
- // 检查当前分组标签的所有父级是否都展开
907
- const currentDepth = currentRow.depth ?? 0;
908
- for (let parentDepth = 0; parentDepth < currentDepth; parentDepth++) {
909
- // 找到同一记录索引下的父级分组ID
910
- const parentRow = groupTabRows.find((row) => row.depth === parentDepth);
911
- if (parentRow && this.groupCollapseState.has(parentRow.groupId)) {
912
- show = false;
913
- break;
876
+ if (parentBreakpointIndex > -1) {
877
+ const parentGroupId = this.generateGroupId(parentGroupField.field_id, parentDepth, parentBreakpointIndex);
878
+ const isParentCollapsed = this.groupCollapseState.has(parentGroupId);
879
+ if (isParentCollapsed) {
880
+ return true;
914
881
  }
915
882
  }
916
- if (show) {
917
- visibleRows.push(currentRow);
918
- }
919
883
  }
920
- return visibleRows;
884
+ return false;
921
885
  }
922
886
  }
923
887
 
@@ -1447,7 +1411,7 @@ function createMultiplePositions(views, activeId, data, targetIndex = data.lengt
1447
1411
  return positions;
1448
1412
  }
1449
1413
  function getPositions(activeId, data, targetIndex = data.length - 1, count = 1, isInsertBefore = false) {
1450
- let startPosition = data.length - 1;
1414
+ let startPosition = data[data.length - 1].positions[activeId];
1451
1415
  let endPosition = startPosition + count + 1;
1452
1416
  if (data[targetIndex]) {
1453
1417
  if (isInsertBefore) {
@@ -1551,7 +1515,7 @@ const apply = (aiTable, records, fields, views, action) => {
1551
1515
  case ActionName.UpdateFieldValue: {
1552
1516
  const [recordId, fieldId] = action.path;
1553
1517
  if (recordId && fieldId) {
1554
- const recordIndex = aiTable.records().findIndex((item) => item._id === recordId);
1518
+ const recordIndex = records.findIndex((item) => item._id === recordId);
1555
1519
  records[recordIndex].values[fieldId] = action.newFieldValue;
1556
1520
  }
1557
1521
  break;
@@ -1559,7 +1523,7 @@ const apply = (aiTable, records, fields, views, action) => {
1559
1523
  case ActionName.UpdateSystemFieldValue: {
1560
1524
  const [recordId] = action.path;
1561
1525
  if (recordId && action.updatedInfo) {
1562
- const recordIndex = aiTable.records().findIndex((item) => item._id === recordId);
1526
+ const recordIndex = records.findIndex((item) => item._id === recordId);
1563
1527
  if (action.updatedInfo.updated_at) {
1564
1528
  records[recordIndex].updated_at = action.updatedInfo.updated_at;
1565
1529
  }
@@ -1584,7 +1548,7 @@ const apply = (aiTable, records, fields, views, action) => {
1584
1548
  }
1585
1549
  case ActionName.RemoveField: {
1586
1550
  const [fieldId] = action.path;
1587
- const fieldIndex = aiTable.fields().findIndex((item) => item._id === fieldId);
1551
+ const fieldIndex = fields.findIndex((item) => item._id === fieldId);
1588
1552
  if (fieldIndex > -1) {
1589
1553
  fields.splice(fieldIndex, 1);
1590
1554
  records.forEach((item) => {
@@ -1595,7 +1559,7 @@ const apply = (aiTable, records, fields, views, action) => {
1595
1559
  }
1596
1560
  case ActionName.RemoveRecord: {
1597
1561
  const [recordId] = action.path;
1598
- const recordIndex = aiTable.records().findIndex((item) => item._id === recordId);
1562
+ const recordIndex = records.findIndex((item) => item._id === recordId);
1599
1563
  if (recordIndex > -1) {
1600
1564
  records.splice(recordIndex, 1);
1601
1565
  }
@@ -2020,6 +1984,24 @@ function getParentGroupValuesByGroupId(aiTable, groupId) {
2020
1984
  return pre;
2021
1985
  }, {});
2022
1986
  }
1987
+ function getPrevRecordIdByAddGroupId(aiTable, groupId) {
1988
+ const activeViewId = aiTable.activeViewId();
1989
+ const activeView = aiTable.viewsMap()[activeViewId];
1990
+ if (!activeView.settings?.groups?.length)
1991
+ return null;
1992
+ const visibleRowsIndexMap = aiTable.context.visibleRowsIndexMap();
1993
+ const rowIndex = visibleRowsIndexMap.get(groupId) ?? -1;
1994
+ if (rowIndex > -1) {
1995
+ const linearRows = aiTable.context.linearRows();
1996
+ const current = linearRows[rowIndex];
1997
+ const prev = linearRows[rowIndex - 1];
1998
+ if (current.type === AITableRowType.add && prev.type === AITableRowType.record) {
1999
+ return prev._id;
2000
+ }
2001
+ return null;
2002
+ }
2003
+ return null;
2004
+ }
2023
2005
 
2024
2006
  function moveRecords(aiTable, options, updatedInfo) {
2025
2007
  const activeViewId = aiTable.activeViewId();
@@ -2085,7 +2067,7 @@ function addFields(aiTable, options) {
2085
2067
  };
2086
2068
  }
2087
2069
  else {
2088
- newField.positions = createPositions(aiTable.views(), aiTable.activeViewId(), aiTable.gridData().fields, fields.length);
2070
+ newField.positions = createPositions(aiTable.views(), aiTable.activeViewId(), aiTable.gridData().fields);
2089
2071
  }
2090
2072
  Actions.addField(aiTable, newField, originId, isDuplicate);
2091
2073
  }
@@ -2120,18 +2102,20 @@ function addRecords(aiTable, trackableEntity, options) {
2120
2102
  const hiddenRecordIds = [];
2121
2103
  let needCopyGroupValuesMap = null;
2122
2104
  if (groups?.length && options.forGroupId) {
2105
+ if (!options.afterRecordId && !options.beforeRecordId) {
2106
+ const prevRecordId = getPrevRecordIdByAddGroupId(aiTable, options.forGroupId);
2107
+ if (prevRecordId) {
2108
+ options.afterRecordId = prevRecordId;
2109
+ }
2110
+ }
2123
2111
  needCopyGroupValuesMap = getParentGroupValuesByGroupId(aiTable, options.forGroupId);
2124
2112
  }
2125
- const records = aiTable.gridData().records;
2126
2113
  newRecordIds.forEach((id, index) => {
2127
2114
  const record = {
2128
2115
  _id: id,
2129
2116
  short_id: newRecordShortIds[index],
2130
2117
  values: newRecordValues,
2131
- ...trackableEntity,
2132
- positions: {
2133
- [activeViewId]: getMaxPosition(records, activeViewId) + 1
2134
- }
2118
+ ...trackableEntity
2135
2119
  };
2136
2120
  if (needCopyGroupValuesMap) {
2137
2121
  groups?.forEach((group) => {
@@ -2459,5 +2443,5 @@ const VIEW_ACTIONS = [ActionName.SetView, ActionName.AddView, ActionName.RemoveV
2459
2443
  * Generated bundle index. Do not edit.
2460
2444
  */
2461
2445
 
2462
- export { AITableStateI18nKey, AITableStateI18nText, Actions, CopyCellsItem, CopyFieldPropertyItem, DividerMenuItem, EditFieldPropertyItem, FLUSHING, GroupCalculator, InsertDownwardRecords, InsertUpwardRecords, PasteCellsItem, RemoveRecordsItem, UndoManagerService, VIEW_ACTIONS, YjsAITable, actionMappers, addFields, addRecords, addView, applyActionOps, applyActions, applyEvents, applyYjsEvents, buildFieldsByView, buildGroupLinearRows, buildRecordsByView, buildRemoveFieldItem, buildSetFieldAction, buildSetRecordPositionsActon, calculateAdaptiveFrozenColumnCount, checkConditions, createMultiplePositions, createPositions, createSharedType, doFilter, findNextRecordForTargetInOriginalRecords, findPrevRecordForTargetInOriginalRecords, freezeToThisColumn, generateCopyName, getDataBySharedType, getDefaultI18nTextByKey, getDefaultRecordDataByFilter, getDefaultRecordValues, getFieldPositionInView, getFieldsSizeMap, getFilteredRecords, getFrozenFieldId, getMaxPosition, getNewRecordsPosition, getParentGroupValuesByGroupId, getParentLinearRowGroups, getPosition, getPositionByAfterOrBeforeRecordId, getPositions, getRecordsBySharedJson, getSharedTypeByData, getSortFields, getSortRecords, getStateI18nTextByKey, isPathEqual, moveFields, moveRecords, removeView, restoreDefaultFrozenColumn, sortRecordsBySortInfo, sortViews, toSharedType, translateYjsEvent, updateFieldAndValues, updateFieldValues, withState };
2446
+ export { AITableStateI18nKey, AITableStateI18nText, Actions, CopyCellsItem, CopyFieldPropertyItem, DividerMenuItem, EditFieldPropertyItem, FLUSHING, GroupCalculator, InsertDownwardRecords, InsertUpwardRecords, PasteCellsItem, RemoveRecordsItem, UndoManagerService, VIEW_ACTIONS, YjsAITable, actionMappers, addFields, addRecords, addView, applyActionOps, applyActions, applyEvents, applyYjsEvents, buildFieldsByView, buildGroupLinearRows, buildRecordsByView, buildRemoveFieldItem, buildSetFieldAction, buildSetRecordPositionsActon, calculateAdaptiveFrozenColumnCount, checkConditions, createMultiplePositions, createPositions, createSharedType, doFilter, findNextRecordForTargetInOriginalRecords, findPrevRecordForTargetInOriginalRecords, freezeToThisColumn, generateCopyName, getDataBySharedType, getDefaultI18nTextByKey, getDefaultRecordDataByFilter, getDefaultRecordValues, getFieldPositionInView, getFieldsSizeMap, getFilteredRecords, getFrozenFieldId, getMaxPosition, getNewRecordsPosition, getParentGroupValuesByGroupId, getParentLinearRowGroups, getPosition, getPositionByAfterOrBeforeRecordId, getPositions, getPrevRecordIdByAddGroupId, getRecordsBySharedJson, getSharedTypeByData, getSortFields, getSortRecords, getStateI18nTextByKey, isPathEqual, moveFields, moveRecords, removeView, restoreDefaultFrozenColumn, sortRecordsBySortInfo, sortViews, toSharedType, translateYjsEvent, updateFieldAndValues, updateFieldValues, withState };
2463
2447
  //# sourceMappingURL=ai-table-state.mjs.map