Skip to content

Commit

Permalink
feat(lib): add event listener for ESC key handler (#404)
Browse files Browse the repository at this point in the history
* feat(SHAPE-2151): add event listener for ESC key handler

* lint: add eslint fixes

* test: include main functionalities testing

* fix type error

* fix lint error

---------

Co-authored-by: Eunjae Lee <[email protected]>
Co-authored-by: Demetrius Feijóo <[email protected]>
  • Loading branch information
3 people authored Sep 25, 2024
1 parent 230ff70 commit 4279218
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 15 deletions.
41 changes: 26 additions & 15 deletions packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createPluginActions, ValidateContent } from './createPluginActions'
import { createHeightChangeListener } from './createHeightChangeListener'
import { createKeydownEscListener } from './createKeydownEscListener'
import { disableDefaultStoryblokStyles } from './disableDefaultStoryblokStyles'
import { pluginUrlParamsFromUrl } from '../messaging'
import { FieldPluginResponse } from './FieldPluginResponse'
Expand Down Expand Up @@ -50,6 +51,8 @@ export const createFieldPlugin: CreateFieldPlugin = ({
}

const { uid, host } = params

// ToDo: In development we need to load localhost:3300
const origin =
typeof targetOrigin === 'string'
? targetOrigin
Expand Down Expand Up @@ -85,24 +88,31 @@ export const createFieldPlugin: CreateFieldPlugin = ({
Exclude<typeof validateContent, undefined>
>['content']

const { actions, messageCallbacks, onHeightChange, initialize } =
createPluginActions<InferredContent>({
uid,
postToContainer,
onUpdateState: (data) => {
onUpdateState({
type: 'loaded',
data,
actions,
})
},
validateContent:
validateContent ||
((content) => ({ content: content as InferredContent })),
})
const {
actions,
messageCallbacks,
onHeightChange,
onKeydownEsc,
initialize,
} = createPluginActions<InferredContent>({
uid,
postToContainer,
onUpdateState: (data) => {
onUpdateState({
type: 'loaded',
data,
actions,
})
},
validateContent:
validateContent ||
((content) => ({ content: content as InferredContent })),
})

const cleanupHeightChangeListener = createHeightChangeListener(onHeightChange)

const cleanupKeydownEscListener = createKeydownEscListener(onKeydownEsc)

const cleanupMessageListenerSideEffects = createPluginMessageListener(
params.uid,
origin,
Expand All @@ -114,6 +124,7 @@ export const createFieldPlugin: CreateFieldPlugin = ({
return () => {
cleanupMessageListenerSideEffects()
cleanupHeightChangeListener()
cleanupKeydownEscListener()
cleanupStyleSideEffects()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { createKeydownEscListener } from './createKeydownEscListener'
import { MockInstance } from 'vitest'

describe('createKeydownEscListener', () => {
let addEventListenerSpy: MockInstance
let removeEventListenerSpy: MockInstance
const escapeEvent = new KeyboardEvent('keydown', { key: 'Escape' })

beforeEach(() => {
addEventListenerSpy = vi.spyOn(document, 'addEventListener')
removeEventListenerSpy = vi.spyOn(document, 'removeEventListener')
})

afterEach(() => {
vi.restoreAllMocks()
})

it('should call addEventListener with keydown and handleEsc', () => {
const mockOnPressed = vi.fn()

createKeydownEscListener(mockOnPressed)

expect(addEventListenerSpy).toHaveBeenCalledWith(
'keydown',
expect.any(Function),
)
})

it('should trigger onPressed when Escape key is pressed', () => {
const mockOnPressed = vi.fn()

const removeListener = createKeydownEscListener(mockOnPressed)

document.dispatchEvent(escapeEvent)

expect(mockOnPressed).toHaveBeenCalled()

removeListener()

expect(removeEventListenerSpy).toHaveBeenCalledWith(
'keydown',
expect.any(Function),
)
})

it('should not trigger onPressed when a non-Escape key is pressed', () => {
const mockOnPressed = vi.fn()

createKeydownEscListener(mockOnPressed)

const enterEvent = new KeyboardEvent('keydown', { key: 'Enter' })
document.dispatchEvent(enterEvent)

expect(mockOnPressed).not.toHaveBeenCalled()
})

it('should not trigger onPressed when the cleanup function is called', () => {
const mockOnPressed = vi.fn()
const removeListener = createKeydownEscListener(mockOnPressed)

removeListener()

expect(removeEventListenerSpy).toHaveBeenCalledWith(
'keydown',
expect.any(Function),
)

document.dispatchEvent(escapeEvent)

expect(mockOnPressed).not.toHaveBeenCalled()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @returns function for cleaning up side effects
*/

export const createKeydownEscListener = (onPressed: () => void) => {
const handleEsc = (event: KeyboardEvent) => {
const key = event.key
if (key === 'Escape') {
onPressed()
}
}

document.addEventListener('keydown', handleEsc)
return () => document.removeEventListener('keydown', handleEsc)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export type CreatePluginActions = <Content>(options: {
messageCallbacks: PluginMessageCallbacks
// This function is called whenever the height changes
onHeightChange: (height: number) => void
// This function is called whenever the ESC key is pressed
onKeydownEsc: () => void
// This initiates the plugin
initialize: Initialize<Content>
}
Expand Down Expand Up @@ -85,6 +87,10 @@ export const createPluginActions: CreatePluginActions = ({
postToContainer(heightChangeMessage(uid, height))
}

const onKeydownEsc = () => {
postToContainer(modalChangeMessage({ uid, status: false }))
}

return {
actions: {
setContent: (content) => {
Expand Down Expand Up @@ -130,6 +136,7 @@ export const createPluginActions: CreatePluginActions = ({
},
messageCallbacks,
onHeightChange,
onKeydownEsc,
initialize: () => {
return new Promise((resolve) => {
const callbackId = pushCallback('loaded', (message) =>
Expand Down

0 comments on commit 4279218

Please sign in to comment.