@canvas-components/list-table 0.2.7 → 0.3.2

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.
package/dist/index.js CHANGED
@@ -980,6 +980,7 @@ function collectLeafColumns(columns) {
980
980
  // src/domain/constants.ts
981
981
  var DEFAULT_ROW_HEIGHT = 32;
982
982
  var DEFAULT_HEADER_ROW_HEIGHT = DEFAULT_ROW_HEIGHT;
983
+ var DEFAULT_SCROLLBAR_THICKNESS = 10;
983
984
  var HORIZONTAL_SCROLL_STEP = 120;
984
985
  var DEFAULT_SUMMARY_ROW_HEIGHT = DEFAULT_ROW_HEIGHT;
985
986
  var DEFAULT_EMPTY_BODY_HEIGHT = 96;
@@ -988,6 +989,7 @@ var FALLBACK_TABLE_WIDTH = 320;
988
989
  var FALLBACK_TABLE_HEIGHT = 240;
989
990
  var BODY_TOOLTIP_DELAY = 1e3;
990
991
  var TABLE_CONTENT_BORDER_SIZE = 2;
992
+ var TABLE_CONTENT_BORDER_RADIUS = 8;
991
993
  var SCROLL_OVERFLOW_EPSILON = 1;
992
994
  function resolveTableSize(value, fallback) {
993
995
  if (value == null) {
@@ -1048,6 +1050,7 @@ var ListTableDomHost = class {
1048
1050
  return this.nodes;
1049
1051
  }
1050
1052
  const wrapper = document.createElement("div");
1053
+ wrapper.className = "canvas-list-table-root";
1051
1054
  wrapper.style.position = "relative";
1052
1055
  wrapper.style.display = "flex";
1053
1056
  wrapper.style.flexDirection = "column";
@@ -1112,7 +1115,7 @@ var ListTableDomHost = class {
1112
1115
  );
1113
1116
  this.applyWrapperHeight();
1114
1117
  this.nodes.contentLayerElement.style.border = `1px solid ${theme.borderColor}`;
1115
- this.nodes.contentLayerElement.style.borderRadius = "0";
1118
+ this.nodes.contentLayerElement.style.borderRadius = `${TABLE_CONTENT_BORDER_RADIUS}px`;
1116
1119
  this.nodes.contentLayerElement.style.background = theme.backgroundColor;
1117
1120
  this.nodes.paginationElement.style.borderTop = `1px solid ${theme.borderColor}`;
1118
1121
  this.nodes.paginationElement.style.background = theme.backgroundColor;
@@ -1759,7 +1762,7 @@ var headerSelectionStateCache = /* @__PURE__ */ new WeakMap();
1759
1762
  var ROW_SELECTION_COLUMN_KEY = "__row_selection__";
1760
1763
  var ROW_SELECTOR_COLUMN_KEY = "__row_selector__";
1761
1764
  var EXPAND_COLUMN_KEY = "__row_expand__";
1762
- var DEFAULT_ROW_SELECTOR_WIDTH = 12;
1765
+ var DEFAULT_ROW_SELECTOR_WIDTH = DEFAULT_SCROLLBAR_THICKNESS;
1763
1766
  function getInitialSelectedRowKeys(options) {
1764
1767
  const rowSelection = options.rowSelection;
1765
1768
  if (!rowSelection) {
@@ -2548,8 +2551,14 @@ function getPriority(descriptor) {
2548
2551
  if (descriptor.kind === "body" && descriptor.fixed) {
2549
2552
  priority += 1;
2550
2553
  }
2554
+ if (isHeaderDescriptor(descriptor.kind) && descriptor.fixed) {
2555
+ priority += 3;
2556
+ }
2551
2557
  return priority;
2552
2558
  }
2559
+ function isHeaderDescriptor(kind) {
2560
+ return kind === "header" || kind === "header-selection" || kind === "header-action" || kind === "column-collapse-trigger" || kind === "resize-handle";
2561
+ }
2553
2562
  function getBasePriority(kind) {
2554
2563
  switch (kind) {
2555
2564
  case "grouping-remove":
@@ -3917,11 +3926,25 @@ function drawImagePlaceholder(ctx, x, y, width, height, backgroundColor = PLACEH
3917
3926
  var SYMBOL_COLOR_MAP = {
3918
3927
  star: "#fadb14",
3919
3928
  sun: "#faad14",
3920
- moon: "#597ef7"
3929
+ moon: "#597ef7",
3930
+ check: "#52c41a",
3931
+ close: "#ff4d4f"
3921
3932
  };
3922
3933
  function drawCellSymbol(ctx, params) {
3923
3934
  const { type, x, y, size, activeColor, inactiveColor } = params;
3924
3935
  const fillRatio = Math.min(Math.max(params.fillRatio, 0), 1);
3936
+ if (type === "check" || type === "close") {
3937
+ drawStatusSymbol(ctx, {
3938
+ type,
3939
+ x,
3940
+ y,
3941
+ size,
3942
+ activeColor,
3943
+ inactiveColor,
3944
+ fillRatio
3945
+ });
3946
+ return;
3947
+ }
3925
3948
  appendCellSymbolPath(ctx, type, x, y, size);
3926
3949
  ctx.fillStyle = inactiveColor;
3927
3950
  ctx.fill("evenodd");
@@ -3939,6 +3962,10 @@ function resolveCellSymbolColor(type) {
3939
3962
  return SYMBOL_COLOR_MAP[type];
3940
3963
  }
3941
3964
  function appendCellSymbolPath(ctx, type, x, y, size) {
3965
+ if (type === "check" || type === "close") {
3966
+ appendStatusSymbolPath(ctx, type, x, y, size);
3967
+ return;
3968
+ }
3942
3969
  if (type === "moon") {
3943
3970
  appendMoonPath(ctx, x, y, size);
3944
3971
  return;
@@ -3959,6 +3986,38 @@ function appendCellSymbolPath(ctx, type, x, y, size) {
3959
3986
  }
3960
3987
  ctx.closePath();
3961
3988
  }
3989
+ function drawStatusSymbol(ctx, params) {
3990
+ const { type, x, y, size, activeColor, inactiveColor, fillRatio } = params;
3991
+ ctx.save();
3992
+ ctx.lineCap = "round";
3993
+ ctx.lineJoin = "round";
3994
+ ctx.lineWidth = Math.max(size * 0.12, 1.5);
3995
+ appendStatusSymbolPath(ctx, type, x, y, size);
3996
+ ctx.strokeStyle = inactiveColor;
3997
+ ctx.stroke();
3998
+ if (fillRatio > 0) {
3999
+ ctx.beginPath();
4000
+ ctx.rect(x, y, size * fillRatio, size);
4001
+ ctx.clip();
4002
+ appendStatusSymbolPath(ctx, type, x, y, size);
4003
+ ctx.strokeStyle = activeColor;
4004
+ ctx.stroke();
4005
+ }
4006
+ ctx.restore();
4007
+ }
4008
+ function appendStatusSymbolPath(ctx, type, x, y, size) {
4009
+ ctx.beginPath();
4010
+ if (type === "check") {
4011
+ ctx.moveTo(x + size * 0.16, y + size * 0.52);
4012
+ ctx.lineTo(x + size * 0.4, y + size * 0.76);
4013
+ ctx.lineTo(x + size * 0.84, y + size * 0.26);
4014
+ return;
4015
+ }
4016
+ ctx.moveTo(x + size * 0.22, y + size * 0.22);
4017
+ ctx.lineTo(x + size * 0.78, y + size * 0.78);
4018
+ ctx.moveTo(x + size * 0.78, y + size * 0.22);
4019
+ ctx.lineTo(x + size * 0.22, y + size * 0.78);
4020
+ }
3962
4021
  function appendMoonPath(ctx, x, y, size) {
3963
4022
  ctx.beginPath();
3964
4023
  ctx.moveTo(x + size * 0.64, y + size * 0.04);
@@ -6228,6 +6287,7 @@ function resolveColumnFormItemProps(column, context) {
6228
6287
  // src/rendering/cell-content/cell-content-renderer.ts
6229
6288
  var CONTENT_HORIZONTAL_PADDING = 12;
6230
6289
  var CONTENT_GAP = 8;
6290
+ var LINK_CONTENT_GAP = 4;
6231
6291
  var CONTENT_VERTICAL_PADDING = 6;
6232
6292
  function resolveBodyCellContents(params) {
6233
6293
  return resolveRawBodyCellContents(params).filter(
@@ -6623,10 +6683,7 @@ function drawBodyCellContents(params) {
6623
6683
  return void 0;
6624
6684
  }
6625
6685
  const tooltipText = column.ellipsis === true && layout.truncated ? buildBodyContentsPlainText(contents) : void 0;
6626
- const blockHeight = Math.min(
6627
- layout.lines.length * lineHeight,
6628
- availableHeight
6629
- );
6686
+ const blockHeight = layout.lines.length * lineHeight;
6630
6687
  const contentTop = resolveContentTop(
6631
6688
  rect,
6632
6689
  blockHeight,
@@ -6635,9 +6692,9 @@ function drawBodyCellContents(params) {
6635
6692
  );
6636
6693
  const contentRect = {
6637
6694
  x: rect.x + paddingInline,
6638
- y: rect.y + paddingBlock,
6695
+ y: rect.y,
6639
6696
  width: availableWidth,
6640
- height: availableHeight
6697
+ height: rect.height
6641
6698
  };
6642
6699
  const contentVisibleRect = visibleRect ? intersectRects(contentRect, visibleRect) : contentRect;
6643
6700
  if (!contentVisibleRect) {
@@ -6665,8 +6722,8 @@ function drawBodyCellContents(params) {
6665
6722
  align: column.align
6666
6723
  });
6667
6724
  line.items.forEach((item, itemIndex) => {
6668
- if (itemIndex > 0 && item.gapBefore) {
6669
- cursorX += CONTENT_GAP;
6725
+ if (itemIndex > 0) {
6726
+ cursorX += item.gapBefore;
6670
6727
  }
6671
6728
  const itemDescriptors = [];
6672
6729
  drawExpandedBodyContent({
@@ -6761,7 +6818,7 @@ function measureBodyCellContentsWidth(params) {
6761
6818
  currentLineWidth = 0;
6762
6819
  return;
6763
6820
  }
6764
- const gapWidth = currentLineWidth > 0 && item.gapBefore ? CONTENT_GAP : 0;
6821
+ const gapWidth = currentLineWidth > 0 ? item.gapBefore : 0;
6765
6822
  currentLineWidth += gapWidth + contentWidth;
6766
6823
  });
6767
6824
  return Math.ceil(
@@ -6792,10 +6849,11 @@ function expandBodyContents(contents) {
6792
6849
  const textOnly = contents.every((content) => content.type === "text");
6793
6850
  const expanded = [];
6794
6851
  contents.forEach((content, contentIndex) => {
6852
+ const previousContent = contents[contentIndex - 1];
6795
6853
  expanded.push({
6796
6854
  content,
6797
6855
  contentIndex,
6798
- gapBefore: expanded.length > 0 && !textOnly
6856
+ gapBefore: expanded.length === 0 || textOnly ? 0 : previousContent?.type === "link" && content.type === "link" ? LINK_CONTENT_GAP : CONTENT_GAP
6799
6857
  });
6800
6858
  if ((content.type === "checkbox" || content.type === "radio") && content.label) {
6801
6859
  const textLabelContent = {
@@ -6808,7 +6866,7 @@ function expandBodyContents(contents) {
6808
6866
  expanded.push({
6809
6867
  content: textLabelContent,
6810
6868
  contentIndex,
6811
- gapBefore: true
6869
+ gapBefore: CONTENT_GAP
6812
6870
  });
6813
6871
  }
6814
6872
  });
@@ -6849,7 +6907,7 @@ function buildSingleLineLayout(ctx, contents, availableWidth, theme) {
6849
6907
  }
6850
6908
  break;
6851
6909
  }
6852
- const gapWidth = line.items.length > 0 && item.gapBefore ? CONTENT_GAP : 0;
6910
+ const gapWidth = line.items.length > 0 ? item.gapBefore : 0;
6853
6911
  const remainingWidth = availableWidth - line.width - gapWidth;
6854
6912
  if (remainingWidth <= 0) {
6855
6913
  truncated = true;
@@ -6917,7 +6975,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
6917
6975
  items: [
6918
6976
  {
6919
6977
  ...currentItem,
6920
- gapBefore: false,
6978
+ gapBefore: 0,
6921
6979
  width: fullWidth2
6922
6980
  }
6923
6981
  ],
@@ -6948,7 +7006,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
6948
7006
  {
6949
7007
  ...currentItem,
6950
7008
  content: fittedContent2,
6951
- gapBefore: false,
7009
+ gapBefore: 0,
6952
7010
  width: fittedWidth
6953
7011
  }
6954
7012
  ],
@@ -6970,11 +7028,11 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
6970
7028
  currentItem = {
6971
7029
  ...currentItem,
6972
7030
  content: setBreakableContentText(currentItem.content, remainingText2),
6973
- gapBefore: false
7031
+ gapBefore: 0
6974
7032
  };
6975
7033
  continue;
6976
7034
  }
6977
- const gapWidth = currentLine.items.length > 0 && currentItem.gapBefore ? CONTENT_GAP : 0;
7035
+ const gapWidth = currentLine.items.length > 0 ? currentItem.gapBefore : 0;
6978
7036
  const remainingWidth = availableWidth - currentLine.width - gapWidth;
6979
7037
  if (remainingWidth <= 0) {
6980
7038
  if (lines.length + 1 >= maxLines) {
@@ -6988,7 +7046,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
6988
7046
  currentLine = { items: [], width: 0 };
6989
7047
  currentItem = {
6990
7048
  ...currentItem,
6991
- gapBefore: false
7049
+ gapBefore: 0
6992
7050
  };
6993
7051
  continue;
6994
7052
  }
@@ -7008,7 +7066,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
7008
7066
  currentLine = { items: [], width: 0 };
7009
7067
  currentItem = {
7010
7068
  ...currentItem,
7011
- gapBefore: false
7069
+ gapBefore: 0
7012
7070
  };
7013
7071
  continue;
7014
7072
  }
@@ -7048,7 +7106,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
7048
7106
  currentLine = { items: [], width: 0 };
7049
7107
  currentItem = {
7050
7108
  ...currentItem,
7051
- gapBefore: false
7109
+ gapBefore: 0
7052
7110
  };
7053
7111
  continue;
7054
7112
  }
@@ -7076,7 +7134,7 @@ function buildWrappedLineLayout(ctx, contents, availableWidth, maxLines, theme)
7076
7134
  currentItem = {
7077
7135
  ...currentItem,
7078
7136
  content: setBreakableContentText(currentItem.content, remainingText),
7079
- gapBefore: false
7137
+ gapBefore: 0
7080
7138
  };
7081
7139
  }
7082
7140
  if (truncated) {
@@ -7589,10 +7647,10 @@ function applyTrailingEllipsis(ctx, line, theme, availableWidth) {
7589
7647
  continue;
7590
7648
  }
7591
7649
  const widthBefore = line.items.slice(0, index).reduce((sum, current, currentIndex) => {
7592
- const gapWidth2 = currentIndex > 0 && current.gapBefore ? CONTENT_GAP : 0;
7650
+ const gapWidth2 = currentIndex > 0 ? current.gapBefore : 0;
7593
7651
  return sum + gapWidth2 + current.width;
7594
7652
  }, 0);
7595
- const gapWidth = index > 0 && item.gapBefore ? CONTENT_GAP : 0;
7653
+ const gapWidth = index > 0 ? item.gapBefore : 0;
7596
7654
  const nextContent = truncateExpandedContent(
7597
7655
  ctx,
7598
7656
  item.content,
@@ -8040,23 +8098,24 @@ function resolveScrollbarRole(x, y, scrollbar) {
8040
8098
 
8041
8099
  // src/services/scrollbar-service.ts
8042
8100
  function resolvePointerHitWithScrollbars(result, x, y, scrollbarLayout) {
8043
- if (result.area !== "empty") {
8044
- return result;
8045
- }
8046
8101
  const horizontalScrollbar = scrollbarLayout.horizontal;
8047
8102
  if (horizontalScrollbar && isPointInScrollbar(x, y, horizontalScrollbar)) {
8103
+ const scrollbarRole = resolveScrollbarRole(x, y, horizontalScrollbar);
8048
8104
  return {
8049
8105
  area: "horizontal-scrollbar",
8050
8106
  columnKey: "__horizontal_scrollbar__",
8051
- scrollbarRole: resolveScrollbarRole(x, y, horizontalScrollbar)
8107
+ scrollbarRole,
8108
+ cursor: scrollbarRole === "thumb" ? "grab" : "pointer"
8052
8109
  };
8053
8110
  }
8054
8111
  const verticalScrollbar = scrollbarLayout.vertical;
8055
8112
  if (verticalScrollbar && isPointInScrollbar(x, y, verticalScrollbar)) {
8113
+ const scrollbarRole = resolveScrollbarRole(x, y, verticalScrollbar);
8056
8114
  return {
8057
8115
  area: "vertical-scrollbar",
8058
8116
  columnKey: "__vertical_scrollbar__",
8059
- scrollbarRole: resolveScrollbarRole(x, y, verticalScrollbar)
8117
+ scrollbarRole,
8118
+ cursor: scrollbarRole === "thumb" ? "grab" : "pointer"
8060
8119
  };
8061
8120
  }
8062
8121
  return result;
@@ -11575,6 +11634,9 @@ function resolveVisibleRowIndexForDataRow(params) {
11575
11634
  if (rowIndex >= params.rowCount) {
11576
11635
  return null;
11577
11636
  }
11637
+ if (params.frozenRows.scroll.dataRowIndexAligned) {
11638
+ return rowIndex;
11639
+ }
11578
11640
  for (const section of [
11579
11641
  params.frozenRows.top,
11580
11642
  params.frozenRows.scroll,
@@ -11598,7 +11660,7 @@ function resolveScrollTopForRowIndex(params) {
11598
11660
  if (frozenRows.top.rowIndexMap?.includes(rowIndex) || frozenRows.bottom.rowIndexMap?.includes(rowIndex)) {
11599
11661
  return null;
11600
11662
  }
11601
- const scrollSectionIndex = frozenRows.scroll.rowIndexMap ? frozenRows.scroll.rowIndexMap.indexOf(rowIndex) : rowIndex;
11663
+ const scrollSectionIndex = frozenRows.scroll.dataRowIndexAligned ? rowIndex : frozenRows.scroll.rowIndexMap ? frozenRows.scroll.rowIndexMap.indexOf(rowIndex) : rowIndex;
11602
11664
  if (scrollSectionIndex < 0) {
11603
11665
  return null;
11604
11666
  }
@@ -12947,69 +13009,55 @@ function matchFilterValue(rawValue, filterValue, optionValue = serializeFilterOp
12947
13009
  }
12948
13010
  function isMeaningfulFilterValue(value) {
12949
13011
  if ((value.filterType ?? "value") === "condition") {
12950
- return isSingleConditionActive(
12951
- value.conditionOperator ?? "none",
12952
- value.conditionValue?.trim() ?? "",
12953
- value.conditionSecondValue?.trim() ?? ""
12954
- ) || isSingleConditionActive(
12955
- value.secondConditionOperator ?? "none",
12956
- value.secondConditionValue?.trim() ?? "",
12957
- value.secondConditionSecondValue?.trim() ?? ""
13012
+ return resolveFilterConditions(value).some(
13013
+ (condition) => isSingleConditionActive(
13014
+ condition.operator,
13015
+ condition.value,
13016
+ condition.secondValue
13017
+ )
12958
13018
  );
12959
13019
  }
12960
13020
  return value.keyword.trim().length > 0 || (value.selectedKeys?.filter(Boolean).length ?? 0) > 0;
12961
13021
  }
12962
13022
  function matchConditionFilterValue(rawValue, filterValue) {
12963
13023
  const sourceText = stringifyFilterValue(rawValue).toLowerCase();
12964
- const firstOperator = filterValue.conditionOperator ?? "none";
12965
- const firstValue = filterValue.conditionValue?.trim().toLowerCase() ?? "";
12966
- const firstSecondValue = filterValue.conditionSecondValue?.trim().toLowerCase() ?? "";
12967
- const secondOperator = filterValue.secondConditionOperator ?? "none";
12968
- const secondValue = filterValue.secondConditionValue?.trim().toLowerCase() ?? "";
12969
- const secondSecondValue = filterValue.secondConditionSecondValue?.trim().toLowerCase() ?? "";
12970
- const relation = filterValue.conditionRelation ?? "and";
12971
- const hasFirst = isSingleConditionActive(
12972
- firstOperator,
12973
- firstValue,
12974
- firstSecondValue
12975
- );
12976
- const hasSecond = isSingleConditionActive(
12977
- secondOperator,
12978
- secondValue,
12979
- secondSecondValue
13024
+ const conditions = resolveFilterConditions(filterValue).filter(
13025
+ (condition) => isSingleConditionActive(
13026
+ condition.operator,
13027
+ condition.value,
13028
+ condition.secondValue
13029
+ )
12980
13030
  );
12981
- if (!hasFirst && !hasSecond) {
13031
+ const relation = filterValue.conditionRelation ?? "and";
13032
+ if (conditions.length === 0) {
12982
13033
  return true;
12983
13034
  }
12984
- if (!hasFirst) {
12985
- return evaluateCondition(
12986
- sourceText,
12987
- secondOperator,
12988
- secondValue,
12989
- secondSecondValue
12990
- );
12991
- }
12992
- if (!hasSecond) {
12993
- return evaluateCondition(
12994
- sourceText,
12995
- firstOperator,
12996
- firstValue,
12997
- firstSecondValue
12998
- );
12999
- }
13000
- const primaryResult = evaluateCondition(
13001
- sourceText,
13002
- firstOperator,
13003
- firstValue,
13004
- firstSecondValue
13005
- );
13006
- const secondaryResult = evaluateCondition(
13035
+ const matches = (condition) => evaluateCondition(
13007
13036
  sourceText,
13008
- secondOperator,
13009
- secondValue,
13010
- secondSecondValue
13037
+ condition.operator,
13038
+ condition.value,
13039
+ condition.secondValue
13011
13040
  );
13012
- return relation === "or" ? primaryResult || secondaryResult : primaryResult && secondaryResult;
13041
+ return relation === "or" ? conditions.some(matches) : conditions.every(matches);
13042
+ }
13043
+ function resolveFilterConditions(filterValue) {
13044
+ const source = filterValue.conditions?.length ? filterValue.conditions : [
13045
+ {
13046
+ operator: filterValue.conditionOperator ?? "none",
13047
+ value: filterValue.conditionValue,
13048
+ secondValue: filterValue.conditionSecondValue
13049
+ },
13050
+ {
13051
+ operator: filterValue.secondConditionOperator ?? "none",
13052
+ value: filterValue.secondConditionValue,
13053
+ secondValue: filterValue.secondConditionSecondValue
13054
+ }
13055
+ ];
13056
+ return source.map((condition) => ({
13057
+ operator: condition.operator,
13058
+ value: condition.value?.trim().toLowerCase() ?? "",
13059
+ secondValue: condition.secondValue?.trim().toLowerCase() ?? ""
13060
+ }));
13013
13061
  }
13014
13062
  function isSingleConditionActive(operator, conditionValue, conditionSecondValue) {
13015
13063
  if (!operator || operator === "none") {
@@ -13138,7 +13186,10 @@ var FILTER_PANEL_TEXTS = {
13138
13186
  relationAndLabel: "\u5E76\u4E14",
13139
13187
  relationOrLabel: "\u6216\u8005",
13140
13188
  resetAction: "\u91CD\u7F6E",
13141
- applyAction: "\u5E94\u7528"
13189
+ applyAction: "\u5E94\u7528",
13190
+ conditionLabel: "\u6761\u4EF6",
13191
+ addConditionAction: "\u65B0\u589E\u6761\u4EF6",
13192
+ deleteConditionAction: "\u5220\u9664\u6761\u4EF6"
13142
13193
  };
13143
13194
  var ASYNC_FILTER_OPTION_BATCH_SIZE = 2e4;
13144
13195
  function sortRows(rows, sortState, leafColumns) {
@@ -13236,7 +13287,8 @@ function buildFilterPanelValue(currentValue) {
13236
13287
  conditionRelation: currentValue.conditionRelation,
13237
13288
  secondConditionOperator: currentValue.secondConditionOperator,
13238
13289
  secondConditionValue: currentValue.secondConditionValue,
13239
- secondConditionSecondValue: currentValue.secondConditionSecondValue
13290
+ secondConditionSecondValue: currentValue.secondConditionSecondValue,
13291
+ conditions: currentValue.conditions
13240
13292
  };
13241
13293
  }
13242
13294
  function resolveFilterModes(column) {
@@ -13361,7 +13413,12 @@ function buildFilterStateValue(value) {
13361
13413
  conditionRelation: value.conditionRelation,
13362
13414
  secondConditionOperator: value.secondConditionOperator,
13363
13415
  secondConditionValue: value.secondConditionValue,
13364
- secondConditionSecondValue: value.secondConditionSecondValue
13416
+ secondConditionSecondValue: value.secondConditionSecondValue,
13417
+ conditions: value.conditions?.map((condition) => ({
13418
+ operator: condition.operator,
13419
+ value: condition.value,
13420
+ secondValue: condition.secondValue
13421
+ }))
13365
13422
  };
13366
13423
  }
13367
13424
  function toQueryFilters(filters) {
@@ -13682,6 +13739,9 @@ function showHeaderContextMenu(params) {
13682
13739
  return true;
13683
13740
  }
13684
13741
  function resolveContextMenuDensity(rowHeight) {
13742
+ if (rowHeight === "auto") {
13743
+ return "auto";
13744
+ }
13685
13745
  if (rowHeight === 56) {
13686
13746
  return "comfortable";
13687
13747
  }
@@ -15121,6 +15181,9 @@ var ListTableEventController = class {
15121
15181
  event.clientY
15122
15182
  );
15123
15183
  const result = this.host.resolvePointerHit(position.x, position.y);
15184
+ this.host.canvasHost.setCursor(
15185
+ result.area === "resize-handle" ? "col-resize" : result.cursor ?? ""
15186
+ );
15124
15187
  const nextHover = {
15125
15188
  rowIndex: result.rowIndex ?? null,
15126
15189
  columnKey: result.columnKey ?? null,
@@ -15143,9 +15206,6 @@ var ListTableEventController = class {
15143
15206
  result,
15144
15207
  () => this.host.updateTooltip(result)
15145
15208
  );
15146
- this.host.canvasHost.setCursor(
15147
- result.area === "resize-handle" ? "col-resize" : result.cursor ?? ""
15148
- );
15149
15209
  this.host.scheduleRender(result);
15150
15210
  });
15151
15211
  __publicField(this, "handleMouseDown", (event) => {
@@ -15316,6 +15376,9 @@ var ListTableEventController = class {
15316
15376
  if (!viewport) {
15317
15377
  return;
15318
15378
  }
15379
+ this.host.canvasHost.setCursor(
15380
+ result.scrollbarRole === "thumb" ? "grabbing" : "pointer"
15381
+ );
15319
15382
  if (result.scrollbarRole === "decrease-button") {
15320
15383
  this.stepScrollbar(result.area, -1, viewport);
15321
15384
  this.startContinuousScroll(result.area, -1, viewport);
@@ -15406,6 +15469,7 @@ var ListTableEventController = class {
15406
15469
  columnKey: null,
15407
15470
  area: "empty"
15408
15471
  };
15472
+ this.host.canvasHost.setCursor("");
15409
15473
  this.host.render();
15410
15474
  });
15411
15475
  __publicField(this, "handleContextMenu", (event) => {
@@ -16551,6 +16615,7 @@ var ListTableEventController = class {
16551
16615
  this.host.setGroupingBarDropActive?.(false);
16552
16616
  this.stopContinuousScroll();
16553
16617
  this.host.tooltip.hide();
16618
+ this.host.canvasHost.setCursor("");
16554
16619
  if (options?.unbindWindowEvents !== false) {
16555
16620
  this.host.canvasHost.unbindWindowDragEvents();
16556
16621
  }
@@ -17458,6 +17523,13 @@ function resolveToggleHeaderColumnVisibilityAction(params) {
17458
17523
 
17459
17524
  // src/shared/theme/density.ts
17460
17525
  function resolveDensitySizes(density) {
17526
+ if (density === "auto") {
17527
+ return {
17528
+ rowHeight: "auto",
17529
+ headerRowHeight: void 0,
17530
+ summaryRowHeight: void 0
17531
+ };
17532
+ }
17461
17533
  if (density === "comfortable") {
17462
17534
  return {
17463
17535
  rowHeight: 56,
@@ -18134,7 +18206,7 @@ function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryR
18134
18206
  filters: filterState,
18135
18207
  ...typeof zoom === "number" && Number.isFinite(zoom) && zoom > 0 ? { zoom } : null,
18136
18208
  ...typeof summaryRowHeight === "number" && Number.isFinite(summaryRowHeight) && summaryRowHeight >= 0 ? { summaryRowHeight } : null,
18137
- ...density === 32 || density === 48 || density === 56 ? { density } : null
18209
+ ...density === 32 || density === 48 || density === 56 || density === "auto" ? { density } : null
18138
18210
  };
18139
18211
  }
18140
18212
 
@@ -18184,7 +18256,7 @@ async function loadListTableStoredConfig(params) {
18184
18256
  filterState: stored.filters ? stored.filters : null,
18185
18257
  zoom: typeof stored.zoom === "number" && Number.isFinite(stored.zoom) && stored.zoom > 0 ? stored.zoom : null,
18186
18258
  summaryRowHeight: typeof stored.summaryRowHeight === "number" && Number.isFinite(stored.summaryRowHeight) && stored.summaryRowHeight >= 0 ? stored.summaryRowHeight : null,
18187
- density: stored.density === 32 || stored.density === 48 || stored.density === 56 ? stored.density : null
18259
+ density: stored.density === 32 || stored.density === 48 || stored.density === 56 || stored.density === "auto" ? stored.density : null
18188
18260
  };
18189
18261
  }
18190
18262
 
@@ -18217,11 +18289,12 @@ var ListTablePersistenceController = class {
18217
18289
  }
18218
18290
  let currentOptions = this.options.getOptions();
18219
18291
  if (stored.density != null) {
18292
+ const densitySizes = resolveDensitySizes(
18293
+ stored.density === "auto" ? "auto" : stored.density === 32 ? "compact" : stored.density === 56 ? "comfortable" : "middle"
18294
+ );
18220
18295
  currentOptions = {
18221
18296
  ...currentOptions,
18222
- rowHeight: stored.density,
18223
- headerRowHeight: stored.density,
18224
- summaryRowHeight: stored.density
18297
+ ...densitySizes
18225
18298
  };
18226
18299
  }
18227
18300
  if (stored.summaryRowHeight != null) {
@@ -18526,7 +18599,6 @@ function getMaxDepth(columns) {
18526
18599
  }
18527
18600
 
18528
18601
  // src/domain/layout/compute-scrollbar-layout.ts
18529
- var DEFAULT_SCROLLBAR_THICKNESS = 10;
18530
18602
  var DEFAULT_HORIZONTAL_LEFT = 0;
18531
18603
  var DEFAULT_HORIZONTAL_RIGHT = 0;
18532
18604
  var DEFAULT_HORIZONTAL_BOTTOM = 0;
@@ -20101,8 +20173,11 @@ function buildListTableRenderSnapshot(params) {
20101
20173
  baseRowsOverride,
20102
20174
  displayRowsOverride
20103
20175
  } = params;
20104
- const scrollbarThickness = options.scrollbar?.visible === false ? 0 : Math.max(options.scrollbar?.thickness ?? 10, 6);
20105
- let width = hostWidth;
20176
+ const scrollbarThickness = options.scrollbar?.visible === false ? 0 : Math.max(
20177
+ options.scrollbar?.thickness ?? DEFAULT_SCROLLBAR_THICKNESS,
20178
+ 6
20179
+ );
20180
+ let width = Math.max(hostWidth - scrollbarThickness, 0);
20106
20181
  let height = hostHeight;
20107
20182
  const sourceNormalizedColumns = normalizeColumns(
20108
20183
  getResolvedColumns(options, selectedRowKeys)
@@ -20323,6 +20398,7 @@ function buildListTableRenderSnapshot(params) {
20323
20398
  let bodyState = resolveCurrentBodyState();
20324
20399
  if (plainRowWindow) {
20325
20400
  bodyState.frozenRows.scroll.windowed = true;
20401
+ bodyState.frozenRows.scroll.dataRowIndexAligned = true;
20326
20402
  bodyState.frozenRows.scroll.rowIndexMap = plainRowWindow.rowIndexMap;
20327
20403
  bodyState.frozenRows.scroll.rowOffsetMap = plainRowWindow.rowOffsetMap;
20328
20404
  bodyState.bodyLayout = resolveBodyLayout({
@@ -20346,6 +20422,7 @@ function buildListTableRenderSnapshot(params) {
20346
20422
  bodyState = resolveCurrentBodyState();
20347
20423
  if (plainRowWindow) {
20348
20424
  bodyState.frozenRows.scroll.windowed = true;
20425
+ bodyState.frozenRows.scroll.dataRowIndexAligned = true;
20349
20426
  bodyState.frozenRows.scroll.rowIndexMap = plainRowWindow.rowIndexMap;
20350
20427
  bodyState.frozenRows.scroll.rowOffsetMap = plainRowWindow.rowOffsetMap;
20351
20428
  bodyState.bodyLayout = resolveBodyLayout({
@@ -20375,53 +20452,6 @@ function buildListTableRenderSnapshot(params) {
20375
20452
  fixedWidthRight: columnMetrics.fixedWidthRight,
20376
20453
  scroll
20377
20454
  });
20378
- for (let index = 0; index < 2 && scrollbarThickness > 0; index += 1) {
20379
- const nextWidth = Math.max(
20380
- hostWidth - (viewportResult.viewport.maxScrollTop > 0 ? scrollbarThickness : 0),
20381
- 0
20382
- );
20383
- const nextHeight = Math.max(
20384
- hostHeight - (viewportResult.viewport.maxScrollLeft > 0 ? scrollbarThickness : 0),
20385
- 0
20386
- );
20387
- if (nextWidth === width && nextHeight === height) {
20388
- break;
20389
- }
20390
- width = nextWidth;
20391
- height = nextHeight;
20392
- bodyState = resolveCurrentBodyState();
20393
- if (plainRowWindow) {
20394
- bodyState.frozenRows.scroll.windowed = true;
20395
- bodyState.frozenRows.scroll.rowIndexMap = plainRowWindow.rowIndexMap;
20396
- bodyState.frozenRows.scroll.rowOffsetMap = plainRowWindow.rowOffsetMap;
20397
- bodyState.bodyLayout = resolveBodyLayout({
20398
- height,
20399
- headerHeight,
20400
- summaryRowHeight,
20401
- hasSummary,
20402
- rowHeight,
20403
- totalBodyHeight: plainRowWindow.totalBodyHeight,
20404
- topFrozenRowCount: 0,
20405
- bottomFrozenRowCount: 0,
20406
- scrollRowCount: plainRowWindow.totalRowCount
20407
- });
20408
- }
20409
- columnMetrics = resolveColumnMetrics({
20410
- columns: leafColumns,
20411
- tableWidth: width
20412
- });
20413
- viewportResult = computeViewport({
20414
- width,
20415
- height,
20416
- headerHeight,
20417
- bodyHeight: bodyState.bodyLayout.scrollBodyHeight,
20418
- totalWidth: columnMetrics.totalWidth,
20419
- totalBodyHeight: bodyState.bodyLayout.totalBodyHeight,
20420
- fixedWidthLeft: columnMetrics.fixedWidthLeft,
20421
- fixedWidthRight: columnMetrics.fixedWidthRight,
20422
- scroll
20423
- });
20424
- }
20425
20455
  scrollPageSize = resolveScrollPageSize({
20426
20456
  options,
20427
20457
  pageSize: query.pagination.pageSize,
@@ -20912,7 +20942,7 @@ function resolveAutoRowHeightMeasureRows(rows, sampleCount = AUTO_ROW_HEIGHT_SAM
20912
20942
  return rows.slice(0, sampleCount);
20913
20943
  }
20914
20944
  function resolveListTableHeaderRowHeight(params) {
20915
- return params.headerRowHeight ?? (params.rowHeight === "auto" ? DEFAULT_ROW_HEIGHT : params.resolvedRowHeight);
20945
+ return params.headerRowHeight ?? params.resolvedRowHeight;
20916
20946
  }
20917
20947
  function buildListTableDebugSnapshot(params) {
20918
20948
  const {
@@ -21074,13 +21104,28 @@ function resolveListTableRenderHostSize(params) {
21074
21104
  }
21075
21105
 
21076
21106
  // src/rendering/primitives/draw-scrollbars.ts
21077
- function drawScrollbars(ctx, layout, descriptors, borderColor, opacity = 1, interactive = true) {
21107
+ function drawScrollbars(ctx, layout, descriptors, borderColor, opacity = 1, interactive = true, verticalFrame) {
21078
21108
  const alpha = Number.isFinite(opacity) ? Math.min(Math.max(opacity, 0), 1) : 1;
21079
21109
  if (alpha <= 1e-3) {
21080
21110
  return;
21081
21111
  }
21082
21112
  ctx.save();
21083
21113
  ctx.globalAlpha = alpha;
21114
+ if (layout.horizontal && verticalFrame) {
21115
+ drawHorizontalScrollbarMask(
21116
+ ctx,
21117
+ layout.horizontal,
21118
+ verticalFrame.bodyBackgroundColor
21119
+ );
21120
+ }
21121
+ if (layout.vertical && verticalFrame) {
21122
+ drawVerticalScrollbarFrame(
21123
+ ctx,
21124
+ layout.vertical,
21125
+ verticalFrame,
21126
+ borderColor
21127
+ );
21128
+ }
21084
21129
  if (layout.horizontal) {
21085
21130
  drawAxisScrollbar(
21086
21131
  ctx,
@@ -21101,6 +21146,45 @@ function drawScrollbars(ctx, layout, descriptors, borderColor, opacity = 1, inte
21101
21146
  interactive
21102
21147
  );
21103
21148
  }
21149
+ if (layout.horizontal) {
21150
+ drawHorizontalScrollbarTopBorder(
21151
+ ctx,
21152
+ layout.horizontal,
21153
+ layout.vertical,
21154
+ borderColor
21155
+ );
21156
+ }
21157
+ ctx.restore();
21158
+ }
21159
+ function drawHorizontalScrollbarMask(ctx, layout, backgroundColor) {
21160
+ const left = layout.decreaseButton.x;
21161
+ const right = layout.increaseButton.x + layout.increaseButton.width;
21162
+ const top = layout.decreaseButton.y;
21163
+ const height = layout.decreaseButton.height;
21164
+ if (right <= left || height <= 0) {
21165
+ return;
21166
+ }
21167
+ ctx.save();
21168
+ ctx.fillStyle = backgroundColor;
21169
+ ctx.fillRect(left, top, right - left, height);
21170
+ ctx.restore();
21171
+ }
21172
+ function drawHorizontalScrollbarTopBorder(ctx, horizontal, vertical, borderColor) {
21173
+ const left = Math.round(horizontal.decreaseButton.x) + 0.5;
21174
+ const horizontalRight = horizontal.increaseButton.x + horizontal.increaseButton.width;
21175
+ const verticalRight = vertical ? vertical.decreaseButton.x + vertical.decreaseButton.width : horizontalRight;
21176
+ const right = Math.round(Math.max(horizontalRight, verticalRight)) - 0.5;
21177
+ const top = Math.round(horizontal.decreaseButton.y) + 0.5;
21178
+ if (right <= left) {
21179
+ return;
21180
+ }
21181
+ ctx.save();
21182
+ ctx.strokeStyle = borderColor;
21183
+ ctx.lineWidth = 1;
21184
+ ctx.beginPath();
21185
+ ctx.moveTo(left, top);
21186
+ ctx.lineTo(right, top);
21187
+ ctx.stroke();
21104
21188
  ctx.restore();
21105
21189
  }
21106
21190
  function drawAxisScrollbar(ctx, layout, axis, descriptors, borderColor, interactive) {
@@ -21131,19 +21215,69 @@ function drawAxisScrollbar(ctx, layout, axis, descriptors, borderColor, interact
21131
21215
  scrollbarRole: "increase-button"
21132
21216
  });
21133
21217
  }
21134
- drawTrack(ctx, layout.track, borderColor);
21135
21218
  drawButton(ctx, layout.decreaseButton, axis, "decrease");
21136
21219
  drawButton(ctx, layout.increaseButton, axis, "increase");
21137
21220
  drawThumb(ctx, layout.thumb);
21221
+ drawTrackBorder(ctx, layout.track, axis, borderColor);
21222
+ }
21223
+ function drawTrackBorder(ctx, rect, axis, borderColor) {
21224
+ const left = Math.round(rect.x) + 0.5;
21225
+ const right = Math.round(rect.x + rect.width) - 0.5;
21226
+ const top = Math.round(rect.y) + 0.5;
21227
+ const bottom = Math.round(rect.y + rect.height) - 0.5;
21228
+ if (right <= left || bottom <= top) {
21229
+ return;
21230
+ }
21231
+ ctx.save();
21232
+ ctx.strokeStyle = borderColor;
21233
+ ctx.lineWidth = 1;
21234
+ ctx.beginPath();
21235
+ if (axis === "horizontal") {
21236
+ ctx.moveTo(left, top);
21237
+ ctx.lineTo(right, top);
21238
+ } else {
21239
+ ctx.moveTo(left, top);
21240
+ ctx.lineTo(left, bottom);
21241
+ }
21242
+ ctx.stroke();
21243
+ ctx.restore();
21138
21244
  }
21139
- function drawTrack(ctx, rect, borderColor) {
21245
+ function drawVerticalScrollbarFrame(ctx, layout, frame, borderColor) {
21246
+ const left = Math.round(layout.decreaseButton.x) + 0.5;
21247
+ const right = Math.round(layout.decreaseButton.x + layout.decreaseButton.width) - 0.5;
21248
+ const top = Math.round(frame.top) + 0.5;
21249
+ const bottom = Math.round(frame.top + frame.height) - 0.5;
21250
+ const headerBottom = Math.round(frame.headerBottom) + 0.5;
21251
+ if (right <= left || bottom <= top) {
21252
+ return;
21253
+ }
21140
21254
  ctx.save();
21141
- ctx.fillStyle = "rgba(148, 163, 184, 0.16)";
21255
+ ctx.fillStyle = frame.headerBackgroundColor;
21256
+ ctx.fillRect(
21257
+ layout.decreaseButton.x,
21258
+ frame.top,
21259
+ layout.decreaseButton.width,
21260
+ Math.max(frame.headerBottom - frame.top, 0)
21261
+ );
21262
+ ctx.fillStyle = frame.bodyBackgroundColor;
21263
+ ctx.fillRect(
21264
+ layout.decreaseButton.x,
21265
+ frame.headerBottom,
21266
+ layout.decreaseButton.width,
21267
+ Math.max(frame.top + frame.height - frame.headerBottom, 0)
21268
+ );
21142
21269
  ctx.strokeStyle = borderColor;
21143
21270
  ctx.lineWidth = 1;
21144
- roundRect(ctx, rect.x, rect.y, rect.width, rect.height, rect.height / 2);
21145
- ctx.fill();
21271
+ ctx.beginPath();
21272
+ ctx.moveTo(left, top);
21273
+ ctx.lineTo(left, bottom);
21146
21274
  ctx.stroke();
21275
+ if (headerBottom > top && headerBottom < bottom) {
21276
+ ctx.beginPath();
21277
+ ctx.moveTo(left, headerBottom);
21278
+ ctx.lineTo(right, headerBottom);
21279
+ ctx.stroke();
21280
+ }
21147
21281
  ctx.restore();
21148
21282
  }
21149
21283
  function drawThumb(ctx, rect) {
@@ -21155,34 +21289,25 @@ function drawThumb(ctx, rect) {
21155
21289
  }
21156
21290
  function drawButton(ctx, rect, axis, direction) {
21157
21291
  ctx.save();
21158
- ctx.fillStyle = "rgba(226, 232, 240, 0.92)";
21159
- ctx.strokeStyle = "rgba(148, 163, 184, 0.65)";
21160
- ctx.lineWidth = 1;
21161
- roundRect(ctx, rect.x, rect.y, rect.width, rect.height, rect.height / 2);
21162
- ctx.fill();
21163
- ctx.stroke();
21164
21292
  ctx.fillStyle = "rgba(71, 85, 105, 0.88)";
21165
21293
  ctx.beginPath();
21294
+ const centerX = rect.x + rect.width / 2;
21295
+ const centerY = rect.y + rect.height / 2;
21296
+ const iconSize = Math.min(rect.width, rect.height) * 0.64;
21297
+ const directionOffset = iconSize * 0.4;
21298
+ const crossAxisOffset = iconSize / 2;
21166
21299
  if (axis === "horizontal") {
21167
- const centerY = rect.y + rect.height / 2;
21168
- const iconWidth = rect.width * 0.28;
21169
- const iconHeight = rect.height * 0.22;
21170
- const centerX = rect.x + rect.width / 2;
21171
- const tipX = direction === "decrease" ? centerX - iconWidth / 2 : centerX + iconWidth / 2;
21172
- const tailX = direction === "decrease" ? centerX + iconWidth / 2 : centerX - iconWidth / 2;
21300
+ const tipX = centerX + (direction === "decrease" ? -1 : 1) * directionOffset;
21301
+ const tailX = centerX + (direction === "decrease" ? 1 : -1) * directionOffset;
21173
21302
  ctx.moveTo(tipX, centerY);
21174
- ctx.lineTo(tailX, centerY - iconHeight);
21175
- ctx.lineTo(tailX, centerY + iconHeight);
21303
+ ctx.lineTo(tailX, centerY - crossAxisOffset);
21304
+ ctx.lineTo(tailX, centerY + crossAxisOffset);
21176
21305
  } else {
21177
- const centerX = rect.x + rect.width / 2;
21178
- const iconWidth = rect.width * 0.22;
21179
- const iconHeight = rect.height * 0.28;
21180
- const centerY = rect.y + rect.height / 2;
21181
- const tipY = direction === "decrease" ? centerY - iconHeight / 2 : centerY + iconHeight / 2;
21182
- const tailY = direction === "decrease" ? centerY + iconHeight / 2 : centerY - iconHeight / 2;
21306
+ const tipY = centerY + (direction === "decrease" ? -1 : 1) * directionOffset;
21307
+ const tailY = centerY + (direction === "decrease" ? 1 : -1) * directionOffset;
21183
21308
  ctx.moveTo(centerX, tipY);
21184
- ctx.lineTo(centerX - iconWidth, tailY);
21185
- ctx.lineTo(centerX + iconWidth, tailY);
21309
+ ctx.lineTo(centerX - crossAxisOffset, tailY);
21310
+ ctx.lineTo(centerX + crossAxisOffset, tailY);
21186
21311
  }
21187
21312
  ctx.closePath();
21188
21313
  ctx.fill();
@@ -23110,7 +23235,8 @@ function drawHeaderCell(params, cell, clipRect) {
23110
23235
  descriptors.push({
23111
23236
  kind: "header",
23112
23237
  rect,
23113
- columnKey: cell.node.key
23238
+ columnKey: cell.node.key,
23239
+ fixed: cell.node.fixed
23114
23240
  });
23115
23241
  if (params.rowSelection.type === "checkbox") {
23116
23242
  drawHeaderSelectionControl(params, rect);
@@ -23118,7 +23244,8 @@ function drawHeaderCell(params, cell, clipRect) {
23118
23244
  kind: "header-selection",
23119
23245
  rect: getHeaderSelectionRect(rect),
23120
23246
  columnKey: cell.node.key,
23121
- controlType: params.rowSelection.type
23247
+ controlType: params.rowSelection.type,
23248
+ fixed: cell.node.fixed
23122
23249
  });
23123
23250
  }
23124
23251
  ctx.restore();
@@ -23128,7 +23255,8 @@ function drawHeaderCell(params, cell, clipRect) {
23128
23255
  descriptors.push({
23129
23256
  kind: "header",
23130
23257
  rect,
23131
- columnKey: cell.node.key
23258
+ columnKey: cell.node.key,
23259
+ fixed: cell.node.fixed
23132
23260
  });
23133
23261
  ctx.restore();
23134
23262
  return;
@@ -23177,12 +23305,25 @@ function drawHeaderCell(params, cell, clipRect) {
23177
23305
  textLayout,
23178
23306
  titleContent,
23179
23307
  ctx
23180
- )
23308
+ ),
23309
+ fixed: cell.node.fixed
23181
23310
  });
23182
23311
  if (cell.node.children.length === 0) {
23183
- drawCollapsedColumnMarkers(params, rect, cell.node.key, collapseMarkerSet);
23184
- drawHeaderActions(params, rect, cell.node.key, visibleState);
23185
- drawResizeHandles(params, rect, cell.node.key);
23312
+ drawCollapsedColumnMarkers(
23313
+ params,
23314
+ rect,
23315
+ cell.node.key,
23316
+ collapseMarkerSet,
23317
+ cell.node.fixed
23318
+ );
23319
+ drawHeaderActions(
23320
+ params,
23321
+ rect,
23322
+ cell.node.key,
23323
+ visibleState,
23324
+ cell.node.fixed
23325
+ );
23326
+ drawResizeHandles(params, rect, cell.node.key, cell.node.fixed);
23186
23327
  }
23187
23328
  ctx.restore();
23188
23329
  }
@@ -23220,7 +23361,7 @@ function measureHeaderContentWidth(ctx, contents) {
23220
23361
  0
23221
23362
  ) + Math.max(contents.length - 1, 0) * gap;
23222
23363
  }
23223
- function drawHeaderActions(params, rect, columnKey, visibilityState) {
23364
+ function drawHeaderActions(params, rect, columnKey, visibilityState, fixed) {
23224
23365
  if (!visibilityState.visible) {
23225
23366
  return;
23226
23367
  }
@@ -23273,7 +23414,8 @@ function drawHeaderActions(params, rect, columnKey, visibilityState) {
23273
23414
  rect: actionRect,
23274
23415
  columnKey,
23275
23416
  actionType,
23276
- visibilityState
23417
+ visibilityState,
23418
+ fixed
23277
23419
  });
23278
23420
  });
23279
23421
  }
@@ -23295,15 +23437,15 @@ function resolveCollapsedColumnMarkerSet(markers, columnKey) {
23295
23437
  hasRightMarker: !!right
23296
23438
  };
23297
23439
  }
23298
- function drawCollapsedColumnMarkers(params, rect, columnKey, markerSet) {
23440
+ function drawCollapsedColumnMarkers(params, rect, columnKey, markerSet, fixed) {
23299
23441
  if (markerSet.left) {
23300
- drawCollapsedColumnMarker(params, rect, columnKey, markerSet.left);
23442
+ drawCollapsedColumnMarker(params, rect, columnKey, markerSet.left, fixed);
23301
23443
  }
23302
23444
  if (markerSet.right) {
23303
- drawCollapsedColumnMarker(params, rect, columnKey, markerSet.right);
23445
+ drawCollapsedColumnMarker(params, rect, columnKey, markerSet.right, fixed);
23304
23446
  }
23305
23447
  }
23306
- function drawCollapsedColumnMarker(params, rect, columnKey, marker) {
23448
+ function drawCollapsedColumnMarker(params, rect, columnKey, marker, fixed) {
23307
23449
  const triggerRect = {
23308
23450
  x: marker.align === "left" ? rect.x + GRID_LINE_OFFSET2 - COLLAPSE_TRIGGER_WIDTH / 2 : rect.x + rect.width + GRID_LINE_OFFSET2 - COLLAPSE_TRIGGER_WIDTH / 2,
23309
23451
  y: rect.y + (rect.height - COLLAPSE_TRIGGER_HEIGHT) / 2,
@@ -23317,7 +23459,8 @@ function drawCollapsedColumnMarker(params, rect, columnKey, marker) {
23317
23459
  rect: triggerRect,
23318
23460
  columnKey,
23319
23461
  cursor: "pointer",
23320
- contentKey: `${marker.rangeStart}:${marker.rangeEnd}`
23462
+ contentKey: `${marker.rangeStart}:${marker.rangeEnd}`,
23463
+ fixed
23321
23464
  });
23322
23465
  }
23323
23466
  function isHeaderCellSelected(params, columnKey, rect) {
@@ -23339,13 +23482,14 @@ function isHeaderCellInRange(rangeHighlight, cell) {
23339
23482
  function isSameRect(left, right) {
23340
23483
  return Math.abs(left.x - right.x) <= 1 && Math.abs(left.y - right.y) <= 1 && Math.abs(left.width - right.width) <= 1 && Math.abs(left.height - right.height) <= 1;
23341
23484
  }
23342
- function drawResizeHandles(params, rect, columnKey) {
23485
+ function drawResizeHandles(params, rect, columnKey, fixed) {
23343
23486
  if (params.isResizable(columnKey)) {
23344
23487
  params.descriptors.push({
23345
23488
  kind: "resize-handle",
23346
23489
  rect: getResizeHandleRect(params, rect, "right"),
23347
23490
  columnKey,
23348
- resizeEdge: "right"
23491
+ resizeEdge: "right",
23492
+ fixed
23349
23493
  });
23350
23494
  }
23351
23495
  const leafIndex = params.leafColumnKeys?.indexOf(columnKey) ?? -1;
@@ -23355,7 +23499,8 @@ function drawResizeHandles(params, rect, columnKey) {
23355
23499
  kind: "resize-handle",
23356
23500
  rect: getResizeHandleRect(params, rect, "left"),
23357
23501
  columnKey: previousColumnKey,
23358
- resizeEdge: "left"
23502
+ resizeEdge: "left",
23503
+ fixed
23359
23504
  });
23360
23505
  }
23361
23506
  }
@@ -23749,15 +23894,18 @@ function resolveActiveCellOverlayLayout(params) {
23749
23894
  const descriptor = selection.rowIndex != null && selection.columnKey != null ? params.descriptors.find(
23750
23895
  (item) => item.kind === "body" && item.rowIndex === selection.rowIndex && item.columnKey === selection.columnKey
23751
23896
  ) : void 0;
23752
- const rangeRects = resolveRangeHighlightLayouts({
23897
+ const rangeLayout = resolveRangeHighlightLayouts({
23753
23898
  descriptors: params.descriptors,
23754
23899
  rangeHighlight: params.rangeHighlight,
23755
23900
  highlightMode: params.highlightMode,
23756
23901
  columnKeys: params.columnKeys ?? [],
23757
23902
  allowColumnRange: selection.rowIndex == null,
23758
23903
  allowRowRange: selection.columnKey === ROW_SELECTOR_COLUMN_KEY,
23759
- resolveClipRect: (item) => resolveActiveCellSectionClipRect(item, params)
23904
+ resolveClipRect: (item) => resolveActiveCellSectionClipRect(item, params),
23905
+ width: params.width,
23906
+ height: params.height
23760
23907
  });
23908
+ const rangeRects = rangeLayout.rects;
23761
23909
  if (!descriptor && rangeRects.length === 0) {
23762
23910
  return null;
23763
23911
  }
@@ -23768,6 +23916,7 @@ function resolveActiveCellOverlayLayout(params) {
23768
23916
  return {
23769
23917
  rect: descriptor?.rect ?? { x: 0, y: 0, width: 0, height: 0 },
23770
23918
  clipRect,
23919
+ rangeSegments: rangeLayout.segments,
23771
23920
  rangeRects
23772
23921
  };
23773
23922
  }
@@ -23776,14 +23925,44 @@ function drawActiveCellOverlay(params) {
23776
23925
  return;
23777
23926
  }
23778
23927
  const { ctx, layout } = params;
23779
- layout.rangeRects.forEach(({ rect, clipRect, omitLeft, omitRight }) => {
23780
- ctx.save();
23781
- ctx.beginPath();
23782
- ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
23783
- ctx.clip();
23784
- drawRangeHighlightBorder(ctx, rect, { omitLeft, omitRight });
23785
- ctx.restore();
23786
- });
23928
+ if (layout.rangeSegments?.length) {
23929
+ layout.rangeSegments.forEach((segment) => {
23930
+ ctx.save();
23931
+ ctx.beginPath();
23932
+ ctx.rect(
23933
+ segment.clipRect.x,
23934
+ segment.clipRect.y,
23935
+ segment.clipRect.width,
23936
+ segment.clipRect.height
23937
+ );
23938
+ ctx.clip();
23939
+ ctx.strokeStyle = "#1677ff";
23940
+ ctx.lineWidth = 1;
23941
+ ctx.beginPath();
23942
+ ctx.moveTo(segment.startX, segment.startY);
23943
+ if (segment.controlX != null && segment.controlY != null) {
23944
+ ctx.quadraticCurveTo(
23945
+ segment.controlX,
23946
+ segment.controlY,
23947
+ segment.endX,
23948
+ segment.endY
23949
+ );
23950
+ } else {
23951
+ ctx.lineTo(segment.endX, segment.endY);
23952
+ }
23953
+ ctx.stroke();
23954
+ ctx.restore();
23955
+ });
23956
+ } else {
23957
+ layout.rangeRects.forEach(({ rect, clipRect, omitLeft, omitRight }) => {
23958
+ ctx.save();
23959
+ ctx.beginPath();
23960
+ ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
23961
+ ctx.clip();
23962
+ drawRangeHighlightBorder(ctx, rect, { omitLeft, omitRight });
23963
+ ctx.restore();
23964
+ });
23965
+ }
23787
23966
  if (layout.rangeRects.length === 0 && layout.rect.width > 0 && layout.rect.height > 0) {
23788
23967
  ctx.save();
23789
23968
  ctx.beginPath();
@@ -23804,17 +23983,19 @@ function resolveRangeHighlightLayouts(params) {
23804
23983
  const cellRange = params.rangeHighlight?.selectedCellRange;
23805
23984
  const rowSelectorRange = rowRange && params.allowRowRange;
23806
23985
  if (!cellRange && !rowSelectorRange && (!columnRange || !params.allowColumnRange)) {
23807
- return [];
23986
+ return { rects: [], segments: [] };
23808
23987
  }
23809
23988
  const bodyDescriptors = params.descriptors.filter(
23810
23989
  (item) => item.kind === "body" && item.columnKey != null && item.rowIndex != null
23811
23990
  );
23812
23991
  const selected = bodyDescriptors.filter((item) => {
23813
- const rowSelected = rowRange != null && item.rowIndex >= rowRange.start && item.rowIndex <= rowRange.end;
23992
+ const itemRowStart = item.rowIndex;
23993
+ const itemRowEnd = itemRowStart + Math.max(item.rowSpan ?? 1, 1) - 1;
23994
+ const rowSelected = rowRange != null && itemRowEnd >= rowRange.start && itemRowStart <= rowRange.end;
23814
23995
  const columnIndex = params.columnKeys.indexOf(item.columnKey);
23815
23996
  const columnSelected = columnRange != null && columnIndex >= columnRange.start && columnIndex <= columnRange.end;
23816
23997
  if (cellRange) {
23817
- return item.rowIndex >= cellRange.startRowIndex && item.rowIndex <= cellRange.endRowIndex && columnIndex >= cellRange.startColumnIndex && columnIndex <= cellRange.endColumnIndex;
23998
+ return itemRowEnd >= cellRange.startRowIndex && itemRowStart <= cellRange.endRowIndex && columnIndex >= cellRange.startColumnIndex && columnIndex <= cellRange.endColumnIndex;
23818
23999
  }
23819
24000
  if (rowSelectorRange) {
23820
24001
  return rowSelected;
@@ -23850,7 +24031,7 @@ function resolveRangeHighlightLayouts(params) {
23850
24031
  layer.push(range);
23851
24032
  groupedByLayer.set(key, layer);
23852
24033
  });
23853
- return ranges.map((range) => {
24034
+ const rects = ranges.map((range) => {
23854
24035
  const layer = groupedByLayer.get(`${range.rect.y}:${range.rect.height}`) ?? [];
23855
24036
  const minX = Math.min(...layer.map((item) => item.rect.x));
23856
24037
  const maxX = Math.max(
@@ -23862,6 +24043,172 @@ function resolveRangeHighlightLayouts(params) {
23862
24043
  omitRight: range.rect.x + range.rect.width < maxX
23863
24044
  };
23864
24045
  });
24046
+ return {
24047
+ rects,
24048
+ segments: roundRangeBorderAtTableBottom(
24049
+ resolveRangeBorderSegments(selected, params.resolveClipRect),
24050
+ params.width,
24051
+ params.height
24052
+ )
24053
+ };
24054
+ }
24055
+ function roundRangeBorderAtTableBottom(segments, width, height) {
24056
+ const inset = 0.5;
24057
+ const left = inset;
24058
+ const right = width - inset;
24059
+ const bottom = height - inset;
24060
+ const radius = Math.max(
24061
+ TABLE_CONTENT_BORDER_RADIUS - TABLE_CONTENT_BORDER_SIZE / 2,
24062
+ 0
24063
+ );
24064
+ if (radius <= 0) return segments;
24065
+ const rounded = segments.map((segment) => ({ ...segment }));
24066
+ const curves = [];
24067
+ const bottomSegments = rounded.filter(
24068
+ (segment) => nearlyEqual(segment.startY, bottom) && nearlyEqual(segment.endY, bottom)
24069
+ );
24070
+ const leftBottom = bottomSegments.find(
24071
+ (segment) => nearlyEqual(segment.startX, left)
24072
+ );
24073
+ const leftSide = rounded.find(
24074
+ (segment) => nearlyEqual(segment.startX, left) && nearlyEqual(segment.endX, left) && nearlyEqual(segment.endY, bottom)
24075
+ );
24076
+ if (leftBottom && leftSide) {
24077
+ leftBottom.startX = Math.min(left + radius, leftBottom.endX);
24078
+ leftSide.endY = Math.max(bottom - radius, leftSide.startY);
24079
+ curves.push({
24080
+ startX: leftSide.endX,
24081
+ startY: leftSide.endY,
24082
+ controlX: left,
24083
+ controlY: bottom,
24084
+ endX: leftBottom.startX,
24085
+ endY: leftBottom.startY,
24086
+ clipRect: leftSide.clipRect
24087
+ });
24088
+ }
24089
+ const rightBottom = bottomSegments.find(
24090
+ (segment) => nearlyEqual(segment.endX, right)
24091
+ );
24092
+ const rightSide = rounded.find(
24093
+ (segment) => nearlyEqual(segment.startX, right) && nearlyEqual(segment.endX, right) && nearlyEqual(segment.endY, bottom)
24094
+ );
24095
+ if (rightBottom && rightSide) {
24096
+ rightBottom.endX = Math.max(right - radius, rightBottom.startX);
24097
+ rightSide.endY = Math.max(bottom - radius, rightSide.startY);
24098
+ curves.push({
24099
+ startX: rightBottom.endX,
24100
+ startY: rightBottom.endY,
24101
+ controlX: right,
24102
+ controlY: bottom,
24103
+ endX: rightSide.endX,
24104
+ endY: rightSide.endY,
24105
+ clipRect: rightSide.clipRect
24106
+ });
24107
+ }
24108
+ return [...rounded, ...curves];
24109
+ }
24110
+ function nearlyEqual(left, right) {
24111
+ return Math.abs(left - right) < 1e-3;
24112
+ }
24113
+ function resolveRangeBorderSegments(descriptors, resolveClipRect) {
24114
+ const byLeft = groupDescriptorsByCoordinate(
24115
+ descriptors,
24116
+ (descriptor) => descriptor.rect.x
24117
+ );
24118
+ const byRight = groupDescriptorsByCoordinate(
24119
+ descriptors,
24120
+ (descriptor) => descriptor.rect.x + descriptor.rect.width
24121
+ );
24122
+ const byTop = groupDescriptorsByCoordinate(
24123
+ descriptors,
24124
+ (descriptor) => descriptor.rect.y
24125
+ );
24126
+ const byBottom = groupDescriptorsByCoordinate(
24127
+ descriptors,
24128
+ (descriptor) => descriptor.rect.y + descriptor.rect.height
24129
+ );
24130
+ return descriptors.flatMap((descriptor) => {
24131
+ const { rect } = descriptor;
24132
+ const left = rect.x;
24133
+ const right = rect.x + rect.width;
24134
+ const top = rect.y;
24135
+ const bottom = rect.y + rect.height;
24136
+ const clipRect = resolveClipRect(descriptor);
24137
+ const horizontal = (y, side) => {
24138
+ const adjacent = (side === "top" ? byBottom : byTop).get(
24139
+ coordinateKey(side === "top" ? top : bottom)
24140
+ ) ?? [];
24141
+ return subtractCoveredIntervals(
24142
+ left,
24143
+ right,
24144
+ adjacent.flatMap((other) => {
24145
+ if (other === descriptor) return [];
24146
+ return [[other.rect.x, other.rect.x + other.rect.width]];
24147
+ })
24148
+ ).map(([start, end]) => ({
24149
+ startX: start + (Math.abs(start - left) < 1e-3 ? 0.5 : 0),
24150
+ startY: y,
24151
+ endX: end - (Math.abs(end - right) < 1e-3 ? 0.5 : 0),
24152
+ endY: y,
24153
+ clipRect
24154
+ }));
24155
+ };
24156
+ const vertical = (x, side) => {
24157
+ const adjacent = (side === "left" ? byRight : byLeft).get(
24158
+ coordinateKey(side === "left" ? left : right)
24159
+ ) ?? [];
24160
+ return subtractCoveredIntervals(
24161
+ top,
24162
+ bottom,
24163
+ adjacent.flatMap((other) => {
24164
+ if (other === descriptor) return [];
24165
+ return [[other.rect.y, other.rect.y + other.rect.height]];
24166
+ })
24167
+ ).map(([start, end]) => ({
24168
+ startX: x,
24169
+ startY: start + (Math.abs(start - top) < 1e-3 ? 0.5 : 0),
24170
+ endX: x,
24171
+ endY: end - (Math.abs(end - bottom) < 1e-3 ? 0.5 : 0),
24172
+ clipRect
24173
+ }));
24174
+ };
24175
+ return [
24176
+ ...horizontal(top + 0.5, "top"),
24177
+ ...horizontal(bottom - 0.5, "bottom"),
24178
+ ...vertical(left + 0.5, "left"),
24179
+ ...vertical(right - 0.5, "right")
24180
+ ];
24181
+ });
24182
+ }
24183
+ function groupDescriptorsByCoordinate(descriptors, getCoordinate) {
24184
+ const groups = /* @__PURE__ */ new Map();
24185
+ descriptors.forEach((descriptor) => {
24186
+ const key = coordinateKey(getCoordinate(descriptor));
24187
+ const group = groups.get(key) ?? [];
24188
+ group.push(descriptor);
24189
+ groups.set(key, group);
24190
+ });
24191
+ return groups;
24192
+ }
24193
+ function coordinateKey(value) {
24194
+ return String(Math.round(value * 1e3) / 1e3);
24195
+ }
24196
+ function subtractCoveredIntervals(start, end, coveredIntervals) {
24197
+ let visible = [[start, end]];
24198
+ coveredIntervals.forEach(([coveredStart, coveredEnd]) => {
24199
+ visible = visible.flatMap(([currentStart, currentEnd]) => {
24200
+ const overlapStart = Math.max(currentStart, coveredStart);
24201
+ const overlapEnd = Math.min(currentEnd, coveredEnd);
24202
+ if (overlapEnd <= overlapStart) return [[currentStart, currentEnd]];
24203
+ const next = [];
24204
+ if (overlapStart > currentStart) next.push([currentStart, overlapStart]);
24205
+ if (overlapEnd < currentEnd) next.push([overlapEnd, currentEnd]);
24206
+ return next;
24207
+ });
24208
+ });
24209
+ return visible.filter(
24210
+ ([currentStart, currentEnd]) => currentEnd > currentStart
24211
+ );
23865
24212
  }
23866
24213
  function drawRangeHighlightBorder(ctx, rect, edges = {}) {
23867
24214
  ctx.save();
@@ -24124,6 +24471,7 @@ function executeListTableRenderPipeline(params) {
24124
24471
  descriptors,
24125
24472
  selection,
24126
24473
  width,
24474
+ height,
24127
24475
  headerHeight,
24128
24476
  topFrozenHeight,
24129
24477
  scrollBodyTop,
@@ -24151,7 +24499,14 @@ function executeListTableRenderPipeline(params) {
24151
24499
  descriptors,
24152
24500
  theme.borderColor,
24153
24501
  scrollbarOpacity,
24154
- isScrollbarInteractive
24502
+ isScrollbarInteractive,
24503
+ {
24504
+ top: 0,
24505
+ height,
24506
+ headerBottom: headerHeight,
24507
+ headerBackgroundColor: theme.headerBackgroundColor,
24508
+ bodyBackgroundColor: theme.backgroundColor
24509
+ }
24155
24510
  );
24156
24511
  if (headerDraggingIndicator) {
24157
24512
  drawDragOverlayFrame({
@@ -25271,7 +25626,7 @@ var ListTableScrollToController = class {
25271
25626
  });
25272
25627
  const targetTop = visibleRowIndex == null ? null : resolveScrollTopForRowIndex({
25273
25628
  rowIndex: visibleRowIndex,
25274
- rowCount: snapshot.visibleRows.length,
25629
+ rowCount: snapshot.frozenRows.scroll.dataRowIndexAligned ? snapshot.dataRowCount : snapshot.visibleRows.length,
25275
25630
  rowHeight: snapshot.rowHeight,
25276
25631
  maxScrollTop: snapshot.viewport.maxScrollTop,
25277
25632
  frozenRows: snapshot.frozenRows
@@ -26618,7 +26973,7 @@ var ListTableCore = class {
26618
26973
  */
26619
26974
  changeDensity(density) {
26620
26975
  this.headerActionController.changeTableDensity(
26621
- density === 32 ? "compact" : density === 56 ? "comfortable" : "middle"
26976
+ density === "auto" ? "auto" : density === 32 ? "compact" : density === 56 ? "comfortable" : "middle"
26622
26977
  );
26623
26978
  }
26624
26979
  /**