Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add beforeKeyhandler hook #2092

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

shlroland
Copy link
Contributor

Description

I'm writing a slash extension.When a menu navigation appears to add or toggle nodes, if a keyboard shortcut is used at that time, the menu does not disappear, and the current search text can not be deleted. Therefore, I have added a hook function to control whether the keyboard shortcut event occurs and to perform certain actions before it is triggered.

Checklist

  • I have read the contributing document.
  • My code follows the code style of this project and pnpm fix completed successfully.
  • I have updated the documentation where necessary.
  • New code is unit tested and all current tests pass when running pnpm test.

Screenshots

@changeset-bot
Copy link

changeset-bot bot commented Jun 19, 2023

⚠️ No Changeset found

Latest commit: 0ee6d21

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added the test: unit ✅ A label for updating tests and test configuration. label Jun 19, 2023
@ocavue
Copy link
Member

ocavue commented Jun 20, 2023

This seems to be a x-y problem to me. Is there any chance that you can assign different priorities to keyboard shortcuts to resolve this issue? I can take a look if you can share your slash menu implementation (maybe after some code trimming).

@shlroland
Copy link
Contributor Author

x-y problem

// slash-menu
import { FloatingWrapper, Icon } from '@remirror/react'
import type { CommandUiIcon, CoreIcon } from 'remirror'
import { isString } from 'remirror'
import cx from 'classnames'
import { type FC } from 'react'
import type { GetPropsWithRefReturn } from 'multishift'
import { isCommandUiIcon, useCommandOptionValues } from 'src/remirror/react'
import type { SlashMenuItem as SlashMenuItemType } from '../types'
import { useSlash } from './use-slash'

export interface SlahItemIconProps {
  icon: CoreIcon | CommandUiIcon | JSX.Element | null | undefined
  size?: number | string
}

export const SlahItemIcon: FC<SlahItemIconProps> = ({
  icon,
  size = '1rem',
}) => {
  if (isString(icon) || isCommandUiIcon(icon)) {
    const iconName = isCommandUiIcon(icon) ? icon.name : icon
    return <Icon name={iconName} size={size} />
  }

  return icon
}

interface SlashMenuItemProps {
  isHighlighted: boolean
  isHovered: boolean
  menuItemProps: GetPropsWithRefReturn<HTMLLIElement, 'ref'>
  item: SlashMenuItemType
}

const SlashMenuItem: FC<SlashMenuItemProps> = ({
  isHighlighted,
  isHovered,
  menuItemProps,
  item,
}) => {
  const commandOptions = useCommandOptionValues({
    commandName: item.command,
    active: false,
    enabled: true,
    attrs: item.attrs,
  })

  return (
    <li
      className={cx(
        'truncate text-slate-500 p-2 min-w-[200px] h-16',
        isHighlighted && '[&]:bg-slate-100',
        isHovered && ' bg-slate-50',
      )}
      onPointerDown={(ev) => ev.preventDefault()}
      {...menuItemProps}
    >
      <div className="h-full grid grid-rows-2 grid-cols-[48px_minmax(100px,_1fr)_72px] cursor-pointer">
        <span
          className={cx(
            'row-span-2 flex-center w-full h-full rounded border border-slate-200 bg-white',
          )}
        >
          <SlahItemIcon icon={commandOptions.icon} size={'24px'} />
        </span>
        <span className="pl-2 font-medium">{commandOptions.label}</span>
        <span className="pl-2 col-start-2 col-end-3 text-xs">
          {commandOptions.description}
        </span>
        <span className="row-start-1 row-end-3 col-start-3 justify-self-center self-center">
          {commandOptions.shortcut}
        </span>
      </div>
    </li>
  )
}

export const SlashMenu = () => {
  const {
    state,
    getMenuProps,
    getItemProps,
    indexIsSelected,
    indexIsHovered,
    isOpen,
  } = useSlash()

  return (
    <FloatingWrapper positioner="cursor" enabled={isOpen} renderOutsideEditor>
      <ol
        {...getMenuProps()}
        className={cx(
          'absolute z-10',
          'max-h-64 w-max my-0 mx-auto pl-0.5 py-1 rounded-lg shadow-md shadow-gray-300',
          'bg-white',
          'overflow-y-auto',
          'common-scrollbar supports-scrollbars:pr-0.5',
        )}
      >
        {isOpen &&
          (state?.list ?? []).map((menuItem, index) => {
            const isHighlighted = indexIsSelected(index)
            const isHovered = indexIsHovered(index)
            return (
              <SlashMenuItem
                key={index}
                isHighlighted={isHighlighted}
                isHovered={isHovered}
                menuItemProps={getItemProps({
                  item: menuItem,
                  index,
                })}
                item={menuItem}
              />
            )
          })}
      </ol>
    </FloatingWrapper>
  )
}
// implementation of slash suggester
  excuteCommnad(selection: FromToProps, commnadName: string, attrs?: Attrs) {
    const chain = this.store.chain.delete(selection)
    chain[commnadName]?.(attrs)

    chain.run()
  }

  createSuggesters(): Suggester {
    return {
      disableDecorations: true,
      char: this.options.suggestionCharacter,
      name: this.name,
      startOfLine: true,
      onChange: (props) => {
        this.options.suggestSlash({
          query: props.query.full,
          text: props.text.full,
          range: props.range,
          exit: !!props.exitReason,
          change: !!props.changeReason,
          apply: (commandName, attrs) => {
            this.excuteCommnad(props.range, commandName, attrs)
          },
        })
      },
    }
  }

@shlroland
Copy link
Contributor Author

shlroland commented Jun 20, 2023

This seems to be a x-y problem to me. Is there any chance that you can assign different priorities to keyboard shortcuts to resolve this issue? I can take a look if you can share your slash menu implementation (maybe after some code trimming).

I have considered this solution, but the slash menu does not specify a particular keyboard shortcut. What is actually needed is the ability to perceive the lifecycle of the keymap execution and perform certain commands that can only be executed within the slash, such as deleting the current selection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
test: unit ✅ A label for updating tests and test configuration.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants