@lensui/lens-table 0.1.75 → 0.1.76

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.cjs CHANGED
@@ -335,11 +335,15 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
335
335
  function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
336
336
  const editorRef = (0, import_react2.useRef)(null);
337
337
  const popupRef = (0, import_react2.useRef)(null);
338
+ const activeOptionRef = (0, import_react2.useRef)(null);
338
339
  const originalValueRef = (0, import_react2.useRef)(value);
339
340
  const listboxId = (0, import_react2.useId)();
340
341
  const originalValue = originalValueRef.current;
341
342
  const [inputValue, setInputValue] = (0, import_react2.useState)(value);
342
- const [activeIndex, setActiveIndex] = (0, import_react2.useState)(0);
343
+ const [activeIndex, setActiveIndex] = (0, import_react2.useState)(() => {
344
+ const selectedIndex = options.findIndex((option) => option.value === value);
345
+ return selectedIndex >= 0 ? selectedIndex : 0;
346
+ });
343
347
  const [popupStyle, setPopupStyle] = (0, import_react2.useState)({});
344
348
  const filteredOptions = (0, import_react2.useMemo)(() => {
345
349
  const query = inputValue.trim().toLocaleLowerCase();
@@ -378,6 +382,9 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
378
382
  window.removeEventListener("scroll", positionPopup, true);
379
383
  };
380
384
  }, [maxDropdownHeight]);
385
+ (0, import_react2.useLayoutEffect)(() => {
386
+ activeOptionRef.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
387
+ }, [activeIndex, filteredOptions, popupStyle]);
381
388
  (0, import_react2.useEffect)(() => {
382
389
  const handleOutsidePointer = (event) => {
383
390
  const target = event.target;
@@ -432,6 +439,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
432
439
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: popupRef, id: listboxId, role: "listbox", className: "rvg-choice-content rvg-searchable-choice-content", style: popupStyle, children: filteredOptions.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
433
440
  "button",
434
441
  {
442
+ ref: index === activeIndex ? activeOptionRef : void 0,
435
443
  type: "button",
436
444
  role: "option",
437
445
  "aria-selected": option.value === originalValue,
@@ -1106,6 +1114,7 @@ function paintGrid(options) {
1106
1114
  const headerLeafTop = options.headerLeafTop ?? 0;
1107
1115
  const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
1108
1116
  const colors = { ...COLORS, ...options.colors };
1117
+ const resolveColor = options.resolveColor ?? ((color) => color);
1109
1118
  const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
1110
1119
  const bodyTop = options.bodyTop ?? headerHeight;
1111
1120
  const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
@@ -1169,8 +1178,9 @@ function paintGrid(options) {
1169
1178
  const trailingRowStyle = options.rowStyle?.(row, rowIndex);
1170
1179
  const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
1171
1180
  const paintTrailingLayer = (fill) => {
1172
- if (!fill) return;
1173
- ctx.fillStyle = fill;
1181
+ const resolvedFill = resolveColor(fill);
1182
+ if (!resolvedFill) return;
1183
+ ctx.fillStyle = resolvedFill;
1174
1184
  ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
1175
1185
  };
1176
1186
  if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
@@ -1213,8 +1223,11 @@ function paintGrid(options) {
1213
1223
  ctx.fillRect(x, y, cellWidth, cellHeight);
1214
1224
  }
1215
1225
  if (rowStyle?.backgroundColor) {
1216
- ctx.fillStyle = rowStyle.backgroundColor;
1217
- ctx.fillRect(x, y, cellWidth, cellHeight);
1226
+ const rowBackground = resolveColor(rowStyle.backgroundColor);
1227
+ if (rowBackground) {
1228
+ ctx.fillStyle = rowBackground;
1229
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1230
+ }
1218
1231
  }
1219
1232
  if (isAxisSelected) {
1220
1233
  ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
@@ -1233,8 +1246,11 @@ function paintGrid(options) {
1233
1246
  const rawValue = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
1234
1247
  const cellStyle = column.cellStyle?.(rawValue, row, rowIndex);
1235
1248
  if (!isSelectedCell && !isRangeCell && cellStyle?.backgroundColor) {
1236
- ctx.fillStyle = cellStyle.backgroundColor;
1237
- ctx.fillRect(x, y, cellWidth, cellHeight);
1249
+ const cellBackground = resolveColor(cellStyle.backgroundColor);
1250
+ if (cellBackground) {
1251
+ ctx.fillStyle = cellBackground;
1252
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1253
+ }
1238
1254
  }
1239
1255
  if (highlightEditedCells && !insertedRowKeys.has(rowKey) && !isSelectedCell && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`)) {
1240
1256
  ctx.fillStyle = colors.editedFill;
@@ -1245,8 +1261,11 @@ function paintGrid(options) {
1245
1261
  ctx.fillRect(x, y, cellWidth, cellHeight);
1246
1262
  }
1247
1263
  if (annotation?.type === "background") {
1248
- ctx.fillStyle = annotation.color;
1249
- ctx.fillRect(x, y, cellWidth, cellHeight);
1264
+ const annotationBackground = resolveColor(annotation.color);
1265
+ if (annotationBackground) {
1266
+ ctx.fillStyle = annotationBackground;
1267
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1268
+ }
1250
1269
  }
1251
1270
  if (isColumnDropTarget) {
1252
1271
  ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
@@ -1262,14 +1281,14 @@ function paintGrid(options) {
1262
1281
  }
1263
1282
  if (rowSpan > 1) {
1264
1283
  const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1265
- ctx.fillStyle = mergedFill;
1284
+ ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
1266
1285
  for (let offset = 1; offset < rowSpan; offset += 1) {
1267
1286
  ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
1268
1287
  }
1269
1288
  }
1270
1289
  if (colSpan > 1 && !verticalBorderless) {
1271
1290
  const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1272
- ctx.fillStyle = mergedFill;
1291
+ ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
1273
1292
  let offsetLeft = 0;
1274
1293
  for (let offset = 1; offset < colSpan; offset += 1) {
1275
1294
  offsetLeft += metrics[columnIndex + offset - 1]?.width ?? 0;
@@ -1365,7 +1384,8 @@ function paintGrid(options) {
1365
1384
  ctx.beginPath();
1366
1385
  ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
1367
1386
  ctx.clip();
1368
- ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : cellStyle?.color ?? rowStyle?.color ?? colors.text;
1387
+ const textColor = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : resolveColor(cellStyle?.color ?? rowStyle?.color) ?? colors.text;
1388
+ ctx.fillStyle = textColor;
1369
1389
  ctx.font = createCellFont(bodyFontSize);
1370
1390
  ctx.textBaseline = "alphabetic";
1371
1391
  ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
@@ -1375,7 +1395,7 @@ function paintGrid(options) {
1375
1395
  }
1376
1396
  if (annotation?.type === "corner") {
1377
1397
  const cornerTop = y - 1;
1378
- ctx.fillStyle = annotation.color;
1398
+ ctx.fillStyle = resolveColor(annotation.color) ?? colors.text;
1379
1399
  ctx.beginPath();
1380
1400
  ctx.moveTo(x + cellWidth - 10, cornerTop);
1381
1401
  ctx.lineTo(x + cellWidth, cornerTop);
@@ -1761,6 +1781,18 @@ function readThemePixel(styles, name, fallback) {
1761
1781
  const value = Number.parseFloat(styles.getPropertyValue(name));
1762
1782
  return Number.isFinite(value) && value > 0 ? value : fallback;
1763
1783
  }
1784
+ function resolveCanvasColor(styles, color) {
1785
+ if (!color) return void 0;
1786
+ let resolved = color.trim();
1787
+ for (let depth = 0; depth < 8; depth += 1) {
1788
+ const variable = resolved.match(/^var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)$/);
1789
+ if (!variable) return resolved || void 0;
1790
+ const value = styles.getPropertyValue(variable[1]).trim();
1791
+ resolved = value || variable[2]?.trim() || "";
1792
+ if (!resolved) return void 0;
1793
+ }
1794
+ return void 0;
1795
+ }
1764
1796
  function getDefaultRowKey(row, index) {
1765
1797
  const id = row.id;
1766
1798
  return typeof id === "string" || typeof id === "number" ? id : index;
@@ -2582,7 +2614,7 @@ function TableInner({
2582
2614
  const scroll = scrollRef.current;
2583
2615
  const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
2584
2616
  const range = isVirtualized ? getViewportRange(scroll.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan) : { rowStart: 0, rowEnd: rows.length, columnStart: 0, columnEnd: columns.length };
2585
- paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, colors: themeColors });
2617
+ paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, resolveColor: (color) => resolveCanvasColor(themeStyles, color), colors: themeColors });
2586
2618
  }, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDragPreview, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, frameBorderless, getRowKey, hasStripedRows, hasVerticalBorders, headerActionSlotWidth, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rowStyle, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
2587
2619
  const scheduleDraw = (0, import_react8.useCallback)(() => {
2588
2620
  if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
package/dist/index.js CHANGED
@@ -305,11 +305,15 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
305
305
  function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownHeight, style, labels, onChange, onCommit, onCancel }) {
306
306
  const editorRef = useRef(null);
307
307
  const popupRef = useRef(null);
308
+ const activeOptionRef = useRef(null);
308
309
  const originalValueRef = useRef(value);
309
310
  const listboxId = useId2();
310
311
  const originalValue = originalValueRef.current;
311
312
  const [inputValue, setInputValue] = useState(value);
312
- const [activeIndex, setActiveIndex] = useState(0);
313
+ const [activeIndex, setActiveIndex] = useState(() => {
314
+ const selectedIndex = options.findIndex((option) => option.value === value);
315
+ return selectedIndex >= 0 ? selectedIndex : 0;
316
+ });
313
317
  const [popupStyle, setPopupStyle] = useState({});
314
318
  const filteredOptions = useMemo(() => {
315
319
  const query = inputValue.trim().toLocaleLowerCase();
@@ -348,6 +352,9 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
348
352
  window.removeEventListener("scroll", positionPopup, true);
349
353
  };
350
354
  }, [maxDropdownHeight]);
355
+ useLayoutEffect(() => {
356
+ activeOptionRef.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
357
+ }, [activeIndex, filteredOptions, popupStyle]);
351
358
  useEffect(() => {
352
359
  const handleOutsidePointer = (event) => {
353
360
  const target = event.target;
@@ -402,6 +409,7 @@ function SearchableChoiceEditor({ value, options, allowCustomValue, maxDropdownH
402
409
  /* @__PURE__ */ jsx3(Portal, { children: /* @__PURE__ */ jsx3("div", { ref: popupRef, id: listboxId, role: "listbox", className: "rvg-choice-content rvg-searchable-choice-content", style: popupStyle, children: filteredOptions.map((option, index) => /* @__PURE__ */ jsxs3(
403
410
  "button",
404
411
  {
412
+ ref: index === activeIndex ? activeOptionRef : void 0,
405
413
  type: "button",
406
414
  role: "option",
407
415
  "aria-selected": option.value === originalValue,
@@ -1076,6 +1084,7 @@ function paintGrid(options) {
1076
1084
  const headerLeafTop = options.headerLeafTop ?? 0;
1077
1085
  const headerLeafHeight = options.headerLeafHeight ?? headerHeight;
1078
1086
  const colors = { ...COLORS, ...options.colors };
1087
+ const resolveColor = options.resolveColor ?? ((color) => color);
1079
1088
  const getAxisSelectionFill = (rowIndex, columnKey) => selectedColumnKeys.has(columnKey) && striped && rowIndex % 2 === 1 ? colors.axisSelectionStripeFill : colors.axisSelectionFill;
1080
1089
  const bodyTop = options.bodyTop ?? headerHeight;
1081
1090
  const getCellSpan = (rowIndex, columnIndex) => options.cellSpans.get(getCellCoordKey(rowIndex, columnIndex));
@@ -1139,8 +1148,9 @@ function paintGrid(options) {
1139
1148
  const trailingRowStyle = options.rowStyle?.(row, rowIndex);
1140
1149
  const y = bodyTop + rowIndex * rowHeight - scrollTop + getRowDragOffset(rowIndex);
1141
1150
  const paintTrailingLayer = (fill) => {
1142
- if (!fill) return;
1143
- ctx.fillStyle = fill;
1151
+ const resolvedFill = resolveColor(fill);
1152
+ if (!resolvedFill) return;
1153
+ ctx.fillStyle = resolvedFill;
1144
1154
  ctx.fillRect(trailingBlankStart, y, width - trailingBlankStart, rowHeight);
1145
1155
  };
1146
1156
  if (striped && rowIndex % 2 === 1) paintTrailingLayer(colors.stripe);
@@ -1183,8 +1193,11 @@ function paintGrid(options) {
1183
1193
  ctx.fillRect(x, y, cellWidth, cellHeight);
1184
1194
  }
1185
1195
  if (rowStyle?.backgroundColor) {
1186
- ctx.fillStyle = rowStyle.backgroundColor;
1187
- ctx.fillRect(x, y, cellWidth, cellHeight);
1196
+ const rowBackground = resolveColor(rowStyle.backgroundColor);
1197
+ if (rowBackground) {
1198
+ ctx.fillStyle = rowBackground;
1199
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1200
+ }
1188
1201
  }
1189
1202
  if (isAxisSelected) {
1190
1203
  ctx.fillStyle = getAxisSelectionFill(rowIndex, column.key);
@@ -1203,8 +1216,11 @@ function paintGrid(options) {
1203
1216
  const rawValue = column.dataIndex === void 0 ? void 0 : row[column.dataIndex];
1204
1217
  const cellStyle = column.cellStyle?.(rawValue, row, rowIndex);
1205
1218
  if (!isSelectedCell && !isRangeCell && cellStyle?.backgroundColor) {
1206
- ctx.fillStyle = cellStyle.backgroundColor;
1207
- ctx.fillRect(x, y, cellWidth, cellHeight);
1219
+ const cellBackground = resolveColor(cellStyle.backgroundColor);
1220
+ if (cellBackground) {
1221
+ ctx.fillStyle = cellBackground;
1222
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1223
+ }
1208
1224
  }
1209
1225
  if (highlightEditedCells && !insertedRowKeys.has(rowKey) && !isSelectedCell && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`)) {
1210
1226
  ctx.fillStyle = colors.editedFill;
@@ -1215,8 +1231,11 @@ function paintGrid(options) {
1215
1231
  ctx.fillRect(x, y, cellWidth, cellHeight);
1216
1232
  }
1217
1233
  if (annotation?.type === "background") {
1218
- ctx.fillStyle = annotation.color;
1219
- ctx.fillRect(x, y, cellWidth, cellHeight);
1234
+ const annotationBackground = resolveColor(annotation.color);
1235
+ if (annotationBackground) {
1236
+ ctx.fillStyle = annotationBackground;
1237
+ ctx.fillRect(x, y, cellWidth, cellHeight);
1238
+ }
1220
1239
  }
1221
1240
  if (isColumnDropTarget) {
1222
1241
  ctx.fillStyle = isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill;
@@ -1232,14 +1251,14 @@ function paintGrid(options) {
1232
1251
  }
1233
1252
  if (rowSpan > 1) {
1234
1253
  const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1235
- ctx.fillStyle = mergedFill;
1254
+ ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
1236
1255
  for (let offset = 1; offset < rowSpan; offset += 1) {
1237
1256
  ctx.fillRect(x, y + offset * rowHeight - 1, cellWidth, 2);
1238
1257
  }
1239
1258
  }
1240
1259
  if (colSpan > 1 && !verticalBorderless) {
1241
1260
  const mergedFill = isColumnDropTarget ? isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : colors.columnDropTargetFill : annotation?.type === "background" ? annotation.color : isSelectedCell || isRangeCell ? colors.selectionFill : highlightEditedCells && !insertedRowKeys.has(rowKey) && editedCellKeys.has(`${typeof rowKey}:${String(rowKey)}\0${column.key}`) ? colors.editedFill : highlightInsertedRows && insertedRowKeys.has(rowKey) ? colors.insertedFill : hoveredRowIndex === rowIndex ? colors.rowHoverFill : isAxisSelected ? getAxisSelectionFill(rowIndex, column.key) : cellStyle?.backgroundColor ?? rowStyle?.backgroundColor ?? (striped && rowIndex % 2 === 1 ? colors.stripe : colors.background);
1242
- ctx.fillStyle = mergedFill;
1261
+ ctx.fillStyle = resolveColor(mergedFill) ?? colors.background;
1243
1262
  let offsetLeft = 0;
1244
1263
  for (let offset = 1; offset < colSpan; offset += 1) {
1245
1264
  offsetLeft += metrics[columnIndex + offset - 1]?.width ?? 0;
@@ -1335,7 +1354,8 @@ function paintGrid(options) {
1335
1354
  ctx.beginPath();
1336
1355
  ctx.rect(x + 2, y + 1, Math.max(0, cellWidth - 4), cellHeight - 2);
1337
1356
  ctx.clip();
1338
- ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : cellStyle?.color ?? rowStyle?.color ?? colors.text;
1357
+ const textColor = isAxisSelected ? colors.axisSelectionText : isColumnDropTarget ? colors.text : resolveColor(cellStyle?.color ?? rowStyle?.color) ?? colors.text;
1358
+ ctx.fillStyle = textColor;
1339
1359
  ctx.font = createCellFont(bodyFontSize);
1340
1360
  ctx.textBaseline = "alphabetic";
1341
1361
  ctx.textAlign = column.align === "right" ? "right" : column.align === "center" ? "center" : "left";
@@ -1345,7 +1365,7 @@ function paintGrid(options) {
1345
1365
  }
1346
1366
  if (annotation?.type === "corner") {
1347
1367
  const cornerTop = y - 1;
1348
- ctx.fillStyle = annotation.color;
1368
+ ctx.fillStyle = resolveColor(annotation.color) ?? colors.text;
1349
1369
  ctx.beginPath();
1350
1370
  ctx.moveTo(x + cellWidth - 10, cornerTop);
1351
1371
  ctx.lineTo(x + cellWidth, cornerTop);
@@ -1731,6 +1751,18 @@ function readThemePixel(styles, name, fallback) {
1731
1751
  const value = Number.parseFloat(styles.getPropertyValue(name));
1732
1752
  return Number.isFinite(value) && value > 0 ? value : fallback;
1733
1753
  }
1754
+ function resolveCanvasColor(styles, color) {
1755
+ if (!color) return void 0;
1756
+ let resolved = color.trim();
1757
+ for (let depth = 0; depth < 8; depth += 1) {
1758
+ const variable = resolved.match(/^var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)$/);
1759
+ if (!variable) return resolved || void 0;
1760
+ const value = styles.getPropertyValue(variable[1]).trim();
1761
+ resolved = value || variable[2]?.trim() || "";
1762
+ if (!resolved) return void 0;
1763
+ }
1764
+ return void 0;
1765
+ }
1734
1766
  function getDefaultRowKey(row, index) {
1735
1767
  const id = row.id;
1736
1768
  return typeof id === "string" || typeof id === "number" ? id : index;
@@ -2552,7 +2584,7 @@ function TableInner({
2552
2584
  const scroll = scrollRef.current;
2553
2585
  const rowScrollTop = fixedHeader ? scroll.top : Math.max(0, scroll.top - bodyTop);
2554
2586
  const range = isVirtualized ? getViewportRange(scroll.left, rowScrollTop, viewport.width, bodyViewportHeight, rows.length, rowHeight, metrics, virtualOverscan) : { rowStart: 0, rowEnd: rows.length, columnStart: 0, columnEnd: columns.length };
2555
- paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, colors: themeColors });
2587
+ paintGrid({ context, width: viewport.width, height: renderHeight, pixelRatio: ratio, scrollLeft: scroll.left, scrollTop: scroll.top, rowHeight, bodyFontSize, headerActionSlotWidth, headerHeight, headerLeafTop, headerLeafHeight, bodyTop, suppressLastRowBottomBorder: bottomSummaryHeight > 0, suppressFrameBottomBorder: bottomSummaryHeight > 0, fixedHeader, verticalBorderless: !hasVerticalBorders, horizontalBorderless, frameBorderless, extendVerticalGridLines: !autoHeight, striped: hasStripedRows, columnDraggable, sortState, filterValues, hoveredHeaderAction: hoveredHeaderActionRef.current, rows, rowStyle, columns, metrics, range, selection, editing, hoveredRowIndex: hoveredRowIndexRef.current, selectionRange, selectedRowKeys: selectedRowKeySet, rowSelectionMode, selectedColumnKeys: selectedColumnKeySet, cellSpans: cellSpanLookup.covered, maxRowSpan: cellSpanLookup.maxRowSpan, highlightEditedCells: highlightsEditedCells, highlightInsertedRows: highlightsInsertedRows, insertedRowKeys: insertedRowKeySet, editedCellKeys, cellAnnotations, getRowKey, rowDragPreview, columnDropTarget, resolveColor: (color) => resolveCanvasColor(themeStyles, color), colors: themeColors });
2556
2588
  }, [autoHeight, bodyTop, bodyViewportHeight, bottomSummaryHeight, cellAnnotations, cellSpanLookup, columnDragPreview, columnDraggable, columnDropTarget, columns, editedCellHighlightColor, editedCellKeys, editing, renderHeight, filterValues, fixedHeader, frameBorderless, getRowKey, hasStripedRows, hasVerticalBorders, headerActionSlotWidth, headerDepth, headerHeight, headerLeafHeight, headerLeafTop, horizontalBorderless, highlightsEditedCells, highlightsInsertedRows, insertedRowHighlightColor, insertedRowKeySet, isVirtualized, metrics, rowDragPreview, rowHeight, rowSelectionMode, rowStyle, rows, selectedColumnKeySet, selectedRowKeySet, selection, selectionRange, sortState, stripedColor, viewport.width, virtualOverscan]);
2557
2589
  const scheduleDraw = useCallback2(() => {
2558
2590
  if (frameRef.current === null) frameRef.current = requestAnimationFrame(draw);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.75",
3
+ "version": "0.1.76",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",