In Imperative.js, a widget is an ES6 generator function which yields values with the function-signature (resolve, reject) => virtual-dom.

The idea is that each input element type; as well as other basic interactions like AJAX calls, timeouts, and non-interactive output like paragaraphs and SVG; is wrapped into a simple widget which returns on any meaningful event. Then application code builds on top of these simple widgets using generator function syntax and the h combinator. Usually there should be no need to write yield statements directly.

For example, here is the button implementation from Imperative/widgets—it outputs a button element, and resolves on several of the most interesting events. The output is a pair of {event, state}—the event is what triggered the return, and the state includes focus and hover states.

function* button(text, styles, state) {
  state = Object.assign({focus: false, hover: false}, state || {})
  return yield (resolve, reject) =>
    I.h('button', {
      style: styles,
      on: {
        mouseenter: (ev) =>
          resolve({event: ev, state: Object.assign(state, {hover: true})}),
        mouseleave: (ev) =>
          resolve({event: ev, state: Object.assign(state, {hover: false})}),
        click: (ev) =>
          resolve({event: ev, state: state}),
        blur: (ev) =>
          resolve({event: ev, state: Object.assign(state, {focus: false})}),
        focus: (ev) =>
          resolve({event: ev, state: Object.assign(state, {focus: true})}),
      },
      hook: {
        insert: (vnode) => state.focus ? vnode.elm.focus() : vnode.elm.blur(),
        postpatch: (old, vnode) => state.focus ? vnode.elm.focus() : vnode.elm.blur()
      }
    }, [text])
}

example("Button", function*() {
  let event = ''
  let state = {}
  while(true) {
    const txt = JSON.stringify(state) + " " + event.type
    const eventState =
      yield* button(txt, {}, {})
    event = eventState.event
    state = eventState.state
  }
}())

This implementation is the simplest, base case for a button. It returns on every event. This one definition should serve for essentially any button in any application. For example, suppose that you are only interested in the click action on the button; you can easily build a widget which returns only the click events by looping on all other events.

function* clickButton(text, styles, hoverStyles, state) {
  while(true) {
    const eventState = yield* button(text, styles, state)
    if(eventState.event.type === 'click')
      return eventState
    else
      state = eventState.state
  }
}

example("clickButton", function*() {
  let state = {}
  let n = 0
  while(true) {
    state = (yield* clickButton("Clicked " + n, {}, {}, state)).state
    n++
  }
}())

This is the general pattern of any Imperative application: the lowest-level widgets return on every event, they are composed into higher-level functions which loop until they reach a higher-level, more semantically meaningful event. For example, for an email application, at the highest level you would build a function which returns a composed email. This would be built out of lower-level functions which return domain objects like email addresses, formatted text, or attachments. These would be built out of even more detailed widgets, down to the most basic widgets which return atomic user interactions and browser events like clicks, keypresses, or file upload events.