git.iko.soy/rowtype-yoga/purescript-yoga-heroui3
on main help sign in
wave 4 overlays (Modal, Drawer, Popover, Tooltip, Dropdown, Menu)
9a3ea40Mark
src/HeroUI.pursnew file+26
@@ -0,0 +1,26 @@
1+-- | HeroUI v3 bindings.
2+-- |
3+-- | v3 components are decomposed compound components, so each lives in its
4+-- | own module meant to be imported qualified, e.g.
5+-- |
6+-- | ```purescript
7+-- | import HeroUI.Button as Button
8+-- | import HeroUI.Card as Card
9+-- | ```
10+-- |
11+-- | This umbrella re-exports only the shared semantic types
12+-- | (`HeroUI.Types`); pull components in per-module as above.
13+module HeroUI (module HeroUI.Types) where
14+
15+import HeroUI.Types
16+ ( Color(..)
17+ , colorToString
18+ , Size(..)
19+ , sizeToString
20+ , FieldVariant(..)
21+ , fieldVariantToString
22+ , SelectionMode(..)
23+ , selectionModeToString
24+ , Orientation(..)
25+ , orientationToString
26+ )
src/HeroUI/Alert.pursnew file+40
@@ -0,0 +1,40 @@
1+module HeroUI.Alert where
2+
3+import Prelude
4+
5+import React.Basic (JSX)
6+import Yoga.React.DOM.Internal (class IsJSX)
7+import Data.Function.Uncurried (runFn4)
8+import HeroUI.Types (Color, colorToString)
9+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
10+import HeroUI.Raw as Raw
11+
12+-- | Alert's `status` shares the semantic colour palette (`HeroUI.Types.Color`).
13+type AlertProps r = (status :: Color, className :: String | r)
14+
15+alert
16+ :: forall givenProps nonDataProps kids
17+ . IsJSX kids
18+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | AlertProps () }
19+ => { | givenProps }
20+ -> kids
21+ -> JSX
22+alert props kids = runFn4 createElementTransformImpl { status: colorToString } Raw.alert props kids
23+
24+type SectionProps r = (className :: String | r)
25+
26+alertIndicator
27+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
28+alertIndicator props kids = runFn4 createElementTransformImpl {} Raw.alertIndicator props kids
29+
30+alertContent
31+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
32+alertContent props kids = runFn4 createElementTransformImpl {} Raw.alertContent props kids
33+
34+alertTitle
35+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
36+alertTitle props kids = runFn4 createElementTransformImpl {} Raw.alertTitle props kids
37+
38+alertDescription
39+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
40+alertDescription props kids = runFn4 createElementTransformImpl {} Raw.alertDescription props kids
src/HeroUI/Breadcrumbs.pursnew file+31
@@ -0,0 +1,31 @@
1+module HeroUI.Breadcrumbs where
2+
3+import Prelude
4+
5+import React.Basic (JSX)
6+import Yoga.React.DOM.Internal (class IsJSX)
7+import Data.Function.Uncurried (runFn4)
8+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
9+import HeroUI.Raw as Raw
10+
11+type BreadcrumbsProps r = (separator :: JSX, className :: String | r)
12+
13+breadcrumbs
14+ :: forall givenProps nonDataProps kids
15+ . IsJSX kids
16+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | BreadcrumbsProps () }
17+ => { | givenProps }
18+ -> kids
19+ -> JSX
20+breadcrumbs props kids = runFn4 createElementTransformImpl {} Raw.breadcrumbs props kids
21+
22+type BreadcrumbsItemProps r = (href :: String, isDisabled :: Boolean, className :: String | r)
23+
24+breadcrumbsItem
25+ :: forall givenProps nonDataProps kids
26+ . IsJSX kids
27+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | BreadcrumbsItemProps () }
28+ => { | givenProps }
29+ -> kids
30+ -> JSX
31+breadcrumbsItem props kids = runFn4 createElementTransformImpl {} Raw.breadcrumbsItem props kids
src/HeroUI/Hooks.jsnew file+13
@@ -0,0 +1,13 @@
1+import {
2+ useOverlayState,
3+ useTheme,
4+ useMediaQuery,
5+ useIsHydrated,
6+ useIsMounted,
7+} from "@heroui/react";
8+
9+export const useOverlayStateImpl = (props) => useOverlayState(props);
10+export const useThemeImpl = () => useTheme();
11+export const useMediaQueryImpl = (query) => useMediaQuery(query);
12+export const useIsHydratedImpl = () => useIsHydrated();
13+export const useIsMountedImpl = () => useIsMounted();
src/HeroUI/Hooks.pursnew file+82
@@ -0,0 +1,82 @@
1+module HeroUI.Hooks
2+ ( UseOverlayState
3+ , UseOverlayStateProps
4+ , UseOverlayStateReturn
5+ , useOverlayState
6+ , UseTheme
7+ , UseThemeReturn
8+ , useTheme
9+ , UseMediaQuery
10+ , useMediaQuery
11+ , UseIsHydrated
12+ , useIsHydrated
13+ , UseIsMounted
14+ , useIsMounted
15+ ) where
16+
17+import Prelude
18+
19+import Data.Nullable (Nullable)
20+import Effect (Effect)
21+import Effect.Uncurried (EffectFn1, runEffectFn1)
22+import Prim.Row as Row
23+import React.Basic.Hooks (Hook)
24+import React.Basic.Hooks.Internal (unsafeHook)
25+import Unsafe.Coerce (unsafeCoerce)
26+
27+-- | Manages overlay open state (Modal, Drawer, Popover, ...). Replaces v2's
28+-- | `useDisclosure`. All props optional. https://heroui.com (useOverlayState)
29+type UseOverlayStateProps =
30+ ( isOpen :: Boolean
31+ , defaultOpen :: Boolean
32+ , onOpenChange :: EffectFn1 Boolean Unit
33+ )
34+
35+type UseOverlayStateReturn =
36+ ( isOpen :: Boolean
37+ , setOpen :: EffectFn1 Boolean Unit
38+ , open :: Effect Unit
39+ , close :: Effect Unit
40+ , toggle :: Effect Unit
41+ )
42+
43+foreign import data UseOverlayState :: Type -> Type
44+foreign import data UseTheme :: Type -> Type
45+foreign import data UseMediaQuery :: Type -> Type
46+foreign import data UseIsHydrated :: Type -> Type
47+foreign import data UseIsMounted :: Type -> Type
48+
49+foreign import useOverlayStateImpl :: EffectFn1 (Record UseOverlayStateProps) (Record UseOverlayStateReturn)
50+foreign import useThemeImpl :: Effect (Record UseThemeReturn)
51+foreign import useMediaQueryImpl :: EffectFn1 String Boolean
52+foreign import useIsHydratedImpl :: Effect Boolean
53+foreign import useIsMountedImpl :: Effect (Effect Boolean)
54+
55+useOverlayState
56+ :: forall props missing
57+ . Row.Union props missing UseOverlayStateProps
58+ => Record props
59+ -> Hook UseOverlayState (Record UseOverlayStateReturn)
60+useOverlayState props = unsafeHook (runEffectFn1 useOverlayStateImpl (widen props))
61+ where
62+ widen :: Record props -> Record UseOverlayStateProps
63+ widen = unsafeCoerce
64+
65+type UseThemeReturn =
66+ ( theme :: String
67+ , resolvedTheme :: Nullable String
68+ , setTheme :: EffectFn1 String Unit
69+ )
70+
71+useTheme :: Hook UseTheme (Record UseThemeReturn)
72+useTheme = unsafeHook useThemeImpl
73+
74+useMediaQuery :: String -> Hook UseMediaQuery Boolean
75+useMediaQuery query = unsafeHook (runEffectFn1 useMediaQueryImpl query)
76+
77+useIsHydrated :: Hook UseIsHydrated Boolean
78+useIsHydrated = unsafeHook useIsHydratedImpl
79+
80+-- | Returns a getter; call the inner `Effect Boolean` to read mounted state.
81+useIsMounted :: Hook UseIsMounted (Effect Boolean)
82+useIsMounted = unsafeHook useIsMountedImpl
src/HeroUI/Pagination.pursnew file+73
@@ -0,0 +1,73 @@
1+module HeroUI.Pagination where
2+
3+import Prelude
4+
5+import React.Basic (JSX)
6+import Yoga.React.DOM.Internal (class IsJSX)
7+import Data.Function.Uncurried (runFn4)
8+import HeroUI.Types (Size, sizeToString)
9+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
10+import HeroUI.Raw as Raw
11+
12+type PaginationProps r = (size :: Size, className :: String | r)
13+
14+pagination
15+ :: forall givenProps nonDataProps kids
16+ . IsJSX kids
17+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | PaginationProps () }
18+ => { | givenProps }
19+ -> kids
20+ -> JSX
21+pagination props kids = runFn4 createElementTransformImpl { size: sizeToString } Raw.pagination props kids
22+
23+type PaginationItemProps r = (isActive :: Boolean, className :: String | r)
24+
25+paginationItem
26+ :: forall givenProps nonDataProps kids
27+ . IsJSX kids
28+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | PaginationItemProps () }
29+ => { | givenProps }
30+ -> kids
31+ -> JSX
32+paginationItem props kids = runFn4 createElementTransformImpl {} Raw.paginationItem props kids
33+
34+type PaginationLinkProps r = (href :: String, isActive :: Boolean, className :: String | r)
35+
36+paginationLink
37+ :: forall givenProps nonDataProps kids
38+ . IsJSX kids
39+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | PaginationLinkProps () }
40+ => { | givenProps }
41+ -> kids
42+ -> JSX
43+paginationLink props kids = runFn4 createElementTransformImpl {} Raw.paginationLink props kids
44+
45+type SectionProps r = (className :: String | r)
46+
47+paginationSummary
48+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
49+paginationSummary props kids = runFn4 createElementTransformImpl {} Raw.paginationSummary props kids
50+
51+paginationContent
52+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
53+paginationContent props kids = runFn4 createElementTransformImpl {} Raw.paginationContent props kids
54+
55+paginationPrevious
56+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
57+paginationPrevious props kids = runFn4 createElementTransformImpl {} Raw.paginationPrevious props kids
58+
59+paginationPreviousIcon
60+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
61+paginationPreviousIcon props kids = runFn4 createElementTransformImpl {} Raw.paginationPreviousIcon props kids
62+
63+paginationNext
64+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
65+paginationNext props kids = runFn4 createElementTransformImpl {} Raw.paginationNext props kids
66+
67+paginationNextIcon
68+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
69+paginationNextIcon props kids = runFn4 createElementTransformImpl {} Raw.paginationNextIcon props kids
70+
71+paginationEllipsis
72+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
73+paginationEllipsis props kids = runFn4 createElementTransformImpl {} Raw.paginationEllipsis props kids
src/HeroUI/Progress.pursnew file+68
@@ -0,0 +1,68 @@
1+module HeroUI.Progress where
2+
3+import Prelude
4+
5+import React.Basic (JSX)
6+import Yoga.React.DOM.Internal (class IsJSX)
7+import Data.Function.Uncurried (runFn4)
8+import HeroUI.Types (Color, Size, colorToString, sizeToString)
9+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
10+import HeroUI.Raw as Raw
11+
12+type ProgressProps r =
13+ ( value :: Number
14+ , minValue :: Number
15+ , maxValue :: Number
16+ , isIndeterminate :: Boolean
17+ , color :: Color
18+ , size :: Size
19+ , className :: String
20+ | r
21+ )
22+
23+progressTransforms :: { color :: Color -> String, size :: Size -> String }
24+progressTransforms = { color: colorToString, size: sizeToString }
25+
26+progressBar
27+ :: forall givenProps nonDataProps kids
28+ . IsJSX kids
29+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | ProgressProps () }
30+ => { | givenProps }
31+ -> kids
32+ -> JSX
33+progressBar props kids = runFn4 createElementTransformImpl progressTransforms Raw.progressBar props kids
34+
35+progressCircle
36+ :: forall givenProps nonDataProps kids
37+ . IsJSX kids
38+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | ProgressProps () }
39+ => { | givenProps }
40+ -> kids
41+ -> JSX
42+progressCircle props kids = runFn4 createElementTransformImpl progressTransforms Raw.progressCircle props kids
43+
44+type SectionProps r = (className :: String | r)
45+
46+progressBarOutput
47+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
48+progressBarOutput props kids = runFn4 createElementTransformImpl {} Raw.progressBarOutput props kids
49+
50+progressBarTrack
51+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
52+progressBarTrack props kids = runFn4 createElementTransformImpl {} Raw.progressBarTrack props kids
53+
54+progressBarFill
55+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
56+progressBarFill props kids = runFn4 createElementTransformImpl {} Raw.progressBarFill props kids
57+
58+progressCircleTrack
59+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
60+progressCircleTrack props kids = runFn4 createElementTransformImpl {} Raw.progressCircleTrack props kids
61+
62+progressCircleTrackCircle
63+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
64+progressCircleTrackCircle props kids = runFn4 createElementTransformImpl {} Raw.progressCircleTrackCircle props kids
65+
66+progressCircleFillCircle
67+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
68+progressCircleFillCircle props kids = runFn4 createElementTransformImpl {} Raw.progressCircleFillCircle props kids
src/HeroUI/Raw.js+96
@@ -160,6 +160,47 @@ import {
160 MenuItemIndicator,
160 MenuItemIndicator,
161 MenuItemSubmenuIndicator,
161 MenuItemSubmenuIndicator,
162 MenuSectionRoot,
162 MenuSectionRoot,
163+ TableRoot,
164+ TableScrollContainer,
165+ TableContent,
166+ TableHeader,
167+ TableColumn,
168+ TableBody,
169+ TableRow,
170+ TableCell,
171+ TableFooter,
172+ PaginationRoot,
173+ PaginationSummary,
174+ PaginationContent,
175+ PaginationItem,
176+ PaginationLink,
177+ PaginationPrevious,
178+ PaginationPreviousIcon,
179+ PaginationNext,
180+ PaginationNextIcon,
181+ PaginationEllipsis,
182+ BreadcrumbsRoot,
183+ BreadcrumbsItem,
184+ ProgressBarRoot,
185+ ProgressBarOutput,
186+ ProgressBarTrack,
187+ ProgressBarFill,
188+ ProgressCircleRoot,
189+ ProgressCircleTrack,
190+ ProgressCircleTrackCircle,
191+ ProgressCircleFillCircle,
192+ AlertRoot,
193+ AlertIndicator,
194+ AlertContent,
195+ AlertTitle,
196+ AlertDescription,
197+ ToastProvider,
198+ ToastContent,
199+ ToastIndicator,
200+ ToastTitle,
201+ ToastDescription,
202+ ToastActionButton,
203+ ToastCloseButton,
163} from "@heroui/react";
204} from "@heroui/react";
164
205
165// Button
206// Button
@@ -392,3 +433,58 @@ export const menuItem = MenuItemRoot;
392export const menuItemIndicator = MenuItemIndicator;
433export const menuItemIndicator = MenuItemIndicator;
393export const menuItemSubmenuIndicator = MenuItemSubmenuIndicator;
434export const menuItemSubmenuIndicator = MenuItemSubmenuIndicator;
394export const menuSection = MenuSectionRoot;
435export const menuSection = MenuSectionRoot;
436+
437+// Table
438+export const table = TableRoot;
439+export const tableScrollContainer = TableScrollContainer;
440+export const tableContent = TableContent;
441+export const tableHeader = TableHeader;
442+export const tableColumn = TableColumn;
443+export const tableBody = TableBody;
444+export const tableRow = TableRow;
445+export const tableCell = TableCell;
446+export const tableFooter = TableFooter;
447+
448+// Pagination
449+export const pagination = PaginationRoot;
450+export const paginationSummary = PaginationSummary;
451+export const paginationContent = PaginationContent;
452+export const paginationItem = PaginationItem;
453+export const paginationLink = PaginationLink;
454+export const paginationPrevious = PaginationPrevious;
455+export const paginationPreviousIcon = PaginationPreviousIcon;
456+export const paginationNext = PaginationNext;
457+export const paginationNextIcon = PaginationNextIcon;
458+export const paginationEllipsis = PaginationEllipsis;
459+
460+// Breadcrumbs
461+export const breadcrumbs = BreadcrumbsRoot;
462+export const breadcrumbsItem = BreadcrumbsItem;
463+
464+// ProgressBar
465+export const progressBar = ProgressBarRoot;
466+export const progressBarOutput = ProgressBarOutput;
467+export const progressBarTrack = ProgressBarTrack;
468+export const progressBarFill = ProgressBarFill;
469+
470+// ProgressCircle
471+export const progressCircle = ProgressCircleRoot;
472+export const progressCircleTrack = ProgressCircleTrack;
473+export const progressCircleTrackCircle = ProgressCircleTrackCircle;
474+export const progressCircleFillCircle = ProgressCircleFillCircle;
475+
476+// Alert
477+export const alert = AlertRoot;
478+export const alertIndicator = AlertIndicator;
479+export const alertContent = AlertContent;
480+export const alertTitle = AlertTitle;
481+export const alertDescription = AlertDescription;
482+
483+// Toast
484+export const toastProvider = ToastProvider;
485+export const toastContent = ToastContent;
486+export const toastIndicator = ToastIndicator;
487+export const toastTitle = ToastTitle;
488+export const toastDescription = ToastDescription;
489+export const toastActionButton = ToastActionButton;
490+export const toastCloseButton = ToastCloseButton;
src/HeroUI/Raw.purs+55
@@ -232,3 +232,58 @@ foreign import menuItem :: forall r. ReactComponent { | r }
232foreign import menuItemIndicator :: forall r. ReactComponent { | r }
232foreign import menuItemIndicator :: forall r. ReactComponent { | r }
233foreign import menuItemSubmenuIndicator :: forall r. ReactComponent { | r }
233foreign import menuItemSubmenuIndicator :: forall r. ReactComponent { | r }
234foreign import menuSection :: forall r. ReactComponent { | r }
234foreign import menuSection :: forall r. ReactComponent { | r }
235+
236+-- Table
237+foreign import table :: forall r. ReactComponent { | r }
238+foreign import tableScrollContainer :: forall r. ReactComponent { | r }
239+foreign import tableContent :: forall r. ReactComponent { | r }
240+foreign import tableHeader :: forall r. ReactComponent { | r }
241+foreign import tableColumn :: forall r. ReactComponent { | r }
242+foreign import tableBody :: forall r. ReactComponent { | r }
243+foreign import tableRow :: forall r. ReactComponent { | r }
244+foreign import tableCell :: forall r. ReactComponent { | r }
245+foreign import tableFooter :: forall r. ReactComponent { | r }
246+
247+-- Pagination
248+foreign import pagination :: forall r. ReactComponent { | r }
249+foreign import paginationSummary :: forall r. ReactComponent { | r }
250+foreign import paginationContent :: forall r. ReactComponent { | r }
251+foreign import paginationItem :: forall r. ReactComponent { | r }
252+foreign import paginationLink :: forall r. ReactComponent { | r }
253+foreign import paginationPrevious :: forall r. ReactComponent { | r }
254+foreign import paginationPreviousIcon :: forall r. ReactComponent { | r }
255+foreign import paginationNext :: forall r. ReactComponent { | r }
256+foreign import paginationNextIcon :: forall r. ReactComponent { | r }
257+foreign import paginationEllipsis :: forall r. ReactComponent { | r }
258+
259+-- Breadcrumbs
260+foreign import breadcrumbs :: forall r. ReactComponent { | r }
261+foreign import breadcrumbsItem :: forall r. ReactComponent { | r }
262+
263+-- ProgressBar
264+foreign import progressBar :: forall r. ReactComponent { | r }
265+foreign import progressBarOutput :: forall r. ReactComponent { | r }
266+foreign import progressBarTrack :: forall r. ReactComponent { | r }
267+foreign import progressBarFill :: forall r. ReactComponent { | r }
268+
269+-- ProgressCircle
270+foreign import progressCircle :: forall r. ReactComponent { | r }
271+foreign import progressCircleTrack :: forall r. ReactComponent { | r }
272+foreign import progressCircleTrackCircle :: forall r. ReactComponent { | r }
273+foreign import progressCircleFillCircle :: forall r. ReactComponent { | r }
274+
275+-- Alert
276+foreign import alert :: forall r. ReactComponent { | r }
277+foreign import alertIndicator :: forall r. ReactComponent { | r }
278+foreign import alertContent :: forall r. ReactComponent { | r }
279+foreign import alertTitle :: forall r. ReactComponent { | r }
280+foreign import alertDescription :: forall r. ReactComponent { | r }
281+
282+-- Toast
283+foreign import toastProvider :: forall r. ReactComponent { | r }
284+foreign import toastContent :: forall r. ReactComponent { | r }
285+foreign import toastIndicator :: forall r. ReactComponent { | r }
286+foreign import toastTitle :: forall r. ReactComponent { | r }
287+foreign import toastDescription :: forall r. ReactComponent { | r }
288+foreign import toastActionButton :: forall r. ReactComponent { | r }
289+foreign import toastCloseButton :: forall r. ReactComponent { | r }
src/HeroUI/Table.pursnew file+93
@@ -0,0 +1,93 @@
1+module HeroUI.Table where
2+
3+import Prelude
4+
5+import Effect.Uncurried (EffectFn1)
6+import Foreign (Foreign)
7+import React.Basic (JSX)
8+import Yoga.React.DOM.Internal (class IsJSX)
9+import Data.Function.Uncurried (runFn4)
10+import HeroUI.Types (SelectionMode, selectionModeToString)
11+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
12+import HeroUI.Raw as Raw
13+
14+type TableProps r = (variant :: String, className :: String | r)
15+
16+table
17+ :: forall givenProps nonDataProps kids
18+ . IsJSX kids
19+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | TableProps () }
20+ => { | givenProps }
21+ -> kids
22+ -> JSX
23+table props kids = runFn4 createElementTransformImpl {} Raw.table props kids
24+
25+-- | The react-aria table that owns selection/sort state.
26+type TableContentProps r =
27+ ( selectionMode :: SelectionMode
28+ , selectedKeys :: Array String
29+ , defaultSelectedKeys :: Array String
30+ , onSelectionChange :: EffectFn1 Foreign Unit
31+ , disabledKeys :: Array String
32+ , className :: String
33+ | r
34+ )
35+
36+tableContent
37+ :: forall givenProps nonDataProps kids
38+ . IsJSX kids
39+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | TableContentProps () }
40+ => { | givenProps }
41+ -> kids
42+ -> JSX
43+tableContent props kids = runFn4 createElementTransformImpl { selectionMode: selectionModeToString } Raw.tableContent props kids
44+
45+type TableColumnProps r =
46+ ( id :: String
47+ , isRowHeader :: Boolean
48+ , allowsSorting :: Boolean
49+ , className :: String
50+ | r
51+ )
52+
53+tableColumn
54+ :: forall givenProps nonDataProps kids
55+ . IsJSX kids
56+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | TableColumnProps () }
57+ => { | givenProps }
58+ -> kids
59+ -> JSX
60+tableColumn props kids = runFn4 createElementTransformImpl {} Raw.tableColumn props kids
61+
62+type TableRowProps r = (id :: String, className :: String | r)
63+
64+tableRow
65+ :: forall givenProps nonDataProps kids
66+ . IsJSX kids
67+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | TableRowProps () }
68+ => { | givenProps }
69+ -> kids
70+ -> JSX
71+tableRow props kids = runFn4 createElementTransformImpl {} Raw.tableRow props kids
72+
73+type SectionProps r = (className :: String | r)
74+
75+tableScrollContainer
76+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
77+tableScrollContainer props kids = runFn4 createElementTransformImpl {} Raw.tableScrollContainer props kids
78+
79+tableHeader
80+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
81+tableHeader props kids = runFn4 createElementTransformImpl {} Raw.tableHeader props kids
82+
83+tableBody
84+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
85+tableBody props kids = runFn4 createElementTransformImpl {} Raw.tableBody props kids
86+
87+tableCell
88+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
89+tableCell props kids = runFn4 createElementTransformImpl {} Raw.tableCell props kids
90+
91+tableFooter
92+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
93+tableFooter props kids = runFn4 createElementTransformImpl {} Raw.tableFooter props kids
src/HeroUI/Toast.jsnew file+10
@@ -0,0 +1,10 @@
1+import { toast } from "@heroui/react";
2+
3+export const toastSuccessImpl = (message) => toast.success(message);
4+export const toastDangerImpl = (message) => toast.danger(message);
5+export const toastInfoImpl = (message) => toast.info(message);
6+export const toastWarningImpl = (message) => toast.warning(message);
7+export const closeToastImpl = (key) => toast.close(key);
8+export const closeAllToastsImpl = () => toast.clear();
9+export const pauseAllToastsImpl = () => toast.pauseAll();
10+export const resumeAllToastsImpl = () => toast.resumeAll();
src/HeroUI/Toast.pursnew file+89
@@ -0,0 +1,89 @@
1+module HeroUI.Toast where
2+
3+import Prelude
4+
5+import Effect (Effect)
6+import Effect.Uncurried (EffectFn1, runEffectFn1)
7+import React.Basic (JSX)
8+import Yoga.React.DOM.Internal (class IsJSX)
9+import Data.Function.Uncurried (runFn4)
10+import HeroUI.Internal (class CoerceHeroProps, createElementTransformImpl)
11+import HeroUI.Raw as Raw
12+
13+-- Render the provider once near the root of the app; fire toasts imperatively.
14+type ToastProviderProps r =
15+ ( placement :: String
16+ , maxVisibleToasts :: Int
17+ , className :: String
18+ | r
19+ )
20+
21+toastProvider
22+ :: forall givenProps nonDataProps kids
23+ . IsJSX kids
24+ => CoerceHeroProps { | givenProps } { | nonDataProps } { | ToastProviderProps () }
25+ => { | givenProps }
26+ -> kids
27+ -> JSX
28+toastProvider props kids = runFn4 createElementTransformImpl {} Raw.toastProvider props kids
29+
30+type SectionProps r = (className :: String | r)
31+
32+toastContent
33+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
34+toastContent props kids = runFn4 createElementTransformImpl {} Raw.toastContent props kids
35+
36+toastIndicator
37+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
38+toastIndicator props kids = runFn4 createElementTransformImpl {} Raw.toastIndicator props kids
39+
40+toastTitle
41+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
42+toastTitle props kids = runFn4 createElementTransformImpl {} Raw.toastTitle props kids
43+
44+toastDescription
45+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
46+toastDescription props kids = runFn4 createElementTransformImpl {} Raw.toastDescription props kids
47+
48+toastActionButton
49+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
50+toastActionButton props kids = runFn4 createElementTransformImpl {} Raw.toastActionButton props kids
51+
52+toastCloseButton
53+ :: forall g n k. IsJSX k => CoerceHeroProps { | g } { | n } { | SectionProps () } => { | g } -> k -> JSX
54+toastCloseButton props kids = runFn4 createElementTransformImpl {} Raw.toastCloseButton props kids
55+
56+-- | Imperative toast API. Each `toastX` fires a toast and returns its key,
57+-- | which you can later pass to `closeToast`.
58+foreign import toastSuccessImpl :: EffectFn1 JSX String
59+foreign import toastDangerImpl :: EffectFn1 JSX String
60+foreign import toastInfoImpl :: EffectFn1 JSX String
61+foreign import toastWarningImpl :: EffectFn1 JSX String
62+foreign import closeToastImpl :: EffectFn1 String Unit
63+foreign import closeAllToastsImpl :: Effect Unit
64+foreign import pauseAllToastsImpl :: Effect Unit
65+foreign import resumeAllToastsImpl :: Effect Unit
66+
67+toastSuccess :: JSX -> Effect String
68+toastSuccess = runEffectFn1 toastSuccessImpl
69+
70+toastDanger :: JSX -> Effect String
71+toastDanger = runEffectFn1 toastDangerImpl
72+
73+toastInfo :: JSX -> Effect String
74+toastInfo = runEffectFn1 toastInfoImpl
75+
76+toastWarning :: JSX -> Effect String
77+toastWarning = runEffectFn1 toastWarningImpl
78+
79+closeToast :: String -> Effect Unit
80+closeToast = runEffectFn1 closeToastImpl
81+
82+closeAllToasts :: Effect Unit
83+closeAllToasts = closeAllToastsImpl
84+
85+pauseAllToasts :: Effect Unit
86+pauseAllToasts = pauseAllToastsImpl
87+
88+resumeAllToasts :: Effect Unit
89+resumeAllToasts = resumeAllToastsImpl
test/HeroUI/Button/Stories.pursnew file+65
@@ -0,0 +1,65 @@
1+module HeroUI.Button.Stories (primary, variants) where
2+
3+import Prelude hiding (div)
4+
5+import Data.Generic.Rep (class Generic)
6+import React.Basic (JSX)
7+import HeroUI.Button as Btn
8+import HeroUI.Types as T
9+import Yoga.React (component)
10+import Yoga.React.DOM.HTML (div)
11+import Yoga.React.DOM.Internal (text)
12+import YogaStories.Controls (enum)
13+import YogaStories.Story (story)
14+
15+-- | v3 merges v2's `color` + `variant` into a single `variant`.
16+data Variant = Primary | Secondary | Tertiary | Ghost | Outline | Danger | DangerSoft
17+
18+derive instance Generic Variant _
19+
20+data Size = Small | Medium | Large
21+
22+derive instance Generic Size _
23+
24+toVariant :: Variant -> Btn.Variant
25+toVariant = case _ of
26+ Primary -> Btn.Primary
27+ Secondary -> Btn.Secondary
28+ Tertiary -> Btn.Tertiary
29+ Ghost -> Btn.Ghost
30+ Outline -> Btn.Outline
31+ Danger -> Btn.Danger
32+ DangerSoft -> Btn.DangerSoft
33+
34+toSize :: Size -> T.Size
35+toSize = case _ of
36+ Small -> T.Sm
37+ Medium -> T.Md
38+ Large -> T.Lg
39+
40+mkButton :: { label :: String, variant :: Variant, size :: Size, isDisabled :: Boolean } -> JSX
41+mkButton = component "ButtonStory" \props -> React.do
42+ pure $ div { className: "dark bg-background text-foreground p-6 rounded-lg flex items-center gap-4" }
43+ [ Btn.button
44+ { variant: toVariant props.variant
45+ , size: toSize props.size
46+ , isDisabled: props.isDisabled
47+ }
48+ (text props.label)
49+ ]
50+
51+primary :: JSX
52+primary = story "primary" mkButton
53+ { label: "Click me"
54+ , variant: enum Primary
55+ , size: enum Medium
56+ , isDisabled: false
57+ }
58+
59+variants :: JSX
60+variants = story "variants" mkButton
61+ { label: "Button"
62+ , variant: enum Outline
63+ , size: enum Large
64+ , isDisabled: false
65+ }
test/HeroUI/HeroUI3Spec.pursnew file+108
@@ -0,0 +1,108 @@
1+module Test.HeroUI.HeroUI3Spec where
2+
3+import Prelude
4+
5+import Effect.Class (liftEffect)
6+import HeroUI.Button as Btn
7+import HeroUI.Card as Card
8+import HeroUI.Checkbox as Checkbox
9+import HeroUI.Chip as Chip
10+import HeroUI.Hooks as Hooks
11+import HeroUI.Input as Input
12+import HeroUI.Separator as Separator
13+import HeroUI.Spinner as Spinner
14+import HeroUI.Switch as Switch
15+import HeroUI.Toast as Toast
16+import HeroUI.Types as T
17+import React.Basic (JSX)
18+import React.Basic.Hooks as React
19+import React.TestingLibrary (cleanup, render)
20+import Test.Spec (Spec, after_, describe, it)
21+import Test.Spec.Assertions (shouldEqual)
22+import Test.Spec.Assertions.DOM (textContentShouldEqual)
23+import Yoga.React (component)
24+import Yoga.React.DOM.Internal (text)
25+
26+spec :: Spec Unit
27+spec = after_ cleanup $ describe "purescript-yoga-heroui3 (HeroUI v3)" do
28+ it "Button renders children and accepts a typed variant + type" do
29+ { findByText } <- render submitButton
30+ btn <- findByText "Submit"
31+ btn `textContentShouldEqual` "Submit"
32+
33+ it "Aria props compile and reach the DOM (no provider needed in v3)" do
34+ { findByLabelText } <- render ariaButton
35+ el <- findByLabelText "close dialog"
36+ el `textContentShouldEqual` "X"
37+
38+ it "Card renders as a compound component" do
39+ { findByText } <- render cardHost
40+ title <- findByText "Card title"
41+ title `textContentShouldEqual` "Card title"
42+
43+ it "Chip accepts color/size/variant from the shared + per-component types" do
44+ { findByText } <- render chipHost
45+ el <- findByText "new"
46+ el `textContentShouldEqual` "new"
47+
48+ it "Switch and Checkbox accept boolean state props" do
49+ _ <- render switchAndCheckbox
50+ pure unit
51+
52+ it "Spinner and Separator render" do
53+ _ <- render spinnerAndSeparator
54+ pure unit
55+
56+ it "useOverlayState exposes isOpen (replaces v2 useDisclosure)" do
57+ { findByText } <- render overlayHost
58+ initial <- findByText "closed"
59+ initial `textContentShouldEqual` "closed"
60+
61+ it "Toast imperative API (success/close/clear) is callable" do
62+ key <- liftEffect $ Toast.toastSuccess (text "saved")
63+ liftEffect $ Toast.closeToast key
64+ liftEffect Toast.closeAllToasts
65+
66+ it "InputType strings round-trip" do
67+ Input.inputTypeToString Input.InputTypeEmail `shouldEqual` "email"
68+ Input.inputTypeToString Input.InputTypeDateTimeLocal `shouldEqual` "datetime-local"
69+
70+submitButton :: JSX
71+submitButton =
72+ Btn.button { variant: Btn.Primary, type: Btn.ButtonTypeSubmit } (text "Submit")
73+
74+ariaButton :: JSX
75+ariaButton = Btn.button { "aria-label": "close dialog" } (text "X")
76+
77+cardHost :: JSX
78+cardHost =
79+ Card.card { variant: Card.Default }
80+ [ Card.cardHeader {} [ Card.cardTitle {} (text "Card title") ]
81+ , Card.cardContent {} (text "body")
82+ ]
83+
84+chipHost :: JSX
85+chipHost =
86+ Chip.chip { color: T.Accent, size: T.Sm, variant: Chip.Soft } (text "new")
87+
88+switchAndCheckbox :: JSX
89+switchAndCheckbox =
90+ Card.card {}
91+ [ Switch.switch_ { defaultSelected: true, size: T.Md } (text "on")
92+ , Checkbox.checkbox { defaultSelected: false, variant: T.Primary } (text "agree")
93+ ]
94+
95+spinnerAndSeparator :: JSX
96+spinnerAndSeparator =
97+ Card.card {}
98+ [ Spinner.spinner { color: Spinner.Accent, size: Spinner.Md } ([] :: Array JSX)
99+ , Separator.separator { orientation: T.Horizontal } ([] :: Array JSX)
100+ ]
101+
102+overlayHost :: JSX
103+overlayHost = overlayComponent {}
104+
105+overlayComponent :: {} -> JSX
106+overlayComponent = component "OverlayHost" \(_ :: {}) -> React.do
107+ state <- Hooks.useOverlayState {}
108+ pure $ text (if state.isOpen then "open" else "closed")
test/JsdomSetup.jsnew file+3
@@ -0,0 +1,3 @@
1+import "global-jsdom/register";
2+
3+export const registerJsdomImpl = () => {};
test/JsdomSetup.pursnew file+9
@@ -0,0 +1,9 @@
1+module Test.JsdomSetup where
2+
3+import Prelude
4+import Effect (Effect)
5+
6+foreign import registerJsdomImpl :: Effect Unit
7+
8+registerJsdom :: Effect Unit
9+registerJsdom = registerJsdomImpl
test/Main.pursnew file+15
@@ -0,0 +1,15 @@
1+module Test.Main where
2+
3+import Prelude
4+
5+import Effect (Effect)
6+import Effect.Aff (launchAff_)
7+import Test.HeroUI.HeroUI3Spec as HeroUI3Spec
8+import Test.JsdomSetup (registerJsdom)
9+import Test.Spec.Reporter (consoleReporter)
10+import Test.Spec.Runner (runSpec)
11+
12+main :: Effect Unit
13+main = do
14+ registerJsdom
15+ launchAff_ $ runSpec [ consoleReporter ] HeroUI3Spec.spec