/ chandeskpro / src / stores / tabStore.ts
swadhinbiswas Initial release v0.1.0 · 1/16/2026
ed7a4e4
105 lines · 3.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

export type TabType = 'catalog' | 'thread';

export interface Tab {
    id: string;
    type: TabType;
    title: string;
    board?: string;
    threadId?: number;
    hasNewReplies?: boolean;
}

interface TabState {
    tabs: Tab[];
    activeTabId: string | null;

    // Actions
    openTab: (tab: Omit<Tab, 'id'>) => string;
    closeTab: (id: string) => void;
    setActiveTab: (id: string) => void;
    reorderTabs: (fromIndex: number, toIndex: number) => void;
    updateTab: (id: string, updates: Partial<Tab>) => void;
    closeAllTabs: () => void;
    closeOtherTabs: (id: string) => void;
}

export const useTabStore = create<TabState>()(
    persist(
        (set, get) => ({
            tabs: [],
            activeTabId: null,

            openTab: (tabData) => {
                const id = `tab-${Date.now()}-${Math.random()}`;
                const newTab: Tab = { id, ...tabData };

                set((state) => ({
                    tabs: [...state.tabs, newTab],
                    activeTabId: id,
                }));

                return id;
            },

            closeTab: (id) => {
                set((state) => {
                    const newTabs = state.tabs.filter((tab) => tab.id !== id);
                    let newActiveTabId = state.activeTabId;

                    // If closing the active tab, switch to the last tab
                    if (state.activeTabId === id) {
                        newActiveTabId = newTabs.length > 0 ? newTabs[newTabs.length - 1].id : null;
                    }

                    return {
                        tabs: newTabs,
                        activeTabId: newActiveTabId,
                    };
                });
            },

            setActiveTab: (id) => {
                set({ activeTabId: id });
            },

            reorderTabs: (fromIndex, toIndex) => {
                set((state) => {
                    const newTabs = [...state.tabs];
                    const [movedTab] = newTabs.splice(fromIndex, 1);
                    newTabs.splice(toIndex, 0, movedTab);
                    return { tabs: newTabs };
                });
            },

            updateTab: (id, updates) => {
                set((state) => ({
                    tabs: state.tabs.map((tab) =>
                        tab.id === id ? { ...tab, ...updates } : tab
                    ),
                }));
            },

            closeAllTabs: () => {
                set({ tabs: [], activeTabId: null });
            },

            closeOtherTabs: (id) => {
                set((state) => ({
                    tabs: state.tabs.filter((tab) => tab.id === id),
                    activeTabId: id,
                }));
            },
        }),
        {
            name: 'tab-storage',
            partialize: (state) => ({
                tabs: state.tabs,
                activeTabId: state.activeTabId,
            }),
        }
    )
);