git.iko.soy/rowtype-yoga/purescript-yoga-react-native
on main help sign in
WIP: React Native bindings development
7082765Mark
docs/src/Docs/Pages/DataViews.purs+5−5
@@ -23,15 +23,15 @@ tableView = L.componentDoc "nativeTableView" "Yoga.React.Native.MacOS.TableView
23 , rows: [ ["file.txt", "4 KB"], ["image.png", "1.2 MB"] ]
23 , rows: [ ["file.txt", "4 KB"], ["image.png", "1.2 MB"] ]
24 , headerVisible: true
24 , headerVisible: true
25 , alternatingRows: true
25 , alternatingRows: true
26− , onSelectRow: E.onInt "rowIndex" setSelected
26+ , onSelectRow: setSelected
27 }"""
27 }"""
28 [ propsTable
28 [ propsTable
29 [ { name: "columns", type_: "Array TableColumn", description: "Column definitions ({ id, title, width })" }
29 [ { name: "columns", type_: "Array TableColumn", description: "Column definitions ({ id, title, width })" }
30 , { name: "rows", type_: "Array (Array String)", description: "Row data as arrays of strings" }
30 , { name: "rows", type_: "Array (Array String)", description: "Row data as arrays of strings" }
31 , { name: "headerVisible", type_: "Boolean", description: "Show column headers" }
31 , { name: "headerVisible", type_: "Boolean", description: "Show column headers" }
32 , { name: "alternatingRows", type_: "Boolean", description: "Alternating row backgrounds" }
32 , { name: "alternatingRows", type_: "Boolean", description: "Alternating row backgrounds" }
33− , { name: "onSelectRow", type_: "EventHandler", description: "Row selection callback" }
33+ , { name: "onSelectRow", type_: "Int -> Effect Unit", description: "Row selection callback" }
34− , { name: "onDoubleClickRow", type_: "EventHandler", description: "Row double-click callback" }
34+ , { name: "onDoubleClickRow", type_: "Int -> Effect Unit", description: "Row double-click callback" }
35 ]
35 ]
36 ]
36 ]
37
37
@@ -50,11 +50,11 @@ outlineView = L.componentDoc "nativeOutlineView" "Yoga.React.Native.MacOS.Outlin
50 }
50 }
51 ]
51 ]
52 , headerVisible: true
52 , headerVisible: true
53− , onSelectItem: E.onString "id" setSelected
53+ , onSelectItem: setSelected
54 }"""
54 }"""
55 [ propsTable
55 [ propsTable
56 [ { name: "items", type_: "Array OutlineItem", description: "Hierarchical tree data (newtype with { id, title, sfSymbol, children })" }
56 [ { name: "items", type_: "Array OutlineItem", description: "Hierarchical tree data (newtype with { id, title, sfSymbol, children })" }
57 , { name: "headerVisible", type_: "Boolean", description: "Show header" }
57 , { name: "headerVisible", type_: "Boolean", description: "Show header" }
58− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
58+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
59 ]
59 ]
60 ]
60 ]
docs/src/Docs/Pages/Display.purs+2−2
@@ -111,11 +111,11 @@ pathControl = L.componentDoc "nativePathControl" "Yoga.React.Native.MacOS.PathCo
111 """nativePathControl
111 """nativePathControl
112 { url: "/Users/you/Documents"
112 { url: "/Users/you/Documents"
113 , pathStyle: T.standard
113 , pathStyle: T.standard
114− , onSelectPath: E.onString "url" setPath
114+ , onSelectPath: setPath
115 }"""
115 }"""
116 [ propsTable
116 [ propsTable
117 [ { name: "url", type_: "String", description: "File path URL to display" }
117 [ { name: "url", type_: "String", description: "File path URL to display" }
118 , { name: "pathStyle", type_: "PathControlStyle", description: "Visual style of the path control" }
118 , { 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" }
120 ]
120 ]
121 ]
121 ]
docs/src/Docs/Pages/FilesAndDragDrop.purs+12−12
@@ -17,18 +17,18 @@ page =
17filePicker :: Nut
17filePicker :: Nut
18filePicker = L.componentDoc "nativeFilePicker" "Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)"
18filePicker = L.componentDoc "nativeFilePicker" "Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)"
19 """nativeFilePicker
19 """nativeFilePicker
20− { mode: T.open
20+ { mode: T.openFile
21 , title: "Choose files"
21 , title: "Choose files"
22 , sfSymbol: "doc.badge.plus"
22 , sfSymbol: "doc.badge.plus"
23 , message: "Select one or more files"
23 , message: "Select one or more files"
24 , allowedTypes: ["pdf", "txt", "png"]
24 , allowedTypes: ["pdf", "txt", "png"]
25 , allowMultiple: true
25 , allowMultiple: true
26 , canChooseDirectories: false
26 , canChooseDirectories: false
27− , onPickFiles: E.onStrings "files" setFiles
27+ , onPickFiles: \files -> setFiles (map _.path files)
28− , onCancel: handler_ (pure unit)
28+ , onCancel: pure unit
29 }"""
29 }"""
30 [ propsTable
30 [ propsTable
31− [ { name: "mode", type_: "FilePickerMode", description: "open or save" }
31+ [ { name: "mode", type_: "FilePickerMode", description: "openFile or saveFile" }
32 , { name: "title", type_: "String", description: "Dialog title" }
32 , { name: "title", type_: "String", description: "Dialog title" }
33 , { name: "sfSymbol", type_: "String", description: "SF Symbol icon for the button" }
33 , { name: "sfSymbol", type_: "String", description: "SF Symbol icon for the button" }
34 , { name: "message", type_: "String", description: "Dialog message" }
34 , { name: "message", type_: "String", description: "Dialog message" }
@@ -36,8 +36,8 @@ filePicker = L.componentDoc "nativeFilePicker" "Yoga.React.Native.MacOS.FilePick
36 , { name: "allowedTypes", type_: "Array String", description: "Allowed file extensions" }
36 , { name: "allowedTypes", type_: "Array String", description: "Allowed file extensions" }
37 , { name: "allowMultiple", type_: "Boolean", description: "Allow selecting multiple files" }
37 , { name: "allowMultiple", type_: "Boolean", description: "Allow selecting multiple files" }
38 , { name: "canChooseDirectories", type_: "Boolean", description: "Allow choosing directories" }
38 , { name: "canChooseDirectories", type_: "Boolean", description: "Allow choosing directories" }
39− , { name: "onPickFiles", type_: "EventHandler", description: "Files selected callback" }
39+ , { name: "onPickFiles", type_: "Array PickedFile -> Effect Unit", description: "Files selected callback ({ path, name })" }
40− , { name: "onCancel", type_: "EventHandler", description: "Cancel callback" }
40+ , { name: "onCancel", type_: "Effect Unit", description: "Cancel callback" }
41 ]
41 ]
42 ]
42 ]
43
43
@@ -45,15 +45,15 @@ dropZone :: Nut
45dropZone = L.componentDoc "nativeDropZone" "Yoga.React.Native.MacOS.DropZone (nativeDropZone)"
45dropZone = L.componentDoc "nativeDropZone" "Yoga.React.Native.MacOS.DropZone (nativeDropZone)"
46 """-- FFINativeComponent: takes props then children
46 """-- FFINativeComponent: takes props then children
47nativeDropZone
47nativeDropZone
48− { onFileDrop: E.onStrings "files" setFiles
48+ { onFileDrop: \dropped -> setFiles dropped.files
49− , onFilesDragEnter: handler_ setDragActive
49+ , onFilesDragEnter: setDragActive
50− , onFilesDragExit: handler_ clearDragActive
50+ , onFilesDragExit: clearDragActive
51 }
51 }
52 [ dropTargetContent ]"""
52 [ dropTargetContent ]"""
53 [ propsTable
53 [ propsTable
54− [ { name: "onFileDrop", type_: "EventHandler", description: "Drop callback with file paths" }
54+ [ { name: "onFileDrop", type_: "DroppedData -> Effect Unit", description: "Drop callback ({ files, strings })" }
55− , { name: "onFilesDragEnter", type_: "EventHandler", description: "Drag enter callback" }
55+ , { name: "onFilesDragEnter", type_: "Effect Unit", description: "Drag enter callback" }
56− , { name: "onFilesDragExit", type_: "EventHandler", description: "Drag exit callback" }
56+ , { name: "onFilesDragExit", type_: "Effect Unit", description: "Drag exit callback" }
57 ]
57 ]
58 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
58 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
59 [ D.text_ "The drop target content is passed as the second argument (IsJSX)." ]
59 [ D.text_ "The drop target content is passed as the second argument (IsJSX)." ]
docs/src/Docs/Pages/InputControls.purs+28−28
@@ -47,11 +47,11 @@ switch :: Nut
47switch = L.componentDoc "nativeSwitch" "Yoga.React.Native.MacOS.Switch (nativeSwitch)"
47switch = L.componentDoc "nativeSwitch" "Yoga.React.Native.MacOS.Switch (nativeSwitch)"
48 """nativeSwitch
48 """nativeSwitch
49 { on: true
49 { on: true
50− , onChange: E.onBool "on" setOn
50+ , onChange: setOn
51 }"""
51 }"""
52 [ propsTable
52 [ propsTable
53 [ { name: "on", type_: "Boolean", description: "Current on/off state" }
53 [ { name: "on", type_: "Boolean", description: "Current on/off state" }
54− , { name: "onChange", type_: "EventHandler", description: "Toggle callback" }
54+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Toggle callback" }
55 ]
55 ]
56 ]
56 ]
57
57
@@ -61,7 +61,7 @@ slider = L.componentDoc "nativeSlider" "Yoga.React.Native.MacOS.Slider (nativeSl
61 { value: 50.0
61 { value: 50.0
62 , minValue: 0.0
62 , minValue: 0.0
63 , maxValue: 100.0
63 , maxValue: 100.0
64− , onChange: E.onNumber "value" setValue
64+ , onChange: setValue
65 }"""
65 }"""
66 [ propsTable
66 [ propsTable
67 [ { name: "value", type_: "Number", description: "Current value" }
67 [ { name: "value", type_: "Number", description: "Current value" }
@@ -69,7 +69,7 @@ slider = L.componentDoc "nativeSlider" "Yoga.React.Native.MacOS.Slider (nativeSl
69 , { name: "maxValue", type_: "Number", description: "Range maximum" }
69 , { name: "maxValue", type_: "Number", description: "Range maximum" }
70 , { name: "numberOfTickMarks", type_: "Int", description: "Number of tick marks" }
70 , { name: "numberOfTickMarks", type_: "Int", description: "Number of tick marks" }
71 , { name: "allowsTickMarkValuesOnly", type_: "Boolean", description: "Snap to tick marks only" }
71 , { name: "allowsTickMarkValuesOnly", type_: "Boolean", description: "Snap to tick marks only" }
72− , { name: "onChange", type_: "EventHandler", description: "Value change callback" }
72+ , { name: "onChange", type_: "Number -> Effect Unit", description: "Value change callback" }
73 ]
73 ]
74 ]
74 ]
75
75
@@ -80,14 +80,14 @@ stepper = L.componentDoc "nativeStepper" "Yoga.React.Native.MacOS.Stepper (nativ
80 , minValue: 0.0
80 , minValue: 0.0
81 , maxValue: 10.0
81 , maxValue: 10.0
82 , increment: 1.0
82 , increment: 1.0
83− , onChange: E.onNumber "value" setValue
83+ , onChange: setValue
84 }"""
84 }"""
85 [ propsTable
85 [ propsTable
86 [ { name: "value", type_: "Number", description: "Current value" }
86 [ { name: "value", type_: "Number", description: "Current value" }
87 , { name: "minValue", type_: "Number", description: "Range minimum" }
87 , { name: "minValue", type_: "Number", description: "Range minimum" }
88 , { name: "maxValue", type_: "Number", description: "Range maximum" }
88 , { name: "maxValue", type_: "Number", description: "Range maximum" }
89 , { name: "increment", type_: "Number", description: "Step increment" }
89 , { name: "increment", type_: "Number", description: "Step increment" }
90− , { name: "onChange", type_: "EventHandler", description: "Value change callback" }
90+ , { name: "onChange", type_: "Number -> Effect Unit", description: "Value change callback" }
91 ]
91 ]
92 ]
92 ]
93
93
@@ -96,13 +96,13 @@ checkbox = L.componentDoc "nativeCheckbox" "Yoga.React.Native.MacOS.Checkbox (na
96 """nativeCheckbox
96 """nativeCheckbox
97 { title: "Enable notifications"
97 { title: "Enable notifications"
98 , checked: true
98 , checked: true
99− , onChange: E.onBool "checked" setChecked
99+ , onChange: setChecked
100 }"""
100 }"""
101 [ propsTable
101 [ propsTable
102 [ { name: "title", type_: "String", description: "Label text" }
102 [ { name: "title", type_: "String", description: "Label text" }
103 , { name: "checked", type_: "Boolean", description: "Checked state" }
103 , { name: "checked", type_: "Boolean", description: "Checked state" }
104 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
104 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
105− , { name: "onChange", type_: "EventHandler", description: "Toggle callback" }
105+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Toggle callback" }
106 ]
106 ]
107 ]
107 ]
108
108
@@ -111,13 +111,13 @@ radioButton = L.componentDoc "nativeRadioButton" "Yoga.React.Native.MacOS.RadioB
111 """nativeRadioButton
111 """nativeRadioButton
112 { title: "Option A"
112 { title: "Option A"
113 , selected: true
113 , selected: true
114− , onChange: E.onBool "selected" setSelected
114+ , onChange: \_ -> setChoice "optionA"
115 }"""
115 }"""
116 [ propsTable
116 [ propsTable
117 [ { name: "title", type_: "String", description: "Label text" }
117 [ { name: "title", type_: "String", description: "Label text" }
118 , { name: "selected", type_: "Boolean", description: "Selection state" }
118 , { name: "selected", type_: "Boolean", description: "Selection state" }
119 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
119 , { name: "enabled", type_: "Boolean", description: "Enable/disable" }
120− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
120+ , { name: "onChange", type_: "Boolean -> Effect Unit", description: "Selection callback" }
121 ]
121 ]
122 ]
122 ]
123
123
@@ -127,13 +127,13 @@ segmented = L.componentDoc "nativeSegmented" "Yoga.React.Native.MacOS.Segmented
127 { labels: ["One", "Two", "Three"]
127 { labels: ["One", "Two", "Three"]
128 , sfSymbols: ["1.circle", "2.circle", "3.circle"]
128 , sfSymbols: ["1.circle", "2.circle", "3.circle"]
129 , selectedIndex: 0
129 , selectedIndex: 0
130− , onChange: E.onInt "selectedIndex" setIndex
130+ , onChange: setIndex
131 }"""
131 }"""
132 [ propsTable
132 [ propsTable
133 [ { name: "labels", type_: "Array String", description: "Segment labels" }
133 [ { name: "labels", type_: "Array String", description: "Segment labels" }
134 , { name: "sfSymbols", type_: "Array String", description: "SF Symbol icons per segment" }
134 , { name: "sfSymbols", type_: "Array String", description: "SF Symbol icons per segment" }
135 , { name: "selectedIndex", type_: "Int", description: "Currently selected index" }
135 , { name: "selectedIndex", type_: "Int", description: "Currently selected index" }
136− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
136+ , { name: "onChange", type_: "Int -> Effect Unit", description: "Selection callback" }
137 ]
137 ]
138 ]
138 ]
139
139
@@ -142,12 +142,12 @@ popUp = L.componentDoc "nativePopUp" "Yoga.React.Native.MacOS.PopUp (nativePopUp
142 """nativePopUp
142 """nativePopUp
143 { items: ["Small", "Medium", "Large"]
143 { items: ["Small", "Medium", "Large"]
144 , selectedIndex: 1
144 , selectedIndex: 1
145− , onChange: E.onInt "selectedIndex" setIndex
145+ , onChange: setIndex
146 }"""
146 }"""
147 [ propsTable
147 [ propsTable
148 [ { name: "items", type_: "Array String", description: "Menu items" }
148 [ { name: "items", type_: "Array String", description: "Menu items" }
149 , { name: "selectedIndex", type_: "Int", description: "Selected item index" }
149 , { name: "selectedIndex", type_: "Int", description: "Selected item index" }
150− , { name: "onChange", type_: "EventHandler", description: "Selection callback" }
150+ , { name: "onChange", type_: "Int -> Effect Unit", description: "Selection callback" }
151 ]
151 ]
152 ]
152 ]
153
153
@@ -157,15 +157,15 @@ comboBox = L.componentDoc "nativeComboBox" "Yoga.React.Native.MacOS.ComboBox (na
157 { items: ["Apple", "Banana", "Cherry"]
157 { items: ["Apple", "Banana", "Cherry"]
158 , text: "Apple"
158 , text: "Apple"
159 , placeholder: "Choose a fruit..."
159 , placeholder: "Choose a fruit..."
160− , onChangeText: E.onString "text" setText
160+ , onChangeText: setText
161− , onSelectItem: E.onString "text" setText
161+ , onSelectItem: setText
162 }"""
162 }"""
163 [ propsTable
163 [ propsTable
164 [ { name: "items", type_: "Array String", description: "Autocomplete suggestions" }
164 [ { name: "items", type_: "Array String", description: "Autocomplete suggestions" }
165 , { name: "text", type_: "String", description: "Current text value" }
165 , { name: "text", type_: "String", description: "Current text value" }
166 , { name: "placeholder", type_: "String", description: "Placeholder text" }
166 , { name: "placeholder", type_: "String", description: "Placeholder text" }
167− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
167+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
168− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
168+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
169 ]
169 ]
170 ]
170 ]
171
171
@@ -174,14 +174,14 @@ searchField = L.componentDoc "nativeSearchField" "Yoga.React.Native.MacOS.Search
174 """nativeSearchField
174 """nativeSearchField
175 { placeholder: "Search..."
175 { placeholder: "Search..."
176 , text: ""
176 , text: ""
177− , onChangeText: E.onString "text" setText
177+ , onChangeText: setText
178− , onSearch: E.onString "text" \q -> search q
178+ , onSearch: \q -> search q
179 }"""
179 }"""
180 [ propsTable
180 [ propsTable
181 [ { name: "text", type_: "String", description: "Current search text" }
181 [ { name: "text", type_: "String", description: "Current search text" }
182 , { name: "placeholder", type_: "String", description: "Placeholder text" }
182 , { name: "placeholder", type_: "String", description: "Placeholder text" }
183− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
183+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
184− , { name: "onSearch", type_: "EventHandler", description: "Search submit callback" }
184+ , { name: "onSearch", type_: "String -> Effect Unit", description: "Search submit callback" }
185 ]
185 ]
186 ]
186 ]
187
187
@@ -190,12 +190,12 @@ tokenField = L.componentDoc "nativeTokenField" "Yoga.React.Native.MacOS.TokenFie
190 """nativeTokenField
190 """nativeTokenField
191 { tokens: ["tag1", "tag2"]
191 { tokens: ["tag1", "tag2"]
192 , placeholder: "Add tags..."
192 , placeholder: "Add tags..."
193− , onChangeTokens: E.onStrings "tokens" setTokens
193+ , onChangeTokens: setTokens
194 }"""
194 }"""
195 [ propsTable
195 [ propsTable
196 [ { name: "tokens", type_: "Array String", description: "Current tokens" }
196 [ { name: "tokens", type_: "Array String", description: "Current tokens" }
197 , { name: "placeholder", type_: "String", description: "Placeholder text" }
197 , { name: "placeholder", type_: "String", description: "Placeholder text" }
198− , { name: "onChangeTokens", type_: "EventHandler", description: "Tokens change callback" }
198+ , { name: "onChangeTokens", type_: "Array String -> Effect Unit", description: "Tokens change callback" }
199 ]
199 ]
200 ]
200 ]
201
201
@@ -203,11 +203,11 @@ datePicker :: Nut
203datePicker = L.componentDoc "nativeDatePicker" "Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)"
203datePicker = L.componentDoc "nativeDatePicker" "Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)"
204 """nativeDatePicker
204 """nativeDatePicker
205 { graphical: true
205 { graphical: true
206− , onChange: E.onString "date" setDate
206+ , onChange: setDate
207 }"""
207 }"""
208 [ propsTable
208 [ propsTable
209 [ { name: "graphical", type_: "Boolean", description: "Show graphical calendar picker" }
209 [ { name: "graphical", type_: "Boolean", description: "Show graphical calendar picker" }
210− , { name: "onChange", type_: "EventHandler", description: "Date change callback" }
210+ , { name: "onChange", type_: "String -> Effect Unit", description: "Date change callback" }
211 ]
211 ]
212 ]
212 ]
213
213
@@ -216,12 +216,12 @@ colorWell = L.componentDoc "nativeColorWell" "Yoga.React.Native.MacOS.ColorWell
216 """nativeColorWell
216 """nativeColorWell
217 { color: "#ff0000"
217 { color: "#ff0000"
218 , minimal: true
218 , minimal: true
219− , onChange: E.onString "color" setColor
219+ , onChange: setColor
220 }"""
220 }"""
221 [ propsTable
221 [ propsTable
222 [ { name: "color", type_: "String", description: "Current color hex value" }
222 [ { name: "color", type_: "String", description: "Current color hex value" }
223 , { name: "minimal", type_: "Boolean", description: "Minimal inline style" }
223 , { name: "minimal", type_: "Boolean", description: "Minimal inline style" }
224− , { name: "onChange", type_: "EventHandler", description: "Color change callback" }
224+ , { name: "onChange", type_: "String -> Effect Unit", description: "Color change callback" }
225 ]
225 ]
226 ]
226 ]
227
227
docs/src/Docs/Pages/LayoutPage.purs+4−4
@@ -63,12 +63,12 @@ tabView = L.componentDoc "nativeTabView" "Yoga.React.Native.MacOS.TabView (nativ
63 , { id: "advanced", label: "Advanced" }
63 , { id: "advanced", label: "Advanced" }
64 ]
64 ]
65 , selectedItem: "general"
65 , selectedItem: "general"
66− , onSelectTab: E.onString "tabId" setTab
66+ , onSelectTab: setTab
67 }"""
67 }"""
68 [ propsTable
68 [ propsTable
69 [ { name: "items", type_: "Array TabItem", description: "Tab items ({ id :: String, label :: String })" }
69 [ { name: "items", type_: "Array TabItem", description: "Tab items ({ id :: String, label :: String })" }
70 , { name: "selectedItem", type_: "String", description: "Selected tab id" }
70 , { name: "selectedItem", type_: "String", description: "Selected tab id" }
71− , { name: "onSelectTab", type_: "EventHandler", description: "Tab selection callback" }
71+ , { name: "onSelectTab", type_: "String -> Effect Unit", description: "Tab selection callback" }
72 ]
72 ]
73 ]
73 ]
74
74
@@ -116,14 +116,14 @@ toolbar = L.componentDoc "nativeToolbar" "Yoga.React.Native.MacOS.Toolbar (nativ
116 , selectedItem: "add"
116 , selectedItem: "add"
117 , toolbarStyle: T.unified
117 , toolbarStyle: T.unified
118 , windowTitle: "My App"
118 , windowTitle: "My App"
119− , onSelectItem: E.onString "itemId" setItem
119+ , onSelectItem: setItem
120 }"""
120 }"""
121 [ propsTable
121 [ propsTable
122 [ { name: "items", type_: "Array ToolbarItem", description: "Toolbar items ({ id, label, sfSymbol })" }
122 [ { name: "items", type_: "Array ToolbarItem", description: "Toolbar items ({ id, label, sfSymbol })" }
123 , { name: "selectedItem", type_: "String", description: "Selected item id" }
123 , { name: "selectedItem", type_: "String", description: "Selected item id" }
124 , { name: "toolbarStyle", type_: "ToolbarStyle", description: "Toolbar visual style" }
124 , { name: "toolbarStyle", type_: "ToolbarStyle", description: "Toolbar visual style" }
125 , { name: "windowTitle", type_: "String", description: "Window title" }
125 , { 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" }
127 ]
127 ]
128 ]
128 ]
129
129
docs/src/Docs/Pages/Overlays.purs+2−2
@@ -77,12 +77,12 @@ nativeContextMenu
77 [ { id: "copy", title: "Copy", sfSymbol: "doc.on.doc" }
77 [ { id: "copy", title: "Copy", sfSymbol: "doc.on.doc" }
78 , { id: "paste", title: "Paste", sfSymbol: "doc.on.clipboard" }
78 , { id: "paste", title: "Paste", sfSymbol: "doc.on.clipboard" }
79 ]
79 ]
80− , onSelectItem: E.onString "itemId" setSelected
80+ , onSelectItem: setSelected
81 }
81 }
82 [ rightClickTarget ]"""
82 [ rightClickTarget ]"""
83 [ propsTable
83 [ propsTable
84 [ { name: "items", type_: "Array ContextMenuItem", description: "Menu items ({ id, title, sfSymbol })" }
84 [ { name: "items", type_: "Array ContextMenuItem", description: "Menu items ({ id, title, sfSymbol })" }
85− , { name: "onSelectItem", type_: "EventHandler", description: "Item selection callback" }
85+ , { name: "onSelectItem", type_: "String -> Effect Unit", description: "Item selection callback" }
86 ]
86 ]
87 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
87 , D.p [ DA.klass_ "text-sm text-gray-400 mt-2" ]
88 [ D.text_ "The right-click target element is passed as the second argument (IsJSX)." ]
88 [ D.text_ "The right-click target element is passed as the second argument (IsJSX)." ]
docs/src/Docs/Pages/RichMedia.purs+9−9
@@ -33,7 +33,7 @@ mapView = L.componentDoc "nativeMapView" "Yoga.React.Native.MacOS.MapView (nativ
33 , subtitle: "CA"
33 , subtitle: "CA"
34 }
34 }
35 ]
35 ]
36− , onRegionChange: E.onNumber "latitude" setLat
36+ , onRegionChange: \region -> setLat region.latitude
37 }"""
37 }"""
38 [ propsTable
38 [ propsTable
39 [ { name: "latitude", type_: "Number", description: "Center latitude" }
39 [ { name: "latitude", type_: "Number", description: "Center latitude" }
@@ -43,8 +43,8 @@ mapView = L.componentDoc "nativeMapView" "Yoga.React.Native.MacOS.MapView (nativ
43 , { name: "mapType", type_: "MapType", description: "Map display type" }
43 , { name: "mapType", type_: "MapType", description: "Map display type" }
44 , { name: "showsUserLocation", type_: "Boolean", description: "Show user location dot" }
44 , { name: "showsUserLocation", type_: "Boolean", description: "Show user location dot" }
45 , { name: "annotations", type_: "Array MapAnnotation", description: "Map pins ({ latitude, longitude, title, subtitle })" }
45 , { name: "annotations", type_: "Array MapAnnotation", description: "Map pins ({ latitude, longitude, title, subtitle })" }
46− , { name: "onRegionChange", type_: "EventHandler", description: "Region change callback" }
46+ , { name: "onRegionChange", type_: "MapRegion -> Effect Unit", description: "Region change callback ({ latitude, longitude, latitudeDelta, longitudeDelta })" }
47− , { name: "onSelectAnnotation", type_: "EventHandler", description: "Annotation tap callback" }
47+ , { name: "onSelectAnnotation", type_: "String -> Effect Unit", description: "Annotation tap callback" }
48 ]
48 ]
49 ]
49 ]
50
50
@@ -54,13 +54,13 @@ pdfView = L.componentDoc "nativePDFView" "Yoga.React.Native.MacOS.PDFView (nativ
54 { source: "/path/to/document.pdf"
54 { source: "/path/to/document.pdf"
55 , autoScales: true
55 , autoScales: true
56 , displayMode: T.singlePage
56 , displayMode: T.singlePage
57− , onPageChange: E.onInt "page" setPage
57+ , onPageChange: setPage
58 }"""
58 }"""
59 [ propsTable
59 [ propsTable
60 [ { name: "source", type_: "String", description: "PDF file path or URL" }
60 [ { name: "source", type_: "String", description: "PDF file path or URL" }
61 , { name: "autoScales", type_: "Boolean", description: "Auto-fit to view" }
61 , { name: "autoScales", type_: "Boolean", description: "Auto-fit to view" }
62 , { name: "displayMode", type_: "PDFDisplayMode", description: "PDF display mode" }
62 , { name: "displayMode", type_: "PDFDisplayMode", description: "PDF display mode" }
63− , { name: "onPageChange", type_: "EventHandler", description: "Page change callback" }
63+ , { name: "onPageChange", type_: "Int -> Effect Unit", description: "Page change callback" }
64 ]
64 ]
65 ]
65 ]
66
66
@@ -68,13 +68,13 @@ webView :: Nut
68webView = L.componentDoc "nativeWebView" "Yoga.React.Native.MacOS.WebView (nativeWebView)"
68webView = L.componentDoc "nativeWebView" "Yoga.React.Native.MacOS.WebView (nativeWebView)"
69 """nativeWebView
69 """nativeWebView
70 { url: "https://purescript.org"
70 { url: "https://purescript.org"
71− , onNavigate: E.onString "url" setUrl
71+ , onNavigate: setUrl
72− , onFinishLoad: handler_ onPageLoaded
72+ , onFinishLoad: \url -> log ("Loaded: " <> url)
73 }"""
73 }"""
74 [ propsTable
74 [ propsTable
75 [ { name: "url", type_: "String", description: "URL to load" }
75 [ { name: "url", type_: "String", description: "URL to load" }
76− , { name: "onNavigate", type_: "EventHandler", description: "Navigation callback" }
76+ , { name: "onNavigate", type_: "String -> Effect Unit", description: "Navigation callback" }
77− , { name: "onFinishLoad", type_: "EventHandler", description: "Page load complete callback" }
77+ , { name: "onFinishLoad", type_: "String -> Effect Unit", description: "Page load complete callback" }
78 ]
78 ]
79 ]
79 ]
80
80
docs/src/Docs/Pages/TextEditing.purs+6−6
@@ -19,8 +19,8 @@ textField = L.componentDoc "nativeTextField" "Yoga.React.Native.MacOS.TextField
19 { text: "Hello"
19 { text: "Hello"
20 , placeholder: "Enter text..."
20 , placeholder: "Enter text..."
21 , secure: false
21 , secure: false
22− , onChangeText: E.onString "text" setText
22+ , onChangeText: setText
23− , onSubmit: handler_ doSubmit
23+ , onSubmit: doSubmit
24 }"""
24 }"""
25 [ propsTable
25 [ propsTable
26 [ { name: "text", type_: "String", description: "Current text value" }
26 [ { name: "text", type_: "String", description: "Current text value" }
@@ -28,8 +28,8 @@ textField = L.componentDoc "nativeTextField" "Yoga.React.Native.MacOS.TextField
28 , { name: "secure", type_: "Boolean", description: "Password field (hides input)" }
28 , { name: "secure", type_: "Boolean", description: "Password field (hides input)" }
29 , { name: "search", type_: "Boolean", description: "Search field style" }
29 , { name: "search", type_: "Boolean", description: "Search field style" }
30 , { name: "rounded", type_: "Boolean", description: "Rounded bezel style" }
30 , { name: "rounded", type_: "Boolean", description: "Rounded bezel style" }
31− , { name: "onChangeText", type_: "EventHandler", description: "Text change callback" }
31+ , { name: "onChangeText", type_: "String -> Effect Unit", description: "Text change callback" }
32− , { name: "onSubmit", type_: "EventHandler", description: "Submit callback (Enter key)" }
32+ , { name: "onSubmit", type_: "String -> Effect Unit", description: "Submit callback (Enter key)" }
33 ]
33 ]
34 ]
34 ]
35
35
@@ -39,12 +39,12 @@ textEditor = L.componentDoc "nativeTextEditor" "Yoga.React.Native.MacOS.TextEdit
39 { text: "Rich text content..."
39 { text: "Rich text content..."
40 , richText: true
40 , richText: true
41 , showsRuler: false
41 , showsRuler: false
42− , onChangeText: E.onString "text" setText
42+ , onChangeText: setText
43 }"""
43 }"""
44 [ propsTable
44 [ propsTable
45 [ { name: "text", type_: "String", description: "Current text content" }
45 [ { name: "text", type_: "String", description: "Current text content" }
46 , { name: "richText", type_: "Boolean", description: "Enable rich text formatting" }
46 , { name: "richText", type_: "Boolean", description: "Enable rich text formatting" }
47 , { name: "showsRuler", type_: "Boolean", description: "Show the formatting ruler" }
47 , { 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" }
49 ]
49 ]
50 ]
50 ]
example-macos/src/Demo/AiMl.purs+6−10
@@ -13,14 +13,12 @@ import Demo.Shared (DemoProps, desc, scrollWrap, sectionTitle)
13import Effect.Aff (launchAff_)
13import Effect.Aff (launchAff_)
14import Effect.Class (liftEffect)
14import Effect.Class (liftEffect)
15import React.Basic (JSX)
15import React.Basic (JSX)
16−import React.Basic.Events (handler, handler_, unsafeEventFn)
17import React.Basic.Hooks (useState', (/\))
16import React.Basic.Hooks (useState', (/\))
18import React.Basic.Hooks as React
17import React.Basic.Hooks as React
19import Yoga.React (component)
18import Yoga.React (component)
20−import Yoga.React.Native (nativeEvent, text, tw, view)
19+import Yoga.React.Native (text, tw, view)
21import Yoga.React.Native.MacOS.Button (nativeButton)
20import Yoga.React.Native.MacOS.Button (nativeButton)
22import Yoga.React.Native.MacOS.CameraView (nativeCameraView)
21import Yoga.React.Native.MacOS.CameraView (nativeCameraView)
23−import Yoga.React.Native.MacOS.Events as E
24import Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)
22import Yoga.React.Native.MacOS.FilePicker (nativeFilePicker)
25import Yoga.React.Native.MacOS.NaturalLanguage (analyzeSentiment, detectLanguage, tokenize)
23import Yoga.React.Native.MacOS.NaturalLanguage (analyzeSentiment, detectLanguage, tokenize)
26import Yoga.React.Native.MacOS.OCR (recognizeText)
24import Yoga.React.Native.MacOS.OCR (recognizeText)
@@ -42,13 +40,11 @@ ocrDemo = component "OCRDemo" \dp -> React.do
42 , allowedTypes: [ "public.image" ]
40 , allowedTypes: [ "public.image" ]
43 , title: "Pick Image"
41 , title: "Pick Image"
44 , sfSymbol: "photo"
42 , sfSymbol: "photo"
45− , onPickFiles: handler
43+ , onPickFiles: \files -> for_ files \file -> do
46− (nativeEvent >>> unsafeEventFn \e -> E.getFieldArray "files" e)
47− \paths -> for_ paths \path -> do
48− setResult "Recognizing..."
44+ setResult "Recognizing..."
49− launchAff_ do
45+ launchAff_ do
50− r <- recognizeText path
46+ r <- recognizeText file.path
51− liftEffect (setResult r)
47+ liftEffect (setResult r)
52 , style: Style.style { height: 24.0, width: 140.0 }
48 , style: Style.style { height: 24.0, width: 140.0 }
53 }
49 }
54 ]
50 ]
example-macos/src/Demo/DragDropFiles.purs+7−12
@@ -2,6 +2,7 @@ module Demo.DragDropFiles (dropZoneDemo, filePickerDemo) where
2
2
3import Prelude
3import Prelude
4
4
5+import Data.String (joinWith)
5import Demo.Shared (DemoProps, card, desc, getFieldJSON, label, scrollWrap, sectionTitle)
6import Demo.Shared (DemoProps, card, desc, getFieldJSON, label, scrollWrap, sectionTitle)
6import React.Basic (JSX)
7import React.Basic (JSX)
7import React.Basic.Events (handler, handler_, unsafeEventFn)
8import React.Basic.Events (handler, handler_, unsafeEventFn)
@@ -68,10 +69,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
68 , allowMultiple: true
69 , allowMultiple: true
69 , allowedTypes: [ "public.image", "public.text" ]
70 , allowedTypes: [ "public.image", "public.text" ]
70 , message: "Select files to open"
71 , message: "Select files to open"
71− , onPickFiles: handler
72+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
72− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
73− setPicked
74− , onCancel: handler_ (setPicked "Cancelled")
73+ , onCancel: setPicked "Cancelled"
75 , style: Style.style { height: 24.0, width: 120.0 }
74 , style: Style.style { height: 24.0, width: 120.0 }
76 }
75 }
77 , nativeFilePicker
76 , nativeFilePicker
@@ -80,10 +79,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
80 , sfSymbol: "folder"
79 , sfSymbol: "folder"
81 , canChooseDirectories: true
80 , canChooseDirectories: true
82 , message: "Select a folder"
81 , message: "Select a folder"
83− , onPickFiles: handler
82+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
84− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
85− setPicked
86− , onCancel: handler_ (setPicked "Cancelled")
83+ , onCancel: setPicked "Cancelled"
87 , style: Style.style { height: 24.0, width: 140.0, marginLeft: 8.0 }
84 , style: Style.style { height: 24.0, width: 140.0, marginLeft: 8.0 }
88 }
85 }
89 , nativeFilePicker
86 , nativeFilePicker
@@ -93,10 +90,8 @@ filePickerDemo = component "FilePickerDemo" \dp -> React.do
93 , defaultName: "Untitled.txt"
90 , defaultName: "Untitled.txt"
94 , allowedTypes: [ "public.plain-text" ]
91 , allowedTypes: [ "public.plain-text" ]
95 , message: "Choose save location"
92 , message: "Choose save location"
96− , onPickFiles: handler
93+ , onPickFiles: \files -> setPicked (joinWith ", " (map _.path files))
97− (nativeEvent >>> unsafeEventFn \e -> getFieldJSON "files" e)
98− setPicked
99− , onCancel: handler_ (setPicked "Cancelled")
94+ , onCancel: setPicked "Cancelled"
100 , style: Style.style { height: 24.0, width: 120.0, marginLeft: 8.0 }
95 , style: Style.style { height: 24.0, width: 120.0, marginLeft: 8.0 }
101 }
96 }
102 ]
97 ]
example-macos/src/Demo/InputControls.purs+11−11
@@ -15,19 +15,22 @@ module Demo.InputControls
15
15
16import Prelude
16import Prelude
17
17
18+import Data.Array
19+ ( (!!)
20+ )
21+import Data.Maybe (fromMaybe)
18import Demo.Shared (DemoProps, card, desc, label, round, scrollWrap, sectionTitle)
22import Demo.Shared (DemoProps, card, desc, label, round, scrollWrap, sectionTitle)
19import React.Basic (JSX)
23import React.Basic (JSX)
20−import React.Basic.Events (handler, unsafeEventFn)
24+
21import React.Basic.Hooks (useState', (/\))
25import React.Basic.Hooks (useState', (/\))
22import React.Basic.Hooks as React
26import React.Basic.Hooks as React
23import Yoga.React (component)
27import Yoga.React (component)
24−import Yoga.React.Native (nativeEvent, text, tw, view)
28+import Yoga.React.Native (text, tw, view)
25import Yoga.React.Native.MacOS.Button (nativeButton)
29import Yoga.React.Native.MacOS.Button (nativeButton)
26import Yoga.React.Native.MacOS.Checkbox (nativeCheckbox)
30import Yoga.React.Native.MacOS.Checkbox (nativeCheckbox)
27import Yoga.React.Native.MacOS.ColorWell (nativeColorWell)
31import Yoga.React.Native.MacOS.ColorWell (nativeColorWell)
28import Yoga.React.Native.MacOS.ComboBox (nativeComboBox)
32import Yoga.React.Native.MacOS.ComboBox (nativeComboBox)
29import Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)
33import Yoga.React.Native.MacOS.DatePicker (nativeDatePicker)
30−import Yoga.React.Native.MacOS.Events as E
31import Yoga.React.Native.MacOS.LevelIndicator (nativeLevelIndicator)
34import Yoga.React.Native.MacOS.LevelIndicator (nativeLevelIndicator)
32import Yoga.React.Native.MacOS.PopUp (nativePopUp)
35import Yoga.React.Native.MacOS.PopUp (nativePopUp)
33import Yoga.React.Native.MacOS.Progress (nativeProgress)
36import Yoga.React.Native.MacOS.Progress (nativeProgress)
@@ -119,21 +122,18 @@ popUpDemo :: DemoProps -> JSX
119popUpDemo = component "PopUpDemo" \dp -> React.do
122popUpDemo = component "PopUpDemo" \dp -> React.do
120 idx /\ setIdx <- useState' 0
123 idx /\ setIdx <- useState' 0
121 title /\ setTitle <- useState' "Small"
124 title /\ setTitle <- useState' "Small"
125+ let items = [ "Small", "Medium", "Large", "Extra Large" ]
122 pure do
126 pure do
123 scrollWrap dp
127 scrollWrap dp
124 [ sectionTitle dp.fg "Pop Up Button"
128 [ sectionTitle dp.fg "Pop Up Button"
125 , card dp.cardBg
129 , card dp.cardBg
126 [ view { style: tw "flex-row items-center" }
130 [ view { style: tw "flex-row items-center" }
127 [ nativePopUp
131 [ nativePopUp
128− { items: [ "Small", "Medium", "Large", "Extra Large" ]
132+ { items
129 , selectedIndex: idx
133 , selectedIndex: idx
130− , onChange: handler
134+ , onChange: \i -> do
131− ( nativeEvent >>> unsafeEventFn \e ->
132− { idx: E.getFieldInt "selectedIndex" e, title: E.getFieldStr "title" e }
133− )
134− \r -> do
135− setIdx r.idx
135+ setIdx i
136− setTitle r.title
136+ setTitle (fromMaybe "" (items !! i))
137 , style: Style.style { height: 24.0, width: 160.0 }
137 , style: Style.style { height: 24.0, width: 160.0 }
138 }
138 }
139 , label dp.dimFg ("Selected: " <> title)
139 , label dp.dimFg ("Selected: " <> title)
src/Yoga/React/Native/MacOS/DropZone.js+21−1
@@ -1,2 +1,22 @@
1+import React from "react";
1import { requireNativeComponent } from "react-native";
2import { requireNativeComponent } from "react-native";
3+const NativeDropZone = requireNativeComponent("MacOSDropZone");
2−export const dropZoneImpl = 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
2
2
3+import Prelude
4+import Effect (Effect)
3import React.Basic (ReactComponent)
5import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
5import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
7import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
7
8
@@ -10,8 +11,13 @@ foreign import dropZoneImpl :: forall props. ReactComponent props
10nativeDropZone :: FFINativeComponent NativeDropZoneAttributes
11nativeDropZone :: FFINativeComponent NativeDropZoneAttributes
11nativeDropZone = createNativeElement dropZoneImpl
12nativeDropZone = createNativeElement dropZoneImpl
12
13
14+type DroppedData =
15+ { files :: Array { path :: String, name :: String }
16+ , strings :: Array String
17+ }
18+
13type NativeDropZoneAttributes = BaseAttributes
19type NativeDropZoneAttributes = BaseAttributes
14− ( onFileDrop :: EventHandler
20+ ( onFileDrop :: DroppedData -> Effect Unit
15− , onFilesDragEnter :: EventHandler
21+ , onFilesDragEnter :: Effect Unit
16− , onFilesDragExit :: EventHandler
22+ , onFilesDragExit :: Effect Unit
17 )
23 )
src/Yoga/React/Native/MacOS/FilePicker.js+13−1
@@ -1,2 +1,14 @@
1+import React from "react";
1import { requireNativeComponent } from "react-native";
2import { requireNativeComponent } from "react-native";
3+const NativeFilePicker = requireNativeComponent("MacOSFilePicker");
2−export const filePickerImpl = 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
2
2
3+import Prelude
4+import Effect (Effect)
3import React.Basic (ReactComponent)
5import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
5import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
7import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
7import Yoga.React.Native.MacOS.Types (FilePickerMode)
8import Yoga.React.Native.MacOS.Types (FilePickerMode)
@@ -11,6 +12,11 @@ foreign import filePickerImpl :: forall props. ReactComponent props
11nativeFilePicker :: FFINativeComponent_ NativeFilePickerAttributes
12nativeFilePicker :: FFINativeComponent_ NativeFilePickerAttributes
12nativeFilePicker = createNativeElement_ filePickerImpl
13nativeFilePicker = createNativeElement_ filePickerImpl
13
14
15+type PickedFile =
16+ { path :: String
17+ , name :: String
18+ }
19+
14type NativeFilePickerAttributes = BaseAttributes
20type NativeFilePickerAttributes = BaseAttributes
15 ( mode :: FilePickerMode
21 ( mode :: FilePickerMode
16 , title :: String
22 , title :: String
@@ -20,6 +26,6 @@ type NativeFilePickerAttributes = BaseAttributes
20 , allowedTypes :: Array String
26 , allowedTypes :: Array String
21 , allowMultiple :: Boolean
27 , allowMultiple :: Boolean
22 , canChooseDirectories :: Boolean
28 , canChooseDirectories :: Boolean
23− , onPickFiles :: EventHandler
29+ , onPickFiles :: Array PickedFile -> Effect Unit
24− , onCancel :: EventHandler
30+ , onCancel :: Effect Unit
25 )
31 )
src/Yoga/React/Native/MacOS/MapView.js+21−1
@@ -1,2 +1,22 @@
1+import React from "react";
1import { requireNativeComponent } from "react-native";
2import { requireNativeComponent } from "react-native";
3+const NativeMapView = requireNativeComponent("MacOSMapView");
2−export const mapViewImpl = 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
2 ( nativeMapView
2 ( nativeMapView
3 , NativeMapViewAttributes
3 , NativeMapViewAttributes
4 , MapAnnotation
4 , MapAnnotation
5+ , MapRegion
5 ) where
6 ) where
6
7
8+import Prelude
9+import Effect (Effect)
7import React.Basic (ReactComponent)
10import React.Basic (ReactComponent)
8−import React.Basic.Events (EventHandler)
9import Yoga.React.Native.Attributes (BaseAttributes)
11import Yoga.React.Native.Attributes (BaseAttributes)
10import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
12import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
11import Yoga.React.Native.MacOS.Types (MapType)
13import Yoga.React.Native.MacOS.Types (MapType)
@@ -22,6 +24,13 @@ type MapAnnotation =
22 , subtitle :: String
24 , subtitle :: String
23 }
25 }
24
26
27+type MapRegion =
28+ { latitude :: Number
29+ , longitude :: Number
30+ , latitudeDelta :: Number
31+ , longitudeDelta :: Number
32+ }
33+
25type NativeMapViewAttributes = BaseAttributes
34type NativeMapViewAttributes = BaseAttributes
26 ( latitude :: Number
35 ( latitude :: Number
27 , longitude :: Number
36 , longitude :: Number
@@ -30,6 +39,6 @@ type NativeMapViewAttributes = BaseAttributes
30 , mapType :: MapType
39 , mapType :: MapType
31 , showsUserLocation :: Boolean
40 , showsUserLocation :: Boolean
32 , annotations :: Array MapAnnotation
41 , annotations :: Array MapAnnotation
33− , onRegionChange :: EventHandler
42+ , onRegionChange :: MapRegion -> Effect Unit
34− , onSelectAnnotation :: EventHandler
43+ , onSelectAnnotation :: String -> Effect Unit
35 )
44 )
src/Yoga/React/Native/MacOS/PopUp.js+10−1
@@ -1,2 +1,11 @@
1+import React from "react";
1import { requireNativeComponent } from "react-native";
2import { requireNativeComponent } from "react-native";
3+const NativePopUp = requireNativeComponent("NativePopUp");
2−export const popUpImpl = 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 @@
1module Yoga.React.Native.MacOS.PopUp (nativePopUp, NativePopUpAttributes) where
1module Yoga.React.Native.MacOS.PopUp (nativePopUp, NativePopUpAttributes) where
2
2
3+import Prelude
4+import Effect (Effect)
3import React.Basic (ReactComponent)
5import React.Basic (ReactComponent)
4−import React.Basic.Events (EventHandler)
5import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Attributes (BaseAttributes)
6import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
7import Yoga.React.Native.Internal (FFINativeComponent_, createNativeElement_)
7
8
@@ -13,5 +14,5 @@ nativePopUp = createNativeElement_ popUpImpl
13type NativePopUpAttributes = BaseAttributes
14type NativePopUpAttributes = BaseAttributes
14 ( items :: Array String
15 ( items :: Array String
15 , selectedIndex :: Int
16 , selectedIndex :: Int
16− , onChange :: EventHandler
17+ , onChange :: Int -> Effect Unit
17 )
18 )