uiStore.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * UI Store Module
  3. *
  4. * Zustand store for managing UI state and operations.
  5. * Handles:
  6. * - Global loading state
  7. * - Global error messages
  8. * - Left panel width with localStorage persistence
  9. *
  10. * @module stores/uiStore
  11. */
  12. import { create } from 'zustand';
  13. import type { UIStoreState } from '../types/store';
  14. import { getItem, setItem } from '../utils/storage';
  15. /**
  16. * LocalStorage key for persisting left panel width
  17. */
  18. const LEFT_PANEL_WIDTH_KEY = 'ax-leftPanelWidth';
  19. /**
  20. * Default left panel width percentage
  21. */
  22. const DEFAULT_LEFT_PANEL_WIDTH = 40;
  23. /**
  24. * Load left panel width from localStorage
  25. *
  26. * @returns Persisted width or default value
  27. */
  28. const loadLeftPanelWidth = (): number => {
  29. const saved = getItem<number>(LEFT_PANEL_WIDTH_KEY);
  30. return saved ?? DEFAULT_LEFT_PANEL_WIDTH;
  31. };
  32. /**
  33. * UI store
  34. *
  35. * Manages global UI state including loading indicators, error messages,
  36. * panel width preferences, and document preview state.
  37. *
  38. * The left panel width is automatically persisted to localStorage
  39. * when updated via setLeftPanelWidth action.
  40. *
  41. * @example
  42. * ```typescript
  43. * // Set global loading state
  44. * useUIStore.getState().setLoading(true);
  45. *
  46. * // Set global error message
  47. * useUIStore.getState().setError('Failed to load document');
  48. *
  49. * // Clear error
  50. * useUIStore.getState().setError(null);
  51. *
  52. * // Update left panel width (persists to localStorage)
  53. * useUIStore.getState().setLeftPanelWidth(35);
  54. *
  55. * // Open document preview
  56. * useUIStore.getState().openDocumentPreview('doc-abc123');
  57. *
  58. * // Close document preview and return to chat
  59. * useUIStore.getState().closeDocumentPreview();
  60. * ```
  61. */
  62. export const useUIStore = create<UIStoreState>((set) => ({
  63. // ============ State ============
  64. loading: false,
  65. error: null,
  66. leftPanelWidth: loadLeftPanelWidth(),
  67. // Note: previewMode is deprecated. Right panel now shows EditorPanel by default.
  68. // Kept for backward compatibility.
  69. previewMode: false,
  70. previewDocumentId: null,
  71. previewDocumentName: null,
  72. // ============ Actions ============
  73. /**
  74. * Set global loading state
  75. *
  76. * Controls the global loading indicator.
  77. * Used for app-wide loading states like initial app load.
  78. *
  79. * @param loading - True to show loading, false to hide
  80. */
  81. setLoading: (loading: boolean) => {
  82. set({ loading });
  83. },
  84. /**
  85. * Set global error message
  86. *
  87. * Sets a global error message to display to the user.
  88. * Pass null to clear the error.
  89. *
  90. * @param error - Error message string or null to clear
  91. */
  92. setError: (error: string | null) => {
  93. set({ error });
  94. },
  95. /**
  96. * Set left panel width and persist to localStorage
  97. *
  98. * Updates the left panel width and saves it to localStorage
  99. * for persistence across sessions.
  100. *
  101. * @param width - Width percentage (0-100)
  102. */
  103. setLeftPanelWidth: (width: number) => {
  104. // Update store state
  105. set({ leftPanelWidth: width });
  106. // Persist to localStorage
  107. setItem(LEFT_PANEL_WIDTH_KEY, width);
  108. },
  109. /**
  110. * Open document preview mode
  111. *
  112. * Opens the document in the right panel EditorPanel for preview and editing.
  113. * Used when user clicks on an export record link in the chat.
  114. *
  115. * @param documentId - ID of the document to preview
  116. * @param documentName - Optional name of the document to display in the editor toolbar
  117. */
  118. openDocumentPreview: (documentId: string, documentName?: string) => {
  119. set({
  120. previewDocumentId: documentId,
  121. previewDocumentName: documentName || null,
  122. });
  123. },
  124. /**
  125. * Close document preview mode
  126. *
  127. * Closes the document in the right panel EditorPanel.
  128. */
  129. closeDocumentPreview: () => {
  130. set({
  131. previewDocumentId: null,
  132. previewDocumentName: null,
  133. });
  134. },
  135. }));
  136. export default useUIStore;