I finally got BLE keyboard functionality working. Although there is an example provided with ESP-IDF, getting the HTTP server (for the camera stream), WiFi, and Bluetooth stacks running at the same time is a bit finicky.
The main issue that arose was IRAM size limitations. I tried the config options found in this IDF doc section, but evidently there still wasn't enough room. There is a new config option found in the ESP-IDF master branch that allows some DRAM sections to be used for IRAM, so I switched to master instead and enabled that option. Then, DRAM wasn't big enough, so I had to force Bluetooth and WiFi to allocate from PSRAM instead, among other things, which finally made it work.
The BLE HID example uses Bluedroid, which is larger than the alternative NimBLE stack. Perhaps switching to this could reduce these issues? I've actually used NimBLE with Mynewt many years ago for another BLE HID project, so it might not be too difficult.
As for the functionality itself, the keyboard supports typing characters as well as backspace, by holding the eye closed for a longer amount of time. Also, to provide visual feedback, the individual Morse dots/dashes are typed out while a character is in progress, then erased once it is finalized and replaced by the final character. I'll try to show this in a video recording.