Skip to content

Commit e71cd89

Browse files
committed
Allow initial values to be specified for some views
The following ActionUI views: - ComboBox - SecureField - TextEditor - TextField - Toggle now allow specifying initial value in their JSON properties.
1 parent 604b3a4 commit e71cd89

16 files changed

Lines changed: 232 additions & 5 deletions

ActionUI/Views/ComboBox.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"type": "ComboBox",
66
"id": 1, // Optional: Non-zero positive integer for runtime programmatic interaction
77
"properties": {
8+
"text": "Option1", // Optional: String initial value, defaults to ""
89
"placeholder": "Select an option", // Optional: String, defaults to ""
910
"options": ["Option1", "Option2"], // Optional: Array of strings, defaults to []
1011
}
@@ -25,6 +26,12 @@ struct ComboBox: ActionUIViewConstruction {
2526
logger.log("ComboBox is not supported on watchOS/tvOS; defaulting to empty properties", .warning)
2627
validatedProperties = [:]
2728
#else
29+
// Validate text (initial value)
30+
if properties["text"] != nil && !(properties["text"] is String) {
31+
logger.log("ComboBox text must be a String; ignoring", .warning)
32+
validatedProperties["text"] = nil
33+
}
34+
2835
// Validate options
2936
if let options = validatedProperties["options"] as? [String] {
3037
if options.isEmpty {
@@ -87,6 +94,9 @@ struct ComboBox: ActionUIViewConstruction {
8794
if let initialValue = model.value as? String {
8895
return initialValue
8996
}
97+
if let text = model.validatedProperties["text"] as? String {
98+
return text
99+
}
90100
return ""
91101
}
92102
}

ActionUI/Views/SecureField.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"type": "SecureField",
55
"id": 1, // Optional: Non-zero positive integer for runtime programmatic interaction
66
"properties": {
7+
"text": "secret", // Optional: String initial value, defaults to ""
78
"placeholder": "Enter password", // Optional: String for placeholder, defaults to ""
89
"textContentType": "password", // Optional: String for content type, must be one of: "password", "newPassword", "oneTimeCode"; defaults to nil, ignored on macOS
910
"actionID": "secure.submit" // Optional: String for action triggered on submit (e.g., Return key)
@@ -25,6 +26,12 @@ struct SecureField: ActionUIViewConstruction {
2526
static var validateProperties: ([String: Any], any ActionUILogger) -> [String: Any] = { properties, logger in
2627
var validatedProperties = properties
2728

29+
// Validate text (initial value)
30+
if properties["text"] != nil && !(properties["text"] is String) {
31+
logger.log("SecureField text must be a String; ignoring", .warning)
32+
validatedProperties["text"] = nil
33+
}
34+
2835
// Validate placeholder
2936
if !(properties["placeholder"] is String?), properties["placeholder"] != nil {
3037
logger.log("SecureField placeholder must be a String; defaulting to nil", .warning)
@@ -101,6 +108,9 @@ struct SecureField: ActionUIViewConstruction {
101108
if let initialValue = model.value as? String {
102109
return initialValue
103110
}
111+
if let text = model.validatedProperties["text"] as? String {
112+
return text
113+
}
104114
return ""
105115
}
106116
}

ActionUI/Views/TextEditor.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"type": "TextEditor",
55
"id": 1, // Optional: Non-zero positive integer for runtime programmatic interaction
66
"properties": {
7+
"text": "Initial content", // Optional: String initial value, defaults to ""
78
"placeholder": "Enter text here" // Optional: String, no default value if omitted or empty
89
}
910
// Note: These properties are specific to TextEditor. Baseline View properties (padding, hidden, foregroundColor, font, background, frame, opacity, cornerRadius, actionID, disabled) and additional View protocol modifiers are inherited and applied via ActionUIRegistry.shared.applyViewModifiers(to: baseView, properties: element.properties).
@@ -19,12 +20,18 @@ struct TextEditor: ActionUIViewConstruction {
1920
static var validateProperties: ([String: Any], any ActionUILogger) -> [String: Any] = { properties, logger in
2021
var validatedProperties = properties
2122

23+
// Validate text (initial value)
24+
if properties["text"] != nil && !(properties["text"] is String) {
25+
logger.log("TextEditor text must be a String; ignoring", .warning)
26+
validatedProperties["text"] = nil
27+
}
28+
2229
// Validate placeholder
2330
if !(properties["placeholder"] is String?), properties["placeholder"] != nil {
2431
logger.log("TextEditor placeholder must be a String; defaulting to nil", .warning)
2532
validatedProperties["placeholder"] = nil
2633
}
27-
34+
2835
return validatedProperties
2936
}
3037

@@ -71,6 +78,9 @@ struct TextEditor: ActionUIViewConstruction {
7178
if let initialValue = model.value as? String {
7279
return initialValue
7380
}
81+
if let text = model.validatedProperties["text"] as? String {
82+
return text
83+
}
7484
return ""
7585
}
7686
}

ActionUI/Views/TextField.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"type": "TextField",
66
"id": 1, // Optional: Non-zero positive integer for runtime programmatic interaction
77
"properties": {
8+
"text": "Hello", // Optional: String initial value for the field, defaults to ""
89
"placeholder": "Enter text", // Optional: String for placeholder, defaults to "" in buildView
910
"textContentType": "username", // Optional: String for content type (e.g., "username", "password"), defaults to nil, ignored on macOS
1011
"actionID": "text.submit", // Optional: String for action triggered on submit (e.g., Return key, inherited from View)
@@ -35,12 +36,18 @@ struct TextField: ActionUIViewConstruction {
3536
validatedProperties["placeholder"] = nil
3637
}
3738

39+
// Validate text (initial value)
40+
if properties["text"] != nil && !(properties["text"] is String) {
41+
logger.log("TextField text must be a String; ignoring", .warning)
42+
validatedProperties["text"] = nil
43+
}
44+
3845
// Validate textContentType
3946
if !(properties["textContentType"] is String?), properties["textContentType"] != nil {
4047
logger.log("TextField textContentType must be a String; defaulting to nil", .warning)
4148
validatedProperties["textContentType"] = nil
4249
}
43-
50+
4451
return validatedProperties
4552
}
4653

ActionUI/Views/Toggle.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"type": "Toggle",
55
"id": 1, // Optional: Non-zero positive integer for runtime programmatic interaction
66
"properties": {
7+
"isOn": true, // Optional: Boolean initial state, defaults to false
78
"title": "Enable Feature", // Optional: String, defaults to "Toggle"
89
"style": "switch", // Optional: "switch" (iOS/macOS/visionOS), "checkbox" (macOS only), "button" (iOS/macOS/visionOS); defaults to "switch"
910
}
@@ -19,6 +20,12 @@ struct Toggle: ActionUIViewConstruction {
1920
static var validateProperties: ([String: Any], any ActionUILogger) -> [String: Any] = { properties, logger in
2021
var validatedProperties = properties
2122

23+
// Validate isOn (initial value)
24+
if properties["isOn"] != nil && !(properties["isOn"] is Bool) {
25+
logger.log("Toggle isOn must be a Bool; ignoring", .warning)
26+
validatedProperties["isOn"] = nil
27+
}
28+
2229
// Validate style based on platform
2330
#if os(macOS)
2431
let validStyles = ["switch", "button", "checkbox"]
@@ -29,7 +36,7 @@ struct Toggle: ActionUIViewConstruction {
2936
logger.log("Toggle style '\(style)' invalid on \(ProcessInfo.processInfo.operatingSystemVersionString); falling back to default", .warning)
3037
validatedProperties["style"] = nil
3138
}
32-
39+
3340
return validatedProperties
3441
}
3542

@@ -85,6 +92,9 @@ struct Toggle: ActionUIViewConstruction {
8592
if let initialValue = model.value as? Bool {
8693
return initialValue
8794
}
95+
if let isOn = model.validatedProperties["isOn"] as? Bool {
96+
return isOn
97+
}
8898
return false
8999
}
90100
}

ActionUISwiftTestApp/Resources/ComboBox.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525
"placeholder": "Choose",
2626
"options": ["A", "B", "C"]
2727
}
28+
},
29+
{
30+
"type": "ComboBox",
31+
"properties": {
32+
"text": "Option2",
33+
"placeholder": "Pre-selected",
34+
"options": ["Option1", "Option2", "Option3"]
35+
}
2836
}
2937
]
3038
}

ActionUISwiftTestApp/Resources/SecureField.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
"placeholder": "New Password",
2727
"textContentType": "newPassword"
2828
}
29+
},
30+
{
31+
"type": "SecureField",
32+
"properties": {
33+
"text": "secret",
34+
"placeholder": "With initial value"
35+
}
2936
}
3037
]
3138
}

ActionUISwiftTestApp/Resources/TextEditor.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@
1616
{
1717
"type": "TextEditor",
1818
"properties": {
19-
"placeholder": "Enter text here"
19+
"placeholder": "Enter text here",
20+
"border": { "color": "#80808060", "width": 1.0 }
21+
}
22+
},
23+
{
24+
"type": "TextEditor",
25+
"properties": {
26+
"text": "This editor has initial content.\nIt supports multiple lines.",
27+
"placeholder": "With initial text",
28+
"border": { "color": "#80808060", "width": 1.0 }
2029
}
2130
}
2231
]

ActionUISwiftTestApp/Resources/TextField.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
"placeholder": "Email",
2727
"textContentType": "emailAddress"
2828
}
29+
},
30+
{
31+
"type": "TextField",
32+
"properties": {
33+
"text": "Pre-filled value",
34+
"placeholder": "With initial text"
35+
}
2936
}
3037
]
3138
}

ActionUISwiftTestApp/Resources/Toggle.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@
2727
"style": "checkbox",
2828
"padding": "default"
2929
}
30+
},
31+
{
32+
"type": "Toggle",
33+
"properties": {
34+
"title": "Initially On",
35+
"isOn": true,
36+
"style": "switch",
37+
"padding": "default"
38+
}
39+
},
40+
{
41+
"type": "Toggle",
42+
"properties": {
43+
"title": "Checked by Default",
44+
"isOn": true,
45+
"style": "checkbox",
46+
"padding": "default"
47+
}
3048
}
3149
]
3250
}

0 commit comments

Comments
 (0)