feat(LayoutManager): create layout manager with persistent store support to manage SampleList items layout

This commit is contained in:
Ilia Mashkov
2026-02-27 18:40:08 +03:00
parent f0aa89097e
commit c86b5f5db8

View File

@@ -0,0 +1,113 @@
import { createPersistentStore } from '$shared/lib';
import { responsiveManager } from '$shared/lib';
export type LayoutMode = 'list' | 'grid';
interface LayoutConfig {
mode: LayoutMode;
}
const STORAGE_KEY = 'glyphdiff:sample-list-layout';
const SM_GAP_PX = 16;
const MD_GAP_PX = 24;
const DEFAULT_CONFIG: LayoutConfig = {
mode: 'list',
};
/**
* LayoutManager manages the layout configuration for SampleList widget.
* Handles mode switching between list/grid and responsive column calculation.
*/
class LayoutManager {
// Private reactive state
#mode = $state<LayoutMode>(DEFAULT_CONFIG.mode);
#store = createPersistentStore<LayoutConfig>(STORAGE_KEY, DEFAULT_CONFIG);
constructor() {
// Load saved layout preference
const saved = this.#store.value;
if (saved && saved.mode) {
this.#mode = saved.mode;
}
}
get mode(): LayoutMode {
return this.#mode;
}
get gap(): number {
return responsiveManager.isMobile || responsiveManager.isTabletPortrait ? SM_GAP_PX : MD_GAP_PX;
}
get isListMode(): boolean {
return this.#mode === 'list';
}
get isGridMode(): boolean {
return this.#mode === 'grid';
}
/**
* Get current number of columns based on mode and screen size.
* List mode always uses 1 column.
* Grid mode uses responsive column counts:
* - Mobile: 1 column
* - Tablet Portrait: 1 column
* - Tablet: 2 columns
* - Desktop: 3 columns
* - Desktop Large: 4 columns
*/
get columns(): number {
if (this.#mode === 'list') {
return 1;
}
// Grid mode: responsive columns
switch (true) {
case responsiveManager.isMobile:
return 1;
case responsiveManager.isTabletPortrait:
return 1;
case responsiveManager.isTablet:
return 2;
case responsiveManager.isDesktop:
return 3;
case responsiveManager.isDesktopLarge:
return 4;
default:
return 1;
}
}
/**
* Set the layout mode.
* @param mode - The new layout mode ('list' or 'grid')
*/
setMode(mode: LayoutMode): void {
if (this.#mode === mode) {
return;
}
this.#mode = mode;
this.#store.value = { mode };
}
/**
* Toggle between list and grid modes.
*/
toggleMode(): void {
this.setMode(this.#mode === 'list' ? 'grid' : 'list');
}
/**
* Reset to default layout mode.
*/
reset(): void {
this.#mode = DEFAULT_CONFIG.mode;
this.#store.clear();
}
}
// Export a singleton — one instance for the whole app
export const layoutManager = new LayoutManager();