Wraps Scriptable’s ListWidget
API with a chainable interface. Enables writing widget syntax that is closer to the actual view hierarchy.
Copy the createWidget()
function to your scripts to get started.
Calling the createWidget()
function will return a new wrapper object representing the widget view with chainable methods:
createWidget()
.render()
Equivalent to:
const widget = new ListWidget()
Script.setWidget(widget)
Note that you cannot pass the wrapper object directly to the Script.setWidget()
method. Instead you should call the .render()
method of the wrapper object.
createWidget()
.presentMedium()
Instead of assigning the value to the property directly, you should call the method that has same name as the property with the value you want to assign as the argument:
createWidget()
.backgroundColor(new Color("#F77"))
.render()
Equivalent to:
const widget = new ListWidget()
widget.backgroundColor = new Color("#F77")
Script.setWidget(widget)
All methods are chainable, except .present...()
methods, which will return a promise that resolves when preview is dismissed:
createWidget()
.setPadding(10, 10, 10, 10)
.backgroundColor(new Color("#F77"))
.presentMedium()
.then(() => console.log("dismissed"))
Equivalent to:
const widget = new ListWidget()
widget.setPadding(10, 10, 10, 10)
widget.backgroundColor = new Color("#F77")
widget.presentMedium()
.then(() => console.log("dismissed"))
To add view, call the same .add...()
methods:
createWidget()
.addText("hello world")
.render()
Equivalent to:
const widget = new ListWidget()
const text = widget.addText("hello world")
Script.setWidget(widget)
But there's something different here. Since all methods are chainable, the .add...()
methods will return the parent view itself instead of the added view.
So how to modify the added view? You can do that by providing a callback as the last argument, which will receive the added view as argument. You can then modify the added view in that callback:
createWidget()
.addText("hello world", text => text.centerAlignText())
.render()
Equivalent to:
const widget = new ListWidget()
const text = widget.addText("hello world")
text.centerAlignText()
Script.setWidget(widget)
The added view received by the callback is also a chainable wrapper object, so you can do this:
createWidget()
.addText("hello world", text => text
.centerAlignText()
.textColor(new Color("#F77"))
)
.render()
Equivalent to:
const widget = new ListWidget()
const text = widget.addText("hello world")
text.centerAlignText()
text.textColor = new Color("#F77")
Script.setWidget(widget)
You can also embed views in stacks the same way:
createWidget()
.addStack(stack => stack.layoutHorizontally()
.addText("hello world", text => text
.centerAlignText()
.textColor(new Color("#F77"))
)
)
.render()
Equivalent to:
const widget = new ListWidget()
const stack = widget.addStack()
stack.layoutHorizontally()
const text = stack.addText("hello world")
text.centerAlignText()
text.textColor = new Color("#F77")
Script.setWidget(widget)
Sometimes we need to render views conditionally or render a list of views. The chaining methods are not very good at this but you can call .doTo()
with a callback that receives the view itself as argument to embed some additional logic in the chain:
const showDate = true
const list = ["Maina", "Aya"]
createWidget()
.doTo(widget => showDate && widget.addDate(new Date))
.addStack(stack => stack.layoutVertically()
.doTo(stack => list.forEach((item) => stack.addText(item)))
)
.render()
You can access the raw view instance by the raw
property of the wrapper object:
Script.setWidget(createWidget().raw)