APL User-defined Commands
You can define custom commands in your APL document or package.
- Overview of user-defined Commands
- Command definitions
- Command inflation
- Nested Expansion of User Commands
Overview of user-defined Commands
The commands
property in the APL document to define a set of commands. A user-defined command can call APL standard commands.
For example, this creates a command called slideInFromRight
that calls the AnimateItem
command:
{
"commands": {
"slideInFromRight": {
"parameters": [
"distance"
],
"command": {
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": 300,
"values": [
{
"property": "opacity",
"from": 0,
"to": 1
},
{
"property": "transformX",
"from": "${distance}",
"to": 0
}
]
}
}
}
}
To use a parameterized command, pass the name of the command as the type:
{
"type": "TouchWrapper"
"onPress": {
"type": "slideInFromRight",
"duration": 500,
"distance": "20vw"
}
}
In the above example the distance
parameter will be bound to 20vw
in
the translateX
property animation. The duration of the command will be
500 milliseconds (the value 500 passed in as the duration overrides the
internal 300 millisecond duration
).
Command definitions
The command
property in the document is a map of command name to a command definition. The
command definition contains the following properties:
Property | Type | Required | Description |
---|---|---|---|
parameters |
Array of parameter definitions | No | Optional named parameters to add to the data-binding context |
command , commands |
Array of commands | Yes | The array of commands to run |
description |
String | No | Description of this command |
commands
The command property is an implicit sequential block of commands to run. The array of commands supports the standard data-binding with array rules including automatic conversion of a single command into an array of commands and substitution of parameters into the array.
parameters
The parameters are named values that can be passed as arguments. Each parameter is an object with the following properties:
Property | Type | Required | Description |
---|---|---|---|
default |
Any | No | The default value to apply if this parameter is not specified. Defaults to empty. |
description |
String | No | A user-provided description of this parameter |
name |
String | Yes | The parameter name |
type |
any , array , boolean , color , dimension , integer , map , number , object , string |
No | The type of the parameter. Defaults to any |
The parameter name must be a unique name starting with an upper- or
lower-case letter and containing no white space
([a-zA-Z][a-zA-Z0-9]*
).
As a convenience, a simple parameter name can be used instead of the
parameter object (for example, "title" instead of { "name": "title", ... }
.
This is not recommended, but does allow compact command definition for
cases where no type coercion or defaults values are required.
Command inflation
Commands are inflated with the following algorithm:
- Each
parameter
is evaluated and added to the data-binding context. - The
command
array is evaluated. - Properties assigned to the object but not matching a named parameter are passed to each command as properties.
For example, note this definition of customPressHandler
:
"commands": {
"customPressHandler": {
"description": "Hide the current component and fire an event if checked."
"parameters": [
"onChecked",
{
"type": "number",
"name": "opacity",
"default": 0.5
}
],
"commands": [
{
"type": "SetValue",
"property": "opacity",
"value": "${opacity}"
},
{
"type": "Sequential",
"when": "${event.target.checked}",
"commands": [
"${onChecked}"
]
}
]
}
}
Now assume this custom command is invoked with:
{
"onPress": {
"type": "customPressHandler",
"onChecked": {
"type": "SendEvent",
"arguments": ["It was checked!"]
},
"delay": 500
}
}
When the onPress
handler fires, the inflated command representation is:
[
{
"type": "SetValue",
"property": "opacity",
"value": 0.5,
"delay": 500
},
{
"type": "Sequential",
"when": "${event.target.checked}",
"delay": 500,
"commands": [
{
"type": "SendEvent",
"arguments": ["It was checked!"]
}
]
}
]
Note the following:
- The original invocation passed a
delay
value of 500. ThecustomPressHandler
definition does not includedelay
as a parameter, so thedelay
value was passed into each of the commands in the custom command. - The original invocation did not pass an
opacity
value, butopacity
is defined as a parameter incustomPressHandler
. So the data-binding context was extended by the default value ofopacity
- in this case 0.5. That value was used in theSetValue
command expansion of${opacity}
.
Nested Expansion of User Commands
You can define user commands that reference other user commands. For example:
{
"SoftStagger": {
"description": "General soft-stagger sliding objects from the left or right",
"parameters": [
"delay",
"duration",
"distance"
],
"commands": [
{
"type": "SetValue",
"property": "opacity",
"value": 0
},
{
"type": "AnimateItem",
"values": [
{
"property": "opacity",
"to": 1
},
{
"property": "translateX",
"from": "${distance}",
"to": 0
}
],
"delay": "${delay}",
"duration": "${duration}",
"easing": "ease-out"
}
]
}
}
You can use the SoftStagger
command as is and pass in the parameters for
delay
, duration
, and distance
. You can also use SoftStagger
to define some standard variations for convenience:
{
"SoftStagger1": {
"commands": {
"type": "SoftStagger",
"delay": 0,
"duration": 666,
"distance": 40
}
},
"SoftStagger2": {
"commands": {
"type": "SoftStagger",
"delay": 50,
"duration": 666,
"distance": 40
}
}
}
You can then add a soft stagger entrance animation to a
component with a line like this: onMount:{"type": "SoftStagger2"}
.
Last updated: Nov 28, 2023