@@ -29,7 +29,12 @@ enum VariableType {
2929 map,
3030
3131 /// Image type. Represents an image URL.
32- image;
32+ image,
33+
34+ /// One of a set of named options ([VariableData.choiceOptions] ), stored as
35+ /// the option's value; e.g. the state a variance node shows, by its id, so
36+ /// renaming the state keeps it.
37+ choice;
3338
3439 /// Returns a string representation of the variable type.
3540 String get label => switch (this ) {
@@ -41,6 +46,7 @@ enum VariableType {
4146 VariableType .list => 'List' ,
4247 VariableType .map => 'Map' ,
4348 VariableType .image => 'Image' ,
49+ VariableType .choice => 'Choice' ,
4450 };
4551
4652 factory VariableType .fromObjectType (Object obj) {
@@ -61,6 +67,9 @@ enum VariableType {
6167 };
6268 }
6369
70+ /// Whether the variable type is [VariableType.choice] .
71+ bool get isChoice => this == VariableType .choice;
72+
6473 /// Whether the variable type is [VariableType.map] .
6574 bool get isMap => this == VariableType .map;
6675
@@ -106,6 +115,30 @@ class VariableData
106115 /// Whether the variable has a value or not.
107116 bool get hasValue => value.isNotEmpty;
108117
118+ /// The `extra` key of a [VariableType.choice] variable's options.
119+ static const String optionsKey = 'options' ;
120+
121+ /// The options of a [VariableType.choice] variable: each a value and the
122+ /// label shown for it. Options stored as plain text are their own label.
123+ List <({String value, String label})> get choiceOptions => [
124+ for (final Object ? option in (extra[optionsKey] as List ? ) ?? const [])
125+ switch (option) {
126+ Map () when option['value' ] != null => (
127+ value: '${option ['value' ]}' ,
128+ label: '${option ['label' ] ?? option ['value' ]}' ,
129+ ),
130+ _ => (value: '$option ' , label: '$option ' ),
131+ },
132+ ];
133+
134+ /// The label of the option this variable's [value] picks, or the value.
135+ String get choiceLabel =>
136+ choiceOptions
137+ .where ((option) => option.value == value)
138+ .map ((option) => option.label)
139+ .firstOrNull ??
140+ value;
141+
109142 /// Type of the variable. This is used to determine how to parse the value.
110143 @JsonKey (unknownEnumValue: VariableType .text)
111144 final VariableType type;
@@ -175,7 +208,7 @@ class VariableData
175208 /// A text variable returns its value as is, so one holding an empty string
176209 /// stays an empty string and compares equal to `''` in conditions.
177210 Object ? getValue () => switch (type) {
178- VariableType .text => value,
211+ VariableType .text || VariableType .choice => value,
179212 VariableType .image => value.isEmpty ? null : value,
180213 VariableType .integer => num .tryParse (value).toInt (),
181214 VariableType .decimal => num .tryParse (value).toDouble (),
@@ -200,6 +233,7 @@ String? sanitizeValueForVariableType(Object? value, VariableType type) {
200233 switch (type) {
201234 case VariableType .text:
202235 case VariableType .image:
236+ case VariableType .choice:
203237 return value.toString ();
204238 case VariableType .integer:
205239 return num .tryParse (value.toString ()).toInt ()? .toString ();
0 commit comments