Module

Select.Primitives.Container

Package
purescript-halogen-select
Repository
citizennet/purescript-halogen-select

The Container primitive contains an array of items that can be selected. As you provide the render functions, this array of items could be anything from a dropdown list to a calendar grid. The primitive provides keyboard and click behaviors for highlighting and selecting items and will be used in nearly every selection component you write.

#ContainerQuery Source

data ContainerQuery o item a

The query type for the Container primitive. This primitive handles selections and keyboard navigation.

Arguments:

  • o: The type of the parent query to embed. This is usually the component that
  •  mounts the search primitive, but it could also be the query type of some
     higher component.
    
  • item: Your custom item type, used by your renderers.

Constructors:

  • Highlight: Change the highlighted item to the next, previous, or a specific index.
  • Select: Select an item at the specified index
  • Key: Capture key events for arrow navigation, Escape to close, and Enter to select.
  • Mouse: Capture mouse events to close the menu or select an item
  • Blur: Trigger the DOM blur event
  • Visibility: Set the visibility by toggling, setting to on, or setting to off.
  • ReplaceItems: Replace the array of items.
  • Raise: Embed a parent query that can be returned to the parent for evaluation.
  • ContainerReceiver: Update the component on new Input when the parent re-renders.

Constructors

#Target Source

data Target

Navigation for the container's Highlight query.

Note: in eval, this wraps around, so providing Highlight Next on the last item in the array will highlight the first item in the array.

Constructors

#MouseState Source

data MouseState

Maintain the state of the mouse in the container's Mouse query.

Constructors

#VisibilityStatus Source

data VisibilityStatus

Possible visibility statuses for the container's Visibility query.

On: Set the container to be visible (use this to "open" the container) Off: Set the container to be visible (use this to "close" the container) Toggle: Toggle between "open" and "closed".

Constructors

#ContainerState Source

type ContainerState item = { highlightedIndex :: Maybe Int, items :: Array item, lastIndex :: Int, mouseDown :: Boolean, open :: Boolean }

The internal state of the Container primitive

  • items: An array of items held within the Container
  • open: Whether the Container is visible
  • highlightedIndex: The index of the highlighted item, if one exists
  • lastIndex: The index of the last item in the Container
  • mouseDown: Whether the mouse is clicked or not

#ContainerInput Source

type ContainerInput o item = { items :: Array item, render :: ContainerState item -> ComponentHTML (ContainerQuery o item) }

The input type of the Container primitive

  • items: The initial value of items in the ContainerState
  • render: The render function for the Container primitive

#Message Source

data Message o item

Messages emitted by the container primitive to notify the parent of important events.

  • ItemSelected: An item has been selected in the container. This does not indicate the item has been removed; if you would like the item to also be removed from the container, make sure to query ReplaceItems from the parent.
  • Emit: A parent query has been triggered and should be evaluated by the parent. Typically:
eval (HandleContainer (Emit q) next) = eval q *> pure next

Constructors

#component Source

component :: forall m eff item o. MonadAff (dom :: DOM | eff) m => Component HTML (ContainerQuery o item) (ContainerInput o item) (Message o item) m

The primitive handles state and transformations but defers all rendering to the parent. The render function can be written using our helper functions to ensure the right events are included.

#getToggleProps Source

getToggleProps :: forall f e item o. (ContainerQuery o item Unit -> Unit -> f Unit) -> Array (IProp (onBlur :: FocusEvent, onClick :: MouseEvent, onKeyDown :: KeyboardEvent, onMouseDown :: MouseEvent, onMouseUp :: MouseEvent, tabIndex :: Int | e) f) -> Array (IProp (onBlur :: FocusEvent, onClick :: MouseEvent, onKeyDown :: KeyboardEvent, onMouseDown :: MouseEvent, onMouseUp :: MouseEvent, tabIndex :: Int | e) f)

Attach properties to a DOM node that will maintain focus and capture key and click events for the container. If you are using the search primitive, this helper is unnecessary.

Note: This function will overwrite any properties of the same name that are already set. Use it directly on the list of properties for the node that will serve as the toggle.

Note: The toggle is not rendered within the container component. Instead, you should define a query on the parent that routes events to the relevant container, and provide that query as the first argument to this function.

-- ToContainer is a parent query you have defined that, in eval, sends queries to the container.
span (getToggleProps ToContainer [ class_ $ ClassName "my-class" ]) [ text "Button" ]

#getChildProps Source

getChildProps :: forall e item o. Array (IProp (onBlur :: FocusEvent, tabIndex :: Int | e) (ContainerQuery o item)) -> Array (IProp (onBlur :: FocusEvent, tabIndex :: Int | e) (ContainerQuery o item))

A helper to embed your own HTML and queries inside the container's render function. It will ensure that your events do not inadvertently steal focus or trigger a blur on the container. Useful to embed buttons and other arbitrary HTML within the container.

To embed your own queries, remember to use the Raise query from the container to wrap them. This will ensure they are re-raised to the parent.

Use directly on the properties for the element you are embedding:

button (getChildProps [ onClick $ input_ $ Raise $ action $ MyQuery "Do something" ]) [ text "Button" ]

Note: This will overwrite any properties of the same name.

#getContainerProps Source

getContainerProps :: forall e item o. Array (IProp (onBlur :: FocusEvent, onMouseDown :: MouseEvent, onMouseUp :: MouseEvent, tabIndex :: Int | e) (ContainerQuery o item)) -> Array (IProp (onBlur :: FocusEvent, onMouseDown :: MouseEvent, onMouseUp :: MouseEvent, tabIndex :: Int | e) (ContainerQuery o item))

Attach properties to the HTML element that encloses the container. This makes sure you can select items without blurring the container, unless you want to. It is used in conjunction with the getItemProps helper, which you should attach to each item in the container.

div (getContainerProps [ class_ (ClassName "my-class") ]) [ ... further html ... ]

Note: This function will overwrite any properties of the same name that are already set.

#getItemProps Source

getItemProps :: forall e item o. Int -> Array (IProp (onBlur :: FocusEvent, onClick :: MouseEvent, onKeyDown :: KeyboardEvent, onMouseOver :: MouseEvent, tabIndex :: Int | e) (ContainerQuery o item)) -> Array (IProp (onBlur :: FocusEvent, onClick :: MouseEvent, onKeyDown :: KeyboardEvent, onMouseOver :: MouseEvent, tabIndex :: Int | e) (ContainerQuery o item))

Attach events to an item in the container to support selection, highlighting, and key events (like Enter to select). Used in conjunction with getContainerProps.

This function requires an index. It's usually easiest to provide a renderer that uses mapWithIndex to ensure indexes are provided properly.

renderItems arrayOfItems = renderItem `mapWithIndex` arrayOfItems
renderItem index item = li (getItemProps index [ class_ (ClassName "item-class") ]) [ text item ]

You should provide CSS to highlight items without requiring hovers, so that arrow keys can properly maintain highlights. To do that, use the container's state to check if the item being rendered has the same index as the highlight, and if so, apply your class:

-- in renderItem...
if state.highlightedIndex == Just index then "highlight-class" else "no-highlight-class"

Note: This function will overwrite any properties of the same name that are already set.