obsidian#KeymapContext TypeScript Examples

The following examples show how to use obsidian#KeymapContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: keymap.ts    From obsidian-switcher-plus with GNU General Public License v3.0 6 votes vote down vote up
private navigateItems(_evt: KeyboardEvent, ctx: KeymapContext): boolean | void {
    const { isOpen, chooser } = this;

    if (isOpen) {
      let index = chooser.selectedItem;
      index = ctx.key === 'n' ? ++index : --index;
      chooser.setSelectedItem(index, true);
    }

    return false;
  }
Example #2
Source File: keymap.test.ts    From obsidian-switcher-plus with GNU General Public License v3.0 4 votes vote down vote up
describe('keymap', () => {
  const mockScope = mock<Scope>();
  const mockChooser = mock<Chooser<AnySuggestion>>();
  const mockModalContainer = mock<HTMLElement>();

  describe('isOpen property', () => {
    let sut: Keymap;

    beforeAll(() => {
      sut = new Keymap(mockScope, mockChooser, mockModalContainer);
    });

    it('should save the value provided for isOpen', () => {
      sut.isOpen = true;
      const result = sut.isOpen;
      expect(result).toBe(true);
    });
  });

  describe('Next/Previous keyboard navigation', () => {
    beforeEach(() => {
      mockReset(mockScope);
      mockReset(mockChooser);
    });

    it('should register ctrl-n/p for navigating forward/backward', () => {
      new Keymap(mockScope, null, null);

      expect(mockScope.register).toHaveBeenCalledWith(
        expect.arrayContaining(['Ctrl']),
        'n',
        expect.anything(),
      );

      expect(mockScope.register).toHaveBeenCalledWith(
        expect.arrayContaining(['Ctrl']),
        'p',
        expect.anything(),
      );
    });

    test('when Open, it should change the selected item with ctrl-n/p keyboard navigation', () => {
      const selectedIndex = 1;
      const navPairs: Record<string, KeymapEventListener> = {
        n: null,
        p: null,
      };

      mockScope.register.mockImplementation((_m, key, func) => {
        if (key in navPairs) {
          navPairs[key] = func;
        }

        return null;
      });

      mockChooser.selectedItem = selectedIndex;

      const sut = new Keymap(mockScope, mockChooser, null);
      sut.isOpen = true; // here

      navPairs.n(mock<KeyboardEvent>(), mock<KeymapContext>({ key: 'n' }));
      navPairs.p(mock<KeyboardEvent>(), mock<KeymapContext>({ key: 'p' }));

      expect(mockChooser.setSelectedItem).toHaveBeenCalledWith(selectedIndex + 1, true);
      expect(mockChooser.setSelectedItem).toHaveBeenCalledWith(selectedIndex - 1, true);
    });

    test('when not Open, it should not change the selected item with ctrl-n/p keyboard navigation', () => {
      const selectedIndex = 1;
      const navPairs: Record<string, KeymapEventListener> = {
        n: null,
        p: null,
      };

      mockScope.register.mockImplementation((_m, key, func) => {
        if (key in navPairs) {
          navPairs[key] = func;
        }

        return null;
      });

      mockChooser.selectedItem = selectedIndex;

      const sut = new Keymap(mockScope, mockChooser, null);
      sut.isOpen = false; // here

      navPairs.n(mock<KeyboardEvent>(), mock<KeymapContext>({ key: 'n' }));
      navPairs.p(mock<KeyboardEvent>(), mock<KeymapContext>({ key: 'p' }));

      expect(mockChooser.setSelectedItem).not.toHaveBeenCalled();
      expect(mockChooser.setSelectedItem).not.toHaveBeenCalled();
    });
  });

  describe('updateKeymapForMode', () => {
    const selector = '.prompt-instructions';
    const mockInstructionsEl = mock<HTMLElement>();
    const mockMetaEnter = mock<Hotkey>({
      modifiers: ['Meta'],
      key: 'Enter',
    });
    const mockShiftEnter = mock<Hotkey>({
      modifiers: ['Shift'],
      key: 'Enter',
    });

    beforeEach(() => {
      mockReset(mockScope);
      mockReset(mockModalContainer);
    });

    it('should do nothing if the helper text (prompt instructions) element is not found', () => {
      const mockQuerySelector =
        mockModalContainer.querySelector.mockReturnValueOnce(null);

      const sut = new Keymap(mockScope, mockChooser, mockModalContainer);

      expect(() => sut.updateKeymapForMode(Mode.Standard)).not.toThrow();
      expect(mockQuerySelector).toHaveBeenCalledWith(selector);
    });

    it('should hide the helper text (prompt instructions) in non-standard modes', () => {
      const mockQuerySelector =
        mockModalContainer.querySelector.mockReturnValueOnce(mockInstructionsEl);

      const sut = new Keymap(mockScope, mockChooser, mockModalContainer);

      sut.updateKeymapForMode(Mode.EditorList);

      expect(mockQuerySelector).toHaveBeenCalledWith(selector);
      expect(mockInstructionsEl.style.display).toBe('none');
    });

    it('should show the helper text (prompt instructions) in standard modes', () => {
      const mockQuerySelector =
        mockModalContainer.querySelector.mockReturnValueOnce(mockInstructionsEl);

      const sut = new Keymap(mockScope, mockChooser, mockModalContainer);

      sut.updateKeymapForMode(Mode.Standard);

      expect(mockQuerySelector).toHaveBeenCalledWith(selector);
      expect(mockInstructionsEl.style.display).toBe('');
    });

    it('should not remove Enter hotkey without shift/meta modifier', () => {
      const mockEnter = mock<Hotkey>({
        modifiers: [],
        key: 'Enter',
      });

      mockScope.keys = [mockEnter];
      const sut = new Keymap(mockScope, null, mockModalContainer);

      sut.updateKeymapForMode(Mode.EditorList);

      expect(mockScope.keys).toContain(mockEnter);
    });

    it('should remove the shift-enter hotkey in non-standard modes', () => {
      mockScope.keys = [mockMetaEnter, mockShiftEnter];
      const sut = new Keymap(mockScope, null, mockModalContainer);

      sut.updateKeymapForMode(Mode.EditorList);

      expect(mockScope.keys).toHaveLength(1);
    });

    it('should keep the meta-enter hotkey registered in non-standard modes', () => {
      mockScope.keys = [mockMetaEnter, mockShiftEnter];
      const sut = new Keymap(mockScope, null, mockModalContainer);

      sut.updateKeymapForMode(Mode.StarredList);

      expect(mockScope.keys).toHaveLength(1);
      expect(mockScope.keys).toContain(mockMetaEnter);
    });

    it('should restore the shift/meta hotkey in standard mode', () => {
      mockScope.keys = [mockMetaEnter, mockShiftEnter];
      const sut = new Keymap(mockScope, null, mockModalContainer);

      // should first remove shift-enter in non-standard mode
      sut.updateKeymapForMode(Mode.EditorList);
      const extendedModeKeyCount = mockScope.keys.length;

      // should restore all hotkeys in standard mode
      sut.updateKeymapForMode(Mode.Standard);

      expect(extendedModeKeyCount).toBe(1);
      expect(mockScope.keys).toContain(mockMetaEnter);
      expect(mockScope.keys).toContain(mockShiftEnter);
    });
  });
});