data-grid-selector
v0.10.3
Published
Framework-agnostic web component for boolean matrices - edit and display 2D boolean arrays with interactive cell selection
Downloads
8
Maintainers
Readme
Features
- Web Component:
<data-grid>to edit/display 2D boolean matrices - Zero-deps ESM: single-file module, framework-agnostic
- Selection: click, click+drag for ranges; debounced updates (
debounceMs, default 100ms) - Events: emits
dataChangewith the current 2D boolean array - API:
update({ data, rowLabels, colLabels, onChange, debounceMs }) - Theming: CSS variables for colors, spacing, sizes (see CSS section)
- UX: sticky headers, desktop-optimized, basic touch tap
- A11y: ARIA roles/labels; focusable interactive cells
- Examples: Vanilla, React, Vue, and CDN usage
Installation
npm install data-grid-selectorUsage
Basic Setup
<!DOCTYPE html>
<html>
<head>
<script type="module">
import 'data-grid-selector';
</script>
</head>
<body>
<data-grid></data-grid>
<script>
const grid = document.querySelector('data-grid');
grid.addEventListener('dataChange', (e) => {
console.log('Data changed:', e.detail);
});
</script>
</body>
</html>With Custom Data
<data-grid></data-grid>
<script>
const grid = document.querySelector('data-grid');
grid.update({
data: Array(7).fill(null).map(() => Array(24).fill(false)),
rowLabels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
colLabels: Array.from({length: 24}, (_, i) => `${i}:00`)
});
</script>JavaScript Constructor
import DataGrid from 'data-grid-selector';
const grid = new DataGrid({
data: Array(31).fill(null).map(() => Array(24).fill(false)),
rowLabels: Array.from({length: 31}, (_, i) => `Day ${i + 1}`),
colLabels: Array.from({length: 24}, (_, i) => `${i}h`)
});
// ⚠️ Must append to DOM
document.getElementById('container').appendChild(grid);API
Constructor Options
const grid = new DataGrid({
data: boolean[][], // 2D boolean array (default: 5x5 grid)
rowLabels: string[], // Array of row labels
colLabels: string[], // Array of column labels
onChange: function, // Callback for data changes
debounceMs: number // Debounce delay (default: 100ms)
});Methods
// Get current data
const data = grid.getData();
// Update data and labels
grid.update({ data: newData, rowLabels: [...], colLabels: [...] });
// Reset to empty grid
grid.reset();Events
grid.addEventListener('dataChange', (e) => {
const data = e.detail; // 2D boolean array
console.log('Grid data changed:', data);
});CSS Customization
data-grid {
--grid-primary: #3b82f6; /* Active cell color */
--grid-bg: #ffffff; /* Background color */
--grid-cell-bg: #f8fafc; /* Cell background */
--grid-text: #1f2937; /* Text color */
--grid-cell-size: 28px; /* Cell size */
--grid-header-width: 80px; /* Header width */
--grid-cell-spacing: 4px; /* Cell spacing */
--grid-cell-radius: 8px; /* Cell border radius */
}Examples
Monthly Schedule
<data-grid></data-grid>
<script>
const grid = document.querySelector('data-grid');
grid.update({
data: Array(31).fill(null).map(() => Array(24).fill(false)),
rowLabels: Array.from({length: 31}, (_, i) => `Day ${i + 1}`),
colLabels: Array.from({length: 24}, (_, i) => `${i}h`)
});
grid.addEventListener('dataChange', (e) => {
const activeHours = e.detail.flat().filter(cell => cell).length;
console.log(`Active hours: ${activeHours}`);
});
</script>React Integration
import 'data-grid-selector';
import { useEffect, useRef } from 'react';
function AttendanceGrid({ data, onDataChange }) {
const gridRef = useRef();
useEffect(() => {
if (gridRef.current) {
gridRef.current.update({
data: data,
rowLabels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
colLabels: Array.from({length: 24}, (_, i) => `${i}:00`)
});
gridRef.current.addEventListener('dataChange', onDataChange);
}
}, [data, onDataChange]);
return <data-grid ref={gridRef} />;
}