packages feed

concoct-0.1.0: src/Concoct/View/Unmount.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module      : Concoct.View.Unmount
-- Copyright   : (c) Matt Hunzinger, 2026
-- License     : BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  : matt@hunzinger.me
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
module Concoct.View.Unmount (Unmount (..), runUnmount) where

import Concoct.View.Internal
import Control.Monad.State

newtype Unmount m a = Unmount {unUnmount :: StateT Stack m a}
  deriving (Functor, Applicative, Monad)

instance (MonadIO m) => MonadView m (Unmount m) where
  useState _ = Unmount $ do
    stack <- get
    let (ref, stack') = rebuildState' stack
    put stack'
    return ref
  useRef _ = Unmount $ do
    stack <- get
    let (ref, stack') = rebuildRef' stack
    put stack'
    return ref
  useEffect _ _ = Unmount $ modify skipStack
  useOnUnmount = Unmount . lift
  component v = Unmount $ do
    modify skipStack
    unUnmount v
  liftView _ = return ()
  switchView _ vTrue vFalse = Unmount $ do
    stack <- get
    let (mcond, stack') = popStack stack
    put stack'
    case mcond of
      Just cond' -> if cond' then unUnmount vTrue else unUnmount vFalse
      Nothing -> error "switchView: Condition not found in stack during unmount"
  listView _ f = Unmount $ do
    stack <- get
    let (mItems, stack') = popStack @[_] stack
    put stack'
    case mItems of
      Just items' -> mapM_ (unUnmount . f) items'
      Nothing -> error "listView: Items not found in stack during unmount"

runUnmount :: (MonadIO m) => Unmount m a -> Stack -> m (a, Stack)
runUnmount vu = runStateT (unUnmount vu)