react-masume-grid 0.1.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.
@@ -0,0 +1,93 @@
1
+ import { CSSProperties } from 'react';
2
+ /** Cell values are plain strings. Formatting/parsing is up to the consumer. */
3
+ export type CellValue = string;
4
+ /**
5
+ * Cell type of a column. Values are always stored as strings; the type
6
+ * controls the editor UI, input normalization and display.
7
+ *
8
+ * - `text` — free text (default)
9
+ * - `number` — right-aligned; input is normalized (full-width digits,
10
+ * commas) and non-numeric input is rejected
11
+ * - `select` — dropdown backed by `options`; stores the option `value`
12
+ * and displays its `label`
13
+ * - `date` — native date picker; stored as `YYYY-MM-DD`; pasted text in
14
+ * common formats (2024/1/5, 2024年1月5日, 20240105) is normalized
15
+ */
16
+ export type ColumnType = 'text' | 'number' | 'select' | 'date';
17
+ export interface SelectOption {
18
+ /** Stored in the data. */
19
+ value: string;
20
+ /** Shown in cells and in the dropdown. Defaults to `value`. */
21
+ label?: string;
22
+ }
23
+ export interface ColumnDef {
24
+ /** Cell type. Default: 'text'. */
25
+ type?: ColumnType;
26
+ /** Choices for a 'select' column (e.g. master data). */
27
+ options?: Array<string | SelectOption>;
28
+ /**
29
+ * For 'select' columns: reject values that are not in `options`.
30
+ * Default: true. Set false to allow free input alongside the dropdown.
31
+ */
32
+ strict?: boolean;
33
+ /** Header caption. Defaults to spreadsheet-style letters (A, B, C, …). */
34
+ title?: string;
35
+ /** Column width in pixels. Defaults to `defaultColumnWidth`. */
36
+ width?: number;
37
+ /** Disallow editing cells in this column. */
38
+ readOnly?: boolean;
39
+ /**
40
+ * Allow resizing this column by dragging its header edge.
41
+ * Overrides the grid-level `resizableColumns`.
42
+ */
43
+ resizable?: boolean;
44
+ }
45
+ export interface CellPos {
46
+ row: number;
47
+ col: number;
48
+ }
49
+ /** Inclusive, normalized rectangular range (top <= bottom, left <= right). */
50
+ export interface NormalizedRange {
51
+ top: number;
52
+ left: number;
53
+ bottom: number;
54
+ right: number;
55
+ }
56
+ export interface MasumeGridProps {
57
+ /** Grid contents as a 2D array of strings. Rows may be ragged. */
58
+ data: CellValue[][];
59
+ /**
60
+ * Column definitions. When omitted, the column count is derived from the
61
+ * longest row in `data` and headers show A, B, C, …
62
+ */
63
+ columns?: ColumnDef[];
64
+ /** Called with a new 2D array whenever cells change (edit / paste / delete). */
65
+ onChange?: (next: CellValue[][]) => void;
66
+ /** Called once per changed cell. Can be used instead of (or with) `onChange`. */
67
+ onCellChange?: (row: number, col: number, value: CellValue) => void;
68
+ /** Called whenever the selection changes, with normalized ranges. */
69
+ onSelectionChange?: (ranges: NormalizedRange[]) => void;
70
+ /** Called when a column resize drag finishes, with the final width in pixels. */
71
+ onColumnResize?: (col: number, width: number) => void;
72
+ /** Show the row-number column. Default: true. */
73
+ showRowNumbers?: boolean;
74
+ /** Show the column header row. Default: true. */
75
+ showHeader?: boolean;
76
+ /** Disallow all editing (selection & copy still work). Default: false. */
77
+ readOnly?: boolean;
78
+ /**
79
+ * Allow column resizing by dragging header edges. Default: true.
80
+ * Requires `showHeader` (handles live in the header row).
81
+ */
82
+ resizableColumns?: boolean;
83
+ /** Row height in pixels. Default: 28. */
84
+ rowHeight?: number;
85
+ /** Header row height in pixels. Default: 28. */
86
+ headerHeight?: number;
87
+ /** Width of columns without an explicit width. Default: 120. */
88
+ defaultColumnWidth?: number;
89
+ /** Width of the row-number column. Default: 48. */
90
+ rowNumberWidth?: number;
91
+ className?: string;
92
+ style?: CSSProperties;
93
+ }
@@ -0,0 +1,34 @@
1
+ import { CellPos, NormalizedRange } from './types';
2
+ /** A selection range as the user built it: anchor (active cell) + focus (drag end). */
3
+ export interface SelRange {
4
+ anchor: CellPos;
5
+ focus: CellPos;
6
+ }
7
+ export declare function clamp(n: number, min: number, max: number): number;
8
+ /** 0 -> A, 25 -> Z, 26 -> AA, 701 -> ZZ, 702 -> AAA */
9
+ export declare function colName(index: number): string;
10
+ /** Prefix sums of column widths; result[i] is the x offset of column i, result[length] the total. */
11
+ export declare function columnOffsets(widths: number[]): number[];
12
+ export declare function normalizeRange(range: SelRange, rowCount: number, colCount: number): NormalizedRange;
13
+ /** Convert full-width digits/signs/separators to their ASCII equivalents. */
14
+ export declare function toHalfWidth(text: string): string;
15
+ /**
16
+ * Normalize input for a number cell: full-width chars are converted and
17
+ * thousands separators removed. Returns the normalized string, '' for empty
18
+ * input, or null when the input is not a valid number.
19
+ */
20
+ export declare function normalizeNumberInput(value: string): string | null;
21
+ /**
22
+ * Normalize input for a date cell to ISO `YYYY-MM-DD`. Accepts
23
+ * YYYY-MM-DD, YYYY/M/D, YYYY.M.D, YYYY年M月D日 and YYYYMMDD (full-width ok).
24
+ * Returns '' for empty input, or null when the input is not a valid date.
25
+ */
26
+ export declare function normalizeDateInput(value: string): string | null;
27
+ /** Serialize a matrix to Excel-compatible TSV (cells with tabs/newlines/quotes get quoted). */
28
+ export declare function matrixToTSV(matrix: string[][]): string;
29
+ /**
30
+ * Parse clipboard text (TSV, Excel-compatible) into a matrix.
31
+ * Handles quoted cells containing tabs/newlines, doubled quotes, CRLF,
32
+ * and strips a single trailing newline (Excel appends one on copy).
33
+ */
34
+ export declare function parseClipboardText(text: string): string[][];
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "react-masume-grid",
3
+ "version": "0.1.0",
4
+ "description": "MasumeGrid (マス目) — a lightweight React spreadsheet component with IME-friendly cell editing, cell types (text/number/select/date), range selection, and Excel-compatible clipboard support.",
5
+ "keywords": [
6
+ "react",
7
+ "spreadsheet",
8
+ "grid",
9
+ "datagrid",
10
+ "table",
11
+ "excel",
12
+ "ime",
13
+ "japanese"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "t92345era",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/t92345era/react-masume-grid.git"
20
+ },
21
+ "homepage": "https://github.com/t92345era/react-masume-grid#readme",
22
+ "bugs": {
23
+ "url": "https://github.com/t92345era/react-masume-grid/issues"
24
+ },
25
+ "type": "module",
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "main": "./dist/masume-grid.cjs",
30
+ "module": "./dist/masume-grid.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/masume-grid.js",
36
+ "require": "./dist/masume-grid.cjs"
37
+ },
38
+ "./styles.css": "./dist/masume-grid.css"
39
+ },
40
+ "sideEffects": [
41
+ "**/*.css"
42
+ ],
43
+ "scripts": {
44
+ "dev": "vite",
45
+ "build": "vite build",
46
+ "typecheck": "tsc --noEmit",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "prepublishOnly": "npm run typecheck && npm run test && npm run build"
50
+ },
51
+ "peerDependencies": {
52
+ "react": ">=18",
53
+ "react-dom": ">=18"
54
+ },
55
+ "devDependencies": {
56
+ "@testing-library/dom": "^10.4.0",
57
+ "@testing-library/react": "^16.3.0",
58
+ "@types/react": "^19.1.0",
59
+ "@types/react-dom": "^19.1.0",
60
+ "@vitejs/plugin-react": "^4.5.0",
61
+ "jsdom": "^26.1.0",
62
+ "puppeteer-core": "^25.3.0",
63
+ "react": "^19.1.0",
64
+ "react-dom": "^19.1.0",
65
+ "typescript": "^5.8.3",
66
+ "vite": "^6.3.5",
67
+ "vite-plugin-dts": "^4.5.4",
68
+ "vitest": "^3.2.4"
69
+ }
70
+ }