https://github.com/metaory/bit-grid-component
🚧 A lightweight, framework-agnostic web component for interactive boolean data visualization. Click and drag to toggle cells on/off 🚧
https://github.com/metaory/bit-grid-component
data-input npm pin vanilla-javascript web-components
Last synced: 5 months ago
JSON representation
🚧 A lightweight, framework-agnostic web component for interactive boolean data visualization. Click and drag to toggle cells on/off 🚧
- Host: GitHub
- URL: https://github.com/metaory/bit-grid-component
- Owner: metaory
- License: mit
- Created: 2025-07-29T11:28:51.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2025-08-31T11:29:12.000Z (5 months ago)
- Last Synced: 2025-08-31T14:00:00.902Z (5 months ago)
- Topics: data-input, npm, pin, vanilla-javascript, web-components
- Language: JavaScript
- Homepage: https://metaory.github.io/data-grid-selector/
- Size: 3.96 MB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
BitGrid Component
Framework-agnostic web component for boolean matrices
edit and display 2D boolean arrays
with interactive cell selection
## Demo and Documentations
## Framework Usage Example
> [!TIP]
> Example Sources are under [./examples/](https://github.com/metaory/bit-grid-component/tree/master/examples)
## Features
- **Web Component**: `` for 2D boolean matrices
- **Zero-deps ESM**: single-file module, framework-agnostic
- **Selection**: click + drag ranges with debounced updates
- **Events**: `dataChange` event with 2D boolean array
- **API**: `update({ data, rowLabels, colLabels, onChange, debounceMs })`
- **Theming**: CSS custom properties for colors and spacing
- **Examples**: Vanilla, React, Vue, Angular, CDN
## Installation
```bash
npm install bit-grid-component
```
## Usage
### Declarative HTML
```html
import 'bit-grid-component'
const grid = document.querySelector('bit-grid');
grid.addEventListener('dataChange', (e) => {
console.log('Data changed:', e.detail);
});
```
### Imperative Update
```html
const grid = document.querySelector('bit-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`)
});
```
### JavaScript Constructor
```javascript
import 'bit-grid-component';
import BitGrid from 'bit-grid-component';
const grid = new BitGrid({
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
```javascript
const grid = new BitGrid({
data: boolean[][], // Optional: 2D boolean array
rowLabels: string[], // Optional: Array of row labels
colLabels: string[], // Optional: Array of column labels
onChange: function, // Optional: Callback for data changes
debounceMs: number // Optional: Debounce delay (default: 100ms)
});
```
**Inference Priority:**
1. If both `rowLabels` and `colLabels` provided → data generated automatically
2. If `data` provided → labels generated if not provided
3. Default → 5x5 grid with auto-generated labels
### Methods
```javascript
// Get current data
const data = grid.getData();
// Update data and labels (infers dimensions)
grid.update({ data: newData, rowLabels: [...], colLabels: [...] });
// Convenience methods
grid.setLabels(['Row1', 'Row2'], ['Col1', 'Col2']);
grid.setData(booleanArray);
grid.setCell(row, col, true);
grid.getCell(row, col);
grid.toggleCell(row, col);
grid.fill(false); // Fill all cells with value
// Reset to empty grid
grid.reset();
```
### Events
```javascript
grid.addEventListener('dataChange', (e) => {
const data = e.detail; // 2D boolean array
console.log('Grid data changed:', data);
});
```
## CSS Customization
```css
bit-grid {
--grid-primary: #3b82f6; /* Active cell color */
--grid-bg: #ffffff; /* Background color */
--grid-cell-bg: #f8fafc; /* Cell background */
--grid-text: #1f2937; /* Text color */
--grid-text-muted: #6b7280; /* Muted text color */
--grid-header-bg: #f1f5f9; /* Header background */
--grid-hover-bg: #e2e8f0; /* Hover background */
--grid-selection-bg: rgba(59, 130, 246, 0.25); /* Selection background */
--grid-selection-active-bg: rgba(59, 130, 246, 0.7); /* Active selection */
--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
```html
const grid = document.querySelector('bit-grid');
// Just provide labels - data auto-generated
grid.update({
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}`);
});
```
### React
```jsx
import 'bit-grid-component';
import { useEffect, useRef } from 'react';
function AttendanceGrid({ data, onDataChange }) {
const gridRef = useRef();
useEffect(() => {
if (gridRef.current) {
// Labels-first approach
gridRef.current.update({
rowLabels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
colLabels: Array.from({length: 24}, (_, i) => `${i}:00`)
});
// Then set data if provided
if (data) {
gridRef.current.setData(data);
}
gridRef.current.addEventListener('dataChange', onDataChange);
}
}, [data, onDataChange]);
return ;
}
```
## License
[MIT](LICENSE)