Skip to content

Commit 662f9b1

Browse files
committed
Render Stepper, Menu, and secure text fields
1 parent 90d36e1 commit 662f9b1

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

  • Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui

Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui/Render.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ import androidx.compose.foundation.shape.CircleShape
100100
import androidx.compose.ui.text.font.FontStyle
101101
import androidx.compose.ui.text.font.FontWeight
102102
import androidx.compose.ui.text.style.TextAlign
103+
import androidx.compose.ui.text.input.PasswordVisualTransformation
103104
import androidx.compose.ui.text.input.TextFieldValue
105+
import androidx.compose.ui.text.input.VisualTransformation
104106
import androidx.compose.ui.unit.TextUnit
105107
import androidx.compose.ui.unit.sp
106108
import androidx.compose.ui.unit.IntOffset
@@ -223,6 +225,10 @@ fun Render(node: ViewNode) {
223225

224226
"TextField" -> RenderTextField(node)
225227

228+
"Stepper" -> RenderStepper(node)
229+
230+
"Menu" -> RenderMenu(node)
231+
226232
"Picker" -> RenderPicker(node)
227233

228234
"NavStack" -> RenderNavStack(node)
@@ -289,10 +295,47 @@ private fun RenderTextField(node: ViewNode) {
289295
}
290296
},
291297
label = { Text(node.string("placeholder") ?: "") },
298+
visualTransformation = if (node.bool("secure") == true) PasswordVisualTransformation() else VisualTransformation.None,
292299
modifier = node.composeModifiers().fillMaxWidth(),
293300
)
294301
}
295302

303+
// Label, then − / + edge buttons pushed to the trailing side.
304+
@Composable
305+
private fun RenderStepper(node: ViewNode) {
306+
val onIncrement = node.long("onIncrement")
307+
val onDecrement = node.long("onDecrement")
308+
Row(verticalAlignment = Alignment.CenterVertically, modifier = node.composeModifiers().fillMaxWidth()) {
309+
RenderChildren(node)
310+
Spacer(modifier = Modifier.weight(1f))
311+
TextButton(onClick = { onDecrement?.let { SwiftBridge.sink.invokeVoid(it) } }) { Text("", fontSize = 20.sp) }
312+
TextButton(onClick = { onIncrement?.let { SwiftBridge.sink.invokeVoid(it) } }) { Text("+", fontSize = 20.sp) }
313+
}
314+
}
315+
316+
// A trigger button opening a dropdown; each child Button becomes a menu item
317+
// firing its own tap callback.
318+
@Composable
319+
private fun RenderMenu(node: ViewNode) {
320+
var expanded by remember { mutableStateOf(false) }
321+
Box {
322+
TextButton(onClick = { expanded = true }) { Text(node.string("label") ?: "") }
323+
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
324+
for (child in node.children) {
325+
if (child.isPresentation()) continue
326+
val onTap = child.long("onTap")
327+
DropdownMenuItem(
328+
text = { Text(pickerLabel(child)) },
329+
onClick = {
330+
expanded = false
331+
onTap?.let { SwiftBridge.sink.invokeVoid(it) }
332+
},
333+
)
334+
}
335+
}
336+
}
337+
}
338+
296339
@Composable
297340
private fun RenderPicker(node: ViewNode) {
298341
val onChange = node.long("onChange")

0 commit comments

Comments
 (0)