1
Fork 0

Remove SProxy reference

This commit is contained in:
prescientmoon 2025-06-09 00:11:33 +02:00
commit c5b397497a
Signed by: prescientmoon
SSH key fingerprint: SHA256:WFp/cO76nbarETAoQcQXuV+0h7XJsEsOCI0UsyPIy6U
4 changed files with 54 additions and 44 deletions

1
.gitignore vendored
View file

@ -6,6 +6,7 @@ node_modules
# Generated files # Generated files
.psci .psci
.psc-ide-port .psc-ide-port
.spago
output output
package-lock.json package-lock.json
generated-docs generated-docs

View file

@ -1,4 +1,7 @@
# Select # Select
> [!NOTE]
> This fork makes this package work with newer PureScript versions, by removing a stale `SProxy` import. This fork is here for personal use only. Use at your own risk.
[![CircleCI](https://circleci.com/gh/citizennet/purescript-halogen-select/tree/master.svg?style=shield)](https://circleci.com/gh/citizennet/purescript-halogen-select/tree/master) [![CircleCI](https://circleci.com/gh/citizennet/purescript-halogen-select/tree/master.svg?style=shield)](https://circleci.com/gh/citizennet/purescript-halogen-select/tree/master)
[![Maintainer: thomashoneyman](https://img.shields.io/badge/maintainer-thomashoneyman-lightgrey.svg)](http://github.com/thomashoneyman) [![Maintainer: thomashoneyman](https://img.shields.io/badge/maintainer-thomashoneyman-lightgrey.svg)](http://github.com/thomashoneyman)
@ -31,18 +34,17 @@ For more information, try the [official documentation](https://citizennet.github
The library provides essential behaviors for selection user interfaces as a group of Halogen components. But you won't find a single render function in the code. Instead, with the help of a few `setProps` helpers, you can write your HTML rendering however you'd like. You can freely include your own queries and the library will return them to be run. You can even use any data you want from your parent state in your render functions. The library manages user interaction, state, accessibility, and logic; you are responsible for rendering HTML depending on that state. The library provides essential behaviors for selection user interfaces as a group of Halogen components. But you won't find a single render function in the code. Instead, with the help of a few `setProps` helpers, you can write your HTML rendering however you'd like. You can freely include your own queries and the library will return them to be run. You can even use any data you want from your parent state in your render functions. The library manages user interaction, state, accessibility, and logic; you are responsible for rendering HTML depending on that state.
1. Provide behaviors, not styles 1. Provide behaviors, not styles
Developers should be able to style and display dropdowns and typeaheads however they would like, rather than be forced to use particular CSS classes or re-implement the component with their HTML. This is accomplished with augmented render functions as described below. We provide the machinery; you provide the HTML and styles. Developers should be able to style and display dropdowns and typeaheads however they would like, rather than be forced to use particular CSS classes or re-implement the component with their HTML. This is accomplished with augmented render functions as described below. We provide the machinery; you provide the HTML and styles.
2. Export the building blocks, not just the end result 2. Export the building blocks, not just the end result
Developers should be able to take a core set of behaviors and choose how they would like to handle them in their own version of the component. If you would like the typeahead's functionality but do something fancy with the selected items, you should be able to. Each building block is exported. Developers should be able to take a core set of behaviors and choose how they would like to handle them in their own version of the component. If you would like the typeahead's functionality but do something fancy with the selected items, you should be able to. Each building block is exported.
3. Require minimal configuration 3. Require minimal configuration
Instantiating a typeahead shouldn't require a 50-field configuration record. We require at minimum two things: the data to populate the menu and the HTML to render that data. The rest is taken care of by the component. You are responsible for handling two things: when an item was selected, and when the user has performed a new search. If you want to do even less, you can use one of our default implementations to drop in to your project. Instantiating a typeahead shouldn't require a 50-field configuration record. We require at minimum two things: the data to populate the menu and the HTML to render that data. The rest is taken care of by the component. You are responsible for handling two things: when an item was selected, and when the user has performed a new search. If you want to do even less, you can use one of our default implementations to drop in to your project.
4. Be accessible (Upcoming)
ARIA props and other features necessary for accessibility online should be handled properly without any setup.
4. Be accessible (Upcoming)
ARIA props and other features necessary for accessibility online should be handled properly without any setup.
# Rendering # Rendering
@ -61,10 +63,8 @@ For example, you can make your container compatible with the component with the
] ]
``` ```
> Warning: If you provide any of the same events that we use for our behaviors, only yours will trigger, preventing that behavior from being applied. E.g., if you provide your own `HE.onValueInput` event on the element you're applying `setInputProps` to, you will end up overriding our search functionality for that input. > Warning: If you provide any of the same events that we use for our behaviors, only yours will trigger, preventing that behavior from being applied. E.g., if you provide your own `HE.onValueInput` event on the element you're applying `setInputProps` to, you will end up overriding our search functionality for that input.
## Inspiration & Thanks ## Inspiration & Thanks
This project drew inspiration from the approach taken by [paypal/downshift](https://github.com/paypal/downshift). Special thanks to [Nathan Faubion](https://github.com/natefaubion) and [Nicholas Scheel](https://github.com/MonoidMusician) for their help. This project drew inspiration from the approach taken by [paypal/downshift](https://github.com/paypal/downshift). Special thanks to [Nathan Faubion](https://github.com/natefaubion) and [Nicholas Scheel](https://github.com/MonoidMusician) for their help.

9
spago.yaml Normal file
View file

@ -0,0 +1,9 @@
package:
name: halogen-select
dependencies:
- halogen
- record
workspace:
packageSet:
registry: 64.10.0
extraPackages: {}

View file

@ -10,7 +10,6 @@ import Prelude
import Control.Monad.Free (liftF) import Control.Monad.Free (liftF)
import Data.Const (Const) import Data.Const (Const)
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Symbol (SProxy(..))
import Data.Time.Duration (Milliseconds) import Data.Time.Duration (Milliseconds)
import Data.Traversable (for_, traverse, traverse_) import Data.Traversable (for_, traverse, traverse_)
import Effect.Aff (Fiber, delay, error, forkAff, killFiber) import Effect.Aff (Fiber, delay, error, forkAff, killFiber)
@ -24,6 +23,7 @@ import Halogen.HTML as HH
import Halogen.Query.ChildQuery (ChildQueryBox) import Halogen.Query.ChildQuery (ChildQueryBox)
import Prim.Row as Row import Prim.Row as Row
import Record.Builder as Builder import Record.Builder as Builder
import Type.Prelude (Proxy(..))
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
import Web.Event.Event (preventDefault) import Web.Event.Event (preventDefault)
import Web.HTML.HTMLElement as HTMLElement import Web.HTML.HTMLElement as HTMLElement
@ -73,6 +73,7 @@ type Slot' = Slot (Const Void) () Void
-- | Represents a way to navigate on `Highlight` events: to the previous -- | Represents a way to navigate on `Highlight` events: to the previous
-- | item, next item, or the item at a particular index. -- | item, next item, or the item at a particular index.
data Target = Prev | Next | Index Int data Target = Prev | Next | Index Int
derive instance eqTarget :: Eq Target derive instance eqTarget :: Eq Target
-- | Represents whether the component should display the item container. You -- | Represents whether the component should display the item container. You
@ -82,6 +83,7 @@ derive instance eqTarget :: Eq Target
-- | render state = if state.visibility == On then renderAll else renderInputOnly -- | render state = if state.visibility == On then renderAll else renderInputOnly
-- | ``` -- | ```
data Visibility = Off | On data Visibility = Off | On
derive instance eqVisibility :: Eq Visibility derive instance eqVisibility :: Eq Visibility
derive instance ordVisibility :: Ord Visibility derive instance ordVisibility :: Ord Visibility
@ -98,7 +100,7 @@ type State st =
, debounceRef :: Maybe (Ref (Maybe Debouncer)) , debounceRef :: Maybe (Ref (Maybe Debouncer))
, visibility :: Visibility , visibility :: Visibility
, highlightedIndex :: Maybe Int , highlightedIndex :: Maybe Int
, getItemCount :: {| st } -> Int , getItemCount :: { | st } -> Int
| st | st
} }
@ -111,7 +113,7 @@ type Input st =
{ inputType :: InputType { inputType :: InputType
, search :: Maybe String , search :: Maybe String
, debounceTime :: Maybe Milliseconds , debounceTime :: Maybe Milliseconds
, getItemCount :: {| st } -> Int , getItemCount :: { | st } -> Int
| st | st
} }
@ -126,39 +128,37 @@ type HalogenM st action slots msg m a =
type Spec st query action slots input msg m = type Spec st query action slots input msg m =
{ -- usual Halogen component spec { -- usual Halogen component spec
render render ::
:: State st State st
-> ComponentHTML action slots m -> ComponentHTML action slots m
-- handle additional actions provided to the component -- handle additional actions provided to the component
, handleAction , handleAction ::
:: action action
-> HalogenM st action slots msg m Unit -> HalogenM st action slots msg m Unit
-- handle additional queries provided to the component -- handle additional queries provided to the component
, handleQuery , handleQuery ::
:: forall a forall a
. query a . query a
-> HalogenM st action slots msg m (Maybe a) -> HalogenM st action slots msg m (Maybe a)
-- handle messages emitted by the component; provide H.raise to simply -- handle messages emitted by the component; provide H.raise to simply
-- raise the Select messages to the parent. -- raise the Select messages to the parent.
, handleEvent , handleEvent ::
:: Event Event
-> HalogenM st action slots msg m Unit -> HalogenM st action slots msg m Unit
-- optionally handle input on parent re-renders -- optionally handle input on parent re-renders
, receive , receive ::
:: input input
-> Maybe action -> Maybe action
-- perform some action when the component initializes. -- perform some action when the component initializes.
, initialize , initialize :: Maybe action
:: Maybe action
-- optionally perform some action on initialization. disabled by default. -- optionally perform some action on initialization. disabled by default.
, finalize , finalize :: Maybe action
:: Maybe action
} }
type Spec' st input m = Spec st (Const Void) Void () input Void m type Spec' st input m = Spec st (Const Void) Void () input Void m
@ -201,11 +201,11 @@ component mkInput spec = H.mkComponent
initialState = Builder.build pipeline initialState = Builder.build pipeline
where where
pipeline = pipeline =
Builder.modify (SProxy :: _ "search") (fromMaybe "") Builder.modify (Proxy :: _ "search") (fromMaybe "")
>>> Builder.modify (SProxy :: _ "debounceTime") (fromMaybe mempty) >>> Builder.modify (Proxy :: _ "debounceTime") (fromMaybe mempty)
>>> Builder.insert (SProxy :: _ "debounceRef") Nothing >>> Builder.insert (Proxy :: _ "debounceRef") Nothing
>>> Builder.insert (SProxy :: _ "visibility") Off >>> Builder.insert (Proxy :: _ "visibility") Off
>>> Builder.insert (SProxy :: _ "highlightedIndex") Nothing >>> Builder.insert (Proxy :: _ "highlightedIndex") Nothing
handleQuery handleQuery
:: forall st query action slots msg m a :: forall st query action slots msg m a
@ -244,7 +244,7 @@ handleAction handleAction' handleEvent = case _ of
case st.inputType, ref of case st.inputType, ref of
Text, Nothing -> unit <$ do Text, Nothing -> unit <$ do
var <- H.liftAff AVar.empty var <- H.liftAff AVar.empty
fiber <- H.liftAff $ forkAff do fiber <- H.liftAff $ forkAff do
delay st.debounceTime delay st.debounceTime
AVar.put unit var AVar.put unit var
@ -319,7 +319,7 @@ handleAction handleAction' handleEvent = case _ of
preventIt preventIt
for_ st.highlightedIndex \ix -> for_ st.highlightedIndex \ix ->
handle $ Select (Index ix) Nothing handle $ Select (Index ix) Nothing
otherKey -> pure unit _ -> pure unit
PreventClick ev -> PreventClick ev ->
H.liftEffect $ preventDefault $ ME.toEvent ev H.liftEffect $ preventDefault $ ME.toEvent ev
@ -348,7 +348,7 @@ handleAction handleAction' handleEvent = case _ of
-- we know that the getItemCount function will only touch user fields, -- we know that the getItemCount function will only touch user fields,
-- and that the state record contains *at least* the user fields, so -- and that the state record contains *at least* the user fields, so
-- this saves us from a set of unnecessary record deletions / modifications -- this saves us from a set of unnecessary record deletions / modifications
userState :: State st -> {| st } userState :: State st -> { | st }
userState = unsafeCoerce userState = unsafeCoerce
lastIndex :: State st -> Int lastIndex :: State st -> Int