OneScript

widget

Widget APIs.

widget provides the widget configuration value and display API used by widgets.

Trigger and execution

A widget runs its script in two situations: rendering the widget, and the configuration stage, when the user opens the Option list while editing the widget. Both run the render script. OneScript reads entries.widget from config.json in the project root to decide which package.json script runs. Change it in the project's More Settings, or edit the file directly.

entries.widget takes one of two forms:

  • A script name: render and tap use the same script.
  • An object: render and click use separate scripts.

Tapping a widget doesn't run a script yet, so click has no effect for now.

{
  "entries": {
    "widget": {
      "render": "widget:render",
      "click": "widget:click"
    }
  }
}

The script names refer to scripts in package.json:

{
  "scripts": {
    "widget:render": "src/widget-render.tsx",
    "widget:click": "src/widget-click.tsx"
  }
}

When no render script is configured, OneScript uses package.main, then index.js, then index.ts. If the configured script isn't in package.json, or its file doesn't exist, the widget shows an error instead of falling back.

import { widget } from "onescript"

widget.inputValue

The input value configured by the user for the widget.

In the main app preview, this value is undefined. In a real widget, it comes from the widget configuration.

import { widget } from "onescript"

const inputValue = widget.inputValue

widget.option

The option the user selected in the widget's Option list, or undefined when nothing is selected. The candidates come from widget.provideOptions(options) in the configuration stage.

The value has the same fields as the option the script provided: id, title, and optionally subtitle and systemImage. When the user switches the widget to another project, the previously selected option belongs to the old project and is not passed to the script.

In the main app preview, this value is undefined.

import { widget } from "onescript"

const city = widget.option?.id ?? "beijing"

widget.family

The system widget size family for the current widget.

On a real widget, this comes from the WidgetKit-assigned WidgetFamily. In the main app preview, it matches the selected Small / Medium / Large size. In the editor or without a runtime context, the default is small.

Possible values: small, medium, large, extraLarge. extraLarge is mainly available on larger devices such as iPad. The app preview currently supports the first three sizes.

import { widget } from "onescript"

const family = widget.family

widget.displaySize

width and height of the current widget, in points.

import { widget } from "onescript"

const { width, height } = widget.displaySize

widget.show(options)

Displays a widget view.

Only runs in the app and widget contexts. After it is called, the script terminates automatically. Calls in other contexts are ignored.

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

function renderWidget() {
  return (
    <VStack modifier={Modifier.padding(12)}>
      <Text>Hello Widget</Text>
    </VStack>
  )
}

await widget.show({
  views: renderWidget()
})

Use widget.family to choose a different view for different widget sizes. For finer layout control, combine it with widget.displaySize.

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

function renderWidget() {
  switch (widget.family) {
    case "small":
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>Compact</Text>
        </VStack>
      )
    case "medium":
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>Medium</Text>
        </VStack>
      )
    default:
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>Large</Text>
        </VStack>
      )
  }
}

await widget.show({
  views: renderWidget()
})

Supported fields:

FieldDescription
viewsThe view returned by onescript/views components.
options.refreshThe earliest time to request the next refresh. Only Date is supported.

When options.refresh is omitted, OneScript requests a refresh about one hour later by default. refresh is the earliest time the system may refresh the widget. It does not guarantee exact execution at that time.

Refresh timing is scheduled by the system and is not guaranteed to occur on time. refresh only sets the earliest time a refresh may happen; the widget may update later than that.

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

const nextRefresh = new Date()
nextRefresh.setHours(8, 0, 0, 0)

if (nextRefresh <= new Date()) {
  nextRefresh.setDate(nextRefresh.getDate() + 1)
}

await widget.show({
  views: (
    <VStack modifier={Modifier.padding(12)}>
      <Text>Good morning</Text>
    </VStack>
  ),
  options: {
    refresh: nextRefresh
  }
})

widget.provideOptions(options)

Provides the candidates for the Option list in the system's Edit Widget sheet.

The sheet is drawn by iOS, so the parameter names and the number of parameters are fixed: Project, Option, and Input Value. When the user opens the Option list, OneScript runs the widget's render script with script.context set to "widgetConfig". The options the script provides are listed in the sheet. After the user selects one, the render stage reads it through widget.option.

Only available in the widgetConfig context; calling it elsewhere throws. The script ends after the call. If the script ends without calling it, the Option list is empty.

FieldDescription
idRequired. A stable identifier, unique within the list.
titleRequired. The text shown in the sheet.
subtitleOptional. Secondary text shown under the title in the list.
systemImageOptional. An SF Symbol name shown next to the option in the list.
import { script, widget } from "onescript"
import { Text } from "onescript/views"

if (script.context === "widgetConfig") {
  await widget.provideOptions([
    {
      id: "beijing",
      title: "Beijing",
      subtitle: "China",
      systemImage: "building.2",
    },
    {
      id: "tokyo",
      title: "Tokyo",
      subtitle: "Japan",
    },
  ])
}

const city = widget.option?.title ?? "Beijing"

await widget.show({
  views: <Text>{city}</Text>
})

The selected option is saved by the system for each widget. Each widget on the Home Screen keeps its own selection.

How is this guide?

Last updated on

On this page