@ishibashi0112/spreadsheet-grid 0.32.0 → 0.34.0

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/README.md CHANGED
@@ -26,7 +26,7 @@ A high-performance, virtualized spreadsheet / data grid for **React 19**, writte
26
26
  - Japanese-aware line wrapping — per-column `wordBreak` / `lineBreak`, including `wordBreak: 'auto-phrase'` for phrase-based breaks on Chromium (BudouX). Cross-browser BudouX recipe in the API reference.
27
27
  - External height control via `height` / `maxHeight` (e.g. `height="100%"` to follow the parent's height).
28
28
  - Both **client-side** (`rows`) and **server-side** (`dataSource`, SSRM) row models — server-side includes query forwarding (filter / sort / global filter), soft refresh (`refreshServerSide()`), load-error retry UI, and cell-edit write-back via `dataSource.updateRows` with optimistic updates and automatic rollback on failure.
29
- - Themeable with CSS custom properties (`--ssg-*`, defined at zero specificity so your overrides always win). Base styles are plain unlayered CSS with single-class specificity, so they survive CSS resets such as Tailwind Preflight; a cascade-layers variant (`style.layer.css`) is also shipped. `className` / `classNames` slots are provided.
29
+ - Themeable with CSS custom properties (`--ssg-*`, defined at zero specificity so your overrides always win). Base styles are plain unlayered CSS with single-class specificity, so they survive CSS resets such as Tailwind Preflight; a cascade-layers variant (`style.layer.css`) is also shipped. `className` / `style` / `classNames` slots cover every visible part (25 slots), and every slot accepts either a class string or `{ className, style }` — the shape returned by StyleX's `stylex.props()`.
30
30
  - Styled tooltips out of the box — action hints and truncated-text previews use a custom dark-chip tooltip (no browser-default `title` look). Add `data-ssg-tooltip="text"` to your own elements (custom cells, headers) to get the same tooltip; colors are themeable via `--ssg-tooltip-*` tokens.
31
31
  - Built-in dark theme — `theme="light" | "dark" | "auto"` switches the grid, every popover / panel / menu, the drag ghost and tooltips through a single token preset. `"auto"` follows `prefers-color-scheme`; with class-based dark frameworks (Mantine / HeroUI / Tailwind) pass your resolved color scheme instead.
32
32
  - Toggle the top / bottom bars and their parts via props — whole bars (`showTopBar` / `showBottomBar`), the default top bar's summary chips and global-filter input, and the Rows/Columns counts in each bar.
@@ -75,6 +75,7 @@ The base styles are plain (unlayered) CSS scoped to `.ssg-*` classes, and all de
75
75
  ```
76
76
 
77
77
  - **Mantine** — works out of the box (no class-name or reset conflicts; grid popovers use `z-index: 1000`, above Mantine's default modal z-index).
78
+ - **StyleX** — works out of the box (no resets, `x`-prefixed atomic classes). Pass `stylex.props(...)` straight into `classNames.*`, `cellClassName`, `getRowClassName` or `detailRow.className` — every slot accepts `string | { className, style }`, so StyleX dynamic styles (delivered through the `style` object) reach the element. StyleX atomic classes and the grid's base classes share the same specificity, so load the grid CSS before StyleX's output, or use `style.layer.css` (required when StyleX's `useLayers` option is on). Bridge tokens with `stylex.create({ grid: { '--ssg-accent': vars.accent } })` on the `root` slot.
78
79
 
79
80
  To override a grid default reliably in plain CSS, chain your class with the grid's base class so it wins by specificity, independent of import order:
80
81
 
@@ -244,7 +245,7 @@ Sorting, column filters, and the global filter stay enabled and are forwarded to
244
245
  }
245
246
  ```
246
247
 
247
- - Use the `classNames` prop for per-part class slots, `cellClassName` per column, and `getRowClassName` per row. Token overrides always apply (tokens are defined at zero specificity). For property overrides, chain with the base class (e.g. `.ssg-body-cell.my-class`) to win regardless of import order — see the Styles section above.
248
+ - Use the `classNames` prop for per-part slots (root / toolbar / statusBar / header & body rows and cells / group & detail rows / popover / menuItem / tooltip / dragGhost / checkbox / cellEditor / emptyState / filterChipBar / errorBar / scrollHint / overlays), `cellClassName` per column, and `getRowClassName` per row. Each accepts a class string or `{ className, style }`; the root also takes a `style` prop. Inline `style` is applied to the part's element while the grid keeps the last word on positioning (`left` / `top` / `width` / `height` / `transform`). Token overrides always apply (tokens are defined at zero specificity). For property overrides, chain with the base class (e.g. `.ssg-body-cell.my-class`) to win regardless of import order — see the Styles section above.
248
249
 
249
250
  ### Dark theme
250
251
 
@@ -314,7 +315,7 @@ The full prop and type reference lives in [`src/components/spreadsheet-grid/API_
314
315
  - 日本語対応の折り返し — 列ごとの `wordBreak` / `lineBreak`。`wordBreak: 'auto-phrase'` で Chromium(Chrome / Edge)の文節折り返し(BudouX)。クロスブラウザの BudouX レシピは API リファレンス参照。
315
316
  - `height` / `maxHeight` によるスクロールコンテナ高さの外部制御(`height="100%"` で親要素の高さに追従)。
316
317
  - **クライアントサイド**(`rows`)と**サーバーサイド**(`dataSource`、SSRM)の両行モデル — サーバーサイドはクエリ送出(フィルター / ソート / グローバルフィルター)、ソフトリフレッシュ(`refreshServerSide()`)、取得失敗の再試行 UI に加え、`dataSource.updateRows` によるセル編集の書き戻し(楽観更新 + 失敗時の自動ロールバック)まで対応。
317
- - CSS カスタムプロパティ(`--ssg-*`。特異度 0 で定義され、利用側の上書きが常に勝ちます)によるテーマ設定。基底スタイルは未レイヤーの単一クラス特異度で、Tailwind Preflight などの CSS リセットに壊されません。カスケードレイヤー版(`style.layer.css`)も同梱。`className` / `classNames` スロットも用意。
318
+ - CSS カスタムプロパティ(`--ssg-*`。特異度 0 で定義され、利用側の上書きが常に勝ちます)によるテーマ設定。基底スタイルは未レイヤーの単一クラス特異度で、Tailwind Preflight などの CSS リセットに壊されません。カスケードレイヤー版(`style.layer.css`)も同梱。`className` / `style` / `classNames` スロットは可視パーツを網羅(25 スロット)し、各スロットは class 文字列でも `{ className, style }`(StyleX の `stylex.props()` の戻り値と同形)でも受け付けます。
318
319
  - スタイル付きツールチップを標準装備 — 操作ヒントや切り詰めテキストの全文表示は、ブラウザ標準の `title` ではなくダークチップのカスタムツールチップで表示。利用側の要素(カスタムセルやヘッダー)にも `data-ssg-tooltip="文言"` を付けるだけで同じ見た目になります。配色は `--ssg-tooltip-*` トークンで調整可。
319
320
  - ダークテーマを標準装備 — `theme="light" | "dark" | "auto"` で、グリッド本体・全ポップオーバー / パネル / メニュー・ドラッグゴースト・ツールチップをトークンプリセット 1 つで一括切替。`"auto"` は `prefers-color-scheme` に追従(Mantine / HeroUI / Tailwind のクラスベース dark 運用では、解決済みのカラースキームを渡す使い方を推奨)。
320
321
  - トップ / ボトムバーとその構成要素(バー全体〔`showTopBar` / `showBottomBar`〕、既定トップバーの summary chips・グローバルフィルター入力、各バーの Rows/Columns 件数)を props で表示制御。
@@ -363,6 +364,7 @@ import '@ishibashi0112/spreadsheet-grid/style.css'
363
364
  ```
364
365
 
365
366
  - **Mantine** — そのままで動作します(クラス名・リセットの衝突なし。グリッドの popover は `z-index: 1000` で Mantine の既定モーダルより前面)。
367
+ - **StyleX** — そのままで動作します(reset を持たず、生成クラスは接頭辞 `x` で衝突しません)。`classNames.*` / `cellClassName` / `getRowClassName` / `detailRow.className` へ `stylex.props(...)` の戻り値をそのまま渡せます(全スロットが `string | { className, style }` を受けるため、`style` 側で届く StyleX の動的スタイルも欠落しません)。StyleX の atomic クラスと基底クラスは同特異度のため、グリッド CSS を先に・StyleX の出力を後に読み込むか、`style.layer.css` を使ってください(StyleX 側で `useLayers` を使う場合は必須)。トークンは `root` スロットに `stylex.create({ grid: { '--ssg-accent': vars.accent } })` を渡して橋渡しできます。
366
368
 
367
369
  素の CSS でグリッド既定を確実に上書きするには、基底クラスと連結して特異度で勝たせてください(読み込み順に依存しません):
368
370
 
@@ -1,3 +1,4 @@
1
+ import type { GridResolvedSlot } from './model/gridTypes';
1
2
  export type ActiveCellOverlayRect = {
2
3
  left: number;
3
4
  top: number;
@@ -9,6 +10,7 @@ type ActiveCellOverlayProps = {
9
10
  headerHeight: number;
10
11
  leadingWidth: number;
11
12
  baseOffset?: number;
13
+ slot?: GridResolvedSlot;
12
14
  };
13
- export declare function ActiveCellOverlay({ rect, headerHeight, leadingWidth, baseOffset, }: ActiveCellOverlayProps): import("react").JSX.Element | null;
15
+ export declare function ActiveCellOverlay({ rect, headerHeight, leadingWidth, baseOffset, slot, }: ActiveCellOverlayProps): import("react").JSX.Element | null;
14
16
  export default ActiveCellOverlay;
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommitDirection, EditorCommitResult, EditorEnterMove, GridColumn, GridColumnEditor, GridRowKey } from './model/gridTypes';
2
+ import type { GridResolvedSlots } from './model/gridTypes';
2
3
  export type { EditorCommitDirection };
3
4
  type CellEditorRect = {
4
5
  left: number;
@@ -24,10 +25,11 @@ type CellEditorLayerProps<T> = {
24
25
  editor?: GridColumnEditor<T>;
25
26
  editorSession?: CellEditorSession<T> | null;
26
27
  themeClassName?: string;
28
+ slots?: GridResolvedSlots;
27
29
  onCommit: (value: unknown, direction?: EditorCommitDirection) => EditorCommitResult | void;
28
30
  onCancel: () => void;
29
31
  align?: 'left' | 'center' | 'right';
30
32
  enterMove?: EditorEnterMove;
31
33
  };
32
- export declare function CellEditorLayer<T>({ rect, headerHeight, leadingWidth, baseOffset, initialValue, editor, editorSession, themeClassName, onCommit, onCancel, align, enterMove, }: CellEditorLayerProps<T>): import("react").JSX.Element | null;
34
+ export declare function CellEditorLayer<T>({ rect, headerHeight, leadingWidth, baseOffset, initialValue, editor, editorSession, themeClassName, slots, onCommit, onCancel, align, enterMove, }: CellEditorLayerProps<T>): import("react").JSX.Element | null;
33
35
  export default CellEditorLayer;
@@ -1,3 +1,4 @@
1
+ import type { GridResolvedSlot } from './model/gridTypes';
1
2
  export type SelectionOverlayRect = {
2
3
  left: number;
3
4
  top: number;
@@ -9,6 +10,7 @@ type SelectionOverlayProps = {
9
10
  headerHeight: number;
10
11
  leadingWidth: number;
11
12
  baseOffset?: number;
13
+ slot?: GridResolvedSlot;
12
14
  };
13
- export declare function SelectionOverlay({ rect, headerHeight, leadingWidth, baseOffset, }: SelectionOverlayProps): import("react").JSX.Element | null;
15
+ export declare function SelectionOverlay({ rect, headerHeight, leadingWidth, baseOffset, slot, }: SelectionOverlayProps): import("react").JSX.Element | null;
14
16
  export default SelectionOverlay;
@@ -1,3 +1,3 @@
1
1
  import './styles.css';
2
2
  import type { SpreadsheetGridProps } from './model/gridTypes';
3
- export declare function SpreadsheetGrid<T extends object>({ rows: rowsProp, dataSource, serverSideRefreshToken, onServerSideLoadError, onServerSideWriteError, columns: columnsProp, onRowsChange, onColumnsChange, rowKeyGetter, createRow, createOverflowColumn, rowHeight: rowHeightProp, autoHeight, estimateRowHeight, headerHeight: headerHeightProp, density, theme, rowHeaderWidth, height, maxHeight, readOnly, dimReadOnlyCells, canEditCell: canEditCellProp, enableUndoRedo, enableClearOnDelete, editorEnterMove, undoHistoryLimit, onUndoRedoStateChange, enableRangeSelection, enableRowSelection, rowSelectionMode, enableSelectAllRows: enableSelectAllRowsProp, rowSelection: rowSelectionProp, selectedRowKeys: selectedRowKeysProp, onRowSelectionChange, enableGlobalFilter, enableColumnFilter, renderFilterDateInput, enableSorting, enableColumnResize, autoSizeColumns, showCellOverflowTooltip, showValidationMarks, enableRowHover, enableColumnHeaderHover, enableColumnMenu, noMatchingRowsText, noRowsText, showTopBar, showBottomBar, showTopBarSummary, showTopBarFilter, globalFilterPlaceholder, globalFilterIcon, showTopBarCounts, showBottomBarCounts, showFilterChipBar, renderTopBar, renderBottomBar, className, classNames, getRowClassName, detailRow, onExpandedDetailRowKeysChange, enableRowDrag, isRowDraggable, onRowMove, enableContextMenu, getContextMenuItems, onContextMenuOpen, scrollHint, ref, onStateChange, onScroll, }: SpreadsheetGridProps<T>): import("react").JSX.Element;
3
+ export declare function SpreadsheetGrid<T extends object>({ rows: rowsProp, dataSource, serverSideRefreshToken, onServerSideLoadError, onServerSideWriteError, columns: columnsProp, onRowsChange, onColumnsChange, rowKeyGetter, isRowExportable, createRow, createOverflowColumn, rowHeight: rowHeightProp, autoHeight, estimateRowHeight, headerHeight: headerHeightProp, density, theme, rowHeaderWidth, height, maxHeight, readOnly, dimReadOnlyCells, canEditCell: canEditCellProp, enableUndoRedo, enableClearOnDelete, editorEnterMove, undoHistoryLimit, onUndoRedoStateChange, enableRangeSelection, enableRowSelection, rowSelectionMode, enableSelectAllRows: enableSelectAllRowsProp, rowSelection: rowSelectionProp, selectedRowKeys: selectedRowKeysProp, onRowSelectionChange, enableGlobalFilter, enableColumnFilter, renderFilterDateInput, enableSorting, enableColumnResize, autoSizeColumns, showCellOverflowTooltip, showValidationMarks, enableRowHover, enableColumnHeaderHover, hoveredRowIndex: hoveredRowIndexProp, onHoveredRowChange, enableColumnMenu, noMatchingRowsText, noRowsText, showTopBar, showBottomBar, showTopBarSummary, showTopBarFilter, globalFilterPlaceholder, globalFilterIcon, showTopBarCounts, showBottomBarCounts, showFilterChipBar, renderTopBar, renderBottomBar, className, style, classNames, getRowClassName, detailRow, onExpandedDetailRowKeysChange, enableRowDrag, isRowDraggable, onRowMove, enableContextMenu, getContextMenuItems, onContextMenuOpen, scrollHint, ref, onStateChange, onScroll, }: SpreadsheetGridProps<T>): import("react").JSX.Element;
@@ -1,7 +1,9 @@
1
+ import type { GridResolvedSlot } from '../model/gridTypes';
1
2
  type CheckboxCellProps = {
2
3
  checked: boolean;
3
4
  readOnly: boolean;
4
5
  onToggle: () => void;
6
+ slot?: GridResolvedSlot;
5
7
  };
6
- export declare function CheckboxCell({ checked, readOnly, onToggle }: CheckboxCellProps): import("react").JSX.Element;
8
+ export declare function CheckboxCell({ checked, readOnly, onToggle, slot, }: CheckboxCellProps): import("react").JSX.Element;
7
9
  export default CheckboxCell;
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommitDirection, EditorCommitResult, EditorEnterMove, GridSelectEditorOption } from '../model/gridTypes';
2
+ import type { GridResolvedSlot } from '../model/gridTypes';
2
3
  type SelectCellEditorProps = {
3
4
  options: GridSelectEditorOption[];
4
5
  value: unknown;
@@ -6,7 +7,8 @@ type SelectCellEditorProps = {
6
7
  onCancel: () => void;
7
8
  align?: 'left' | 'center' | 'right';
8
9
  themeClassName?: string;
10
+ popoverSlot?: GridResolvedSlot;
9
11
  enterMove?: EditorEnterMove;
10
12
  };
11
- export declare function SelectCellEditor({ options, value, onCommit, onCancel, align, themeClassName, enterMove, }: SelectCellEditorProps): import("react").JSX.Element;
13
+ export declare function SelectCellEditor({ options, value, onCommit, onCancel, align, themeClassName, popoverSlot, enterMove, }: SelectCellEditorProps): import("react").JSX.Element;
12
14
  export default SelectCellEditor;
@@ -1,6 +1,7 @@
1
1
  import { type PointerEvent, type RefObject } from 'react';
2
2
  import type { GridColumn, GridColumnPinned } from '../model/gridTypes';
3
3
  import { type GridPaneLayout } from '../logic/geometry';
4
+ import type { GridResolvedSlot } from '../model/gridTypes';
4
5
  type ApplyColumnOrderAndPin = (orderedKeys: string[], pinOverride?: Map<string, GridColumnPinned | undefined>) => void;
5
6
  type UseColumnHeaderDragControllerArgs<T> = {
6
7
  enabled: boolean;
@@ -14,6 +15,7 @@ type UseColumnHeaderDragControllerArgs<T> = {
14
15
  centerLeadingWidth: number;
15
16
  rightLeadingWidth: number;
16
17
  applyColumnOrderAndPin: ApplyColumnOrderAndPin;
18
+ ghostSlot?: GridResolvedSlot;
17
19
  };
18
20
  export declare const useColumnHeaderDragController: <T>(args: UseColumnHeaderDragControllerArgs<T>) => {
19
21
  onColumnDragHandlePointerDown: (column: GridColumn<T>, event: PointerEvent<HTMLElement>) => void;
@@ -14,9 +14,10 @@ type UseGridClipboardControllerArgs<T extends object> = {
14
14
  onRowsChange?: (nextRows: T[]) => void;
15
15
  onColumnsChange?: (nextColumns: GridColumn<T>[]) => void;
16
16
  applyServerSideCellEdits?: (edits: ServerSideCellEditInput<T>[]) => number;
17
+ isRowExportable?: SpreadsheetGridProps<T>['isRowExportable'];
17
18
  dispatch: Dispatch<GridUiAction>;
18
19
  };
19
- export declare const useGridClipboardController: <T extends object>({ rows, rowModel, visibleColumns, uiState, readOnly, canEditCell, createRow, createOverflowColumn, onRowsChange, onColumnsChange, applyServerSideCellEdits, dispatch, }: UseGridClipboardControllerArgs<T>) => {
20
+ export declare const useGridClipboardController: <T extends object>({ rows, rowModel, visibleColumns, uiState, readOnly, canEditCell, createRow, createOverflowColumn, onRowsChange, onColumnsChange, applyServerSideCellEdits, isRowExportable, dispatch, }: UseGridClipboardControllerArgs<T>) => {
20
21
  isWholeGridSelected: boolean;
21
22
  handleCopy: () => Promise<void>;
22
23
  handlePaste: (event: React.ClipboardEvent<HTMLDivElement>) => void;
@@ -1 +1,2 @@
1
- export declare function useGridTooltip(): void;
1
+ import type { GridResolvedSlot } from '../model/gridTypes';
2
+ export declare function useGridTooltip(slot?: GridResolvedSlot): void;
@@ -0,0 +1,3 @@
1
+ import type { GridClassNames, GridResolvedSlot, GridResolvedSlots, GridSlotProps } from '../model/gridTypes';
2
+ export declare function useResolvedGridSlots(classNames: GridClassNames | undefined): GridResolvedSlots;
3
+ export declare function useResolvedGridSlot(slot: GridSlotProps | undefined): GridResolvedSlot;
@@ -1,5 +1,6 @@
1
1
  import { type PointerEvent, type RefObject } from 'react';
2
2
  import type { RowMetrics } from '../logic/verticalGeometry';
3
+ import type { GridResolvedSlot } from '../model/gridTypes';
3
4
  type UseRowDragControllerArgs = {
4
5
  enabled: boolean;
5
6
  rowMetrics: RowMetrics;
@@ -10,6 +11,7 @@ type UseRowDragControllerArgs = {
10
11
  bodyScrollRef: RefObject<HTMLDivElement | null>;
11
12
  getRowDragLabel: (viewIndex: number) => string;
12
13
  commitRowMove: (fromIndex: number, toIndex: number) => void;
14
+ ghostSlot?: GridResolvedSlot;
13
15
  };
14
16
  export declare const useRowDragController: (args: UseRowDragControllerArgs) => {
15
17
  onRowDragHandlePointerDown: (viewIndex: number, event: PointerEvent<HTMLElement>) => void;