@glideapps/glide-data-grid
Advanced tools
Comparing version 5.3.1-alpha3 to 5.3.1
@@ -371,6 +371,6 @@ # Basic Usage | ||
```ts | ||
getBounds: (col: number, row?: number) => Rectangle | undefined; | ||
getBounds: (col?: number, row?: number) => Rectangle | undefined; | ||
``` | ||
`getBounds` returns the current bounding box of a cell. This does not need to be a currently rendered cell. | ||
`getBounds` returns the current bounding box of a cell. This does not need to be a currently rendered cell. If called with `col` and `row` as undefined, the bounding box of the entire data grid scroll area is returned. | ||
@@ -377,0 +377,0 @@ --- |
@@ -5,4 +5,4 @@ import type { ImageWindowLoader, Item, Rectangle } from "../data-grid/data-grid-types"; | ||
private loadedLocations; | ||
private visibleWindow; | ||
private freezeCols; | ||
visibleWindow: Rectangle; | ||
freezeCols: number; | ||
private isInWindow; | ||
@@ -9,0 +9,0 @@ private cache; |
@@ -35,3 +35,4 @@ import * as React from "react"; | ||
export declare function useStateWithReactiveInput<T>(inputState: T): [T, React.Dispatch<React.SetStateAction<T>>, () => void]; | ||
export declare function makeAccessibilityStringForArray(arr: readonly string[]): string; | ||
export {}; | ||
//# sourceMappingURL=utils.d.ts.map |
import type { DataGridSearchProps } from "../data-grid-search/data-grid-search"; | ||
import { type GridCell, type GridSelection } from "../data-grid/data-grid-types"; | ||
import { type CopyBuffer } from "./copy-paste"; | ||
export declare function expandSelection(newVal: GridSelection, getCellsForSelection: DataGridSearchProps["getCellsForSelection"], rowMarkerOffset: number, spanRangeBehavior: "allowPartial" | "default", abortController: AbortController): GridSelection; | ||
export declare function unquote(str: string): string[][]; | ||
export declare function decodeHTML(tableEl: HTMLTableElement): string[][] | undefined; | ||
export declare function formatCell(cell: GridCell, index: number, raw: boolean, columnIndexes: readonly number[], escapeValues: boolean): string; | ||
export declare function formatForCopy(cells: readonly (readonly GridCell[])[], columnIndexes: readonly number[]): string; | ||
export declare function unquote(str: string): CopyBuffer; | ||
export declare function copyToClipboard(cells: readonly (readonly GridCell[])[], columnIndexes: readonly number[], e?: ClipboardEvent): void; | ||
//# sourceMappingURL=data-editor-fns.d.ts.map |
@@ -25,2 +25,3 @@ import * as React from "react"; | ||
readonly paste: boolean; | ||
readonly cut: boolean; | ||
readonly search: boolean; | ||
@@ -27,0 +28,0 @@ readonly first: boolean; |
import type { Theme } from "../.."; | ||
import type { SpriteManager } from "../data-grid-sprites"; | ||
import type { InnerGridCell, Rectangle, ImageWindowLoader, CustomCell, ProvideEditorCallback, BaseGridMouseEventArgs } from "../data-grid-types"; | ||
import type { InnerGridCell, Rectangle, ImageWindowLoader, CustomCell, ProvideEditorCallback, BaseGridMouseEventArgs, BooleanEmpty, BooleanIndeterminate } from "../data-grid-types"; | ||
export interface BaseDrawArgs { | ||
@@ -64,3 +64,7 @@ ctx: CanvasRenderingContext2D; | ||
readonly getAccessibilityString: (cell: T) => string; | ||
readonly onPaste: (val: string, cell: T) => T | undefined; | ||
readonly onPaste: (val: string, cell: T, details: { | ||
readonly rawValue: string | string[] | number | boolean | BooleanEmpty | BooleanIndeterminate; | ||
readonly formatted?: string | string[]; | ||
readonly formattedString?: string; | ||
}) => T | undefined; | ||
} | ||
@@ -67,0 +71,0 @@ /** @category Renderers */ |
@@ -12,2 +12,6 @@ import type { Theme } from "../common/styles"; | ||
export declare function cellIsInRange(location: Item, cell: InnerGridCell, selection: GridSelection): number; | ||
export declare function remapForDnDState(columns: readonly MappedGridColumn[], dndState?: { | ||
src: number; | ||
dest: number; | ||
}): readonly MappedGridColumn[]; | ||
export declare function getStickyWidth(columns: readonly MappedGridColumn[], dndState?: { | ||
@@ -14,0 +18,0 @@ src: number; |
@@ -94,2 +94,3 @@ import type { Theme } from "../common/styles"; | ||
readonly direction: readonly [-1 | 0 | 1, -1 | 0 | 1]; | ||
readonly isMaybeScrollbar: boolean; | ||
} | ||
@@ -96,0 +97,0 @@ /** @category Types */ |
@@ -198,3 +198,3 @@ import * as React from "react"; | ||
focus: () => void; | ||
getBounds: (col: number, row?: number) => Rectangle | undefined; | ||
getBounds: (col?: number, row?: number) => Rectangle | undefined; | ||
damage: (cells: DamageUpdateList) => void; | ||
@@ -201,0 +201,0 @@ } |
{ | ||
"name": "@glideapps/glide-data-grid", | ||
"version": "5.3.1-alpha3", | ||
"version": "5.3.1", | ||
"description": "React data grid for beautifully displaying and editing large amounts of data with amazing performance.", | ||
@@ -5,0 +5,0 @@ "sideEffects": [ |
import { renderHook } from "@testing-library/react-hooks"; | ||
import { useResizeDetector } from "../src/common/resize-detector"; | ||
import { maybe, deepEqual } from "../src/common/support"; | ||
import { makeAccessibilityStringForArray } from "../src/common/utils"; | ||
@@ -37,1 +38,33 @@ describe("maybe", () => { | ||
}); | ||
describe("makeAccessibilityStringForArray", () => { | ||
it("should return an empty string for an empty array", () => { | ||
expect(makeAccessibilityStringForArray([])).toBe(""); | ||
}); | ||
it("should join array elements with a comma and a space", () => { | ||
const input = ["a", "b", "c"]; | ||
const output = "a, b, c"; | ||
expect(makeAccessibilityStringForArray(input)).toBe(output); | ||
}); | ||
it("should stop joining when total character count exceeds 10,000", () => { | ||
const singleStr = "a".repeat(5000); // Each string has 5000 'a' characters | ||
const input = [singleStr, singleStr, "b"]; // Two strings of 5000 'a' and one 'b' | ||
const output = singleStr + ", " + singleStr; // Only two strings of 5000 'a' should be joined | ||
expect(makeAccessibilityStringForArray(input)).toBe(output); | ||
}); | ||
it("should handle large arrays without exceeding the 10,000 character limit", () => { | ||
const input = Array.from({ length: 10_000 }).fill("a") as string[]; // 10,000 'a' strings | ||
const output = Array.from({ length: 10_000 }).fill("a").join(", "); // Should join all since it doesn't exceed the limit | ||
expect(makeAccessibilityStringForArray(input)).toBe(output); | ||
}); | ||
it("should return a string without trailing comma if limit is hit", () => { | ||
const singleStr = "a".repeat(4999); // Each string has 4999 'a' characters | ||
const input = [singleStr, singleStr, "b", "c", "d"]; // Two strings of 4999 'a' and one 'b' | ||
const output = singleStr + ", " + singleStr + ", b, c"; // Only two strings of 4999 'a' should be joined without the 'b' | ||
expect(makeAccessibilityStringForArray(input)).toBe(output); | ||
}); | ||
}); |
@@ -1,99 +0,152 @@ | ||
import { GridCellKind } from "../src"; | ||
import { decodeHTML, formatCell } from "../src/data-editor/data-editor-fns"; | ||
/* eslint-disable sonarjs/no-duplicate-string */ | ||
import { CompactSelection, type GridSelection } from "../src"; | ||
import { expandSelection, unquote } from "../src/data-editor/data-editor-fns"; // Adjust the import path to your setup | ||
describe("data-editor-fns", () => { | ||
test("decode html", () => { | ||
const root = document.createElement("table"); | ||
root.innerHTML = ` | ||
<tbody> | ||
<tr> | ||
<td>1</td> | ||
<td>2</td> | ||
</tr> | ||
<tr> | ||
<td>3</td> | ||
<td>4</td> | ||
</tr> | ||
</tbody> | ||
`; | ||
describe("unquote", () => { | ||
it("should correctly unquote single line string without quotes", () => { | ||
const input = "hello\tworld"; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "hello", formatted: "hello", format: "string" }, | ||
{ rawValue: "world", formatted: "world", format: "string" }, | ||
], | ||
]); | ||
}); | ||
const decoded = decodeHTML(root); | ||
it("should correctly unquote single line string with quotes", () => { | ||
const input = `"hello"\t"world"`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "hello", formatted: "hello", format: "string" }, | ||
{ rawValue: "world", formatted: "world", format: "string" }, | ||
], | ||
]); | ||
}); | ||
expect(decoded).toEqual([ | ||
["1", "2"], | ||
["3", "4"], | ||
it("should handle double quotes correctly", () => { | ||
const input = `"he""llo"\t"wo""rld"`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: `he"llo`, formatted: `he"llo`, format: "string" }, | ||
{ rawValue: `wo"rld`, formatted: `wo"rld`, format: "string" }, | ||
], | ||
]); | ||
}); | ||
test("decode html line breaks", () => { | ||
const root = document.createElement("table"); | ||
root.innerHTML = ` | ||
<tbody> | ||
<tr> | ||
<td>1<br>1.1</td> | ||
<td>2<br/>2.1</td> | ||
</tr> | ||
<tr> | ||
<td>3</td> | ||
<td>4</td> | ||
</tr> | ||
</tbody> | ||
`; | ||
it("should correctly unquote multi line strings", () => { | ||
const input = `"hello"\t"world"\n"foo"\t"bar"`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "hello", formatted: "hello", format: "string" }, | ||
{ rawValue: "world", formatted: "world", format: "string" }, | ||
], | ||
[ | ||
{ rawValue: "foo", formatted: "foo", format: "string" }, | ||
{ rawValue: "bar", formatted: "bar", format: "string" }, | ||
], | ||
]); | ||
}); | ||
const decoded = decodeHTML(root); | ||
it("should handle empty strings correctly", () => { | ||
const input = ""; | ||
const output = unquote(input); | ||
expect(output).toEqual([[]]); | ||
}); | ||
expect(decoded).toEqual([ | ||
["1\n1.1", "2\n2.1"], | ||
["3", "4"], | ||
it("should correctly unquote strings containing tabs within quotes", () => { | ||
const input = `"hello\tworld"\tfoo`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "hello\tworld", formatted: "hello\tworld", format: "string" }, | ||
{ rawValue: "foo", formatted: "foo", format: "string" }, | ||
], | ||
]); | ||
}); | ||
test("format empty bubble cell", () => { | ||
expect( | ||
formatCell( | ||
{ | ||
kind: GridCellKind.Bubble, | ||
allowOverlay: true, | ||
data: [], | ||
}, | ||
0, | ||
false, | ||
[0], | ||
true | ||
) | ||
).toEqual(""); | ||
it("should correctly unquote strings containing newlines within quotes", () => { | ||
const input = `"hello\nworld"\tfoo`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "hello\nworld", formatted: "hello\nworld", format: "string" }, | ||
{ rawValue: "foo", formatted: "foo", format: "string" }, | ||
], | ||
]); | ||
}); | ||
test("format empty bubble cell with comma", () => { | ||
expect( | ||
formatCell( | ||
{ | ||
kind: GridCellKind.Bubble, | ||
allowOverlay: true, | ||
data: ["foo, bar", "baz"], | ||
it("should correctly unquote multi-line strings where newlines are within quotes", () => { | ||
const input = `"start"\t"middle\npart"\t"end"`; | ||
const output = unquote(input); | ||
expect(output).toEqual([ | ||
[ | ||
{ rawValue: "start", formatted: "start", format: "string" }, | ||
{ rawValue: "middle\npart", formatted: "middle\npart", format: "string" }, | ||
{ rawValue: "end", formatted: "end", format: "string" }, | ||
], | ||
]); | ||
}); | ||
}); | ||
describe("expandSelection", () => { | ||
const getCellsForSelection = jest.fn(); | ||
const abortController = new AbortController(); | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
it("should return the original selection if spanRangeBehavior is allowPartial", () => { | ||
const selection: GridSelection = { | ||
current: { | ||
cell: [0, 0], | ||
range: { | ||
x: 0, | ||
y: 0, | ||
width: 1, | ||
height: 1, | ||
}, | ||
0, | ||
false, | ||
[0], | ||
true | ||
) | ||
).toEqual('"foo, bar",baz'); | ||
rangeStack: [], | ||
}, | ||
columns: CompactSelection.empty(), | ||
rows: CompactSelection.empty(), | ||
}; | ||
const result = expandSelection(selection, getCellsForSelection, 0, "allowPartial", abortController); | ||
expect(result).toEqual(selection); | ||
}); | ||
test("format respects copyData", () => { | ||
expect( | ||
formatCell( | ||
{ | ||
kind: GridCellKind.Bubble, | ||
allowOverlay: true, | ||
data: ["foo, bar", "baz"], | ||
copyData: "override", | ||
it("should return the original selection if current selection is undefined", () => { | ||
const selection = { | ||
current: undefined, | ||
columns: CompactSelection.empty(), | ||
rows: CompactSelection.empty(), | ||
}; | ||
const result = expandSelection(selection, getCellsForSelection, 0, "default", abortController); | ||
expect(result).toEqual(selection); | ||
}); | ||
it("should return the original selection if getCellsForSelection returns a function", () => { | ||
const selection: GridSelection = { | ||
current: { | ||
cell: [0, 0], | ||
range: { | ||
x: 0, | ||
y: 0, | ||
width: 1, | ||
height: 1, | ||
}, | ||
0, | ||
false, | ||
[0], | ||
true | ||
) | ||
).toEqual("override"); | ||
rangeStack: [], | ||
}, | ||
columns: CompactSelection.empty(), | ||
rows: CompactSelection.empty(), | ||
}; | ||
getCellsForSelection.mockReturnValue(() => ({})); | ||
const result = expandSelection(selection, getCellsForSelection, 0, "default", abortController); | ||
expect(result).toEqual(selection); | ||
expect(getCellsForSelection).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
3242724
34795
177
33545
0