Module

Hylograph.Internal.Capabilities.Selection

Package
purescript-hylograph-selection
Repository
afcondon/purescript-hylograph-selection

Internal: Type class defining selection operations.

The SelectionM class abstracts over different selection interpreters, enabling the same visualization code to run with:

  • D3 rendering (DOM manipulation)
  • String output (for testing/SSR)
  • Mermaid diagrams
  • Accessibility descriptions

Phantom types (SEmpty, SBoundOwns, etc.) enforce valid operation sequences at compile time.

Internal module - see Hylograph.Selection for the public API.

#SelectionM Source

class SelectionM :: (Type -> Type -> Type -> Type) -> (Type -> Type) -> Constraintclass (Monad m) <= SelectionM sel m | m -> sel where

Type class for selection operations

This is the tagless final interface that user code programs against. Different interpreters can provide different implementations:

  • D3v2: Manipulates actual DOM using Hylograph.Internal.Selection.Operations
  • String: Generates HTML strings
  • Meta: Records operations for visualization/debugging
  • Music: Generates audio representations

The phantom type parameters (SEmpty, SBound, etc.) provide compile-time safety even though the type class itself doesn't enforce state transitions. The interpreters use these phantom types with unsafePartial to safely pattern match on the underlying SelectionImpl.

Example user code:

drawCircles :: forall m sel. SelectionM sel m => m Unit
drawCircles = do
  svg <- select "svg"
  circles <- renderData Circle [1, 2, 3] "circle" svg
    (Just \d -> [fill "green", cx (\_ -> d * 100.0)])
    Nothing
    Nothing
  pure unit

Members

  • select :: forall datum. String -> m (sel SEmpty Element datum)

    Select a single element by CSS selector

    Returns an empty selection (no data bound). The datum type is polymorphic and will be inferred from usage. This is typically the starting point for data binding.

  • selectElement :: forall datum. Element -> m (sel SEmpty Element datum)

    Select from a DOM element directly

    This is useful for framework integration (React, Vue, etc.) where you have a reference to a DOM element rather than a CSS selector.

    Example (React):

    useEffect do
      for_ (toMaybe containerRef.current) \element -> do
        void $ runD3 do
          container <- selectElement element
          renderTree container myVisualization
    
  • selectAll :: forall state parent parentDatum datum. String -> sel state parent parentDatum -> m (sel SEmpty Element datum)

    Select all elements matching selector within a parent selection

    Returns an empty selection of the matched elements. The datum type is polymorphic and will be inferred from usage.

  • openSelection :: forall state parent parentDatum datum. sel state parent parentDatum -> String -> m (sel SEmpty Element datum)

    Open selection (parent-first argument order)

    Alias for selectAll with arguments flipped. Takes parent selection first, then selector string.

    Example:

    openSel <- openSelection letterGroup "text"
    
  • selectAllWithData :: forall state parent parentDatum datum. String -> sel state parent parentDatum -> m (sel SBoundOwns Element datum)

    Select all elements matching selector and extract their bound data

    Use this when selecting child elements that have inherited data from their parent. This is necessary when you want to use the selection with transitions that need access to the bound data (like withTransitionStaggered).

    Example:

    groups <- selectSimulationGroups
    circles <- selectAllWithData "circle" groups.nodes
    withTransitionStaggered config delayFn circles [fill colorByDepth]
    
  • renderData :: forall f parent datum. Foldable f => Ord datum => ElementType -> f datum -> String -> sel SEmpty parent datum -> Maybe (datum -> Array (Attribute datum)) -> Maybe (datum -> Array (Attribute datum)) -> Maybe (datum -> Array (Attribute datum)) -> m (sel SBoundOwns Element datum)

    High-level data rendering (recommended for most use cases)

    Manages the entire enter-update-exit cycle automatically. Users provide Maybe callbacks for each phase.

    This is the user-friendly API that prevents sequencing errors by handling enter/update/exit internally.

    Example:

    circles <- renderData Circle [1, 2, 3] "circle" svg
      (Just \d -> [fill "green", cx (\_ -> d * 100.0)])  -- Enter
      (Just \d -> [fill "orange"])                        -- Update
      Nothing                                             -- Exit (just remove)
    
  • appendData :: forall f parent parentDatum datum. Foldable f => ElementType -> f datum -> Array (Attribute datum) -> sel SEmpty parent parentDatum -> m (sel SBoundOwns Element datum)

    Simple data append for initial renders

    A simplified variant for when you just want to create elements without worrying about updates or exits.

    Perfect for initial renders where there are no existing elements.

    Example:

    svg <- select "svg"
    circles <- appendData Circle [1, 2, 3]
      [radius 10.0, fill "steelblue"]
      svg
    
  • joinData :: forall f parent parentDatum datum. Foldable f => Ord datum => f datum -> String -> sel SEmpty parent parentDatum -> m (JoinResult sel parent datum)

    Low-level data join for power users

    Explicitly returns enter, update, and exit selections. Users must handle each set manually using append/setAttrs/remove.

    Example:

    JoinResult { enter, update, exit } <- joinData [1, 2, 3] "circle" svg
    enterEls <- append Circle [...] enter
    updateEls <- setAttrs [...] update
    remove exit
    merged <- merge enterEls updateEls
    
  • joinDataWithKey :: forall f parent parentDatum datum key. Foldable f => Ord key => f datum -> (datum -> key) -> String -> sel SEmpty parent parentDatum -> m (JoinResult sel parent datum)

    Data join with custom key function

    Like joinData, but uses a key function to extract comparable keys instead of requiring Ord on the data itself.

    This is essential for data types that don't have lawful Ord instances (e.g., opaque foreign types like D3Link_Swizzled).

    Example:

    JoinResult { enter, update, exit } <- joinDataWithKey links (\l -> l.id) "line" svg
    
  • updateJoin :: forall f parent parentDatum datum key elemType. Foldable f => Ord key => sel SEmpty parent parentDatum -> elemType -> f datum -> (datum -> key) -> String -> m (JoinResult sel parent datum)

    Update join with key function

    Performs a data join using a key function for object constancy. The element type parameter is for API consistency but not used internally.

    Example:

    openSel <- openSelection letterGroup "text"
    { enter, update, exit } <- updateJoin openSel Text letters charToKey "text"
    
  • append :: forall parent datum. ElementType -> Array (Attribute datum) -> sel SPending parent datum -> m (sel SBoundOwns Element datum)

    Append new elements to a pending (enter) selection

    Creates DOM elements for each datum and applies attributes. Returns a bound selection.

  • setAttrs :: forall datum. Array (Attribute datum) -> sel SBoundOwns Element datum -> m (sel SBoundOwns Element datum)

    Set attributes on a bound selection

    Updates existing elements with new attribute values. Returns the updated selection.

  • setAttrsExit :: forall datum. Array (Attribute datum) -> sel SExiting Element datum -> m (sel SExiting Element datum)

    Set attributes on an exiting selection

    Similar to setAttrs but works on selections in the exit phase. Useful for styling elements before they animate out and are removed.

  • remove :: forall datum. sel SExiting Element datum -> m Unit

    Remove elements from an exit selection

    Removes elements from the DOM.

  • clear :: String -> m Unit

    Clear all children from an element

    Selects the element and removes all its children. Useful for clearing a container before rendering new content.

    Example:

    clear "#viz"
    svg <- appendChild SVG [...] container
    
  • merge :: forall datum. sel SBoundOwns Element datum -> sel SBoundOwns Element datum -> m (sel SBoundOwns Element datum)

    Merge two bound selections

    Combines selections in document order (following D3 semantics). Useful for combining enter and update selections.

  • appendChild :: forall parent datum datumOut. ElementType -> Array (Attribute datumOut) -> sel SEmpty parent datum -> m (sel SEmpty Element datumOut)

    Append a single child element to a parent selection

    Creates one new element and appends it to each parent. Returns an empty selection of the newly created element(s).

    Example:

    container <- select "#viz"
    svg <- appendChild SVG [width 400.0, height 150.0] container
    
  • appendChildInheriting :: forall parent datum. ElementType -> Array (Attribute datum) -> sel SBoundOwns parent datum -> m (sel SBoundInherits Element datum)

    Append a child element that inherits the parent's data

    Creates one child element for each parent, copying the parent's data. Returns a selection with SBoundInherits state to document data inheritance.

    This enables nested data-bound structures like:

    -- Create groups with data
    groups <- append Group [] enterSelection  -- SBoundOwns
    
    -- Add circles that inherit group's data
    circles <- appendChildInheriting Circle [radius 5.0] groups  -- SBoundInherits
    
    -- Add text that also inherits group's data
    labels <- appendChildInheriting Text [textContent _.name] groups  -- SBoundInherits
    
  • on :: forall state elem datum. Behavior datum -> sel state elem datum -> m (sel state elem datum)

    Attach a behavior (zoom, drag, etc.) to a selection

    Returns the selection unchanged to allow chaining.

    Example:

    svg <- appendChild SVG [...] container
    zoomGroup <- appendChild Group [...] svg
    _ <- on (Drag defaultDrag) zoomGroup
    _ <- on (Zoom $ defaultZoom (ScaleExtent 0.5 4.0) ".zoom-group") svg
    
  • renderTree :: forall parent parentDatum datum. Ord datum => sel SEmpty parent parentDatum -> Tree datum -> m (Map String (sel SBoundOwns Element datum))

    Declarative tree rendering (high-level API)

    Renders an entire tree structure at once, returning a map of named selections. This is the declarative alternative to imperative appendChild chains.

    Example:

    import Hylograph.AST as T
    
    tree =
      T.named "svg" SVG [width 800] `T.withChildren`
        [ T.named "zoom" Group [class_ "zoom"] `T.withChild`
            T.named "nodes" Group [class_ "nodes"]
        ]
    
    container <- select "#viz"
    selections <- renderTree container tree
    
    -- Access named selections
    case Map.lookup "svg" selections of
      Just svg -> ...
      Nothing -> ...
    

#renderTreeWithSimulation Source

renderTreeWithSimulation :: forall parent parentDatum datum m sel. SelectionM sel m => Ord datum => sel SEmpty parent parentDatum -> Tree datum -> (Map String (sel SBoundOwns Element datum) -> m Unit) -> m (Map String (sel SBoundOwns Element datum))

Render a tree and then run a callback with the named selections

This is a convenience function for integrating TreeAPI with simulations. The callback receives the map of named selections, allowing setup of simulation-related elements like data joins, tick functions, and behaviors.

This enables a declarative tree structure while still supporting the imperative setup required for D3 force simulations.

Example:

renderTreeWithSimulation container myTree \selections -> do
  case Map.lookup "nodes" selections of
    Just nodesGroup -> do
      -- Set up simulation with the nodes group
      _ <- init { nodes: data, links: links, ... }
      JoinResult { enter, update, exit } <- joinData nodes "g" nodesGroup
      -- ... handle enter/update/exit
    Nothing -> pure unit

#withDatumType Source

withDatumType :: forall sel elem datumIn datumOut. sel SEmpty elem datumIn -> sel SEmpty elem datumOut

Cast the phantom datum type of an empty selection

This is safe because SEmpty selections have no data bound - the datum type is purely a phantom type that will be "filled in" when data is later bound.

Use this to prepare container selections for genericUpdateSimulation which expects specific datum types even though the selections are empty.

Example:

nodesGroup <- appendChild Group [ class_ "nodes" ] inner
linksGroup <- appendChild Group [ class_ "links" ] inner

-- Cast the phantom types for genericUpdateSimulation
genericUpdateSimulation
  { nodes: withDatumType nodesGroup
  , links: withDatumType linksGroup
  }
  ...
Modules
Data.DependencyGraph
Hylograph.AST
Hylograph.Axis.Axis
Hylograph.Brush
Hylograph.Brush.FFI
Hylograph.Brush.Types
Hylograph.Classify
Hylograph.Data.Graph
Hylograph.Data.Graph.Algorithms
Hylograph.Data.Node
Hylograph.Data.Tree
Hylograph.Expr.Animation
Hylograph.Expr.Attr
Hylograph.Expr.Datum
Hylograph.Expr.Expr
Hylograph.Expr.Friendly
Hylograph.Expr.Integration
Hylograph.Expr.Interpreter.CodeGen
Hylograph.Expr.Interpreter.Eval
Hylograph.Expr.Interpreter.Meta
Hylograph.Expr.Interpreter.PureSVG
Hylograph.Expr.Interpreter.SVG
Hylograph.Expr.Path
Hylograph.Expr.Path.Generators
Hylograph.Expr.Sugar
Hylograph.Expr.Units
Hylograph.HATS
Hylograph.HATS.Friendly
Hylograph.HATS.InterpreterTick
Hylograph.HATS.Transitions
Hylograph.Interaction.Brush
Hylograph.Interaction.Coordinated
Hylograph.Interaction.Pointer
Hylograph.Interaction.Zoom
Hylograph.Internal.Attribute
Hylograph.Internal.Behavior.FFI
Hylograph.Internal.Behavior.Types
Hylograph.Internal.Capabilities.Selection
Hylograph.Internal.Capabilities.Transition
Hylograph.Internal.FFI
Hylograph.Internal.Selection.Join
Hylograph.Internal.Selection.Operations
Hylograph.Internal.Selection.Operations.Conversions
Hylograph.Internal.Selection.Operations.Helpers
Hylograph.Internal.Selection.Operations.Selection
Hylograph.Internal.Selection.Query
Hylograph.Internal.Selection.Types
Hylograph.Internal.Transition.FFI
Hylograph.Internal.Transition.Manager
Hylograph.Internal.Transition.Scene
Hylograph.Internal.Transition.Types
Hylograph.Internal.Types
Hylograph.Interpreter.D3
Hylograph.Interpreter.English
Hylograph.Interpreter.Mermaid
Hylograph.Interpreter.MetaAST
Hylograph.Interpreter.SemiQuine
Hylograph.Interpreter.SemiQuine.TreeToCode
Hylograph.Interpreter.SemiQuine.Types
Hylograph.Render
Hylograph.Scale
Hylograph.Scale.FP
Hylograph.Shape.Arc
Hylograph.Shape.Pie
Hylograph.Shape.Polygon
Hylograph.Tooltip
Hylograph.Transform
Hylograph.TreeDSL
Hylograph.TreeDSL.ShapeTree
Hylograph.Unified
Hylograph.Unified.Attribute
Hylograph.Unified.DataDSL
Hylograph.Unified.Display
Hylograph.Unified.Examples
Hylograph.Unified.Join
Hylograph.Unified.Sugar