@codella-software/react 2.2.27 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/filters-and-sort/useFiltersAndSort.ts","../src/form-builder/useFormBuilder.ts","../src/live-updates/LiveUpdateProvider.tsx","../src/live-updates/useLiveListener.ts","../src/live-updates/useLiveRequest.ts","../src/live-updates/useLiveUpdateListener.ts","../src/live-updates/useLiveUpdates.ts","../src/rich-content/useRichContent.ts","../src/table-builder/useTableService.ts","../src/tabs/useTabsHooks.tsx"],"sourcesContent":["// Real implementation of useFiltersAndSort hook\nimport { FiltersAndSortService, type FilterAndSortState } from '@codella-software/utils'\nimport { useEffect, useMemo, useState } from 'react'\n\n/**\n * Hook options for useFiltersAndSort\n */\nexport interface UseFiltersAndSortOptions {\n /** FiltersAndSortService instance */\n service: FiltersAndSortService\n}\n\n/**\n * Hook return value for useFiltersAndSort\n */\nexport interface UseFiltersAndSortReturn {\n /** Current filter state */\n filters: Record<string, any>\n /** Current sort field */\n sortBy: string | null\n /** Current sort direction */\n sortDirection: 'asc' | 'desc'\n /** Current page (0-based) */\n page: number\n /** Page size */\n pageSize: number\n /** Current search query */\n query: string\n /** Set filter */\n setFilter: (key: string, value: any) => void\n /** Clear specific filter */\n clearFilter: (key: string) => void\n /** Clear all filters */\n clearAllFilters: () => void\n /** Set/toggle sort (auto-toggles between asc -> desc -> none) */\n setSort: (field: string) => void\n /** Toggle sort direction for field (alias for setSort) */\n toggleSort: (field: string) => void\n /** Set page */\n setPage: (page: number) => void\n /** Set page size */\n setPageSize: (size: number) => void\n /** Go to next page */\n nextPage: () => void\n /** Go to previous page */\n prevPage: () => void\n /** Set search query */\n setQuery: (query: string) => void\n /** Reset to initial state */\n reset: () => void\n}\n\n/**\n * React hook that wraps FiltersAndSortService\n *\n * @param options - Hook options including FiltersAndSortService instance\n * @returns Filters and sort state with control methods\n *\n * @example\n * ```tsx\n * const service = new FiltersAndSortService({ storageKey: 'my-filters' });\n *\n * function MyTable() {\n * const filters = useFiltersAndSort({ service });\n * return (\n * <div>\n * <input\n * value={filters.filters.name || ''}\n * onChange={(e) => filters.setFilter('name', e.target.value)}\n * />\n * <button onClick={() => filters.clearAllFilters()}>Clear</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useFiltersAndSort(\n options: UseFiltersAndSortOptions\n): UseFiltersAndSortReturn {\n const { service } = options\n\n if (!service) {\n throw new Error('useFiltersAndSort: service is required')\n }\n\n const [state, setState] = useState<FilterAndSortState>(() => {\n return service.getCurrentState()\n })\n\n useEffect(() => {\n if (!service) {\n return\n }\n\n const subscription = service.getState().subscribe((newState: FilterAndSortState) => {\n setState(newState)\n })\n\n return () => subscription.unsubscribe()\n }, [service])\n\n const callbacks = useMemo(() => ({\n setFilter: (key: string, value: any) => {\n service.setFilters({ [key]: value })\n },\n\n clearFilter: (key: string) => {\n service.removeFilter(key)\n },\n\n clearAllFilters: () => {\n service.clearFilters()\n },\n\n setSort: (field: string) => {\n service.setSort(field)\n },\n\n toggleSort: (field: string) => {\n service.setSort(field)\n },\n\n setPage: (page: number) => {\n service.setPagination(page)\n },\n\n setPageSize: (size: number) => {\n const currentPage = state.pagination.page\n service.setPagination(currentPage, size)\n },\n\n nextPage: () => {\n service.setPagination(state.pagination.page + 1)\n },\n\n prevPage: () => {\n const newPage = Math.max(0, state.pagination.page - 1)\n service.setPagination(newPage)\n },\n\n setQuery: (query: string) => {\n service.setQuery(query)\n },\n\n reset: () => {\n service.reset()\n },\n }), [service, state.pagination.page])\n\n const memoizedReturn = useMemo(() => ({\n filters: state.filters,\n sortBy: state.sort?.fieldName || null,\n sortDirection: state.sort?.direction || 'asc',\n page: state.pagination.page,\n pageSize: state.pagination.limit,\n query: state.query,\n ...callbacks,\n }), [state, callbacks])\n\n return memoizedReturn\n}\n","// React hook for FormBuilder with proper state management\nimport { FormBuilder } from '@codella-software/utils'\nimport { useEffect, useMemo, useState } from 'react'\n\n/**\n * Hook options for useFormBuilder\n */\nexport interface UseFormBuilderOptions<T extends Record<string, any>> {\n /** FormBuilder instance */\n builder: FormBuilder<T>\n}\n\n/**\n * Hook return value for useFormBuilder\n */\nexport interface UseFormBuilderReturn<T extends Record<string, any>> {\n /** Current form values */\n values: T\n /** Form validation errors */\n errors: Record<string, string | undefined>\n /** Form touched fields */\n touched: Record<string, boolean>\n /** Current form step (for multi-step forms) */\n currentStep: number\n /** Total form steps */\n totalSteps: number\n /** Is form currently submitting */\n isSubmitting: boolean\n /** Is form valid */\n isValid: boolean\n /** Set field value */\n setFieldValue: (field: keyof T, value: any) => Promise<void>\n /** Set field touched */\n setFieldTouched: (field: keyof T, touched: boolean) => void\n /** Validate entire form */\n validate: () => Promise<Record<string, string | undefined>>\n /** Submit form */\n submit: () => Promise<T | null>\n /** Reset form to initial values */\n reset: () => void\n /** Go to next step */\n nextStep: () => void\n /** Go to previous step */\n prevStep: () => void\n}\n\n/**\n * React hook that wraps FormBuilder and provides form state management\n *\n * @param options - Hook options including FormBuilder instance\n * @returns Form state and methods\n *\n * @example\n * ```tsx\n * const builder = new FormBuilder<{ name: string }>()\n * .addField({ name: 'name', type: 'text', label: 'Name' })\n * .build();\n *\n * function MyForm() {\n * const form = useFormBuilder({ builder });\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); form.submit(); }}>\n * <input\n * value={form.values.name}\n * onChange={(e) => form.setFieldValue('name', e.target.value)}\n * />\n * {form.errors.name && <span>{form.errors.name}</span>}\n * <button type=\"submit\">Submit</button>\n * </form>\n * );\n * }\n * ```\n */\nexport function useFormBuilder<T extends Record<string, any>>(\n options: UseFormBuilderOptions<T>\n): UseFormBuilderReturn<T> {\n const { builder } = options\n\n if (!builder) {\n throw new Error('useFormBuilder: builder is required')\n }\n\n // Subscribe to form state\n const [state, setState] = useState(() => builder.currentState)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n useEffect(() => {\n if (!builder || !builder.state$) {\n return\n }\n\n const subscription = builder.state$.subscribe((newState: any) => {\n setState(newState)\n })\n\n return () => subscription.unsubscribe()\n }, [builder])\n\n const memoizedReturn = useMemo(() => ({\n values: state.values,\n errors: state.errors,\n touched: state.touched,\n currentStep: 0, // Multi-step requires MultiStepFormBuilder\n totalSteps: 1, // Multi-step requires MultiStepFormBuilder\n isSubmitting,\n isValid: Object.keys(state.errors).length === 0,\n\n setFieldValue: async (field: keyof T, value: any) => {\n builder.setFieldValue(field as string, value)\n },\n\n setFieldTouched: (field: keyof T, touched: boolean) => {\n builder.setFieldTouched(field as string, touched)\n },\n\n validate: async () => {\n return builder.validate()\n },\n\n submit: async () => {\n setIsSubmitting(true)\n try {\n await builder.submit()\n setIsSubmitting(false)\n return null\n } catch (error) {\n setIsSubmitting(false)\n throw error\n }\n },\n\n reset: () => {\n builder.reset()\n },\n\n nextStep: () => {\n // Multi-step forms use MultiStepFormBuilder, not FormBuilder\n console.warn('nextStep() is only available on MultiStepFormBuilder')\n },\n\n prevStep: () => {\n // Multi-step forms use MultiStepFormBuilder, not FormBuilder\n console.warn('prevStep() is only available on MultiStepFormBuilder')\n },\n }), [builder, state, isSubmitting])\n\n return memoizedReturn\n}\n","import { FC, ReactNode, createContext, useContext, useEffect, useState } from 'react';\n\nimport type { IAuthProvider } from '@codella-software/utils';\nimport {\n LiveUpdateService,\n SSEService,\n WebsocketService,\n type EventMapping,\n type LiveUpdateType,\n} from '@codella-software/utils/live-updates';\n\nexport interface LiveUpdateContextValue {\n service: LiveUpdateService;\n isConnected: boolean;\n type: LiveUpdateType;\n canSend: boolean;\n}\n\nconst LiveUpdateContext = createContext<LiveUpdateContextValue | null>(null);\n\n/**\n * Hook to access the LiveUpdateContext\n * Must be used within a LiveUpdateProvider\n */\nexport const useLiveUpdateContext = () => {\n const context = useContext(LiveUpdateContext);\n if (!context) {\n throw new Error('useLiveUpdateContext must be used within LiveUpdateProvider');\n }\n return context;\n};\n\nexport interface LiveUpdateProviderProps {\n children: ReactNode;\n authProvider: IAuthProvider;\n sseUrl?: string;\n wsUrl?: string;\n sseEnabled?: boolean;\n wsEnabled?: boolean;\n eventMappings?: Record<string, EventMapping>;\n}\n\n/**\n * Provider component for live updates service\n * Manages service initialization and connection state\n * \n * @example\n * ```tsx\n * import { LiveUpdateProvider } from '@codella/react';\n * import { createFirebaseAuthProvider } from '@codella-software/utils';\n * \n * function App() {\n * const authProvider = createFirebaseAuthProvider({ auth: getAuth() });\n * \n * return (\n * <LiveUpdateProvider\n * authProvider={authProvider}\n * sseUrl=\"http://api.example.com/sse\"\n * wsUrl=\"ws://api.example.com/ws\"\n * eventMappings={{\n * 'notifications': { sseEvent: 'GET_NOTIFICATIONS' }\n * }}\n * >\n * <YourApp />\n * </LiveUpdateProvider>\n * );\n * }\n * ```\n */\nexport const LiveUpdateProvider: FC<LiveUpdateProviderProps> = ({\n children,\n authProvider,\n sseUrl = 'http://localhost:3000/sse',\n wsUrl = 'ws://localhost:3000/ws',\n sseEnabled = true,\n wsEnabled = true,\n eventMappings = {},\n}) => {\n const [isConnected, setIsConnected] = useState(false);\n const [service] = useState(() => {\n const sseService = new SSEService({\n url: sseUrl,\n authProvider,\n });\n\n const wsService = new WebsocketService({\n url: wsUrl,\n authProvider,\n });\n\n return new LiveUpdateService(wsService, sseService);\n });\n\n useEffect(() => {\n if (authProvider.isAuthenticated()) {\n service.initialize({\n sseEnabled,\n wsEnabled,\n authProvider,\n eventMappings,\n });\n } else {\n service.disconnect();\n }\n\n const subscription = service.isConnected$.subscribe(setIsConnected);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [authProvider, sseEnabled, wsEnabled, service, eventMappings]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n service.disconnect();\n };\n }, [service]);\n\n return (\n <LiveUpdateContext.Provider\n value={{\n service,\n isConnected,\n type: service.type,\n canSend: service.canSend,\n }}\n >\n {children}\n </LiveUpdateContext.Provider>\n );\n};\n","import { useEffect, useState } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook to listen for specific WebSocket actions\n * @param action - The WS_ACTIONS enum value to listen for\n * @param enabled - Whether to subscribe (defaults to true)\n * @returns The latest message payload or null\n */\nexport const useLiveListener = <T = unknown>(action: WS_ACTIONS, enabled = true) => {\n const { service } = useLiveUpdateContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!enabled || !service) {\n return;\n }\n\n const subscription = service.on(action).subscribe({\n next: (value) => {\n setData(value);\n setError(null);\n },\n error: (err) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [action, enabled, service]);\n\n return { data, error };\n};\n","import { useCallback } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook for request-response pattern over WebSocket\n * @param sendAction - The action to send\n * @param responseAction - The action to wait for\n * @returns Function to send request and promise for response\n */\nexport const useLiveRequest = <TReq = unknown, TRes = unknown>() => {\n const { service, canSend } = useLiveUpdateContext();\n\n const request = useCallback(\n (sendAction: WS_ACTIONS, responseAction: WS_ACTIONS, payload?: TReq) => {\n if (!canSend) {\n return Promise.reject(new Error('WebSocket not available for sending'));\n }\n\n return service\n .on(responseAction)\n .toPromise()\n .catch(() => {\n throw new Error(`No response received for action: ${responseAction}`);\n });\n },\n [canSend, service],\n );\n\n return { request, canSend };\n};\n","import { useCallback } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\nexport interface UseUpdateListenerOptions {\n enabled?: boolean;\n}\n\n/**\n * Hook to listen for and handle live updates with callback\n * @param action - The WS_ACTIONS enum value to listen for\n * @param onUpdate - Callback when update is received\n * @param enabled - Whether to subscribe (defaults to true)\n */\nexport const useLiveUpdateListener = <T = unknown>(\n action: WS_ACTIONS,\n onUpdate: (data: T) => void,\n { enabled = true }: UseUpdateListenerOptions = {},\n) => {\n const { service } = useLiveUpdateContext();\n\n const handleUpdate = useCallback(\n (data: T) => {\n onUpdate(data);\n },\n [onUpdate],\n );\n\n // Subscribe to updates\n // The subscription is managed by the effect in the hook\n // Users need to call subscribe manually or use useLiveListener instead\n const subscribe = useCallback(() => {\n if (!enabled || !service) {\n return () => {};\n }\n\n const subscription = service.on(action).subscribe(handleUpdate);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [action, enabled, service, handleUpdate]);\n\n return { subscribe };\n};\n","import { useEffect, useState } from 'react';\n\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook to subscribe to live update events\n * @param eventName - The event name (must be mapped in LiveUpdateProvider.eventMappings)\n * @returns The latest event data or null\n */\nexport const useLiveUpdates = <T = unknown>(eventName: string) => {\n const { service } = useLiveUpdateContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!service) {\n return;\n }\n\n const subscription = service.on(eventName).subscribe({\n next: (value) => {\n setData(value);\n setError(null);\n },\n error: (err) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [eventName, service]);\n\n return { data, error };\n};\n","/**\n * React hook for RichContentService\n */\n\nimport {\n ContentEditableAdapter,\n DocumentNode,\n MarkType,\n RichContentConfig,\n RichContentService,\n RichContentState,\n Selection,\n} from '@codella-software/utils/rich-content';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\n/**\n * Hook options for useRichContent\n */\nexport interface UseRichContentOptions extends RichContentConfig {\n /** DOM element ref for contentEditable */\n editorRef?: React.RefObject<HTMLElement>;\n /** Custom adapter instance */\n adapter?: ContentEditableAdapter;\n}\n\n/**\n * Hook return value for useRichContent\n */\nexport interface UseRichContentReturn {\n /** Service instance */\n service: RichContentService;\n /** Current document content */\n content: DocumentNode;\n /** Full state object */\n state: RichContentState;\n /** Current editor focus state */\n isFocused: boolean;\n /** Can undo */\n canUndo: boolean;\n /** Can redo */\n canRedo: boolean;\n /** Active mark types */\n selectedFormats: Set<MarkType>;\n /** Current selection */\n selection: Selection | null;\n /** Is dirty (has unsaved changes) */\n isDirty: boolean;\n\n // Commands\n /** Insert text */\n insertText: (text: string) => void;\n /** Insert paragraph */\n insertParagraph: () => void;\n /** Insert heading */\n insertHeading: (level: 1 | 2 | 3 | 4 | 5 | 6) => void;\n /** Insert image */\n insertImage: (url: string) => void;\n /** Upload image file */\n uploadImage: (file: File) => Promise<void>;\n /** Insert mention */\n insertMention: (id: string, label: string) => void;\n /** Insert list */\n insertList: (type: 'ordered' | 'unordered') => void;\n /** Toggle mark */\n toggleMark: (mark: MarkType) => void;\n /** Delete content */\n deleteContent: () => void;\n /** Undo */\n undo: () => void;\n /** Redo */\n redo: () => void;\n /** Clear history */\n clearHistory: () => void;\n /** Focus editor */\n focus: () => void;\n /** Set focus state */\n setFocus: (focused: boolean) => void;\n /** Get plain text */\n getPlainText: () => string;\n /** Set selection */\n setSelection: (selection: Selection | null) => void;\n}\n\n/**\n * React hook that wraps RichContentService and manages state subscriptions\n */\nexport function useRichContent(options: UseRichContentOptions = {}): UseRichContentReturn {\n // Create service instance\n const service = useMemo(() => RichContentService.create(options), []);\n\n // State from service\n const [content, setContent] = useState<DocumentNode>(service.getContent());\n const [state, setState] = useState<RichContentState>(service.getState());\n const [isFocused, setIsFocused] = useState(false);\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n const [selectedFormats, setSelectedFormats] = useState<Set<MarkType>>(new Set());\n\n // Subscriptions\n useEffect(() => {\n if (!service) {\n return\n }\n\n const contentSub = service.getContent$().subscribe(setContent);\n const stateSub = service.getState$().subscribe((newState) => {\n setState(newState);\n setIsFocused(newState.isFocused);\n setCanUndo(newState.canUndo);\n setCanRedo(newState.canRedo);\n setSelectedFormats(newState.selectedFormats || new Set());\n });\n\n return () => {\n contentSub.unsubscribe();\n stateSub.unsubscribe();\n };\n }, [service]);\n\n // Attach adapter if provided\n useEffect(() => {\n if (options.adapter) {\n service.attachAdapter(options.adapter);\n return () => service.detachAdapter();\n }\n }, [options.adapter, service]);\n\n // Setup default adapter if editorRef provided\n const defaultAdapterRef = useRef<ContentEditableAdapter | null>(null);\n\n useEffect(() => {\n if (options.editorRef?.current && !options.adapter && !defaultAdapterRef.current) {\n const { DefaultContentEditableAdapter } = require('@codella-software/utils/rich-content');\n const adapter = new DefaultContentEditableAdapter();\n adapter.mount(options.editorRef.current);\n service.attachAdapter(adapter);\n defaultAdapterRef.current = adapter;\n\n return () => {\n adapter.unmount();\n service.detachAdapter();\n defaultAdapterRef.current = null;\n };\n }\n }, [options.editorRef, options.adapter, service]);\n\n // Command callbacks\n const insertText = useCallback((text: string) => service.insertText(text), [service]);\n const insertParagraph = useCallback(() => service.insertParagraph(), [service]);\n const insertHeading = useCallback((level: any) => service.insertHeading(level), [service]);\n const insertImage = useCallback((url: string) => service.insertImage(url), [service]);\n const uploadImage = useCallback((file: File) => service.uploadImage(file), [service]);\n const insertMention = useCallback((id: string, label: string) => service.insertMention(id, label), [service]);\n const insertList = useCallback((type: 'ordered' | 'unordered') => service.insertList(type), [service]);\n const toggleMark = useCallback((mark: MarkType) => service.toggleMark(mark), [service]);\n const deleteContent = useCallback(() => service.deleteContent(), [service]);\n const undo = useCallback(() => service.undo(), [service]);\n const redo = useCallback(() => service.redo(), [service]);\n const clearHistory = useCallback(() => service.clearHistory(), [service]);\n const focus = useCallback(() => service.getAdapter()?.focus(), [service]);\n const setFocus = useCallback((focused: boolean) => service.setFocus(focused), [service]);\n const getPlainText = useCallback(() => service.getPlainText(), [service]);\n const setSelection = useCallback((sel: Selection | null) => service.setSelection(sel), [service]);\n\n return {\n service,\n content,\n state,\n isFocused,\n canUndo,\n canRedo,\n selectedFormats,\n selection: state.selection || null,\n isDirty: state.isDirty,\n\n insertText,\n insertParagraph,\n insertHeading,\n insertImage,\n uploadImage,\n insertMention,\n insertList,\n toggleMark,\n deleteContent,\n undo,\n redo,\n clearHistory,\n focus,\n setFocus,\n getPlainText,\n setSelection,\n };\n}\n","/**\n * @deprecated TableBuilder is a configuration builder, not a stateful service.\n * \n * For reactive table state management, use FiltersAndSortService instead:\n * \n * @example\n * ```tsx\n * import { createFiltersAndSortService } from '@codella-software/utils';\n * import { useFiltersAndSort } from '@codella-software/react';\n * \n * const service = createFiltersAndSortService({\n * storageKey: 'my-table',\n * initialState: { pagination: { page: 0, limit: 10 } }\n * });\n * \n * function MyTable() {\n * const { page, pageSize, filters, setFilter, setPage } = useFiltersAndSort({ service });\n * \n * // Fetch data with current state\n * const { data } = useQuery({\n * queryKey: ['data', page, pageSize, filters],\n * queryFn: () => fetchData({ page, pageSize, ...filters })\n * });\n * \n * // Build table config\n * const tableConfig = createTableBuilder()\n * .data(data?.items ?? [])\n * .totalRows(data?.total ?? 0)\n * .columns([...])\n * .filtersAndSort(service.getCurrentState(), service.getActions())\n * .build();\n * \n * return <DynamicTable config={tableConfig} />;\n * }\n * ```\n */\nexport function useTableService() {\n throw new Error(\n 'useTableService is deprecated. TableBuilder is a configuration builder, not a stateful service. ' +\n 'Use FiltersAndSortService with useFiltersAndSort hook for reactive state management. ' +\n 'See documentation: https://github.com/CodellaSoftware/codella-utils'\n );\n}\n","import type { TabChangeEvent, TabsConfig } from '@codella-software/utils/tabs';\nimport { TabsService } from '@codella-software/utils/tabs';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\ninterface TabsContextValue {\n service: TabsService;\n activeTabId: string;\n tabs: ReturnType<TabsService['getTabs']>;\n}\n\nconst TabsContext = createContext<TabsContextValue | undefined>(undefined);\n\n/**\n * Props for TabsProvider\n */\nexport interface TabsProviderProps {\n config: TabsConfig;\n children: React.ReactNode;\n}\n\n/**\n * Tabs provider for React\n */\nexport function TabsProvider({ config, children }: TabsProviderProps) {\n const [service] = useState(() => new TabsService(config));\n const [activeTabId, setActiveTabId] = useState(() => service.getActiveTabId());\n const [tabs, setTabs] = useState(() => service.getTabs());\n\n useEffect(() => {\n const activeTabSubscription = service.getActiveTabId$().subscribe(setActiveTabId);\n const tabsSubscription = service.getTabs$().subscribe(setTabs);\n\n return () => {\n activeTabSubscription.unsubscribe();\n tabsSubscription.unsubscribe();\n };\n }, [service]);\n\n useEffect(() => {\n return () => {\n service.destroy();\n };\n }, [service]);\n\n return (\n <TabsContext.Provider value={{ service, activeTabId, tabs }}>\n {children}\n </TabsContext.Provider>\n );\n}\n\n/**\n * Hook to access tabs service from context\n */\nexport function useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error('useTabsContext must be used within a TabsProvider');\n }\n return context;\n}\n\n/**\n * Hook to use tabs service directly\n */\nexport function useTabsService() {\n const { service } = useTabsContext();\n return service;\n}\n\n/**\n * Hook to get active tab\n */\nexport function useActiveTab() {\n const { service } = useTabsContext();\n const [activeTab, setActiveTab] = useState(() => service.getActiveTab());\n\n useEffect(() => {\n const subscription = service.getActiveTab$().subscribe(setActiveTab);\n return () => subscription.unsubscribe();\n }, [service]);\n\n return activeTab;\n}\n\n/**\n * Hook to get all tabs\n */\nexport function useTabs() {\n const { tabs } = useTabsContext();\n return tabs;\n}\n\n/**\n * Hook to listen to tab changes\n */\nexport function useTabChange() {\n const { service } = useTabsContext();\n const [changeEvent, setChangeEvent] = useState<TabChangeEvent | null>(null);\n\n useEffect(() => {\n const subscription = service.onTabChange$().subscribe(setChangeEvent);\n return () => subscription.unsubscribe();\n }, [service]);\n\n return changeEvent;\n}\n\n/**\n * Hook to set active tab\n */\nexport function useSetActiveTab() {\n const { service } = useTabsContext();\n return {\n setActiveTab: (tabId: string) => service.setActiveTab(tabId),\n setActiveTabByIndex: (index: number) => service.setActiveTabByIndex(index),\n nextTab: () => service.nextTab(),\n previousTab: () => service.previousTab(),\n };\n}\n"],"names":["useState","useEffect","useMemo","createContext","useContext","SSEService","WebsocketService","LiveUpdateService","jsx","useCallback","RichContentService","useRef","TabsService","tabs"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/filters-and-sort/useFiltersAndSort.ts","../src/form-builder/useFormBuilder.ts","../src/live-updates/LiveUpdateProvider.tsx","../src/live-updates/useLiveListener.ts","../src/live-updates/useLiveRequest.ts","../src/live-updates/useLiveUpdateListener.ts","../src/live-updates/useLiveUpdates.ts","../src/rich-content/useRichContent.ts","../src/tabs/useTabsHooks.tsx"],"sourcesContent":["import { FiltersAndSortService, type FilterAndSortState, type SortDirection } from '@codella-software/utils'\nimport { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\n\n/**\n * Configuration for creating a new FiltersAndSortService instance\n */\nexport interface FiltersAndSortConfig<T extends Record<string, any> = Record<string, any>> {\n /** Unique storage key for persistence */\n storageKey: string\n /** Whether to persist state to storage (default: true) */\n persistToStorage?: boolean\n /** Initial state override */\n initialState?: Partial<FilterAndSortState<T>>\n /** Default filter values used when clearing filters */\n defaultFilters?: T\n /** Skip hydrating state from storage on init */\n skipStorageHydration?: boolean\n /** Debounce time for storage persistence in ms (default: 300) */\n storageDebounceMs?: number\n /** Optional storage key prefix */\n storageKeyPrefix?: string\n}\n\n/**\n * Hook options for useFiltersAndSort\n */\nexport interface UseFiltersAndSortOptions<T extends Record<string, any> = Record<string, any>> {\n /** An existing FiltersAndSortService instance to use */\n service?: FiltersAndSortService<T>\n /** Configuration to create a new service instance (mutually exclusive with service) */\n config?: FiltersAndSortConfig<T>\n /** Enable debug logging */\n debug?: boolean\n /** Custom equality function for state comparison */\n isEqual?: (prev: FilterAndSortState<T>, next: FilterAndSortState<T>) => boolean\n}\n\n/**\n * Hook return value for useFiltersAndSort\n */\nexport interface UseFiltersAndSortReturn<T extends Record<string, any> = Record<string, any>> {\n // State\n /** Current filter state */\n filters: T\n /** Current sort field */\n sortBy: string | null\n /** Current sort direction */\n sortDirection: SortDirection\n /** Current page (0-based) */\n page: number\n /** Page size */\n pageSize: number\n /** Current search query */\n query: string\n /** Full state object for advanced use cases */\n state: FilterAndSortState<T>\n\n // Filter actions\n /** Set a single filter value */\n setFilter: <K extends keyof T>(key: K, value: T[K]) => void\n /** Set multiple filters at once */\n setFilters: (filters: Partial<T>) => void\n /** Clear a specific filter */\n clearFilter: <K extends keyof T>(key: K) => void\n /** Clear all filters (resets to defaultFilters) */\n clearAllFilters: () => void\n /** Check if a specific filter is active */\n hasFilter: <K extends keyof T>(key: K) => boolean\n /** Check if any filters are active */\n hasAnyFilters: () => boolean\n /** Get count of active filters */\n activeFilterCount: number\n\n // Sort actions\n /** Set/toggle sort (auto-toggles between asc -> desc -> none) */\n setSort: (field: string) => void\n /** Toggle sort direction for field (alias for setSort) */\n toggleSort: (field: string) => void\n /** Clear current sort */\n clearSort: () => void\n /** Check if a field is currently sorted */\n isSortedBy: (field: string) => boolean\n\n // Pagination actions\n /** Set page */\n setPage: (page: number) => void\n /** Set page size (resets to page 0) */\n setPageSize: (size: number) => void\n /** Set both page and pageSize atomically */\n setPagination: (page: number, size?: number) => void\n /** Go to next page */\n nextPage: () => void\n /** Go to previous page */\n prevPage: () => void\n /** Go to first page */\n firstPage: () => void\n /** Check if on first page */\n isFirstPage: boolean\n /** Calculate offset for API requests */\n offset: number\n\n // Query actions\n /** Set search query */\n setQuery: (query: string) => void\n /** Clear search query */\n clearQuery: () => void\n\n // General actions\n /** Reset to initial state */\n reset: () => void\n /** Clear storage and reset */\n clearStorageAndReset: () => void\n /** Get the storage key being used */\n storageKey: string\n\n // Service access\n /** Direct access to the underlying service (for advanced use cases) */\n getService: () => FiltersAndSortService<T>\n}\n\n/**\n * Default shallow equality check for filter state\n */\nfunction defaultIsEqual<T>(prev: FilterAndSortState<T>, next: FilterAndSortState<T>): boolean {\n if (prev === next) return true\n\n // Quick reference equality checks\n if (prev.query !== next.query) return false\n if (prev.pagination.page !== next.pagination.page) return false\n if (prev.pagination.limit !== next.pagination.limit) return false\n\n // Sort comparison\n const prevSort = prev.sort\n const nextSort = next.sort\n if (prevSort?.fieldName !== nextSort?.fieldName) return false\n if (prevSort?.direction !== nextSort?.direction) return false\n\n // Shallow filter comparison\n const prevFilters = prev.filters as Record<string, unknown>\n const nextFilters = next.filters as Record<string, unknown>\n const prevKeys = Object.keys(prevFilters)\n const nextKeys = Object.keys(nextFilters)\n\n if (prevKeys.length !== nextKeys.length) return false\n\n for (const key of prevKeys) {\n if (prevFilters[key] !== nextFilters[key]) return false\n }\n\n return true\n}\n\n/**\n * Count active filters (non-null, non-undefined, non-empty string values)\n */\nfunction countActiveFilters<T extends Record<string, unknown>>(filters: T, defaultFilters?: T): number {\n let count = 0\n const keys = Object.keys(filters as Record<string, unknown>) as Array<keyof T>\n for (const key of keys) {\n const value = filters[key]\n const defaultValue = defaultFilters?.[key]\n const isDefault = value === defaultValue\n const isEmpty = value === null || value === undefined || value === ''\n const isEmptyArray = Array.isArray(value) && value.length === 0\n\n if (!isEmpty && !isEmptyArray && !isDefault) {\n count++\n }\n }\n return count\n}\n\n/**\n * React hook that wraps FiltersAndSortService with enhanced functionality\n *\n * @typeParam T - The filters object type\n * @param options - Hook options including service instance or config\n * @returns Filters and sort state with control methods\n *\n * @example\n * ```tsx\n * // Option 1: Create service externally (recommended for sharing between components)\n * const service = new FiltersAndSortService<MyFilters>({ storageKey: 'my-filters' });\n *\n * function MyTable() {\n * const {\n * filters,\n * setFilter,\n * clearAllFilters,\n * hasAnyFilters,\n * activeFilterCount\n * } = useFiltersAndSort({ service });\n *\n * return (\n * <div>\n * <input\n * value={filters.name || ''}\n * onChange={(e) => setFilter('name', e.target.value)}\n * />\n * {hasAnyFilters() && (\n * <button onClick={clearAllFilters}>\n * Clear ({activeFilterCount})\n * </button>\n * )}\n * </div>\n * );\n * }\n *\n * // Option 2: Let the hook create the service (simpler for single-component use)\n * function SimpleTable() {\n * const filters = useFiltersAndSort({\n * config: {\n * storageKey: 'simple-table',\n * defaultFilters: { status: 'all' }\n * }\n * });\n * // ...\n * }\n * ```\n */\nexport function useFiltersAndSort<T extends Record<string, any> = Record<string, any>>(\n options: UseFiltersAndSortOptions<T>\n): UseFiltersAndSortReturn<T> {\n const { service: externalService, config, debug = false, isEqual = defaultIsEqual } = options\n\n // Validate options\n if (!externalService && !config) {\n throw new Error(\n 'useFiltersAndSort: either `service` or `config` must be provided. ' +\n 'Pass an existing FiltersAndSortService instance via `service`, or ' +\n 'provide a `config` object to create a new service.'\n )\n }\n\n if (externalService && config) {\n if (debug) {\n console.warn(\n 'useFiltersAndSort: both `service` and `config` were provided. ' +\n 'The `service` will be used and `config` will be ignored.'\n )\n }\n }\n\n // Track if we own the service (created it ourselves)\n const ownsServiceRef = useRef(false)\n const serviceRef = useRef<FiltersAndSortService<T> | null>(null)\n const isEqualRef = useRef(isEqual)\n\n // Keep isEqual ref updated\n useEffect(() => {\n isEqualRef.current = isEqual\n }, [isEqual])\n\n // Initialize service (only once)\n if (!serviceRef.current) {\n if (externalService) {\n serviceRef.current = externalService\n ownsServiceRef.current = false\n } else if (config) {\n serviceRef.current = new FiltersAndSortService<T>({\n storageKey: config.storageKey,\n persistToStorage: config.persistToStorage,\n initialState: config.initialState,\n defaultFilters: config.defaultFilters,\n skipStorageHydration: config.skipStorageHydration,\n storageDebounceMs: config.storageDebounceMs,\n storageKeyPrefix: config.storageKeyPrefix,\n })\n ownsServiceRef.current = true\n\n if (debug) {\n console.log(`useFiltersAndSort: created service with key \"${config.storageKey}\"`)\n }\n }\n }\n\n const svc = serviceRef.current!\n\n // Get default filters for active filter counting\n const defaultFiltersRef = useRef<T | undefined>(config?.defaultFilters)\n\n // Use useSyncExternalStore for better concurrent mode support\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n const subscription = svc.getState().subscribe(() => {\n onStoreChange()\n })\n return () => subscription.unsubscribe()\n },\n [svc]\n )\n\n const getSnapshot = useCallback(() => svc.getCurrentState(), [svc])\n\n // For SSR - return initial state\n const getServerSnapshot = useCallback(() => svc.getDefaultState(), [svc])\n\n const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n\n // Debug logging\n useEffect(() => {\n if (!debug) return\n\n const sub = svc.getState().subscribe((newState) => {\n console.log(`useFiltersAndSort [${svc.getStorageKey()}]:`, newState)\n })\n return () => sub.unsubscribe()\n }, [svc, debug])\n\n // Cleanup owned service on unmount\n useEffect(() => {\n return () => {\n if (ownsServiceRef.current && serviceRef.current) {\n if (debug) {\n console.log(`useFiltersAndSort: destroying owned service \"${serviceRef.current.getStorageKey()}\"`)\n }\n serviceRef.current.destroy()\n serviceRef.current = null\n }\n }\n }, [debug])\n\n // Stable callback references using useCallback\n const setFilter = useCallback(\n <K extends keyof T>(key: K, value: T[K]) => {\n svc.setFilters({ [key]: value } as unknown as Partial<T>)\n },\n [svc]\n )\n\n const setFilters = useCallback(\n (filters: Partial<T>) => {\n svc.setFilters(filters)\n },\n [svc]\n )\n\n const clearFilter = useCallback(\n <K extends keyof T>(key: K) => {\n svc.removeFilter(key)\n },\n [svc]\n )\n\n const clearAllFilters = useCallback(() => {\n svc.clearFilters()\n }, [svc])\n\n const hasFilter = useCallback(\n <K extends keyof T>(key: K): boolean => {\n const value = svc.getCurrentState().filters[key]\n const defaultValue = defaultFiltersRef.current?.[key]\n if (value === defaultValue) return false\n if (value === null || value === undefined || value === '') return false\n if (Array.isArray(value) && value.length === 0) return false\n return true\n },\n [svc]\n )\n\n const hasAnyFilters = useCallback((): boolean => {\n return countActiveFilters(svc.getCurrentState().filters, defaultFiltersRef.current) > 0\n }, [svc])\n\n const setSort = useCallback(\n (field: string) => {\n svc.setSort(field)\n },\n [svc]\n )\n\n const clearSort = useCallback(() => {\n svc.setSort('')\n }, [svc])\n\n const isSortedBy = useCallback(\n (field: string): boolean => {\n return svc.getCurrentState().sort?.fieldName === field\n },\n [svc]\n )\n\n const setPage = useCallback(\n (page: number) => {\n if (page < 0) {\n if (debug) {\n console.warn('useFiltersAndSort: setPage called with negative value, clamping to 0')\n }\n page = 0\n }\n svc.setPagination(page)\n },\n [svc, debug]\n )\n\n const setPageSize = useCallback(\n (size: number) => {\n if (size < 1) {\n if (debug) {\n console.warn('useFiltersAndSort: setPageSize called with value < 1, clamping to 1')\n }\n size = 1\n }\n // Reset to page 0 when changing page size to avoid out-of-bounds\n svc.setPagination(0, size)\n },\n [svc, debug]\n )\n\n const setPagination = useCallback(\n (page: number, size?: number) => {\n if (page < 0) {\n if (debug) {\n console.warn('useFiltersAndSort: setPagination called with negative page, clamping to 0')\n }\n page = 0\n }\n if (size !== undefined && size < 1) {\n if (debug) {\n console.warn('useFiltersAndSort: setPagination called with size < 1, clamping to 1')\n }\n size = 1\n }\n svc.setPagination(page, size)\n },\n [svc, debug]\n )\n\n const nextPage = useCallback(() => {\n svc.setPagination(svc.getCurrentState().pagination.page + 1)\n }, [svc])\n\n const prevPage = useCallback(() => {\n const newPage = Math.max(0, svc.getCurrentState().pagination.page - 1)\n svc.setPagination(newPage)\n }, [svc])\n\n const firstPage = useCallback(() => {\n svc.setPagination(0)\n }, [svc])\n\n const setQuery = useCallback(\n (query: string) => {\n svc.setQuery(query)\n },\n [svc]\n )\n\n const clearQuery = useCallback(() => {\n svc.setQuery('')\n }, [svc])\n\n const reset = useCallback(() => {\n svc.reset()\n }, [svc])\n\n const clearStorageAndReset = useCallback(() => {\n svc.clearStorage()\n svc.reset()\n }, [svc])\n\n const getService = useCallback(() => svc, [svc])\n\n // Derived values\n const activeFilterCount = useMemo(\n () => countActiveFilters(state.filters, defaultFiltersRef.current),\n [state.filters]\n )\n\n const isFirstPage = state.pagination.page === 0\n const offset = state.pagination.page * state.pagination.limit\n\n // Memoize the return object to prevent unnecessary re-renders\n return useMemo(\n () => ({\n // State\n filters: state.filters,\n sortBy: state.sort?.fieldName ?? null,\n sortDirection: state.sort?.direction ?? 'asc',\n page: state.pagination.page,\n pageSize: state.pagination.limit,\n query: state.query,\n state,\n\n // Filter actions\n setFilter,\n setFilters,\n clearFilter,\n clearAllFilters,\n hasFilter,\n hasAnyFilters,\n activeFilterCount,\n\n // Sort actions\n setSort,\n toggleSort: setSort,\n clearSort,\n isSortedBy,\n\n // Pagination actions\n setPage,\n setPageSize,\n setPagination,\n nextPage,\n prevPage,\n firstPage,\n isFirstPage,\n offset,\n\n // Query actions\n setQuery,\n clearQuery,\n\n // General actions\n reset,\n clearStorageAndReset,\n storageKey: svc.getStorageKey(),\n\n // Service access\n getService,\n }),\n [\n state,\n setFilter,\n setFilters,\n clearFilter,\n clearAllFilters,\n hasFilter,\n hasAnyFilters,\n activeFilterCount,\n setSort,\n clearSort,\n isSortedBy,\n setPage,\n setPageSize,\n setPagination,\n nextPage,\n prevPage,\n firstPage,\n isFirstPage,\n offset,\n setQuery,\n clearQuery,\n reset,\n clearStorageAndReset,\n svc,\n getService,\n ]\n )\n}\n\n/**\n * Convenience hook for creating a filters service with simpler API\n * Equivalent to useFiltersAndSort({ config: ... })\n */\nexport function useFilters<T extends Record<string, any> = Record<string, any>>(\n storageKey: string,\n options?: Omit<FiltersAndSortConfig<T>, 'storageKey'>\n): UseFiltersAndSortReturn<T> {\n return useFiltersAndSort<T>({\n config: {\n storageKey,\n ...options,\n },\n })\n}\n\nexport type { FilterAndSortState, SortDirection }\n","// React hook for FormBuilder with proper state management\nimport { FormBuilder } from '@codella-software/utils'\nimport { useEffect, useMemo, useState } from 'react'\n\n/**\n * Hook options for useFormBuilder\n */\nexport interface UseFormBuilderOptions<T extends Record<string, any>> {\n /** FormBuilder instance */\n builder: FormBuilder<T>\n}\n\n/**\n * Hook return value for useFormBuilder\n */\nexport interface UseFormBuilderReturn<T extends Record<string, any>> {\n /** Current form values */\n values: T\n /** Form validation errors */\n errors: Record<string, string | undefined>\n /** Form touched fields */\n touched: Record<string, boolean>\n /** Current form step (for multi-step forms) */\n currentStep: number\n /** Total form steps */\n totalSteps: number\n /** Is form currently submitting */\n isSubmitting: boolean\n /** Is form valid */\n isValid: boolean\n /** Set field value */\n setFieldValue: (field: keyof T, value: any) => Promise<void>\n /** Set field touched */\n setFieldTouched: (field: keyof T, touched: boolean) => void\n /** Validate entire form */\n validate: () => Promise<Record<string, string | undefined>>\n /** Submit form */\n submit: () => Promise<T | null>\n /** Reset form to initial values */\n reset: () => void\n /** Go to next step */\n nextStep: () => void\n /** Go to previous step */\n prevStep: () => void\n}\n\n/**\n * React hook that wraps FormBuilder and provides form state management\n *\n * @param options - Hook options including FormBuilder instance\n * @returns Form state and methods\n *\n * @example\n * ```tsx\n * const builder = new FormBuilder<{ name: string }>()\n * .addField({ name: 'name', type: 'text', label: 'Name' })\n * .build();\n *\n * function MyForm() {\n * const form = useFormBuilder({ builder });\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); form.submit(); }}>\n * <input\n * value={form.values.name}\n * onChange={(e) => form.setFieldValue('name', e.target.value)}\n * />\n * {form.errors.name && <span>{form.errors.name}</span>}\n * <button type=\"submit\">Submit</button>\n * </form>\n * );\n * }\n * ```\n */\nexport function useFormBuilder<T extends Record<string, any>>(\n options: UseFormBuilderOptions<T>\n): UseFormBuilderReturn<T> {\n const { builder } = options\n\n if (!builder) {\n throw new Error('useFormBuilder: builder is required')\n }\n\n // Subscribe to form state\n const [state, setState] = useState(() => builder.currentState)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n useEffect(() => {\n if (!builder || !builder.state$) {\n return\n }\n\n const subscription = builder.state$.subscribe((newState: any) => {\n setState(newState)\n })\n\n return () => subscription.unsubscribe()\n }, [builder])\n\n const memoizedReturn = useMemo(() => ({\n values: state.values,\n errors: state.errors,\n touched: state.touched,\n currentStep: 0, // Multi-step requires MultiStepFormBuilder\n totalSteps: 1, // Multi-step requires MultiStepFormBuilder\n isSubmitting,\n isValid: Object.keys(state.errors).length === 0,\n\n setFieldValue: async (field: keyof T, value: any) => {\n builder.setFieldValue(field as string, value)\n },\n\n setFieldTouched: (field: keyof T, touched: boolean) => {\n builder.setFieldTouched(field as string, touched)\n },\n\n validate: async () => {\n return builder.validate()\n },\n\n submit: async () => {\n setIsSubmitting(true)\n try {\n await builder.submit()\n setIsSubmitting(false)\n return null\n } catch (error) {\n setIsSubmitting(false)\n throw error\n }\n },\n\n reset: () => {\n builder.reset()\n },\n\n nextStep: () => {\n // Multi-step forms use MultiStepFormBuilder, not FormBuilder\n console.warn('nextStep() is only available on MultiStepFormBuilder')\n },\n\n prevStep: () => {\n // Multi-step forms use MultiStepFormBuilder, not FormBuilder\n console.warn('prevStep() is only available on MultiStepFormBuilder')\n },\n }), [builder, state, isSubmitting])\n\n return memoizedReturn\n}\n","import { FC, ReactNode, createContext, useContext, useEffect, useState } from 'react';\n\nimport type { IAuthProvider } from '@codella-software/utils';\nimport {\n LiveUpdateService,\n SSEService,\n WebsocketService,\n type EventMapping,\n type LiveUpdateType,\n} from '@codella-software/utils/live-updates';\n\nexport interface LiveUpdateContextValue {\n service: LiveUpdateService;\n isConnected: boolean;\n type: LiveUpdateType;\n canSend: boolean;\n}\n\nconst LiveUpdateContext = createContext<LiveUpdateContextValue | null>(null);\n\n/**\n * Hook to access the LiveUpdateContext\n * Must be used within a LiveUpdateProvider\n */\nexport const useLiveUpdateContext = () => {\n const context = useContext(LiveUpdateContext);\n if (!context) {\n throw new Error('useLiveUpdateContext must be used within LiveUpdateProvider');\n }\n return context;\n};\n\nexport interface LiveUpdateProviderProps {\n children: ReactNode;\n authProvider: IAuthProvider;\n sseUrl?: string;\n wsUrl?: string;\n sseEnabled?: boolean;\n wsEnabled?: boolean;\n eventMappings?: Record<string, EventMapping>;\n}\n\n/**\n * Provider component for live updates service\n * Manages service initialization and connection state\n * \n * @example\n * ```tsx\n * import { LiveUpdateProvider } from '@codella/react';\n * import { createFirebaseAuthProvider } from '@codella-software/utils';\n * \n * function App() {\n * const authProvider = createFirebaseAuthProvider({ auth: getAuth() });\n * \n * return (\n * <LiveUpdateProvider\n * authProvider={authProvider}\n * sseUrl=\"http://api.example.com/sse\"\n * wsUrl=\"ws://api.example.com/ws\"\n * eventMappings={{\n * 'notifications': { sseEvent: 'GET_NOTIFICATIONS' }\n * }}\n * >\n * <YourApp />\n * </LiveUpdateProvider>\n * );\n * }\n * ```\n */\nexport const LiveUpdateProvider: FC<LiveUpdateProviderProps> = ({\n children,\n authProvider,\n sseUrl = 'http://localhost:3000/sse',\n wsUrl = 'ws://localhost:3000/ws',\n sseEnabled = true,\n wsEnabled = true,\n eventMappings = {},\n}) => {\n const [isConnected, setIsConnected] = useState(false);\n const [service] = useState(() => {\n const sseService = new SSEService({\n url: sseUrl,\n authProvider,\n });\n\n const wsService = new WebsocketService({\n url: wsUrl,\n authProvider,\n });\n\n return new LiveUpdateService(wsService, sseService);\n });\n\n useEffect(() => {\n if (authProvider.isAuthenticated()) {\n service.initialize({\n sseEnabled,\n wsEnabled,\n authProvider,\n eventMappings,\n });\n } else {\n service.disconnect();\n }\n\n const subscription = service.isConnected$.subscribe(setIsConnected);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [authProvider, sseEnabled, wsEnabled, service, eventMappings]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n service.disconnect();\n };\n }, [service]);\n\n return (\n <LiveUpdateContext.Provider\n value={{\n service,\n isConnected,\n type: service.type,\n canSend: service.canSend,\n }}\n >\n {children}\n </LiveUpdateContext.Provider>\n );\n};\n","import { useEffect, useState } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook to listen for specific WebSocket actions\n * @param action - The WS_ACTIONS enum value to listen for\n * @param enabled - Whether to subscribe (defaults to true)\n * @returns The latest message payload or null\n */\nexport const useLiveListener = <T = unknown>(action: WS_ACTIONS, enabled = true) => {\n const { service } = useLiveUpdateContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!enabled || !service) {\n return;\n }\n\n const subscription = service.on(action).subscribe({\n next: (value) => {\n setData(value);\n setError(null);\n },\n error: (err) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [action, enabled, service]);\n\n return { data, error };\n};\n","import { useCallback } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook for request-response pattern over WebSocket\n * @param sendAction - The action to send\n * @param responseAction - The action to wait for\n * @returns Function to send request and promise for response\n */\nexport const useLiveRequest = <TReq = unknown, TRes = unknown>() => {\n const { service, canSend } = useLiveUpdateContext();\n\n const request = useCallback(\n (sendAction: WS_ACTIONS, responseAction: WS_ACTIONS, payload?: TReq) => {\n if (!canSend) {\n return Promise.reject(new Error('WebSocket not available for sending'));\n }\n\n return service\n .on(responseAction)\n .toPromise()\n .catch(() => {\n throw new Error(`No response received for action: ${responseAction}`);\n });\n },\n [canSend, service],\n );\n\n return { request, canSend };\n};\n","import { useCallback } from 'react';\n\nimport type { WS_ACTIONS } from '@codella-software/utils/live-updates';\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\nexport interface UseUpdateListenerOptions {\n enabled?: boolean;\n}\n\n/**\n * Hook to listen for and handle live updates with callback\n * @param action - The WS_ACTIONS enum value to listen for\n * @param onUpdate - Callback when update is received\n * @param enabled - Whether to subscribe (defaults to true)\n */\nexport const useLiveUpdateListener = <T = unknown>(\n action: WS_ACTIONS,\n onUpdate: (data: T) => void,\n { enabled = true }: UseUpdateListenerOptions = {},\n) => {\n const { service } = useLiveUpdateContext();\n\n const handleUpdate = useCallback(\n (data: T) => {\n onUpdate(data);\n },\n [onUpdate],\n );\n\n // Subscribe to updates\n // The subscription is managed by the effect in the hook\n // Users need to call subscribe manually or use useLiveListener instead\n const subscribe = useCallback(() => {\n if (!enabled || !service) {\n return () => {};\n }\n\n const subscription = service.on(action).subscribe(handleUpdate);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [action, enabled, service, handleUpdate]);\n\n return { subscribe };\n};\n","import { useEffect, useState } from 'react';\n\nimport { useLiveUpdateContext } from './LiveUpdateProvider';\n\n/**\n * Hook to subscribe to live update events\n * @param eventName - The event name (must be mapped in LiveUpdateProvider.eventMappings)\n * @returns The latest event data or null\n */\nexport const useLiveUpdates = <T = unknown>(eventName: string) => {\n const { service } = useLiveUpdateContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!service) {\n return;\n }\n\n const subscription = service.on(eventName).subscribe({\n next: (value) => {\n setData(value);\n setError(null);\n },\n error: (err) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [eventName, service]);\n\n return { data, error };\n};\n","/**\n * React hook for RichContentService\n */\n\nimport {\n ContentEditableAdapter,\n DocumentNode,\n MarkType,\n RichContentConfig,\n RichContentService,\n RichContentState,\n Selection,\n} from '@codella-software/utils/rich-content';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\n/**\n * Hook options for useRichContent\n */\nexport interface UseRichContentOptions extends RichContentConfig {\n /** DOM element ref for contentEditable */\n editorRef?: React.RefObject<HTMLElement>;\n /** Custom adapter instance */\n adapter?: ContentEditableAdapter;\n}\n\n/**\n * Hook return value for useRichContent\n */\nexport interface UseRichContentReturn {\n /** Service instance */\n service: RichContentService;\n /** Current document content */\n content: DocumentNode;\n /** Full state object */\n state: RichContentState;\n /** Current editor focus state */\n isFocused: boolean;\n /** Can undo */\n canUndo: boolean;\n /** Can redo */\n canRedo: boolean;\n /** Active mark types */\n selectedFormats: Set<MarkType>;\n /** Current selection */\n selection: Selection | null;\n /** Is dirty (has unsaved changes) */\n isDirty: boolean;\n\n // Commands\n /** Insert text */\n insertText: (text: string) => void;\n /** Insert paragraph */\n insertParagraph: () => void;\n /** Insert heading */\n insertHeading: (level: 1 | 2 | 3 | 4 | 5 | 6) => void;\n /** Insert image */\n insertImage: (url: string) => void;\n /** Upload image file */\n uploadImage: (file: File) => Promise<void>;\n /** Insert mention */\n insertMention: (id: string, label: string) => void;\n /** Insert list */\n insertList: (type: 'ordered' | 'unordered') => void;\n /** Toggle mark */\n toggleMark: (mark: MarkType) => void;\n /** Delete content */\n deleteContent: () => void;\n /** Undo */\n undo: () => void;\n /** Redo */\n redo: () => void;\n /** Clear history */\n clearHistory: () => void;\n /** Focus editor */\n focus: () => void;\n /** Set focus state */\n setFocus: (focused: boolean) => void;\n /** Get plain text */\n getPlainText: () => string;\n /** Set selection */\n setSelection: (selection: Selection | null) => void;\n}\n\n/**\n * React hook that wraps RichContentService and manages state subscriptions\n */\nexport function useRichContent(options: UseRichContentOptions = {}): UseRichContentReturn {\n // Create service instance\n const service = useMemo(() => RichContentService.create(options), []);\n\n // State from service\n const [content, setContent] = useState<DocumentNode>(service.getContent());\n const [state, setState] = useState<RichContentState>(service.getState());\n const [isFocused, setIsFocused] = useState(false);\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n const [selectedFormats, setSelectedFormats] = useState<Set<MarkType>>(new Set());\n\n // Subscriptions\n useEffect(() => {\n if (!service) {\n return\n }\n\n const contentSub = service.getContent$().subscribe(setContent);\n const stateSub = service.getState$().subscribe((newState) => {\n setState(newState);\n setIsFocused(newState.isFocused);\n setCanUndo(newState.canUndo);\n setCanRedo(newState.canRedo);\n setSelectedFormats(newState.selectedFormats || new Set());\n });\n\n return () => {\n contentSub.unsubscribe();\n stateSub.unsubscribe();\n };\n }, [service]);\n\n // Attach adapter if provided\n useEffect(() => {\n if (options.adapter) {\n service.attachAdapter(options.adapter);\n return () => service.detachAdapter();\n }\n }, [options.adapter, service]);\n\n // Setup default adapter if editorRef provided\n const defaultAdapterRef = useRef<ContentEditableAdapter | null>(null);\n\n useEffect(() => {\n if (options.editorRef?.current && !options.adapter && !defaultAdapterRef.current) {\n const { DefaultContentEditableAdapter } = require('@codella-software/utils/rich-content');\n const adapter = new DefaultContentEditableAdapter();\n adapter.mount(options.editorRef.current);\n service.attachAdapter(adapter);\n defaultAdapterRef.current = adapter;\n\n return () => {\n adapter.unmount();\n service.detachAdapter();\n defaultAdapterRef.current = null;\n };\n }\n }, [options.editorRef, options.adapter, service]);\n\n // Command callbacks\n const insertText = useCallback((text: string) => service.insertText(text), [service]);\n const insertParagraph = useCallback(() => service.insertParagraph(), [service]);\n const insertHeading = useCallback((level: any) => service.insertHeading(level), [service]);\n const insertImage = useCallback((url: string) => service.insertImage(url), [service]);\n const uploadImage = useCallback((file: File) => service.uploadImage(file), [service]);\n const insertMention = useCallback((id: string, label: string) => service.insertMention(id, label), [service]);\n const insertList = useCallback((type: 'ordered' | 'unordered') => service.insertList(type), [service]);\n const toggleMark = useCallback((mark: MarkType) => service.toggleMark(mark), [service]);\n const deleteContent = useCallback(() => service.deleteContent(), [service]);\n const undo = useCallback(() => service.undo(), [service]);\n const redo = useCallback(() => service.redo(), [service]);\n const clearHistory = useCallback(() => service.clearHistory(), [service]);\n const focus = useCallback(() => service.getAdapter()?.focus(), [service]);\n const setFocus = useCallback((focused: boolean) => service.setFocus(focused), [service]);\n const getPlainText = useCallback(() => service.getPlainText(), [service]);\n const setSelection = useCallback((sel: Selection | null) => service.setSelection(sel), [service]);\n\n return {\n service,\n content,\n state,\n isFocused,\n canUndo,\n canRedo,\n selectedFormats,\n selection: state.selection || null,\n isDirty: state.isDirty,\n\n insertText,\n insertParagraph,\n insertHeading,\n insertImage,\n uploadImage,\n insertMention,\n insertList,\n toggleMark,\n deleteContent,\n undo,\n redo,\n clearHistory,\n focus,\n setFocus,\n getPlainText,\n setSelection,\n };\n}\n","import type { TabChangeEvent, TabsConfig } from '@codella-software/utils/tabs';\nimport { TabsService } from '@codella-software/utils/tabs';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\ninterface TabsContextValue {\n service: TabsService;\n activeTabId: string;\n tabs: ReturnType<TabsService['getTabs']>;\n}\n\nconst TabsContext = createContext<TabsContextValue | undefined>(undefined);\n\n/**\n * Props for TabsProvider\n */\nexport interface TabsProviderProps {\n config: TabsConfig;\n children: React.ReactNode;\n}\n\n/**\n * Tabs provider for React\n */\nexport function TabsProvider({ config, children }: TabsProviderProps) {\n const [service] = useState(() => new TabsService(config));\n const [activeTabId, setActiveTabId] = useState(() => service.getActiveTabId());\n const [tabs, setTabs] = useState(() => service.getTabs());\n\n useEffect(() => {\n const activeTabSubscription = service.getActiveTabId$().subscribe(setActiveTabId);\n const tabsSubscription = service.getTabs$().subscribe(setTabs);\n\n return () => {\n activeTabSubscription.unsubscribe();\n tabsSubscription.unsubscribe();\n };\n }, [service]);\n\n useEffect(() => {\n return () => {\n service.destroy();\n };\n }, [service]);\n\n return (\n <TabsContext.Provider value={{ service, activeTabId, tabs }}>\n {children}\n </TabsContext.Provider>\n );\n}\n\n/**\n * Hook to access tabs service from context\n */\nexport function useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error('useTabsContext must be used within a TabsProvider');\n }\n return context;\n}\n\n/**\n * Hook to use tabs service directly\n */\nexport function useTabsService() {\n const { service } = useTabsContext();\n return service;\n}\n\n/**\n * Hook to get active tab\n */\nexport function useActiveTab() {\n const { service } = useTabsContext();\n const [activeTab, setActiveTab] = useState(() => service.getActiveTab());\n\n useEffect(() => {\n const subscription = service.getActiveTab$().subscribe(setActiveTab);\n return () => subscription.unsubscribe();\n }, [service]);\n\n return activeTab;\n}\n\n/**\n * Hook to get all tabs\n */\nexport function useTabs() {\n const { tabs } = useTabsContext();\n return tabs;\n}\n\n/**\n * Hook to listen to tab changes\n */\nexport function useTabChange() {\n const { service } = useTabsContext();\n const [changeEvent, setChangeEvent] = useState<TabChangeEvent | null>(null);\n\n useEffect(() => {\n const subscription = service.onTabChange$().subscribe(setChangeEvent);\n return () => subscription.unsubscribe();\n }, [service]);\n\n return changeEvent;\n}\n\n/**\n * Hook to set active tab\n */\nexport function useSetActiveTab() {\n const { service } = useTabsContext();\n return {\n setActiveTab: (tabId: string) => service.setActiveTab(tabId),\n setActiveTabByIndex: (index: number) => service.setActiveTabByIndex(index),\n nextTab: () => service.nextTab(),\n previousTab: () => service.previousTab(),\n };\n}\n"],"names":["useRef","useEffect","FiltersAndSortService","useCallback","useSyncExternalStore","useMemo","useState","createContext","useContext","SSEService","WebsocketService","LiveUpdateService","jsx","RichContentService","TabsService","tabs"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -42,6 +42,5 @@ export { useFiltersAndSort, type UseFiltersAndSortOptions, type UseFiltersAndSor
42
42
  export { useFormBuilder, type UseFormBuilderOptions, type UseFormBuilderReturn } from './form-builder';
43
43
  export * from './live-updates';
44
44
  export * from './rich-content';
45
- export { useTableService } from './table-builder';
46
45
  export * from './tabs';
47
46
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AACnH,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACtG,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,cAAc,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AACnH,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACtG,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA"}
package/dist/index.mjs CHANGED
@@ -1,75 +1,315 @@
1
- import { useState, useEffect, useMemo, createContext, useContext, useCallback, useRef } from "react";
1
+ import { FiltersAndSortService } from "@codella-software/utils";
2
+ import { useRef, useEffect, useCallback, useSyncExternalStore, useMemo, useState, createContext, useContext } from "react";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import { SSEService, WebsocketService, LiveUpdateService } from "@codella-software/utils/live-updates";
4
5
  import { RichContentService } from "@codella-software/utils/rich-content";
5
6
  import { TabsService } from "@codella-software/utils/tabs";
7
+ function defaultIsEqual(prev, next) {
8
+ if (prev === next) return true;
9
+ if (prev.query !== next.query) return false;
10
+ if (prev.pagination.page !== next.pagination.page) return false;
11
+ if (prev.pagination.limit !== next.pagination.limit) return false;
12
+ const prevSort = prev.sort;
13
+ const nextSort = next.sort;
14
+ if ((prevSort == null ? void 0 : prevSort.fieldName) !== (nextSort == null ? void 0 : nextSort.fieldName)) return false;
15
+ if ((prevSort == null ? void 0 : prevSort.direction) !== (nextSort == null ? void 0 : nextSort.direction)) return false;
16
+ const prevFilters = prev.filters;
17
+ const nextFilters = next.filters;
18
+ const prevKeys = Object.keys(prevFilters);
19
+ const nextKeys = Object.keys(nextFilters);
20
+ if (prevKeys.length !== nextKeys.length) return false;
21
+ for (const key of prevKeys) {
22
+ if (prevFilters[key] !== nextFilters[key]) return false;
23
+ }
24
+ return true;
25
+ }
26
+ function countActiveFilters(filters, defaultFilters) {
27
+ let count = 0;
28
+ const keys = Object.keys(filters);
29
+ for (const key of keys) {
30
+ const value = filters[key];
31
+ const defaultValue = defaultFilters == null ? void 0 : defaultFilters[key];
32
+ const isDefault = value === defaultValue;
33
+ const isEmpty = value === null || value === void 0 || value === "";
34
+ const isEmptyArray = Array.isArray(value) && value.length === 0;
35
+ if (!isEmpty && !isEmptyArray && !isDefault) {
36
+ count++;
37
+ }
38
+ }
39
+ return count;
40
+ }
6
41
  function useFiltersAndSort(options) {
7
- const { service } = options;
8
- if (!service) {
9
- throw new Error("useFiltersAndSort: service is required");
42
+ const { service: externalService, config, debug = false, isEqual = defaultIsEqual } = options;
43
+ if (!externalService && !config) {
44
+ throw new Error(
45
+ "useFiltersAndSort: either `service` or `config` must be provided. Pass an existing FiltersAndSortService instance via `service`, or provide a `config` object to create a new service."
46
+ );
10
47
  }
11
- const [state, setState] = useState(() => {
12
- return service.getCurrentState();
13
- });
48
+ if (externalService && config) {
49
+ if (debug) {
50
+ console.warn(
51
+ "useFiltersAndSort: both `service` and `config` were provided. The `service` will be used and `config` will be ignored."
52
+ );
53
+ }
54
+ }
55
+ const ownsServiceRef = useRef(false);
56
+ const serviceRef = useRef(null);
57
+ const isEqualRef = useRef(isEqual);
14
58
  useEffect(() => {
15
- if (!service) {
16
- return;
59
+ isEqualRef.current = isEqual;
60
+ }, [isEqual]);
61
+ if (!serviceRef.current) {
62
+ if (externalService) {
63
+ serviceRef.current = externalService;
64
+ ownsServiceRef.current = false;
65
+ } else if (config) {
66
+ serviceRef.current = new FiltersAndSortService({
67
+ storageKey: config.storageKey,
68
+ persistToStorage: config.persistToStorage,
69
+ initialState: config.initialState,
70
+ defaultFilters: config.defaultFilters,
71
+ skipStorageHydration: config.skipStorageHydration,
72
+ storageDebounceMs: config.storageDebounceMs,
73
+ storageKeyPrefix: config.storageKeyPrefix
74
+ });
75
+ ownsServiceRef.current = true;
76
+ if (debug) {
77
+ console.log(`useFiltersAndSort: created service with key "${config.storageKey}"`);
78
+ }
17
79
  }
18
- const subscription = service.getState().subscribe((newState) => {
19
- setState(newState);
80
+ }
81
+ const svc = serviceRef.current;
82
+ const defaultFiltersRef = useRef(config == null ? void 0 : config.defaultFilters);
83
+ const subscribe = useCallback(
84
+ (onStoreChange) => {
85
+ const subscription = svc.getState().subscribe(() => {
86
+ onStoreChange();
87
+ });
88
+ return () => subscription.unsubscribe();
89
+ },
90
+ [svc]
91
+ );
92
+ const getSnapshot = useCallback(() => svc.getCurrentState(), [svc]);
93
+ const getServerSnapshot = useCallback(() => svc.getDefaultState(), [svc]);
94
+ const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
95
+ useEffect(() => {
96
+ if (!debug) return;
97
+ const sub = svc.getState().subscribe((newState) => {
98
+ console.log(`useFiltersAndSort [${svc.getStorageKey()}]:`, newState);
20
99
  });
21
- return () => subscription.unsubscribe();
22
- }, [service]);
23
- const callbacks = useMemo(() => ({
24
- setFilter: (key, value) => {
25
- service.setFilters({ [key]: value });
100
+ return () => sub.unsubscribe();
101
+ }, [svc, debug]);
102
+ useEffect(() => {
103
+ return () => {
104
+ if (ownsServiceRef.current && serviceRef.current) {
105
+ if (debug) {
106
+ console.log(`useFiltersAndSort: destroying owned service "${serviceRef.current.getStorageKey()}"`);
107
+ }
108
+ serviceRef.current.destroy();
109
+ serviceRef.current = null;
110
+ }
111
+ };
112
+ }, [debug]);
113
+ const setFilter = useCallback(
114
+ (key, value) => {
115
+ svc.setFilters({ [key]: value });
26
116
  },
27
- clearFilter: (key) => {
28
- service.removeFilter(key);
117
+ [svc]
118
+ );
119
+ const setFilters = useCallback(
120
+ (filters) => {
121
+ svc.setFilters(filters);
122
+ },
123
+ [svc]
124
+ );
125
+ const clearFilter = useCallback(
126
+ (key) => {
127
+ svc.removeFilter(key);
29
128
  },
30
- clearAllFilters: () => {
31
- service.clearFilters();
129
+ [svc]
130
+ );
131
+ const clearAllFilters = useCallback(() => {
132
+ svc.clearFilters();
133
+ }, [svc]);
134
+ const hasFilter = useCallback(
135
+ (key) => {
136
+ var _a;
137
+ const value = svc.getCurrentState().filters[key];
138
+ const defaultValue = (_a = defaultFiltersRef.current) == null ? void 0 : _a[key];
139
+ if (value === defaultValue) return false;
140
+ if (value === null || value === void 0 || value === "") return false;
141
+ if (Array.isArray(value) && value.length === 0) return false;
142
+ return true;
32
143
  },
33
- setSort: (field) => {
34
- service.setSort(field);
144
+ [svc]
145
+ );
146
+ const hasAnyFilters = useCallback(() => {
147
+ return countActiveFilters(svc.getCurrentState().filters, defaultFiltersRef.current) > 0;
148
+ }, [svc]);
149
+ const setSort = useCallback(
150
+ (field) => {
151
+ svc.setSort(field);
35
152
  },
36
- toggleSort: (field) => {
37
- service.setSort(field);
153
+ [svc]
154
+ );
155
+ const clearSort = useCallback(() => {
156
+ svc.setSort("");
157
+ }, [svc]);
158
+ const isSortedBy = useCallback(
159
+ (field) => {
160
+ var _a;
161
+ return ((_a = svc.getCurrentState().sort) == null ? void 0 : _a.fieldName) === field;
38
162
  },
39
- setPage: (page) => {
40
- service.setPagination(page);
163
+ [svc]
164
+ );
165
+ const setPage = useCallback(
166
+ (page) => {
167
+ if (page < 0) {
168
+ if (debug) {
169
+ console.warn("useFiltersAndSort: setPage called with negative value, clamping to 0");
170
+ }
171
+ page = 0;
172
+ }
173
+ svc.setPagination(page);
41
174
  },
42
- setPageSize: (size) => {
43
- const currentPage = state.pagination.page;
44
- service.setPagination(currentPage, size);
175
+ [svc, debug]
176
+ );
177
+ const setPageSize = useCallback(
178
+ (size) => {
179
+ if (size < 1) {
180
+ if (debug) {
181
+ console.warn("useFiltersAndSort: setPageSize called with value < 1, clamping to 1");
182
+ }
183
+ size = 1;
184
+ }
185
+ svc.setPagination(0, size);
45
186
  },
46
- nextPage: () => {
47
- service.setPagination(state.pagination.page + 1);
187
+ [svc, debug]
188
+ );
189
+ const setPagination = useCallback(
190
+ (page, size) => {
191
+ if (page < 0) {
192
+ if (debug) {
193
+ console.warn("useFiltersAndSort: setPagination called with negative page, clamping to 0");
194
+ }
195
+ page = 0;
196
+ }
197
+ if (size !== void 0 && size < 1) {
198
+ if (debug) {
199
+ console.warn("useFiltersAndSort: setPagination called with size < 1, clamping to 1");
200
+ }
201
+ size = 1;
202
+ }
203
+ svc.setPagination(page, size);
48
204
  },
49
- prevPage: () => {
50
- const newPage = Math.max(0, state.pagination.page - 1);
51
- service.setPagination(newPage);
205
+ [svc, debug]
206
+ );
207
+ const nextPage = useCallback(() => {
208
+ svc.setPagination(svc.getCurrentState().pagination.page + 1);
209
+ }, [svc]);
210
+ const prevPage = useCallback(() => {
211
+ const newPage = Math.max(0, svc.getCurrentState().pagination.page - 1);
212
+ svc.setPagination(newPage);
213
+ }, [svc]);
214
+ const firstPage = useCallback(() => {
215
+ svc.setPagination(0);
216
+ }, [svc]);
217
+ const setQuery = useCallback(
218
+ (query) => {
219
+ svc.setQuery(query);
52
220
  },
53
- setQuery: (query) => {
54
- service.setQuery(query);
221
+ [svc]
222
+ );
223
+ const clearQuery = useCallback(() => {
224
+ svc.setQuery("");
225
+ }, [svc]);
226
+ const reset = useCallback(() => {
227
+ svc.reset();
228
+ }, [svc]);
229
+ const clearStorageAndReset = useCallback(() => {
230
+ svc.clearStorage();
231
+ svc.reset();
232
+ }, [svc]);
233
+ const getService = useCallback(() => svc, [svc]);
234
+ const activeFilterCount = useMemo(
235
+ () => countActiveFilters(state.filters, defaultFiltersRef.current),
236
+ [state.filters]
237
+ );
238
+ const isFirstPage = state.pagination.page === 0;
239
+ const offset = state.pagination.page * state.pagination.limit;
240
+ return useMemo(
241
+ () => {
242
+ var _a, _b;
243
+ return {
244
+ // State
245
+ filters: state.filters,
246
+ sortBy: ((_a = state.sort) == null ? void 0 : _a.fieldName) ?? null,
247
+ sortDirection: ((_b = state.sort) == null ? void 0 : _b.direction) ?? "asc",
248
+ page: state.pagination.page,
249
+ pageSize: state.pagination.limit,
250
+ query: state.query,
251
+ state,
252
+ // Filter actions
253
+ setFilter,
254
+ setFilters,
255
+ clearFilter,
256
+ clearAllFilters,
257
+ hasFilter,
258
+ hasAnyFilters,
259
+ activeFilterCount,
260
+ // Sort actions
261
+ setSort,
262
+ toggleSort: setSort,
263
+ clearSort,
264
+ isSortedBy,
265
+ // Pagination actions
266
+ setPage,
267
+ setPageSize,
268
+ setPagination,
269
+ nextPage,
270
+ prevPage,
271
+ firstPage,
272
+ isFirstPage,
273
+ offset,
274
+ // Query actions
275
+ setQuery,
276
+ clearQuery,
277
+ // General actions
278
+ reset,
279
+ clearStorageAndReset,
280
+ storageKey: svc.getStorageKey(),
281
+ // Service access
282
+ getService
283
+ };
55
284
  },
56
- reset: () => {
57
- service.reset();
58
- }
59
- }), [service, state.pagination.page]);
60
- const memoizedReturn = useMemo(() => {
61
- var _a, _b;
62
- return {
63
- filters: state.filters,
64
- sortBy: ((_a = state.sort) == null ? void 0 : _a.fieldName) || null,
65
- sortDirection: ((_b = state.sort) == null ? void 0 : _b.direction) || "asc",
66
- page: state.pagination.page,
67
- pageSize: state.pagination.limit,
68
- query: state.query,
69
- ...callbacks
70
- };
71
- }, [state, callbacks]);
72
- return memoizedReturn;
285
+ [
286
+ state,
287
+ setFilter,
288
+ setFilters,
289
+ clearFilter,
290
+ clearAllFilters,
291
+ hasFilter,
292
+ hasAnyFilters,
293
+ activeFilterCount,
294
+ setSort,
295
+ clearSort,
296
+ isSortedBy,
297
+ setPage,
298
+ setPageSize,
299
+ setPagination,
300
+ nextPage,
301
+ prevPage,
302
+ firstPage,
303
+ isFirstPage,
304
+ offset,
305
+ setQuery,
306
+ clearQuery,
307
+ reset,
308
+ clearStorageAndReset,
309
+ svc,
310
+ getService
311
+ ]
312
+ );
73
313
  }
74
314
  function useFormBuilder(options) {
75
315
  const { builder } = options;
@@ -367,11 +607,6 @@ function useRichContent(options = {}) {
367
607
  setSelection
368
608
  };
369
609
  }
370
- function useTableService() {
371
- throw new Error(
372
- "useTableService is deprecated. TableBuilder is a configuration builder, not a stateful service. Use FiltersAndSortService with useFiltersAndSort hook for reactive state management. See documentation: https://github.com/CodellaSoftware/codella-utils"
373
- );
374
- }
375
610
  const TabsContext = createContext(void 0);
376
611
  function TabsProvider({ config, children }) {
377
612
  const [service] = useState(() => new TabsService(config));
@@ -448,7 +683,6 @@ export {
448
683
  useRichContent,
449
684
  useSetActiveTab,
450
685
  useTabChange,
451
- useTableService,
452
686
  useTabs,
453
687
  useTabsContext,
454
688
  useTabsService