Widget Aliran
Energi, air, atau data yang mengalir antara sumber, penyimpanan, dan konsumen, lengkap dengan laju langsung di setiap jalur.
Bagian ini menjelaskan fitur dalam pembaruan aplikasi yang sedang menunggu tinjauan App Store. Fitur ini akan otomatis terbuka di sini begitu pembaruan tersedia.
The flow template describes something moving through a system, in four generic slots:
what comes in (inputs), what buffers it (storage), what is traded with the
outside (exchange), and what consumes it (output). Home energy is the
obvious case — solar in, battery buffering, grid import and export, house draw — but water, data
and money map onto the same four slots.
Fields
| Field | Type | Notes |
|---|---|---|
template | string | Required. Must be "flow" |
flow | object | Required. At least one of inputs, output, storage, exchange must be present |
flow.inputs | object[] | Production sources (solar, wind, well). Up to 3 nodes |
flow.output | object | The consumption endpoint — the house, the cluster, the tap |
flow.storage | object | The buffer. The only slot that renders level |
flow.exchange | object | Two-way link with the outside — grid, mains, upstream provider |
rate | float | Required on every node. Instantaneous rate, finite. Signed on the two-way slots: see Behavior below |
name | string | Label override for that node (rename an input to "Wind"). Max 32 characters |
total | float | Cumulative total so far today (kWh, litres). Must not be negative |
level | float | Fill percentage, 0 to 100. Read on the storage slot only |
icon, color | string | SF Symbol (max 128 characters) and a named color or hex for that node |
unit | string | Content-level unit for every rate on the widget (e.g. "W", "L/min"). Max 32 characters |
Example: home energy
{
"content": {
"template": "flow",
"label": "Power",
"subtitle": "Solar · grid · home",
"icon": "point.3.filled.connected.trianglepath.dotted",
"unit": "W",
"accent_color": "mint",
"flow": {
"inputs": [
{ "name": "Solar", "rate": 3200, "total": 12.4, "icon": "sun.max.fill", "color": "yellow" }
],
"output": { "name": "Home", "rate": 1000, "total": 9.8, "icon": "house.fill" },
"storage": { "name": "Battery", "rate": 800, "level": 76, "icon": "battery.75percent", "color": "green" },
"exchange": { "name": "Grid", "rate": -1400, "total": 3.1, "icon": "bolt.fill", "color": "cyan" }
}
}
}Behavior
The sign of rate is what makes the two-way slots readable, and it means different
things per slot. On exchange, positive is inbound (importing from the
grid) and negative is outbound (exporting to it) — the example above is exporting
1400 W. On storage, positive is filling and negative is draining. Inputs and the output are one-directional, so their rates are plain
magnitudes.
Only the slots you send are drawn, so the same template covers a solar array with no battery, a
water main with no local source, or a bare consumption meter. storage additionally
shows its level as a fill indicator; level on any other slot is ignored. total is the running figure for the day and renders under the rate where the widget
family has room.
Merge-patch semantics run deep on objects and shallow on arrays. Patching {"content": {"flow": {"exchange": {"rate": -900}}}} updates just that one rate and leaves the exchange node's name and icon — and the other three slots — untouched. flow.inputs is an array, so it is replaced wholesale: send every input each time you send any of them. Clear a slot with an explicit null.
Wire up slots and flip the signs on the playground to see how each direction renders.