MCPcopy
hub / github.com/claude-code-best/claude-code / HooksConfigMenu

Function HooksConfigMenu

src/components/hooks/HooksConfigMenu.tsx:48–289  ·  view source on GitHub ↗
({ toolNames, onExit }: Props)

Source from the content-addressed store, hash-verified

46 | { mode: 'view-hook'; event: HookEvent; hook: IndividualHookConfig };
47
48export function HooksConfigMenu({ toolNames, onExit }: Props): React.ReactNode {
49 const [modeState, setModeState] = useState<ModeState>({
50 mode: 'select-event',
51 });
52 // Cache whether hooks are disabled by policy settings.
53 // getSettingsForSource() is expensive (file read + JSON parse + validation),
54 // so we compute it once on mount and only re-compute when policy settings change.
55 // Short-circuit evaluation ensures we skip the expensive check when hooks aren't disabled.
56 const [disabledByPolicy, setDisabledByPolicy] = useState(() => {
57 const settings = getSettings_DEPRECATED();
58 const hooksDisabled = settings?.disableAllHooks === true;
59 return hooksDisabled && getSettingsForSource('policySettings')?.disableAllHooks === true;
60 });
61
62 // Check if hooks are restricted to managed-only by policy
63 const [restrictedByPolicy, setRestrictedByPolicy] = useState(() => {
64 return getSettingsForSource('policySettings')?.allowManagedHooksOnly === true;
65 });
66
67 // Update cached values when policy settings change
68 useSettingsChange(source => {
69 if (source === 'policySettings') {
70 const settings = getSettings_DEPRECATED();
71 const hooksDisabled = settings?.disableAllHooks === true;
72 setDisabledByPolicy(hooksDisabled && getSettingsForSource('policySettings')?.disableAllHooks === true);
73 setRestrictedByPolicy(getSettingsForSource('policySettings')?.allowManagedHooksOnly === true);
74 }
75 });
76
77 // Extract commonly used values from modeState for convenience
78 const mode = modeState.mode;
79 const selectedEvent = 'event' in modeState ? modeState.event : 'PreToolUse';
80 const selectedMatcher = 'matcher' in modeState ? modeState.matcher : null;
81
82 const mcp = useAppState(s => s.mcp);
83 const appStateStore = useAppStateStore();
84 const combinedToolNames = useMemo(() => [...toolNames, ...mcp.tools.map(tool => tool.name)], [toolNames, mcp.tools]);
85
86 const hooksByEventAndMatcher = useMemo(
87 () => groupHooksByEventAndMatcher(appStateStore.getState(), combinedToolNames),
88 [combinedToolNames, appStateStore],
89 );
90
91 const sortedMatchersForSelectedEvent = useMemo(
92 () => getSortedMatchersForEvent(hooksByEventAndMatcher, selectedEvent),
93 [hooksByEventAndMatcher, selectedEvent],
94 );
95
96 const hooksForSelectedMatcher = useMemo(
97 () => getHooksForMatcher(hooksByEventAndMatcher, selectedEvent, selectedMatcher),
98 [hooksByEventAndMatcher, selectedEvent, selectedMatcher],
99 );
100
101 // Handler for exiting the dialog
102 const handleExit = useCallback(() => {
103 onExit('Hooks dialog dismissed', { display: 'system' });
104 }, [onExit]);
105

Callers

nothing calls this directly

Calls 13

getSettingsForSourceFunction · 0.85
useSettingsChangeFunction · 0.85
useAppStateFunction · 0.85
useAppStateStoreFunction · 0.85
getHooksForMatcherFunction · 0.85
onExitFunction · 0.85
useKeybindingFunction · 0.85
getMatcherMetadataFunction · 0.85
pluralFunction · 0.85
getStateMethod · 0.80

Tested by

no test coverage detected