generator_annotations

auto-webclient grammar version yar.11

  1. Generator Contracts
    1. Default
    2. Handheld
    3. Production
  2. Annotations
    1. Global Features
    2. Handheld Menu
    3. Sparse Annotation Tree
      1. Navigation expressions
      2. Annotation Node
      3. Handheld

Generator Contracts

Default

The default generator.

global-features
	'full screen planning' {
		'default zoom level': feature 'zoom level'
		'has more zoom levels': stategroup @default: 'no' (
			'yes' {
				'zoom levels': list non-empty {
					'zoom level': feature 'zoom level'
				}
			}
			'no' { }
		)
		'windows': list non-empty {
			'label': text
			'window': feature 'planning'
		}
	}

	'dashboard' {
		'dashboard': feature 'dashboard 2'
	}

node-features
	'dimension' component unbound {
		'dimension': stategroup @default: 'default' (
			'custom' {
				'width': number
				'height': number
			}
			'default' { }
		)
	}

	'margin' component unbound {
		'margin': stategroup @default: 'default' (
			'custom' {
				'top': number
				'right': number
				'bottom': number
				'left': number
			}
			'default' { }
		)
	}

	'color' component unbound {
		'color': stategroup @default: 'auto' (
			'auto' { }
			'blue' { }
			'orange' { }
			'green' { }
			'red' { }
			'black' { }
			'grey' { }
			'grey light' { }
			'grey dark' { }
			'teal' { }
			'purple' { }
			'hex' {
				'value': text
			}
		)
	}

	'range' {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'range start': stategroup (
			'static' {
				'value': number
			}
			'dynamic' {
				'value': number binding { }
			}
		)
		'ranges': list {
			'type': stategroup (
				'green' { }
				'blue' { }
				'orange' { }
				'red' { }
			)
			'range size': stategroup (
				'static' {
					'value': number
				}
				'dynamic' {
					'value': number binding { }
				}
			)
		}
		'value': number binding { }
		'style': stategroup (
			'progress bar' { }
			'gauge' { }
		)
	}

	'pie chart' {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'query': query binding {
			'label': query text binding { }
			'property': query number binding { }
			'merge small slices': stategroup (
				'yes' {
					'below percentage': number
				}
				'no' { }
			)
			'sorting': stategroup (
				'yes' {
					'direction': stategroup (
						'ascending' { }
						'descending' { }
					)
				}
				'no' { }
			)
		}
	}

	'bar chart' {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'query': query binding {
			'label': query text binding { }
			'style': stategroup (
				'grouped' {
					'bars': list {
						'property': query number binding { }
						'color': feature 'color'
					}
				}
				'stacked' {
					'bars': list {
						'property': query number binding { }
						'color': feature 'color'
					}
				}
				'bar' {
					'property': query number binding { }
				}
			)
			'sorting': stategroup (
				'yes' {
					'direction': stategroup (
						'ascending' { }
						'descending' { }
					)
					'axis': stategroup (
						'single' {
							'sort': query number binding { }
						}
						'sum' { }
					)
				}
				'no' { }
			)
		}
	}

	'line chart query' component query {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'label': query text binding { }
		'lines': list {
			'property': query number binding { }
			'color': feature 'color'
		}
		'style': stategroup (
			'line' { }
			'area' { }
		)
		'sort': query number binding {
			'direction': stategroup (
				'ascending' { }
				'descending' { }
			)
		}
	}

	'chart value' component query {
		'type': stategroup (
			'text' {
				'property': query text binding { }
			}
			'number' {
				'property': query number binding { }
			}
		// TODO 'state group' {
		// 	'property': query stategroup binding { }
		// }
		)
	}

	'2d chart query' component query {
		'title': text
		'x': feature 'chart value'
		'x label': stategroup @default: 'auto' (
			'auto' { }
			'text' {
				'property': query text binding { }
			}
		)
		'format x': stategroup @default: 'auto' (
			'auto' { }
			'day' { }
			'month' { }
			'month and year' { }
			'week' { }
			'week and year' { }
			'custom' {
				'parts': list non-empty {
					'type': stategroup (
						'abbreviated weekday name' { }
						'full weekday name' { }
						'abbreviated month name' { }
						'full month name' { }
						'the locale’s date and time' { }
						'zero-padded day of the month' { }
						'space-padded day of the month' { }
						'microseconds' { }
						'ISO 8601 week-based year without century' { }
						'ISO 8601 week-based year with century' { }
						'hour (24-hour clock)' { }
						'hour (12-hour clock)' { }
						'day of the year' { }
						'month' { }
						'minute' { }
						'milliseconds' { }
						'either AM or PM' { }
						'quarter of the year' { }
						'milliseconds since UNIX epoch' { }
						'seconds since UNIX epoch' { }
						'second' { }
						'Monday-based (ISO 8601) weekday' { }
						'Sunday-based week of the year' { }
						'ISO 8601 week of the year' { }
						'Sunday-based weekday' { }
						'Monday-based week of the year' { }
						'the locale’s date' { }
						'the locale’s time' { }
						'year without century' { }
						'year with century' { }
						'time zone offset' { }
						'percent sign' { }
						'text' {
							'value': text
						}
					)
				}
			}
		)
		'size': stategroup @default: 'small' (
			'small' { }
			'medium' { }
			'large' { }
		)
		'bar mode': stategroup @default: 'grouped' (
			'grouped' { }
			'stacked' { }
		)
		'lines': list {
			'name': text @default: ""
			'y': query number binding { }
			/// setting `y aggregate` switches the default `sum` function to handle multiple y
			/// values on the same x value.
			'y aggregate': stategroup @default: 'sum' (
				'sum' { }
				'minimum' { }
				'maximum' { }
				'average' { }
			)
			'color': stategroup @default: 'auto' (
				'auto' { }
				'custom' {
					'color': text
				}
			)
			'style': stategroup @default: 'line' (
				'line' {
					'stack': stategroup @default: 'no' (
						'no' { }
						'yes' { }
					)
					'shape': stategroup @default: 'linear' (
						'linear' { }
						'horizontal vertical' { }
						'vertical horizontal' { }
						'horizontal vertical horizontal' { }
						'vertical horizontal vertical' { }
						'spline' { }
					)
					'dash': stategroup @default: 'solid' (
						'solid' { }
						'dot' { }
						'dash dot' { }
						'long dash dot' { }
					)
				}
				'area' { }
				'bar' { }
			)
			'partition': stategroup @default: 'no' (
				'no' { }
				'yes' {
					'value': query text binding { }
					'color': stategroup @default: 'auto' (
						'auto' { }
						'custom' {
							'color': query text binding { }
						}
					)
				}
			)
		}
	}

	'line chart' {
		'query': query binding {
			'chart': feature 'line chart query'
		}
	}

	'scatter chart' {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'query': query binding {
			'label': query text binding { }
			'x label': text
			'x property': query number binding { }
			'y label': text
			'y property': query number binding { }
			'style': stategroup (
				'dot' { }
				'connected dot' {
					'sort': query number binding {
						'direction': stategroup (
							'ascending' { }
							'descending' { }
						)
					}
				}
				'bubble' {
					'z property': query number binding { }
				}
			)
		}
	}

	'radar chart' {
		'dimension': feature 'dimension'
		'margin': feature 'margin'
		'query': query binding {
			'label': query text binding { }
			'values': list {
				'property': query number binding { }
			}
			'style': stategroup (
				'spider' { }
				'radar' { }
			)
		}
	}

	'dashboard' {
		'cell width': number
		'cell height': number
		'grid gap': stategroup @default: 'yes' (
			'yes' {
				'size': number @default: 20
			}
			'no' { }
		)
		'widgets': list {
			'x': number
			'width': number
			'y': number
			'height': number
			'widget': stategroup (
				'number' {
					'value': number binding { }
					'number size': stategroup (
						'large' { }
						'fixed' {
							'value': number
						}
					)
					'unit size': stategroup @default: 'auto' (
						'auto' { }
						'fixed' {
							'value': number
						}
					)
				}
				'range' {
					'range': feature 'range'
				}
				'pie chart' {
					'chart': feature 'pie chart'
				}
				'bar chart' {
					'chart': feature 'bar chart'
				}
				'line chart' {
					'chart': feature 'line chart'
				}
				'scatter chart' {
					'chart': feature 'scatter chart'
				}
				'radar chart' {
					'chart': feature 'radar chart'
				}
				'legend' {
					'binding': stategroup (
						'static' {
							'values': list {
								'label': text
								'color': feature 'color'
							}
						}
						'dynamic' {
							'query': query binding {
								'label': query text binding { }
							}
						}
					)
				}
			)
		}
	}

	'dashboard 2' {
		'widgets': list {
			'type': stategroup (
				'grouped charts' {
					'query': query binding {
						'charts': list {
							'widget': stategroup (
								'2d chart' {
									'chart': feature '2d chart query'
								}
								'table' {
									'title': text
									'size': stategroup @default: 'small' (
										'small' { }
										'medium' { }
										'large' { }
									)
									'properties': list {
										'property': query property binding { }
									}
								}
							)
						}
					}
				}
				'tabs' {
					'widgets': list {
						'name': text
						'widget': feature 'dashboard 2'
					}
				}
			)
		}
	}

	'label' component {
		'parts': list non-empty {
			'type': stategroup (
				'static text' {
					'text': text
				}
				'dynamic text' {
					'text': text binding { }
				}
				'dynamic number' {
					'number': number binding { }
				}
			)
		}
	}

	'query label' component query {
		'parts': list non-empty {
			'type': stategroup (
				'static text' {
					'text': text
				}
				'dynamic text' {
					'text': text binding { }
				}
				'query text' {
					'text': query text binding { }
				}
				'dynamic number' {
					'number': number binding { }
				}
				'query number' {
					'number': query number binding { }
				}
			)
		}
	}

	'planning' component {
		'rows': query binding {
			'label': feature 'query label'
			'options': feature 'row options'
			'items': query binding {
				'label': feature 'query label'
				'start': query number requires filter binding { }
				'end': query number requires filter binding { }
				'options': feature 'item options'
			}
		}
	}

	'row options' component query {
		'has filters': stategroup @default: 'no' (
			'yes' {
				'filters': list non-empty {
					'label': text
					'type': stategroup (
						'number' {
							'number': query number requires filter binding { }
						}
						'text' {
							'text': query text requires filter binding { }
						}
						'stategroup' {
							'stategroup': query stategroup requires filter binding { }
						}
					)
				}
			}
			'no' { }
		)
		'has tooltip': stategroup @default: 'no' (
			'yes' {
				'label': feature 'query label'
			}
			'no' { }
		)
		'has group': stategroup @default: 'no' (
			'yes' {
				'group': query text binding { }
			}
			'no' { }
		)
		'has children': stategroup @default: 'no' (
			'yes' {
				'rows': feature 'planning'
			}
			'no' { }
		)
		'filter start and end': stategroup @default: 'no' (
			'yes' {
				'start': query number requires filter binding { }
				'end': query number requires filter binding { }
			}
			'no' { }
		)
		'has popup': stategroup @default: 'no' (
			'yes' {
				'popup': feature 'popup'
			}
			'no' { }
		)
	}

	'item options' component query {
		'has filters': stategroup @default: 'no' (
			'yes' {
				'filters': list non-empty {
					'label': text
					'type': stategroup (
						'number' {
							'number': query number requires filter binding { }
						}
						'text' {
							'text': query text requires filter binding { }
						}
						'stategroup' {
							'stategroup': query stategroup requires filter binding { }
						}
					)
				}
			}
			'no' { }
		)
		'has tooltip': stategroup @default: 'no' (
			'yes' {
				'label': feature 'query label'
			}
			'no' { }
		)
		'draggable': stategroup @default: 'no' (
			'yes' {
				'move': command binding {
					'start': number binding { }
					'can switch row': stategroup @default: 'no' (
						'yes' {
							'row': text binding { }
						}
						'no' { }
					)
					'can be dropped on item': stategroup @default: 'no' (
						'yes' {
							'item': text binding { }
						}
						'no' { }
					)
				}
				'has alternative move command': stategroup @default: 'no' (
					'yes' {
						'move': command binding {
							'start': number binding { }
							'can switch row': stategroup @default: 'no' (
								'yes' {
									'row': text binding { }
								}
								'no' { }
							)
							'can be dropped on item': stategroup @default: 'no' (
								'yes' {
									'item': text binding { }
								}
								'no' { }
							)
						}
					}
					'no' { }
				)
			}
			'no' { }
		)
		'has popup': stategroup @default: 'no' (
			'yes' {
				'popup': feature 'popup'
			}
			'no' { }
		)
		'has icon bar': stategroup @default: 'no' (
			'yes' {
				'stategroups': list non-empty {
					'stategroup': stategroup binding {
						'states': list {
							'state': state binding {
								'has tooltip': stategroup @default: 'no' (
									'yes' {
										'label': feature 'label'
									}
									'no' { }
								)
							}
						}
					}
				}
			}
			'no' { }
		)
	}

	'zoom level' component unbound {
		'name': text
		'days before today': number
		'days after today': number
		'tag interval': number
		'snap': stategroup (
			'none' { }
			'minute' {
				'minutes': number
			}
			'day' { }
			'week' { }
			'month' { }
			'year' { }
		)
		'width': number
		'date tags size': stategroup (
			'm' { }
			's' { }
			'xs' { }
		)
		'round off to day': stategroup (
			'yes' { }
			'no' { }
		)
	}

	'popup' component {
		'label': feature 'label'
		'node': feature 'node'
		'has open view button': stategroup (
			'yes' {
				'label': text
			}
			'no' { }
		)
	}

	'node' component {
		'entries': list non-empty {
			'type': stategroup (
				'number' {
					'number': number binding { }
				}
				'text' {
					'text': text binding { }
				}
				'stategroup' {
					'stategroup': stategroup binding {
						'states': list {
							'state': state binding {
								'has node': stategroup @default: 'no' (
									'yes' {
										'node': feature 'node'
									}
									'no' { }
								)
							}
						}
					}
				}
				'file' {
					'file': file binding { }
				}
				'command' {
					'command': command binding { }
				}
				'query' {
					'label': feature 'label'
					'query': query binding { }
				}
				// 'planning' {
				// 	'planning': feature 'planning'
				// }
				'chart' {
					'label': feature 'label'
					'type': stategroup (
						'range' {
							'range': feature 'range'
						}
						'pie chart' {
							'chart': feature 'pie chart'
						}
						'bar chart' {
							'chart': feature 'bar chart'
						}
						'line chart' {
							'chart': feature 'line chart'
						}
						'scatter chart' {
							'chart': feature 'scatter chart'
						}
						'radar chart' {
							'chart': feature 'radar chart'
						}
					)
				}
			)
		}
	}

collection-features

stategroup-features

number-features

text-features

file-features

Handheld

The handheld generator.

global-features

node-features

collection-features

stategroup-features

number-features

text-features

file-features

Production

The production generator.

global-features

node-features

collection-features

stategroup-features

number-features

text-features

file-features

Annotations

Global Features

Configure global features provided by the selected generator.

'has global features': stategroup (
	'yes' {
		'configured features': dictionary { [ feature ]
			'has more features': stategroup = node-switch successor (
				| node = 'yes' { 'next feature' = successor }
				| none = 'no'
			)
			'feature': component 'feature'
		}
	}
	'no' { }
)

Handheld Menu

'handheld menu': stategroup (
	'yes' { [ handheld-menu (, ) ]
		'items': dictionary {
			'icon': [ icon: ] text
			'view': component 'handheld view selector'
			'has more items': stategroup = node-switch successor (
				| node = 'yes' { 'next item' = successor }
				| none = 'no'
			)
		}
	}
	'no' { }
)

Sparse Annotation Tree

The root node of the annotations.

'annotations': component 'extended annotations'
'singular path' {
	'has steps': stategroup (
		'yes' {
			'type': stategroup (
				'group' {
					'group': [ . ] reference
				}
			)
			'tail': component 'singular path'
		}
		'no' { }
	)
}
'conditional path' {
	'head': component 'singular path'
	'has steps': stategroup (
		'yes' {
			'type': stategroup (
				'state' {
					'state group': [ . ] reference
					'state': [ ? ] reference
				}
			)
			'tail': component 'conditional path'
		}
		'no' { }
	)
}
'collection path' {
	'head': component 'conditional path'
	'collection': [ ., [] ] reference
	'has more steps': stategroup (
		'yes' {
			'tail': component 'collection path'
		}
		'no' { }
	)
}
'query path' {
	'has steps': stategroup (
		'yes' {
			'type': stategroup (
				'parent' { [ ^ ] }
				'reference' {
					'reference': [ > ] reference
					'result': stategroup (
						'referenced node' { }
						'rule' {
							'rule': [ $ ] reference
						}
					)
				}
				'group' {
					'group': [ + ] reference
				}
				'state' {
					'state group': [ ? ] reference
					'state': [ | ] reference
				}
			)
			'tail': component 'query path'
		}
		'no' { }
	)
}

Annotation Node

'extended annotations' { [ (, ) ]
	'node features': component 'features matrix'
	'has handheld frames': stategroup (
		'yes' {
			'handheld frames': dictionary { [ handheld: ]
				'frame': component 'handheld view frame'
			}
			'main frame': reference = first
		}
		'no' { }
	)
	'properties': dictionary {
		'type': [ : ] stategroup (
			'command' { [ command ]
				'annotations': component 'extended annotations'
			}
			'action' { [ action ]
				'annotations': component 'extended annotations'
			}
			'group' { [ group ]
				'annotations': component 'extended annotations'
			}
			'reference set' { [ reference-set ]
				'has custom queries': stategroup (
					'yes' {
						'custom queries': dictionary { [ query ]
							'has more queries': stategroup = node-switch successor (
								| node = 'yes' { 'next query' = successor }
								| none = 'no'
							)
							'query': component 'custom query'
						}
					}
					'no' { }
				)
			}
			'collection' { [ collection ]
				'entries are custom properties': stategroup (
					'yes' { [ @properties ]
						'type': stategroup (
							'value' {
								'value attribute': [ value: ] reference
							}
							'node' { [ node ] }
						)
					}
					'no' { }
				)
				'show as list': stategroup (
					'yes' { [ @list: ]
						'property': [ . ] reference
					}
					'no' { }
				)
				'has custom queries': stategroup (
					'yes' {
						'custom queries': dictionary { [ query ]
							'has more queries': stategroup = node-switch successor (
								| node = 'yes' { 'next query' = successor }
								| none = 'no'
							)
							'query': component 'custom query'
						}
					}
					'no' { }
				)
				'collection features': component 'features matrix'
				'sub tree': stategroup (
					'yes' {
						'annotations': component 'extended annotations'
					}
					'no' { }
				)
			}
			'stategroup' { [ stategroup ]
				'stategroup features': component 'features matrix'
				'states': [ (, ) ] dictionary { [ | ]
					'annotations': component 'extended annotations'
				}
			}
			'number' { [ number ]
				'number features': component 'features matrix'
			}
			'text' { [ text ]
				'text features': component 'features matrix'
			}
			'file' { [ file ]
				'file features': component 'features matrix'
			}
		)
	}
}
'features matrix' {
	'configured features': dictionary { [ feature ]
		'has more features': stategroup = node-switch successor (
			| node = 'yes' { 'next feature' = successor }
			| none = 'no'
		)
		'feature': component 'feature'
	}
}
'feature' {
	'properties': component 'feature properties'
}
'feature properties' {
	'properties': [ (, ) ] dictionary {
		'type': [ = ] stategroup (
			'binding' {
				'type': stategroup (
					'user' { [ user ] }
					'collection' { [ collection ]
						'path': component 'query path'
						'collection': [ . ] reference
					}
					'stategroup' { [ stategroup ]
						'path': component 'query path'
						'stategroup': [ . ] reference
					}
					'state' { [ state ]
						'state': reference
					}
					'number' { [ number ]
						'path': component 'query path'
						'number': [ . ] reference
					}
					'text' { [ text ]
						'path': component 'query path'
						'text': [ . ] reference
					}
					'file' { [ file ]
						'path': component 'query path'
						'file': [ . ] reference
					}
					'command' { [ command ]
						'path': component 'query path'
						'command': [ . ] reference
					}
					'action' { [ action ]
						'path': component 'query path'
						'action': [ . ] reference
					}
					'query' { [ query ]
						'path': component 'collection path'
						'query': component 'custom query'
					}
					'query property' { [ query property ]
						'property': reference
					}
					'query stategroup' { [ query stategroup ]
						'property': reference
					}
					'query number' { [ query number ]
						'property': reference
					}
					'query text' { [ query text ]
						'property': reference
					}
					'query file' { [ query file ]
						'property': reference
					}
				)
				'properties': component 'feature properties'
			}
			'configuration' {
				'type': stategroup (
					'list' {
						'properties': [ [, ] ] component 'feature properties list'
					}
					'stategroup' {
						'state': reference
						'properties': component 'feature properties'
					}
					'number' {
						'value': integer
					}
					'text' {
						'value': text
					}
				)
			}
			'feature' {
				'properties': component 'feature properties'
			}
		)
	}
}
'feature properties list' {
	'has entry': stategroup (
		'yes' {
			'entry': component 'feature properties'
			'tail': component 'feature properties list'
		}
		'no' { }
	)
}
'custom query' {
	'custom limit': stategroup (
		'yes' { [ limit: ]
			'sample': stategroup (
				'yes' {
					'sample size': integer
					'sample limit': [ /, / ] integer
				}
				'no' { }
			)
			'absolute limit': integer
		}
		'no' { }
	)
	'properties': [ [, ] ] dictionary {
		'has more properties': stategroup = node-switch successor (
			| node = 'yes' { 'next property' = successor }
			| none = 'no'
		)
		'context path': [ -> ] component 'query path'
		'type': [ : ] stategroup (
			'stategroup' { [ stategroup ]
				'property': reference
				'filter': stategroup (
					'yes' { [ filter ]
						'states': [ ? ] dictionary { [ | ]
							'is selected': stategroup (
								'yes' { [ selected ] }
								'no' { }
							)
						}
					}
					'simple' { [ filter simple ] }
					'no' { }
				)
			}
			'number' { [ number ]
				'property': reference
				'filter': stategroup (
					'yes' { [ filter ]
						'operator': stategroup (
							'smaller' { [ < ] }
							'smaller equal' { [ <= ] }
							'greater' { [ > ] }
							'greater equal' { [ >= ] }
							'equal' { [ == ] }
						)
						'criteria': stategroup (
							'now' { [ now ]
								'offset': [ + ] integer
							}
							'static' {
								'value': integer
							}
						)
					}
					'simple' { [ filter simple ] }
					'no' { }
				)
			}
			'text' { [ text ]
				'property': reference
				'filter': stategroup (
					'yes' { [ filter ]
						'criteria': text
					}
					'simple' { [ filter simple ] }
					'containment' { [ filter, selection ]
						'operator': stategroup (
							'in' { [ in ] }
							'not in' { [ not in ] }
						)
					}
					'no' { }
				)
			}
			'file' { [ file ]
				'property': reference
			}
			'action' { [ action ]
				'attribute': reference
			}
			'command' { [ command ]
				'attribute': reference
			}
		)
	}
	'custom sorting': stategroup (
		'yes' {
			'direction': stategroup (
				'ascending' { [ @ascending: ] }
				'descending' { [ @descending: ] }
			)
			'type': stategroup (
				'number' {
					'number': [ # ] reference
				}
				'text' {
					'text': [ . ] reference
				}
			)
		}
		'no' { }
	)
}

Handheld

'annotated collection selector' {
	'has step': stategroup (
		'yes' {
			'property': [ . ] reference
			'type': stategroup (
				'group' { }
				'collection' { [ [] ] }
				'state' {
					'state': [ ? ] reference
				}
			)
			'tail': component 'annotated collection selector'
		}
		'no' {
			'property': [ ., [] ] reference
		}
	)
}
'handheld frame selector' {
	'type': stategroup (
		'inline' {
			'frame': component 'handheld view frame'
		}
		'annotated' {
			'frame': reference
		}
	)
}
'handheld view details' {
	'title': stategroup (
		'yes' {
			'property': [ title: ] component 'handheld view descriptor'
		}
		'no' { }
	)
	'fields': dictionary {
		'has more fields': stategroup = node-switch successor (
			| node = 'yes' { 'next field' = successor }
			| none = 'no'
		)
		'emphasis': [ : ] stategroup (
			'yes' { [ @emphasis ] }
			'no' { }
		)
		'property': component 'handheld view descriptor'
	}
}
'handheld view elements' {
	'has element': stategroup (
		'yes' {
			'type': [ -> ] stategroup (
				'label' { [ label: ]
					'text': reference
				}
				'inline view' { [ inline view: ]
					'frame': component 'handheld frame selector'
				}
				'view' {
					'view': component 'handheld view selector'
				}
			)
			'tail': component 'handheld view elements'
		}
		'no' { }
	)
}
'handheld view frame' {
	'type': stategroup (
		'decision' { [ (, ) ]
			'options': dictionary {
				'has more options': stategroup = node-switch successor (
					| node = 'yes' { 'next option' = successor }
					| none = 'no'
				)
				'emphasis': [ : ] stategroup (
					'low' { }
					'medium' { [ @emphasis: medium ] }
					'high' { [ @emphasis: high ] }
				)
				'frame': component 'handheld frame selector'
			}
		}
		'collection navigation' { [ collection (, ) ]
			'collection context': [ path: ] stategroup (
				'this' { }
				'root' { [ root ] }
			)
			'path': component 'annotated collection selector'
			'annotations': group {
				'header': stategroup (
					'yes' { }
					'no' { [ @no-header ] }
				)
				'layout': stategroup (
					'set' { [ @layout: ]
						'type': stategroup (
							'tabular' { [ tabular ] }
							'cards' { [ cards ] }
							'buttons' { [ buttons ] }
							'partition' { [ partition ]
								'path': [ on ] component 'query path'
								'property': [ . ] reference
								'type': stategroup (
									'simple' { }
									'year' { [ by, year ] }
									'month' { [ by, month ] }
									'week' { [ by, week ] }
									'day' { [ by, day ] }
									'hour' { [ by, hour ] }
								)
							}
						)
					}
					'default' { }
				)
			}
			'details': stategroup (
				'yes' {
					'details': component 'handheld view details'
				}
				'no' {
					'property': [ label: ] component 'handheld view descriptor'
				}
			)
			'filters': stategroup (
				'yes' { [ filters: ]
					'fields': dictionary {
						'has more fields': stategroup = node-switch successor (
							| node = 'yes' { 'next field' = successor }
							| none = 'no'
						)
						'path': [ : ] component 'query path'
						'property': [ . ] reference
						'type': stategroup (
							'stategroup' {
								'filter': stategroup (
									'state' {
										'state': [ is ] reference
									}
									'not state' {
										'state': [ is not ] reference
									}
									'states' {
										'states': [ is (, ) ] dictionary { }
									}
									'simple' { [ stategroup ] }
								)
							}
							'number' {
								'filter': stategroup (
									'match' {
										'operator': stategroup (
											'smaller' { [ smaller ] }
											'smaller equal' { [ smaller or equal ] }
											'greater' { [ greater ] }
											'greater equal' { [ greater or equal ] }
											'equal' { [ equal ] }
										)
										'type': [ than ] stategroup (
											'now' { [ now + ] }
											'static' { }
										)
										'offset': integer
									}
									'simple' { [ number ] }
								)
							}
							'text' {
								'filter': stategroup (
									'pattern' {
										'criteria': [ match ] text
									}
									'simple' { [ text ] }
									'current node' { [ this ] }
									'containment' { [ filter, selection ]
										'operator': stategroup (
											'in' { [ in ] }
											'not in' { [ not in ] }
										)
									}
								)
							}
						)
					}
				}
				'no' { }
			)
			'sort': stategroup (
				'yes' { [ sort: ]
					'path': component 'query path'
					'property': component 'handheld view property'
					'direction': stategroup (
						'ascending' { [ ascending ] }
						'descending' { [ descending ] }
					)
				}
				'no' { }
			)
			'action': stategroup (
				'yes' { [ view: ]
					'emphasis': stategroup (
						'low' { }
						'medium' { [ @emphasis: medium ] }
						'high' { [ @emphasis: high ] }
					)
					'view': component 'handheld view selector'
				}
				'no' { }
			)
		}
		'group navigation' {
			'property': [ . ] reference
			'frame': component 'handheld frame selector'
		}
		'state navigation' {
			'property': [ . ] reference
			'state': [ ? ] reference
			'frame': component 'handheld frame selector'
		}
		'reference navigation' {
			'text': [ > ] reference
			'frame': component 'handheld frame selector'
		}
		'pivot view' { [ pivot (, ) ]
			'options': group { dynamic-order
				'show crosshair': stategroup (
					'yes' { [ @crosshair ] }
					'no' { }
				)
				'show grid': stategroup (
					'yes' { [ @grid ] }
					'no' { }
				)
			}
			'columns': [ columns: . ] reference
			'column grouping': [ : ] reference
			'column label': [ label: ] component 'handheld view descriptor'
			'cells': [ cells: . ] reference
			'row grouping': [ : ] reference
			'row label': [ label: ] component 'handheld view descriptor'
			'content': stategroup (
				'inline view' { [ inline view: ]
					'frame': component 'handheld frame selector'
				}
				'label' { [ label: ]
					'property': component 'handheld view descriptor'
				}
			)
		}
		'detail view' { [ details (, ) ]
			'details': component 'handheld view details'
			'elements': component 'handheld view elements'
		}
		'command view' { [ command (, ) ]
			'details': component 'handheld view details'
			'selection': [ view: ] stategroup (
				'button' {
					'emphasis': stategroup (
						'low' { }
						'medium' { [ @emphasis: medium ] }
						'high' { [ @emphasis: high ] }
					)
				}
				'scan' { [ @scan (, ) ]
					'referencer': group {
						'path': component 'conditional path'
						'collection': [ ., [] ] reference
					}
					'path': [ using: ] component 'conditional path'
					'search property': [ . ] reference
				}
			)
			'view': component 'handheld view selector'
		}
	)
}
'handheld view descriptor' {
	'type': stategroup (
		'dynamic' {
			'property': component 'handheld view property selector'
		}
		'static text' {
			'text': reference
		}
		'icon' {
			'icon name': [ icon: ] text
		}
	)
	'has tail': stategroup (
		'yes' { [ , ]
			'tail': component 'handheld view descriptor'
		}
		'no' { }
	)
}
'handheld view property' {
	'property': [ . ] reference
	'style': stategroup (
		'default' { }
		'barcode' { [ @barcode: ]
			'barcode type': stategroup (
				'CODE128' { [ CODE128 ] }
				'CODE128A' { [ CODE128A ] }
				'CODE128B' { [ CODE128B ] }
				'CODE128C' { [ CODE128C ] }
				'EAN13' { [ EAN13 ] }
				'EAN8' { [ EAN8 ] }
				'EAN5' { [ EAN5 ] }
				'EAN2' { [ EAN2 ] }
				'UPCA' { [ UPCA ] }
				'UPCE' { [ UPCE ] }
				'CODE39' { [ CODE39 ] }
				'ITF' { [ ITF ] }
				'ITF14' { [ ITF14 ] }
				'MSI10' { [ MSI10 ] }
				'MSI11' { [ MSI11 ] }
				'MSI1010' { [ MSI1010 ] }
				'MSI1110' { [ MSI1110 ] }
				'Pharmacode' { [ Pharmacode ] }
				'Codabar' { [ Codabar ] }
			)
		}
		'qrcode' { [ @qrcode ] }
	)
}
'handheld view property selector' {
	'type': stategroup (
		'switch' {
			'stategroup': [ . ] reference
			'states': [ (, ) ] dictionary { [ | ]
				'tail': component 'handheld view property selector'
			}
		}
		'step' {
			'type': stategroup (
				'group' {
					'group': [ . ] reference
				}
				'state' {
					'stategroup': [ . ] reference
					'state': [ ? ] reference
				}
				'reference' {
					'text': [ > ] reference
				}
				'parent' { [ ^ ] }
			)
			'tail': component 'handheld view property selector'
		}
		'property' {
			'property': component 'handheld view property'
		}
	)
}
'handheld command annotations' { [ (, ) ]
	'properties': dictionary {
		'type': [ : ] stategroup (
			'group' { [ group ]
				'parameters': component 'handheld command annotations'
			}
			'collection' { [ collection ]
				'parameters': component 'handheld command annotations'
			}
			'stategroup' { [ stategroup (, ) ]
				'states': dictionary {
					'parameters': component 'handheld command annotations'
				}
			}
			'text' { [ text ]
				'style': stategroup (
					'buttons' { [ @button ] }
					'keyboard' { [ @keyboard ] }
					'default' { }
					'scan' { [ @scan using: ]
						'path': component 'conditional path'
						'search property': [ . ] reference
					}
				)
			}
		)
	}
}
'handheld view context' {
	'has step': stategroup (
		'yes' { [ ^ ]
			'tail': component 'handheld view context'
		}
		'no' { }
	)
}
'handheld view selector' {
	'type': stategroup (
		'switch' {
			'property': [ . ] reference
			'states': [ (, ) ] dictionary { [ | ]
				'tail': component 'handheld view selector'
			}
		}
		'step' {
			'type': stategroup (
				'group' {
					'property': [ . ] reference
				}
				'state' {
					'property': [ . ] reference
					'state': [ ? ] reference
				}
				'reference' {
					'text': [ > ] reference
				}
			)
			'tail': component 'handheld view selector'
		}
		'command' {
			'command': [ command: ] reference
			'annotations': group { dynamic-order
				'auto execute': stategroup (
					'yes' { [ @auto-execute ] }
					'no' { }
				)
				'close after execute': stategroup (
					'yes' { }
					'no' { [ @keep-open ] }
				)
				'emphasis': stategroup (
					'low' { }
					'medium' { [ @emphasis: medium ] }
					'high' { [ @emphasis: high ] }
				)
			}
			'parameter annotations': stategroup (
				'yes' {
					'parameters': component 'handheld command annotations'
				}
				'no' { }
			)
			'open view': stategroup (
				'yes' { [ and ]
					'context': component 'handheld view context'
					'frame': component 'handheld frame selector'
				}
				'no' { }
			)
			'has details': stategroup (
				'no' { }
				'yes' { [ details (, ) ]
					'details': component 'handheld view details'
					'elements': component 'handheld view elements'
				}
			)
		}
		'view' {
			'emphasis': [ : ] stategroup (
				'low' { }
				'medium' { [ @emphasis: medium ] }
				'high' { [ @emphasis: high ] }
			)
			'context': component 'handheld view context'
			'frame': component 'handheld frame selector'
			'title': stategroup (
				'custom' { [ title: ]
					'property': component 'handheld view descriptor'
				}
				'default' { }
			)
		}
	)
}