feat(LayoutManager): create layout manager with persistent store support to manage SampleList items layout
This commit is contained in:
@@ -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();
|
||||
Reference in New Issue
Block a user