Overview
The store module provides centralized state management using Zustand. It manages bins, grid configuration, view modes, selection state, drag interactions, and undo/redo history.
Import
import { useStore, type Bin, type ViewMode, type RenderMode } from '@/store/useStore';
Types
Bin
Represents a single Gridfinity bin with all its properties.
interface Bin {
id: string; // Unique identifier (UUID)
x: number; // Grid position X (0-based column)
y: number; // Grid position Y (0-based row)
w: number; // Width in grid units
d: number; // Depth in grid units
h: number; // Height in grid units
cornerRadius: number; // Corner radius in mm
wallThickness: number; // Wall thickness in mm
bottomThickness: number; // Bottom thickness in mm
stackingLip: boolean; // Enable stacking lip feature
labelShelf: boolean; // Enable 45° label shelf
labelWidth: number; // Label shelf width in mm
magnets: boolean; // Enable magnet holes
screws: boolean; // Enable screw holes
dividersX: number; // Number of X-axis dividers
dividersY: number; // Number of Y-axis dividers
color: string; // Hex color code
label: string; // User-defined label
group: string; // Bin group/category ID
}
UUID generated automatically on creation
Grid column position (0-indexed)
Grid row position (0-indexed)
Width in grid units (1 unit = 42mm)
Depth in grid units (1 unit = 42mm)
Height in grid units (1 unit = 7mm)
ViewMode
type ViewMode = '2d' | '3d' | 'split';
Controls the viewport layout.
RenderMode
type RenderMode = 'standard' | 'technical' | 'blueprint';
Controls the 3D rendering style.
DragState
Tracks drag-and-drop interactions for placing and moving bins.
interface DragState {
mode: 'idle' | 'placing' | 'dragging';
binId: string | null; // ID of bin being dragged
origin: { col: number; row: number } | null; // Drag start position
ghost: { col: number; row: number } | null; // Ghost preview position
ghostValid: boolean; // Whether ghost position is valid
placingConfig: Omit<Bin, 'id' | 'x' | 'y'> | null; // Config for new bin placement
}
State Properties
Grid Configuration
Bin Management
Array of all bins in the grid
selectedBinId
string | null
default:"null"
ID of the primary selected bin
Array of all selected bin IDs (supports multi-select)
View Settings
viewMode
ViewMode
default:"'split'"
Current viewport layout mode
renderMode
RenderMode
default:"'standard'"
Current 3D rendering style
Whether to render the baseplate
Whether to show dimension annotations
Whether to enable section view (cut-through)
Interaction State
Current drag-and-drop state
History
Undo/redo history stack of bin states
Current position in history stack
Actions
addBin
Adds a new bin to the grid.
addBin(bin: Omit<Bin, 'id'>): void
Bin configuration without ID (generated automatically)
Example:
const { addBin } = useStore();
addBin({
x: 0,
y: 0,
w: 2,
d: 2,
h: 3,
cornerRadius: 3.75,
wallThickness: 1.2,
bottomThickness: 0.8,
stackingLip: true,
labelShelf: false,
labelWidth: 12,
magnets: false,
screws: false,
dividersX: 0,
dividersY: 0,
color: '#00d4aa',
label: 'Small Parts',
group: 'parts',
});
Source: src/store/useStore.ts:112-121
removeBin
Removes a bin by ID.
removeBin(id: string): void
Source: src/store/useStore.ts:123-133
updateBin
Updates properties of an existing bin.
updateBin(id: string, updates: Partial<Bin>): void
Properties to update (partial update)
Example:
const { updateBin } = useStore();
updateBin('bin-id', {
h: 6,
labelShelf: true,
dividersX: 2,
});
Source: src/store/useStore.ts:135-139
moveBin
Moves a bin to a new grid position.
moveBin(id: string, x: number, y: number): void
Source: src/store/useStore.ts:141-145
selectBin
Selects a bin, with optional multi-select support.
selectBin(id: string | null, multi?: boolean): void
ID of bin to select, or null to clear selection
Whether to add to selection (multi-select mode)
Behavior:
- If
id is null, clears all selections
- If
multi is false, replaces current selection
- If
multi is true, toggles the bin in the selection set
Source: src/store/useStore.ts:147-160
setGridSize
Updates the grid dimensions.
setGridSize(cols: number, rows: number): void
Source: src/store/useStore.ts:162
setViewMode
Changes the viewport layout.
setViewMode(mode: ViewMode): void
New view mode: ‘2d’, ‘3d’, or ‘split’
Source: src/store/useStore.ts:164
setRenderMode
Changes the 3D rendering style.
setRenderMode(mode: RenderMode): void
New render mode: ‘standard’, ‘technical’, or ‘blueprint’
Source: src/store/useStore.ts:166
setShowDimensions
Toggles dimension annotations.
setShowDimensions(on: boolean): void
Whether to show dimensions
Source: src/store/useStore.ts:168
setSectionView
Toggles section view (cut-through).
setSectionView(on: boolean): void
Whether to enable section view
Source: src/store/useStore.ts:170
clearAll
Removes all bins and clears selection.
Source: src/store/useStore.ts:172-175
setDragState
Updates the drag state (used internally by drag handlers).
setDragState(state: Partial<DragState>): void
state
Partial<DragState>
required
Partial drag state to merge
Source: src/store/useStore.ts:177-179
startPlacing
Enters bin placement mode with a configuration template.
startPlacing(config: Omit<Bin, 'id' | 'x' | 'y'>): void
config
Omit<Bin, 'id' | 'x' | 'y'>
required
Bin configuration for placement (position determined by user click)
Source: src/store/useStore.ts:181-190
cancelPlacing
Exits placement mode without creating a bin.
Source: src/store/useStore.ts:192
undo
Reverts to the previous state in history.
Source: src/store/useStore.ts:194-201
redo
Reapplies the next state in history.
Source: src/store/useStore.ts:203-210
Usage Example
import { useStore } from '@/store/useStore';
function BinEditor() {
const bins = useStore((state) => state.bins);
const addBin = useStore((state) => state.addBin);
const updateBin = useStore((state) => state.updateBin);
const selectedBinId = useStore((state) => state.selectedBinId);
const handleAddBin = () => {
addBin({
x: 0, y: 0, w: 1, d: 1, h: 3,
cornerRadius: 3.75,
wallThickness: 1.2,
bottomThickness: 0.8,
stackingLip: true,
labelShelf: false,
labelWidth: 12,
magnets: false,
screws: false,
dividersX: 0,
dividersY: 0,
color: '#00d4aa',
label: 'New Bin',
group: '',
});
};
const handleUpdateHeight = (id: string, newHeight: number) => {
updateBin(id, { h: newHeight });
};
return (
<div>
<button onClick={handleAddBin}>Add Bin</button>
{bins.map(bin => (
<div key={bin.id}>
{bin.label} - {bin.w}x{bin.d}x{bin.h}
</div>
))}
</div>
);
}
History Management
The store automatically tracks bin changes for undo/redo:
- Recorded operations:
addBin, removeBin, updateBin, moveBin, clearAll
- History stack: Maintains a snapshot of
bins array after each operation
- Max history: Limited only by browser memory
- Implementation: Uses deep cloning via
JSON.parse(JSON.stringify())
Source: src/store/useStore.ts:87-91