Stirling-PDF/frontend/src/contexts/RightRailContext.tsx

65 lines
2.4 KiB
TypeScript
Raw Normal View History

Feature/v2/right rail (#4255) # Description of Changes <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com> Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-08-25 12:53:33 +01:00
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
import { RightRailAction, RightRailButtonConfig } from '../types/rightRail';
interface RightRailContextValue {
buttons: RightRailButtonConfig[];
actions: Record<string, RightRailAction>;
registerButtons: (buttons: RightRailButtonConfig[]) => void;
unregisterButtons: (ids: string[]) => void;
setAction: (id: string, action: RightRailAction) => void;
clear: () => void;
}
const RightRailContext = createContext<RightRailContextValue | undefined>(undefined);
export function RightRailProvider({ children }: { children: React.ReactNode }) {
const [buttons, setButtons] = useState<RightRailButtonConfig[]>([]);
const [actions, setActions] = useState<Record<string, RightRailAction>>({});
const registerButtons = useCallback((newButtons: RightRailButtonConfig[]) => {
setButtons(prev => {
const byId = new Map(prev.map(b => [b.id, b] as const));
newButtons.forEach(nb => {
const existing = byId.get(nb.id) || ({} as RightRailButtonConfig);
byId.set(nb.id, { ...existing, ...nb });
});
const merged = Array.from(byId.values());
merged.sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.id.localeCompare(b.id));
if (process.env.NODE_ENV === 'development') {
const ids = newButtons.map(b => b.id);
const dupes = ids.filter((id, idx) => ids.indexOf(id) !== idx);
if (dupes.length) console.warn('[RightRail] Duplicate ids in registerButtons:', dupes);
}
return merged;
});
}, []);
const unregisterButtons = useCallback((ids: string[]) => {
setButtons(prev => prev.filter(b => !ids.includes(b.id)));
setActions(prev => Object.fromEntries(Object.entries(prev).filter(([id]) => !ids.includes(id))));
}, []);
const setAction = useCallback((id: string, action: RightRailAction) => {
setActions(prev => ({ ...prev, [id]: action }));
}, []);
const clear = useCallback(() => {
setButtons([]);
setActions({});
}, []);
const value = useMemo<RightRailContextValue>(() => ({ buttons, actions, registerButtons, unregisterButtons, setAction, clear }), [buttons, actions, registerButtons, unregisterButtons, setAction, clear]);
return (
<RightRailContext.Provider value={value}>
{children}
</RightRailContext.Provider>
);
}
export function useRightRail() {
const ctx = useContext(RightRailContext);
if (!ctx) throw new Error('useRightRail must be used within RightRailProvider');
return ctx;
}