Repository: h2oai/wave
File: ui/src/side_panel.tsx (TypeScript)

Code before:
 */
export interface SidePanel {
  /** The side panel's title. */
  title: S
  /** The components displayed in this side panel. */
  items: Component[]
  /** The width of the dialog, e.g. '400px'. Defaults to '600px'. */
  width?: S
  /** True if the side panel should have a closing 'X' button at the top right corner. */
  closable?: B
  /** True to prevent closing when clicking or tapping outside the side panel. Prevents interacting with the page behind the side panel. Defaults to False. */
  blocking?: B
  /** An identifying name for this component. */
  name?: Id
  /** The events to capture on this side panel. One of 'dismissed'. */
  events?: S[]
}

export default bond(() => {
  const
    onDismiss = () => {
      const
        { closable, blocking, name, events } = sidePanelB() || {},
        ev = events?.find(e => e === 'dismissed')

      if ((closable || !blocking) && ev && name) wave.emit(name, ev, true)
      sidePanelB(null)
    },
    render = () => {
      const { title, width = '600px', items = [], closable = false, blocking = false } = sidePanelB() || {}
      return (
        <Fluent.Panel
          isOpen={!!sidePanelB()}
          headerText={title}
          type={Fluent.PanelType.custom}
          customWidth={width}
          onDismiss={onDismiss}
          hasCloseButton={closable}
          overlayProps={blocking ? { style: { cursor: 'default' } } : undefined}
          isBlocking
          isLightDismiss={!blocking}>
          <XComponents items={items} />
        </Fluent.Panel >
      )
    }
  return { render, sidePanelB }
})

Review comment (suggestion):
Shouldn't this be just this?
```suggestion
      if (ev && name) wave.emit(name, ev, true)
```
I would expect `(closable || !blocking)` to be handled by Fluent. I assume `onDismiss` callback should not be called if user clicks outside the blocking side panel. @marek-mihok please verify and update the code accordingly.

Code after:
 */
export interface SidePanel {
  /** The side panel's title. */
  title: S
  /** The components displayed in this side panel. */
  items: Component[]
  /** The width of the dialog, e.g. '400px'. Defaults to '600px'. */
  width?: S
  /** An identifying name for this component. */
  name?: Id
  /** The events to capture on this side panel. One of 'dismissed'. */
  events?: S[]
  /** True to prevent closing when clicking or tapping outside the side panel. Prevents interacting with the page behind the side panel. Defaults to False. */
  blocking?: B
  /** True if the side panel should have a closing 'X' button at the top right corner. */
  closable?: B
}

export default bond(() => {
  const
    onDismiss = () => {
      const
        { name, events } = sidePanelB() || {},
        ev = events?.find(e => e === 'dismissed')

      if (ev && name) wave.emit(name, ev, true)
      sidePanelB(null)
    },
    render = () => {
      const { title, width = '600px', items = [], closable = false, blocking = false } = sidePanelB() || {}
      return (
        <Fluent.Panel
          isOpen={!!sidePanelB()}
          headerText={title}
          type={Fluent.PanelType.custom}
          customWidth={width}
          onDismiss={onDismiss}
          hasCloseButton={closable}
          overlayProps={blocking ? { style: { cursor: 'default' } } : undefined}
          isBlocking
          isLightDismiss={!blocking}>
          <XComponents items={items} />
        </Fluent.Panel >
      )
    }
  return { render, sidePanelB }
})