@ricsam/react-spreadsheets 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/react-spreadsheets",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/lib.mjs CHANGED
@@ -8,6 +8,8 @@ import React2, {
8
8
  useCallback as useCallback3,
9
9
  useEffect as useEffect3,
10
10
  useImperativeHandle,
11
+ useId,
12
+ useLayoutEffect,
11
13
  useMemo,
12
14
  useRef as useRef3,
13
15
  useState as useState4
@@ -1472,6 +1474,7 @@ var CellComponent = React2.memo(({
1472
1474
  value,
1473
1475
  row,
1474
1476
  col,
1477
+ domId,
1475
1478
  selectionManager,
1476
1479
  cellToPixelBase,
1477
1480
  getColumnWidth,
@@ -1485,11 +1488,11 @@ var CellComponent = React2.memo(({
1485
1488
  }) => {
1486
1489
  const cellRef = useCallback3((el) => {
1487
1490
  if (el) {
1488
- const rowIndex2 = row - 1;
1489
- const colIndex2 = columnToIndex(col);
1491
+ const rowIndex = row - 1;
1492
+ const colIndex = columnToIndex(col);
1490
1493
  return selectionManager.setupCellElement(el, {
1491
- row: rowIndex2,
1492
- col: colIndex2
1494
+ row: rowIndex,
1495
+ col: colIndex
1493
1496
  });
1494
1497
  }
1495
1498
  }, [row, col, selectionManager]);
@@ -1517,16 +1520,22 @@ var CellComponent = React2.memo(({
1517
1520
  });
1518
1521
  const inputRef = useCallback3((el) => {
1519
1522
  if (el) {
1520
- const rowIndex2 = row - 1;
1521
- const colIndex2 = columnToIndex(col);
1523
+ const rowIndex = row - 1;
1524
+ const colIndex = columnToIndex(col);
1522
1525
  return selectionManager.setupInputElement(el, {
1523
- rowIndex: rowIndex2,
1524
- colIndex: colIndex2
1526
+ rowIndex,
1527
+ colIndex
1525
1528
  });
1526
1529
  }
1527
1530
  }, [row, col, selectionManager]);
1528
1531
  return /* @__PURE__ */ jsxs2("div", {
1529
1532
  ref: cellRef,
1533
+ id: domId,
1534
+ role: "gridcell",
1535
+ "aria-rowindex": row + 1,
1536
+ "aria-colindex": colIndex + 2,
1537
+ "aria-selected": isSelected,
1538
+ "data-cell-address": `${col}${row}`,
1530
1539
  className: cn("rsp-cell", {
1531
1540
  "rsp-cell-multiline": typeof value === "string" && value.includes(`
1532
1541
  `),
@@ -1546,6 +1555,7 @@ var CellComponent = React2.memo(({
1546
1555
  children: [
1547
1556
  isBeingEdited ? /* @__PURE__ */ jsx3("textarea", {
1548
1557
  className: "rsp-cell-editor",
1558
+ "aria-label": `Edit ${col}${row}`,
1549
1559
  "data-testid": `spreadsheet-cell-input-${col}${row}`,
1550
1560
  ref: inputRef,
1551
1561
  defaultValue: inputValue?.toString() ?? "",
@@ -1624,6 +1634,10 @@ var HeaderComponent = React2.memo(({
1624
1634
  const content = type === "col" ? reverseHeaders ? index + 1 : indexToColumn(index) : reverseHeaders ? rowToLetter(index + 1) : index + 1;
1625
1635
  return /* @__PURE__ */ jsxs2("div", {
1626
1636
  ref: headerRef,
1637
+ role: type === "col" ? "columnheader" : "rowheader",
1638
+ "aria-colindex": type === "col" ? index + 2 : 1,
1639
+ "aria-rowindex": type === "row" ? index + 2 : 1,
1640
+ "aria-selected": isSelected,
1627
1641
  className: cn("rsp-header", `rsp-header-${type}`, {
1628
1642
  "rsp-header-selected": isSelected
1629
1643
  }),
@@ -1768,6 +1782,9 @@ var Spreadsheet = forwardRef(({
1768
1782
  style,
1769
1783
  className,
1770
1784
  containerProps,
1785
+ "aria-label": ariaLabel = "Spreadsheet",
1786
+ "aria-labelledby": ariaLabelledBy,
1787
+ "aria-describedby": ariaDescribedBy,
1771
1788
  cellData: controlledCellData,
1772
1789
  onCellDataChange,
1773
1790
  onCellDataChangeError,
@@ -1790,6 +1807,7 @@ var Spreadsheet = forwardRef(({
1790
1807
  parentSelected = true,
1791
1808
  disableClipboard = false
1792
1809
  }, ref) => {
1810
+ const gridId = useId();
1793
1811
  const [{ width, height }, containerRef] = useResizeObserver();
1794
1812
  const [containerDivRef, setContainerDivRef] = useState4(null);
1795
1813
  const colorScheme = useColorScheme(containerDivRef);
@@ -1983,15 +2001,15 @@ var Spreadsheet = forwardRef(({
1983
2001
  };
1984
2002
  const effectsRef = useRef3(effectsRefOb);
1985
2003
  effectsRef.current = effectsRefOb;
1986
- const setupCanvas = useCallback3((canvas, width2, height2) => {
2004
+ const setupCanvas = useCallback3((canvas, width, height) => {
1987
2005
  const ctx = canvas.getContext("2d");
1988
2006
  if (!ctx)
1989
2007
  return null;
1990
2008
  const devicePixelRatio = window.devicePixelRatio || 1;
1991
- canvas.width = width2 * devicePixelRatio;
1992
- canvas.height = height2 * devicePixelRatio;
1993
- canvas.style.width = width2 + "px";
1994
- canvas.style.height = height2 + "px";
2009
+ canvas.width = width * devicePixelRatio;
2010
+ canvas.height = height * devicePixelRatio;
2011
+ canvas.style.width = width + "px";
2012
+ canvas.style.height = height + "px";
1995
2013
  ctx.scale(devicePixelRatio, devicePixelRatio);
1996
2014
  return ctx;
1997
2015
  }, []);
@@ -2219,36 +2237,36 @@ var Spreadsheet = forwardRef(({
2219
2237
  return selectionManager.listenToUpdateData((updates) => {
2220
2238
  const editingState = selectionManager.isEditing;
2221
2239
  try {
2222
- const { cellData: cellData2, onCellDataChange: onCellDataChange2 } = effectsRef.current;
2223
- const newData = new Map(cellData2);
2240
+ const { cellData, onCellDataChange } = effectsRef.current;
2241
+ const newData = new Map(cellData);
2224
2242
  updates.forEach(({ value, rowIndex, colIndex }) => {
2225
2243
  const key = `${indexToColumn(colIndex)}${rowIndex + 1}`;
2226
- const parseValue2 = effectsRef.current.parseValue;
2244
+ const parseValue = effectsRef.current.parseValue;
2227
2245
  if (value === "") {
2228
2246
  newData.delete(key);
2229
2247
  } else {
2230
2248
  let parsedValue = value;
2231
- if (parseValue2 && typeof value === "string") {
2249
+ if (parseValue && typeof value === "string") {
2232
2250
  const match = key.match(/^([A-Z]+)(\d+)$/);
2233
2251
  const col = match?.[1];
2234
2252
  const rowText = match?.[2];
2235
2253
  if (col && rowText) {
2236
2254
  const row = parseInt(rowText, 10);
2237
- const colIndex2 = columnToIndex(col);
2238
- const rowIndex2 = row - 1;
2239
- parsedValue = parseValue2(value, {
2255
+ const colIndex = columnToIndex(col);
2256
+ const rowIndex = row - 1;
2257
+ parsedValue = parseValue(value, {
2240
2258
  id: key,
2241
2259
  row,
2242
2260
  col,
2243
- rowIndex: rowIndex2,
2244
- colIndex: colIndex2
2261
+ rowIndex,
2262
+ colIndex
2245
2263
  });
2246
2264
  }
2247
2265
  }
2248
2266
  newData.set(key, parsedValue);
2249
2267
  }
2250
2268
  });
2251
- onCellDataChange2?.(newData);
2269
+ onCellDataChange?.(newData);
2252
2270
  setInternalCellData(newData);
2253
2271
  } catch (error) {
2254
2272
  console.error("Failed to update spreadsheet cell data:", error);
@@ -2431,13 +2449,13 @@ var Spreadsheet = forwardRef(({
2431
2449
  const handleColumnResizeDoubleClick = useCallback3((e, col) => {
2432
2450
  e.preventDefault();
2433
2451
  e.stopPropagation();
2434
- const { viewport: viewport2, gridDims: gridDims2, height: height2, cellData: cellData2 } = effectsRef.current;
2452
+ const { viewport, gridDims, height, cellData } = effectsRef.current;
2435
2453
  let maxWidth = 50;
2436
- const startRow = Math.max(0, Math.floor(viewport2.scrollY / gridDims2.cellHeight));
2437
- const endRow = Math.ceil((viewport2.scrollY + height2) / gridDims2.cellHeight) + 1;
2454
+ const startRow = Math.max(0, Math.floor(viewport.scrollY / gridDims.cellHeight));
2455
+ const endRow = Math.ceil((viewport.scrollY + height) / gridDims.cellHeight) + 1;
2438
2456
  for (let row = startRow;row <= endRow; row++) {
2439
2457
  const cellKey = `${col}${getRowNumber(row)}`;
2440
- const content = cellData2.get(cellKey) ?? "";
2458
+ const content = cellData.get(cellKey) ?? "";
2441
2459
  if (content) {
2442
2460
  const estimatedWidth = String(content).length * 8 + 20;
2443
2461
  maxWidth = Math.max(maxWidth, estimatedWidth);
@@ -2706,8 +2724,8 @@ var Spreadsheet = forwardRef(({
2706
2724
  return editingCleanup;
2707
2725
  }, [selectionManager]);
2708
2726
  React2.useEffect(() => {
2709
- return selectionManager.observeStateChange((state) => state.hasFocus, (hasFocus2) => {
2710
- if (hasFocus2 && selectedOverlayId) {
2727
+ return selectionManager.observeStateChange((state) => state.hasFocus, (hasFocus) => {
2728
+ if (hasFocus && selectedOverlayId) {
2711
2729
  setSelectedOverlay(null);
2712
2730
  }
2713
2731
  });
@@ -2810,6 +2828,21 @@ var Spreadsheet = forwardRef(({
2810
2828
  const visibleCells = React2.useMemo(() => getVisibleCells(), [getVisibleCells]);
2811
2829
  const visibleColumnHeaders = React2.useMemo(() => getVisibleColumnHeaders(), [getVisibleColumnHeaders]);
2812
2830
  const visibleRowHeaders = React2.useMemo(() => getVisibleRowHeaders(), [getVisibleRowHeaders]);
2831
+ const activeAddress = useSelectionManager(selectionManager, () => {
2832
+ const cell = selectionManager.getTopLeftCellInSelection();
2833
+ return cell ? `${indexToColumn(cell.col)}${cell.row + 1}` : undefined;
2834
+ });
2835
+ const activeCellId = visibleCells.some((cell) => `${cell.col}${cell.row}` === activeAddress) ? `${gridId}-cell-${activeAddress}` : undefined;
2836
+ const accessibilityManager = selectionManager;
2837
+ useLayoutEffect(() => {
2838
+ accessibilityManager.setInputCaptureAccessibility?.({
2839
+ label: `${ariaLabel} keyboard input`,
2840
+ controls: gridId,
2841
+ activeDescendant: activeCellId,
2842
+ describedBy: ariaDescribedBy
2843
+ });
2844
+ return () => accessibilityManager.setInputCaptureAccessibility?.({});
2845
+ }, [accessibilityManager, ariaLabel, ariaDescribedBy, gridId, activeCellId]);
2813
2846
  const hasFocus = useSelectionManager(selectionManager, () => selectionManager.hasFocus);
2814
2847
  const referenceSelection = useSelectionManager(selectionManager, () => selectionManager.referenceSelection);
2815
2848
  const referenceSelectionRect = useMemo(() => {
@@ -2885,7 +2918,21 @@ var Spreadsheet = forwardRef(({
2885
2918
  width,
2886
2919
  height
2887
2920
  },
2921
+ id: gridId,
2922
+ role: "grid",
2923
+ "aria-activedescendant": activeCellId,
2924
+ "aria-label": ariaLabel,
2925
+ "aria-labelledby": ariaLabelledBy,
2926
+ "aria-describedby": ariaDescribedBy,
2927
+ "aria-rowcount": finiteRowCount === undefined ? -1 : finiteRowCount + 1,
2928
+ "aria-colcount": finiteColumnCount === undefined ? -1 : finiteColumnCount + 1,
2929
+ "aria-multiselectable": "true",
2888
2930
  tabIndex: 0,
2931
+ onFocus: (event) => {
2932
+ if (event.target === event.currentTarget && !selectionManager.hasFocus) {
2933
+ selectionManager.focus();
2934
+ }
2935
+ },
2889
2936
  children: [
2890
2937
  /* @__PURE__ */ jsx3("span", {
2891
2938
  ref: gridLineProbeRef,
@@ -2901,12 +2948,15 @@ var Spreadsheet = forwardRef(({
2901
2948
  }),
2902
2949
  /* @__PURE__ */ jsx3("canvas", {
2903
2950
  ref: canvasRef,
2951
+ "aria-hidden": "true",
2904
2952
  className: "rsp-canvas",
2905
2953
  "data-testid": "spreadsheet-canvas",
2906
2954
  style: { width, height }
2907
2955
  }),
2908
2956
  /* @__PURE__ */ jsx3("div", {
2909
2957
  className: "rsp-column-headers",
2958
+ role: "row",
2959
+ "aria-rowindex": 1,
2910
2960
  "data-testid": "spreadsheet-column-headers",
2911
2961
  style: {
2912
2962
  left: gridDims.headerWidth,
@@ -2949,16 +2999,21 @@ var Spreadsheet = forwardRef(({
2949
2999
  transformOrigin: "0 0"
2950
3000
  },
2951
3001
  children: visibleRowHeaders.map(({ row, rowIndex }) => {
2952
- return /* @__PURE__ */ jsx3(HeaderComponent, {
2953
- index: rowIndex,
2954
- type: "row",
2955
- selectionManager,
2956
- getColumnWidth,
2957
- getRowHeight,
2958
- handleColumnResizeStart,
2959
- handleColumnResizeDoubleClick,
2960
- handleRowResizeStart,
2961
- handleRowResizeDoubleClick
3002
+ return /* @__PURE__ */ jsx3("div", {
3003
+ role: "row",
3004
+ "aria-rowindex": row + 1,
3005
+ "aria-owns": visibleCells.filter((cell) => cell.row === row).map((cell) => `${gridId}-cell-${cell.col}${cell.row}`).join(" ") || undefined,
3006
+ children: /* @__PURE__ */ jsx3(HeaderComponent, {
3007
+ index: rowIndex,
3008
+ type: "row",
3009
+ selectionManager,
3010
+ getColumnWidth,
3011
+ getRowHeight,
3012
+ handleColumnResizeStart,
3013
+ handleColumnResizeDoubleClick,
3014
+ handleRowResizeStart,
3015
+ handleRowResizeDoubleClick
3016
+ })
2962
3017
  }, row);
2963
3018
  })
2964
3019
  })
@@ -2981,6 +3036,7 @@ var Spreadsheet = forwardRef(({
2981
3036
  },
2982
3037
  children: [
2983
3038
  visibleCells.map((cell) => /* @__PURE__ */ jsx3(CellComponent, {
3039
+ domId: `${gridId}-cell-${cell.col}${cell.row}`,
2984
3040
  value: cellData.get(`${cell.col}${cell.row}`) ?? "",
2985
3041
  row: cell.row,
2986
3042
  col: cell.col,
@@ -3815,11 +3871,11 @@ function FormulaSheet({
3815
3871
  });
3816
3872
  }
3817
3873
  }),
3818
- spreadsheetSelectionManager.observeStateChange((state2) => {
3819
- const currentSelection = state2.selections.length === 1 ? state2.selections[0] : undefined;
3874
+ spreadsheetSelectionManager.observeStateChange((state) => {
3875
+ const currentSelection = state.selections.length === 1 ? state.selections[0] : undefined;
3820
3876
  return currentSelection;
3821
- }, (selection2) => {
3822
- setSelectedArea(selection2 ?? null);
3877
+ }, (selection) => {
3878
+ setSelectedArea(selection ?? null);
3823
3879
  })
3824
3880
  ];
3825
3881
  const handleUndoRedoKeyDown = (event) => {
@@ -3935,7 +3991,7 @@ function FormulaSheet({
3935
3991
  workbookName
3936
3992
  });
3937
3993
  if (!tableInfo) {
3938
- const style2 = conditionalStyle ? {
3994
+ const style = conditionalStyle ? {
3939
3995
  ...conditionalStyle.backgroundColor && {
3940
3996
  backgroundColor: conditionalStyle.backgroundColor
3941
3997
  },
@@ -3957,7 +4013,7 @@ function FormulaSheet({
3957
4013
  ...getBorderCellStyle(conditionalStyle),
3958
4014
  ...getWrapCellStyle(conditionalStyle)
3959
4015
  } : {};
3960
- return customCellStyle ? customCellStyle(cell, style2) : style2;
4016
+ return customCellStyle ? customCellStyle(cell, style) : style;
3961
4017
  }
3962
4018
  const isHeaderRow = cell.rowIndex === tableInfo.start.rowIndex;
3963
4019
  const isFirstColumn = cell.colIndex === tableInfo.start.colIndex;
@@ -4507,4 +4563,4 @@ export {
4507
4563
  useResizeObserver
4508
4564
  };
4509
4565
 
4510
- //# debugId=7847981F1291DEF064756E2164756E21
4566
+ //# debugId=FA27216279C90A7964756E2164756E21