git.iko.soy/rowtype-yoga/purescript-yoga-react-native
on main help sign in
93 files changed+1052−455
since splitsnapshots
unifiedsplit
README.md+1 docs/src/Docs/Pages/DataViews.purs+32−19 docs/src/Docs/Pages/Display.purs+2−2 docs/src/Docs/Pages/FilesAndDragDrop.purs+24−19 docs/src/Docs/Pages/InputControls.purs+110−67 docs/src/Docs/Pages/LayoutPage.purs+12−12 docs/src/Docs/Pages/Overlays.purs+45−28 docs/src/Docs/Pages/QuickStart.purs+1−1 docs/src/Docs/Pages/RichMedia.purs+33−20 docs/src/Docs/Pages/SystemServices.purs+8−5 docs/src/Docs/Pages/TextEditing.purs+12−12 example-macos/src/Demo/AiMl.purs+13−17 example-macos/src/Demo/Chat.purs+11−13 example-macos/src/Demo/DataViews.purs+3−4 example-macos/src/Demo/Display.purs+3−4 example-macos/src/Demo/DragDropFiles.purs+26−26 example-macos/src/Demo/InputControls.purs+28−28 example-macos/src/Demo/Layout.purs+1−2 example-macos/src/Demo/MapsDocs.purs+1−2 example-macos/src/Demo/Navigation.purs+6−4 example-macos/src/Demo/Overlays.purs+11−13 example-macos/src/Demo/SpringAnimation.purs+123 example-macos/src/Demo/SystemServices.purs+28−30 example-macos/src/Demo/TextEditing.purs+1−2 example-macos/src/Demo/WebBrowser.purs+4−10 example-macos/src/Main.purs+1−2 spago.lock+10−1 spago.yaml+5−2 src/Yoga/React/Native/Animated.js+24−1 src/Yoga/React/Native/Animated.purs+9 src/Yoga/React/Native/MacOS/Alert.purs+2−1 src/Yoga/React/Native/MacOS/Button.js+9−1 src/Yoga/React/Native/MacOS/Button.purs+3−2 src/Yoga/React/Native/MacOS/Checkbox.js+9−1 src/Yoga/React/Native/MacOS/Checkbox.purs+3−2 src/Yoga/React/Native/MacOS/ColorWell.js+9−1 src/Yoga/React/Native/MacOS/ColorWell.purs+3−2 src/Yoga/React/Native/MacOS/ComboBox.js+12−1 src/Yoga/React/Native/MacOS/ComboBox.purs+4−3 src/Yoga/React/Native/MacOS/ContextMenu.js+10−1 src/Yoga/React/Native/MacOS/ContextMenu.purs+3−2 src/Yoga/React/Native/MacOS/DatePicker.js+9−1 src/Yoga/React/Native/MacOS/DatePicker.purs+3−2 src/Yoga/React/Native/MacOS/DropZone.js+21−1 src/Yoga/React/Native/MacOS/DropZone.purs+11−5 src/Yoga/React/Native/MacOS/FilePicker.js+13−1 src/Yoga/React/Native/MacOS/FilePicker.purs+10−4 src/Yoga/React/Native/MacOS/HelpButton.js+9−1 src/Yoga/React/Native/MacOS/HelpButton.purs+3−2 src/Yoga/React/Native/MacOS/MapView.js+21−1 src/Yoga/React/Native/MacOS/MapView.purs+12−3 src/Yoga/React/Native/MacOS/Menu.js+1−1 src/Yoga/React/Native/MacOS/Menu.purs+10−4 src/Yoga/React/Native/MacOS/OutlineView.js+9−1 src/Yoga/React/Native/MacOS/OutlineView.purs+3−2 src/Yoga/React/Native/MacOS/PDFView.js+10−1 src/Yoga/React/Native/MacOS/PDFView.purs+3−2 src/Yoga/React/Native/MacOS/PathControl.js+9−1 src/Yoga/React/Native/MacOS/PathControl.purs+3−2 src/Yoga/React/Native/MacOS/PopUp.js+10−1 src/Yoga/React/Native/MacOS/PopUp.purs+3−2 src/Yoga/React/Native/MacOS/Popover.js+9−1 src/Yoga/React/Native/MacOS/Popover.purs+3−2 src/Yoga/React/Native/MacOS/RadioButton.js+9−1 src/Yoga/React/Native/MacOS/RadioButton.purs+3−2 src/Yoga/React/Native/MacOS/SearchField.js+12−1 src/Yoga/React/Native/MacOS/SearchField.purs+4−3 src/Yoga/React/Native/MacOS/Segmented.js+10−1 src/Yoga/React/Native/MacOS/Segmented.purs+3−2 src/Yoga/React/Native/MacOS/Sheet.js+9−1 src/Yoga/React/Native/MacOS/Sheet.purs+3−2 src/Yoga/React/Native/MacOS/Slider.js+11−1 src/Yoga/React/Native/MacOS/Slider.purs+3−2 src/Yoga/React/Native/MacOS/Stepper.js+9−1 src/Yoga/React/Native/MacOS/Stepper.purs+3−2 src/Yoga/React/Native/MacOS/Switch.js+11−1 src/Yoga/React/Native/MacOS/Switch.purs+3−2 src/Yoga/React/Native/MacOS/TabView.js+9−1 src/Yoga/React/Native/MacOS/TabView.purs+3−2 src/Yoga/React/Native/MacOS/TableView.js+14−1 src/Yoga/React/Native/MacOS/TableView.purs+4−3 src/Yoga/React/Native/MacOS/TextEditor.js+9−1 src/Yoga/React/Native/MacOS/TextEditor.purs+3−2 src/Yoga/React/Native/MacOS/TextField.js+14−1 src/Yoga/React/Native/MacOS/TextField.purs+4−3 src/Yoga/React/Native/MacOS/TokenField.js+10−1 src/Yoga/React/Native/MacOS/TokenField.purs+3−2 src/Yoga/React/Native/MacOS/Toolbar.js+10−1 src/Yoga/React/Native/MacOS/Toolbar.purs+3−2 src/Yoga/React/Native/MacOS/UserNotification.js+1−1 src/Yoga/React/Native/MacOS/UserNotification.purs+16−4 src/Yoga/React/Native/MacOS/WebView.js+12−1 src/Yoga/React/Native/MacOS/WebView.purs+4−3
README.md+1
@@ -87,3 +87,4 @@ myButton = nativeButton
8787- Node.js 20+ / Bun
8888- PureScript 0.15+ and Spago
8989- CocoaPods
90+
docs/src/Docs/Pages/DataViews.purs+32−19
@@ -15,46 +15,59 @@ page =
1515
1616tableView :: Nut
1717tableView = L.componentDoc "nativeTableView" "Yoga.React.Native.MacOS.TableView (nativeTableView)"
18− """nativeTableView
18+ """selected /\ setSelected <- useState' ""
19+
20+nativeTableView
1921 { columns:
20− [ { id: "name", title: "Name", width: 200.0 }
21− , { id: "size", title: "Size", width: 100.0 }
22+ [ { id: "name", title: "Name", width: 150.0 }
23+ , { id: "type", title: "Type", width: 100.0 }
24+ , { id: "size", title: "Size", width: 80.0 }
25+ ]
26+ , rows:
27+ [ [ "Main.purs", "PureScript", "12 KB" ]
28+ , [ "App.tsx", "TypeScript", "8 KB" ]
29+ , [ "style.css", "CSS", "3 KB" ]
30+ , [ "index.html", "HTML", "1 KB" ]
2231 ]
23− , rows: [ ["file.txt", "4 KB"], ["image.png", "1.2 MB"] ]
2432 , headerVisible: true
2533 , alternatingRows: true
26− , onSelectRow: handler (syntheticEvent >>> \e -> ...)
34+ , onSelectRow: \i -> setSelected ("Row " <> show i)
35+ , onDoubleClickRow: \i -> setSelected ("Double-clicked row " <> show i)
2736 }"""
2837 [ propsTable
2938 [ { name: "columns", type_: "Array TableColumn", description: "Column definitions ({ id, title, width })" }
3039 , { name: "rows", type_: "Array (Array String)", description: "Row data as arrays of strings" }
3140 , { name: "headerVisible", type_: "Boolean", description: "Show column headers" }
3241 , { name: "alternatingRows", type_: "Boolean", description: "Alternating row backgrounds" }
33− , { name: "onSelectRow", type_: "EventHandler", description: "Row selection callback" }
34− , { name: "onDoubleClickRow", type_: "EventHandler", description: "Row double-click callback" }
42+ , { name: "onSelectRow", type_: "Int -> Effect Unit", description: "Row selection callback" }
43+ , { name: "onDoubleClickRow", type_: "Int -> Effect Unit", description: "Row double-click callback" }
3544 ]
3645 ]
3746
3847outlineView :: Nut
3948outlineView = L.componentDoc "nativeOutlineView" "Yoga.React.Native.MacOS.OutlineView (nativeOutlineView)"
40− """nativeOutlineView
49+ """selection /\ setSelection <- useState' ""
50+let file id title = OutlineItem { id, title, sfSymbol: "doc", children: [] }
51+let folder id title children = OutlineItem { id, title, sfSymbol: "folder", children }
52+
53+nativeOutlineView
4154 { items:
42− [ OutlineItem
43− { id: "docs"
44− , title: "Documents"
45− , sfSymbol: "folder"
46− , children:
47− [ OutlineItem { id: "report", title: "report.pdf", sfSymbol: "doc", children: [] }
48− , OutlineItem { id: "notes", title: "notes.txt", sfSymbol: "doc.text", children: [] }
55+ [ folder "src" "src"
56+ [ file "main" "Main.purs"
57+ , folder "macos" "MacOS"
58+ [ file "btn" "Button.purs"
59+ , file "sl" "Slider.purs"
4960 ]
50− }
61+ ]
62+ , folder "test" "test"
63+ [ file "t1" "MacOSComponents.test.js" ]
5164 ]
52− , headerVisible: true
53− , onSelectItem: handler (syntheticEvent >>> \e -> ...)
65+ , headerVisible: false
66+ , onSelectItem: setSelection
5467 }"""
5568 [ propsTable
5669 [ { name: "items", type_: "Array OutlineItem", description: "Hierarchical tree data (newtype with { id, title, sfSymbol, children })" }
5770 , { name: "headerVisible", type_: "Boolean", description: "Show header" }
58− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
71+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
5972 ]
6073 ]
docs/src/Docs/Pages/Display.purs+2−2
@@ -111,11 +111,11 @@ pathControl = L.componentDoc "nativePathControl" "Yoga.React.Native.MacOS.PathCo
111111 """nativePathControl
112112 { url: "/Users/you/Documents"
113113 , pathStyle: T.standard
114− , onSelectPath: handler (syntheticEvent >>> \e -> ...)
114+ , onSelectPath: setPath
115115 }"""
116116 [ propsTable
117117 [ { name: "url", type_: "String", description: "File path URL to display" }
118118 , { name: "pathStyle", type_: "PathControlStyle", description: "Visual style of the path control" }
119− , { name: "onSelectPath", type_: "EventHandler", description: "Path segment selection callback" }
119+ , { name: "onSelectPath", type_: "String -> Effect Unit", description: "Path segment selection callback" }
120120 ]
121121 ]
docs/src/Docs/Pages/FilesAndDragDrop.purs+24−19
@@ -16,19 +16,20 @@ page =
1616
1717filePicker :: Nut
1818filePicker = L.componentDoc "nativeFilePicker" "Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)"
19− """nativeFilePicker
20− { mode: T.open
21− , title: "Choose files"
19+ """picked /\ setPicked <- useState' ""
20+
21+nativeFilePicker
22+ { mode: T.openFile
23+ , title: "Open Files"
2224 , sfSymbol: "doc.badge.plus"
23− , message: "Select one or more files"
24− , allowedTypes: ["pdf", "txt", "png"]
2525 , allowMultiple: true
26− , canChooseDirectories: false
27− , onPickFiles: handler (syntheticEvent >>> \e -> ...)
28− , onCancel: handler_ (pure unit)
26+ , allowedTypes: [ "public.image", "public.text" ]
27+ , message: "Select files to open"
28+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
29+ , onCancel: setPicked "Cancelled"
2930 }"""
3031 [ propsTable
31− [ { name: "mode", type_: "FilePickerMode", description: "open or save" }
32+ [ { name: "mode", type_: "FilePickerMode", description: "openFile or saveFile" }
3233 , { name: "title", type_: "String", description: "Dialog title" }
3334 , { name: "sfSymbol", type_: "String", description: "SF Symbol icon for the button" }
3435 , { name: "message", type_: "String", description: "Dialog message" }
@@ -36,24 +37,28 @@ filePicker = L.componentDoc "nativeFilePicker" "Yoga.React.Native.MacOS.FilePick
3637 , { name: "allowedTypes", type_: "Array String", description: "Allowed file extensions" }
3738 , { name: "allowMultiple", type_: "Boolean", description: "Allow selecting multiple files" }
3839 , { name: "canChooseDirectories", type_: "Boolean", description: "Allow choosing directories" }
39− , { name: "onPickFiles", type_: "EventHandler", description: "Files selected callback" }
40− , { name: "onCancel", type_: "EventHandler", description: "Cancel callback" }
40+ , { name: "onPickFiles", type_: "Array PickedFile -> Effect Unit", description: "Files selected callback ({ path, name })" }
41+ , { name: "onCancel", type_: "Effect Unit", description: "Cancel callback" }
4142 ]
4243 ]
4344
4445dropZone :: Nut
4546dropZone = L.componentDoc "nativeDropZone" "Yoga.React.Native.MacOS.DropZone (nativeDropZone)"
46− """-- FFINativeComponent: takes props then children
47+ """dropped /\ setDropped <- useState' ""
48+dragging /\ setDragging <- useState' false
49+
4750nativeDropZone
48− { onFileDrop: handler (syntheticEvent >>> \e -> ...)
49− , onFilesDragEnter: handler_ setDragActive
50− , onFilesDragExit: handler_ clearDragActive
51+ { onFileDrop: \d -> do
52+ setDropped (joinWith ", " (map _.name d.files))
53+ setDragging false
54+ , onFilesDragEnter: setDragging true
55+ , onFilesDragExit: setDragging false
5156 }
52− [ dropTargetContent ]"""
57+ [ text_ (if dragging then "Release to drop!" else "Drop files here") ]"""
5358 [ propsTable
54− [ { name: "onFileDrop", type_: "EventHandler", description: "Drop callback with file paths" }
55− , { name: "onFilesDragEnter", type_: "EventHandler", description: "Drag enter callback" }
56− , { name: "onFilesDragExit", type_: "EventHandler", description: "Drag exit callback" }
59+ [ { name: "onFileDrop", type_: "DroppedData -> Effect Unit", description: "Drop callback ({ files, strings })" }
60+ , { name: "onFilesDragEnter", type_: "Effect Unit", description: "Drag enter callback" }
61+ , { name: "onFilesDragExit", type_: "Effect Unit", description: "Drag exit callback" }
5762 ]
5863 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
5964 [ D.text_ "The drop target content is passed as the second argument (IsJSX)." ]
docs/src/Docs/Pages/InputControls.purs+110−67
@@ -27,10 +27,13 @@ page =
2727
2828button :: Nut
2929button = L.componentDoc "nativeButton" "Yoga.React.Native.MacOS.Button (nativeButton)"
30− """nativeButton
31− { title: "Click me"
30+ """status /\ setStatus <- useState' "Ready"
31+
32+nativeButton
33+ { title: "Say Hello"
3234 , bezelStyle: T.push
33− , onPress: handler_ doSomething
35+ , primary: true
36+ , onPress: setStatus "Hello from PureScript!"
3437 }"""
3538 [ propsTable
3639 [ { name: "title", type_: "String", description: "Button label text (mutually exclusive with sfSymbol)" }
@@ -39,29 +42,34 @@ button = L.componentDoc "nativeButton" "Yoga.React.Native.MacOS.Button (nativeBu
3942 , { name: "destructive", type_: "Boolean", description: "Red destructive styling" }
4043 , { name: "primary", type_: "Boolean", description: "Primary action button" }
4144 , { name: "buttonEnabled", type_: "Boolean", description: "Enable/disable the button" }
42− , { name: "onPress", type_: "EventHandler", description: "Press callback" }
45+ , { name: "onPress", type_: "Effect Unit", description: "Press callback" }
4346 ]
4447 ]
4548
4649switch :: Nut
4750switch = L.componentDoc "nativeSwitch" "Yoga.React.Native.MacOS.Switch (nativeSwitch)"
48− """nativeSwitch
49− { on: true
50− , onChange: handler (syntheticEvent >>> \e -> ...)
51+ """on /\ setOn <- useState' false
52+
53+nativeSwitch
54+ { on
55+ , onChange: setOn
5156 }"""
5257 [ propsTable
5358 [ { name: "on", type_: "Boolean", description: "Current on/off state" }
54− , { name: "onChange", type_: "EventHandler", description: "Toggle callback" }
59+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Toggle callback" }
5560 ]
5661 ]
5762
5863slider :: Nut
5964slider = L.componentDoc "nativeSlider" "Yoga.React.Native.MacOS.Slider (nativeSlider)"
60− """nativeSlider
61− { value: 50.0
65+ """value /\ setValue <- useState' 50.0
66+
67+nativeSlider
68+ { value
6269 , minValue: 0.0
6370 , maxValue: 100.0
64− , onChange: handler (syntheticEvent >>> \e -> ...)
71+ , numberOfTickMarks: 11
72+ , onChange: setValue
6573 }"""
6674 [ propsTable
6775 [ { name: "value", type_: "Number", description: "Current value" }
@@ -69,167 +77,202 @@ slider = L.componentDoc "nativeSlider" "Yoga.React.Native.MacOS.Slider (nativeSl
6977 , { name: "maxValue", type_: "Number", description: "Range maximum" }
7078 , { name: "numberOfTickMarks", type_: "Int", description: "Number of tick marks" }
7179 , { name: "allowsTickMarkValuesOnly", type_: "Boolean", description: "Snap to tick marks only" }
72− , { name: "onChange", type_: "EventHandler", description: "Value change callback" }
80+ , { name: "onChange", type_: "Number -> Effect Unit", description: "Value change callback" }
7381 ]
7482 ]
7583
7684stepper :: Nut
7785stepper = L.componentDoc "nativeStepper" "Yoga.React.Native.MacOS.Stepper (nativeStepper)"
78− """nativeStepper
79− { value: 1.0
86+ """value /\ setValue <- useState' 5.0
87+
88+nativeStepper
89+ { value
8090 , minValue: 0.0
81− , maxValue: 10.0
91+ , maxValue: 50.0
8292 , increment: 1.0
83− , onChange: handler (syntheticEvent >>> \e -> ...)
93+ , onChange: setValue
8494 }"""
8595 [ propsTable
8696 [ { name: "value", type_: "Number", description: "Current value" }
8797 , { name: "minValue", type_: "Number", description: "Range minimum" }
8898 , { name: "maxValue", type_: "Number", description: "Range maximum" }
8999 , { name: "increment", type_: "Number", description: "Step increment" }
90− , { name: "onChange", type_: "EventHandler", description: "Value change callback" }
100+ , { name: "onChange", type_: "Number -> Effect Unit", description: "Value change callback" }
91101 ]
92102 ]
93103
94104checkbox :: Nut
95105checkbox = L.componentDoc "nativeCheckbox" "Yoga.React.Native.MacOS.Checkbox (nativeCheckbox)"
96− """nativeCheckbox
97− { title: "Enable notifications"
98− , checked: true
99− , onChange: handler (syntheticEvent >>> \e -> ...)
106+ """a /\ setA <- useState' true
107+
108+nativeCheckbox
109+ { checked: a
110+ , title: "Enable notifications"
111+ , enabled: true
112+ , onChange: setA
100113 }"""
101114 [ propsTable
102115 [ { name: "title", type_: "String", description: "Label text" }
103116 , { name: "checked", type_: "Boolean", description: "Checked state" }
104117 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
105− , { name: "onChange", type_: "EventHandler", description: "Toggle callback" }
118+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Toggle callback" }
106119 ]
107120 ]
108121
109122radioButton :: Nut
110123radioButton = L.componentDoc "nativeRadioButton" "Yoga.React.Native.MacOS.RadioButton (nativeRadioButton)"
111− """nativeRadioButton
112− { title: "Option A"
113− , selected: true
114− , onChange: handler (syntheticEvent >>> \e -> ...)
124+ """choice /\ setChoice <- useState' "option1"
125+
126+nativeRadioButton
127+ { selected: choice == "option1"
128+ , title: "Small"
129+ , enabled: true
130+ , onChange: \_ -> setChoice "option1"
131+ }
132+nativeRadioButton
133+ { selected: choice == "option2"
134+ , title: "Medium"
135+ , enabled: true
136+ , onChange: \_ -> setChoice "option2"
115137 }"""
116138 [ propsTable
117139 [ { name: "title", type_: "String", description: "Label text" }
118140 , { name: "selected", type_: "Boolean", description: "Selection state" }
119141 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
120− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
142+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Selection callback" }
121143 ]
122144 ]
123145
124146segmented :: Nut
125147segmented = L.componentDoc "nativeSegmented" "Yoga.React.Native.MacOS.Segmented (nativeSegmented)"
126− """nativeSegmented
127− { labels: ["One", "Two", "Three"]
128− , sfSymbols: ["1.circle", "2.circle", "3.circle"]
129− , selectedIndex: 0
130− , onChange: handler (syntheticEvent >>> \e -> ...)
148+ """mapType /\ setMapType <- useState' 0
149+
150+nativeSegmented
151+ { labels: [ "Standard", "Satellite", "Hybrid" ]
152+ , selectedIndex: mapType
153+ , onChange: setMapType
131154 }"""
132155 [ propsTable
133156 [ { name: "labels", type_: "Array String", description: "Segment labels" }
134157 , { name: "sfSymbols", type_: "Array String", description: "SF Symbol icons per segment" }
135158 , { name: "selectedIndex", type_: "Int", description: "Currently selected index" }
136− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
159+ , { name: "onChange", type_: "Int -> Effect Unit", description: "Selection callback" }
137160 ]
138161 ]
139162
140163popUp :: Nut
141164popUp = L.componentDoc "nativePopUp" "Yoga.React.Native.MacOS.PopUp (nativePopUp)"
142− """nativePopUp
143− { items: ["Small", "Medium", "Large"]
144− , selectedIndex: 1
145− , onChange: handler (syntheticEvent >>> \e -> ...)
165+ """idx /\ setIdx <- useState' 0
166+title /\ setTitle <- useState' "Small"
167+let items = [ "Small", "Medium", "Large", "Extra Large" ]
168+
169+nativePopUp
170+ { items
171+ , selectedIndex: idx
172+ , onChange: \i -> do
173+ setIdx i
174+ setTitle (fromMaybe "" (items !! i))
146175 }"""
147176 [ propsTable
148177 [ { name: "items", type_: "Array String", description: "Menu items" }
149178 , { name: "selectedIndex", type_: "Int", description: "Selected item index" }
150− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
179+ , { name: "onChange", type_: "Int -> Effect Unit", description: "Selection callback" }
151180 ]
152181 ]
153182
154183comboBox :: Nut
155184comboBox = L.componentDoc "nativeComboBox" "Yoga.React.Native.MacOS.ComboBox (nativeComboBox)"
156− """nativeComboBox
157− { items: ["Apple", "Banana", "Cherry"]
158− , text: "Apple"
159− , placeholder: "Choose a fruit..."
160− , onChangeText: handler (syntheticEvent >>> \e -> ...)
161− , onSelectItem: handler (syntheticEvent >>> \e -> ...)
185+ """txt /\ setTxt <- useState' ""
186+result /\ setResult <- useState' ""
187+
188+nativeComboBox
189+ { items: [ "Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape" ]
190+ , text: txt
191+ , placeholder: "Type a fruit..."
192+ , onChangeText: setTxt
193+ , onSelectItem: \t -> do
194+ setTxt t
195+ setResult ("Selected: " <> t)
162196 }"""
163197 [ propsTable
164198 [ { name: "items", type_: "Array String", description: "Autocomplete suggestions" }
165199 , { name: "text", type_: "String", description: "Current text value" }
166200 , { name: "placeholder", type_: "String", description: "Placeholder text" }
167− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
168− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
201+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
202+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
169203 ]
170204 ]
171205
172206searchField :: Nut
173207searchField = L.componentDoc "nativeSearchField" "Yoga.React.Native.MacOS.SearchField (nativeSearchField)"
174− """nativeSearchField
175− { placeholder: "Search..."
176− , text: ""
177− , onChangeText: handler (syntheticEvent >>> \e -> ...)
178− , onSearch: handler (syntheticEvent >>> \e -> ...)
208+ """query /\ setQuery <- useState' ""
209+result /\ setResult <- useState' ""
210+
211+nativeSearchField
212+ { text: query
213+ , placeholder: "Search..."
214+ , onChangeText: setQuery
215+ , onSearch: \t -> setResult ("Searched: " <> t)
179216 }"""
180217 [ propsTable
181218 [ { name: "text", type_: "String", description: "Current search text" }
182219 , { name: "placeholder", type_: "String", description: "Placeholder text" }
183− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
184− , { name: "onSearch", type_: "EventHandler", description: "Search submit callback" }
220+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
221+ , { name: "onSearch", type_: "String -> Effect Unit", description: "Search submit callback" }
185222 ]
186223 ]
187224
188225tokenField :: Nut
189226tokenField = L.componentDoc "nativeTokenField" "Yoga.React.Native.MacOS.TokenField (nativeTokenField)"
190− """nativeTokenField
191− { tokens: ["tag1", "tag2"]
227+ """tokens /\ setTokens <- useState' [ "PureScript", "React", "macOS" ]
228+
229+nativeTokenField
230+ { tokens
192231 , placeholder: "Add tags..."
193− , onChangeTokens: handler (syntheticEvent >>> \e -> ...)
232+ , onChangeTokens: setTokens
194233 }"""
195234 [ propsTable
196235 [ { name: "tokens", type_: "Array String", description: "Current tokens" }
197236 , { name: "placeholder", type_: "String", description: "Placeholder text" }
198− , { name: "onChangeTokens", type_: "EventHandler", description: "Tokens change callback" }
237+ , { name: "onChangeTokens", type_: "Array String -> Effect Unit", description: "Tokens change callback" }
199238 ]
200239 ]
201240
202241datePicker :: Nut
203242datePicker = L.componentDoc "nativeDatePicker" "Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)"
204− """nativeDatePicker
205− { graphical: true
206− , onChange: handler (syntheticEvent >>> \e -> ...)
243+ """dateText /\ setDateText <- useState' ""
244+
245+nativeDatePicker
246+ { graphical: false
247+ , onChange: setDateText
207248 }"""
208249 [ propsTable
209250 [ { name: "graphical", type_: "Boolean", description: "Show graphical calendar picker" }
210− , { name: "onChange", type_: "EventHandler", description: "Date change callback" }
251+ , { name: "onChange", type_: "String -> Effect Unit", description: "Date change callback" }
211252 ]
212253 ]
213254
214255colorWell :: Nut
215256colorWell = L.componentDoc "nativeColorWell" "Yoga.React.Native.MacOS.ColorWell (nativeColorWell)"
216− """nativeColorWell
217− { color: "#ff0000"
257+ """color /\ setColor <- useState' "#FF6600"
258+
259+nativeColorWell
260+ { color
218261 , minimal: true
219− , onChange: handler (syntheticEvent >>> \e -> ...)
262+ , onChange: setColor
220263 }"""
221264 [ propsTable
222265 [ { name: "color", type_: "String", description: "Current color hex value" }
223266 , { name: "minimal", type_: "Boolean", description: "Minimal inline style" }
224− , { name: "onChange", type_: "EventHandler", description: "Color change callback" }
267+ , { name: "onChange", type_: "String -> Effect Unit", description: "Color change callback" }
225268 ]
226269 ]
227270
228271helpButton :: Nut
229272helpButton = L.componentDoc "nativeHelpButton" "Yoga.React.Native.MacOS.HelpButton (nativeHelpButton)"
230273 """nativeHelpButton
231− { onPress: handler_ showHelp }"""
274+ { onPress: showHelp }"""
232275 [ propsTable
233− [ { name: "onPress", type_: "EventHandler", description: "Press callback" }
276+ [ { name: "onPress", type_: "Effect Unit", description: "Press callback" }
234277 ]
235278 ]
docs/src/Docs/Pages/LayoutPage.purs+12−12
@@ -57,18 +57,21 @@ nativeSplitView
5757
5858tabView :: Nut
5959tabView = L.componentDoc "nativeTabView" "Yoga.React.Native.MacOS.TabView (nativeTabView)"
60− """nativeTabView
60+ """selected /\ setSelected <- useState' "general"
61+
62+nativeTabView
6163 { items:
6264 [ { id: "general", label: "General" }
6365 , { id: "advanced", label: "Advanced" }
66+ , { id: "about", label: "About" }
6467 ]
65− , selectedItem: "general"
66− , onSelectTab: handler (syntheticEvent >>> \e -> ...)
68+ , selectedItem: selected
69+ , onSelectTab: setSelected
6770 }"""
6871 [ propsTable
6972 [ { name: "items", type_: "Array TabItem", description: "Tab items ({ id :: String, label :: String })" }
7073 , { name: "selectedItem", type_: "String", description: "Selected tab id" }
71− , { name: "onSelectTab", type_: "EventHandler", description: "Tab selection callback" }
74+ , { name: "onSelectTab", type_: "String -> Effect Unit", description: "Tab selection callback" }
7275 ]
7376 ]
7477
@@ -109,21 +112,18 @@ sidebarLayout
109112toolbar :: Nut
110113toolbar = L.componentDoc "nativeToolbar" "Yoga.React.Native.MacOS.Toolbar (nativeToolbar)"
111114 """nativeToolbar
112− { items:
113− [ { id: "add", label: "Add", sfSymbol: "plus" }
114− , { id: "delete", label: "Delete", sfSymbol: "trash" }
115− ]
116− , selectedItem: "add"
115+ { items: []
116+ , selectedItem: ""
117117 , toolbarStyle: T.unified
118− , windowTitle: "My App"
119− , onSelectItem: handler (syntheticEvent >>> \e -> ...)
118+ , windowTitle: "PureScript React Native"
119+ , onSelectItem: \_ -> pure unit
120120 }"""
121121 [ propsTable
122122 [ { name: "items", type_: "Array ToolbarItem", description: "Toolbar items ({ id, label, sfSymbol })" }
123123 , { name: "selectedItem", type_: "String", description: "Selected item id" }
124124 , { name: "toolbarStyle", type_: "ToolbarStyle", description: "Toolbar visual style" }
125125 , { name: "windowTitle", type_: "String", description: "Window title" }
126− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
126+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
127127 ]
128128 ]
129129
docs/src/Docs/Pages/Overlays.purs+45−28
@@ -35,15 +35,25 @@ alert = L.componentDoc "macosAlert" "Yoga.React.Native.MacOS.Alert (macosAlert)"
3535
3636sheet :: Nut
3737sheet = L.componentDoc "nativeSheet" "Yoga.React.Native.MacOS.Sheet (nativeSheet)"
38− """-- FFINativeComponent: takes props then children
38+ """visible /\ setVisible <- useState' false
39+
40+nativeButton
41+ { title: "Show Sheet"
42+ , bezelStyle: T.push
43+ , onPress: setVisible true
44+ }
3945nativeSheet
40− { visible: true
41− , onDismiss: handler_ hideSheet
46+ { visible
47+ , onDismiss: setVisible false
4248 }
43− [ sheetContent ]"""
49+ [ nativeButton
50+ { title: "Dismiss"
51+ , onPress: setVisible false
52+ }
53+ ]"""
4454 [ propsTable
4555 [ { name: "visible", type_: "Boolean", description: "Show/hide the sheet" }
46− , { name: "onDismiss", type_: "EventHandler", description: "Dismiss callback" }
56+ , { name: "onDismiss", type_: "Effect Unit", description: "Dismiss callback" }
4757 ]
4858 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
4959 [ D.text_ "Sheet content is passed as the second argument (IsJSX)." ]
@@ -51,19 +61,24 @@ nativeSheet
5161
5262popover :: Nut
5363popover = L.componentDoc "nativePopover" "Yoga.React.Native.MacOS.Popover (nativePopover)"
54− """-- FFINativeComponent: takes props then children
64+ """visible /\ setVisible <- useState' false
65+
5566nativePopover
56− { visible: true
57− , preferredEdge: T.maxY
67+ { visible
68+ , preferredEdge: T.bottom
5869 , behavior: T.transient
59− , onClose: handler_ hidePopover
70+ , onClose: setVisible false
6071 }
61− [ popoverContent ]"""
72+ [ nativeButton
73+ { title: if visible then "Hide" else "Show Popover"
74+ , onPress: setVisible (not visible)
75+ }
76+ ]"""
6277 [ propsTable
6378 [ { name: "visible", type_: "Boolean", description: "Show/hide" }
6479 , { name: "preferredEdge", type_: "PopoverEdge", description: "Preferred edge for popover placement" }
6580 , { name: "behavior", type_: "PopoverBehavior", description: "Popover behavior" }
66− , { name: "onClose", type_: "EventHandler", description: "Close callback" }
81+ , { name: "onClose", type_: "Effect Unit", description: "Close callback" }
6782 ]
6883 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
6984 [ D.text_ "Popover content is passed as the second argument (IsJSX)." ]
@@ -71,18 +86,22 @@ nativePopover
7186
7287contextMenu :: Nut
7388contextMenu = L.componentDoc "nativeContextMenu" "Yoga.React.Native.MacOS.ContextMenu (nativeContextMenu)"
74− """-- FFINativeComponent: takes props then children
89+ """result /\ setResult <- useState' ""
90+
7591nativeContextMenu
7692 { items:
77− [ { id: "copy", title: "Copy", sfSymbol: "doc.on.doc" }
93+ [ { id: "cut", title: "Cut", sfSymbol: "scissors" }
94+ , { id: "copy", title: "Copy", sfSymbol: "doc.on.doc" }
7895 , { id: "paste", title: "Paste", sfSymbol: "doc.on.clipboard" }
96+ , { id: "sep", title: "-", sfSymbol: "" }
97+ , { id: "delete", title: "Delete", sfSymbol: "trash" }
7998 ]
80− , onSelectItem: handler (syntheticEvent >>> \e -> ...)
99+ , onSelectItem: setResult
81100 }
82− [ rightClickTarget ]"""
101+ [ text_ "Right-click me!" ]"""
83102 [ propsTable
84103 [ { name: "items", type_: "Array ContextMenuItem", description: "Menu items ({ id, title, sfSymbol })" }
85− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
104+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
86105 ]
87106 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
88107 [ D.text_ "The right-click target element is passed as the second argument (IsJSX)." ]
@@ -90,17 +109,15 @@ nativeContextMenu
90109
91110menu :: Nut
92111menu = L.componentDoc "macosShowMenu" "Yoga.React.Native.MacOS.Menu (macosShowMenu)"
93− """-- Imperative function with 2 positional args
94−macosShowMenu
95− [ { title: "New", id: "new" }
96− , { title: "Open", id: "open" }
97− ]
98− (\selectedId -> log selectedId)
99− # liftEffect"""
100− [ D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
101− [ D.text_ "Signature: Array MenuItem -> (String -> Effect Unit) -> Effect Unit" ]
102− , propsTable
103− [ { name: "arg 1", type_: "Array MenuItem", description: "Menu items ({ title :: String, id :: String })" }
104− , { name: "arg 2", type_: "String -> Effect Unit", description: "Callback receiving the selected item id" }
112+ """macosShowMenu
113+ { items:
114+ [ { title: "New", id: "new" }
115+ , { title: "Open", id: "open" }
116+ ]
117+ , onSelectItem: \selectedId -> log selectedId
118+ }"""
119+ [ propsTable
120+ [ { name: "items", type_: "Array MenuItem", description: "Menu items ({ title, id })" }
121+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Callback receiving the selected item id" }
105122 ]
106123 ]
docs/src/Docs/Pages/QuickStart.purs+1−1
@@ -57,7 +57,7 @@ import Yoga.React.Native.MacOS.Types as T
5757myButton = nativeButton
5858 { title: "Click me"
5959 , bezelStyle: T.push
60− , onPress: handler_ doSomething
60+ , onPress: doSomething
6161 , style: Style.style { height: 24.0 }
6262 }"""
6363
docs/src/Docs/Pages/RichMedia.purs+33−20
@@ -19,21 +19,27 @@ page =
1919
2020mapView :: Nut
2121mapView = L.componentDoc "nativeMapView" "Yoga.React.Native.MacOS.MapView (nativeMapView)"
22− """nativeMapView
22+ """mapType /\ setMapType <- useState' 0
23+let mt = case mapType of
24+ 1 -> T.satelliteMap
25+ 2 -> T.hybridMap
26+ _ -> T.standardMap
27+
28+nativeMapView
2329 { latitude: 37.7749
2430 , longitude: -122.4194
2531 , latitudeDelta: 0.05
2632 , longitudeDelta: 0.05
27− , mapType: T.standard
28− , showsUserLocation: true
33+ , mapType: mt
34+ , showsUserLocation: false
2935 , annotations:
30− [ { latitude: 37.7749
31− , longitude: -122.4194
32− , title: "San Francisco"
33− , subtitle: "CA"
36+ [ { latitude: 37.7749, longitude: -122.4194
37+ , title: "San Francisco", subtitle: "California"
38+ }
39+ , { latitude: 37.8199, longitude: -122.4783
40+ , title: "Golden Gate Bridge", subtitle: ""
3441 }
3542 ]
36− , onRegionChange: handler (syntheticEvent >>> \e -> ...)
3743 }"""
3844 [ propsTable
3945 [ { name: "latitude", type_: "Number", description: "Center latitude" }
@@ -43,38 +49,45 @@ mapView = L.componentDoc "nativeMapView" "Yoga.React.Native.MacOS.MapView (nativ
4349 , { name: "mapType", type_: "MapType", description: "Map display type" }
4450 , { name: "showsUserLocation", type_: "Boolean", description: "Show user location dot" }
4551 , { name: "annotations", type_: "Array MapAnnotation", description: "Map pins ({ latitude, longitude, title, subtitle })" }
46− , { name: "onRegionChange", type_: "EventHandler", description: "Region change callback" }
47− , { name: "onSelectAnnotation", type_: "EventHandler", description: "Annotation tap callback" }
52+ , { name: "onRegionChange", type_: "MapRegion -> Effect Unit", description: "Region change callback ({ latitude, longitude, latitudeDelta, longitudeDelta })" }
53+ , { name: "onSelectAnnotation", type_: "String -> Effect Unit", description: "Annotation tap callback" }
4854 ]
4955 ]
5056
5157pdfView :: Nut
5258pdfView = L.componentDoc "nativePDFView" "Yoga.React.Native.MacOS.PDFView (nativePDFView)"
5359 """nativePDFView
54− { source: "/path/to/document.pdf"
60+ { source: "https://example.com/document.pdf"
5561 , autoScales: true
56− , displayMode: T.singlePage
57− , onPageChange: handler (syntheticEvent >>> \e -> ...)
62+ , displayMode: T.singlePageContinuous
63+ , onPageChange: setPage
5864 }"""
5965 [ propsTable
6066 [ { name: "source", type_: "String", description: "PDF file path or URL" }
6167 , { name: "autoScales", type_: "Boolean", description: "Auto-fit to view" }
6268 , { name: "displayMode", type_: "PDFDisplayMode", description: "PDF display mode" }
63− , { name: "onPageChange", type_: "EventHandler", description: "Page change callback" }
69+ , { name: "onPageChange", type_: "Int -> Effect Unit", description: "Page change callback" }
6470 ]
6571 ]
6672
6773webView :: Nut
6874webView = L.componentDoc "nativeWebView" "Yoga.React.Native.MacOS.WebView (nativeWebView)"
69− """nativeWebView
70− { url: "https://purescript.org"
71− , onNavigate: handler (syntheticEvent >>> \e -> ...)
72− , onFinishLoad: handler_ onPageLoaded
75+ """url /\ setUrl <- useState' "https://pursuit.purescript.org"
76+urlBar /\ setUrlBar <- useState' "https://pursuit.purescript.org"
77+
78+nativeTextField
79+ { text: urlBar
80+ , onChangeText: setUrlBar
81+ , onSubmit: setUrl
82+ }
83+nativeWebView
84+ { url
85+ , onFinishLoad: setUrlBar
7386 }"""
7487 [ propsTable
7588 [ { name: "url", type_: "String", description: "URL to load" }
76− , { name: "onNavigate", type_: "EventHandler", description: "Navigation callback" }
77− , { name: "onFinishLoad", type_: "EventHandler", description: "Page load complete callback" }
89+ , { name: "onNavigate", type_: "String -> Effect Unit", description: "Navigation callback" }
90+ , { name: "onFinishLoad", type_: "String -> Effect Unit", description: "Page load complete callback" }
7891 ]
7992 ]
8093
docs/src/Docs/Pages/SystemServices.purs+8−5
@@ -44,11 +44,14 @@ macosShare ["Check out this library!", "https://github.com/rowtype-yoga/purescri
4444
4545notification :: Nut
4646notification = L.componentDoc "macosNotify" "Yoga.React.Native.MacOS.UserNotification (macosNotify)"
47− """-- Takes 2 positional String args: title and body
48−macosNotify "Build Complete" "Your project compiled successfully."
49− # liftEffect"""
50− [ D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
51− [ D.text_ "Signature: String -> String -> Effect Unit" ]
47+ """macosNotify
48+ { title: "Build Complete"
49+ , body: "Your project compiled successfully."
50+ }"""
51+ [ propsTable
52+ [ { name: "title", type_: "String", description: "Notification title" }
53+ , { name: "body", type_: "String", description: "Notification body text" }
54+ ]
5255 ]
5356
5457sound :: Nut
docs/src/Docs/Pages/TextEditing.purs+12−12
@@ -15,12 +15,13 @@ page =
1515
1616textField :: Nut
1717textField = L.componentDoc "nativeTextField" "Yoga.React.Native.MacOS.TextField (nativeTextField)"
18− """nativeTextField
19− { text: "Hello"
20− , placeholder: "Enter text..."
21− , secure: false
22− , onChangeText: handler (syntheticEvent >>> \e -> ...)
23− , onSubmit: handler_ doSubmit
18+ """txt /\ setTxt <- useState' ""
19+
20+nativeTextField
21+ { placeholder: "Type something..."
22+ , search: true
23+ , text: txt
24+ , onChangeText: setTxt
2425 }"""
2526 [ propsTable
2627 [ { name: "text", type_: "String", description: "Current text value" }
@@ -28,23 +29,22 @@ textField = L.componentDoc "nativeTextField" "Yoga.React.Native.MacOS.TextField
2829 , { name: "secure", type_: "Boolean", description: "Password field (hides input)" }
2930 , { name: "search", type_: "Boolean", description: "Search field style" }
3031 , { name: "rounded", type_: "Boolean", description: "Rounded bezel style" }
31− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
32− , { name: "onSubmit", type_: "EventHandler", description: "Submit callback (Enter key)" }
32+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
33+ , { name: "onSubmit", type_: "String -> Effect Unit", description: "Submit callback (Enter key)" }
3334 ]
3435 ]
3536
3637textEditor :: Nut
3738textEditor = L.componentDoc "nativeTextEditor" "Yoga.React.Native.MacOS.TextEditor (nativeTextEditor)"
3839 """nativeTextEditor
39− { text: "Rich text content..."
40+ { text: "Welcome to the PureScript-driven native text editor."
4041 , richText: true
41− , showsRuler: false
42− , onChangeText: handler (syntheticEvent >>> \e -> ...)
42+ , showsRuler: true
4343 }"""
4444 [ propsTable
4545 [ { name: "text", type_: "String", description: "Current text content" }
4646 , { name: "richText", type_: "Boolean", description: "Enable rich text formatting" }
4747 , { name: "showsRuler", type_: "Boolean", description: "Show the formatting ruler" }
48− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
48+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
4949 ]
5050 ]
example-macos/src/Demo/AiMl.purs+13−17
@@ -13,14 +13,12 @@ import Demo.Shared (DemoProps, desc, scrollWrap, sectionTitle)
1313import Effect.Aff (launchAff_)
1414import Effect.Class (liftEffect)
1515import React.Basic (JSX)
16−import React.Basic.Events (handler, handler_, unsafeEventFn)
1716import React.Basic.Hooks (useState', (/\))
1817import React.Basic.Hooks as React
1918import Yoga.React (component)
20−import Yoga.React.Native (nativeEvent, text, tw, view)
19+import Yoga.React.Native (text, tw, view)
2120import Yoga.React.Native.MacOS.Button (nativeButton)
2221import Yoga.React.Native.MacOS.CameraView (nativeCameraView)
23−import Yoga.React.Native.MacOS.Events as E
2422import Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)
2523import Yoga.React.Native.MacOS.NaturalLanguage (analyzeSentiment, detectLanguage, tokenize)
2624import Yoga.React.Native.MacOS.OCR (recognizeText)
@@ -42,13 +40,11 @@ ocrDemo = component "OCRDemo" \dp -> React.do
4240 , allowedTypes: [ "public.image" ]
4341 , title: "Pick Image"
4442 , sfSymbol: "photo"
45− , onPickFiles: handler
46− (nativeEvent >>> unsafeEventFn \e -> E.getFieldArray "files" e)
47− \paths -> for_ paths \path -> do
48− setResult "Recognizing..."
49− launchAff_ do
50− r <- recognizeText path
51− liftEffect (setResult r)
43+ , onPickFiles: \files -> for_ files \file -> do
44+ setResult "Recognizing..."
45+ launchAff_ do
46+ r <- recognizeText file.path
47+ liftEffect (setResult r)
5248 , style: Style.style { height: 24.0, width: 140.0 }
5349 }
5450 ]
@@ -68,13 +64,13 @@ speechRecognitionDemo = component "SpeechRecognitionDemo" \dp -> React.do
6864 [ nativeButton
6965 { title: if speech.listening then "Listening..." else "Start"
7066 , bezelStyle: T.push
71− , onPress: handler_ speech.start
67+ , onPress: speech.start
7268 , style: Style.style { height: 24.0, width: 130.0 }
7369 }
7470 , nativeButton
7571 { title: "Stop"
7672 , bezelStyle: T.push
77− , onPress: handler_ speech.stop
73+ , onPress: speech.stop
7874 , style: Style.style { height: 24.0, width: 80.0, marginLeft: 8.0 }
7975 }
8076 ]
@@ -94,14 +90,14 @@ naturalLanguageDemo = component "NaturalLanguageDemo" \dp -> React.do
9490 , nativeTextField
9591 { text: txt
9692 , placeholder: "Enter text to analyze..."
97− , onChangeText: E.onString "text" setTxt
93+ , onChangeText: setTxt
9894 , style: Style.style { height: 24.0 } <> tw "mb-2"
9995 }
10096 , view { style: tw "flex-row items-center mb-2" }
10197 [ nativeButton
10298 { title: "Language"
10399 , bezelStyle: T.push
104− , onPress: handler_ $ launchAff_ do
100+ , onPress: launchAff_ do
105101 lang <- detectLanguage txt
106102 liftEffect (setResult ("Language: " <> lang))
107103 , style: Style.style { height: 24.0, width: 110.0 }
@@ -109,7 +105,7 @@ naturalLanguageDemo = component "NaturalLanguageDemo" \dp -> React.do
109105 , nativeButton
110106 { title: "Sentiment"
111107 , bezelStyle: T.push
112− , onPress: handler_ $ launchAff_ do
108+ , onPress: launchAff_ do
113109 score <- analyzeSentiment txt
114110 liftEffect (setResult ("Sentiment: " <> show score))
115111 , style: Style.style { height: 24.0, width: 110.0, marginLeft: 8.0 }
@@ -117,7 +113,7 @@ naturalLanguageDemo = component "NaturalLanguageDemo" \dp -> React.do
117113 , nativeButton
118114 { title: "Tokenize"
119115 , bezelStyle: T.push
120− , onPress: handler_ $ launchAff_ do
116+ , onPress: launchAff_ do
121117 tokens <- tokenize txt
122118 liftEffect (setResult ("Tokens: " <> joinWith ", " tokens))
123119 , style: Style.style { height: 24.0, width: 110.0, marginLeft: 8.0 }
@@ -138,7 +134,7 @@ cameraDemo = component "CameraDemo" \dp -> React.do
138134 , nativeButton
139135 { title: if on then "Stop" else "Start"
140136 , bezelStyle: T.push
141− , onPress: handler_ (setOn (not on))
137+ , onPress: setOn (not on)
142138 , style: Style.style { height: 24.0, width: 100.0 }
143139 }
144140 ]
example-macos/src/Demo/Chat.purs+11−13
@@ -18,7 +18,6 @@ import React.Basic.Hooks as React
1818import Yoga.React (component)
1919import Yoga.React.Native (text, tw, view)
2020import Yoga.React.Native.MacOS.Button (nativeButton)
21−import Yoga.React.Native.MacOS.Events as E
2221import Yoga.React.Native.MacOS.PatternBackground (nativePatternBackground)
2322import Yoga.React.Native.MacOS.Popover (nativePopover)
2423import Yoga.React.Native.MacOS.ScrollView (nativeScrollView)
@@ -189,7 +188,7 @@ chatDemo = component "ChatDemo" \dp -> React.do
189188 , nativeButton
190189 { title: ""
191190 , bezelStyle: T.toolbar
192− , onPress: handler_ (selectRoom r.roomId)
191+ , onPress: selectRoom r.roomId
193192 , style: Style.style { position: "absolute", top: 0.0, left: 0.0, right: 0.0, bottom: 0.0, opacity: 0.0 }
194193 }
195194 ]
@@ -213,16 +212,15 @@ chatDemo = component "ChatDemo" \dp -> React.do
213212 { visible: reactPopover == Just idx
214213 , preferredEdge: T.bottom
215214 , behavior: T.transient
216− , onClose: handler_ (setReactPopover Nothing)
215+ , onClose: setReactPopover Nothing
217216 , style: Style.style {}
218217 }
219218 [ nativeButton
220219 { title: "☺"
221220 , bezelStyle: T.toolbar
222− , onPress: handler_
223− ( if reactPopover == Just idx then setReactPopover Nothing
224− else setReactPopover (Just idx)
225− )
221+ , onPress:
222+ if reactPopover == Just idx then setReactPopover Nothing
223+ else setReactPopover (Just idx)
226224 , style: Style.style { height: 20.0, width: 24.0 }
227225 }
228226 , view { style: tw "flex-row items-center p-2" <> Style.style { height: 40.0 } }
@@ -230,7 +228,7 @@ chatDemo = component "ChatDemo" \dp -> React.do
230228 nativeButton
231229 { title: emoji
232230 , bezelStyle: T.toolbar
233− , onPress: handler_ (reactToMessage idx emoji)
231+ , onPress: reactToMessage idx emoji
234232 , style: Style.style { height: 32.0, width: 32.0 }
235233 }
236234 )
@@ -253,7 +251,7 @@ chatDemo = component "ChatDemo" \dp -> React.do
253251 , nativeButton
254252 { title: ""
255253 , bezelStyle: T.toolbar
256− , onPress: handler_ (scrollToMessage origIdx)
254+ , onPress: scrollToMessage origIdx
257255 , style: Style.style { position: "absolute", top: 0.0, left: 0.0, right: 0.0, bottom: 0.0, opacity: 0.0 }
258256 }
259257 ]
@@ -311,7 +309,7 @@ chatDemo = component "ChatDemo" \dp -> React.do
311309 , nativeButton
312310 { title: "✕"
313311 , bezelStyle: T.toolbar
314− , onPress: handler_ (setReplyingTo Nothing)
312+ , onPress: setReplyingTo Nothing
315313 , style: Style.style { height: 20.0, width: 24.0 }
316314 }
317315 ]
@@ -361,14 +359,14 @@ chatDemo = component "ChatDemo" \dp -> React.do
361359 , placeholder: "Message..."
362360 , search: false
363361 , rounded: true
364− , onChangeText: E.onString "text" \t -> setInputText (replaceEmoji t)
365− , onSubmit: E.onString "text" \t -> sendMessage rid t
362+ , onChangeText: \t -> setInputText (replaceEmoji t)
363+ , onSubmit: \t -> sendMessage rid t
366364 , style: tw "flex-1" <> Style.style { height: 28.0 }
367365 }
368366 , nativeButton
369367 { sfSymbol: "paperplane.fill"
370368 , bezelStyle: T.toolbar
371− , onPress: handler_ (sendMessage rid inputText)
369+ , onPress: sendMessage rid inputText
372370 , style: Style.style { height: 28.0, width: 36.0, marginLeft: 8.0 }
373371 }
374372 ]
example-macos/src/Demo/DataViews.purs+3−4
@@ -8,7 +8,6 @@ import React.Basic.Hooks (useState', (/\))
88import React.Basic.Hooks as React
99import Yoga.React (component)
1010import Yoga.React.Native (tw)
11−import Yoga.React.Native.MacOS.Events as E
1211import Yoga.React.Native.MacOS.OutlineView (OutlineItem(..), nativeOutlineView)
1312import Yoga.React.Native.MacOS.TableView (nativeTableView)
1413import Yoga.React.Native.Style as Style
@@ -35,8 +34,8 @@ tableViewDemo = component "TableViewDemo" \dp -> React.do
3534 ]
3635 , headerVisible: true
3736 , alternatingRows: true
38− , onSelectRow: E.onInt "rowIndex" \i -> setSelected ("Row " <> show i)
39− , onDoubleClickRow: E.onInt "rowIndex" \i -> setSelected ("Double-clicked row " <> show i)
37+ , onSelectRow: \i -> setSelected ("Row " <> show i)
38+ , onDoubleClickRow: \i -> setSelected ("Double-clicked row " <> show i)
4039 , style: Style.style { height: 180.0 } <> tw "rounded-lg overflow-hidden mb-2"
4140 }
4241 , if selected == "" then mempty
@@ -69,7 +68,7 @@ outlineViewDemo = component "OutlineViewDemo" \dp -> React.do
6968 , OutlineItem { id: "pkg", title: "package.json", sfSymbol: "doc.text", children: [] }
7069 ]
7170 , headerVisible: false
72− , onSelectItem: E.onString "id" setSelection
71+ , onSelectItem: setSelection
7372 , style: Style.style { height: 200.0 } <> tw "rounded-lg overflow-hidden mb-2"
7473 }
7574 , if selection == "" then mempty
example-macos/src/Demo/Display.purs+3−4
@@ -17,7 +17,6 @@ import React.Basic.Hooks as React
1717import Yoga.React (component)
1818import Yoga.React.Native (text, tw, view)
1919import Yoga.React.Native.MacOS.AnimatedImage (nativeAnimatedImage)
20−import Yoga.React.Native.MacOS.Events as E
2120import Yoga.React.Native.MacOS.Image (nativeImage)
2221import Yoga.React.Native.MacOS.LevelIndicator (nativeLevelIndicator)
2322import Yoga.React.Native.MacOS.PathControl (nativePathControl)
@@ -83,7 +82,7 @@ levelIndicatorDemo = component "LevelIndicatorDemo" \dp -> React.do
8382 , minValue: 0.0
8483 , maxValue: 100.0
8584 , numberOfTickMarks: 11
86− , onChange: E.onNumber "value" setValue
85+ , onChange: setValue
8786 , style: Style.style { height: 24.0 }
8887 }
8988 , nativeLevelIndicator
@@ -109,7 +108,7 @@ progressDemo = component "ProgressDemo" \dp -> React.do
109108 , minValue: 0.0
110109 , maxValue: 100.0
111110 , numberOfTickMarks: 11
112− , onChange: E.onNumber "value" setValue
111+ , onChange: setValue
113112 , style: Style.style { height: 24.0 }
114113 }
115114 , nativeProgress
@@ -142,7 +141,7 @@ pathControlDemo = component "PathControlDemo" \dp -> pure do
142141 , nativePathControl
143142 { url: "/Users"
144143 , pathStyle: T.standardPath
145− , onSelectPath: E.onString "url" \_ -> pure unit
144+ , onSelectPath: \_ -> pure unit
146145 , style: Style.style { height: 24.0 } <> tw "mb-2"
147146 }
148147 ]
example-macos/src/Demo/DragDropFiles.purs+26−26
@@ -2,13 +2,14 @@ module Demo.DragDropFiles (dropZoneDemo, filePickerDemo) where
22
33import Prelude
44
5−import Demo.Shared (DemoProps, card, desc, getFieldJSON, label, scrollWrap, sectionTitle)
5+import Data.String (joinWith)
6+import Demo.Shared (DemoProps, card, desc, label, scrollWrap, sectionTitle)
67import React.Basic (JSX)
7−import React.Basic.Events (handler, handler_, unsafeEventFn)
88import React.Basic.Hooks (useState', (/\))
99import React.Basic.Hooks as React
1010import Yoga.React (component)
11−import Yoga.React.Native (nativeEvent, text, tw, view)
11+import Yoga.React.Native (text, tw, view)
12+import Yoga.React.Native.MacOS.DropZone (nativeDropZone)
1213import Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)
1314import Yoga.React.Native.MacOS.Types as T
1415import Yoga.React.Native.Style as Style
@@ -23,18 +24,23 @@ dropZoneDemo = component "DropZoneDemo" \dp -> React.do
2324 scrollWrap dp
2425 [ sectionTitle dp.fg "Drop Zone"
2526 , desc dp "Drag files from Finder into the area below"
26− , view
27− { draggedTypes: [ "NSFilenamesPboardType" ]
28− , onDrop: handler
29− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "dataTransfer" e)
30− \r -> do
31− setDropped r
32− setStatus "Drop files here"
33− setDragging false
34− , onDragEnter: handler_ do
27+ , nativeDropZone
28+ { onFileDrop: \d -> do
29+ let fileNames = joinWith ", " (map _.name d.files)
30+ let stringItems = joinWith ", " d.strings
31+ let
32+ info = case fileNames, stringItems of
33+ "", "" -> "Empty drop"
34+ fs, "" -> "Files: " <> fs
35+ "", ss -> "Strings: " <> ss
36+ fs, ss -> "Files: " <> fs <> " | Strings: " <> ss
37+ setDropped info
38+ setStatus "Drop files here"
39+ setDragging false
40+ , onFilesDragEnter: do
3541 setStatus "Release to drop!"
3642 setDragging true
37− , onDragLeave: handler_ do
43+ , onFilesDragExit: do
3844 setStatus "Drop files here"
3945 setDragging false
4046 , style: tw "rounded-lg items-center justify-center mb-2"
@@ -48,7 +54,7 @@ dropZoneDemo = component "DropZoneDemo" \dp -> React.do
4854 [ text { style: tw "text-sm" <> Style.style { color: dp.fg } } status
4955 , if dropped == "" then mempty
5056 else text { style: tw "text-xs mt-2 px-4" <> Style.style { color: dp.dimFg } }
51− ("Dropped: " <> dropped)
57+ dropped
5258 ]
5359 ]
5460
@@ -68,10 +74,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
6874 , allowMultiple: true
6975 , allowedTypes: [ "public.image", "public.text" ]
7076 , message: "Select files to open"
71− , onPickFiles: handler
72− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
73− setPicked
74− , onCancel: handler_ (setPicked "Cancelled")
77+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
78+ , onCancel: setPicked "Cancelled"
7579 , style: Style.style { height: 24.0, width: 120.0 }
7680 }
7781 , nativeFilePicker
@@ -80,10 +84,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
8084 , sfSymbol: "folder"
8185 , canChooseDirectories: true
8286 , message: "Select a folder"
83− , onPickFiles: handler
84− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
85− setPicked
86− , onCancel: handler_ (setPicked "Cancelled")
87+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
88+ , onCancel: setPicked "Cancelled"
8789 , style: Style.style { height: 24.0, width: 140.0, marginLeft: 8.0 }
8890 }
8991 , nativeFilePicker
@@ -93,10 +95,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
9395 , defaultName: "Untitled.txt"
9496 , allowedTypes: [ "public.plain-text" ]
9597 , message: "Choose save location"
96− , onPickFiles: handler
97− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
98− setPicked
99− , onCancel: handler_ (setPicked "Cancelled")
98+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
99+ , onCancel: setPicked "Cancelled"
100100 , style: Style.style { height: 24.0, width: 120.0, marginLeft: 8.0 }
101101 }
102102 ]
example-macos/src/Demo/InputControls.purs+28−28
@@ -15,19 +15,22 @@ module Demo.InputControls
1515
1616import Prelude
1717
18+import Data.Array
19+ ( (!!)
20+ )
21+import Data.Maybe (fromMaybe)
1822import Demo.Shared (DemoProps, card, desc, label, round, scrollWrap, sectionTitle)
1923import React.Basic (JSX)
20−import React.Basic.Events (handler, handler_, unsafeEventFn)
24+
2125import React.Basic.Hooks (useState', (/\))
2226import React.Basic.Hooks as React
2327import Yoga.React (component)
24−import Yoga.React.Native (nativeEvent, text, tw, view)
28+import Yoga.React.Native (text, tw, view)
2529import Yoga.React.Native.MacOS.Button (nativeButton)
2630import Yoga.React.Native.MacOS.Checkbox (nativeCheckbox)
2731import Yoga.React.Native.MacOS.ColorWell (nativeColorWell)
2832import Yoga.React.Native.MacOS.ComboBox (nativeComboBox)
2933import Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)
30−import Yoga.React.Native.MacOS.Events as E
3134import Yoga.React.Native.MacOS.LevelIndicator (nativeLevelIndicator)
3235import Yoga.React.Native.MacOS.PopUp (nativePopUp)
3336import Yoga.React.Native.MacOS.Progress (nativeProgress)
@@ -52,13 +55,13 @@ buttonDemo = component "ButtonDemo" \dp -> React.do
5255 { title: "Say Hello"
5356 , bezelStyle: T.push
5457 , primary: true
55− , onPress: handler_ (setStatus "Hello from PureScript!")
58+ , onPress: setStatus "Hello from PureScript!"
5659 , style: Style.style { height: 24.0, width: 140.0 }
5760 }
5861 , nativeButton
5962 { title: "Reset"
6063 , bezelStyle: T.push
61− , onPress: handler_ (setStatus "Ready")
64+ , onPress: setStatus "Ready"
6265 , style: Style.style { height: 24.0, width: 100.0, marginLeft: 8.0 }
6366 }
6467 , label dp.dimFg status
@@ -76,7 +79,7 @@ switchDemo = component "SwitchDemo" \dp -> React.do
7679 [ view { style: tw "flex-row items-center" }
7780 [ nativeSwitch
7881 { on
79− , onChange: E.onBool "on" setOn
82+ , onChange: setOn
8083 , style: Style.style { height: 24.0, width: 48.0 }
8184 }
8285 , label dp.dimFg (if on then "On" else "Off")
@@ -96,7 +99,7 @@ sliderDemo = component "SliderDemo" \dp -> React.do
9699 , minValue: 0.0
97100 , maxValue: 100.0
98101 , numberOfTickMarks: 11
99− , onChange: E.onNumber "value" setValue
102+ , onChange: setValue
100103 , style: Style.style { height: 24.0 }
101104 }
102105 , label dp.dimFg ("Value: " <> show (round value) <> " / 100")
@@ -119,21 +122,18 @@ popUpDemo :: DemoProps -> JSX
119122popUpDemo = component "PopUpDemo" \dp -> React.do
120123 idx /\ setIdx <- useState' 0
121124 title /\ setTitle <- useState' "Small"
125+ let items = [ "Small", "Medium", "Large", "Extra Large" ]
122126 pure do
123127 scrollWrap dp
124128 [ sectionTitle dp.fg "Pop Up Button"
125129 , card dp.cardBg
126130 [ view { style: tw "flex-row items-center" }
127131 [ nativePopUp
128− { items: [ "Small", "Medium", "Large", "Extra Large" ]
132+ { items
129133 , selectedIndex: idx
130− , onChange: handler
131− ( nativeEvent >>> unsafeEventFn \e ->
132− { idx: E.getFieldInt "selectedIndex" e, title: E.getFieldStr "title" e }
133− )
134− \r -> do
135− setIdx r.idx
136− setTitle r.title
134+ , onChange: \i -> do
135+ setIdx i
136+ setTitle (fromMaybe "" (items !! i))
137137 , style: Style.style { height: 24.0, width: 160.0 }
138138 }
139139 , label dp.dimFg ("Selected: " <> title)
@@ -154,8 +154,8 @@ comboBoxDemo = component "ComboBoxDemo" \dp -> React.do
154154 { items: [ "Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape" ]
155155 , text: txt
156156 , placeholder: "Type a fruit..."
157− , onChangeText: E.onString "text" setTxt
158− , onSelectItem: E.onString "text" \t -> do
157+ , onChangeText: setTxt
158+ , onSelectItem: \t -> do
159159 setTxt t
160160 setResult ("Selected: " <> t)
161161 , style: Style.style { height: 28.0 } <> tw "mb-2"
@@ -180,7 +180,7 @@ stepperDemo = component "StepperDemo" \dp -> React.do
180180 , minValue: 0.0
181181 , maxValue: 50.0
182182 , increment: 1.0
183− , onChange: E.onNumber "value" setValue
183+ , onChange: setValue
184184 , style: Style.style { width: 100.0, height: 24.0 }
185185 }
186186 ]
@@ -196,7 +196,7 @@ datePickerDemo = component "DatePickerDemo" \dp -> React.do
196196 , card dp.cardBg
197197 [ nativeDatePicker
198198 { graphical: false
199− , onChange: E.onString "date" setDateText
199+ , onChange: setDateText
200200 , style: Style.style { height: 24.0, width: 200.0 }
201201 }
202202 , if dateText == "" then mempty
@@ -215,7 +215,7 @@ colorWellDemo = component "ColorWellDemo" \dp -> React.do
215215 [ nativeColorWell
216216 { color
217217 , minimal: true
218− , onChange: E.onString "color" setColor
218+ , onChange: setColor
219219 , style: Style.style { height: 32.0, width: 48.0 }
220220 }
221221 , view
@@ -240,14 +240,14 @@ checkboxDemo = component "CheckboxDemo" \dp -> React.do
240240 { checked: a
241241 , title: "Enable notifications"
242242 , enabled: true
243− , onChange: E.onBool "checked" setA
243+ , onChange: setA
244244 , style: Style.style { height: 24.0 } <> tw "mb-1"
245245 }
246246 , nativeCheckbox
247247 { checked: b
248248 , title: "Dark mode"
249249 , enabled: true
250− , onChange: E.onBool "checked" setB
250+ , onChange: setB
251251 , style: Style.style { height: 24.0 }
252252 }
253253 ]
@@ -264,21 +264,21 @@ radioButtonDemo = component "RadioButtonDemo" \dp -> React.do
264264 { selected: choice == "option1"
265265 , title: "Small"
266266 , enabled: true
267− , onChange: handler_ (setChoice "option1")
267+ , onChange: \_ -> setChoice "option1"
268268 , style: Style.style { height: 24.0 } <> tw "mb-1"
269269 }
270270 , nativeRadioButton
271271 { selected: choice == "option2"
272272 , title: "Medium"
273273 , enabled: true
274− , onChange: handler_ (setChoice "option2")
274+ , onChange: \_ -> setChoice "option2"
275275 , style: Style.style { height: 24.0 } <> tw "mb-1"
276276 }
277277 , nativeRadioButton
278278 { selected: choice == "option3"
279279 , title: "Large"
280280 , enabled: true
281− , onChange: handler_ (setChoice "option3")
281+ , onChange: \_ -> setChoice "option3"
282282 , style: Style.style { height: 24.0 }
283283 }
284284 , label dp.dimFg ("Selected: " <> choice)
@@ -295,8 +295,8 @@ searchFieldDemo = component "SearchFieldDemo" \dp -> React.do
295295 , nativeSearchField
296296 { text: query
297297 , placeholder: "Search..."
298− , onChangeText: E.onString "text" setQuery
299− , onSearch: E.onString "text" \t -> setResult ("Searched: " <> t)
298+ , onChangeText: setQuery
299+ , onSearch: \t -> setResult ("Searched: " <> t)
300300 , style: Style.style { height: 28.0 } <> tw "mb-2"
301301 }
302302 , if result == "" then mempty
@@ -313,7 +313,7 @@ tokenFieldDemo = component "TokenFieldDemo" \dp -> React.do
313313 , nativeTokenField
314314 { tokens
315315 , placeholder: "Add tags..."
316− , onChangeTokens: E.onStrings "tokens" setTokens
316+ , onChangeTokens: setTokens
317317 , style: Style.style { height: 28.0 } <> tw "mb-2"
318318 }
319319 ]
example-macos/src/Demo/Layout.purs+1−2
@@ -9,7 +9,6 @@ import React.Basic.Hooks as React
99import Yoga.React (component)
1010import Yoga.React.Native (text, tw, view)
1111import Yoga.React.Native.MacOS.Box (nativeBox)
12−import Yoga.React.Native.MacOS.Events as E
1312import Yoga.React.Native.MacOS.SplitView (nativeSplitView)
1413import Yoga.React.Native.MacOS.TabView (nativeTabView)
1514import Yoga.React.Native.Style as Style
@@ -65,7 +64,7 @@ tabViewDemo = component "TabViewDemo" \dp -> React.do
6564 , { id: "about", label: "About" }
6665 ]
6766 , selectedItem: selected
68− , onSelectTab: E.onString "tabId" setSelected
67+ , onSelectTab: setSelected
6968 , style: Style.style { height: 32.0 } <> tw "mb-2"
7069 }
7170 ]
example-macos/src/Demo/MapsDocs.purs+1−2
@@ -8,7 +8,6 @@ import React.Basic.Hooks (useState', (/\))
88import React.Basic.Hooks as React
99import Yoga.React (component)
1010import Yoga.React.Native (text, tw, view)
11−import Yoga.React.Native.MacOS.Events as E
1211import Yoga.React.Native.MacOS.MapView (nativeMapView)
1312import Yoga.React.Native.MacOS.PDFView (nativePDFView)
1413import Yoga.React.Native.MacOS.Segmented (nativeSegmented)
@@ -30,7 +29,7 @@ mapViewDemo = component "MapViewDemo" \dp -> React.do
3029 , nativeSegmented
3130 { labels: [ "Standard", "Satellite", "Hybrid" ]
3231 , selectedIndex: mapType
33− , onChange: E.onInt "selectedIndex" setMapType
32+ , onChange: setMapType
3433 , style: Style.style { width: 240.0, height: 24.0 }
3534 }
3635 ]
example-macos/src/Demo/Navigation.purs+6−4
@@ -6,6 +6,7 @@ import Data.Array (concatMap, null)
66import Data.String (toLower, contains, Pattern(..))
77import Demo.AiMl (cameraDemo, naturalLanguageDemo, ocrDemo, speechRecognitionDemo)
88import Demo.Animation (riveDemo)
9+import Demo.SpringAnimation (springDemo)
910import Demo.Chat (chatDemo)
1011import Demo.DataViews (outlineViewDemo, tableViewDemo)
1112import Demo.Display (animatedImageDemo, imageDemo, levelIndicatorDemo, pathControlDemo, progressDemo, separatorDemo, videoPlayerDemo)
@@ -24,7 +25,6 @@ import React.Basic.Hooks (useState', (/\))
2425import React.Basic.Hooks as React
2526import Yoga.React (component)
2627import Yoga.React.Native (text, tw, view)
27−import Yoga.React.Native.MacOS.Events as E
2828import Yoga.React.Native.MacOS.OutlineView (OutlineItem(..), nativeOutlineView)
2929import Yoga.React.Native.MacOS.SearchField (nativeSearchField)
3030import Yoga.React.Native.Style as Style
@@ -81,7 +81,8 @@ outlineTree = do
8181 , leaf "filepicker" "File Picker" "folder"
8282 ]
8383 , folder "animation" "Animation" "play.circle"
84− [ leaf "rive" "Rive" "play.circle"
84+ [ leaf "springs" "Spring Physics" "sparkles"
85+ , leaf "rive" "Rive" "play.circle"
8586 ]
8687 , folder "system" "System Services" "gearshape.2"
8788 [ leaf "clipboard" "Clipboard" "doc.on.clipboard"
@@ -135,13 +136,13 @@ outlineSidebar _ setSelectedItem = sidebarComponent { setSelectedItem }
135136 [ nativeSearchField
136137 { text: search
137138 , placeholder: "Filter..."
138− , onChangeText: E.onString "text" setSearch
139+ , onChangeText: setSearch
139140 , style: Style.style { height: 24.0, marginLeft: 8.0, marginRight: 8.0, marginBottom: 4.0 }
140141 }
141142 , nativeOutlineView
142143 { items
143144 , headerVisible: false
144− , onSelectItem: E.onString "id" props.setSelectedItem
145+ , onSelectItem: props.setSelectedItem
145146 , style: tw "flex-1"
146147 }
147148 ]
@@ -181,6 +182,7 @@ demoContent dp = case _ of
181182 "outlineview" -> outlineViewDemo dp
182183 "dropzone" -> dropZoneDemo dp
183184 "filepicker" -> filePickerDemo dp
185+ "springs" -> springDemo dp
184186 "rive" -> riveDemo dp
185187 "clipboard" -> clipboardDemo dp
186188 "share" -> shareDemo dp
example-macos/src/Demo/Overlays.purs+11−13
@@ -10,7 +10,6 @@ import Prelude
1010
1111import Demo.Shared (DemoProps, card, desc, label, scrollWrap, sectionTitle)
1212import React.Basic (JSX)
13−import React.Basic.Events (handler_)
1413import React.Basic.Hooks (useState', (/\))
1514import React.Basic.Hooks as React
1615import Yoga.React (component)
@@ -18,7 +17,6 @@ import Yoga.React.Native (text, tw, view)
1817import Yoga.React.Native.MacOS.Alert (macosAlert)
1918import Yoga.React.Native.MacOS.Button (nativeButton)
2019import Yoga.React.Native.MacOS.ContextMenu (nativeContextMenu)
21−import Yoga.React.Native.MacOS.Events as E
2220import Yoga.React.Native.MacOS.Menu (macosShowMenu)
2321import Yoga.React.Native.MacOS.Popover (nativePopover)
2422import Yoga.React.Native.MacOS.Sheet (nativeSheet)
@@ -33,7 +31,7 @@ alertDemo = component "AlertDemo" \dp -> pure do
3331 , nativeButton
3432 { title: "Show Alert"
3533 , bezelStyle: T.push
36− , onPress: handler_ (macosAlert { style: T.warning, title: "Are you sure?", message: "This action cannot be undone.", buttons: [ "Cancel", "OK" ] })
34+ , onPress: macosAlert { style: T.warning, title: "Are you sure?", message: "This action cannot be undone.", buttons: [ "Cancel", "OK" ] }
3735 , style: Style.style { height: 24.0, width: 120.0 } <> tw "mb-4"
3836 }
3937 ]
@@ -48,12 +46,12 @@ sheetDemo = component "SheetDemo" \dp -> React.do
4846 , nativeButton
4947 { title: "Show Sheet"
5048 , bezelStyle: T.push
51− , onPress: handler_ (setVisible true)
49+ , onPress: setVisible true
5250 , style: Style.style { height: 24.0, width: 120.0 } <> tw "mb-2"
5351 }
5452 , nativeSheet
5553 { visible
56− , onDismiss: handler_ (setVisible false)
54+ , onDismiss: setVisible false
5755 }
5856 [ view { style: tw "p-6" <> Style.style { width: 400.0, height: 200.0 } }
5957 [ text { style: tw "text-lg font-semibold mb-2" <> Style.style { color: dp.fg } } "Sheet Content"
@@ -61,7 +59,7 @@ sheetDemo = component "SheetDemo" \dp -> React.do
6159 , nativeButton
6260 { title: "Dismiss"
6361 , bezelStyle: T.push
64− , onPress: handler_ (setVisible false)
62+ , onPress: setVisible false
6563 , style: Style.style { height: 24.0, width: 100.0 }
6664 }
6765 ]
@@ -79,13 +77,13 @@ popoverDemo = component "PopoverDemo" \dp -> React.do
7977 { visible
8078 , preferredEdge: T.bottom
8179 , behavior: T.transient
82− , onClose: handler_ (setVisible false)
80+ , onClose: setVisible false
8381 , style: tw "mb-2"
8482 }
8583 [ nativeButton
8684 { title: if visible then "Hide Popover" else "Show Popover"
8785 , bezelStyle: T.push
88− , onPress: handler_ (setVisible (not visible))
86+ , onPress: setVisible (not visible)
8987 , style: Style.style { height: 24.0, width: 140.0 }
9088 }
9189 , view { style: tw "p-4" <> Style.style { width: 200.0, height: 80.0 } }
@@ -111,7 +109,7 @@ contextMenuDemo = component "ContextMenuDemo" \dp -> React.do
111109 , { id: "delete", title: "Delete", sfSymbol: "trash" }
112110 , { id: "selectAll", title: "Select All", sfSymbol: "selection.pin.in.out" }
113111 ]
114− , onSelectItem: E.onString "itemId" setResult
112+ , onSelectItem: setResult
115113 , style: Style.style {}
116114 }
117115 ( card dp.cardBg
@@ -135,16 +133,16 @@ menuDemo = component "MenuDemo" \dp -> React.do
135133 [ nativeButton
136134 { title: "Show Menu"
137135 , bezelStyle: T.push
138− , onPress: handler_
139− ( macosShowMenu
136+ , onPress: macosShowMenu
137+ { items:
140138 [ { title: "New File", id: "new" }
141139 , { title: "Open...", id: "open" }
142140 , { title: "-", id: "sep" }
143141 , { title: "Save", id: "save" }
144142 , { title: "Save As...", id: "saveAs" }
145143 ]
146− \itemId -> setResult ("Menu: " <> itemId)
147− )
144+ , onSelectItem: \itemId -> setResult ("Menu: " <> itemId)
145+ }
148146 , style: Style.style { height: 24.0, width: 120.0 }
149147 }
150148 , if result == "" then mempty
example-macos/src/Demo/SpringAnimation.pursnew file+123
@@ -0,0 +1,123 @@
1+module Demo.SpringAnimation (springDemo) where
2+
3+import Prelude
4+
5+import Demo.Shared (DemoProps, card, desc, scrollWrap, sectionTitle)
6+import React.Basic (JSX)
7+import React.Basic.Hooks (useState', (/\))
8+import React.Basic.Hooks as React
9+import Yoga.React (component)
10+import Yoga.React.Native (text, tw, view)
11+import Yoga.React.Native.Animated (animatedView, animatedView_, interpolate, useSpring)
12+import React.Basic.Events (handler_)
13+import Yoga.React.Native.Pressable (pressable)
14+import Yoga.React.Native.MacOS.Button (nativeButton)
15+import Yoga.React.Native.MacOS.Types as T
16+import Yoga.React.Native.Style as Style
17+
18+springDemo :: DemoProps -> JSX
19+springDemo = component "SpringDemo" \dp -> React.do
20+ pressed /\ setPressed <- useState' false
21+ toggled /\ setToggled <- useState' false
22+ fadeIn /\ setFadeIn <- useState' false
23+ showItems /\ setShowItems <- useState' false
24+ let scaleTarget = if pressed then 0.92 else 1.0
25+ scale <- useSpring scaleTarget { stiffness: 400.0, damping: 15.0 }
26+ let toggleTarget = if toggled then 200.0 else 0.0
27+ translateX <- useSpring toggleTarget { stiffness: 180.0, damping: 14.0 }
28+ let fadeTarget = if fadeIn then 1.0 else 0.0
29+ opacity <- useSpring fadeTarget { stiffness: 120.0, damping: 20.0 }
30+ item0 <- useSpring (if showItems then 1.0 else 0.0) { stiffness: 200.0, damping: 18.0 }
31+ item1 <- useSpring (if showItems then 1.0 else 0.0) { stiffness: 180.0, damping: 18.0, delay: 50 }
32+ item2 <- useSpring (if showItems then 1.0 else 0.0) { stiffness: 160.0, damping: 18.0, delay: 100 }
33+ item3 <- useSpring (if showItems then 1.0 else 0.0) { stiffness: 140.0, damping: 18.0, delay: 150 }
34+ pure do
35+ scrollWrap dp
36+ [ sectionTitle dp.fg "Spring Animations"
37+ , desc dp "Declarative spring physics using useSpring"
38+
39+ , sectionTitle dp.fg "Scale on Press"
40+ , desc dp "Hold down the card — it springs to 0.92x, release to bounce back"
41+ , pressable
42+ { onPressIn: handler_ (setPressed true)
43+ , onPressOut: handler_ (setPressed false)
44+ }
45+ [ animatedView
46+ { style: Style.style { transform: [ { scale } ] } }
47+ [ card dp.cardBg
48+ [ view { style: tw "items-center py-4" }
49+ [ text { style: tw "text-sm font-semibold" <> Style.style { color: dp.fg } }
50+ (if pressed then "Pressing..." else "Hold me!")
51+ , text { style: tw "text-xs mt-1" <> Style.style { color: dp.dimFg } }
52+ "useSpring { stiffness: 400, damping: 15 }"
53+ ]
54+ ]
55+ ]
56+ ]
57+
58+ , sectionTitle dp.fg "Spring Toggle"
59+ , desc dp "Slides a box 200px to the right with a spring"
60+ , nativeButton
61+ { title: if toggled then "Spring Left" else "Spring Right"
62+ , bezelStyle: T.push
63+ , onPress: setToggled (not toggled)
64+ , style: Style.style { height: 24.0, width: 140.0, marginBottom: 8.0 }
65+ }
66+ , animatedView_
67+ { style: tw "rounded-lg"
68+ <> Style.style
69+ { width: 60.0
70+ , height: 60.0
71+ , backgroundColor: "#007AFF"
72+ , transform: [ { translateX } ]
73+ }
74+ }
75+
76+ , sectionTitle dp.fg "Fade In"
77+ , desc dp "Springs opacity from 0 to 1"
78+ , nativeButton
79+ { title: if fadeIn then "Fade Out" else "Fade In"
80+ , bezelStyle: T.push
81+ , onPress: setFadeIn (not fadeIn)
82+ , style: Style.style { height: 24.0, width: 120.0, marginBottom: 8.0 }
83+ }
84+ , animatedView
85+ { style: Style.style { opacity } }
86+ [ card dp.cardBg
87+ [ view { style: tw "items-center py-3" }
88+ [ text { style: tw "text-sm" <> Style.style { color: dp.fg } } "I fade with a spring curve"
89+ ]
90+ ]
91+ ]
92+
93+ , sectionTitle dp.fg "Staggered Items"
94+ , desc dp "Each item springs in with increasing delay"
95+ , nativeButton
96+ { title: if showItems then "Hide Items" else "Show Items"
97+ , bezelStyle: T.push
98+ , onPress: setShowItems (not showItems)
99+ , style: Style.style { height: 24.0, width: 120.0, marginBottom: 8.0 }
100+ }
101+ , staggeredItem dp "PureScript" "#007AFF" item0
102+ , staggeredItem dp "React Native" "#34C759" item1
103+ , staggeredItem dp "macOS" "#FF9500" item2
104+ , staggeredItem dp "Spring Physics" "#AF52DE" item3
105+ ]
106+ where
107+ staggeredItem _ title color anim =
108+ animatedView
109+ { style: Style.style
110+ { opacity: anim
111+ , transform: [ { translateX: slideX } ]
112+ , marginBottom: 4.0
113+ }
114+ }
115+ [ view
116+ { style: tw "rounded-lg px-4 py-2 flex-row items-center"
117+ <> Style.style { backgroundColor: color }
118+ }
119+ [ text { style: tw "text-sm font-semibold" <> Style.style { color: "#FFFFFF" } } title
120+ ]
121+ ]
122+ where
123+ slideX = interpolate anim { inputRange: [ 0.0, 1.0 ], outputRange: [ -30.0, 0.0 ], extrapolate: "clamp" }
example-macos/src/Demo/SystemServices.purs+28−30
@@ -14,14 +14,13 @@ import Prelude
1414
1515import Demo.Shared (DemoProps, desc, scrollWrap, sectionTitle)
1616import React.Basic (JSX)
17−import React.Basic.Events (handler_)
17+
1818import React.Basic.Hooks (useState', (/\))
1919import React.Basic.Hooks as React
2020import Yoga.React (component)
2121import Yoga.React.Native (tw, view)
2222import Yoga.React.Native.MacOS.Button (nativeButton)
2323import Yoga.React.Native.MacOS.ColorPanel (macosShowColorPanel)
24−import Yoga.React.Native.MacOS.Events as E
2524import Yoga.React.Native.MacOS.FontPanel (macosShowFontPanel)
2625import Yoga.React.Native.MacOS.Pasteboard (copyToClipboard)
2726import Yoga.React.Native.MacOS.QuickLook (macosQuickLook)
@@ -43,7 +42,7 @@ clipboardDemo = component "ClipboardDemo" \dp -> pure do
4342 [ nativeButton
4443 { title: "Copy 'Hello'"
4544 , bezelStyle: T.push
46− , onPress: handler_ (copyToClipboard "Hello from PureScript!")
45+ , onPress: copyToClipboard "Hello from PureScript!"
4746 , style: Style.style { height: 24.0, width: 120.0 }
4847 }
4948 ]
@@ -57,7 +56,7 @@ shareDemo = component "ShareDemo" \dp -> pure do
5756 , nativeButton
5857 { title: "Share Text"
5958 , bezelStyle: T.push
60− , onPress: handler_ (macosShare [ "Hello from PureScript React Native!" ])
59+ , onPress: macosShare [ "Hello from PureScript React Native!" ]
6160 , style: Style.style { height: 24.0, width: 120.0 } <> tw "mb-2"
6261 }
6362 ]
@@ -70,7 +69,7 @@ notificationsDemo = component "NotificationsDemo" \dp -> pure do
7069 , nativeButton
7170 { title: "Send Notification"
7271 , bezelStyle: T.push
73− , onPress: handler_ (macosNotify "PureScript" "Hello from React Native macOS!")
72+ , onPress: macosNotify { title: "PureScript", body: "Hello from React Native macOS!" }
7473 , style: Style.style { height: 24.0, width: 160.0 } <> tw "mb-2"
7574 }
7675 ]
@@ -84,19 +83,19 @@ soundDemo = component "SoundDemo" \dp -> pure do
8483 [ nativeButton
8584 { title: "Glass"
8685 , bezelStyle: T.push
87− , onPress: handler_ (macosPlaySound "Glass")
86+ , onPress: macosPlaySound "Glass"
8887 , style: Style.style { height: 24.0, width: 80.0 }
8988 }
9089 , nativeButton
9190 { title: "Ping"
9291 , bezelStyle: T.push
93− , onPress: handler_ (macosPlaySound "Ping")
92+ , onPress: macosPlaySound "Ping"
9493 , style: Style.style { height: 24.0, width: 80.0, marginLeft: 8.0 }
9594 }
9695 , nativeButton
9796 { title: "Beep"
9897 , bezelStyle: T.push
99− , onPress: handler_ macosBeep
98+ , onPress: macosBeep
10099 , style: Style.style { height: 24.0, width: 80.0, marginLeft: 8.0 }
101100 }
102101 ]
@@ -113,22 +112,21 @@ statusBarDemo = component "StatusBarDemo" \dp -> React.do
113112 [ nativeButton
114113 { title: if active then "Remove" else "Add to Menu Bar"
115114 , bezelStyle: T.push
116− , onPress: handler_
117− ( if active then do
118− macosRemoveStatusBarItem
119− setActive false
120− else do
121− macosSetStatusBarItem
122− { title: ""
123− , sfSymbol: "swift"
124− , menuItems:
125− [ { id: "about", title: "About PureScript RN" }
126− , { id: "sep", title: "-" }
127− , { id: "quit", title: "Quit" }
128− ]
129− }
130− setActive true
131− )
115+ , onPress:
116+ if active then do
117+ macosRemoveStatusBarItem
118+ setActive false
119+ else do
120+ macosSetStatusBarItem
121+ { title: ""
122+ , sfSymbol: "swift"
123+ , menuItems:
124+ [ { id: "about", title: "About PureScript RN" }
125+ , { id: "sep", title: "-" }
126+ , { id: "quit", title: "Quit" }
127+ ]
128+ }
129+ setActive true
132130 , style: Style.style { height: 24.0, width: 180.0 }
133131 }
134132 ]
@@ -143,7 +141,7 @@ quickLookDemo = component "QuickLookDemo" \dp -> pure do
143141 [ nativeButton
144142 { title: "Preview /etc/hosts"
145143 , bezelStyle: T.push
146− , onPress: handler_ (macosQuickLook "/etc/hosts")
144+ , onPress: macosQuickLook "/etc/hosts"
147145 , style: Style.style { height: 24.0, width: 180.0 }
148146 }
149147 ]
@@ -158,7 +156,7 @@ colorPanelDemo = component "ColorPanelDemo" \dp -> pure do
158156 [ nativeButton
159157 { title: "Show Color Panel"
160158 , bezelStyle: T.push
161− , onPress: handler_ macosShowColorPanel
159+ , onPress: macosShowColorPanel
162160 , style: Style.style { height: 24.0, width: 180.0 }
163161 }
164162 ]
@@ -173,7 +171,7 @@ fontPanelDemo = component "FontPanelDemo" \dp -> pure do
173171 [ nativeButton
174172 { title: "Show Font Panel"
175173 , bezelStyle: T.push
176− , onPress: handler_ macosShowFontPanel
174+ , onPress: macosShowFontPanel
177175 , style: Style.style { height: 24.0, width: 180.0 }
178176 }
179177 ]
@@ -189,20 +187,20 @@ speechDemo = component "SpeechDemo" \dp -> React.do
189187 , nativeTextField
190188 { text: txt
191189 , placeholder: "Text to speak..."
192− , onChangeText: E.onString "text" setTxt
190+ , onChangeText: setTxt
193191 , style: Style.style { height: 24.0 } <> tw "mb-2"
194192 }
195193 , view { style: tw "flex-row items-center mb-4" }
196194 [ nativeButton
197195 { title: "Speak"
198196 , bezelStyle: T.push
199− , onPress: handler_ (say txt)
197+ , onPress: say txt
200198 , style: Style.style { height: 24.0, width: 100.0 }
201199 }
202200 , nativeButton
203201 { title: "Stop"
204202 , bezelStyle: T.push
205− , onPress: handler_ stopSpeaking
203+ , onPress: stopSpeaking
206204 , style: Style.style { height: 24.0, width: 100.0, marginLeft: 8.0 }
207205 }
208206 ]
example-macos/src/Demo/TextEditing.purs+1−2
@@ -8,7 +8,6 @@ import React.Basic.Hooks (useState', (/\))
88import React.Basic.Hooks as React
99import Yoga.React (component)
1010import Yoga.React.Native (tw, view)
11−import Yoga.React.Native.MacOS.Events as E
1211import Yoga.React.Native.MacOS.TextField (nativeTextField)
1312import Yoga.React.Native.MacOS.TextEditor (nativeTextEditor)
1413import Yoga.React.Native.Style as Style
@@ -24,7 +23,7 @@ textFieldDemo = component "TextFieldDemo" \dp -> React.do
2423 { placeholder: "Type something..."
2524 , search: true
2625 , text: txt
27− , onChangeText: E.onString "text" setTxt
26+ , onChangeText: setTxt
2827 , style: Style.style { height: 24.0 }
2928 }
3029 , if txt == "" then mempty
example-macos/src/Demo/WebBrowser.purs+4−10
@@ -4,12 +4,10 @@ import Prelude
44
55import Demo.Shared (DemoProps, sectionTitle)
66import React.Basic (JSX)
7−import React.Basic.Events (handler, unsafeEventFn)
87import React.Basic.Hooks (useState', (/\))
98import React.Basic.Hooks as React
109import Yoga.React (component)
11−import Yoga.React.Native (nativeEvent, tw, view)
12−import Yoga.React.Native.MacOS.Events as E
10+import Yoga.React.Native (tw, view)
1311import Yoga.React.Native.MacOS.TextField (nativeTextField)
1412import Yoga.React.Native.MacOS.WebView (nativeWebView)
1513import Yoga.React.Native.Style as Style
@@ -25,17 +23,13 @@ webViewDemo = component "WebViewDemo" \dp -> React.do
2523 { text: urlBar
2624 , placeholder: "Enter URL..."
2725 , search: false
28− , onChangeText: E.onString "text" setUrlBar
29− , onSubmit: E.onString "text" setUrl
26+ , onChangeText: setUrlBar
27+ , onSubmit: setUrl
3028 , style: Style.style { height: 24.0, marginBottom: 8.0 }
3129 }
3230 , nativeWebView
3331 { url
34− , onFinishLoad: handler
35− ( nativeEvent >>> unsafeEventFn \e ->
36− { url: E.getFieldStr "url" e, title: E.getFieldStr "title" e }
37− )
38− \r -> setUrlBar r.url
32+ , onFinishLoad: setUrlBar
3933 , style: tw "flex-1" <> Style.style { minHeight: 400.0 }
4034 }
4135 ]
example-macos/src/Main.purs+1−2
@@ -8,7 +8,6 @@ import Demo.Navigation (demoContent, outlineSidebar)
88import Demo.Shared (DemoProps)
99import Effect (Effect)
1010import React.Basic (JSX)
11−import React.Basic.Events (handler_)
1211import React.Basic.Hooks (useState', (/\))
1312import React.Basic.Hooks as React
1413import Yoga.React (component)
@@ -45,7 +44,7 @@ app = component "App" \_ -> React.do
4544 , selectedItem: ""
4645 , toolbarStyle: T.unified
4746 , windowTitle: "PureScript React Native"
48− , onSelectItem: handler_ (pure unit)
47+ , onSelectItem: \_ -> pure unit
4948 , style: Style.style { height: 0.0, width: 0.0 }
5049 }
5150 , sidebarLayout
spago.lock+10−1
@@ -17,6 +17,12 @@
1717 {
1818 "functions": ">=6.0.0 <7.0.0"
1919 },
20+ {
21+ "maybe": ">=6.0.0 <7.0.0"
22+ },
23+ {
24+ "newtype": ">=5.0.0 <6.0.0"
25+ },
2026 {
2127 "nullable": ">=6.0.0 <7.0.0"
2228 },
@@ -27,7 +33,10 @@
2733 "react-basic": ">=17.0.0 <18.0.0"
2834 },
2935 {
30− "react-basic-hooks": ">=8.2.0 <10.0.0"
36+ "react-basic-hooks": ">=8.2.0 <9.0.0"
37+ },
38+ {
39+ "tuples": ">=7.0.0 <8.0.0"
3140 },
3241 {
3342 "type-equality": ">=4.0.1 <5.0.0"
spago.yaml+5−2
@@ -1,7 +1,7 @@
11package:
22 name: yoga-react-native
33 publish:
4− version: 0.1.0
4+ version: 0.2.1
55 license: MIT
66 location:
77 githubOwner: rowtype-yoga
@@ -11,10 +11,13 @@ package:
1111 - effect: ">=4.0.0 <5.0.0"
1212 - foreign: ">=7.0.0 <8.0.0"
1313 - functions: ">=6.0.0 <7.0.0"
14+ - maybe: ">=6.0.0 <7.0.0"
15+ - newtype: ">=5.0.0 <6.0.0"
1416 - nullable: ">=6.0.0 <7.0.0"
1517 - prelude: ">=6.0.1 <7.0.0"
1618 - react-basic: ">=17.0.0 <18.0.0"
17− - react-basic-hooks: ">=8.2.0 <10.0.0"
19+ - react-basic-hooks: ">=8.2.0 <9.0.0"
20+ - tuples: ">=7.0.0 <8.0.0"
1821 - type-equality: ">=4.0.1 <5.0.0"
1922 - typelevel-prelude: ">=7.0.0 <8.0.0"
2023 - unsafe-coerce: ">=6.0.0 <7.0.0"
src/Yoga/React/Native/Animated.js+24−1
@@ -1,4 +1,5 @@
11import { Animated, useAnimatedValue } from "react-native";
2+import { useRef, useEffect } from "react";
23
34export const newValueImpl = (n) => new Animated.Value(n);
45export const newValueXYImpl = (x, y) => new Animated.ValueXY({ x, y });
@@ -27,9 +28,31 @@ export const subtractImpl = (a) => (b) => Animated.subtract(a, b);
2728export const multiplyImpl = (a) => (b) => Animated.multiply(a, b);
2829export const divideImpl = (a) => (b) => Animated.divide(a, b);
2930export const moduloImpl = (a) => (n) => Animated.modulo(a, n);
30−export const diffClampImpl = (a) => (min) => (max) => Animated.diffClamp(a, min, max);
31+export const diffClampImpl = (a) => (min) => (max) =>
32+ Animated.diffClamp(a, min, max);
3133export const _animatedViewImpl = Animated.View;
3234export const _animatedTextImpl = Animated.Text;
3335export const _animatedImageImpl = Animated.Image;
3436export const _animatedScrollViewImpl = Animated.ScrollView;
3537export const useAnimatedValueImpl = (n) => () => useAnimatedValue(n);
38+
39+export const useSpringImpl = (target) => (config) => () => {
40+ const valueRef = useRef(null);
41+ const prevTargetRef = useRef(target);
42+ if (valueRef.current === null) {
43+ valueRef.current = new Animated.Value(target);
44+ }
45+ useEffect(() => {
46+ if (prevTargetRef.current !== target) {
47+ prevTargetRef.current = target;
48+ const anim = Animated.spring(valueRef.current, {
49+ toValue: target,
50+ useNativeDriver: false,
51+ ...config,
52+ });
53+ anim.start();
54+ return () => anim.stop();
55+ }
56+ });
57+ return valueRef.current;
58+};
src/Yoga/React/Native/Animated.purs+9
@@ -39,6 +39,8 @@ module Yoga.React.Native.Animated
3939 , animatedScrollView_
4040 , useAnimatedValue
4141 , UseAnimatedValue
42+ , useSpring
43+ , UseSpring
4244 , TimingConfig
4345 , SpringConfig
4446 , DecayConfig
@@ -272,3 +274,10 @@ foreign import data UseAnimatedValue :: Type -> Type
272274
273275useAnimatedValue :: Number -> Hook UseAnimatedValue AnimatedValue
274276useAnimatedValue n = unsafeHook (useAnimatedValueImpl n)
277+
278+foreign import useSpringImpl :: forall r. Number -> { | r } -> Effect AnimatedValue
279+
280+foreign import data UseSpring :: Type -> Type
281+
282+useSpring :: forall r. Number -> { | r } -> Hook UseSpring AnimatedValue
283+useSpring target config = unsafeHook (useSpringImpl target config)
src/Yoga/React/Native/MacOS/Alert.purs+2−1
@@ -8,6 +8,7 @@ import Prelude
88import Effect (Effect)
99import Effect.Uncurried (EffectFn1, runEffectFn1)
1010import Prim.Row (class Union)
11+import Unsafe.Coerce (unsafeCoerce)
1112import Yoga.React.Native.MacOS.Types (AlertStyle)
1213
1314type AlertProps =
@@ -24,4 +25,4 @@ macosAlert
2425 . Union given missing AlertProps
2526 => { | given }
2627 -> Effect Unit
27−macosAlert = runEffectFn1 alertImpl
28+macosAlert r = runEffectFn1 alertImpl (unsafeCoerce r)
src/Yoga/React/Native/MacOS/Button.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const buttonImpl = requireNativeComponent("NativeButton");
3+const NativeButton = requireNativeComponent("NativeButton");
4+export const buttonImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onPress === "function") {
7+ nativeProps.onPress = () => props.onPress();
8+ }
9+ return React.createElement(NativeButton, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/Button.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.Button (nativeButton, NativeButtonAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78import Yoga.React.Native.MacOS.Types (BezelStyle)
@@ -18,5 +19,5 @@ type NativeButtonAttributes = BaseAttributes
1819 , destructive :: Boolean
1920 , primary :: Boolean
2021 , buttonEnabled :: Boolean
21− , onPress :: EventHandler
22+ , onPress :: Effect Unit
2223 )
src/Yoga/React/Native/MacOS/Checkbox.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const checkboxImpl = requireNativeComponent("MacOSCheckbox");
3+const NativeCheckbox = requireNativeComponent("MacOSCheckbox");
4+export const checkboxImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) => props.onChange(!!e.nativeEvent.checked)();
8+ }
9+ return React.createElement(NativeCheckbox, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/Checkbox.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.Checkbox
33 , NativeCheckboxAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -17,5 +18,5 @@ type NativeCheckboxAttributes = BaseAttributes
1718 ( checked :: Boolean
1819 , title :: String
1920 , enabled :: Boolean
20− , onChange :: EventHandler
21+ , onChange :: Boolean -> Effect Unit
2122 )
src/Yoga/React/Native/MacOS/ColorWell.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const colorWellImpl = requireNativeComponent("NativeColorWell");
3+const NativeColorWell = requireNativeComponent("NativeColorWell");
4+export const colorWellImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) => props.onChange(e.nativeEvent.color)();
8+ }
9+ return React.createElement(NativeColorWell, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/ColorWell.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.ColorWell (nativeColorWell, NativeColorWellAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -13,5 +14,5 @@ nativeColorWell = createNativeElement_ colorWellImpl
1314type NativeColorWellAttributes = BaseAttributes
1415 ( color :: String
1516 , minimal :: Boolean
16− , onChange :: EventHandler
17+ , onChange :: String -> Effect Unit
1718 )
src/Yoga/React/Native/MacOS/ComboBox.js+12−1
@@ -1,2 +1,13 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const comboBoxImpl = requireNativeComponent("MacOSComboBox");
3+const NativeComboBox = requireNativeComponent("MacOSComboBox");
4+export const comboBoxImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChangeText === "function") {
7+ nativeProps.onChangeText = (e) => props.onChangeText(e.nativeEvent.text)();
8+ }
9+ if (typeof props.onSelectItem === "function") {
10+ nativeProps.onSelectItem = (e) => props.onSelectItem(e.nativeEvent.text)();
11+ }
12+ return React.createElement(NativeComboBox, { ...nativeProps, ref });
13+});
src/Yoga/React/Native/MacOS/ComboBox.purs+4−3
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.ComboBox
33 , NativeComboBoxAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -17,6 +18,6 @@ type NativeComboBoxAttributes = BaseAttributes
1718 ( items :: Array String
1819 , text :: String
1920 , placeholder :: String
20− , onChangeText :: EventHandler
21− , onSelectItem :: EventHandler
21+ , onChangeText :: String -> Effect Unit
22+ , onSelectItem :: String -> Effect Unit
2223 )
src/Yoga/React/Native/MacOS/ContextMenu.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const contextMenuImpl = requireNativeComponent("MacOSContextMenu");
3+const NativeContextMenu = requireNativeComponent("MacOSContextMenu");
4+export const contextMenuImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectItem === "function") {
7+ nativeProps.onSelectItem = (e) =>
8+ props.onSelectItem(e.nativeEvent.itemId)();
9+ }
10+ return React.createElement(NativeContextMenu, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/ContextMenu.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.ContextMenu (nativeContextMenu, NativeContextMenuAttributes, ContextMenuItem) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
78
@@ -18,5 +19,5 @@ type ContextMenuItem =
1819
1920type NativeContextMenuAttributes = BaseAttributes
2021 ( items :: Array ContextMenuItem
21− , onSelectItem :: EventHandler
22+ , onSelectItem :: String -> Effect Unit
2223 )
src/Yoga/React/Native/MacOS/DatePicker.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const datePickerImpl = requireNativeComponent("NativeDatePicker");
3+const NativeDatePicker = requireNativeComponent("NativeDatePicker");
4+export const datePickerImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) => props.onChange(e.nativeEvent.date)();
8+ }
9+ return React.createElement(NativeDatePicker, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/DatePicker.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.DatePicker (nativeDatePicker, NativeDatePickerAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -12,5 +13,5 @@ nativeDatePicker = createNativeElement_ datePickerImpl
1213
1314type NativeDatePickerAttributes = BaseAttributes
1415 ( graphical :: Boolean
15− , onChange :: EventHandler
16+ , onChange :: String -> Effect Unit
1617 )
src/Yoga/React/Native/MacOS/DropZone.js+21−1
@@ -1,2 +1,22 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const dropZoneImpl = requireNativeComponent("MacOSDropZone");
3+const NativeDropZone = requireNativeComponent("MacOSDropZone");
4+export const dropZoneImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onFileDrop === "function") {
7+ nativeProps.onFileDrop = (e) => {
8+ const data = {
9+ files: e.nativeEvent.files || [],
10+ strings: e.nativeEvent.strings || [],
11+ };
12+ props.onFileDrop(data)();
13+ };
14+ }
15+ if (typeof props.onFilesDragEnter === "function") {
16+ nativeProps.onFilesDragEnter = () => props.onFilesDragEnter();
17+ }
18+ if (typeof props.onFilesDragExit === "function") {
19+ nativeProps.onFilesDragExit = () => props.onFilesDragExit();
20+ }
21+ return React.createElement(NativeDropZone, { ...nativeProps, ref });
22+});
src/Yoga/React/Native/MacOS/DropZone.purs+11−5
@@ -1,7 +1,8 @@
1−module Yoga.React.Native.MacOS.DropZone (nativeDropZone, NativeDropZoneAttributes) where
1+module Yoga.React.Native.MacOS.DropZone (nativeDropZone, NativeDropZoneAttributes, DroppedData) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
78
@@ -10,8 +11,13 @@ foreign import dropZoneImpl :: forall props. ReactComponent props
1011nativeDropZone :: FFINativeComponent NativeDropZoneAttributes
1112nativeDropZone = createNativeElement dropZoneImpl
1213
14+type DroppedData =
15+ { files :: Array { path :: String, name :: String }
16+ , strings :: Array String
17+ }
18+
1319type NativeDropZoneAttributes = BaseAttributes
14− ( onFileDrop :: EventHandler
15− , onFilesDragEnter :: EventHandler
16− , onFilesDragExit :: EventHandler
20+ ( onFileDrop :: DroppedData -> Effect Unit
21+ , onFilesDragEnter :: Effect Unit
22+ , onFilesDragExit :: Effect Unit
1723 )
src/Yoga/React/Native/MacOS/FilePicker.js+13−1
@@ -1,2 +1,14 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const filePickerImpl = requireNativeComponent("MacOSFilePicker");
3+const NativeFilePicker = requireNativeComponent("MacOSFilePicker");
4+export const filePickerImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onPickFiles === "function") {
7+ nativeProps.onPickFiles = (e) =>
8+ props.onPickFiles(e.nativeEvent.files || [])();
9+ }
10+ if (typeof props.onCancel === "function") {
11+ nativeProps.onCancel = () => props.onCancel();
12+ }
13+ return React.createElement(NativeFilePicker, { ...nativeProps, ref });
14+});
src/Yoga/React/Native/MacOS/FilePicker.purs+10−4
@@ -1,7 +1,8 @@
1−module Yoga.React.Native.MacOS.FilePicker (nativeFilePicker, NativeFilePickerAttributes) where
1+module Yoga.React.Native.MacOS.FilePicker (nativeFilePicker, NativeFilePickerAttributes, PickedFile) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78import Yoga.React.Native.MacOS.Types (FilePickerMode)
@@ -11,6 +12,11 @@ foreign import filePickerImpl :: forall props. ReactComponent props
1112nativeFilePicker :: FFINativeComponent_ NativeFilePickerAttributes
1213nativeFilePicker = createNativeElement_ filePickerImpl
1314
15+type PickedFile =
16+ { path :: String
17+ , name :: String
18+ }
19+
1420type NativeFilePickerAttributes = BaseAttributes
1521 ( mode :: FilePickerMode
1622 , title :: String
@@ -20,6 +26,6 @@ type NativeFilePickerAttributes = BaseAttributes
2026 , allowedTypes :: Array String
2127 , allowMultiple :: Boolean
2228 , canChooseDirectories :: Boolean
23− , onPickFiles :: EventHandler
24− , onCancel :: EventHandler
29+ , onPickFiles :: Array PickedFile -> Effect Unit
30+ , onCancel :: Effect Unit
2531 )
src/Yoga/React/Native/MacOS/HelpButton.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const helpButtonImpl = requireNativeComponent("MacOSHelpButton");
3+const NativeHelpButton = requireNativeComponent("MacOSHelpButton");
4+export const helpButtonImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onPress === "function") {
7+ nativeProps.onPress = () => props.onPress();
8+ }
9+ return React.createElement(NativeHelpButton, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/HelpButton.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.HelpButton
33 , NativeHelpButtonAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -14,5 +15,5 @@ nativeHelpButton :: FFINativeComponent_ NativeHelpButtonAttributes
1415nativeHelpButton = createNativeElement_ helpButtonImpl
1516
1617type NativeHelpButtonAttributes = BaseAttributes
17− ( onPress :: EventHandler
18+ ( onPress :: Effect Unit
1819 )
src/Yoga/React/Native/MacOS/MapView.js+21−1
@@ -1,2 +1,22 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const mapViewImpl = requireNativeComponent("MacOSMapView");
3+const NativeMapView = requireNativeComponent("MacOSMapView");
4+export const mapViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onRegionChange === "function") {
7+ nativeProps.onRegionChange = (e) => {
8+ const r = e.nativeEvent;
9+ props.onRegionChange({
10+ latitude: r.latitude ?? 0,
11+ longitude: r.longitude ?? 0,
12+ latitudeDelta: r.latitudeDelta ?? 0,
13+ longitudeDelta: r.longitudeDelta ?? 0,
14+ })();
15+ };
16+ }
17+ if (typeof props.onSelectAnnotation === "function") {
18+ nativeProps.onSelectAnnotation = (e) =>
19+ props.onSelectAnnotation(e.nativeEvent.title || "")();
20+ }
21+ return React.createElement(NativeMapView, { ...nativeProps, ref });
22+});
src/Yoga/React/Native/MacOS/MapView.purs+12−3
@@ -2,10 +2,12 @@ module Yoga.React.Native.MacOS.MapView
22 ( nativeMapView
33 , NativeMapViewAttributes
44 , MapAnnotation
5+ , MapRegion
56 ) where
67
8+import Prelude
9+import Effect (Effect)
710import React.Basic (ReactComponent)
8−import React.Basic.Events (EventHandler)
911import Yoga.React.Native.Attributes (BaseAttributes)
1012import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1113import Yoga.React.Native.MacOS.Types (MapType)
@@ -22,6 +24,13 @@ type MapAnnotation =
2224 , subtitle :: String
2325 }
2426
27+type MapRegion =
28+ { latitude :: Number
29+ , longitude :: Number
30+ , latitudeDelta :: Number
31+ , longitudeDelta :: Number
32+ }
33+
2534type NativeMapViewAttributes = BaseAttributes
2635 ( latitude :: Number
2736 , longitude :: Number
@@ -30,6 +39,6 @@ type NativeMapViewAttributes = BaseAttributes
3039 , mapType :: MapType
3140 , showsUserLocation :: Boolean
3241 , annotations :: Array MapAnnotation
33− , onRegionChange :: EventHandler
34− , onSelectAnnotation :: EventHandler
42+ , onRegionChange :: MapRegion -> Effect Unit
43+ , onSelectAnnotation :: String -> Effect Unit
3544 )
src/Yoga/React/Native/MacOS/Menu.js+1−1
@@ -1,6 +1,6 @@
11import { NativeModules, Platform } from "react-native";
22
3−export const showMenuImpl = (items, callback) => {
3+export const showMenuImpl = ({ items, onSelectItem: callback }) => {
44 if (Platform.OS !== "macos") return;
55 const mod = NativeModules.MacOSMenuModule;
66 if (mod && mod.show) {
src/Yoga/React/Native/MacOS/Menu.purs+10−4
@@ -1,19 +1,25 @@
11module Yoga.React.Native.MacOS.Menu
22 ( macosShowMenu
33 , MenuItem
4+ , MenuProps
45 ) where
56
67import Prelude
78
89import Effect (Effect)
9−import Effect.Uncurried (EffectFn2, runEffectFn2)
10+import Effect.Uncurried (EffectFn1, runEffectFn1)
1011
1112type MenuItem =
1213 { title :: String
1314 , id :: String
1415 }
1516
16−foreign import showMenuImpl :: EffectFn2 (Array MenuItem) (String -> Effect Unit) Unit
17+type MenuProps =
18+ { items :: Array MenuItem
19+ , onSelectItem :: String -> Effect Unit
20+ }
21+
22+foreign import showMenuImpl :: EffectFn1 MenuProps Unit
1723
18−macosShowMenu :: Array MenuItem -> (String -> Effect Unit) -> Effect Unit
19−macosShowMenu = runEffectFn2 showMenuImpl
24+macosShowMenu :: MenuProps -> Effect Unit
25+macosShowMenu = runEffectFn1 showMenuImpl
src/Yoga/React/Native/MacOS/OutlineView.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const outlineViewImpl = requireNativeComponent("MacOSOutlineView");
3+const NativeOutlineView = requireNativeComponent("MacOSOutlineView");
4+export const outlineViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectItem === "function") {
7+ nativeProps.onSelectItem = (e) => props.onSelectItem(e.nativeEvent.id)();
8+ }
9+ return React.createElement(NativeOutlineView, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/OutlineView.purs+3−2
@@ -4,8 +4,9 @@ module Yoga.React.Native.MacOS.OutlineView
44 , OutlineItem(..)
55 ) where
66
7+import Prelude
8+import Effect (Effect)
79import React.Basic (ReactComponent)
8−import React.Basic.Events (EventHandler)
910import Yoga.React.Native.Attributes (BaseAttributes)
1011import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1112
@@ -24,5 +25,5 @@ newtype OutlineItem = OutlineItem
2425type NativeOutlineViewAttributes = BaseAttributes
2526 ( items :: Array OutlineItem
2627 , headerVisible :: Boolean
27− , onSelectItem :: EventHandler
28+ , onSelectItem :: String -> Effect Unit
2829 )
src/Yoga/React/Native/MacOS/PDFView.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const pdfViewImpl = requireNativeComponent("MacOSPDFView");
3+const NativePDFView = requireNativeComponent("MacOSPDFView");
4+export const pdfViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onPageChange === "function") {
7+ nativeProps.onPageChange = (e) =>
8+ props.onPageChange(e.nativeEvent.pageIndex | 0)();
9+ }
10+ return React.createElement(NativePDFView, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/PDFView.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.PDFView
33 , NativePDFViewAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011import Yoga.React.Native.MacOS.Types (PDFDisplayMode)
@@ -18,5 +19,5 @@ type NativePDFViewAttributes = BaseAttributes
1819 ( source :: String
1920 , autoScales :: Boolean
2021 , displayMode :: PDFDisplayMode
21− , onPageChange :: EventHandler
22+ , onPageChange :: Int -> Effect Unit
2223 )
src/Yoga/React/Native/MacOS/PathControl.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const pathControlImpl = requireNativeComponent("MacOSPathControl");
3+const NativePathControl = requireNativeComponent("MacOSPathControl");
4+export const pathControlImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectPath === "function") {
7+ nativeProps.onSelectPath = (e) => props.onSelectPath(e.nativeEvent.url)();
8+ }
9+ return React.createElement(NativePathControl, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/PathControl.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.PathControl
33 , NativePathControlAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011import Yoga.React.Native.MacOS.Types (PathControlStyle)
@@ -17,5 +18,5 @@ nativePathControl = createNativeElement_ pathControlImpl
1718type NativePathControlAttributes = BaseAttributes
1819 ( url :: String
1920 , pathStyle :: PathControlStyle
20− , onSelectPath :: EventHandler
21+ , onSelectPath :: String -> Effect Unit
2122 )
src/Yoga/React/Native/MacOS/PopUp.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const popUpImpl = requireNativeComponent("NativePopUp");
3+const NativePopUp = requireNativeComponent("NativePopUp");
4+export const popUpImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) =>
8+ props.onChange(e.nativeEvent.selectedIndex | 0)();
9+ }
10+ return React.createElement(NativePopUp, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/PopUp.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.PopUp (nativePopUp, NativePopUpAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -13,5 +14,5 @@ nativePopUp = createNativeElement_ popUpImpl
1314type NativePopUpAttributes = BaseAttributes
1415 ( items :: Array String
1516 , selectedIndex :: Int
16− , onChange :: EventHandler
17+ , onChange :: Int -> Effect Unit
1718 )
src/Yoga/React/Native/MacOS/Popover.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const popoverImpl = requireNativeComponent("MacOSPopover");
3+const NativePopover = requireNativeComponent("MacOSPopover");
4+export const popoverImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onClose === "function") {
7+ nativeProps.onClose = () => props.onClose();
8+ }
9+ return React.createElement(NativePopover, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/Popover.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.Popover
33 , NativePopoverAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
1011import Yoga.React.Native.MacOS.Types (PopoverEdge, PopoverBehavior)
@@ -18,5 +19,5 @@ type NativePopoverAttributes = BaseAttributes
1819 ( visible :: Boolean
1920 , preferredEdge :: PopoverEdge
2021 , behavior :: PopoverBehavior
21− , onClose :: EventHandler
22+ , onClose :: Effect Unit
2223 )
src/Yoga/React/Native/MacOS/RadioButton.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const radioButtonImpl = requireNativeComponent("MacOSRadioButton");
3+const NativeRadioButton = requireNativeComponent("MacOSRadioButton");
4+export const radioButtonImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) => props.onChange(!!e.nativeEvent.selected)();
8+ }
9+ return React.createElement(NativeRadioButton, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/RadioButton.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.RadioButton
33 , NativeRadioButtonAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -17,5 +18,5 @@ type NativeRadioButtonAttributes = BaseAttributes
1718 ( selected :: Boolean
1819 , title :: String
1920 , enabled :: Boolean
20− , onChange :: EventHandler
21+ , onChange :: Boolean -> Effect Unit
2122 )
src/Yoga/React/Native/MacOS/SearchField.js+12−1
@@ -1,2 +1,13 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const searchFieldImpl = requireNativeComponent("MacOSSearchField");
3+const NativeSearchField = requireNativeComponent("MacOSSearchField");
4+export const searchFieldImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChangeText === "function") {
7+ nativeProps.onChangeText = (e) => props.onChangeText(e.nativeEvent.text)();
8+ }
9+ if (typeof props.onSearch === "function") {
10+ nativeProps.onSearch = (e) => props.onSearch(e.nativeEvent.text)();
11+ }
12+ return React.createElement(NativeSearchField, { ...nativeProps, ref });
13+});
src/Yoga/React/Native/MacOS/SearchField.purs+4−3
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.SearchField
33 , NativeSearchFieldAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -16,6 +17,6 @@ nativeSearchField = createNativeElement_ searchFieldImpl
1617type NativeSearchFieldAttributes = BaseAttributes
1718 ( text :: String
1819 , placeholder :: String
19− , onChangeText :: EventHandler
20− , onSearch :: EventHandler
20+ , onChangeText :: String -> Effect Unit
21+ , onSearch :: String -> Effect Unit
2122 )
src/Yoga/React/Native/MacOS/Segmented.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const segmentedImpl = requireNativeComponent("NativeSegmented");
3+const NativeSegmented = requireNativeComponent("NativeSegmented");
4+export const segmentedImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) =>
8+ props.onChange(e.nativeEvent.selectedIndex | 0)();
9+ }
10+ return React.createElement(NativeSegmented, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/Segmented.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.Segmented (nativeSegmented, NativeSegmentedAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -14,5 +15,5 @@ type NativeSegmentedAttributes = BaseAttributes
1415 ( labels :: Array String
1516 , sfSymbols :: Array String
1617 , selectedIndex :: Int
17− , onChange :: EventHandler
18+ , onChange :: Int -> Effect Unit
1819 )
src/Yoga/React/Native/MacOS/Sheet.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const sheetImpl = requireNativeComponent("MacOSSheet");
3+const NativeSheet = requireNativeComponent("MacOSSheet");
4+export const sheetImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onDismiss === "function") {
7+ nativeProps.onDismiss = () => props.onDismiss();
8+ }
9+ return React.createElement(NativeSheet, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/Sheet.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.Sheet
33 , NativeSheetAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
1011
@@ -15,5 +16,5 @@ nativeSheet = createNativeElement sheetImpl
1516
1617type NativeSheetAttributes = BaseAttributes
1718 ( visible :: Boolean
18− , onDismiss :: EventHandler
19+ , onDismiss :: Effect Unit
1920 )
src/Yoga/React/Native/MacOS/Slider.js+11−1
@@ -1,2 +1,12 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const sliderImpl = requireNativeComponent("NativeSlider");
3+
4+const NativeSlider = requireNativeComponent("NativeSlider");
5+
6+export const sliderImpl = React.forwardRef((props, ref) => {
7+ const nativeProps = { ...props };
8+ if (typeof props.onChange === "function") {
9+ nativeProps.onChange = (e) => props.onChange(e.nativeEvent.value ?? 0)();
10+ }
11+ return React.createElement(NativeSlider, { ...nativeProps, ref });
12+});
src/Yoga/React/Native/MacOS/Slider.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.Slider (nativeSlider, NativeSliderAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -16,5 +17,5 @@ type NativeSliderAttributes = BaseAttributes
1617 , maxValue :: Number
1718 , numberOfTickMarks :: Int
1819 , allowsTickMarkValuesOnly :: Boolean
19− , onChange :: EventHandler
20+ , onChange :: Number -> Effect Unit
2021 )
src/Yoga/React/Native/MacOS/Stepper.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const stepperImpl = requireNativeComponent("MacOSStepper");
3+const NativeStepper = requireNativeComponent("MacOSStepper");
4+export const stepperImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChange === "function") {
7+ nativeProps.onChange = (e) => props.onChange(e.nativeEvent.value ?? 0)();
8+ }
9+ return React.createElement(NativeStepper, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/Stepper.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.Stepper
33 , NativeStepperAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -18,5 +19,5 @@ type NativeStepperAttributes = BaseAttributes
1819 , minValue :: Number
1920 , maxValue :: Number
2021 , increment :: Number
21− , onChange :: EventHandler
22+ , onChange :: Number -> Effect Unit
2223 )
src/Yoga/React/Native/MacOS/Switch.js+11−1
@@ -1,2 +1,12 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const switchImpl = requireNativeComponent("NativeSwitch");
3+
4+const NativeSwitch = requireNativeComponent("NativeSwitch");
5+
6+export const switchImpl = React.forwardRef((props, ref) => {
7+ const nativeProps = { ...props };
8+ if (typeof props.onChange === "function") {
9+ nativeProps.onChange = (e) => props.onChange(!!e.nativeEvent.on)();
10+ }
11+ return React.createElement(NativeSwitch, { ...nativeProps, ref });
12+});
src/Yoga/React/Native/MacOS/Switch.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.Switch (nativeSwitch, NativeSwitchAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -12,5 +13,5 @@ nativeSwitch = createNativeElement_ switchImpl
1213
1314type NativeSwitchAttributes = BaseAttributes
1415 ( on :: Boolean
15− , onChange :: EventHandler
16+ , onChange :: Boolean -> Effect Unit
1617 )
src/Yoga/React/Native/MacOS/TabView.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const tabViewImpl = requireNativeComponent("MacOSTabView");
3+const NativeTabView = requireNativeComponent("MacOSTabView");
4+export const tabViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectTab === "function") {
7+ nativeProps.onSelectTab = (e) => props.onSelectTab(e.nativeEvent.tabId)();
8+ }
9+ return React.createElement(NativeTabView, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/TabView.purs+3−2
@@ -4,8 +4,9 @@ module Yoga.React.Native.MacOS.TabView
44 , TabItem
55 ) where
66
7+import Prelude
8+import Effect (Effect)
79import React.Basic (ReactComponent)
8−import React.Basic.Events (EventHandler)
910import Yoga.React.Native.Attributes (BaseAttributes)
1011import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1112
@@ -22,5 +23,5 @@ type TabItem =
2223type NativeTabViewAttributes = BaseAttributes
2324 ( items :: Array TabItem
2425 , selectedItem :: String
25− , onSelectTab :: EventHandler
26+ , onSelectTab :: String -> Effect Unit
2627 )
src/Yoga/React/Native/MacOS/TableView.js+14−1
@@ -1,2 +1,15 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const tableViewImpl = requireNativeComponent("MacOSTableView");
3+const NativeTableView = requireNativeComponent("MacOSTableView");
4+export const tableViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectRow === "function") {
7+ nativeProps.onSelectRow = (e) =>
8+ props.onSelectRow(e.nativeEvent.rowIndex | 0)();
9+ }
10+ if (typeof props.onDoubleClickRow === "function") {
11+ nativeProps.onDoubleClickRow = (e) =>
12+ props.onDoubleClickRow(e.nativeEvent.rowIndex | 0)();
13+ }
14+ return React.createElement(NativeTableView, { ...nativeProps, ref });
15+});
src/Yoga/React/Native/MacOS/TableView.purs+4−3
@@ -4,8 +4,9 @@ module Yoga.React.Native.MacOS.TableView
44 , TableColumn
55 ) where
66
7+import Prelude
8+import Effect (Effect)
79import React.Basic (ReactComponent)
8−import React.Basic.Events (EventHandler)
910import Yoga.React.Native.Attributes (BaseAttributes)
1011import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1112
@@ -25,6 +26,6 @@ type NativeTableViewAttributes = BaseAttributes
2526 , rows :: Array (Array String)
2627 , headerVisible :: Boolean
2728 , alternatingRows :: Boolean
28− , onSelectRow :: EventHandler
29− , onDoubleClickRow :: EventHandler
29+ , onSelectRow :: Int -> Effect Unit
30+ , onDoubleClickRow :: Int -> Effect Unit
3031 )
src/Yoga/React/Native/MacOS/TextEditor.js+9−1
@@ -1,2 +1,10 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const textEditorImpl = requireNativeComponent("NativeTextEditor");
3+const NativeTextEditor = requireNativeComponent("NativeTextEditor");
4+export const textEditorImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChangeText === "function") {
7+ nativeProps.onChangeText = (e) => props.onChangeText(e.nativeEvent.text)();
8+ }
9+ return React.createElement(NativeTextEditor, { ...nativeProps, ref });
10+});
src/Yoga/React/Native/MacOS/TextEditor.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.TextEditor (nativeTextEditor, NativeTextEditorAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -14,5 +15,5 @@ type NativeTextEditorAttributes = BaseAttributes
1415 ( text :: String
1516 , richText :: Boolean
1617 , showsRuler :: Boolean
17− , onChangeText :: EventHandler
18+ , onChangeText :: String -> Effect Unit
1819 )
src/Yoga/React/Native/MacOS/TextField.js+14−1
@@ -1,2 +1,15 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const textFieldImpl = requireNativeComponent("NativeTextField");
3+
4+const NativeTextField = requireNativeComponent("NativeTextField");
5+
6+export const textFieldImpl = React.forwardRef((props, ref) => {
7+ const nativeProps = { ...props };
8+ if (typeof props.onChangeText === "function") {
9+ nativeProps.onChangeText = (e) => props.onChangeText(e.nativeEvent.text)();
10+ }
11+ if (typeof props.onSubmit === "function") {
12+ nativeProps.onSubmit = (e) => props.onSubmit(e.nativeEvent.text)();
13+ }
14+ return React.createElement(NativeTextField, { ...nativeProps, ref });
15+});
src/Yoga/React/Native/MacOS/TextField.purs+4−3
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.TextField (nativeTextField, NativeTextFieldAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -16,6 +17,6 @@ type NativeTextFieldAttributes = BaseAttributes
1617 , secure :: Boolean
1718 , search :: Boolean
1819 , rounded :: Boolean
19− , onChangeText :: EventHandler
20− , onSubmit :: EventHandler
20+ , onChangeText :: String -> Effect Unit
21+ , onSubmit :: String -> Effect Unit
2122 )
src/Yoga/React/Native/MacOS/TokenField.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const tokenFieldImpl = requireNativeComponent("MacOSTokenField");
3+const NativeTokenField = requireNativeComponent("MacOSTokenField");
4+export const tokenFieldImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onChangeTokens === "function") {
7+ nativeProps.onChangeTokens = (e) =>
8+ props.onChangeTokens(e.nativeEvent.tokens || [])();
9+ }
10+ return React.createElement(NativeTokenField, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/TokenField.purs+3−2
@@ -3,8 +3,9 @@ module Yoga.React.Native.MacOS.TokenField
33 , NativeTokenFieldAttributes
44 ) where
55
6+import Prelude
7+import Effect (Effect)
68import React.Basic (ReactComponent)
7−import React.Basic.Events (EventHandler)
89import Yoga.React.Native.Attributes (BaseAttributes)
910import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
1011
@@ -16,5 +17,5 @@ nativeTokenField = createNativeElement_ tokenFieldImpl
1617type NativeTokenFieldAttributes = BaseAttributes
1718 ( tokens :: Array String
1819 , placeholder :: String
19− , onChangeTokens :: EventHandler
20+ , onChangeTokens :: Array String -> Effect Unit
2021 )
src/Yoga/React/Native/MacOS/Toolbar.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const toolbarImpl = requireNativeComponent("MacOSToolbar");
3+const NativeToolbar = requireNativeComponent("MacOSToolbar");
4+export const toolbarImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onSelectItem === "function") {
7+ nativeProps.onSelectItem = (e) =>
8+ props.onSelectItem(e.nativeEvent.itemId)();
9+ }
10+ return React.createElement(NativeToolbar, { ...nativeProps, ref });
11+});
src/Yoga/React/Native/MacOS/Toolbar.purs+3−2
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.Toolbar (nativeToolbar, NativeToolbarAttributes, ToolbarItem) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78import Yoga.React.Native.MacOS.Types (ToolbarStyle)
@@ -22,5 +23,5 @@ type NativeToolbarAttributes = BaseAttributes
2223 , selectedItem :: String
2324 , toolbarStyle :: ToolbarStyle
2425 , windowTitle :: String
25− , onSelectItem :: EventHandler
26+ , onSelectItem :: String -> Effect Unit
2627 )
src/Yoga/React/Native/MacOS/UserNotification.js+1−1
@@ -1,6 +1,6 @@
11import { NativeModules, Platform } from "react-native";
22
3−export const notifyImpl = (title, body) => {
3+export const notifyImpl = ({ title = "", body = "" }) => {
44 if (Platform.OS !== "macos") return;
55 const mod = NativeModules.MacOSNotificationModule;
66 if (mod && mod.notify) {
src/Yoga/React/Native/MacOS/UserNotification.purs+16−4
@@ -1,13 +1,25 @@
11module Yoga.React.Native.MacOS.UserNotification
22 ( macosNotify
3+ , NotifyProps
34 ) where
45
56import Prelude
67
78import Effect (Effect)
8−import Effect.Uncurried (EffectFn2, runEffectFn2)
9+import Effect.Uncurried (EffectFn1, runEffectFn1)
10+import Prim.Row (class Union)
11+import Unsafe.Coerce (unsafeCoerce)
912
10−foreign import notifyImpl :: EffectFn2 String String Unit
13+type NotifyProps =
14+ ( title :: String
15+ , body :: String
16+ )
1117
12−macosNotify :: String -> String -> Effect Unit
13−macosNotify = runEffectFn2 notifyImpl
18+foreign import notifyImpl :: EffectFn1 (Record NotifyProps) Unit
19+
20+macosNotify
21+ :: forall given missing
22+ . Union given missing NotifyProps
23+ => { | given }
24+ -> Effect Unit
25+macosNotify r = runEffectFn1 notifyImpl (unsafeCoerce r)
src/Yoga/React/Native/MacOS/WebView.js+12−1
@@ -1,2 +1,13 @@
1+import React from "react";
12import { requireNativeComponent } from "react-native";
2−export const webViewImpl = requireNativeComponent("NativeWebView");
3+const NativeWebView = requireNativeComponent("NativeWebView");
4+export const webViewImpl = React.forwardRef((props, ref) => {
5+ const nativeProps = { ...props };
6+ if (typeof props.onNavigate === "function") {
7+ nativeProps.onNavigate = (e) => props.onNavigate(e.nativeEvent.url)();
8+ }
9+ if (typeof props.onFinishLoad === "function") {
10+ nativeProps.onFinishLoad = (e) => props.onFinishLoad(e.nativeEvent.url)();
11+ }
12+ return React.createElement(NativeWebView, { ...nativeProps, ref });
13+});
src/Yoga/React/Native/MacOS/WebView.purs+4−3
@@ -1,7 +1,8 @@
11module Yoga.React.Native.MacOS.WebView (nativeWebView, NativeWebViewAttributes) where
22
3+import Prelude
4+import Effect (Effect)
35import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
56import Yoga.React.Native.Attributes (BaseAttributes)
67import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
78
@@ -12,6 +13,6 @@ nativeWebView = createNativeElement_ webViewImpl
1213
1314type NativeWebViewAttributes = BaseAttributes
1415 ( url :: String
15− , onNavigate :: EventHandler
16− , onFinishLoad :: EventHandler
16+ , onNavigate :: String -> Effect Unit
17+ , onFinishLoad :: String -> Effect Unit
1718 )