@salesforce/afv-skills 1.49.0 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/skills/experience-ui-bundle-deploy/SKILL.md +43 -2
  3. package/skills/experience-ui-bundle-deploy/references/config-scaffold.md +16 -3
  4. package/skills/experience-ui-bundle-deploy/references/logout-url.md +97 -0
  5. package/skills/experience-ui-bundle-deploy/scripts/set-logout-url.mjs +304 -0
  6. package/skills/experience-ui-bundle-localize/SKILL.md +107 -90
  7. package/skills/experience-ui-bundle-localize/references/angular/check-i18n-wired.sh +159 -0
  8. package/skills/experience-ui-bundle-localize/references/angular/i18n-setup.md +250 -0
  9. package/skills/experience-ui-bundle-localize/references/angular/interpolation.md +156 -0
  10. package/skills/experience-ui-bundle-localize/references/angular/localize.md +111 -0
  11. package/skills/experience-ui-bundle-localize/references/{gotchas.md → common/gotchas.md} +27 -43
  12. package/skills/experience-ui-bundle-localize/references/{label-xml.md → common/label-xml.md} +27 -17
  13. package/skills/experience-ui-bundle-localize/references/common/platform-sdk-i18n.md +169 -0
  14. package/skills/experience-ui-bundle-localize/references/{verifying.md → common/verifying.md} +26 -16
  15. package/skills/experience-ui-bundle-localize/{scripts → references/react}/check-i18n-wired.sh +8 -3
  16. package/skills/experience-ui-bundle-localize/references/{i18n-setup.md → react/i18n-setup.md} +48 -10
  17. package/skills/experience-ui-bundle-localize/references/{interpolation.md → react/interpolation.md} +4 -4
  18. package/skills/experience-ui-bundle-localize/references/react/localize.md +76 -0
  19. package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +92 -24
  20. package/skills/experience-ui-bundle-localize/scripts/detect-framework.sh +73 -0
  21. package/skills/experience-ui-bundle-site-generate/SKILL.md +1 -1
  22. package/skills/field-service-data-capture-form-deployer-configure/SKILL.md +180 -0
  23. package/skills/field-service-data-capture-form-deployer-configure/examples/inventory-transfer-spec.json +135 -0
  24. package/skills/field-service-data-capture-form-deployer-configure/examples/sample-spec.json +140 -0
  25. package/skills/field-service-data-capture-form-deployer-configure/examples/sectioned-spec.json +64 -0
  26. package/skills/field-service-data-capture-form-deployer-configure/references/field-types.md +297 -0
  27. package/skills/field-service-data-capture-form-deployer-configure/references/flow-metadata-json.md +243 -0
  28. package/skills/field-service-data-capture-form-deployer-configure/references/post-screen-automation.md +127 -0
  29. package/skills/field-service-data-capture-form-designer-configure/SKILL.md +110 -0
  30. package/skills/field-service-data-capture-form-designer-configure/references/extraction-from-image.md +244 -0
  31. package/skills/field-service-data-capture-form-designer-configure/references/extraction-from-prompt.md +222 -0
  32. package/skills/field-service-data-capture-form-editor-configure/SKILL.md +134 -0
  33. package/skills/field-service-data-capture-reference-configure/SKILL.md +762 -0
  34. package/skills/field-service-data-capture-reference-configure/examples/DataCapture_Showcase.flow-meta.xml +2022 -0
  35. package/skills/field-service-data-capture-reference-configure/examples/Data_Capture_All_Components.flow-meta.xml +2170 -0
  36. package/skills/field-service-data-capture-reference-configure/examples/Repeater_with_prepopulation.flow-meta.xml +231 -0
  37. package/skills/field-service-foundation-setup-designer-get/SKILL.md +135 -0
  38. package/skills/field-service-mobile-branding-configure/SKILL.md +133 -0
  39. package/skills/field-service-mobile-branding-configure/examples/dark-blue-scheme.json +16 -0
  40. package/skills/field-service-mobile-branding-configure/examples/salesforce-default-scheme.json +16 -0
  41. package/skills/field-service-mobile-branding-configure/references/color-fields.md +66 -0
  42. package/skills/field-service-mobile-branding-configure/references/contrast-validation.md +55 -0
  43. package/skills/field-service-mobile-branding-configure/references/derivation-methodology.md +83 -0
  44. package/skills/field-service-objective-designer-configure/SKILL.md +342 -0
  45. package/skills/field-service-prework-brief-deployer-configure/SKILL.md +83 -0
  46. package/skills/field-service-scheduling-policy-designer-query/SKILL.md +121 -0
  47. package/skills/field-service-setup-orchestrator-get/SKILL.md +48 -0
  48. package/skills/field-service-sobject-create-configure/SKILL.md +56 -0
  49. package/skills/field-service-voice-to-form-configure/SKILL.md +650 -0
  50. package/skills/field-service-work-rule-designer-configure/SKILL.md +303 -0
  51. package/skills/service-digital-engagement-channel-configure/SKILL.md +20 -37
  52. package/skills/service-digital-engagement-channel-configure/assets/messaging_channel_template.xml +3 -2
  53. package/skills/service-digital-engagement-channel-configure/examples/asa_agent_channel.xml +4 -4
  54. package/skills/service-helpagent-coordinate/SKILL.md +37 -29
  55. package/skills/service-helpagent-coordinate/assets/help-agent-spec.md +33 -28
  56. package/skills/service-helpagent-coordinate/references/agent-script.md +4 -1
  57. package/skills/service-helpagent-coordinate/references/channel-voice.md +1 -1
  58. package/skills/service-helpagent-coordinate/references/channel-web-chat.md +10 -12
@@ -0,0 +1,135 @@
1
+ {
2
+ "formTitle": "Inventory Transfer",
3
+ "formType": "Inventory Transfer",
4
+ "screens": {
5
+ "InventoryTransfer": [
6
+ {
7
+ "fieldName": "From",
8
+ "fieldLabel": "From",
9
+ "fieldType": "ShortText",
10
+ "isRequired": true,
11
+ "defaultValue": null,
12
+ "options": null
13
+ },
14
+ {
15
+ "fieldName": "To",
16
+ "fieldLabel": "To",
17
+ "fieldType": "Radio",
18
+ "isRequired": true,
19
+ "defaultValue": null,
20
+ "options": ["Truck", "Work Order"]
21
+ },
22
+ {
23
+ "fieldName": "Work_Order_Number",
24
+ "fieldLabel": "Work Order Number",
25
+ "fieldType": "ShortText",
26
+ "isRequired": true,
27
+ "defaultValue": null,
28
+ "options": null,
29
+ "visibility": { "field": "To", "operator": "EqualTo", "value": "Work Order" }
30
+ },
31
+ {
32
+ "fieldName": "Part",
33
+ "fieldLabel": "Parts",
34
+ "fieldType": "Repeater",
35
+ "isRequired": false,
36
+ "repeaterFields": [
37
+ {
38
+ "fieldName": "Quantity",
39
+ "fieldLabel": "Quantity",
40
+ "fieldType": "Counter",
41
+ "isRequired": true,
42
+ "min": 1,
43
+ "value": 1
44
+ },
45
+ {
46
+ "fieldName": "Part_Number",
47
+ "fieldLabel": "Part Number",
48
+ "fieldType": "ShortText",
49
+ "isRequired": true
50
+ },
51
+ {
52
+ "fieldName": "Part_Description",
53
+ "fieldLabel": "Part Description",
54
+ "fieldType": "ShortText",
55
+ "isRequired": true
56
+ }
57
+ ]
58
+ }
59
+ ]
60
+ },
61
+ "postScreen": {
62
+ "variables": [
63
+ { "name": "Transfer_Destination", "type": "String" }
64
+ ],
65
+ "decision": {
66
+ "name": "Transfer_Location_Decision",
67
+ "label": "Transfer Location Decision",
68
+ "defaultLabel": "Error",
69
+ "branches": [
70
+ {
71
+ "name": "Truck_Decision",
72
+ "label": "Truck",
73
+ "when": { "field": "To", "operator": "EqualTo", "value": "Truck" },
74
+ "then": "Get_Truck"
75
+ },
76
+ {
77
+ "name": "Work_Order_Decision",
78
+ "label": "Work Order",
79
+ "when": { "field": "To", "operator": "EqualTo", "value": "Work Order" },
80
+ "then": "Get_WO"
81
+ }
82
+ ]
83
+ },
84
+ "recordLookups": [
85
+ {
86
+ "name": "Get_Truck",
87
+ "label": "Get Truck",
88
+ "object": "Location",
89
+ "filters": [
90
+ { "field": "Service_Resource__c", "operator": "EqualTo", "valueRef": "$User.Id" }
91
+ ],
92
+ "outputAssignments": [
93
+ { "assignTo": "Transfer_Destination", "field": "Id" }
94
+ ],
95
+ "next": "Part_Transfers"
96
+ },
97
+ {
98
+ "name": "Get_WO",
99
+ "label": "Get WO",
100
+ "object": "WorkOrder",
101
+ "filters": [
102
+ { "field": "Id", "operator": "EqualTo", "valueRef": "Work_Order_Number.value" }
103
+ ],
104
+ "outputAssignments": [
105
+ { "assignTo": "Transfer_Destination", "field": "LocationId" }
106
+ ],
107
+ "next": "Part_Transfers"
108
+ }
109
+ ],
110
+ "loop": {
111
+ "name": "Part_Transfers",
112
+ "label": "Part Transfers",
113
+ "description": "Transfer each part",
114
+ "collection": "Part.AddedItems",
115
+ "next": "Transfer_Part"
116
+ },
117
+ "recordCreates": [
118
+ {
119
+ "name": "Transfer_Part",
120
+ "label": "Transfer Part",
121
+ "object": "ProductTransfer",
122
+ "next": "Part_Transfers",
123
+ "inputAssignments": [
124
+ { "field": "DestinationLocationId", "valueRef": "Transfer_Destination" },
125
+ { "field": "IsReceived", "boolean": true },
126
+ { "field": "OwnerId", "valueRef": "$User.Id" },
127
+ { "field": "Product2Id", "valueRef": "Part_Transfers.Part_Number.value" },
128
+ { "field": "QuantityReceived", "valueRef": "Part_Transfers.Quantity.value" },
129
+ { "field": "QuantitySent", "valueRef": "Part_Transfers.Quantity.value" },
130
+ { "field": "ReceivedById", "valueRef": "$User.Id" }
131
+ ]
132
+ }
133
+ ]
134
+ }
135
+ }
@@ -0,0 +1,140 @@
1
+ {
2
+ "formTitle": "HVAC Compressor Inspection",
3
+ "formType": "Equipment Inspection",
4
+ "screens": {
5
+ "HeaderInformation": [
6
+ {
7
+ "fieldName": "jobName",
8
+ "fieldLabel": "Job Name",
9
+ "fieldType": "ShortText",
10
+ "isRequired": true,
11
+ "defaultValue": null,
12
+ "options": null
13
+ },
14
+ {
15
+ "fieldName": "inspectorName",
16
+ "fieldLabel": "Inspector Name",
17
+ "fieldType": "Name",
18
+ "isRequired": true,
19
+ "defaultValue": null,
20
+ "options": null
21
+ },
22
+ {
23
+ "fieldName": "inspectorEmail",
24
+ "fieldLabel": "Inspector Email",
25
+ "fieldType": "Email",
26
+ "isRequired": false,
27
+ "defaultValue": null,
28
+ "options": null
29
+ },
30
+ {
31
+ "fieldName": "inspectionDate",
32
+ "fieldLabel": "Inspection Date",
33
+ "fieldType": "Date",
34
+ "isRequired": true,
35
+ "defaultValue": null,
36
+ "options": null
37
+ }
38
+ ],
39
+ "OperatingParameters": [
40
+ {
41
+ "fieldName": "oilTemperature",
42
+ "fieldLabel": "Oil temperature (°C)",
43
+ "fieldType": "Numeric",
44
+ "isRequired": false,
45
+ "defaultValue": null,
46
+ "options": null
47
+ },
48
+ {
49
+ "fieldName": "filterCount",
50
+ "fieldLabel": "Number of filters replaced",
51
+ "fieldType": "Counter",
52
+ "isRequired": false,
53
+ "defaultValue": null,
54
+ "options": null
55
+ },
56
+ {
57
+ "fieldName": "overallCondition",
58
+ "fieldLabel": "Overall Condition",
59
+ "fieldType": "Radio",
60
+ "isRequired": true,
61
+ "defaultValue": null,
62
+ "options": ["Excellent", "Good", "Fair", "Poor", "Critical"]
63
+ },
64
+ {
65
+ "fieldName": "issuesIdentified",
66
+ "fieldLabel": "Issues Identified (select all that apply)",
67
+ "fieldType": "CheckboxGroup",
68
+ "isRequired": false,
69
+ "defaultValue": null,
70
+ "options": ["Corrosion", "Wear", "Leakage", "Noise", "Vibration"]
71
+ },
72
+ {
73
+ "fieldName": "priority",
74
+ "fieldLabel": "Priority",
75
+ "fieldType": "Picklist",
76
+ "isRequired": false,
77
+ "defaultValue": null,
78
+ "options": ["High", "Medium", "Low"]
79
+ },
80
+ {
81
+ "fieldName": "wallThicknessStamped",
82
+ "fieldLabel": "Has wall thickness been stamped adjacent to measuring point?",
83
+ "fieldType": "Checkbox",
84
+ "isRequired": false,
85
+ "defaultValue": null,
86
+ "options": null
87
+ },
88
+ {
89
+ "fieldName": "emergencyShutdown",
90
+ "fieldLabel": "Emergency Shutdown Activated",
91
+ "fieldType": "Toggle",
92
+ "isRequired": false,
93
+ "defaultValue": null,
94
+ "options": null
95
+ }
96
+ ],
97
+ "AttachmentsAndSignature": [
98
+ {
99
+ "fieldName": "safetyInstructions",
100
+ "fieldLabel": "Safety Instructions",
101
+ "fieldType": "DisplayText",
102
+ "isRequired": false,
103
+ "defaultValue": "All personnel must wear appropriate PPE. Ensure equipment is locked out before proceeding.",
104
+ "options": null
105
+ },
106
+ {
107
+ "fieldName": "damagePhoto",
108
+ "fieldLabel": "Photo of Damage",
109
+ "fieldType": "UploadImage",
110
+ "isRequired": false,
111
+ "defaultValue": null,
112
+ "options": null
113
+ },
114
+ {
115
+ "fieldName": "technicalDrawing",
116
+ "fieldLabel": "Upload Technical Drawing (PDF)",
117
+ "fieldType": "UploadFile",
118
+ "isRequired": false,
119
+ "defaultValue": null,
120
+ "options": null
121
+ },
122
+ {
123
+ "fieldName": "remarks",
124
+ "fieldLabel": "Remarks",
125
+ "fieldType": "LongText",
126
+ "isRequired": false,
127
+ "defaultValue": null,
128
+ "options": null
129
+ },
130
+ {
131
+ "fieldName": "inspectorSignature",
132
+ "fieldLabel": "Inspector Signature",
133
+ "fieldType": "Signature",
134
+ "isRequired": true,
135
+ "defaultValue": null,
136
+ "options": null
137
+ }
138
+ ]
139
+ }
140
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "formTitle": "Asset Inspection (Sectioned)",
3
+ "formType": "Asset Inspection",
4
+ "screens": {
5
+ "Inspection": [
6
+ { "section": "Asset Details" },
7
+ {
8
+ "fieldName": "AssetName",
9
+ "fieldLabel": "Asset Name",
10
+ "fieldType": "ShortText",
11
+ "isRequired": true
12
+ },
13
+ {
14
+ "fieldName": "Manufacturer",
15
+ "fieldLabel": "Manufacturer",
16
+ "fieldType": "Picklist",
17
+ "isRequired": false,
18
+ "options": ["Demag", "Konecranes", "Other"]
19
+ },
20
+ {
21
+ "fieldName": "SerialNumber",
22
+ "fieldLabel": "Serial Number",
23
+ "fieldType": "ShortText",
24
+ "isRequired": false
25
+ },
26
+
27
+ { "section": "Inspection Result" },
28
+ {
29
+ "fieldName": "OverallCondition",
30
+ "fieldLabel": "Overall Condition",
31
+ "fieldType": "Picklist",
32
+ "isRequired": true,
33
+ "options": ["Pass", "Fail", "N/A"]
34
+ },
35
+ {
36
+ "fieldName": "IssuesFound",
37
+ "fieldLabel": "Issues Found (select all that apply)",
38
+ "fieldType": "CheckboxGroup",
39
+ "isRequired": false,
40
+ "options": ["Corrosion", "Wear", "Leak", "Noise", "Vibration"]
41
+ },
42
+ {
43
+ "fieldName": "Notes",
44
+ "fieldLabel": "Notes",
45
+ "fieldType": "LongText",
46
+ "isRequired": false
47
+ },
48
+
49
+ { "section": "Sign-Off" },
50
+ {
51
+ "fieldName": "InspectorName",
52
+ "fieldLabel": "Inspector Name",
53
+ "fieldType": "Name",
54
+ "isRequired": true
55
+ },
56
+ {
57
+ "fieldName": "InspectionDate",
58
+ "fieldLabel": "Inspection Date",
59
+ "fieldType": "Date",
60
+ "isRequired": true
61
+ }
62
+ ]
63
+ }
64
+ }
@@ -0,0 +1,297 @@
1
+ # Field types reference
2
+
3
+ Mapping of intermediate-JSON `fieldType` to the runtime component used in the deployed Flow. The `Flow strategy` column is the `fieldType` value in the Flow `Metadata` JSON (see [flow-metadata-json.md](flow-metadata-json.md)). **All names here have been verified against a live Field Service org by retrieving real flows and deploying probe flows** (May 2026).
4
+
5
+ > **Picking a type:** classify from the actual control on the form, not from the field's label or name. A text line labeled "Signature" is `ShortText`. A textarea labeled "Photo of damage" is `LongText`. Only emit `Signature`, `UploadFile`, `UploadImage`, `FileView`, `Address`, `Matrix`, or `Repeater` when the source shows the corresponding widget (sign-here pad, file/camera picker, compound address, row-shared grid, user-added rows table) — or when the user explicitly describes that widget in prose. See the "control evidence" table in `extraction-prompt.md`.
6
+
7
+ ## Verified types
8
+
9
+ | `fieldType` | `extensionName` | Flow strategy |
10
+ |-----------------|------------------------------------------------|--------------------------|
11
+ | `ShortText` | `runtime_service_fieldservice:dcTextInput` | `ComponentInstance` |
12
+ | `LongText` | `runtime_service_fieldservice:dcLongText` | `ComponentInstance` |
13
+ | `Name` | `runtime_service_fieldservice:dcName` | `ComponentInstance` |
14
+ | `Email` | `runtime_service_fieldservice:dcEmail` | `ComponentInstance` |
15
+ | `Phone` | `runtime_service_fieldservice:dcPhone` | `ComponentInstance` |
16
+ | `Numeric` | `runtime_service_fieldservice:dcNumeric` | `ComponentInstance` |
17
+ | `Counter` | `runtime_service_fieldservice:dcCounter` | `ComponentInstance` (supports `min`, `max`, `value` numeric params) |
18
+ | `Date` | `runtime_service_fieldservice:dcDate` | `ComponentInstance` |
19
+ | `DateTime` | `runtime_service_fieldservice:dcDateTime` | `ComponentInstance` |
20
+ | `Checkbox` | `runtime_service_fieldservice:dcCheckbox` | `ComponentInstance` |
21
+ | `Toggle` | `runtime_service_fieldservice:dcToggle` | `ComponentInstance` |
22
+ | `Picklist` | `runtime_service_fieldservice:dcPicklist` | `ComponentChoice` |
23
+ | `Radio` | `runtime_service_fieldservice:dcRbGroup` | `ComponentChoice` (verified May 2026 via retrieved Inventory_Transfer flow) |
24
+ | `CheckboxGroup` | `runtime_service_fieldservice:dcCbGroup` | `ComponentMultiChoice` |
25
+ | `Signature` | `runtime_service_fieldservice:dcSignature` | `ComponentInstance` (auto-wires `parentRecordId` and `recordId` to the standard input variables) |
26
+ | `UploadFile` | `runtime_service_fieldservice:dcUpFile` | `ComponentInstance` (auto-wires `recordId` → `parentRecordId`) |
27
+ | `UploadImage` | `runtime_service_fieldservice:dcUpImage` | `ComponentInstance` (auto-wires `recordId` → `parentRecordId`) |
28
+ | `Images` | `runtime_service_fieldservice:dcImages` | `ComponentInstance` (gallery viewer, auto-wires `recordId` → `parentRecordId`) |
29
+ | `Address` | `runtime_service_fieldservice:dcAddress` | `ComponentInstance` (compound street/city/state/zip widget) |
30
+ | `Matrix` | `runtime_service_fieldservice:dcMatrix` | `ComponentMultiChoice` (column choices via `<choiceReferences>`; row labels via `questions` JSON-array input parameter) |
31
+ | `Lookup` | `runtime_service_fieldservice:dcLookup` | `ComponentInstance` (requires `lookupObject`; optional `lookupSearchFields`, `lookupMulti`) |
32
+ | `FileView` | `runtime_service_fieldservice:dcFileView` | `ComponentInstance` (requires `fileName` — static asset filename without extension) |
33
+ | `DisplayText` | (native — no extension) | native `DisplayText` |
34
+ | `Repeater` | (native — no extension; nested `<fields>`) | native `Repeater` (verified May 2026; supports any `ComponentInstance` child) |
35
+
36
+ ## Falls back to a placeholder
37
+
38
+ | `fieldType` | Falls back to | Why |
39
+ |--------------|---------------------------------------------|-----|
40
+ | `Lookup` *with no `lookupObject`* | `dcTextInput` w/ `[Lookup — set objectApiName in Flow Builder]` prefix | `dcLookup` deploys but won't render without an `objectApiName`. Supply `lookupObject` in the spec or the admin must wire it up in Flow Builder. |
41
+ | `FileView` *with no `fileName`* | `dcTextInput` w/ `[FileView — set fileName in Flow Builder]` prefix | `dcFileView` needs a static asset `fileName`. |
42
+
43
+ ## Required Flow boilerplate
44
+
45
+ A Data Capture Flow won't deploy without these keys in `Metadata`:
46
+
47
+ 1. **`environments`** must include `Offline`:
48
+ ```json
49
+ "environments": ["Offline"]
50
+ ```
51
+ 2. **Three input variables** (Text, Available for Input):
52
+ ```json
53
+ "variables": [
54
+ { "name": "parentObjectType", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false },
55
+ { "name": "parentRecordId", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false },
56
+ { "name": "recordId", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false }
57
+ ]
58
+ ```
59
+ 3. **`processType`** must be `DataCaptureFlow`.
60
+
61
+ ## Choice/MultiChoice fields
62
+
63
+ For `Picklist`, `Radio` (`dcRbGroup`), and `CheckboxGroup`, options are NOT inline parameters. They are top-level `choices` entries referenced from the field via a `choiceReferences` array:
64
+
65
+ ```json
66
+ "choices": [
67
+ { "name": "Good", "choiceText": "Good", "dataType": "String", "value": { "stringValue": "Good" } }
68
+ ]
69
+ ```
70
+ ```json
71
+ {
72
+ "name": "overallCondition",
73
+ "choiceReferences": ["Good", "Fair", "Poor"],
74
+ "extensionName": "runtime_service_fieldservice:dcPicklist",
75
+ "fieldText": "Overall Condition",
76
+ "fieldType": "ComponentChoice",
77
+ "inputsOnNextNavToAssocScrn": "UseStoredValues",
78
+ "isRequired": true,
79
+ "storeOutputAutomatically": true
80
+ }
81
+ ```
82
+
83
+ Dedupe choices across the whole flow — two fields with `["Good","Fair","Poor"]` share the same three `choices` entries.
84
+
85
+ ## Repeater fields
86
+
87
+ `Repeater` is a native Flow field type — not a component. The JSON shape (children are a nested `fields` array):
88
+
89
+ ```json
90
+ {
91
+ "name": "Part",
92
+ "fieldType": "Repeater",
93
+ "fields": [
94
+ { "name": "Quantity", "extensionName": "runtime_service_fieldservice:dcCounter", "fieldType": "ComponentInstance" },
95
+ { "name": "Part_Number", "extensionName": "runtime_service_fieldservice:dcTextInput", "fieldType": "ComponentInstance" }
96
+ ],
97
+ "isRequired": false,
98
+ "styleProperties": { "verticalAlignment": { "stringValue": "top" }, "width": { "stringValue": "12" } }
99
+ }
100
+ ```
101
+
102
+ In the spec, supply children as `repeaterFields`:
103
+
104
+ ```json
105
+ {
106
+ "fieldName": "Part",
107
+ "fieldLabel": "Parts",
108
+ "fieldType": "Repeater",
109
+ "isRequired": false,
110
+ "repeaterFields": [
111
+ { "fieldName": "Quantity", "fieldLabel": "Quantity", "fieldType": "Counter", "isRequired": true, "min": 1, "value": 1 },
112
+ { "fieldName": "Part_Number", "fieldLabel": "Part Number", "fieldType": "ShortText", "isRequired": true },
113
+ { "fieldName": "Part_Description", "fieldLabel": "Part Description", "fieldType": "ShortText", "isRequired": true }
114
+ ]
115
+ }
116
+ ```
117
+
118
+ The runtime exposes the captured rows as the collection `<RepeaterName>.AddedItems`, with each row's child accessible as `<loopVar>.<ChildName>.value` inside a Loop element. See `flow-metadata-json.md` for the loop/createRecord pattern.
119
+
120
+ ## Counter min/max/value
121
+
122
+ `dcCounter` accepts these optional numeric input parameters: `min`, `max`, `value` (initial value). In the spec:
123
+
124
+ ```json
125
+ {
126
+ "fieldName": "Quantity",
127
+ "fieldLabel": "Quantity",
128
+ "fieldType": "Counter",
129
+ "isRequired": true,
130
+ "min": 1,
131
+ "max": 999,
132
+ "value": 1
133
+ }
134
+ ```
135
+
136
+ ## Specialized component spec keys
137
+
138
+ ### Signature / UploadFile / UploadImage / Images
139
+
140
+ Auto-wired — no extra spec keys needed. Inject:
141
+ - `Signature` → `parentRecordId` and `recordId` input parameters, both as `{ "elementReference": ... }` to the flow's standard input variables of the same name.
142
+ - `UploadFile` / `UploadImage` / `Images` → `recordId` input parameter as `{ "elementReference": "parentRecordId" }` (the runtime attaches the captured file/image to the parent record passed in via `parentRecordId`).
143
+
144
+ These standard input variables are present on every flow:
145
+
146
+ ```json
147
+ "variables": [
148
+ { "name": "parentObjectType", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false },
149
+ { "name": "parentRecordId", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false },
150
+ { "name": "recordId", "dataType": "String", "isCollection": false, "isInput": true, "isOutput": false }
151
+ ]
152
+ ```
153
+
154
+ So `Signature` / `UploadFile` / `UploadImage` / `Images` deploy and run end-to-end as long as the flow is launched from a standard Field Service entry point (Mobile App, Work Order, Asset, etc.) that supplies `parentRecordId`.
155
+
156
+ ### Address
157
+
158
+ No extra spec keys. Renders as `dcAddress` ComponentInstance with the field label.
159
+
160
+ ### Matrix
161
+
162
+ ```json
163
+ {
164
+ "fieldName": "PreTripChecklist",
165
+ "fieldLabel": "Pre-trip checklist",
166
+ "fieldType": "Matrix",
167
+ "isRequired": true,
168
+ "options": ["OK", "NOK", "N/A"],
169
+ "matrixRows": ["Tires", "Lights", "Brakes", "Fluids"]
170
+ }
171
+ ```
172
+
173
+ - `options` become column choices (`<choiceReferences>`), exactly like Picklist.
174
+ - `matrixRows` become per-row prompts, JSON-encoded into the `questions` input parameter as a string array.
175
+
176
+ ### Lookup
177
+
178
+ ```json
179
+ {
180
+ "fieldName": "AssetLookup",
181
+ "fieldLabel": "Asset",
182
+ "fieldType": "Lookup",
183
+ "isRequired": true,
184
+ "lookupObject": "Asset",
185
+ "lookupSearchFields": "Name, SerialNumber",
186
+ "lookupMulti": false
187
+ }
188
+ ```
189
+
190
+ - `lookupObject` (required) — the object API name to look up against.
191
+ - `lookupSearchFields` — comma-separated field API names searched by typeahead.
192
+ - `lookupMulti` (or `isMultiSelection`) — `true` to allow selecting multiple records.
193
+
194
+ If `lookupObject` is missing, the field renders as a labeled ShortText placeholder so the flow still deploys.
195
+
196
+ ### FileView
197
+
198
+ ```json
199
+ {
200
+ "fieldName": "ManualPreview",
201
+ "fieldLabel": "Manual",
202
+ "fieldType": "FileView",
203
+ "fileName": "service_manual_v3"
204
+ }
205
+ ```
206
+
207
+ `fileName` is the static-asset filename (without extension). If missing, falls back to a labeled ShortText placeholder.
208
+
209
+ ## Visibility rules
210
+
211
+ A field can be conditionally shown based on a previously-captured field. The spec shape:
212
+
213
+ ```json
214
+ {
215
+ "fieldName": "Work_Order_Number",
216
+ "fieldLabel": "Work Order Number",
217
+ "fieldType": "ShortText",
218
+ "isRequired": true,
219
+ "visibility": {
220
+ "field": "To",
221
+ "operator": "EqualTo",
222
+ "value": "Work Order"
223
+ }
224
+ }
225
+ ```
226
+
227
+ Look up the matching choice api name (e.g. `Work_Order`) and emit a `visibilityRule` on the field:
228
+
229
+ ```json
230
+ "visibilityRule": {
231
+ "conditionLogic": "and",
232
+ "conditions": [
233
+ { "leftValueReference": "Work_Order", "operator": "EqualTo", "rightValue": { "booleanValue": true } }
234
+ ]
235
+ }
236
+ ```
237
+
238
+ > Note: Field Service's runtime evaluates visibility against the choice's *boolean selection state*, not the parent field's string value. The `leftValueReference` is therefore the **choice api name**, not the field name. If `visibility.value` doesn't match any known choice, warn and skip the rule.
239
+
240
+ ## Field name rules
241
+
242
+ - `fieldName` must match `^[A-Za-z][A-Za-z0-9_]*$`, ≤ 80 chars, unique per flow.
243
+ - Choice api names are derived from the option's display text (sanitized).
244
+ - Screen api names are derived as `Screen_<PascalCaseScreenKey>`.
245
+
246
+ ## Sections
247
+
248
+ A Section is a visual grouping inside a screen, rendered as a Salesforce Flow `RegionContainer` (one full-width Region column) with a header bar showing the section label. Use sections **only when the source explicitly shows them** (visible group headers in an image/PDF, or the user describing named sub-sections in prose). A flat field list is the right default.
249
+
250
+ To declare sections, mix section-header items into a screen's field list. A section header is an item with a `section` key and **no** `fieldName`:
251
+
252
+ ```json
253
+ {
254
+ "screens": {
255
+ "AssetInspection": [
256
+ { "section": "Asset Details" },
257
+ { "fieldName": "AssetName", "fieldLabel": "Asset Name", "fieldType": "ShortText" },
258
+ { "fieldName": "Manufacturer", "fieldLabel": "Manufacturer", "fieldType": "Picklist", "options": ["Demag","Konecranes"] },
259
+
260
+ { "section": "Inspection" },
261
+ { "fieldName": "Condition", "fieldLabel": "Condition", "fieldType": "Picklist", "options": ["Pass","Fail"] },
262
+ { "fieldName": "Notes", "fieldLabel": "Notes", "fieldType": "LongText" }
263
+ ]
264
+ }
265
+ }
266
+ ```
267
+
268
+ Rules:
269
+ - A `section` item starts a new section. All subsequent fields belong to it until the next `section` item or the end of the screen.
270
+ - Fields appearing **before** the first `section` item are bucketed into an implicit section labeled `"General"`.
271
+ - Specs with no `section` items deploy as a flat field list — fully backward-compatible.
272
+ - Sections are **single-column, full-width** by default. Multi-column layouts are not generated; if a source shows two columns, file each field separately and let it stack.
273
+ - Section api names are auto-derived from the label (`Sec_<sanitized>`, deduped within the screen).
274
+
275
+ The emitted JSON matches the verified `SectionWithHeader` pattern from `salesforce-data-capture/examples/Data_Capture_All_Components.flow-meta.xml`:
276
+
277
+ ```json
278
+ {
279
+ "name": "Sec_Asset_Details",
280
+ "fieldText": "Asset Details",
281
+ "fieldType": "RegionContainer",
282
+ "fields": [
283
+ {
284
+ "name": "Sec_Asset_Details_Col1",
285
+ "fieldType": "Region",
286
+ "fields": [ /* AssetName, Manufacturer, etc. */ ],
287
+ "inputParameters": [
288
+ { "name": "width", "value": { "stringValue": "12" } }
289
+ ],
290
+ "isRequired": false
291
+ }
292
+ ],
293
+ "isRequired": false,
294
+ "regionContainerType": "SectionWithHeader",
295
+ "styleProperties": {}
296
+ }
297
+ ```